Prechádzať zdrojové kódy

项目更新20220326

VEAR 3 rokov pred
rodič
commit
9ee963cbe2
47 zmenil súbory, kde vykonal 2607 pridanie a 155 odobranie
  1. 1 1
      doc/开发计划.md
  2. 2 0
      doc/支付宝.md
  3. 18 1
      pom.xml
  4. 52 0
      src/main/java/org/springblade/common/config/ApilayAutoConfiguration.java
  5. 52 0
      src/main/java/org/springblade/common/constant/AlipayUrlConstants.java
  6. 91 0
      src/main/java/org/springblade/common/utils/NotifyUtils.java
  7. 148 0
      src/main/java/org/springblade/common/utils/StringUtils.java
  8. 200 0
      src/main/java/org/springblade/modules/api/controller/AliPay01Controller.java
  9. 856 0
      src/main/java/org/springblade/modules/api/controller/AliPay02Controller.java
  10. 90 35
      src/main/java/org/springblade/modules/api/controller/Api01Controller.java
  11. 6 8
      src/main/java/org/springblade/modules/api/controller/Api02Controller.java
  12. 8 1
      src/main/java/org/springblade/modules/api/controller/Api03Controller.java
  13. 1 1
      src/main/java/org/springblade/modules/api/controller/Api04Controller.java
  14. 8 13
      src/main/java/org/springblade/modules/api/controller/Api05Controller.java
  15. 4 29
      src/main/java/org/springblade/modules/api/controller/Api06Controller.java
  16. 8 0
      src/main/java/org/springblade/modules/api/controller/Api07Controller.java
  17. 19 5
      src/main/java/org/springblade/modules/api/controller/Api08Controller.java
  18. 11 12
      src/main/java/org/springblade/modules/api/controller/WxPayV3Controller.java
  19. 70 0
      src/main/java/org/springblade/modules/api/request/OrderConsignRandomRequest.java
  20. 43 0
      src/main/java/org/springblade/modules/api/response/ConsignResponse.java
  21. 6 3
      src/main/java/org/springblade/modules/api/response/IndexResponse.java
  22. 120 0
      src/main/java/org/springblade/modules/auth/granter/PhoneTokenGranter.java
  23. 2 4
      src/main/java/org/springblade/modules/auth/provider/TokenGranterBuilder.java
  24. 17 0
      src/main/java/org/springblade/modules/finance/controller/AbstractAliPayApiController.java
  25. 110 0
      src/main/java/org/springblade/modules/finance/pay/entity/AliPayBean.java
  26. 135 0
      src/main/java/org/springblade/modules/finance/pay/entity/AlipayProperties.java
  27. 42 0
      src/main/java/org/springblade/modules/finance/pay/interceptor/AliPayInterceptor.java
  28. 11 1
      src/main/java/org/springblade/modules/finance/service/IOrderService.java
  29. 160 25
      src/main/java/org/springblade/modules/finance/service/impl/OrderServiceImpl.java
  30. 8 3
      src/main/java/org/springblade/modules/shopping/entity/Consign.java
  31. 7 0
      src/main/java/org/springblade/modules/shopping/mapper/ConsignMapper.java
  32. 16 0
      src/main/java/org/springblade/modules/shopping/mapper/ConsignMapper.xml
  33. 2 1
      src/main/java/org/springblade/modules/shopping/service/IConsignConfigService.java
  34. 10 0
      src/main/java/org/springblade/modules/shopping/service/IConsignService.java
  35. 19 5
      src/main/java/org/springblade/modules/shopping/service/impl/ConsignConfigServiceImpl.java
  36. 24 0
      src/main/java/org/springblade/modules/shopping/service/impl/ConsignServiceImpl.java
  37. 1 0
      src/main/java/org/springblade/modules/shopping/vo/ConsignVO.java
  38. 16 0
      src/main/java/org/springblade/modules/shopping/wrapper/ConsignWrapper.java
  39. 5 0
      src/main/java/org/springblade/modules/system/entity/UserApp.java
  40. 3 0
      src/main/java/org/springblade/modules/system/vo/UserAppVO.java
  41. 43 0
      src/main/resources/alipay/alipayCertPublicKey_RSA2.crt
  42. 88 0
      src/main/resources/alipay/alipayRootCert.crt
  43. 24 0
      src/main/resources/alipay/appCertPublicKey_2021003125657245.crt
  44. 23 1
      src/main/resources/application-dev.yml
  45. 1 1
      src/main/resources/application-prod.yml
  46. 23 2
      src/main/resources/application-test.yml
  47. 3 3
      src/main/resources/application.yml

+ 1 - 1
doc/开发计划.md

@@ -8,7 +8,7 @@
 * 调整接口顺序
 * 订单批量支付(不做)
 * 加配货功能(加字段,添加配货表)
-* 数据库表添加索引
+* 数据库表添加索引 
 
 ## 寄售状态
 * 寄售商品 

+ 2 - 0
doc/支付宝.md

@@ -0,0 +1,2 @@
+### 应用私钥
+MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQDnZsFikVksqiqIsn/keE5CD202GyZTE9kMqI3DhtZxgX1k6JMpYdzhvt0ptrtEhXiUs7YpgK3n3P7lSa+RP7dVHZsoBsWyAG+U8Jkqxxl0fxd4MNoACw8rVIsl3SOnFXHFXZ36ARTVANUG9S3KhVF7wtYs5Yd8vFzOwbz3+pN9Cc286VJ/HmoM5FTb+T5waeYcIbUBBmG9wAjS6kbaImbjDF/lCesSwhjliBL7FFFFh1zFRG/MunX42Pl/DuGoWJ7jXXBOqMzg26UzpvM5KbHUzK+lgHMEVchnUb2KVxVRHW9WJoIsTuXudAI/PNSM0rHRQUpN3WqZB6wUq1KdPxRBAgMBAAECggEBALzYEwJJ9CiLRuMAKXde5x7qUApT5dbu37eA5xCmveMr9hWf6FlhUE264erlAbdN5bYVY5hDN6l9pVeh5vH2ubtwyerEfBpkWKuIHrfWfGOiRJkF5SMb42lNObHQ4wO8cHjNids5frLGVxOyi4g3fOQvgXJqb0PQxTzGx1zo1ey3wdRmwnRhEhFNL7/ESD3dZKsuK/OnWs17amUzDe2BoKbJ6g9zN8jc7bKOYVoPtIW2g4+u/x3xuWE6PD9Sz6GSIJqTZ0VtKSFRazgv+G+uvGYR6rtHg/z28Wzj3fQrIEdVKr/RhkvYx4njo/+aG/ppNF42f5O+RuojDI9groSknXECgYEA/mw+hxUS5KS0Qp34ieLnoOATl1siRB07wQTdlOzAsn0Iwet8XFiX5KzISIZvNiMXKXckAM5P1WnOcar3EHRhwQSL5qq3UTrjHLSJ7jk44ZO75WDWPb6sP4/RYuI5bFykIjQxJYjhcpYCaYGySLEb6E/AkCLamsf44p46Hhh9AHsCgYEA6NX6MrrOA0LHvXqKv01wVnaSEtdKdUD8tXg/8+upILR2OHAAqppvyYE8OHdIMpnCnhJIkbNq/oNEq26zZuJHiYKXtUoDS60K6SMttjdLpC0pcjrGWyjaTo/8Nu4lfQ+O8gM1c8d71QPhUro4B4nSP4sP5EwkyHZuRhwus8tVh3MCgYBF3dnJ5JqcmTI7PQA8dUggYIhgvxEI3XJETh6/P8im+zkFb7Jl9Zo4nM4fRHOTzU0WAPatFfrMY1Li2g0gwqT5iVMV0/mlX+NwRY+/EI2zPIuTsOUEbbEFf2wDmJYmUMZt8iEw6obmnZUp/gjEd4ZvZD9AFaIscQ/Cw6q4CweAswKBgAjC1HFIOixBPQbSL5pXLZzzRTfURgb3dQrXBYEGIw0J/VDOVhgVS5OHe16cjmjpBDuycGybFbGR+umAdtuuNAbmlRLLQCh+0GRJYJT0q7H3yRF1SLVxahV+sXzXpS15gmV03XQH048GYFoei7Es7G5bqzNp8hBg9HFK6i71vbglAoGBAN/kK3CeHki03rNME/6JzmJexgvd8qb88iR1/8uh0mfGI9QkALlQ8X3GmVjjZZRBjLvUMh298rtV5pPGiin+/GXYa/BV4H/IeFk/w+SsJJWfjIEhFKNJgAahYHbSr1QjeU8wax5Cb7YzYjLeo258IQJhMho3DT7eSd0h1hJ146QJ

+ 18 - 1
pom.xml

@@ -29,6 +29,8 @@
         <docker.password>Harbor12345</docker.password>
         <docker.namespace>blade</docker.namespace>
         <docker.plugin.version>1.4.13</docker.plugin.version>
+
+        <ijapy.version>2.7.9</ijapy.version>
     </properties>
 
     <dependencyManagement>
@@ -198,7 +200,22 @@
         <dependency>
             <groupId>com.github.javen205</groupId>
             <artifactId>IJPay-WxPay</artifactId>
-            <version>2.7.9</version>
+            <version>${ijapy.version}</version>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.commons</groupId>
+            <artifactId>commons-lang3</artifactId>
+            <version>3.9</version>
+        </dependency>
+        <dependency>
+            <groupId>com.github.javen205</groupId>
+            <artifactId>IJPay-AliPay</artifactId>
+            <version>${ijapy.version}</version>
+        </dependency>
+        <dependency>
+            <groupId>com.github.javen205</groupId>
+            <artifactId>IJPay-Core</artifactId>
+            <version>${ijapy.version}</version>
         </dependency>
     </dependencies>
 

+ 52 - 0
src/main/java/org/springblade/common/config/ApilayAutoConfiguration.java

@@ -0,0 +1,52 @@
+package org.springblade.common.config;
+
+import com.alipay.api.AlipayClient;
+import com.alipay.api.AlipayConstants;
+import com.alipay.api.DefaultAlipayClient;
+import org.springblade.common.constant.AlipayUrlConstants;
+import org.springblade.modules.finance.pay.entity.AlipayProperties;
+import org.springframework.boot.context.properties.EnableConfigurationProperties;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+
+import java.util.Objects;
+
+/**
+ * 支付宝客户端自动配置
+ *
+ * @author xuwei
+ *
+ */
+@Configuration
+@EnableConfigurationProperties(AlipayProperties.class)
+public class ApilayAutoConfiguration {
+
+    private static final String ERROR_MSG_APPID_NULL = "alipay application's appid cann't be null";
+
+    private static final String ERROR_MSG_PRIVATE_KEY_NULL = "alipay application's privateKey cann't be null";
+
+    private static final String ERROR_MSG_ALIPAY_PUBLIC_KEY_NULL = "alipay's publicKey cann't be null";
+
+    /**
+     * 构造支付宝客户端
+     *
+     * @param properties
+     *            支付宝配置
+     * @return 支付宝客户端
+     */
+    @Bean
+    public AlipayClient alipayClient(AlipayProperties properties) {
+
+        String gatewayUrl = AlipayUrlConstants.gateway(properties.isDev());
+        String appId = Objects.requireNonNull(properties.getAppId(), ERROR_MSG_APPID_NULL);
+        String privateKey = Objects.requireNonNull(properties.getPrivateKey(), ERROR_MSG_PRIVATE_KEY_NULL);
+        String format = AlipayConstants.FORMAT_JSON;
+        String charset = AlipayConstants.CHARSET_UTF8;
+        String alipayPublicKey = Objects.requireNonNull(properties.getAlipayPublicKey(),
+                ERROR_MSG_ALIPAY_PUBLIC_KEY_NULL);
+        String signType = AlipayConstants.SIGN_TYPE_RSA.equals(properties.getSignType()) ? AlipayConstants.SIGN_TYPE_RSA
+                : AlipayConstants.SIGN_TYPE_RSA2;
+
+        return new DefaultAlipayClient(gatewayUrl, appId, privateKey, format, charset, alipayPublicKey, signType);
+    }
+}

+ 52 - 0
src/main/java/org/springblade/common/constant/AlipayUrlConstants.java

@@ -0,0 +1,52 @@
+package org.springblade.common.constant;
+
+/**
+ * 支付宝地址常量
+ *
+ * @author xuwei
+ *
+ */
+public interface AlipayUrlConstants {
+
+    /**
+     * OAUTH2地址 正式环境
+     */
+    String OAUTH2 = "https://openauth.alipay.com/oauth2/";
+
+    /**
+     * OAUTH2地址 沙箱模式
+     */
+    String OAUTH2_DEV = "https://openauth.alipaydev.com/oauth2/";
+
+    /**
+     * 网关地址 正式环境
+     */
+    String GATEWAY = "https://openapi.alipay.com/gateway.do";
+
+    /**
+     * 网关地址 沙箱模式
+     */
+    String GATEWAY_DEV = "https://openapi.alipaydev.com/gateway.do";
+
+    /**
+     * 获取OAUTH2地址
+     *
+     * @param dev
+     *            是否为沙箱模式
+     * @return OAUTH2地址
+     */
+    static String oauth2(boolean dev) {
+        return dev ? OAUTH2_DEV : OAUTH2;
+    }
+
+    /**
+     * 获取网关地址
+     *
+     * @param dev
+     *            是否为沙箱模式
+     * @return 网关地址
+     */
+    static String gateway(boolean dev) {
+        return dev ? GATEWAY_DEV : GATEWAY;
+    }
+}

+ 91 - 0
src/main/java/org/springblade/common/utils/NotifyUtils.java

@@ -0,0 +1,91 @@
+package org.springblade.common.utils;
+
+import com.alipay.api.AlipayApiException;
+import com.alipay.api.AlipayConstants;
+import com.alipay.api.internal.util.AlipaySignature;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springblade.modules.finance.pay.entity.AlipayProperties;
+
+import java.util.Map;
+import java.util.Map.Entry;
+import java.util.stream.Collectors;
+
+/**
+ * 通知回调工具类
+ *
+ * @author xuwei
+ *
+ */
+public class NotifyUtils {
+
+    private static final Logger LOGGER = LoggerFactory.getLogger(NotifyUtils.class);
+
+    private NotifyUtils() {
+
+    }
+
+    /**
+     * 回调数据通过支付宝公钥进行验签
+     *
+     * @param properties
+     *            支付宝配置
+     * @param requestParams
+     *            请求参数
+     * @return 是否检查通过
+     */
+    public static boolean rsaCheck(AlipayProperties properties, Map<String, String[]> requestParams) {
+        try {
+            return rsaCheck(properties, requestParams, false);
+        } catch (Exception e) {
+            LOGGER.debug(e.getMessage(), e);
+            return false;
+        }
+    }
+
+    /**
+     * 回调数据通过支付宝公钥进行验签
+     *
+     * @param properties
+     *            支付宝配置
+     * @param requestParams
+     *            请求参数
+     * @param throwException
+     *            检查失败是否抛出异常
+     * @return 是否检查通过
+     *
+     * @throws NullPointerException
+     *             当requestParams为空的时候抛出NullPointerException
+     * @throws AlipayApiException
+     *             支付宝公钥验签失败的时候抛出AlipayApiException
+     */
+    public static boolean rsaCheck(AlipayProperties properties, Map<String, String[]> requestParams,
+            boolean throwException) throws AlipayApiException {
+        if (requestParams == null) {
+            if (throwException) {
+                throw new NullPointerException("requestParams cann't be null");
+            }
+            return false;
+        }
+
+        Map<String, String> params = requestParams.entrySet().stream().filter(NotifyUtils::entryCheck)
+                .collect(Collectors.toMap(e -> e.getKey(), e -> String.join(",", e.getValue())));
+
+        try {
+            return AlipaySignature.rsaCheckV1(params, properties.getAlipayPublicKey(), AlipayConstants.CHARSET_UTF8,
+                    AlipayConstants.SIGN_TYPE_RSA2);
+        } catch (AlipayApiException e) {
+            LOGGER.debug(e.getMessage(), e);
+            if (throwException) {
+                throw e;
+            }
+        }
+
+        return false;
+    }
+
+    private static boolean entryCheck(Entry<String, String[]> entry) {
+        return entry != null && entry.getKey() != null && entry.getValue() != null;
+    }
+
+}

+ 148 - 0
src/main/java/org/springblade/common/utils/StringUtils.java

@@ -0,0 +1,148 @@
+package org.springblade.common.utils;
+
+import java.io.UnsupportedEncodingException;
+import java.net.URLEncoder;
+import java.text.MessageFormat;
+import java.text.SimpleDateFormat;
+import java.util.Date;
+import java.util.Locale;
+import java.util.Random;
+import java.util.UUID;
+
+/**
+ * 字符串工具类,继承lang3字符串工具类
+ *
+ * @author L.com
+ */
+public final class StringUtils extends org.apache.commons.lang3.StringUtils {
+
+	/**
+	 * 随机字符串
+	 */
+	private static final String INT_TEMP = "0123456789";
+	private static final String STR_TEMP = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
+	private static final String ALL_TEMP = INT_TEMP + STR_TEMP;
+	private static final Random RANDOM = new Random();
+
+	public static String encode(String str) {
+		String encode = null;
+		try {
+			encode = URLEncoder.encode(str, "UTF-8");
+		} catch (UnsupportedEncodingException e) {
+			e.printStackTrace();
+		}
+		return encode;
+	}
+
+	/**
+	 * 获取UUID,去掉`-`的
+	 *
+	 * @return {String}
+	 */
+	public static String generateStr() {
+		return UUID.randomUUID().toString().replace("-", "");
+	}
+
+	/**
+	 * 要求外部订单号必须唯一。
+	 *
+	 * @return {String}
+	 */
+	public static String getOutTradeNo() {
+		SimpleDateFormat format = new SimpleDateFormat("MMddHHmmss", Locale.getDefault());
+		Date date = new Date();
+		String key = format.format(date);
+		key = key + System.currentTimeMillis();
+		key = key.substring(0, 15);
+		return key;
+	}
+
+	/**
+	 * 字符串格式化
+	 * <p>
+	 * use: format("my name is {0}, and i like {1}!", "L.cm", "java")
+	 * <p>
+	 * int long use {0,number,#}
+	 *
+	 * @param s
+	 * @param args
+	 * @return {String}转换后的字符串
+	 */
+	public static String format(String s, Object... args) {
+		return MessageFormat.format(s, args);
+	}
+
+	/**
+	 * 替换某个字符
+	 *
+	 * @param str
+	 * @param regex
+	 * @param args
+	 * @return {String}
+	 */
+	public static String replace(String str, String regex, String... args) {
+		int length = args.length;
+		for (int i = 0; i < length; i++) {
+			str = str.replaceFirst(regex, args[i]);
+		}
+		return str;
+	}
+
+	/**
+	 * 清理字符串,清理出某些不可见字符
+	 *
+	 * @param txt
+	 * @return {String}
+	 */
+	public static String cleanChars(String txt) {
+		return txt.replaceAll("[  	`·•�\\f\\t\\v]", "");
+	}
+
+	/**
+	 * 随机数生成
+	 *
+	 * @param count
+	 * @return {String}
+	 */
+	public static String random(int count, RandomType randomType) {
+		if (count == 0) {
+			return "";
+		}
+		if (count < 0) {
+			throw new IllegalArgumentException("Requested random string length " + count + " is less than 0.");
+		}
+		char[] buffer = new char[count];
+		for (int i = 0; i < count; i++) {
+			if (randomType.equals(RandomType.INT)) {
+				buffer[i] = INT_TEMP.charAt(RANDOM.nextInt(INT_TEMP.length()));
+			} else if (randomType.equals(RandomType.STRING)) {
+				buffer[i] = STR_TEMP.charAt(RANDOM.nextInt(STR_TEMP.length()));
+			} else {
+				buffer[i] = ALL_TEMP.charAt(RANDOM.nextInt(ALL_TEMP.length()));
+			}
+		}
+		return new String(buffer);
+	}
+
+	public static void main(String[] args) {
+		System.out.println(random(32, RandomType.ALL));
+	}
+
+	/**
+	 * 生成的随机数类型
+	 */
+	public enum RandomType {
+		/**
+		 * 整数
+		 */
+		INT,
+		/**
+		 * 字符串
+		 */
+		STRING,
+		/**
+		 * 所有类型
+		 */
+		ALL
+	}
+}

+ 200 - 0
src/main/java/org/springblade/modules/api/controller/AliPay01Controller.java

@@ -0,0 +1,200 @@
+package org.springblade.modules.api.controller;
+
+import com.alibaba.fastjson.JSONObject;
+import com.alipay.api.AlipayApiException;
+import com.alipay.api.AlipayClient;
+import com.alipay.api.AlipayResponse;
+import com.alipay.api.request.AlipayFundAuthOperationDetailQueryRequest;
+import com.alipay.api.request.AlipayFundAuthOrderAppFreezeRequest;
+import com.alipay.api.request.AlipayTradeAppPayRequest;
+import com.alipay.api.request.AlipayTradePayRequest;
+import com.alipay.api.response.AlipayFundAuthOperationDetailQueryResponse;
+import com.alipay.api.response.AlipayFundAuthOrderAppFreezeResponse;
+import com.alipay.api.response.AlipayTradePayResponse;
+import com.baomidou.mybatisplus.core.toolkit.Wrappers;
+import com.github.xiaoymin.knife4j.annotations.ApiOperationSupport;
+import io.swagger.annotations.Api;
+import io.swagger.annotations.ApiOperation;
+import io.swagger.annotations.ApiParam;
+import lombok.AllArgsConstructor;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springblade.common.constant.CommonConstant;
+import org.springblade.common.utils.NotifyUtils;
+import org.springblade.core.log.annotation.ApiLog;
+import org.springblade.core.log.logger.BladeLogger;
+import org.springblade.core.tool.api.R;
+import org.springblade.core.tool.utils.StringUtil;
+import org.springblade.modules.finance.entity.Order;
+import org.springblade.modules.finance.pay.entity.AlipayProperties;
+import org.springblade.modules.finance.service.IOrderService;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.*;
+
+import javax.servlet.http.HttpServletRequest;
+
+@RestController
+@AllArgsConstructor
+@RequestMapping(CommonConstant.API_URL + "/aliPay/sdk")
+@Api(value = "支付宝SDK", tags = "95.支付宝SDK")
+public class AliPay01Controller {
+
+	private static final Logger log = LoggerFactory.getLogger(AliPay01Controller.class);
+
+	//异步回调路径 https://wine.gzzzyd.com/api/v1/aliPay/sdk/notify_url
+	private static final String NOTIFY_URL = "https://wine.gzzzyd.com/api/v1/aliPay/sdk/notify_url";
+
+	@Autowired
+	private AlipayClient client;//支付宝请求sdk客户端
+
+	@Autowired
+	private AlipayProperties properties;//支付宝sdk配置
+
+	private final IOrderService orderService;
+
+	@Autowired
+	private BladeLogger logger;
+
+	@ApiLog("发起支付-直接交易")
+	@PostMapping("/pay_001")
+	@ApiOperation(value = "统一收单线下交易查询", notes = "当面付")
+	@ApiOperationSupport(order = 1)
+	public R pay001(@ApiParam(value = "订单号", required = true) @RequestParam String outTradeNo,
+					@ApiParam(value = "支付渠道:aliPay支付宝,wechatPay微信支付,unionPay银联 ", required = true) @RequestParam String payFor) throws AlipayApiException {
+		Order order = orderService.getOne(Wrappers.<Order>lambdaQuery().eq(Order::getOutTradeNo, outTradeNo));
+		if (order == null){
+			return R.fail("请求参数错误!");
+		}
+		if(StringUtil.isEmpty(payFor)){
+			return R.fail("请选择支付方式!");
+		}
+		if("aliPay".equals(payFor)){
+			JSONObject data = new JSONObject();
+			data.put("out_trade_no", outTradeNo); //商户订单号
+			//产品码, APP支付 QUICK_MSECURITY_PAY, PC支付 FAST_INSTANT_TRADE_PAY, 移动H5支付 QUICK_WAP_PAY
+			data.put("product_code", "QUICK_MSECURITY_PAY");
+			data.put("total_amount", "0.01"); //订单金额
+			data.put("subject", "中宏酒业"); //订单标题
+			//APP支付
+			AlipayTradeAppPayRequest request = new AlipayTradeAppPayRequest();
+			request.setNotifyUrl(NOTIFY_URL); //异步通知地址
+			request.setBizContent(data.toJSONString()); //业务参数
+			//APP支付
+			try {
+				AlipayResponse response = client.sdkExecute(request);
+				return R.data(response.getBody());
+			} catch (AlipayApiException e) {
+				e.printStackTrace();
+			}
+			return R.fail("发起支付失败!");
+		}
+		return R.fail("该支付方式暂不支持!");
+	}
+
+	@ApiLog("发起支付-预授权")
+	@PostMapping("/pay_002")
+	@ApiOperation(value = "统一收单交易支付接口", notes = "预授权")
+	@ApiOperationSupport(order = 2)
+	public R pay002(@ApiParam(value = "订单号", required = true) @RequestParam String outTradeNo,
+					@ApiParam(value = "授权订单号", required = true) @RequestParam String authCode,
+					@ApiParam(value = "支付渠道:aliPay支付宝,wechatPay微信支付,unionPay银联 ", required = true) @RequestParam String payFor) throws AlipayApiException {
+		Order order = orderService.getOne(Wrappers.<Order>lambdaQuery().eq(Order::getOutTradeNo, outTradeNo));
+		if (order == null){
+			return R.fail("请求参数错误!");
+		}
+		if(StringUtil.isEmpty(payFor)){
+			return R.fail("请选择支付方式!");
+		}
+		if("aliPay".equals(payFor)){
+			JSONObject data = new JSONObject();
+			data.put("out_trade_no", outTradeNo); //商户订单号
+			//产品码, APP支付 QUICK_MSECURITY_PAY, PC支付 FAST_INSTANT_TRADE_PAY, 移动H5支付 QUICK_WAP_PAY
+			data.put("product_code", "QUICK_MSECURITY_PAY");
+			data.put("total_amount", "0.01"); //订单金额
+			data.put("subject", "中宏酒业"); //订单标题
+			data.put("scene", "bar_code");
+			data.put("auth_code", authCode);
+			//APP支付
+			AlipayTradePayRequest request = new AlipayTradePayRequest();
+			request.setNotifyUrl(NOTIFY_URL); //异步通知地址
+			request.setBizContent(data.toJSONString()); //业务参数
+			//APP支付
+			try {
+				AlipayTradePayResponse response = client.sdkExecute(request);
+				return R.data(response.getBody());
+			} catch (AlipayApiException e) {
+				e.printStackTrace();
+			}
+			return R.fail("发起支付失败!");
+		}
+		return R.fail("该支付方式暂不支持!");
+	}
+
+	@PostMapping("/pay_003")
+	@ApiOperation(value = "线上资金授权冻结接口", notes = "支付请求")
+	@ApiOperationSupport(order = 3)
+	public R pay003(@ApiParam(value = "订单号", required = true) @RequestParam("outTradeNo") String outTradeNo) throws AlipayApiException {
+		JSONObject data = new JSONObject();
+		data.put("out_order_no", outTradeNo);
+		data.put("out_request_no", outTradeNo);
+		data.put("order_title","预授权冻结");
+		data.put("amount",0.01);
+		data.put("product_code","PRE_AUTH_ONLINE"); //销售产品码。支付宝预授权产品固定为 PRE_AUTH_ONLINE
+		data.put("payee_user_id", "2088341967443472");
+		data.put("timeout_express","30m");
+		//APP支付
+		AlipayFundAuthOrderAppFreezeRequest request = new AlipayFundAuthOrderAppFreezeRequest();
+		request.setNotifyUrl(NOTIFY_URL); //异步通知地址
+		request.setBizContent(data.toJSONString()); //业务参数
+		//APP支付
+		AlipayFundAuthOrderAppFreezeResponse response = client.sdkExecute(request);
+		if(response.isSuccess()){
+			return R.data(response.getBody());
+		}
+		return R.fail("授权失败!");
+	}
+
+	@GetMapping("/pay_004")
+	@ApiOperation(value = "资金授权操作查询接口", notes = "支付请求")
+	@ApiOperationSupport(order = 3)
+	public R pay004(@ApiParam(value = "订单号", required = true) @RequestParam String outTradeNo,
+					@ApiParam(value = "查询明细,1查询冻结明细,2查询解冻明细,3查询支付明细时", required = true) @RequestParam Integer type) throws AlipayApiException {
+		JSONObject data = new JSONObject();
+		if(type == 1){ //查询冻结明细
+			data.put("out_order_no",outTradeNo);
+			data.put("operation_type","FREEZE");
+		}else if(type == 2){ //查询解冻明细
+			data.put("out_order_no",outTradeNo);
+			data.put("operation_type","UNFREEZE");
+		}else if(type == 3){ //查询支付明细时
+			data.put("out_order_no",outTradeNo);
+			data.put("operation_type","PAY");
+		}else{
+			return R.fail("参数错误!");
+		}
+		// 设置整体请求参数
+		//APP支付
+		AlipayFundAuthOperationDetailQueryRequest request = new AlipayFundAuthOperationDetailQueryRequest();
+		request.setBizContent(data.toString());
+		//APP支付
+		AlipayFundAuthOperationDetailQueryResponse response = client.sdkExecute(request);
+		if(response.isSuccess()){
+			return R.data(response.getBody());
+		}
+		return R.fail("授权失败!");
+	}
+
+	@RequestMapping(value = "/notify_url", method = {RequestMethod.GET, RequestMethod.POST})
+	@ApiOperation(value = "异步通知相应", notes = "异步通知相应")
+	@ApiOperationSupport(order = 100)
+	public String notify(HttpServletRequest request) {
+		logger.info("支付宝回调-预授权", request.getParameterMap().toString());
+		if (!NotifyUtils.rsaCheck(properties, request.getParameterMap())) {
+			//这里处理验签失败
+		}
+		log.info("支付宝回调-预授权");
+		log.info(request.getParameterMap().toString());
+		request.getParameter("trade_no");//获取请求参数中的商户订单号
+		return "success";
+	}
+}

+ 856 - 0
src/main/java/org/springblade/modules/api/controller/AliPay02Controller.java

@@ -0,0 +1,856 @@
+package org.springblade.modules.api.controller;
+
+import cn.hutool.core.date.DateUtil;
+import com.alibaba.fastjson.JSON;
+import com.alibaba.fastjson.JSONObject;
+import com.alipay.api.AlipayApiException;
+import com.alipay.api.domain.*;
+import com.alipay.api.internal.util.AlipaySignature;
+import com.alipay.api.response.AlipayFundAuthOrderFreezeResponse;
+import com.alipay.api.response.AlipayFundCouponOrderAgreementPayResponse;
+import com.alipay.api.response.AlipayTradeCreateResponse;
+import com.github.xiaoymin.knife4j.annotations.ApiOperationSupport;
+import com.ijpay.alipay.AliPayApi;
+import com.ijpay.alipay.AliPayApiConfig;
+import com.ijpay.alipay.AliPayApiConfigKit;
+import com.ijpay.core.kit.PayKit;
+import com.ijpay.core.kit.RsaKit;
+import io.swagger.annotations.Api;
+import io.swagger.annotations.ApiOperation;
+import lombok.AllArgsConstructor;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springblade.common.constant.CommonConstant;
+import org.springblade.common.utils.StringUtils;
+import org.springblade.modules.finance.controller.AbstractAliPayApiController;
+import org.springblade.modules.finance.pay.entity.AjaxResult;
+import org.springblade.modules.finance.pay.entity.AliPayBean;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.*;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import java.util.Date;
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * <p>IJPay 让支付触手可及,封装了微信支付、支付宝支付、银联支付常用的支付方式以及各种常用的接口。</p>
+ *
+ * <p>不依赖任何第三方 mvc 框架,仅仅作为工具使用简单快速完成支付模块的开发,可轻松嵌入到任何系统里。 </p>
+ *
+ * <p>IJPay 交流群: 723992875</p>
+ *
+ * <p>Node.js 版: https://gitee.com/javen205/TNWX</p>
+ *
+ * <p>支付宝支付 Demo</p>
+ *
+ * @author Javen
+ */
+@RestController
+@AllArgsConstructor
+@RequestMapping(CommonConstant.API_URL + "/aliPay")
+@Api(value = "支付宝接口", tags = "96.支付宝接口")
+public class AliPay02Controller extends AbstractAliPayApiController {
+	private static final Logger log = LoggerFactory.getLogger(AliPay02Controller.class);
+
+	// 证书模式
+	// private final static String NOTIFY_URL = "/aliPay/cert_notify_url";
+	// private final static String RETURN_URL = "/aliPay/cert_return_url";
+
+	// 普通公钥模式
+    private final static String NOTIFY_URL = "/api/v1/aliPay/notify_url";
+	private final static String RETURN_URL = "/api/v1/aliPay/return_url";
+
+	private final AjaxResult result = new AjaxResult();
+
+	@Autowired
+	private AliPayBean aliPayBean;
+
+	@Override
+	public AliPayApiConfig getApiConfig() throws AlipayApiException {
+		AliPayApiConfig aliPayApiConfig;
+		try {
+			aliPayApiConfig = AliPayApiConfigKit.getApiConfig(aliPayBean.getAppId());
+		} catch (Exception e) {
+			aliPayApiConfig = AliPayApiConfig.builder()
+				.setAppId(aliPayBean.getAppId()) //aliPayBean.getAppId()
+				.setAliPayPublicKey(aliPayBean.getPublicKey())
+				.setAppCertPath(aliPayBean.getAppCertPath())
+				.setAliPayCertPath(aliPayBean.getAliPayCertPath())
+				.setAliPayRootCertPath(aliPayBean.getAliPayRootCertPath())
+				.setCharset("UTF-8")
+				.setPrivateKey(aliPayBean.getPrivateKey())
+				.setServiceUrl(aliPayBean.getServerUrl())
+				.setSignType("RSA2")
+				// 普通公钥方式
+				//.build();
+				// 证书模式
+				.buildByCert();
+		}
+		return aliPayApiConfig;
+	}
+
+	@PostMapping("/test")
+	@ApiOperation(value = "获取阿里支付配置信息", notes = "获取阿里支付配置信息")
+	@ApiOperationSupport(order = 2)
+	public AliPayApiConfig test() {
+		AliPayApiConfig aliPayApiConfig = AliPayApiConfigKit.getAliPayApiConfig();
+		String charset = aliPayApiConfig.getCharset();
+		log.info("charset>" + charset);
+		return aliPayApiConfig;
+	}
+
+
+	/**
+	 * app支付
+	 */
+	@GetMapping(value = "/appPay")
+	@ApiOperationSupport(order = 3)
+	@ApiOperation(value = "阿里支付", notes = "阿里支付")
+	public AjaxResult appPay() {
+		try {
+			AlipayTradeAppPayModel model = new AlipayTradeAppPayModel();
+			model.setBody("我是测试数据-By Javen");
+			model.setSubject("App支付测试-By Javen");
+			model.setOutTradeNo(StringUtils.getOutTradeNo());
+			model.setTimeoutExpress("30m");
+			model.setTotalAmount("0.01");
+			model.setPassbackParams("zzy");
+			model.setProductCode("123456512655");
+			String orderInfo = AliPayApi.appPayToResponse(model, aliPayBean.getDomain() + NOTIFY_URL).getBody();
+			result.success(orderInfo);
+		} catch (AlipayApiException e) {
+			e.printStackTrace();
+			result.addError("system error:" + e.getMessage());
+		}
+		return result;
+	}
+
+	/**
+	 * 创建订单
+	 * {"alipay_trade_create_response":{"code":"10000","msg":"Success","out_trade_no":"081014283315033","trade_no":"2017081021001004200200274066"},"sign":"ZagfFZntf0loojZzdrBNnHhenhyRrsXwHLBNt1Z/dBbx7cF1o7SZQrzNjRHHmVypHKuCmYifikZIqbNNrFJauSuhT4MQkBJE+YGPDtHqDf4Ajdsv3JEyAM3TR/Xm5gUOpzCY7w+RZzkHevsTd4cjKeGM54GBh0hQH/gSyhs4pEN3lRWopqcKkrkOGZPcmunkbrUAF7+AhKGUpK+AqDw4xmKFuVChDKaRdnhM6/yVsezJFXzlQeVgFjbfiWqULxBXq1gqicntyUxvRygKA+5zDTqE5Jj3XRDjVFIDBeOBAnM+u03fUP489wV5V5apyI449RWeybLg08Wo+jUmeOuXOA=="}
+	 */
+	@RequestMapping(value = "/tradeCreate" , method = {RequestMethod.GET, RequestMethod.POST})
+	@ResponseBody
+	@ApiOperation(value = "创建订单", notes = "创建订单")
+	@ApiOperationSupport(order = 4)
+	public String tradeCreate(@RequestParam("outTradeNo") String outTradeNo) {
+		String notifyUrl = aliPayBean.getDomain() + NOTIFY_URL;
+		AlipayTradeCreateModel model = new AlipayTradeCreateModel();
+		model.setOutTradeNo(outTradeNo);
+		model.setTotalAmount("88.88");
+		model.setBody("Body");
+		model.setSubject("Javen 测试统一收单交易创建接口");
+		//买家支付宝账号,和buyer_id不能同时为空
+		model.setBuyerLogonId("skuaqo5756@sandbox.com");
+		try {
+			AlipayTradeCreateResponse response = AliPayApi.tradeCreateToResponse(model, notifyUrl);
+			return response.getBody();
+		} catch (AlipayApiException e) {
+			e.printStackTrace();
+		}
+		return null;
+	}
+
+	@PostMapping(value = "/wapPayNoSdk")
+	public void wapPayNoSdk(HttpServletResponse response) {
+		try {
+			AliPayApiConfig aliPayApiConfig = AliPayApiConfigKit.getAliPayApiConfig();
+			Map<String, String> paramsMap = new HashMap<>();
+			paramsMap.put("app_id", aliPayApiConfig.getAppId());
+			paramsMap.put("method", "alipay.trade.wap.pay");
+			paramsMap.put("return_url", aliPayBean.getDomain() + RETURN_URL);
+			paramsMap.put("charset", aliPayApiConfig.getCharset());
+			paramsMap.put("sign_type", aliPayApiConfig.getSignType());
+			paramsMap.put("timestamp", DateUtil.format(new Date(), "yyyy-MM-dd HH:mm:ss"));
+			paramsMap.put("version", "1.0");
+			paramsMap.put("notify_url", aliPayBean.getDomain() + NOTIFY_URL);
+
+			Map<String, String> bizMap = new HashMap<>();
+			bizMap.put("body", "IJPay 聚合支付-H5");
+			bizMap.put("subject", "IJPay 让支付触手可及");
+			bizMap.put("out_trade_no", StringUtils.getOutTradeNo());
+			bizMap.put("total_amount", "6.66");
+			bizMap.put("product_code", "QUICK_WAP_WAY");
+
+			paramsMap.put("biz_content", JSON.toJSONString(bizMap));
+
+			String content = PayKit.createLinkString(paramsMap);
+
+			System.out.println(content);
+
+			String encrypt = RsaKit.encryptByPrivateKey(content, aliPayApiConfig.getPrivateKey());
+			System.out.println(encrypt);
+//            encrypt = AlipaySignature.rsaSign(content,aliPayApiConfig.getPrivateKey(), "UTF-8","RSA2");
+//            System.out.println(encrypt);
+			paramsMap.put("sign", encrypt);
+
+			String url = aliPayApiConfig.getServiceUrl() + "?" + PayKit.createLinkString(paramsMap, true);
+			System.out.println(url);
+			response.sendRedirect(url);
+
+		} catch (Exception e) {
+			e.printStackTrace();
+		}
+	}
+
+	@PostMapping(value = "/wapPay")
+	public void wapPay(HttpServletResponse response) {
+		String body = "我是测试数据-By Javen";
+		String subject = "Javen Wap支付测试";
+		String totalAmount = "1";
+		String passBackParams = "1";
+		String returnUrl = aliPayBean.getDomain() + RETURN_URL;
+		String notifyUrl = aliPayBean.getDomain() + NOTIFY_URL;
+
+		AlipayTradeWapPayModel model = new AlipayTradeWapPayModel();
+		model.setBody(body);
+		model.setSubject(subject);
+		model.setTotalAmount(totalAmount);
+		model.setPassbackParams(passBackParams);
+		String outTradeNo = StringUtils.getOutTradeNo();
+		System.out.println("wap outTradeNo>" + outTradeNo);
+		model.setOutTradeNo(outTradeNo);
+		model.setProductCode("QUICK_WAP_PAY");
+
+		try {
+			AliPayApi.wapPay(response, model, returnUrl, notifyUrl);
+		} catch (Exception e) {
+			e.printStackTrace();
+		}
+	}
+
+
+	/**
+	 * PC支付
+	 */
+	@PostMapping(value = "/pcPay")
+	@ApiOperation(value = "PC支付", notes = "PC支付")
+	public void pcPay(HttpServletResponse response) {
+		try {
+			String totalAmount = "88.88";
+			String outTradeNo = StringUtils.getOutTradeNo();
+			log.info("pc outTradeNo>" + outTradeNo);
+
+			String returnUrl = aliPayBean.getDomain() + RETURN_URL;
+			String notifyUrl = aliPayBean.getDomain() + NOTIFY_URL;
+			AlipayTradePagePayModel model = new AlipayTradePagePayModel();
+
+			model.setOutTradeNo(outTradeNo);
+			model.setProductCode("FAST_INSTANT_TRADE_PAY");
+			model.setTotalAmount(totalAmount);
+			model.setSubject("Javen PC支付测试");
+			model.setBody("Javen IJPay PC支付测试");
+			model.setPassbackParams("passback_params");
+			/**
+			 * 花呗分期相关的设置,测试环境不支持花呗分期的测试
+			 * hb_fq_num代表花呗分期数,仅支持传入3、6、12,其他期数暂不支持,传入会报错;
+			 * hb_fq_seller_percent代表卖家承担收费比例,商家承担手续费传入100,用户承担手续费传入0,仅支持传入100、0两种,其他比例暂不支持,传入会报错。
+			 */
+//            ExtendParams extendParams = new ExtendParams();
+//            extendParams.setHbFqNum("3");
+//            extendParams.setHbFqSellerPercent("0");
+//            model.setExtendParams(extendParams);
+
+			AliPayApi.tradePage(response, model, notifyUrl, returnUrl);
+		} catch (Exception e) {
+			e.printStackTrace();
+		}
+
+	}
+
+	@PostMapping(value = "/tradePay")
+	@ApiOperation(value = "支付宝声波/条形码支付测试", notes = "支付宝声波/条形码支付测试")
+	public String tradePay(@RequestParam("authCode") String authCode, @RequestParam("scene") String scene) {
+		String subject = null;
+		String waveCode = "wave_code";
+		String barCode = "bar_code";
+		if (scene.equals(waveCode)) {
+			subject = "Javen 支付宝声波支付测试";
+		} else if (scene.equals(barCode)) {
+			subject = "Javen 支付宝条形码支付测试";
+		}
+		String totalAmount = "100";
+		String notifyUrl = aliPayBean.getDomain() + NOTIFY_URL;
+
+		AlipayTradePayModel model = new AlipayTradePayModel();
+		model.setAuthCode(authCode);
+		model.setSubject(subject);
+		model.setTotalAmount(totalAmount);
+		model.setOutTradeNo(StringUtils.getOutTradeNo());
+		model.setScene(scene);
+		try {
+			return AliPayApi.tradePayToResponse(model, notifyUrl).getBody();
+		} catch (Exception e) {
+			e.printStackTrace();
+		}
+
+		return null;
+	}
+
+	/**
+	 * 扫码支付
+	 */
+	@GetMapping(value = "/tradePreCreatePay")
+	@ApiOperation(value = "扫码支付", notes = "扫码支付")
+	public String tradePreCreatePay() {
+		String subject = "Javen 支付宝扫码支付测试";
+		String totalAmount = "86";
+		String storeId = "123";
+//        String notifyUrl = aliPayBean.getDomain() + NOTIFY_URL;
+		String notifyUrl = aliPayBean.getDomain() + "/aliPay/cert_notify_url";
+
+		AlipayTradePrecreateModel model = new AlipayTradePrecreateModel();
+		model.setSubject(subject);
+		model.setTotalAmount(totalAmount);
+		model.setStoreId(storeId);
+		model.setTimeoutExpress("5m");
+		model.setOutTradeNo(StringUtils.getOutTradeNo());
+		try {
+			String resultStr = AliPayApi.tradePrecreatePayToResponse(model, notifyUrl).getBody();
+			JSONObject jsonObject = JSONObject.parseObject(resultStr);
+			return jsonObject.getJSONObject("alipay_trade_precreate_response").getString("qr_code");
+		} catch (Exception e) {
+			e.printStackTrace();
+		}
+		return null;
+	}
+
+	/**
+	 * 单笔转账到支付宝账户
+	 * https://docs.open.alipay.com/309/106235/
+	 */
+	@GetMapping(value = "/transfer")
+	@ApiOperation(value = "单笔转账到支付宝账户", notes = "单笔转账到支付宝账户")
+	public String transfer() {
+		String totalAmount = "66";
+		AlipayFundTransToaccountTransferModel model = new AlipayFundTransToaccountTransferModel();
+		model.setOutBizNo(StringUtils.getOutTradeNo());
+		model.setPayeeType("ALIPAY_LOGONID");
+		model.setPayeeAccount("gxthqd7606@sandbox.com");
+		model.setAmount(totalAmount);
+		model.setPayerShowName("测试退款");
+		model.setPayerRealName("沙箱环境");
+		model.setRemark("javen测试单笔转账到支付宝");
+
+		try {
+			return AliPayApi.transferToResponse(model).getBody();
+		} catch (Exception e) {
+			e.printStackTrace();
+		}
+		return null;
+	}
+
+	@GetMapping(value = "/transferQuery")
+	@ApiOperation(value = "查询转账信息", notes = "查询转账信息")
+	public String transferQuery(@RequestParam(required = false, name = "outBizNo") String outBizNo,
+								@RequestParam(required = false, name = "orderId") String orderId) {
+		AlipayFundTransOrderQueryModel model = new AlipayFundTransOrderQueryModel();
+		if (StringUtils.isNotEmpty(outBizNo)) {
+			model.setOutBizNo(outBizNo);
+		}
+		if (StringUtils.isNotEmpty(orderId)) {
+			model.setOrderId(orderId);
+		}
+
+		try {
+			return AliPayApi.transferQueryToResponse(model).getBody();
+		} catch (Exception e) {
+			e.printStackTrace();
+		}
+		return null;
+	}
+
+	@GetMapping(value = "/uniTransfer")
+	@ResponseBody
+	@ApiOperation(value = "统一转账-转账至支付宝账户", notes = "统一转账-转账至支付宝账户")
+	public String uniTransfer() {
+		String totalAmount = "1";
+		AlipayFundTransUniTransferModel model = new AlipayFundTransUniTransferModel();
+		model.setOutBizNo(StringUtils.getOutTradeNo());
+		model.setTransAmount(totalAmount);
+		model.setProductCode("TRANS_ACCOUNT_NO_PWD");
+		model.setBizScene("DIRECT_TRANSFER");
+		model.setOrderTitle("统一转账-转账至支付宝账户");
+		model.setRemark("IJPay 测试统一转账");
+
+		Participant payeeInfo = new Participant();
+		payeeInfo.setIdentity("gxthqd7606@sandbox.com");
+		payeeInfo.setIdentityType("ALIPAY_LOGON_ID");
+		payeeInfo.setName("沙箱环境");
+		model.setPayeeInfo(payeeInfo);
+
+		try {
+			return AliPayApi.uniTransferToResponse(model, null).getBody();
+		} catch (Exception e) {
+			e.printStackTrace();
+		}
+		return null;
+	}
+
+	@GetMapping(value = "/uniTransferQuery")
+	@ResponseBody
+	public String uniTransferQuery(@RequestParam(required = false, name = "outBizNo") String outBizNo,
+								   @RequestParam(required = false, name = "orderId") String orderId) {
+		AlipayFundTransCommonQueryModel model = new AlipayFundTransCommonQueryModel();
+		if (StringUtils.isNotEmpty(outBizNo)) {
+			model.setOutBizNo(outBizNo);
+		}
+		if (StringUtils.isNotEmpty(orderId)) {
+			model.setOrderId(orderId);
+		}
+
+		try {
+			return AliPayApi.transCommonQueryToResponse(model, null).getBody();
+		} catch (Exception e) {
+			e.printStackTrace();
+		}
+		return null;
+	}
+
+	@GetMapping(value = "/accountQuery")
+	@ResponseBody
+	@ApiOperation(value = "账号查询", notes = "账号查询")
+	public String accountQuery(@RequestParam(required = true, name = "aliPayUserId") String aliPayUserId) {
+		AlipayFundAccountQueryModel model = new AlipayFundAccountQueryModel();
+		model.setAlipayUserId(aliPayUserId);
+		model.setAccountType("ACCTRANS_ACCOUNT");
+		try {
+			return AliPayApi.accountQueryToResponse(model, null).getBody();
+		} catch (Exception e) {
+			e.printStackTrace();
+		}
+		return null;
+	}
+
+	/**
+	 * 资金授权冻结接口
+	 */
+	@GetMapping(value = "/authOrderFreeze")
+	@ResponseBody
+	@ApiOperation(value = "资金授权冻结接口", notes = "资金授权冻结接口")
+	public AlipayFundAuthOrderFreezeResponse authOrderFreeze(@RequestParam("auth_code") String authCode) {
+		try {
+			AlipayFundAuthOrderFreezeModel model = new AlipayFundAuthOrderFreezeModel();
+			model.setOutOrderNo(StringUtils.getOutTradeNo());
+			model.setOutRequestNo(StringUtils.getOutTradeNo());
+			model.setAuthCode(authCode);
+			model.setAuthCodeType("bar_code");
+			model.setOrderTitle("资金授权冻结-By IJPay");
+			model.setAmount("36");
+			model.setProductCode("PRE_AUTH");
+
+			return AliPayApi.authOrderFreezeToResponse(model);
+		} catch (Exception e) {
+			e.printStackTrace();
+		}
+		return null;
+	}
+
+
+	/**
+	 * 红包协议支付接口
+	 * https://docs.open.alipay.com/301/106168/
+	 */
+	@GetMapping(value = "/agreementPay")
+	@ResponseBody
+	@ApiOperation(value = "红包协议支付接口", notes = "红包协议支付接口")
+	public AlipayFundCouponOrderAgreementPayResponse agreementPay() {
+		try {
+			AlipayFundCouponOrderAgreementPayModel model = new AlipayFundCouponOrderAgreementPayModel();
+			model.setOutOrderNo(StringUtils.getOutTradeNo());
+			model.setOutRequestNo(StringUtils.getOutTradeNo());
+			model.setOrderTitle("红包协议支付接口-By IJPay");
+			model.setAmount("36");
+			model.setPayerUserId("2088102180432465");
+
+			return AliPayApi.fundCouponOrderAgreementPayToResponse(model);
+		} catch (Exception e) {
+			e.printStackTrace();
+		}
+		return null;
+	}
+
+	/**
+	 * 下载对账单
+	 */
+	@GetMapping(value = "/dataDataServiceBill")
+	@ResponseBody
+	@ApiOperation(value = "下载对账单", notes = "下载对账单")
+	public String dataDataServiceBill(@RequestParam("billDate") String billDate) {
+		try {
+			AlipayDataDataserviceBillDownloadurlQueryModel model = new AlipayDataDataserviceBillDownloadurlQueryModel();
+			model.setBillType("trade");
+			model.setBillDate(billDate);
+			return AliPayApi.billDownloadUrlQuery(model);
+		} catch (AlipayApiException e) {
+			e.printStackTrace();
+		}
+		return null;
+	}
+
+	/**
+	 * 退款
+	 */
+	@PostMapping(value = "/tradeRefund")
+	@ResponseBody
+	@ApiOperation(value = "退款", notes = "退款")
+	public String tradeRefund(@RequestParam(required = false, name = "outTradeNo") String outTradeNo, @RequestParam(required = false, name = "tradeNo") String tradeNo) {
+
+		try {
+			AlipayTradeRefundModel model = new AlipayTradeRefundModel();
+			if (StringUtils.isNotEmpty(outTradeNo)) {
+				model.setOutTradeNo(outTradeNo);
+			}
+			if (StringUtils.isNotEmpty(tradeNo)) {
+				model.setTradeNo(tradeNo);
+			}
+			model.setRefundAmount("86.00");
+			model.setRefundReason("正常退款");
+			return AliPayApi.tradeRefundToResponse(model).getBody();
+		} catch (AlipayApiException e) {
+			e.printStackTrace();
+		}
+		return null;
+	}
+
+	/**
+	 * 交易查询
+	 */
+	@PostMapping(value = "/tradeQuery")
+	@ResponseBody
+	@ApiOperation(value = "交易查询", notes = "交易查询")
+	public String tradeQuery(@RequestParam(required = false, name = "outTradeNo") String outTradeNo, @RequestParam(required = false, name = "tradeNo") String tradeNo) {
+		try {
+			AlipayTradeQueryModel model = new AlipayTradeQueryModel();
+			if (StringUtils.isNotEmpty(outTradeNo)) {
+				model.setOutTradeNo(outTradeNo);
+			}
+			if (StringUtils.isNotEmpty(tradeNo)) {
+				model.setTradeNo(tradeNo);
+			}
+			return AliPayApi.tradeQueryToResponse(model).getBody();
+		} catch (AlipayApiException e) {
+			e.printStackTrace();
+		}
+		return null;
+	}
+
+	@PostMapping(value = "/tradeQueryByStr")
+	@ResponseBody
+	@ApiOperation(value = "交易查询", notes = "交易查询")
+	public String tradeQueryByStr(@RequestParam(required = false, name = "outTradeNo") String outTradeNo, @RequestParam(required = false, name = "tradeNo") String tradeNo) {
+		AlipayTradeQueryModel model = new AlipayTradeQueryModel();
+		if (StringUtils.isNotEmpty(outTradeNo)) {
+			model.setOutTradeNo(outTradeNo);
+		}
+		if (StringUtils.isNotEmpty(tradeNo)) {
+			model.setTradeNo(tradeNo);
+		}
+
+		try {
+			return AliPayApi.tradeQueryToResponse(model).getBody();
+		} catch (AlipayApiException e) {
+			e.printStackTrace();
+		}
+
+		return null;
+	}
+
+
+
+	/**
+	 * 撤销订单
+	 */
+	@PostMapping(value = "/tradeCancel")
+	@ResponseBody
+	@ApiOperation(value = "撤销订单", notes = "撤销订单")
+	public String tradeCancel(@RequestParam(required = false, name = "outTradeNo") String outTradeNo, @RequestParam(required = false, name = "tradeNo") String tradeNo) {
+		try {
+			AlipayTradeCancelModel model = new AlipayTradeCancelModel();
+			if (StringUtils.isNotEmpty(outTradeNo)) {
+				model.setOutTradeNo(outTradeNo);
+			}
+			if (StringUtils.isNotEmpty(tradeNo)) {
+				model.setTradeNo(tradeNo);
+			}
+
+			return AliPayApi.tradeCancelToResponse(model).getBody();
+		} catch (AlipayApiException e) {
+			e.printStackTrace();
+		}
+		return null;
+	}
+
+	/**
+	 * 关闭订单
+	 */
+	@ApiOperation(value = "关闭订单", notes = "关闭订单")
+	@RequestMapping(value = "/tradeClose")
+	@ResponseBody
+	public String tradeClose(@RequestParam("outTradeNo") String outTradeNo, @RequestParam("tradeNo") String tradeNo) {
+		try {
+			AlipayTradeCloseModel model = new AlipayTradeCloseModel();
+			if (StringUtils.isNotEmpty(outTradeNo)) {
+				model.setOutTradeNo(outTradeNo);
+			}
+			if (StringUtils.isNotEmpty(tradeNo)) {
+				model.setTradeNo(tradeNo);
+			}
+
+			return AliPayApi.tradeCloseToResponse(model).getBody();
+		} catch (AlipayApiException e) {
+			e.printStackTrace();
+		}
+		return null;
+	}
+
+	/**
+	 * 结算
+	 */
+	@ApiOperation(value = "结算", notes = "结算")
+	@RequestMapping(value = "/tradeOrderSettle")
+	@ResponseBody
+	public String tradeOrderSettle(@RequestParam("tradeNo") String tradeNo) {
+		try {
+			AlipayTradeOrderSettleModel model = new AlipayTradeOrderSettleModel();
+			model.setOutRequestNo(StringUtils.getOutTradeNo());
+			model.setTradeNo(tradeNo);
+
+			return AliPayApi.tradeOrderSettleToResponse(model).getBody();
+		} catch (AlipayApiException e) {
+			e.printStackTrace();
+		}
+		return null;
+	}
+
+	/**
+	 * 获取应用授权URL并授权
+	 */
+	@ApiOperation(value = "获取应用授权URL并授权", notes = "获取应用授权URL并授权")
+	@PostMapping(value = "/toOauth")
+	@ResponseBody
+	public void toOauth(HttpServletResponse response) {
+		try {
+			String redirectUri = aliPayBean.getDomain() + "/aliPay/redirect_uri";
+			String oauth2Url = AliPayApi.getOauth2Url(aliPayBean.getAppId(), redirectUri);
+			response.sendRedirect(oauth2Url);
+		} catch (Exception e) {
+			e.printStackTrace();
+		}
+	}
+
+	/**
+	 * 应用授权回调
+	 */
+	@RequestMapping(value = "/redirect_uri")
+	@ResponseBody
+	@ApiOperation(value = "应用授权回调", notes = "应用授权回调")
+	public String redirectUri(@RequestParam("app_id") String appId, @RequestParam("app_auth_code") String appAuthCode) {
+		try {
+			System.out.println("app_id:" + appId);
+			System.out.println("app_auth_code:" + appAuthCode);
+			//使用app_auth_code换取app_auth_token
+			AlipayOpenAuthTokenAppModel model = new AlipayOpenAuthTokenAppModel();
+			model.setGrantType("authorization_code");
+			model.setCode(appAuthCode);
+			return AliPayApi.openAuthTokenAppToResponse(model).getBody();
+		} catch (Exception e) {
+			e.printStackTrace();
+		}
+		return null;
+	}
+
+	/**
+	 * 查询授权信息
+	 */
+	@GetMapping(value = "/openAuthTokenAppQuery")
+	@ResponseBody
+	@ApiOperation(value = "查询授权信息", notes = "查询授权信息")
+	public String openAuthTokenAppQuery(@RequestParam("appAuthToken") String appAuthToken) {
+		try {
+			AlipayOpenAuthTokenAppQueryModel model = new AlipayOpenAuthTokenAppQueryModel();
+			model.setAppAuthToken(appAuthToken);
+			return AliPayApi.openAuthTokenAppQueryToResponse(model).getBody();
+		} catch (AlipayApiException e) {
+			e.printStackTrace();
+		}
+		return null;
+	}
+
+	/**
+	 * 批量付款到支付宝账户有密接口
+	 */
+	@PostMapping(value = "/batchTrans")
+	@ResponseBody
+	@ApiOperation(value = "批量付款到支付宝账户有密接口", notes = "批量付款到支付宝账户有密接口")
+	public void batchTrans(HttpServletResponse response) {
+		try {
+			String signType = "MD5";
+			String notifyUrl = aliPayBean.getDomain() + NOTIFY_URL;
+			Map<String, String> params = new HashMap<>(15);
+			params.put("partner", "PID");
+			params.put("sign_type", signType);
+			params.put("notify_url", notifyUrl);
+			params.put("account_name", "xxx");
+			params.put("detail_data", "流水号1^收款方账号1^收款账号姓名1^付款金额1^备注说明1|流水号2^收款方账号2^收款账号姓名2^付款金额2^备注说明2");
+			params.put("batch_no", String.valueOf(System.currentTimeMillis()));
+			params.put("batch_num", 1 + "");
+			params.put("batch_fee", 10.00 + "");
+			params.put("email", "xx@xxx.com");
+
+			AliPayApi.batchTrans(params, aliPayBean.getPrivateKey(), signType, response);
+		} catch (Exception e) {
+			e.printStackTrace();
+		}
+	}
+
+
+	/**
+	 * 地铁购票核销码发码
+	 */
+	@ApiOperation(value = "地铁购票核销码发码", notes = "地铁购票核销码发码")
+	@PostMapping(value = "/voucherGenerate")
+	@ResponseBody
+	public String voucherGenerate(@RequestParam("tradeNo") String tradeNo) {
+		try {
+			//需要支付成功的订单号
+//			String tradeNo = getPara("tradeNo");
+
+			AlipayCommerceCityfacilitatorVoucherGenerateModel model = new AlipayCommerceCityfacilitatorVoucherGenerateModel();
+			model.setCityCode("440300");
+			model.setTradeNo(tradeNo);
+			model.setTotalFee("8");
+			model.setTicketNum("2");
+			model.setTicketType("oneway");
+			model.setSiteBegin("001");
+			model.setSiteEnd("002");
+			model.setTicketPrice("4");
+			return AliPayApi.voucherGenerateToResponse(model).getBody();
+		} catch (AlipayApiException e) {
+			e.printStackTrace();
+		}
+		return null;
+	}
+
+	@RequestMapping(value = "/return_url")
+	@ResponseBody
+	@ApiOperation(value = "支付回调", notes = "支付回调")
+	public String returnUrl(HttpServletRequest request) {
+		try {
+			// 获取支付宝GET过来反馈信息
+			Map<String, String> map = AliPayApi.toMap(request);
+			for (Map.Entry<String, String> entry : map.entrySet()) {
+				System.out.println(entry.getKey() + " = " + entry.getValue());
+			}
+
+			boolean verifyResult = AlipaySignature.rsaCheckV1(map, aliPayBean.getPublicKey(), "UTF-8",
+				"RSA2");
+
+			if (verifyResult) {
+				// TODO 请在这里加上商户的业务逻辑程序代码
+				System.out.println("return_url 验证成功");
+
+				return "success";
+			} else {
+				System.out.println("return_url 验证失败");
+				// TODO
+				return "failure";
+			}
+		} catch (AlipayApiException e) {
+			e.printStackTrace();
+			return "failure";
+		}
+	}
+
+	@RequestMapping(value = "/cert_return_url")
+	@ResponseBody
+	@ApiOperation(value = "支付回调(证书)", notes = "支付回调(证书)")
+	public String certReturnUrl(HttpServletRequest request) {
+		try {
+			// 获取支付宝GET过来反馈信息
+			Map<String, String> map = AliPayApi.toMap(request);
+			for (Map.Entry<String, String> entry : map.entrySet()) {
+				System.out.println(entry.getKey() + " = " + entry.getValue());
+			}
+
+			boolean verifyResult = AlipaySignature.rsaCertCheckV1(map, aliPayBean.getAliPayCertPath(), "UTF-8",
+				"RSA2");
+
+			if (verifyResult) {
+				// TODO 请在这里加上商户的业务逻辑程序代码
+				System.out.println("certReturnUrl 验证成功");
+
+				return "success";
+			} else {
+				System.out.println("certReturnUrl 验证失败");
+				// TODO
+				return "failure";
+			}
+		} catch (AlipayApiException e) {
+			e.printStackTrace();
+			return "failure";
+		}
+	}
+
+
+	@RequestMapping(value = "/notify_url")
+	@ResponseBody
+	@ApiOperation(value = "验证支付回调", notes = "验证支付回调")
+	public String notifyUrl(HttpServletRequest request) {
+		try {
+			// 获取支付宝POST过来反馈信息
+			Map<String, String> params = AliPayApi.toMap(request);
+
+			for (Map.Entry<String, String> entry : params.entrySet()) {
+				System.out.println(entry.getKey() + " = " + entry.getValue());
+			}
+
+			boolean verifyResult = AlipaySignature.rsaCheckV1(params, aliPayBean.getPublicKey(), "UTF-8", "RSA2");
+
+			if (verifyResult) {
+				// TODO 请在这里加上商户的业务逻辑程序代码 异步通知可能出现订单重复通知 需要做去重处理
+				System.out.println("notify_url 验证成功succcess");
+				return "success";
+			} else {
+				System.out.println("notify_url 验证失败");
+				// TODO
+				return "failure";
+			}
+		} catch (AlipayApiException e) {
+			e.printStackTrace();
+			return "failure";
+		}
+	}
+
+	@RequestMapping(value = "/cert_notify_url")
+	@ResponseBody
+	@ApiOperation(value = "验证支付回调(证书)", notes = "验证支付回调(证书)")
+	public String certNotifyUrl(HttpServletRequest request) {
+		try {
+			// 获取支付宝POST过来反馈信息
+			Map<String, String> params = AliPayApi.toMap(request);
+
+			for (Map.Entry<String, String> entry : params.entrySet()) {
+				System.out.println(entry.getKey() + " = " + entry.getValue());
+			}
+
+			boolean verifyResult = AlipaySignature.rsaCertCheckV1(params, aliPayBean.getAliPayCertPath(), "UTF-8", "RSA2");
+
+			if (verifyResult) {
+				// TODO 请在这里加上商户的业务逻辑程序代码 异步通知可能出现订单重复通知 需要做去重处理
+				System.out.println("certNotifyUrl 验证成功succcess");
+				return "success";
+			} else {
+				System.out.println("certNotifyUrl 验证失败");
+				// TODO
+				return "failure";
+			}
+		} catch (AlipayApiException e) {
+			e.printStackTrace();
+			return "failure";
+		}
+	}
+
+}

+ 90 - 35
src/main/java/org/springblade/modules/api/controller/Api01Controller.java

@@ -16,6 +16,8 @@
  */
 package org.springblade.modules.api.controller;
 
+import cn.hutool.core.util.DesensitizedUtil;
+import cn.hutool.core.util.PhoneUtil;
 import com.baomidou.mybatisplus.core.toolkit.Wrappers;
 import com.github.xiaoymin.knife4j.annotations.ApiOperationSupport;
 import io.swagger.annotations.Api;
@@ -25,13 +27,17 @@ import lombok.AllArgsConstructor;
 import org.springblade.common.constant.CommonConstant;
 import org.springblade.core.boot.ctrl.BladeController;
 import org.springblade.core.cache.utils.CacheUtil;
+import org.springblade.core.jwt.JwtUtil;
+import org.springblade.core.jwt.props.JwtProperties;
+import org.springblade.core.launch.constant.TokenConstant;
 import org.springblade.core.log.annotation.ApiLog;
+import org.springblade.core.redis.cache.BladeRedis;
+import org.springblade.core.secure.BladeUser;
+import org.springblade.core.secure.utils.AuthUtil;
+import org.springblade.core.sms.model.SmsCode;
 import org.springblade.core.tool.api.R;
 import org.springblade.core.tool.support.Kv;
-import org.springblade.core.tool.utils.DateUtil;
-import org.springblade.core.tool.utils.DigestUtil;
-import org.springblade.core.tool.utils.Func;
-import org.springblade.core.tool.utils.WebUtil;
+import org.springblade.core.tool.utils.*;
 import org.springblade.modules.auth.enums.UserEnum;
 import org.springblade.modules.auth.provider.ITokenGranter;
 import org.springblade.modules.auth.provider.TokenGranterBuilder;
@@ -39,17 +45,17 @@ import org.springblade.modules.auth.provider.TokenParameter;
 import org.springblade.modules.auth.utils.TokenUtil;
 import org.springblade.modules.platform.entity.UserRecom;
 import org.springblade.modules.platform.service.IUserRecomService;
+import org.springblade.modules.resource.builder.sms.SmsBuilder;
 import org.springblade.modules.system.entity.User;
 import org.springblade.modules.system.entity.UserInfo;
 import org.springblade.modules.system.service.IUserService;
-import org.springframework.web.bind.annotation.PostMapping;
-import org.springframework.web.bind.annotation.RequestMapping;
-import org.springframework.web.bind.annotation.RequestParam;
-import org.springframework.web.bind.annotation.RestController;
+import org.springframework.web.bind.annotation.*;
 
 import javax.servlet.http.HttpServletResponse;
 
 import static org.springblade.core.cache.constant.CacheConstant.USER_CACHE;
+import static org.springblade.modules.resource.utils.SmsUtil.VALIDATE_FAIL;
+import static org.springblade.modules.resource.utils.SmsUtil.VALIDATE_SUCCESS;
 
 /**
  * 控制器
@@ -65,6 +71,8 @@ public class Api01Controller extends BladeController {
 
 	private final IUserService userService;
 	private final IUserRecomService userRecomService;
+	private final BladeRedis bladeRedis;
+	private final JwtProperties jwtProperties;
 
 	@ApiLog("用户注册")
 	@PostMapping("/user-register")
@@ -72,27 +80,36 @@ public class Api01Controller extends BladeController {
 	@ApiOperation(value = "用户注册", notes = "手机号注册")
 	public R userRegister(@ApiParam(value = "邀请码", required = true) @RequestParam(value = "inviteCode") String inviteCode,
 						  @ApiParam(value = "手机号", required = true) @RequestParam(value = "phone") String phone,
+						  @ApiParam(value = "密码", required = true) @RequestParam(value = "password") String password,
 						  @ApiParam(value = "验证码", required = true) @RequestParam(value = "captchaCode", required = false) String captchaCode,
-						  @ApiParam(value = "密码", required = true) @RequestParam(value = "password") String password){
+						  @ApiParam(value = "验证ID, 发送验证码返回的ID", required = true) @RequestParam(value = "captchaId") String captchaId){
 		User query = userService.getOne(Wrappers.<User>query().lambda().eq(User::getCode, inviteCode));
 		if (query == null){
 			return R.fail("邀请码输入错误!");
 		}
+		if (!PhoneUtil.isPhone(phone)){
+			return R.fail("请输入正确的手机号!");
+		}
+		if (StringUtil.isBlank(captchaCode) || StringUtil.isBlank(captchaId)){
+			return R.fail("请输入手机验证码!");
+		}
 		User query1 = userService.getOne(Wrappers.<User>query().lambda().eq(User::getAccount, phone));
 		if (query1 != null){
 			return R.fail("手机号已注册!");
 		}
+		boolean flg = captchaCode(phone, captchaId, captchaCode);
+		if (!flg){
+			return R.fail(VALIDATE_FAIL);
+		}
 		String tenantId = WebUtil.getRequest().getHeader(TokenUtil.TENANT_HEADER_KEY);
 		User user = new User();
 		user.setAccount(phone);
 		user.setPhone(phone);
 		user.setTenantId(tenantId);
 		user.setPassword(password);
-		String startStr = phone.substring(0,3);
-		String endStr = phone.substring(phone.length()- 2);
-		user.setName(startStr + "*****" + endStr);
+		user.setName(DesensitizedUtil.mobilePhone(phone));
 		CacheUtil.clear(USER_CACHE);
-		boolean flg = userService.registerApp(user, query.getId());
+		flg = userService.registerApp(user, query.getId());
 		if (flg){
 			//添加用户推荐记录表数据
 			query1 = userService.getOne(Wrappers.<User>query().lambda().eq(User::getAccount, phone));
@@ -137,46 +154,84 @@ public class Api01Controller extends BladeController {
 	@PostMapping("/login_phone")
 	@ApiOperationSupport(order = 3)
 	@ApiOperation(value = "手机验证码登录", notes = "账号:account,密码:password")
-	public Kv phoneLogin(@ApiParam(value = "账号", required = true) @RequestParam String username,
-						 @ApiParam(value = "密码", required = true) @RequestParam String password) {
+	public R phoneLogin(@ApiParam(value = "账号", required = true) @RequestParam String username,
+						@ApiParam(value = "验证码", required = true) @RequestParam(value = "captchaCode") String captchaCode,
+						@ApiParam(value = "验证ID, 发送验证码返回的ID", required = true) @RequestParam(value = "captchaId") String captchaId) {
+		if (!PhoneUtil.isPhone(username)){
+			return R.fail("请输入正确的手机号!");
+		}
+		if (StringUtil.isEmpty(captchaCode) ||StringUtil.isEmpty(captchaId)){
+			return R.fail("请输入手机验证码!");
+		}
 		String tenantId = WebUtil.getRequest().getHeader(TokenUtil.TENANT_HEADER_KEY);
-		Kv authInfo = Kv.create();
-		String grantType = WebUtil.getRequest().getParameter("grant_type");
-		String refreshToken = WebUtil.getRequest().getParameter("refresh_token");
-
-		String userType = Func.toStr(WebUtil.getRequest().getHeader(TokenUtil.USER_TYPE_HEADER_KEY), TokenUtil.DEFAULT_USER_TYPE);
-
+		String grantType = "phone";
+		String userType = Func.toStr(WebUtil.getRequest().getHeader(TokenUtil.USER_TYPE_HEADER_KEY), UserEnum.APP.getName());
 		TokenParameter tokenParameter = new TokenParameter();
 		tokenParameter.getArgs().set("tenantId", tenantId)
 			.set("username", username)
-			.set("password", password)
+			.set("captchaId", captchaId)
+			.set("captchaCode", captchaCode)
 			.set("grantType", grantType)
-			.set("refreshToken", refreshToken)
 			.set("userType", userType);
-
 		ITokenGranter granter = TokenGranterBuilder.getGranter(grantType);
 		UserInfo userInfo = granter.grant(tokenParameter);
-		if (userInfo == null || userInfo.getUser() == null) {
-			return authInfo.set("error_code", HttpServletResponse.SC_BAD_REQUEST).set("error_description", "用户名或密码不正确");
-		}
-		return TokenUtil.createAuthInfo(userInfo);
+		return R.data(TokenUtil.createAuthInfo(userInfo));
 	}
 
 
-	@ApiLog("重置密码")
+	@ApiLog("修改密码")
 	@PostMapping("/reset_password")
 	@ApiOperationSupport(order = 4)
-	@ApiOperation(value = "重置密码", notes = "账号:account,密码:password")
-	public R resetPassword(@ApiParam(value = "验证码", required = true) @RequestParam String code,
-						 @ApiParam(value = "账号", required = true) @RequestParam String username,
-						 @ApiParam(value = "密码", required = true) @RequestParam String password) {
+	@ApiOperation(value = "修改密码", notes = "账号:account,密码:password")
+	public R resetPassword(@ApiParam(value = "手机号", required = true) @RequestParam String username,
+						   @ApiParam(value = "密码", required = true) @RequestParam String password,
+						   @ApiParam(value = "验证码", required = true) @RequestParam(value = "captchaCode") String captchaCode,
+						   @ApiParam(value = "验证ID, 发送验证码返回的ID", required = true) @RequestParam(value = "captchaId") String captchaId) {
 		String tenantId = WebUtil.getRequest().getHeader(TokenUtil.TENANT_HEADER_KEY);
+		if (!PhoneUtil.isPhone(username)){
+			return R.fail("请输入正确的手机号!");
+		}
+		if (StringUtil.isEmpty(captchaCode) ||StringUtil.isEmpty(captchaId)){
+			return R.fail("请输入手机验证码!");
+		}
 		User user = userService.userByAccount(tenantId, username);
-		boolean flg = userService.resetPassword(user.getId(), password);
+		if (user == null){
+			return R.fail("该手机号为注册!");
+		}
+		boolean flg = captchaCode(username, captchaId,captchaCode);
+		if (!flg){
+			return R.fail(VALIDATE_FAIL);
+		}
+		User updateUser = new User();
+		updateUser.setId(user.getId());
+		updateUser.setPassword(DigestUtil.encrypt(password));
+		flg = userService.updateById(updateUser);
+		if (!flg){
+			return R.fail("操作失败");
+		}
 		CacheUtil.clear(USER_CACHE);
-		return R.status(flg);
+		return R.success("操作成功");
 	}
 
+	@GetMapping("/logout")
+	@ApiOperation(value = "退出登录")
+	@ApiOperationSupport(order = 5)
+	public R logout() {
+		BladeUser user = AuthUtil.getUser();
+		if (user != null && jwtProperties.getState()) {
+			String token = JwtUtil.getToken(WebUtil.getRequest().getHeader(TokenConstant.HEADER));
+			JwtUtil.removeAccessToken(user.getTenantId(), String.valueOf(user.getUserId()), token);
+		}
+		return R.success("退出成功");
+	}
 
+	private boolean captchaCode(String phone, String captchaId, String captchaCode){
+		String key = "blade:sms::captcha:" + phone + ":" + captchaId;
+		String cache = bladeRedis.get(key);
+		if (captchaCode.equals(cache)){
+			return true;
+		}
+		return false;
+	}
 
 }

+ 6 - 8
src/main/java/org/springblade/modules/api/controller/Api02Controller.java

@@ -26,6 +26,7 @@ import org.springblade.common.cache.ParamCache;
 import org.springblade.common.constant.CommonConstant;
 import org.springblade.core.boot.ctrl.BladeController;
 import org.springblade.core.tool.api.R;
+import org.springblade.core.tool.support.Kv;
 import org.springblade.core.tool.utils.DateUtil;
 import org.springblade.modules.api.response.IndexResponse;
 import org.springblade.modules.api.service.IApiService;
@@ -45,6 +46,7 @@ import org.springblade.modules.shopping.entity.Goods;
 import org.springblade.modules.shopping.entity.GoodsAttributes;
 import org.springblade.modules.shopping.entity.GoodsSpecs;
 import org.springblade.modules.shopping.service.*;
+import org.springblade.modules.shopping.vo.ConsignVO;
 import org.springblade.modules.shopping.vo.GoodsAttributesVO;
 import org.springblade.modules.shopping.vo.GoodsVO;
 import org.springblade.modules.shopping.vo.SpecCatsVO;
@@ -106,15 +108,11 @@ public class Api02Controller extends BladeController {
 				.orderByAsc(Goods::getSort)
 			.last(" limit 6"));
 		response.setGoodsTicket(list);
-		int consignLimit = Integer.parseInt(ParamCache.getValue(CommonConstant.DEFAULT_CONSIGN_LIMIT));
-		List<Consign> consignList = consignService.list(Wrappers.<Consign>lambdaQuery()
-			.eq(Consign::getIsSale, 2) //上架
-			.eq(Consign::getIsDelivery, 1) //未交割
-			.lt(Consign::getStartTime, DateUtil.now()) //开始时间小于当前时间
-			.last(" limit " + consignLimit) );
-		String startTime = consignConfigService.selectCacheConsignConfig();
+		Kv kv = consignConfigService.selectCacheConsignConfig();
+		List<ConsignVO> consignList = consignService.selectConsignList(kv.getLong("id"));
 		response.setConsigns(consignList);
-		response.setTime(startTime);
+		response.setStartTime(kv.getStr("startTime"));
+		response.setEndTime(kv.getStr("endTime"));
 		return R.data(response);
 	}
 

+ 8 - 1
src/main/java/org/springblade/modules/api/controller/Api03Controller.java

@@ -87,7 +87,7 @@ public class Api03Controller extends BladeController {
 
 	@GetMapping("/consign-page")
 	@ApiOperationSupport(order = 1)
-	@ApiOperation(value = "抢购专区", notes = "传入consign")
+	@ApiOperation(value = "抢购专区-查询所有数据", notes = "传入consign")
 	public R<List<ConsignVO>> ConsignPage(@ApiParam(value = "场次开始时间", required = true) @RequestParam String time,
 										  Query query) {
 		Consign consign = new Consign();
@@ -102,6 +102,13 @@ public class Api03Controller extends BladeController {
 		return R.data(ConsignWrapper.build().listVO(pages.getRecords()));
 	}
 
+	@GetMapping("/consign-list")
+	@ApiOperationSupport(order = 1)
+	@ApiOperation(value = "抢购专区-展示两条数据", notes = "传入consign")
+	public R<List<ConsignVO>> ConsignList(@ApiParam(value = "场次ID", required = true) @RequestParam Long id) {
+		return R.data(consignService.selectConsignList(id));
+	}
+
 	@GetMapping("/consign-detailById")
 	@ApiOperationSupport(order = 10)
 	@ApiOperation(value = "浏览商品", notes = "传入consign主键ID")

+ 1 - 1
src/main/java/org/springblade/modules/api/controller/Api04Controller.java

@@ -95,7 +95,7 @@ public class Api04Controller extends BladeController {
 
 	@PostMapping("/user-updateById")
 	@ApiOperationSupport(order = 2)
-	@ApiOperation(value = "修改昵称和头像", notes = "传入用户ID")
+	@ApiOperation(value = "修改用户资料", notes = "传入用户ID")
 	public R userUpdateById(@Valid @RequestBody UserAppUpdateRequest request) {
 		User user = new User();
 		user.setId(request.getUserId());

+ 8 - 13
src/main/java/org/springblade/modules/api/controller/Api05Controller.java

@@ -16,6 +16,7 @@
  */
 package org.springblade.modules.api.controller;
 
+import com.alipay.api.AlipayClient;
 import com.baomidou.mybatisplus.core.metadata.IPage;
 import com.github.xiaoymin.knife4j.annotations.ApiOperationSupport;
 import io.swagger.annotations.Api;
@@ -26,12 +27,11 @@ import org.springblade.common.constant.CommonConstant;
 import org.springblade.core.boot.ctrl.BladeController;
 import org.springblade.core.mp.support.Condition;
 import org.springblade.core.mp.support.Query;
-import org.springblade.core.redis.cache.BladeRedis;
 import org.springblade.core.tool.api.R;
 import org.springblade.core.tool.utils.StringUtil;
 import org.springblade.core.tool.utils.WebUtil;
 import org.springblade.modules.api.request.OrderCommonSaveRequest;
-import org.springblade.modules.api.request.OrderConsignSaveRequest;
+import org.springblade.modules.api.request.OrderConsignRandomRequest;
 import org.springblade.modules.api.request.OrderTakeRequest;
 import org.springblade.modules.auth.utils.TokenUtil;
 import org.springblade.modules.finance.entity.Order;
@@ -42,6 +42,7 @@ import org.springblade.modules.shopping.entity.Consign;
 import org.springblade.modules.shopping.service.IConsignService;
 import org.springblade.modules.shopping.vo.ConsignVO;
 import org.springblade.modules.shopping.wrapper.ConsignWrapper;
+import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.web.bind.annotation.*;
 
 import javax.validation.Valid;
@@ -61,6 +62,8 @@ public class Api05Controller extends BladeController {
 
 	private final IOrderService orderService;
 	private final IConsignService consignService;
+	@Autowired
+	private AlipayClient client;//支付宝请求sdk客户端
 
 	@PostMapping("/finance/order-commonSave")
 	@ApiOperationSupport(order = 1)
@@ -79,18 +82,11 @@ public class Api05Controller extends BladeController {
 		return R.data(orderService.commonOrderInsert(request, tenantId));
 	}
 
-	@PostMapping("/finance/order-consignSave")
+	@PostMapping("/finance/order-consignRandom")
 	@ApiOperationSupport(order = 2)
-	@ApiOperation(value = "立即抢购、再来一单", notes = "生成寄售订单, 传入用户ID")
-	public R consignSave(@Valid @RequestBody OrderConsignSaveRequest request) {
+	@ApiOperation(value = "寄售抢购", notes = "抢购订单")
+	public R consignRandom(@Valid @RequestBody OrderConsignRandomRequest request) {
 		String tenantId = WebUtil.getRequest().getHeader(TokenUtil.TENANT_HEADER_KEY);
-		if(StringUtil.isEmpty(request.getUserId()) || StringUtil.isEmpty(request.getConsignId())
-			|| StringUtil.isEmpty(request.getGoodsId())){
-			return R.fail("请求参数错误!");
-		}
-		if(request.getPayFee() > 0){
-			return R.fail("请求参数错误!");
-		}
 		return R.data(orderService.consignOrderInsert(request, tenantId));
 	}
 
@@ -156,5 +152,4 @@ public class Api05Controller extends BladeController {
 		return R.status(orderService.orderEnd(orderId,userId));
 	}
 
-
 }

+ 4 - 29
src/main/java/org/springblade/modules/api/controller/Api06Controller.java

@@ -23,7 +23,6 @@ import io.swagger.annotations.Api;
 import io.swagger.annotations.ApiOperation;
 import io.swagger.annotations.ApiParam;
 import lombok.AllArgsConstructor;
-import org.springblade.common.cache.ParamCache;
 import org.springblade.common.constant.CacheBizConstant;
 import org.springblade.common.constant.CommonConstant;
 import org.springblade.core.boot.ctrl.BladeController;
@@ -31,21 +30,17 @@ import org.springblade.core.mp.support.Condition;
 import org.springblade.core.mp.support.Query;
 import org.springblade.core.redis.cache.BladeRedis;
 import org.springblade.core.tool.api.R;
-import org.springblade.core.tool.support.Kv;
-import org.springblade.core.tool.utils.DateUtil;
 import org.springblade.core.tool.utils.StringUtil;
 import org.springblade.modules.desk.entity.Notice;
 import org.springblade.modules.desk.service.INoticeService;
 import org.springblade.modules.desk.vo.NoticeVO;
 import org.springblade.modules.desk.wrapper.NoticeWrapper;
-import org.springblade.modules.platform.service.IAdsService;
-import org.springblade.modules.platform.service.IFreightService;
-import org.springblade.modules.platform.service.IUserAddressService;
-import org.springblade.modules.platform.service.IUserBrowseService;
 import org.springblade.modules.shopping.entity.Brands;
-import org.springblade.modules.shopping.entity.Consign;
 import org.springblade.modules.shopping.entity.Goods;
-import org.springblade.modules.shopping.service.*;
+import org.springblade.modules.shopping.service.IBrandsService;
+import org.springblade.modules.shopping.service.IConsignConfigService;
+import org.springblade.modules.shopping.service.IConsignService;
+import org.springblade.modules.shopping.service.IGoodsService;
 import org.springblade.modules.system.service.IRegionService;
 import org.springframework.web.bind.annotation.GetMapping;
 import org.springframework.web.bind.annotation.RequestMapping;
@@ -67,10 +62,8 @@ import java.util.List;
 public class Api06Controller extends BladeController {
 
 	private final IGoodsService goodsService;
-	private final IConsignConfigService consignConfigService;
 	private final IBrandsService brandsService;
 	private final INoticeService noticeService;
-	private final IConsignService consignService;
 	public static IRegionService regionService;
 	private final BladeRedis bladeRedis;
 
@@ -145,22 +138,4 @@ public class Api06Controller extends BladeController {
 			.orderByDesc(Notice::getUpdateTime));
 		return R.data(NoticeWrapper.build().listVO(list));
 	}
-
-	@GetMapping("/consign-list")
-	@ApiOperationSupport(order = 4)
-	@ApiOperation(value = "首页抢购专区", notes = "传入consign")
-	public R consignList() {
-		Kv kv = Kv.create();
-		int limit = Integer.parseInt(ParamCache.getValue(CommonConstant.DEFAULT_CONSIGN_LIMIT));
-		List<Consign> list = consignService.list(Wrappers.<Consign>lambdaQuery()
-			.eq(Consign::getIsSale, 2) //上架
-			.eq(Consign::getIsDelivery, 1) //未交割
-			.lt(Consign::getStartTime, DateUtil.now()) //开始时间小于当前时间
-			.last(" limit " + limit) );
-		String startTime = consignConfigService.selectCacheConsignConfig();
-		kv.set("time", startTime);//下一场时间
-		kv.set("data", list);
-		return R.data(kv);
-	}
-
 }

+ 8 - 0
src/main/java/org/springblade/modules/api/controller/Api07Controller.java

@@ -24,20 +24,28 @@ import lombok.SneakyThrows;
 import org.springblade.common.constant.CommonConstant;
 import org.springblade.core.boot.ctrl.BladeController;
 import org.springblade.core.oss.model.BladeFile;
+import org.springblade.core.sms.model.SmsCode;
+import org.springblade.core.sms.model.SmsData;
 import org.springblade.core.tenant.annotation.NonDS;
 import org.springblade.core.tool.api.R;
 import org.springblade.core.tool.utils.FileUtil;
 import org.springblade.core.tool.utils.WebUtil;
 import org.springblade.modules.auth.utils.TokenUtil;
 import org.springblade.modules.resource.builder.oss.OssBuilder;
+import org.springblade.modules.resource.builder.sms.SmsBuilder;
 import org.springblade.modules.resource.entity.Attach;
 import org.springblade.modules.resource.service.IAttachService;
+import org.springblade.modules.resource.utils.SmsUtil;
 import org.springframework.web.bind.annotation.PostMapping;
 import org.springframework.web.bind.annotation.RequestMapping;
 import org.springframework.web.bind.annotation.RequestParam;
 import org.springframework.web.bind.annotation.RestController;
 import org.springframework.web.multipart.MultipartFile;
 
+import java.util.Map;
+
+import static org.springblade.modules.resource.utils.SmsUtil.*;
+
 /**
  * 控制器
  *

+ 19 - 5
src/main/java/org/springblade/modules/api/controller/Api08Controller.java

@@ -21,25 +21,30 @@ import io.swagger.annotations.Api;
 import io.swagger.annotations.ApiOperation;
 import io.swagger.annotations.ApiParam;
 import lombok.AllArgsConstructor;
+import lombok.SneakyThrows;
 import org.springblade.common.cache.ParamCache;
 import org.springblade.common.constant.CacheBizConstant;
 import org.springblade.common.constant.CommonConstant;
 import org.springblade.core.boot.ctrl.BladeController;
 import org.springblade.core.mp.support.Condition;
 import org.springblade.core.redis.cache.BladeRedis;
+import org.springblade.core.sms.model.SmsCode;
+import org.springblade.core.sms.model.SmsData;
 import org.springblade.core.tool.api.R;
 import org.springblade.modules.platform.entity.Ads;
 import org.springblade.modules.platform.entity.Payments;
 import org.springblade.modules.platform.service.IAdsService;
 import org.springblade.modules.platform.service.IPaymentsService;
-import org.springframework.web.bind.annotation.GetMapping;
-import org.springframework.web.bind.annotation.RequestMapping;
-import org.springframework.web.bind.annotation.RequestParam;
-import org.springframework.web.bind.annotation.RestController;
+import org.springblade.modules.resource.builder.sms.SmsBuilder;
+import org.springblade.modules.resource.utils.SmsUtil;
+import org.springframework.web.bind.annotation.*;
 
 import java.util.List;
+import java.util.Map;
 import java.util.Objects;
 
+import static org.springblade.modules.resource.utils.SmsUtil.*;
+
 /**
  * 控制器
  *
@@ -54,7 +59,7 @@ public class Api08Controller extends BladeController {
 
 	private final IPaymentsService paymentsService;
 	private final IAdsService adsService;
-
+	private final SmsBuilder smsBuilder;
 	private final BladeRedis bladeRedis;
 
 	@GetMapping("/payments-list")
@@ -83,4 +88,13 @@ public class Api08Controller extends BladeController {
 		return R.data(adsService.selectAdsList(type, limit));
 	}
 
+	@SneakyThrows
+	@PostMapping("/common/send-validate")
+	@ApiOperation(value = "短信发送", notes = "传入手机号")
+	public R sendValidate(@RequestParam String phone) {
+		Map<String, String> params = SmsUtil.getValidateParams();
+		SmsCode smsCode = smsBuilder.template().sendValidate(new SmsData(params).setKey(PARAM_KEY), phone);
+		return smsCode.isSuccess() ? R.data(smsCode, SEND_SUCCESS) : R.fail(SEND_FAIL);
+	}
+
 }

+ 11 - 12
src/main/java/org/springblade/modules/api/controller/WxPayV3Controller.java

@@ -59,7 +59,7 @@ import java.util.*;
  */
 @RestController
 @RequestMapping(CommonConstant.API_URL + "/wxPay/v3")
-@Api(value = "微信支付接口v3", tags = "97.微信支付v3")
+@Api(value = "微信支付接口v3", tags = "98.微信支付v3")
 @EnableAsync
 public class WxPayV3Controller {
 	private final static int OK = 200;
@@ -108,17 +108,16 @@ public class WxPayV3Controller {
 			// 获取证书序列号
 			X509Certificate certificate = PayKit.getCertificate(FileUtil.getInputStream(wxPayV3Bean.getCertPath()));
 			serialNo = certificate.getSerialNumber().toString(16).toUpperCase();
-
-//            System.out.println("输出证书信息:\n" + certificate.toString());
-//            // 输出关键信息,截取部分并进行标记
-//            System.out.println("证书序列号:" + certificate.getSerialNumber().toString(16));
-//            System.out.println("版本号:" + certificate.getVersion());
-//            System.out.println("签发者:" + certificate.getIssuerDN());
-//            System.out.println("有效起始日期:" + certificate.getNotBefore());
-//            System.out.println("有效终止日期:" + certificate.getNotAfter());
-//            System.out.println("主体名:" + certificate.getSubjectDN());
-//            System.out.println("签名算法:" + certificate.getSigAlgName());
-//            System.out.println("签名:" + certificate.getSignature().toString());
+            System.out.println("输出证书信息:" + certificate.toString());
+            // 输出关键信息,截取部分并进行标记
+            System.out.println("证书序列号:" + certificate.getSerialNumber().toString(16));
+            System.out.println("版本号:" + certificate.getVersion());
+            System.out.println("签发者:" + certificate.getIssuerDN());
+            System.out.println("有效起始日期:" + certificate.getNotBefore());
+            System.out.println("有效终止日期:" + certificate.getNotAfter());
+            System.out.println("主体名:" + certificate.getSubjectDN());
+            System.out.println("签名算法:" + certificate.getSigAlgName());
+            System.out.println("签名:" + certificate.getSignature().toString());
 		}
 		System.out.println("serialNo:" + serialNo);
 		return serialNo;

+ 70 - 0
src/main/java/org/springblade/modules/api/request/OrderConsignRandomRequest.java

@@ -0,0 +1,70 @@
+/*
+ *      Copyright (c) 2018-2028, Chill Zhuang All rights reserved.
+ *
+ *  Redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions are met:
+ *
+ *  Redistributions of source code must retain the above copyright notice,
+ *  this list of conditions and the following disclaimer.
+ *  Redistributions in binary form must reproduce the above copyright
+ *  notice, this list of conditions and the following disclaimer in the
+ *  documentation and/or other materials provided with the distribution.
+ *  Neither the name of the dreamlu.net developer nor the names of its
+ *  contributors may be used to endorse or promote products derived from
+ *  this software without specific prior written permission.
+ *  Author: Chill 庄骞 (smallchill@163.com)
+ */
+package org.springblade.modules.api.request;
+
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+
+import javax.validation.constraints.Max;
+import javax.validation.constraints.Min;
+import javax.validation.constraints.NotBlank;
+import javax.validation.constraints.NotNull;
+import java.io.Serializable;
+
+/**
+ * 请求实体类
+ *
+ * @author BladeX
+ * @since 2022-02-13
+ */
+@Data
+@ApiModel(value = "新增寄售订单实体对象", description = "请求实体类")
+public class OrderConsignRandomRequest implements Serializable {
+
+	private static final long serialVersionUID = 1L;
+
+	@NotNull(message = "缺少请求参数错误!")
+	@ApiModelProperty(value = "用户ID")
+	private Long userId;
+
+	@NotNull(message = "缺少请求参数错误!")
+	@ApiModelProperty(value = "寄售商品ID")
+	private Long consignId;
+
+	@NotNull(message = "缺少请求参数错误!")
+	@ApiModelProperty(value = "批次ID")
+	private Long consignConfigId;
+
+	@NotBlank(message = "请输入手机号")
+	@ApiModelProperty(value = "手机号")
+	private String telPhone;
+
+	@Min(value = 1)
+	@Max(value = 2)
+	@ApiModelProperty(value = "寄售方式,1提货,2寄售")
+	private Integer consignType;
+
+	@NotBlank(message = "请输入收货地址")
+	@ApiModelProperty(value = "收货地址")
+	private String userAddress;
+
+	@NotBlank(message = "请输入收货人")
+	@ApiModelProperty(value = "收货人")
+	private String receivingName;
+
+}

+ 43 - 0
src/main/java/org/springblade/modules/api/response/ConsignResponse.java

@@ -0,0 +1,43 @@
+/*
+ *      Copyright (c) 2018-2028, Chill Zhuang All rights reserved.
+ *
+ *  Redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions are met:
+ *
+ *  Redistributions of source code must retain the above copyright notice,
+ *  this list of conditions and the following disclaimer.
+ *  Redistributions in binary form must reproduce the above copyright
+ *  notice, this list of conditions and the following disclaimer in the
+ *  documentation and/or other materials provided with the distribution.
+ *  Neither the name of the dreamlu.net developer nor the names of its
+ *  contributors may be used to endorse or promote products derived from
+ *  this software without specific prior written permission.
+ *  Author: Chill 庄骞 (smallchill@163.com)
+ */
+package org.springblade.modules.api.response;
+
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+
+import java.io.Serializable;
+
+/**
+ * 视图实体类
+ *
+ * @author Chill
+ */
+@Data
+@ApiModel(value = "ConsignResponse对象", description = "实体类")
+public class ConsignResponse implements Serializable {
+	private static final long serialVersionUID = 1L;
+
+	@ApiModelProperty(value = "订单号")
+	private String outTradeNo;
+
+	@ApiModelProperty(value = "剩余次数")
+	private Integer num;
+
+	@ApiModelProperty(value = "状态")
+	private Integer state;
+}

+ 6 - 3
src/main/java/org/springblade/modules/api/response/IndexResponse.java

@@ -48,10 +48,13 @@ public class IndexResponse implements Serializable {
 	@ApiModelProperty(value = "酒票专区")
 	private List<Goods> goodsTicket;
 
-	@ApiModelProperty(value = "抢购时间")
-	private String time;
+	@ApiModelProperty(value = "开始时间")
+	private String startTime;
+
+	@ApiModelProperty(value = "结束时间")
+	private String endTime;
 
 	@ApiModelProperty(value = "抢购商品")
-	private List<Consign> consigns;
+	private List<ConsignVO> consigns;
 
 }

+ 120 - 0
src/main/java/org/springblade/modules/auth/granter/PhoneTokenGranter.java

@@ -0,0 +1,120 @@
+/*
+ *      Copyright (c) 2018-2028, Chill Zhuang All rights reserved.
+ *
+ *  Redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions are met:
+ *
+ *  Redistributions of source code must retain the above copyright notice,
+ *  this list of conditions and the following disclaimer.
+ *  Redistributions in binary form must reproduce the above copyright
+ *  notice, this list of conditions and the following disclaimer in the
+ *  documentation and/or other materials provided with the distribution.
+ *  Neither the name of the dreamlu.net developer nor the names of its
+ *  contributors may be used to endorse or promote products derived from
+ *  this software without specific prior written permission.
+ *  Author: Chill 庄骞 (smallchill@163.com)
+ */
+package org.springblade.modules.auth.granter;
+
+import lombok.AllArgsConstructor;
+import org.springblade.common.cache.CacheNames;
+import org.springblade.common.cache.ParamCache;
+import org.springblade.core.log.exception.ServiceException;
+import org.springblade.core.redis.cache.BladeRedis;
+import org.springblade.core.sms.model.SmsCode;
+import org.springblade.core.tool.utils.DigestUtil;
+import org.springblade.core.tool.utils.Func;
+import org.springblade.core.tool.utils.StringUtil;
+import org.springblade.core.tool.utils.WebUtil;
+import org.springblade.modules.auth.enums.UserEnum;
+import org.springblade.modules.auth.provider.ITokenGranter;
+import org.springblade.modules.auth.provider.TokenParameter;
+import org.springblade.modules.auth.utils.TokenUtil;
+import org.springblade.modules.resource.builder.sms.SmsBuilder;
+import org.springblade.modules.system.entity.Tenant;
+import org.springblade.modules.system.entity.User;
+import org.springblade.modules.system.entity.UserInfo;
+import org.springblade.modules.system.service.IRoleService;
+import org.springblade.modules.system.service.ITenantService;
+import org.springblade.modules.system.service.IUserService;
+import org.springframework.stereotype.Component;
+
+import javax.servlet.http.HttpServletRequest;
+import java.time.Duration;
+import java.util.List;
+
+import static org.springblade.modules.resource.utils.SmsUtil.VALIDATE_FAIL;
+
+/**
+ * 验证码TokenGranter
+ *
+ * @author Chill
+ */
+@Component
+@AllArgsConstructor
+public class PhoneTokenGranter implements ITokenGranter {
+
+	public static final String GRANT_TYPE = "phone";
+	public static final Integer FAIL_COUNT = 5;
+	public static final String FAIL_COUNT_VALUE = "account.failCount";
+
+	private final IUserService userService;
+	private final ITenantService tenantService;
+	private final BladeRedis bladeRedis;
+
+	@Override
+	public UserInfo grant(TokenParameter tokenParameter) {
+		// 获取验证码信息
+		String captchaId = tokenParameter.getArgs().getStr("captchaId");
+		String username = tokenParameter.getArgs().getStr("username");//手机号
+		String captchaCode = tokenParameter.getArgs().getStr("captchaCode");
+		String tenantId = tokenParameter.getArgs().getStr("tenantId");
+		// 获取验证码
+		String cache = bladeRedis.get(this.cacheKey(username, captchaId));
+		// 判断验证码
+		if (!captchaCode.equals(cache)) {
+			throw new ServiceException(VALIDATE_FAIL);
+		}
+		// 判断登录是否锁定
+		int cnt = Func.toInt(bladeRedis.get(CacheNames.tenantKey(tenantId, CacheNames.USER_FAIL_KEY, username)), 0);
+		int failCount = Func.toInt(ParamCache.getValue(FAIL_COUNT_VALUE), FAIL_COUNT);
+		if (cnt >= failCount) {
+			throw new ServiceException(TokenUtil.USER_HAS_TOO_MANY_FAILS);
+		}
+		User user = userService.userByAccount(tenantId, username);
+		if (user == null){
+			throw new ServiceException("手机号不存在");
+		}
+		String password = user.getPassword();
+		UserInfo userInfo = null;
+		if (Func.isNoneBlank(username, password)) {
+			// 获取租户信息
+			Tenant tenant = tenantService.getByTenantId(tenantId);
+			if (TokenUtil.judgeTenant(tenant)) {
+				throw new ServiceException(TokenUtil.USER_HAS_NO_TENANT_PERMISSION);
+			}
+			// 获取用户类型
+			String userType = tokenParameter.getArgs().getStr("userType");
+			// 根据不同用户类型调用对应的接口返回数据,用户可自行拓展
+			if (userType.equals(UserEnum.WEB.getName())) {
+				userInfo = userService.userInfo(tenantId, username, password, UserEnum.WEB);
+			} else if (userType.equals(UserEnum.APP.getName())) {
+				userInfo = userService.userInfo(tenantId, username, password, UserEnum.APP);
+			} else {
+				userInfo = userService.userInfo(tenantId, username, password, UserEnum.OTHER);
+			}
+		}
+		// 错误次数锁定
+		if (userInfo == null || userInfo.getUser() == null) {
+			bladeRedis.setEx(CacheNames.tenantKey(tenantId, CacheNames.USER_FAIL_KEY, username), cnt + 1, Duration.ofMinutes(30));
+		}
+		// 成功则清除登录错误次数
+		bladeRedis.del(CacheNames.tenantKey(tenantId, CacheNames.USER_FAIL_KEY, username));
+		return userInfo;
+	}
+
+	private String cacheKey(String phone, String id) {
+		return "blade:sms::captcha:" + phone + ":" + id;
+	}
+
+}

+ 2 - 4
src/main/java/org/springblade/modules/auth/provider/TokenGranterBuilder.java

@@ -20,10 +20,7 @@ import lombok.AllArgsConstructor;
 import org.springblade.core.secure.exception.SecureException;
 import org.springblade.core.tool.utils.Func;
 import org.springblade.core.tool.utils.SpringUtil;
-import org.springblade.modules.auth.granter.CaptchaTokenGranter;
-import org.springblade.modules.auth.granter.PasswordTokenGranter;
-import org.springblade.modules.auth.granter.RefreshTokenGranter;
-import org.springblade.modules.auth.granter.SocialTokenGranter;
+import org.springblade.modules.auth.granter.*;
 
 import java.util.Map;
 import java.util.concurrent.ConcurrentHashMap;
@@ -46,6 +43,7 @@ public class TokenGranterBuilder {
 		GRANTER_POOL.put(CaptchaTokenGranter.GRANT_TYPE, SpringUtil.getBean(CaptchaTokenGranter.class));
 		GRANTER_POOL.put(RefreshTokenGranter.GRANT_TYPE, SpringUtil.getBean(RefreshTokenGranter.class));
 		GRANTER_POOL.put(SocialTokenGranter.GRANT_TYPE, SpringUtil.getBean(SocialTokenGranter.class));
+		GRANTER_POOL.put(PhoneTokenGranter.GRANT_TYPE, SpringUtil.getBean(PhoneTokenGranter.class));
 	}
 
 	/**

+ 17 - 0
src/main/java/org/springblade/modules/finance/controller/AbstractAliPayApiController.java

@@ -0,0 +1,17 @@
+package org.springblade.modules.finance.controller;
+
+import com.alipay.api.AlipayApiException;
+import com.ijpay.alipay.AliPayApiConfig;
+
+/**
+ * @author Javen
+ */
+public abstract class AbstractAliPayApiController {
+	/**
+	 * 获取支付宝配置
+	 *
+	 * @return {@link AliPayApiConfig} 支付宝配置
+	 * @throws AlipayApiException 支付宝 Api 异常
+	 */
+	public abstract AliPayApiConfig getApiConfig() throws AlipayApiException;
+}

+ 110 - 0
src/main/java/org/springblade/modules/finance/pay/entity/AliPayBean.java

@@ -0,0 +1,110 @@
+package org.springblade.modules.finance.pay.entity;
+
+import org.springframework.boot.context.properties.ConfigurationProperties;
+import org.springframework.context.annotation.PropertySource;
+import org.springframework.stereotype.Component;
+
+/**
+ * <p>IJPay 让支付触手可及,封装了微信支付、支付宝支付、银联支付常用的支付方式以及各种常用的接口。</p>
+ *
+ * <p>不依赖任何第三方 mvc 框架,仅仅作为工具使用简单快速完成支付模块的开发,可轻松嵌入到任何系统里。 </p>
+ *
+ * <p>IJPay 交流群: 723992875</p>
+ *
+ * <p>Node.js 版: https://gitee.com/javen205/TNWX</p>
+ *
+ * <p>支付宝配置 Bean</p>
+ *
+ * @author Javen
+ */
+@Component
+@ConfigurationProperties(prefix = "alipay.ijpay")
+public class AliPayBean {
+	private String appId;
+	private String privateKey;
+	private String publicKey;
+	private String appCertPath;
+	private String aliPayCertPath;
+	private String aliPayRootCertPath;
+	private String serverUrl;
+	private String domain;
+
+	public String getAppId() {
+		return appId;
+	}
+
+	public void setAppId(String appId) {
+		this.appId = appId;
+	}
+
+	public String getPrivateKey() {
+		return privateKey;
+	}
+
+	public void setPrivateKey(String privateKey) {
+		this.privateKey = privateKey;
+	}
+
+	public String getPublicKey() {
+		return publicKey;
+	}
+
+	public void setPublicKey(String publicKey) {
+		this.publicKey = publicKey;
+	}
+
+	public String getAppCertPath() {
+		return appCertPath;
+	}
+
+	public void setAppCertPath(String appCertPath) {
+		this.appCertPath = appCertPath;
+	}
+
+	public String getAliPayCertPath() {
+		return aliPayCertPath;
+	}
+
+	public void setAliPayCertPath(String aliPayCertPath) {
+		this.aliPayCertPath = aliPayCertPath;
+	}
+
+	public String getAliPayRootCertPath() {
+		return aliPayRootCertPath;
+	}
+
+	public void setAliPayRootCertPath(String aliPayRootCertPath) {
+		this.aliPayRootCertPath = aliPayRootCertPath;
+	}
+
+	public String getServerUrl() {
+		return serverUrl;
+	}
+
+	public void setServerUrl(String serverUrl) {
+		this.serverUrl = serverUrl;
+	}
+
+
+	public String getDomain() {
+		return domain;
+	}
+
+	public void setDomain(String domain) {
+		this.domain = domain;
+	}
+
+	@Override
+	public String toString() {
+		return "AliPayBean{" +
+			"appId='" + appId + '\'' +
+			", privateKey='" + privateKey + '\'' +
+			", publicKey='" + publicKey + '\'' +
+			", appCertPath='" + appCertPath + '\'' +
+			", aliPayCertPath='" + aliPayCertPath + '\'' +
+			", aliPayRootCertPath='" + aliPayRootCertPath + '\'' +
+			", serverUrl='" + serverUrl + '\'' +
+			", domain='" + domain + '\'' +
+			'}';
+	}
+}

+ 135 - 0
src/main/java/org/springblade/modules/finance/pay/entity/AlipayProperties.java

@@ -0,0 +1,135 @@
+package org.springblade.modules.finance.pay.entity;
+
+import org.springframework.boot.context.properties.ConfigurationProperties;
+
+/**
+ * 支付宝支付配置
+ *
+ * @author guer
+ *
+ */
+@ConfigurationProperties("alipay.sdk")
+public class AlipayProperties {
+
+    /**
+     * 沙箱模式标志
+     */
+    private boolean dev;
+
+    /**
+     * 应用ID
+     */
+    private String appId;
+
+    /**
+     * 私钥
+     */
+    private String privateKey;
+
+    /**
+     * 支付宝公钥
+     */
+    private String alipayPublicKey;
+
+    /**
+     * 签名模式
+     */
+    private String signType;
+
+
+	/**
+     * 返回沙箱模式标志
+     *
+     * @return 沙箱模式标志
+     */
+    public boolean isDev() {
+        return dev;
+    }
+
+    /**
+     * 设置沙箱模式标志
+     *
+     * @param dev
+     *            沙箱模式标志
+     */
+    public void setDev(boolean dev) {
+        this.dev = dev;
+    }
+
+    /**
+     * 返回应用ID
+     *
+     * @return 应用ID
+     */
+    public String getAppId() {
+        return appId;
+    }
+
+    /**
+     * 设置应用ID
+     *
+     * @param appId
+     *            应用ID
+     */
+    public void setAppId(String appId) {
+        this.appId = appId;
+    }
+
+    /**
+     * 返回私钥
+     *
+     * @return 私钥
+     */
+    public String getPrivateKey() {
+        return privateKey;
+    }
+
+    /**
+     * 设置私钥
+     *
+     * @param privateKey
+     *            私钥
+     */
+    public void setPrivateKey(String privateKey) {
+        this.privateKey = privateKey;
+    }
+
+    /**
+     * 返回支付宝公钥
+     *
+     * @return 支付宝公钥
+     */
+    public String getAlipayPublicKey() {
+        return alipayPublicKey;
+    }
+
+    /**
+     * 设置支付宝公钥
+     *
+     * @param alipayPublicKey
+     *            支付宝公钥
+     */
+    public void setAlipayPublicKey(String alipayPublicKey) {
+        this.alipayPublicKey = alipayPublicKey;
+    }
+
+    /**
+     * 返回签名模式
+     *
+     * @return 签名模式
+     */
+    public String getSignType() {
+        return signType;
+    }
+
+    /**
+     * 设置签名模式
+     *
+     * @param signType
+     *            签名模式
+     */
+    public void setSignType(String signType) {
+        this.signType = signType;
+    }
+
+}

+ 42 - 0
src/main/java/org/springblade/modules/finance/pay/interceptor/AliPayInterceptor.java

@@ -0,0 +1,42 @@
+package org.springblade.modules.finance.pay.interceptor;
+
+import com.alipay.api.AlipayApiException;
+import com.ijpay.alipay.AliPayApiConfigKit;
+import org.springblade.modules.finance.controller.AbstractAliPayApiController;
+import org.springframework.stereotype.Component;
+import org.springframework.web.method.HandlerMethod;
+import org.springframework.web.servlet.HandlerInterceptor;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+/**
+ * <p>IJPay 让支付触手可及,封装了微信支付、支付宝支付、银联支付常用的支付方式以及各种常用的接口。</p>
+ *
+ * <p>不依赖任何第三方 mvc 框架,仅仅作为工具使用简单快速完成支付模块的开发,可轻松嵌入到任何系统里。 </p>
+ *
+ * <p>IJPay 交流群: 723992875</p>
+ *
+ * <p>Node.js 版: https://gitee.com/javen205/TNWX</p>
+ *
+ * <p>支付宝支付拦截器</p>
+ *
+ * @author Javen
+ */
+@Component
+public class AliPayInterceptor implements HandlerInterceptor {
+
+	@Override
+	public boolean preHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object handler) throws AlipayApiException {
+		if (HandlerMethod.class.equals(handler.getClass())) {
+			HandlerMethod method = (HandlerMethod) handler;
+			Object controller = method.getBean();
+			if (!(controller instanceof AbstractAliPayApiController)) {
+				throw new RuntimeException("控制器需要继承 AbstractAliPayApiController");
+			}
+			AliPayApiConfigKit.setThreadLocalAliPayApiConfig(((AbstractAliPayApiController) controller).getApiConfig());
+			return true;
+		}
+		return false;
+	}
+}

+ 11 - 1
src/main/java/org/springblade/modules/finance/service/IOrderService.java

@@ -17,7 +17,9 @@
 package org.springblade.modules.finance.service;
 
 import org.springblade.modules.api.request.OrderCommonSaveRequest;
+import org.springblade.modules.api.request.OrderConsignRandomRequest;
 import org.springblade.modules.api.request.OrderConsignSaveRequest;
+import org.springblade.modules.api.response.ConsignResponse;
 import org.springblade.modules.finance.entity.Order;
 import org.springblade.modules.api.request.OrderTakeRequest;
 import org.springblade.modules.finance.vo.OrderVO;
@@ -87,10 +89,18 @@ public interface IOrderService extends IService<Order> {
 
 	/**
 	 * 提货
-	 * 订单状态变为待
+	 * 订单状态变为待
 	 * @param request 用户ID
 	 * @return
 	 */
 	boolean consignSelfTake(OrderTakeRequest request);
 
+
+	/**
+	 * 寄售抢购
+	 * @param request 请求参数
+	 * @param tenantId 租户号
+	 * @return Response
+	 */
+	ConsignResponse consignOrderInsert(OrderConsignRandomRequest request, String tenantId);
 }

+ 160 - 25
src/main/java/org/springblade/modules/finance/service/impl/OrderServiceImpl.java

@@ -23,14 +23,12 @@ import org.springblade.common.constant.CommonConstant;
 import org.springblade.core.log.exception.ServiceException;
 import org.springblade.core.log.logger.BladeLogger;
 import org.springblade.core.tool.utils.DateUtil;
-import org.springblade.modules.api.request.OrderCommonSaveRequest;
-import org.springblade.modules.api.request.OrderConsignSaveRequest;
-import org.springblade.modules.api.request.OrderGoodsSaveRequest;
+import org.springblade.modules.api.request.*;
+import org.springblade.modules.api.response.ConsignResponse;
 import org.springblade.modules.finance.entity.Order;
 import org.springblade.modules.finance.entity.OrderConsign;
 import org.springblade.modules.finance.entity.OrderGoods;
 import org.springblade.modules.finance.mapper.OrderConsignMapper;
-import org.springblade.modules.api.request.OrderTakeRequest;
 import org.springblade.modules.finance.vo.OrderVO;
 import org.springblade.modules.finance.mapper.OrderMapper;
 import org.springblade.modules.finance.service.IOrderService;
@@ -138,33 +136,34 @@ public class OrderServiceImpl extends ServiceImpl<OrderMapper, Order> implements
 			if (goods.getGoodsStock() == 0){
 				throw new ServiceException("该商品库存不足!");
 			}
+			OrderGoods orderGoods = new OrderGoods();
+			orderGoods.setGoodsImg(goods.getGoodsImg());
+			Double goodsPrice = goods.getGoodsPrice();
+			Double ticketNum = goods.getTicketNum();
 			GoodsSpecs goodsSpecs = goodsSpecsMapper.selectById(item.getGoodsSpecIds());
-			if (goodsSpecs == null){
-				throw new ServiceException("订单生成失败");
-			}
-			//获取商品规格数据
-			SpecItems specItems = specItemsMapper.selectById(goodsSpecs.getSpecIds());
-			if (specItems == null){
-				throw new ServiceException("订单生成失败");
+			if (goodsSpecs != null){
+				//获取商品规格数据
+				orderGoods.setGoodsPrice(goodsSpecs.getSpecPrice());
+				goodsPrice = goodsSpecs.getSpecPrice();
+				ticketNum = goodsSpecs.getTicketNum();
+				SpecItems specItems = specItemsMapper.selectById(goodsSpecs.getSpecIds());
+				if (specItems != null){
+					orderGoods.setGoodsSpecNames(specItems.getItemName());
+					if(orderGoods.getGoodsImg() != null){
+						orderGoods.setGoodsImg(specItems.getItemImg());
+					}
+				}
 			}
-			OrderGoods orderGoods = new OrderGoods();
 			orderGoods.setOutTradeNo(outTradeNo);
 			orderGoods.setGoodsImg(goods.getGoodsImg());
 			orderGoods.setGoodsName(goods.getGoodsName());
 			orderGoods.setGoodsNum(item.getGoodsNum());
 			orderGoods.setGoodsSpecIds(item.getGoodsSpecIds());
-			orderGoods.setGoodsPrice(goodsSpecs.getSpecPrice());
-			orderGoods.setGoodsSpecNames(specItems.getItemName());
 			orderGoods.setTicketVal(goods.getTicketNum());
-			Double specPrice = NumberUtil.toDouble(NumberUtil.mul(goodsSpecs.getSpecPrice(), item.getGoodsNum()));
+			Double specPrice = NumberUtil.toDouble(NumberUtil.mul(goodsPrice, item.getGoodsNum()));
 			totalFee = NumberUtil.add(totalFee, specPrice);
-			Double specTicket = NumberUtil.toDouble(NumberUtil.mul(goodsSpecs.getTicketNum(), item.getGoodsNum()));
+			Double specTicket = NumberUtil.toDouble(NumberUtil.mul(ticketNum, item.getGoodsNum()));
 			totalTicket = NumberUtil.add(totalTicket, specTicket);
-			if(orderGoods.getGoodsImg() != null){
-				orderGoods.setGoodsImg(specItems.getItemImg());
-			}else{
-				orderGoods.setGoodsImg(goods.getGoodsImg());
-			}
 			boolean flg = orderGoods.insert();
 			if (!flg){
 				throw new ServiceException("操作失败!");
@@ -195,8 +194,7 @@ public class OrderServiceImpl extends ServiceImpl<OrderMapper, Order> implements
 			throw new ServiceException("您的信誉分不够!");
 		}
 		//已抢次数
-		int count = orderConsignMapper.selectCount(Wrappers.<OrderConsign>lambdaQuery()
-			.eq(OrderConsign::getPayUserId,request.getUserId()).last(" and to_days(create_time)= to_days(now())"));
+		int count = orderConsignMapper.selectCount(Wrappers.<OrderConsign>lambdaQuery().last(" where to_days(create_time)= to_days(now())"));
 		//可抢次数
 		float k = (float) (query.getCreditScore() / 100);
 		if(count >= k){
@@ -335,6 +333,128 @@ public class OrderServiceImpl extends ServiceImpl<OrderMapper, Order> implements
 		return false;
 	}
 
+	@Override
+	@Transactional(rollbackFor = Exception.class)
+	public ConsignResponse consignOrderInsert(OrderConsignRandomRequest request, String tenantId) {
+		ConsignResponse response = new ConsignResponse();
+		UserApp userApp = new UserApp();
+		UserApp query = userApp.selectOne(Wrappers.<UserApp>lambdaQuery().eq(UserApp::getUserId,request.getUserId()));
+		if (query == null){
+			throw new ServiceException("请重新登录!");
+		}
+		if (query.getState() != 1){
+			throw new ServiceException("登录账号已冻结!");
+		}
+		if (query.getCreditScore() < 100){
+			throw new ServiceException("您的信誉分不够!");
+		}
+		//是特殊账号的不判断的抢购次数
+		if (query.getIsAuth() != 2){
+			//已抢次数 (可抢订单数/日)
+			int count = orderConsignMapper.selectCount(Wrappers.<OrderConsign>lambdaQuery().last(" where to_days(create_time)= to_days(now())"));
+			//可抢次数
+			double k = (double)query.getCreditScore() / 100;
+			Integer num = NumberUtil.roundDown(k, 2).intValue() - (count + 1);
+			response.setNum(num);
+			if(count >= k){
+				throw new ServiceException("您抢购的次数已用完!");
+			}
+		}
+		//获取寄售商品数据
+		Consign consign = consignMapper.randomConsign(request.getConsignConfigId());
+		if (consign == null){
+			throw new ServiceException("亲,好物已抢完欢迎再来!");
+		}
+		//查询商品信息
+		Goods goods = goodsMapper.selectById(consign.getGoodsId());
+		if (goods == null){
+			throw new ServiceException("商品不存在!");
+		}
+		User user = userMapper.selectById(query.getUserId());
+		//生成订单号
+		String outTradeNo = PayKit.generateStr();
+		Order order = new Order();
+		order.setTenantId(tenantId);
+		if(user != null){
+			order.setUserName(user.getName());
+		}
+		order.setOutTradeNo(outTradeNo);
+		order.setUserId(query.getUserId());
+		order.setOrderType(3);//寄售订单
+		order.setPayFlag(1); //待付款
+		order.setPayFee(consign.getConsignPrice());
+		order.setUserAddress(request.getUserAddress());
+		order.setTelPhone(request.getTelPhone());
+		order.setDistributeMode(2);//默认物流配送
+		order.setDeliveryStaff("物流配送");
+		order.setReceivingName(request.getReceivingName());
+		int i = baseMapper.insert(order);
+		if (i == 1){
+			OrderGoods orderGoods = new OrderGoods();
+			orderGoods.setOutTradeNo(outTradeNo);
+			orderGoods.setGoodsImg(goods.getGoodsImg());
+			orderGoods.setGoodsName(goods.getGoodsName());
+			orderGoods.setGoodsNum(1);
+			boolean flg = orderGoods.insert();
+			if (!flg){
+				throw new ServiceException("操作失败!");
+			}
+			//添加寄售订单数据
+			OrderConsign orderConsign = new OrderConsign();
+			orderConsign.setTotalNum(1);//默认寄售数量为1
+			//判断来源为寄售
+			if(consign.getConsignFor() == 2){
+				//更新寄售状态
+				Consign updateConsign = new Consign();
+				updateConsign.setId(consign.getId());
+				updateConsign.setConsignState(2); //
+				updateConsign.setConsignType(request.getConsignType());//修改寄售类型(寄售方式)
+				updateConsign.setNowStock(0); //当前库存为0
+				int c =  consignMapper.updateById(updateConsign);
+				if (c != 1){
+					throw new ServiceException("操作失败!");
+				}
+			}else if(consign.getConsignFor() == 1){ //来源为后台
+				//减少库存数客户到达一定的数修改寄售状态为已寄售
+				Consign updateConsign = new Consign();
+				updateConsign.setId(consign.getId());
+				if (consign.getConsignType() == 2){
+					//寄售状态为已寄售
+					updateConsign.setConsignState(2); //待付款
+				}
+				updateConsign.setConsignType(request.getConsignType());
+				updateConsign.setNowStock(consign.getNowStock() - 1);
+				int c =  consignMapper.updateById(updateConsign);
+				if (c != 1){
+					throw new ServiceException("操作失败!");
+				}
+			}
+			orderConsign.setConsignId(consign.getId()); //寄售ID
+			orderConsign.setOutTradeNo(outTradeNo);
+			orderConsign.setGoodsId(consign.getGoodsId());
+			orderConsign.setGoodsName(goods.getGoodsName());
+			orderConsign.setConsignType(request.getConsignType());
+			orderConsign.setPayUserId(request.getUserId()); //支付人
+			if(request.getConsignType() == 1){
+				orderConsign.setConsignDays(0);
+			}else if(request.getConsignType() == 2){
+				orderConsign.setConsignDays(consign.getConsignDays() + 1);
+			}else{
+				throw new ServiceException("请求参数错误!");
+			}
+			orderConsign.setConsignUserId(consign.getConsignUserId());
+			orderConsign.setTotalPrice(consign.getConsignPrice());
+			orderConsign.setConsignPrice(consign.getConsignPrice());
+			int j = orderConsignMapper.insert(orderConsign);
+			if(j != 1){
+				throw new ServiceException("操作失败!");
+			}
+			response.setOutTradeNo(outTradeNo);
+			return response;
+		}
+		return response;
+	}
+
 	@Override
 	public boolean payCommonSuccess(String outTradeNo, String payCode) {
 		Order queryOrder = baseMapper.selectOne(Wrappers.<Order>lambdaQuery().eq(Order::getOutTradeNo, outTradeNo));
@@ -356,6 +476,8 @@ public class OrderServiceImpl extends ServiceImpl<OrderMapper, Order> implements
 			logger.error("订单异常", "寄售无数据!订单号:" + outTradeNo);
 			return false;
 		}
+		//更新订单
+		Order order = new Order();
 		//更新寄售状态为已售出
 		if(queryConsign.getNowStock() == 0){
 			Consign updateConsign = new Consign();
@@ -372,6 +494,7 @@ public class OrderServiceImpl extends ServiceImpl<OrderMapper, Order> implements
 			Consign consign = new Consign();
 			consign.setOrderId(queryOrder.getId()); //保存来源的订单ID
 			consign.setConsignFor(2);//寄售开源订单
+			consign.setConsignConfigId(queryConsign.getConsignConfigId());
 			consign.setConsignDays(query.getConsignDays());
 			consign.setConsignUserId(query.getPayUserId());//支付人变为寄售人
 			consign.setConsignType(0);//无
@@ -406,8 +529,6 @@ public class OrderServiceImpl extends ServiceImpl<OrderMapper, Order> implements
 				throw new ServiceException("订单变为寄售失败");
 			}
 		}
-		//更新订单
-		Order order = new Order();
 		order.setPayFlag(2);//待发货
 		order.setPayTime(DateUtil.now()); //支付时间
 		order.setPayCode(payCode); //支付方式
@@ -417,6 +538,20 @@ public class OrderServiceImpl extends ServiceImpl<OrderMapper, Order> implements
 			throw new ServiceException("订单回调失败!");
 		}
 		//更新用户数据
+		UserApp userApp = new UserApp();
+		UserApp queryUserApp = userApp.selectOne(Wrappers.<UserApp>lambdaQuery().eq(UserApp::getUserId,queryOrder.getUserId()));
+		if (queryUserApp == null){
+			logger.error("订单异常", "获取用户信息失败!订单号:" + outTradeNo);
+			throw new ServiceException("获取用户信息失败!");
+		}
+		userApp.setId(queryUserApp.getId());
+		Double ticket = NumberUtil.add(queryUserApp.getTicket(), queryOrder.getTotalTicket());
+		userApp.setTicket(ticket);
+		boolean flg = userApp.updateById();
+		if (!flg){
+			logger.error("订单异常", "更新用户信息失败!订单号:" + outTradeNo);
+			throw new ServiceException("更新用户信息失败!");
+		}
 		return true;
 	}
 

+ 8 - 3
src/main/java/org/springblade/modules/shopping/entity/Consign.java

@@ -55,12 +55,19 @@ public class Consign implements Serializable {
 	 */
 	@ApiModelProperty(value = "订单ID")
 	private Long orderId;
+
 	/**
 	 * 商品ID
 	 */
 	@ApiModelProperty(value = "商品ID")
 	private Long goodsId;
 
+	/**
+	 * 批次ID
+	 */
+	@ApiModelProperty(value = "批次ID")
+	private Long consignConfigId;
+
 	/**
 	 * 标题
 	 */
@@ -168,9 +175,7 @@ public class Consign implements Serializable {
 	@ApiModelProperty(value = "寄售来源")
 	private Integer consignFor;
 
-	/**
-	 * 删除标识
-	 */
+
 	@JsonIgnore
 	@TableLogic
 	@ApiModelProperty(value = "删除标识")

+ 7 - 0
src/main/java/org/springblade/modules/shopping/mapper/ConsignMapper.java

@@ -16,6 +16,7 @@
  */
 package org.springblade.modules.shopping.mapper;
 
+import org.apache.ibatis.annotations.Param;
 import org.springblade.modules.shopping.entity.Consign;
 import org.springblade.modules.shopping.vo.ConsignVO;
 import com.baomidou.mybatisplus.core.mapper.BaseMapper;
@@ -39,4 +40,10 @@ public interface ConsignMapper extends BaseMapper<Consign> {
 	 */
 	List<ConsignVO> selectConsignPage(IPage page, ConsignVO consign);
 
+	/**
+	 * 获取随机数
+	 * @param consignConfigId 批次ID
+	 * @return Consign
+	 */
+	Consign randomConsign(@Param("consignConfigId") Long consignConfigId);
 }

+ 16 - 0
src/main/java/org/springblade/modules/shopping/mapper/ConsignMapper.xml

@@ -22,4 +22,20 @@
         SELECT * FROM t_consign WHERE is_deleted = 0
     </select>
 
+    <select id="randomConsign" resultMap="consignResultMap">
+        SELECT
+        *
+        FROM
+        t_consign t
+        WHERE
+        consign_config_id = #{consignConfigId}
+        AND now_stock > 0
+        AND is_sale = 2
+        AND t.id >= (
+        RAND() * (SELECT max(id) FROM t_consign)
+        )
+        order by t.consign_for desc
+        LIMIT 1
+    </select>
+
 </mapper>

+ 2 - 1
src/main/java/org/springblade/modules/shopping/service/IConsignConfigService.java

@@ -16,6 +16,7 @@
  */
 package org.springblade.modules.shopping.service;
 
+import org.springblade.core.tool.support.Kv;
 import org.springblade.modules.shopping.entity.ConsignConfig;
 import org.springblade.modules.shopping.vo.ConsignConfigVO;
 import com.baomidou.mybatisplus.extension.service.IService;
@@ -50,6 +51,6 @@ public interface IConsignConfigService extends IService<ConsignConfig> {
 	 * 获取最新场次时间
 	 * @return List
 	 */
-	String selectCacheConsignConfig();
+	Kv selectCacheConsignConfig();
 
 }

+ 10 - 0
src/main/java/org/springblade/modules/shopping/service/IConsignService.java

@@ -21,6 +21,8 @@ import org.springblade.modules.shopping.vo.ConsignVO;
 import com.baomidou.mybatisplus.extension.service.IService;
 import com.baomidou.mybatisplus.core.metadata.IPage;
 
+import java.util.List;
+
 /**
  * 商品寄售表 服务类
  *
@@ -39,4 +41,12 @@ public interface IConsignService extends IService<Consign> {
 	IPage<ConsignVO> selectConsignPage(IPage<ConsignVO> page, ConsignVO consign);
 
 
+	/**
+	 * 抢购页面展示两条数据
+	 *
+	 * @param consignConfigId 场次ID
+	 * @return List
+	 */
+	List<ConsignVO> selectConsignList(Long consignConfigId);
+
 }

+ 19 - 5
src/main/java/org/springblade/modules/shopping/service/impl/ConsignConfigServiceImpl.java

@@ -20,6 +20,7 @@ import cn.hutool.core.date.DateTime;
 import com.baomidou.mybatisplus.core.toolkit.Wrappers;
 import org.springblade.common.constant.CacheBizConstant;
 import org.springblade.core.redis.cache.BladeRedis;
+import org.springblade.core.tool.support.Kv;
 import org.springblade.core.tool.utils.DateUtil;
 import org.springblade.modules.shopping.entity.ConsignConfig;
 import org.springblade.modules.shopping.vo.ConsignConfigVO;
@@ -63,21 +64,34 @@ public class ConsignConfigServiceImpl extends ServiceImpl<ConsignConfigMapper, C
 	}
 
 	@Override
-	public String selectCacheConsignConfig() {
+	public Kv selectCacheConsignConfig() {
+		Kv kv = Kv.create();
 		List<ConsignConfig> list = selectCacheList();
 		String todayYmd = DateUtil.format(DateUtil.now(), DateUtil.PATTERN_DATE);
 		for (ConsignConfig consignConfig : list) {
 			String hms = DateUtil.format(consignConfig.getStartTime(), DateUtil.PATTERN_TIME);
-			String time = todayYmd + " " + hms;
-			Date startDate = DateUtil.parse(time, DateUtil.PATTERN_DATETIME);
+			String startTime = todayYmd + " " + hms;
+			Date startDate = DateUtil.parse(startTime, DateUtil.PATTERN_DATETIME);
 			long seconds = DateUtil.between(DateUtil.now(), startDate).getSeconds();
 			if (seconds > 0) {
-				return time;
+				String endHms = DateUtil.format(consignConfig.getStartTime(), DateUtil.PATTERN_TIME);
+				String endTime = todayYmd + " " + endHms;
+				kv.set("startTime",startTime)
+					.set("endTime", endTime)
+					.set("id",consignConfig.getId());
+				return kv;
 			}
 		}
+		ConsignConfig consignConfig = list.get(0);
 		DateTime date = cn.hutool.core.date.DateUtil.tomorrow();
 		String nextYmd = DateUtil.format(date, DateUtil.PATTERN_DATE);
-		return nextYmd + " " + DateUtil.format(list.get(0).getStartTime(), DateUtil.PATTERN_TIME);
+		String startTime = nextYmd + " " + DateUtil.format(consignConfig.getStartTime(), DateUtil.PATTERN_TIME);
+		String endHms = DateUtil.format(consignConfig.getEndTime(), DateUtil.PATTERN_TIME);
+		String endTime = todayYmd + " " + endHms;
+		kv.set("startTime",startTime)
+			.set("endTime", endTime)
+			.set("id",list.get(0).getId());
+		return kv;
 	}
 
 }

+ 24 - 0
src/main/java/org/springblade/modules/shopping/service/impl/ConsignServiceImpl.java

@@ -16,14 +16,20 @@
  */
 package org.springblade.modules.shopping.service.impl;
 
+import com.baomidou.mybatisplus.core.toolkit.Wrappers;
+import org.springblade.core.mp.support.Condition;
+import org.springblade.core.tool.utils.DateUtil;
 import org.springblade.modules.shopping.entity.Consign;
 import org.springblade.modules.shopping.vo.ConsignVO;
 import org.springblade.modules.shopping.mapper.ConsignMapper;
 import org.springblade.modules.shopping.service.IConsignService;
 import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import org.springblade.modules.shopping.wrapper.ConsignWrapper;
 import org.springframework.stereotype.Service;
 import com.baomidou.mybatisplus.core.metadata.IPage;
 
+import java.util.List;
+
 /**
  * 商品寄售表 服务实现类
  *
@@ -38,4 +44,22 @@ public class ConsignServiceImpl extends ServiceImpl<ConsignMapper, Consign> impl
 		return page.setRecords(baseMapper.selectConsignPage(page, consign));
 	}
 
+	@Override
+	public List<ConsignVO> selectConsignList(Long consignConfigId) {
+		//String startTime = DateUtil.format(DateUtil.now(), DateUtil.PATTERN_DATETIME);
+		List<Consign> list = baseMapper.selectList(Wrappers.<Consign>lambdaQuery()
+			.eq(Consign::getIsSale,2)
+			.eq(Consign::getConsignFor,1)
+			.gt(Consign::getNowStock,0)
+			.eq(Consign::getConsignConfigId, consignConfigId)
+			//.last(" and to_days(start_time) = to_days(now())")
+		); //获取当前寄售的时间
+		if (list.size() > 0){
+			Consign consign = list.get(0);
+			consign.setConsignFor(2);
+			list.add(consign);
+		}
+		return ConsignWrapper.build().listVO(list);
+	}
+
 }

+ 1 - 0
src/main/java/org/springblade/modules/shopping/vo/ConsignVO.java

@@ -20,6 +20,7 @@ import io.swagger.annotations.ApiModel;
 import io.swagger.annotations.ApiModelProperty;
 import lombok.Data;
 import lombok.EqualsAndHashCode;
+import org.springblade.modules.finance.entity.OrderGoods;
 import org.springblade.modules.shopping.entity.Consign;
 
 import java.util.List;

+ 16 - 0
src/main/java/org/springblade/modules/shopping/wrapper/ConsignWrapper.java

@@ -16,6 +16,7 @@
  */
 package org.springblade.modules.shopping.wrapper;
 
+import com.baomidou.mybatisplus.core.toolkit.Wrappers;
 import org.springblade.common.cache.DictBizCache;
 import org.springblade.common.cache.DictCache;
 import org.springblade.common.enums.DictBizEnum;
@@ -23,15 +24,20 @@ import org.springblade.common.enums.DictEnum;
 import org.springblade.core.mp.support.BaseEntityWrapper;
 import org.springblade.core.tool.utils.BeanUtil;
 import org.springblade.core.tool.utils.SpringUtil;
+import org.springblade.modules.finance.entity.OrderGoods;
+import org.springblade.modules.finance.service.IOrderGoodsService;
 import org.springblade.modules.shopping.entity.Consign;
 import org.springblade.modules.shopping.entity.ConsignConfig;
 import org.springblade.modules.shopping.entity.Goods;
+import org.springblade.modules.shopping.entity.GoodsAttributes;
+import org.springblade.modules.shopping.service.IGoodsAttributesService;
 import org.springblade.modules.shopping.service.IGoodsService;
 import org.springblade.modules.shopping.vo.ConsignConfigVO;
 import org.springblade.modules.shopping.vo.ConsignVO;
 import org.springblade.modules.system.entity.User;
 import org.springblade.modules.system.service.IUserService;
 
+import java.util.List;
 import java.util.Objects;
 
 /**
@@ -46,10 +52,12 @@ public class ConsignWrapper extends BaseEntityWrapper<Consign, ConsignVO> {
 	}
 	public static IGoodsService goodsService;
 	public static IUserService userService;
+	public static IGoodsAttributesService goodsAttributesService;
 
 	static {
 		goodsService = SpringUtil.getBean(IGoodsService.class);
 		userService = SpringUtil.getBean(IUserService.class);
+		goodsAttributesService =  SpringUtil.getBean(IGoodsAttributesService.class);
 	}
 
 	@Override
@@ -63,6 +71,14 @@ public class ConsignWrapper extends BaseEntityWrapper<Consign, ConsignVO> {
 		User user = userService.getById(entity.getConsignUserId());
 		if (goods != null){
 			vo.setProductNo(goods.getProductNo());
+			List<GoodsAttributes> list = goodsAttributesService.list(Wrappers.<GoodsAttributes>lambdaQuery().eq(GoodsAttributes::getGoodsId, vo.getId()));
+			vo.setGoodsAttributes(GoodsAttributesWrapper.build().listVO(list));
+			//商品规格项和值
+			//vo.setSpecItems(apiService.specItemsList(vo.getId()));
+			vo.setGoodsImg(goods.getGoodsImg());
+			vo.setGallery(goods.getGallery());
+			vo.setGoodsLabel(goods.getGoodsLabel());
+			vo.setTextImg(goods.getTextImg());
 		}
 		if(user != null){
 			vo.setConsignUserIdDisplayName(user.getName());

+ 5 - 0
src/main/java/org/springblade/modules/system/entity/UserApp.java

@@ -101,6 +101,11 @@ public class UserApp extends Model<UserApp> {
 	@ApiModelProperty(value = "账号状态:1正常,2冻结,3删除")
 	private Integer state;
 
+	/**
+	 * 是否有特殊权限
+	 */
+	@ApiModelProperty(value = "是否有特殊权限")
+	private Integer isAuth;
 	/**
 	 * 简介说明
 	 */

+ 3 - 0
src/main/java/org/springblade/modules/system/vo/UserAppVO.java

@@ -63,6 +63,9 @@ public class UserAppVO extends UserApp {
 	@JsonIgnore
 	private String parentPath;
 
+	@JsonIgnore
+	private Integer isAuth;
+
 	@ApiModelProperty(value = "性别")
 	private String sexDisplayName;
 

+ 43 - 0
src/main/resources/alipay/alipayCertPublicKey_RSA2.crt

@@ -0,0 +1,43 @@
+-----BEGIN CERTIFICATE-----
+MIIDrDCCApSgAwIBAgIQICIDJWqWmjEZRIFyusWpMjANBgkqhkiG9w0BAQsFADCBgjELMAkGA1UE
+BhMCQ04xFjAUBgNVBAoMDUFudCBGaW5hbmNpYWwxIDAeBgNVBAsMF0NlcnRpZmljYXRpb24gQXV0
+aG9yaXR5MTkwNwYDVQQDDDBBbnQgRmluYW5jaWFsIENlcnRpZmljYXRpb24gQXV0aG9yaXR5IENs
+YXNzIDIgUjEwHhcNMjIwMzI1MTU0NTUwWhcNMjcwMzI0MTU0NTUwWjCBjDELMAkGA1UEBhMCQ04x
+JzAlBgNVBAoMHui0teW3nuS4reWuj+enkeaKgOaciemZkOWFrOWPuDEPMA0GA1UECwwGQWxpcGF5
+MUMwQQYDVQQDDDrmlK/ku5jlrp0o5Lit5Zu9Kee9kee7nOaKgOacr+aciemZkOWFrOWPuC0yMDg4
+MzQxOTY3NDQzNDcyMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAhIxPBQL0OKBc6fcU
+/9PdVTMA7L2s314oU2w1q06ywQSDdhF3RY1Bo0Eqh4Zg8QpPirFeyAc4rhFjyKZRlngQXrybcAhU
+fswD86QQGodObe3aA9bbWdXiTt10Q5CBk5GImadNiEW6Adh+0bY5ezf1RbxIjbGDfH6x5gatZnpj
+PswiHMQnskZtg9JSfE2u8WEKuSaH8yhnkllHpIHWnWvFvXwNVNycXdmDrEe7gIB1yCouNK6/DZ7I
+QH2AajSuvbxmCqO0MzywEfgvLqE0GFVsKKmXvgJebRAnW9RmGhmrxvEIceXCjR3tbxM9gX8lioDl
+qKnBootTgAbjIJ5VrPvKPwIDAQABoxIwEDAOBgNVHQ8BAf8EBAMCA/gwDQYJKoZIhvcNAQELBQAD
+ggEBACV8AVKuorSPk4DGN1gAEkBP2YKQnlFqO+34i+C2HW3QZT9MSemCCZonMPXM7ZxF3YyT9WLh
+qib2wvSu6h1Q9r8s9Yl+Y1epPWl3N9ePQIjcgPKlnpD8Uq5//vTarlXODqj1g4VQLRqzN9Nceyfd
+97BCw82HPvRgf2Jbmohq08bvtp5YloO/nLNrmkWMU2Obrm1IB/Wnqi92pJCO/GK19bvhLrGaDW2w
+MLLJnJFM5VVF7/IRi45BdIfEbheY1qydB8JUphjhRRheWxm2JF72CN6/MWxgIzVITHd0TyA4Z4vx
+hVb2CydtXWKngrzhvlyLNl8R7Vb14ixp74tISZichuU=
+-----END CERTIFICATE-----
+-----BEGIN CERTIFICATE-----
+MIIE4jCCAsqgAwIBAgIIYsSr5bKAMl8wDQYJKoZIhvcNAQELBQAwejELMAkGA1UEBhMCQ04xFjAU
+BgNVBAoMDUFudCBGaW5hbmNpYWwxIDAeBgNVBAsMF0NlcnRpZmljYXRpb24gQXV0aG9yaXR5MTEw
+LwYDVQQDDChBbnQgRmluYW5jaWFsIENlcnRpZmljYXRpb24gQXV0aG9yaXR5IFIxMB4XDTE4MDMy
+MjE0MzQxNVoXDTM3MTEyNjE0MzQxNVowgYIxCzAJBgNVBAYTAkNOMRYwFAYDVQQKDA1BbnQgRmlu
+YW5jaWFsMSAwHgYDVQQLDBdDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTE5MDcGA1UEAwwwQW50IEZp
+bmFuY2lhbCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eSBDbGFzcyAyIFIxMIIBIjANBgkqhkiG9w0B
+AQEFAAOCAQ8AMIIBCgKCAQEAsLMfYaoRoPRbmDcAfXPCmKf43pWRN5yTXa/KJWO0l+mrgQvs89bA
+NEvbDUxlkGwycwtwi5DgBuBgVhLliXu+R9CYgr2dXs8D8Hx/gsggDcyGPLmVrDOnL+dyeauheARZ
+fA3du60fwEwwbGcVIpIxPa/4n3IS/ElxQa6DNgqxh8J9Xwh7qMGl0JK9+bALuxf7B541Gr4p0WEN
+G8fhgjBV4w4ut9eQLOoa1eddOUSZcy46Z7allwowwgt7b5VFfx/P1iKJ3LzBMgkCK7GZ2kiLrL7R
+iqV+h482J7hkJD+ardoc6LnrHO/hIZymDxok+VH9fVeUdQa29IZKrIDVj65THQIDAQABo2MwYTAf
+BgNVHSMEGDAWgBRfdLQEwE8HWurlsdsio4dBspzhATAdBgNVHQ4EFgQUSqHkYINtUSAtDPnS8Xoy
+oP9p7qEwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwDQYJKoZIhvcNAQELBQADggIB
+AIQ8TzFy4bVIVb8+WhHKCkKNPcJe2EZuIcqvRoi727lZTJOfYy/JzLtckyZYfEI8J0lasZ29wkTt
+a1IjSo+a6XdhudU4ONVBrL70U8Kzntplw/6TBNbLFpp7taRALjUgbCOk4EoBMbeCL0GiYYsTS0mw
+7xdySzmGQku4GTyqutIGPQwKxSj9iSFw1FCZqr4VP4tyXzMUgc52SzagA6i7AyLedd3tbS6lnR5B
+L+W9Kx9hwT8L7WANAxQzv/jGldeuSLN8bsTxlOYlsdjmIGu/C9OWblPYGpjQQIRyvs4Cc/mNhrh+
+14EQgwuemIIFDLOgcD+iISoN8CqegelNcJndFw1PDN6LkVoiHz9p7jzsge8RKay/QW6C03KNDpWZ
+EUCgCUdfHfo8xKeR+LL1cfn24HKJmZt8L/aeRZwZ1jwePXFRVtiXELvgJuM/tJDIFj2KD337iV64
+fWcKQ/ydDVGqfDZAdcU4hQdsrPWENwPTQPfVPq2NNLMyIH9+WKx9Ed6/WzeZmIy5ZWpX1TtTolo6
+OJXQFeItMAjHxW/ZSZTok5IS3FuRhExturaInnzjYpx50a6kS34c5+c8hYq7sAtZ/CNLZmBnBCFD
+aMQqT8xFZJ5uolUaSeXxg7JFY1QsYp5RKvj4SjFwCGKJ2+hPPe9UyyltxOidNtxjaknOCeBHytOr
+-----END CERTIFICATE-----

+ 88 - 0
src/main/resources/alipay/alipayRootCert.crt

@@ -0,0 +1,88 @@
+-----BEGIN CERTIFICATE-----
+MIIBszCCAVegAwIBAgIIaeL+wBcKxnswDAYIKoEcz1UBg3UFADAuMQswCQYDVQQG
+EwJDTjEOMAwGA1UECgwFTlJDQUMxDzANBgNVBAMMBlJPT1RDQTAeFw0xMjA3MTQw
+MzExNTlaFw00MjA3MDcwMzExNTlaMC4xCzAJBgNVBAYTAkNOMQ4wDAYDVQQKDAVO
+UkNBQzEPMA0GA1UEAwwGUk9PVENBMFkwEwYHKoZIzj0CAQYIKoEcz1UBgi0DQgAE
+MPCca6pmgcchsTf2UnBeL9rtp4nw+itk1Kzrmbnqo05lUwkwlWK+4OIrtFdAqnRT
+V7Q9v1htkv42TsIutzd126NdMFswHwYDVR0jBBgwFoAUTDKxl9kzG8SmBcHG5Yti
+W/CXdlgwDAYDVR0TBAUwAwEB/zALBgNVHQ8EBAMCAQYwHQYDVR0OBBYEFEwysZfZ
+MxvEpgXBxuWLYlvwl3ZYMAwGCCqBHM9VAYN1BQADSAAwRQIgG1bSLeOXp3oB8H7b
+53W+CKOPl2PknmWEq/lMhtn25HkCIQDaHDgWxWFtnCrBjH16/W3Ezn7/U/Vjo5xI
+pDoiVhsLwg==
+-----END CERTIFICATE-----
+
+-----BEGIN CERTIFICATE-----
+MIIF0zCCA7ugAwIBAgIIH8+hjWpIDREwDQYJKoZIhvcNAQELBQAwejELMAkGA1UE
+BhMCQ04xFjAUBgNVBAoMDUFudCBGaW5hbmNpYWwxIDAeBgNVBAsMF0NlcnRpZmlj
+YXRpb24gQXV0aG9yaXR5MTEwLwYDVQQDDChBbnQgRmluYW5jaWFsIENlcnRpZmlj
+YXRpb24gQXV0aG9yaXR5IFIxMB4XDTE4MDMyMTEzNDg0MFoXDTM4MDIyODEzNDg0
+MFowejELMAkGA1UEBhMCQ04xFjAUBgNVBAoMDUFudCBGaW5hbmNpYWwxIDAeBgNV
+BAsMF0NlcnRpZmljYXRpb24gQXV0aG9yaXR5MTEwLwYDVQQDDChBbnQgRmluYW5j
+aWFsIENlcnRpZmljYXRpb24gQXV0aG9yaXR5IFIxMIICIjANBgkqhkiG9w0BAQEF
+AAOCAg8AMIICCgKCAgEAtytTRcBNuur5h8xuxnlKJetT65cHGemGi8oD+beHFPTk
+rUTlFt9Xn7fAVGo6QSsPb9uGLpUFGEdGmbsQ2q9cV4P89qkH04VzIPwT7AywJdt2
+xAvMs+MgHFJzOYfL1QkdOOVO7NwKxH8IvlQgFabWomWk2Ei9WfUyxFjVO1LVh0Bp
+dRBeWLMkdudx0tl3+21t1apnReFNQ5nfX29xeSxIhesaMHDZFViO/DXDNW2BcTs6
+vSWKyJ4YIIIzStumD8K1xMsoaZBMDxg4itjWFaKRgNuPiIn4kjDY3kC66Sl/6yTl
+YUz8AybbEsICZzssdZh7jcNb1VRfk79lgAprm/Ktl+mgrU1gaMGP1OE25JCbqli1
+Pbw/BpPynyP9+XulE+2mxFwTYhKAwpDIDKuYsFUXuo8t261pCovI1CXFzAQM2w7H
+DtA2nOXSW6q0jGDJ5+WauH+K8ZSvA6x4sFo4u0KNCx0ROTBpLif6GTngqo3sj+98
+SZiMNLFMQoQkjkdN5Q5g9N6CFZPVZ6QpO0JcIc7S1le/g9z5iBKnifrKxy0TQjtG
+PsDwc8ubPnRm/F82RReCoyNyx63indpgFfhN7+KxUIQ9cOwwTvemmor0A+ZQamRe
+9LMuiEfEaWUDK+6O0Gl8lO571uI5onYdN1VIgOmwFbe+D8TcuzVjIZ/zvHrAGUcC
+AwEAAaNdMFswCwYDVR0PBAQDAgEGMAwGA1UdEwQFMAMBAf8wHQYDVR0OBBYEFF90
+tATATwda6uWx2yKjh0GynOEBMB8GA1UdIwQYMBaAFF90tATATwda6uWx2yKjh0Gy
+nOEBMA0GCSqGSIb3DQEBCwUAA4ICAQCVYaOtqOLIpsrEikE5lb+UARNSFJg6tpkf
+tJ2U8QF/DejemEHx5IClQu6ajxjtu0Aie4/3UnIXop8nH/Q57l+Wyt9T7N2WPiNq
+JSlYKYbJpPF8LXbuKYG3BTFTdOVFIeRe2NUyYh/xs6bXGr4WKTXb3qBmzR02FSy3
+IODQw5Q6zpXj8prYqFHYsOvGCEc1CwJaSaYwRhTkFedJUxiyhyB5GQwoFfExCVHW
+05ZFCAVYFldCJvUzfzrWubN6wX0DD2dwultgmldOn/W/n8at52mpPNvIdbZb2F41
+T0YZeoWnCJrYXjq/32oc1cmifIHqySnyMnavi75DxPCdZsCOpSAT4j4lAQRGsfgI
+kkLPGQieMfNNkMCKh7qjwdXAVtdqhf0RVtFILH3OyEodlk1HYXqX5iE5wlaKzDop
+PKwf2Q3BErq1xChYGGVS+dEvyXc/2nIBlt7uLWKp4XFjqekKbaGaLJdjYP5b2s7N
+1dM0MXQ/f8XoXKBkJNzEiM3hfsU6DOREgMc1DIsFKxfuMwX3EkVQM1If8ghb6x5Y
+jXayv+NLbidOSzk4vl5QwngO/JYFMkoc6i9LNwEaEtR9PhnrdubxmrtM+RjfBm02
+77q3dSWFESFQ4QxYWew4pHE0DpWbWy/iMIKQ6UZ5RLvB8GEcgt8ON7BBJeMc+Dyi
+kT9qhqn+lw==
+-----END CERTIFICATE-----
+
+-----BEGIN CERTIFICATE-----
+MIICiDCCAgygAwIBAgIIQX76UsB/30owDAYIKoZIzj0EAwMFADB6MQswCQYDVQQG
+EwJDTjEWMBQGA1UECgwNQW50IEZpbmFuY2lhbDEgMB4GA1UECwwXQ2VydGlmaWNh
+dGlvbiBBdXRob3JpdHkxMTAvBgNVBAMMKEFudCBGaW5hbmNpYWwgQ2VydGlmaWNh
+dGlvbiBBdXRob3JpdHkgRTEwHhcNMTkwNDI4MTYyMDQ0WhcNNDkwNDIwMTYyMDQ0
+WjB6MQswCQYDVQQGEwJDTjEWMBQGA1UECgwNQW50IEZpbmFuY2lhbDEgMB4GA1UE
+CwwXQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkxMTAvBgNVBAMMKEFudCBGaW5hbmNp
+YWwgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkgRTEwdjAQBgcqhkjOPQIBBgUrgQQA
+IgNiAASCCRa94QI0vR5Up9Yr9HEupz6hSoyjySYqo7v837KnmjveUIUNiuC9pWAU
+WP3jwLX3HkzeiNdeg22a0IZPoSUCpasufiLAnfXh6NInLiWBrjLJXDSGaY7vaokt
+rpZvAdmjXTBbMAsGA1UdDwQEAwIBBjAMBgNVHRMEBTADAQH/MB0GA1UdDgQWBBRZ
+4ZTgDpksHL2qcpkFkxD2zVd16TAfBgNVHSMEGDAWgBRZ4ZTgDpksHL2qcpkFkxD2
+zVd16TAMBggqhkjOPQQDAwUAA2gAMGUCMQD4IoqT2hTUn0jt7oXLdMJ8q4vLp6sg
+wHfPiOr9gxreb+e6Oidwd2LDnC4OUqCWiF8CMAzwKs4SnDJYcMLf2vpkbuVE4dTH
+Rglz+HGcTLWsFs4KxLsq7MuU+vJTBUeDJeDjdA==
+-----END CERTIFICATE-----
+
+-----BEGIN CERTIFICATE-----
+MIIDxTCCAq2gAwIBAgIUEMdk6dVgOEIS2cCP0Q43P90Ps5YwDQYJKoZIhvcNAQEF
+BQAwajELMAkGA1UEBhMCQ04xEzARBgNVBAoMCmlUcnVzQ2hpbmExHDAaBgNVBAsM
+E0NoaW5hIFRydXN0IE5ldHdvcmsxKDAmBgNVBAMMH2lUcnVzQ2hpbmEgQ2xhc3Mg
+MiBSb290IENBIC0gRzMwHhcNMTMwNDE4MDkzNjU2WhcNMzMwNDE4MDkzNjU2WjBq
+MQswCQYDVQQGEwJDTjETMBEGA1UECgwKaVRydXNDaGluYTEcMBoGA1UECwwTQ2hp
+bmEgVHJ1c3QgTmV0d29yazEoMCYGA1UEAwwfaVRydXNDaGluYSBDbGFzcyAyIFJv
+b3QgQ0EgLSBHMzCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAOPPShpV
+nJbMqqCw6Bz1kehnoPst9pkr0V9idOwU2oyS47/HjJXk9Rd5a9xfwkPO88trUpz5
+4GmmwspDXjVFu9L0eFaRuH3KMha1Ak01citbF7cQLJlS7XI+tpkTGHEY5pt3EsQg
+wykfZl/A1jrnSkspMS997r2Gim54cwz+mTMgDRhZsKK/lbOeBPpWtcFizjXYCqhw
+WktvQfZBYi6o4sHCshnOswi4yV1p+LuFcQ2ciYdWvULh1eZhLxHbGXyznYHi0dGN
+z+I9H8aXxqAQfHVhbdHNzi77hCxFjOy+hHrGsyzjrd2swVQ2iUWP8BfEQqGLqM1g
+KgWKYfcTGdbPB1MCAwEAAaNjMGEwHQYDVR0OBBYEFG/oAMxTVe7y0+408CTAK8hA
+uTyRMB8GA1UdIwQYMBaAFG/oAMxTVe7y0+408CTAK8hAuTyRMA8GA1UdEwEB/wQF
+MAMBAf8wDgYDVR0PAQH/BAQDAgEGMA0GCSqGSIb3DQEBBQUAA4IBAQBLnUTfW7hp
+emMbuUGCk7RBswzOT83bDM6824EkUnf+X0iKS95SUNGeeSWK2o/3ALJo5hi7GZr3
+U8eLaWAcYizfO99UXMRBPw5PRR+gXGEronGUugLpxsjuynoLQu8GQAeysSXKbN1I
+UugDo9u8igJORYA+5ms0s5sCUySqbQ2R5z/GoceyI9LdxIVa1RjVX8pYOj8JFwtn
+DJN3ftSFvNMYwRuILKuqUYSHc2GPYiHVflDh5nDymCMOQFcFG3WsEuB+EYQPFgIU
+1DHmdZcz7Llx8UOZXX2JupWCYzK1XhJb+r4hK5ncf/w8qGtYlmyJpxk3hr1TfUJX
+Yf4Zr0fJsGuv
+-----END CERTIFICATE-----

+ 24 - 0
src/main/resources/alipay/appCertPublicKey_2021003125657245.crt

@@ -0,0 +1,24 @@
+-----BEGIN CERTIFICATE-----
+MIIEqzCCA5OgAwIBAgIQICIDJbPbM7ejFvqGajOkTTANBgkqhkiG9w0BAQsFADCBgjELMAkGA1UE
+BhMCQ04xFjAUBgNVBAoMDUFudCBGaW5hbmNpYWwxIDAeBgNVBAsMF0NlcnRpZmljYXRpb24gQXV0
+aG9yaXR5MTkwNwYDVQQDDDBBbnQgRmluYW5jaWFsIENlcnRpZmljYXRpb24gQXV0aG9yaXR5IENs
+YXNzIDEgUjEwHhcNMjIwMzI1MTU0NTUwWhcNMjcwMzI0MTU0NTUwWjBzMQswCQYDVQQGEwJDTjEn
+MCUGA1UECgwe6LS15bee5Lit5a6P56eR5oqA5pyJ6ZmQ5YWs5Y+4MQ8wDQYDVQQLDAZBbGlwYXkx
+KjAoBgNVBAMMITIwODgzNDE5Njc0NDM0NzItMjAyMTAwMzEyNTY1NzI0NTCCASIwDQYJKoZIhvcN
+AQEBBQADggEPADCCAQoCggEBAJThdNs2Oc06a4SfAESBQE5UsrkJpSJQUoSRVbX/axOWKMBFnMu3
+PBd9uS/McSEJK74T44DUW61uHkfA0ALTpu+pgNL5NesW5nQtwNpT3aWTken953w2FFe2bSCyzVNL
+S95s6r7eR6MSsi9UKD2Q0ytgyuZ1/wbT7MqUKne+t90zfsh4tencag5yQ3MeH8tPust3v/1Bx1II
++LE9LC6yt8K6zDcfT3dy5aRX1Zfgaj/MdMv2sATAk86ffo6HJVzWgbXXdkmJWDsqCxkY4IknKH0G
++Uqra+4rGfKVDCr0qHl74F8/YVJaztrVcyP/v0mxlPHO0n20WpxJdCH32+rWd3UCAwEAAaOCASkw
+ggElMB8GA1UdIwQYMBaAFHEH4gRhFuTl8mXrMQ/J4PQ8mtWRMB0GA1UdDgQWBBTzl1MHKfooZ6Td
+yrVlNRzvSy8PkTBABgNVHSAEOTA3MDUGB2CBHAFuAQEwKjAoBggrBgEFBQcCARYcaHR0cDovL2Nh
+LmFsaXBheS5jb20vY3BzLnBkZjAOBgNVHQ8BAf8EBAMCBsAwLwYDVR0fBCgwJjAkoCKgIIYeaHR0
+cDovL2NhLmFsaXBheS5jb20vY3JsNjMuY3JsMGAGCCsGAQUFBwEBBFQwUjAoBggrBgEFBQcwAoYc
+aHR0cDovL2NhLmFsaXBheS5jb20vY2E2LmNlcjAmBggrBgEFBQcwAYYaaHR0cDovL2NhLmFsaXBh
+eS5jb206ODM0MC8wDQYJKoZIhvcNAQELBQADggEBAD+saJFzxKDOOGbVHey11iOK8HmDq7rCCcrn
+UXt6EW3I7w9j9SNpmvcyPnYw/+65Pe4vd0GAHuQFdmGHXcaxbwdAkGP/0QmNHzcIcwaXhNzVsxrU
+Zt5QU0iaGLaouOMKXXuWNNLcT8l9W7TGOHGljrWuuFXhAooqs8CW0tx7cWZaDfOIs1EXw+E2bHcq
+mKwqmsEPHMghrQuLO4WLW5zU0NbJ7dMNm2rHk5F49Vm4iUZ5OmMBqst0fiHLn5YJSUBvS+6AdCJ5
+3B+PpBDCSFeJPFJOZYagWYx9KS/HLRnO1jWJ+fjEscElGs02PTRnIhzrshvCwIRMex4vgaghVFzr
+qFc=
+-----END CERTIFICATE-----

+ 23 - 1
src/main/resources/application-dev.yml

@@ -13,7 +13,7 @@ spring:
     #  commandTimeout: 5000
   datasource:
     # MySql
-    url: jdbc:mysql://localhost:3306/t-dev?useSSL=false&useUnicode=true&characterEncoding=utf-8&zeroDateTimeBehavior=convertToNull&transformedBitIsBoolean=true&serverTimezone=GMT%2B8&nullCatalogMeansCurrent=true&allowPublicKeyRetrieval=true
+    url: jdbc:mysql://localhost:3306/t-dev?useSSL=false&useUnicode=true&characterEncoding=utf-8&zeroDateTimeBehavior=convertToNull&transformedBitIsBoolean=true&serverTimezone=Asia/Shanghai&nullCatalogMeansCurrent=true&allowPublicKeyRetrieval=true
     username: root
     password: 123456
     # PostgreSQL
@@ -64,4 +64,26 @@ v3:
   apiKey3: 89e3e5afd8623772bf5a56f460af839a
   apiKey: 89e3e5afd8623772bf5a56f460af839a
   domain: https://wine.gzzzyd.com
+alipay:
+  ijpay:
+    appId: 2021003125657245
+    privateKey: MIIEvAIBADANBgkqhkiG9w0BAQEFAASCBKYwggSiAgEAAoIBAQCU4XTbNjnNOmuEnwBEgUBOVLK5CaUiUFKEkVW1/2sTlijARZzLtzwXfbkvzHEhCSu+E+OA1Futbh5HwNAC06bvqYDS+TXrFuZ0LcDaU92lk5Hp/ed8NhRXtm0gss1TS0vebOq+3kejErIvVCg9kNMrYMrmdf8G0+zKlCp3vrfdM37IeLXp3GoOckNzHh/LT7rLd7/9QcdSCPixPSwusrfCusw3H093cuWkV9WX4Go/zHTL9rAEwJPOn36OhyVc1oG113ZJiVg7KgsZGOCJJyh9BvlKq2vuKxnylQwq9Kh5e+BfP2FSWs7a1XMj/79JsZTxztJ9tFqcSXQh99vq1nd1AgMBAAECggEAVglIT5oxoxEcq0J7lBshf2Lg+Z/CR2clmKioYImfZm1DVYGlD/DvECA+kYnS4qV7GthBg+S0qi/V3d9mFgwcD6nj4YfVCets+Dyskz8d+p6iFxf820IhVWL+A4Rwta7wxDQrIGwx9+JJCKLYsmNsNUg1WSNdYqO71oHzXMnhVTmYJ6sKOrrBucyI4Ydu9UbfN+DRRGD9seL+Nxh1V2PPXs4ftk2kRlG18LaTPgFba1g8QBIpGDR9gFqM+DvBHUxAWsPRnL1+q0c6o5Ndk7W5f7Ob1zxF/lgqHudiG38jItkwc7MLMOYjbV5wiJPZc93nsHS1CKPSEX9/snNLnx2LQQKBgQDMyLBVVasfTMQpMjyi+Jof9JLHPiRP3dEHwZECUgfdWhPoidLjK9y1wszmCLrcg01842WufrpbJ1QXs+g8x6+DhLHvcKum1znsvQKWdy/2V6a2eahNHsYi1Qus+N0dFgotfZwfElfkIU/jAwh6OnYPCXQCVmdvoxzmdk81L04d5QKBgQC6HY6EZ8o4mo4CzDss2qxT2oKuiI0clnbDPC9LJzkRBVbHosx6AO+C3RyfREZxMzNhYW3XnozifDyRw6rlvI6toE3l9ku71dJS1aKZwbH/h0rdHXXqDHARYc9rdwCzOM2t2Kve/PgXxCDQdwY/m0deXM22oKdOlb7miz2YTGLaUQKBgEg8qucPNzPtUmztybH7W/LVxUj/RLPfnTLNNyfIY/nTIp6ur3NvL4X2V2z1u2S59IWPeXjaP0aUUvehgNSf4+vSzSmXZxWNamN2MQl+ta6CMM7Bj3rU1jPHTz0O9ICkG6b8Xiwfvl082v9LPJxRLwAS55dDf21D7pflN/+c1kN5AoGARaRHrt3TeojCuONJBUiyERKDseFgxCC9QeLkY3/Cx86yoTMWxlRRSyuHyUTYAwXApSC65GLsntcUJwsLiLmcvfVtEK6vuhKRh/Nuy5ACFfa/Gawrci/DQ43Q+opmFaoctH+OGHuaLfJywO64xNZKx1F8nGjTEgHQlB3oJ3P1zXECgYBW/GRUU+SevGeLjZTZ9WqG+ztseItnmEwmar9tGhR9TNv3vDiL5/fsAfI8ApMiIzDe6+QfS5Lxx5rD6V4Et/zBpsf8JzqP2eDiTe9UiHxDr2v5NIxelf404VZcdRh83u84lCJTa/ZYanFu94UW6h70MHhDWtiWddtFR3EXt5hD9w==
+    publicKey: MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAhIxPBQL0OKBc6fcU/9PdVTMA7L2s314oU2w1q06ywQSDdhF3RY1Bo0Eqh4Zg8QpPirFeyAc4rhFjyKZRlngQXrybcAhUfswD86QQGodObe3aA9bbWdXiTt10Q5CBk5GImadNiEW6Adh+0bY5ezf1RbxIjbGDfH6x5gatZnpjPswiHMQnskZtg9JSfE2u8WEKuSaH8yhnkllHpIHWnWvFvXwNVNycXdmDrEe7gIB1yCouNK6/DZ7IQH2AajSuvbxmCqO0MzywEfgvLqE0GFVsKKmXvgJebRAnW9RmGhmrxvEIceXCjR3tbxM9gX8lioDlqKnBootTgAbjIJ5VrPvKPwIDAQAB
+    appCertPath: alipay/appCertPublicKey_2021003125657245.crt
+    aliPayCertPath: alipay/alipayCertPublicKey_RSA2.crt
+    aliPayRootCertPath: alipay/alipayRootCert.crt
+    serverUrl: https://openapi.alipay.com/gateway.do
+    domain: https://wine.gzzzyd.com
+  sdk:
+    dev: false #默认false,为true表示使用沙箱环境
+    sign-type: RSA2 #签名算法
+    app-id: 2021003125657245 #应用ID
+    #应用私钥
+    private-key: MIIEvAIBADANBgkqhkiG9w0BAQEFAASCBKYwggSiAgEAAoIBAQCU4XTbNjnNOmuEnwBEgUBOVLK5CaUiUFKEkVW1/2sTlijARZzLtzwXfbkvzHEhCSu+E+OA1Futbh5HwNAC06bvqYDS+TXrFuZ0LcDaU92lk5Hp/ed8NhRXtm0gss1TS0vebOq+3kejErIvVCg9kNMrYMrmdf8G0+zKlCp3vrfdM37IeLXp3GoOckNzHh/LT7rLd7/9QcdSCPixPSwusrfCusw3H093cuWkV9WX4Go/zHTL9rAEwJPOn36OhyVc1oG113ZJiVg7KgsZGOCJJyh9BvlKq2vuKxnylQwq9Kh5e+BfP2FSWs7a1XMj/79JsZTxztJ9tFqcSXQh99vq1nd1AgMBAAECggEAVglIT5oxoxEcq0J7lBshf2Lg+Z/CR2clmKioYImfZm1DVYGlD/DvECA+kYnS4qV7GthBg+S0qi/V3d9mFgwcD6nj4YfVCets+Dyskz8d+p6iFxf820IhVWL+A4Rwta7wxDQrIGwx9+JJCKLYsmNsNUg1WSNdYqO71oHzXMnhVTmYJ6sKOrrBucyI4Ydu9UbfN+DRRGD9seL+Nxh1V2PPXs4ftk2kRlG18LaTPgFba1g8QBIpGDR9gFqM+DvBHUxAWsPRnL1+q0c6o5Ndk7W5f7Ob1zxF/lgqHudiG38jItkwc7MLMOYjbV5wiJPZc93nsHS1CKPSEX9/snNLnx2LQQKBgQDMyLBVVasfTMQpMjyi+Jof9JLHPiRP3dEHwZECUgfdWhPoidLjK9y1wszmCLrcg01842WufrpbJ1QXs+g8x6+DhLHvcKum1znsvQKWdy/2V6a2eahNHsYi1Qus+N0dFgotfZwfElfkIU/jAwh6OnYPCXQCVmdvoxzmdk81L04d5QKBgQC6HY6EZ8o4mo4CzDss2qxT2oKuiI0clnbDPC9LJzkRBVbHosx6AO+C3RyfREZxMzNhYW3XnozifDyRw6rlvI6toE3l9ku71dJS1aKZwbH/h0rdHXXqDHARYc9rdwCzOM2t2Kve/PgXxCDQdwY/m0deXM22oKdOlb7miz2YTGLaUQKBgEg8qucPNzPtUmztybH7W/LVxUj/RLPfnTLNNyfIY/nTIp6ur3NvL4X2V2z1u2S59IWPeXjaP0aUUvehgNSf4+vSzSmXZxWNamN2MQl+ta6CMM7Bj3rU1jPHTz0O9ICkG6b8Xiwfvl082v9LPJxRLwAS55dDf21D7pflN/+c1kN5AoGARaRHrt3TeojCuONJBUiyERKDseFgxCC9QeLkY3/Cx86yoTMWxlRRSyuHyUTYAwXApSC65GLsntcUJwsLiLmcvfVtEK6vuhKRh/Nuy5ACFfa/Gawrci/DQ43Q+opmFaoctH+OGHuaLfJywO64xNZKx1F8nGjTEgHQlB3oJ3P1zXECgYBW/GRUU+SevGeLjZTZ9WqG+ztseItnmEwmar9tGhR9TNv3vDiL5/fsAfI8ApMiIzDe6+QfS5Lxx5rD6V4Et/zBpsf8JzqP2eDiTe9UiHxDr2v5NIxelf404VZcdRh83u84lCJTa/ZYanFu94UW6h70MHhDWtiWddtFR3EXt5hD9w==
+    #支付宝公钥
+    alipay-public-key: MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAhIxPBQL0OKBc6fcU/9PdVTMA7L2s314oU2w1q06ywQSDdhF3RY1Bo0Eqh4Zg8QpPirFeyAc4rhFjyKZRlngQXrybcAhUfswD86QQGodObe3aA9bbWdXiTt10Q5CBk5GImadNiEW6Adh+0bY5ezf1RbxIjbGDfH6x5gatZnpjPswiHMQnskZtg9JSfE2u8WEKuSaH8yhnkllHpIHWnWvFvXwNVNycXdmDrEe7gIB1yCouNK6/DZ7IQH2AajSuvbxmCqO0MzywEfgvLqE0GFVsKKmXvgJebRAnW9RmGhmrxvEIceXCjR3tbxM9gX8lioDlqKnBootTgAbjIJ5VrPvKPwIDAQAB
+    # 商户支付宝账号
+    payee-user-id: 2088341967443472
+    # 回调域名
+    domain: https://wine.gzzzyd.com
 

+ 1 - 1
src/main/resources/application-prod.yml

@@ -14,7 +14,7 @@ spring:
     #  nodes: 127.0.0.1:7001,127.0.0.1:7002,127.0.0.1:7003
     #  commandTimeout: 5000
   datasource:
-    url: jdbc:mysql://localhost:3306/bladex_boot?useSSL=false&useUnicode=true&characterEncoding=utf-8&zeroDateTimeBehavior=convertToNull&transformedBitIsBoolean=true&serverTimezone=GMT%2B8&nullCatalogMeansCurrent=true&allowPublicKeyRetrieval=true
+    url: jdbc:mysql://localhost:3306/bladex_boot?useSSL=false&useUnicode=true&characterEncoding=utf-8&zeroDateTimeBehavior=convertToNull&transformedBitIsBoolean=true&serverTimezone=Asia/Shanghai&nullCatalogMeansCurrent=true&allowPublicKeyRetrieval=true
     username: root
     password: root
 

+ 23 - 2
src/main/resources/application-test.yml

@@ -14,7 +14,7 @@ spring:
     #  nodes: 127.0.0.1:7001,127.0.0.1:7002,127.0.0.1:7003
     #  commandTimeout: 5000
   datasource:
-    url: jdbc:mysql://172.26.218.204:3306/t-test?useSSL=false&useUnicode=true&characterEncoding=utf-8&zeroDateTimeBehavior=convertToNull&transformedBitIsBoolean=true&serverTimezone=GMT%2B8&nullCatalogMeansCurrent=true&allowPublicKeyRetrieval=true
+    url: jdbc:mysql://172.26.218.204:3306/t-test?useSSL=false&useUnicode=true&characterEncoding=utf-8&zeroDateTimeBehavior=convertToNull&transformedBitIsBoolean=true&serverTimezone=&serverTimezone=Asia/Shanghai&nullCatalogMeansCurrent=true&allowPublicKeyRetrieval=true
     username: root
     password: 123456
 
@@ -38,7 +38,6 @@ blade:
     remote-mode: true
     upload-domain: https://wine.gzzzyd.com
     remote-path: /usr/local/nginx/dist
-
 wxpay:
   appId: wx3064b51f7bace3c8
   appSecret: 89e3e5afd8623772bf5a56f460af839a
@@ -56,3 +55,25 @@ v3:
   apiKey3: 89e3e5afd8623772bf5a56f460af839a
   apiKey: 89e3e5afd8623772bf5a56f460af839a
   domain: https://wine.gzzzyd.com
+alipay:
+  ijpay:
+    appId: 2021003125657245
+    privateKey: MIIEvAIBADANBgkqhkiG9w0BAQEFAASCBKYwggSiAgEAAoIBAQCU4XTbNjnNOmuEnwBEgUBOVLK5CaUiUFKEkVW1/2sTlijARZzLtzwXfbkvzHEhCSu+E+OA1Futbh5HwNAC06bvqYDS+TXrFuZ0LcDaU92lk5Hp/ed8NhRXtm0gss1TS0vebOq+3kejErIvVCg9kNMrYMrmdf8G0+zKlCp3vrfdM37IeLXp3GoOckNzHh/LT7rLd7/9QcdSCPixPSwusrfCusw3H093cuWkV9WX4Go/zHTL9rAEwJPOn36OhyVc1oG113ZJiVg7KgsZGOCJJyh9BvlKq2vuKxnylQwq9Kh5e+BfP2FSWs7a1XMj/79JsZTxztJ9tFqcSXQh99vq1nd1AgMBAAECggEAVglIT5oxoxEcq0J7lBshf2Lg+Z/CR2clmKioYImfZm1DVYGlD/DvECA+kYnS4qV7GthBg+S0qi/V3d9mFgwcD6nj4YfVCets+Dyskz8d+p6iFxf820IhVWL+A4Rwta7wxDQrIGwx9+JJCKLYsmNsNUg1WSNdYqO71oHzXMnhVTmYJ6sKOrrBucyI4Ydu9UbfN+DRRGD9seL+Nxh1V2PPXs4ftk2kRlG18LaTPgFba1g8QBIpGDR9gFqM+DvBHUxAWsPRnL1+q0c6o5Ndk7W5f7Ob1zxF/lgqHudiG38jItkwc7MLMOYjbV5wiJPZc93nsHS1CKPSEX9/snNLnx2LQQKBgQDMyLBVVasfTMQpMjyi+Jof9JLHPiRP3dEHwZECUgfdWhPoidLjK9y1wszmCLrcg01842WufrpbJ1QXs+g8x6+DhLHvcKum1znsvQKWdy/2V6a2eahNHsYi1Qus+N0dFgotfZwfElfkIU/jAwh6OnYPCXQCVmdvoxzmdk81L04d5QKBgQC6HY6EZ8o4mo4CzDss2qxT2oKuiI0clnbDPC9LJzkRBVbHosx6AO+C3RyfREZxMzNhYW3XnozifDyRw6rlvI6toE3l9ku71dJS1aKZwbH/h0rdHXXqDHARYc9rdwCzOM2t2Kve/PgXxCDQdwY/m0deXM22oKdOlb7miz2YTGLaUQKBgEg8qucPNzPtUmztybH7W/LVxUj/RLPfnTLNNyfIY/nTIp6ur3NvL4X2V2z1u2S59IWPeXjaP0aUUvehgNSf4+vSzSmXZxWNamN2MQl+ta6CMM7Bj3rU1jPHTz0O9ICkG6b8Xiwfvl082v9LPJxRLwAS55dDf21D7pflN/+c1kN5AoGARaRHrt3TeojCuONJBUiyERKDseFgxCC9QeLkY3/Cx86yoTMWxlRRSyuHyUTYAwXApSC65GLsntcUJwsLiLmcvfVtEK6vuhKRh/Nuy5ACFfa/Gawrci/DQ43Q+opmFaoctH+OGHuaLfJywO64xNZKx1F8nGjTEgHQlB3oJ3P1zXECgYBW/GRUU+SevGeLjZTZ9WqG+ztseItnmEwmar9tGhR9TNv3vDiL5/fsAfI8ApMiIzDe6+QfS5Lxx5rD6V4Et/zBpsf8JzqP2eDiTe9UiHxDr2v5NIxelf404VZcdRh83u84lCJTa/ZYanFu94UW6h70MHhDWtiWddtFR3EXt5hD9w==
+    publicKey: MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAhIxPBQL0OKBc6fcU/9PdVTMA7L2s314oU2w1q06ywQSDdhF3RY1Bo0Eqh4Zg8QpPirFeyAc4rhFjyKZRlngQXrybcAhUfswD86QQGodObe3aA9bbWdXiTt10Q5CBk5GImadNiEW6Adh+0bY5ezf1RbxIjbGDfH6x5gatZnpjPswiHMQnskZtg9JSfE2u8WEKuSaH8yhnkllHpIHWnWvFvXwNVNycXdmDrEe7gIB1yCouNK6/DZ7IQH2AajSuvbxmCqO0MzywEfgvLqE0GFVsKKmXvgJebRAnW9RmGhmrxvEIceXCjR3tbxM9gX8lioDlqKnBootTgAbjIJ5VrPvKPwIDAQAB
+    appCertPath: /usr/local/liquor/alipay/appCertPublicKey_2021003125657245.crt
+    aliPayCertPath: /usr/local/liquor/alipay/alipayCertPublicKey_RSA2.crt
+    aliPayRootCertPath: /usr/local/liquor/alipay/alipayRootCert.crt
+    serverUrl: https://openapi.alipay.com/gateway.do
+    domain: https://wine.gzzzyd.com
+  sdk:
+    dev: false #默认false,为true表示使用沙箱环境
+    sign-type: RSA2 #签名算法
+    app-id: 2021003125657245 #应用ID
+    #应用私钥
+    private-key: MIIEvAIBADANBgkqhkiG9w0BAQEFAASCBKYwggSiAgEAAoIBAQCU4XTbNjnNOmuEnwBEgUBOVLK5CaUiUFKEkVW1/2sTlijARZzLtzwXfbkvzHEhCSu+E+OA1Futbh5HwNAC06bvqYDS+TXrFuZ0LcDaU92lk5Hp/ed8NhRXtm0gss1TS0vebOq+3kejErIvVCg9kNMrYMrmdf8G0+zKlCp3vrfdM37IeLXp3GoOckNzHh/LT7rLd7/9QcdSCPixPSwusrfCusw3H093cuWkV9WX4Go/zHTL9rAEwJPOn36OhyVc1oG113ZJiVg7KgsZGOCJJyh9BvlKq2vuKxnylQwq9Kh5e+BfP2FSWs7a1XMj/79JsZTxztJ9tFqcSXQh99vq1nd1AgMBAAECggEAVglIT5oxoxEcq0J7lBshf2Lg+Z/CR2clmKioYImfZm1DVYGlD/DvECA+kYnS4qV7GthBg+S0qi/V3d9mFgwcD6nj4YfVCets+Dyskz8d+p6iFxf820IhVWL+A4Rwta7wxDQrIGwx9+JJCKLYsmNsNUg1WSNdYqO71oHzXMnhVTmYJ6sKOrrBucyI4Ydu9UbfN+DRRGD9seL+Nxh1V2PPXs4ftk2kRlG18LaTPgFba1g8QBIpGDR9gFqM+DvBHUxAWsPRnL1+q0c6o5Ndk7W5f7Ob1zxF/lgqHudiG38jItkwc7MLMOYjbV5wiJPZc93nsHS1CKPSEX9/snNLnx2LQQKBgQDMyLBVVasfTMQpMjyi+Jof9JLHPiRP3dEHwZECUgfdWhPoidLjK9y1wszmCLrcg01842WufrpbJ1QXs+g8x6+DhLHvcKum1znsvQKWdy/2V6a2eahNHsYi1Qus+N0dFgotfZwfElfkIU/jAwh6OnYPCXQCVmdvoxzmdk81L04d5QKBgQC6HY6EZ8o4mo4CzDss2qxT2oKuiI0clnbDPC9LJzkRBVbHosx6AO+C3RyfREZxMzNhYW3XnozifDyRw6rlvI6toE3l9ku71dJS1aKZwbH/h0rdHXXqDHARYc9rdwCzOM2t2Kve/PgXxCDQdwY/m0deXM22oKdOlb7miz2YTGLaUQKBgEg8qucPNzPtUmztybH7W/LVxUj/RLPfnTLNNyfIY/nTIp6ur3NvL4X2V2z1u2S59IWPeXjaP0aUUvehgNSf4+vSzSmXZxWNamN2MQl+ta6CMM7Bj3rU1jPHTz0O9ICkG6b8Xiwfvl082v9LPJxRLwAS55dDf21D7pflN/+c1kN5AoGARaRHrt3TeojCuONJBUiyERKDseFgxCC9QeLkY3/Cx86yoTMWxlRRSyuHyUTYAwXApSC65GLsntcUJwsLiLmcvfVtEK6vuhKRh/Nuy5ACFfa/Gawrci/DQ43Q+opmFaoctH+OGHuaLfJywO64xNZKx1F8nGjTEgHQlB3oJ3P1zXECgYBW/GRUU+SevGeLjZTZ9WqG+ztseItnmEwmar9tGhR9TNv3vDiL5/fsAfI8ApMiIzDe6+QfS5Lxx5rD6V4Et/zBpsf8JzqP2eDiTe9UiHxDr2v5NIxelf404VZcdRh83u84lCJTa/ZYanFu94UW6h70MHhDWtiWddtFR3EXt5hD9w==
+    #支付宝公钥
+    alipay-public-key: MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAhIxPBQL0OKBc6fcU/9PdVTMA7L2s314oU2w1q06ywQSDdhF3RY1Bo0Eqh4Zg8QpPirFeyAc4rhFjyKZRlngQXrybcAhUfswD86QQGodObe3aA9bbWdXiTt10Q5CBk5GImadNiEW6Adh+0bY5ezf1RbxIjbGDfH6x5gatZnpjPswiHMQnskZtg9JSfE2u8WEKuSaH8yhnkllHpIHWnWvFvXwNVNycXdmDrEe7gIB1yCouNK6/DZ7IQH2AajSuvbxmCqO0MzywEfgvLqE0GFVsKKmXvgJebRAnW9RmGhmrxvEIceXCjR3tbxM9gX8lioDlqKnBootTgAbjIJ5VrPvKPwIDAQAB
+    # 商户支付宝账号
+    payee-user-id: 2088341967443472
+    # 回调域名
+    domain: https://wine.gzzzyd.com

+ 3 - 3
src/main/resources/application.yml

@@ -35,8 +35,8 @@ spring:
       min-evictable-idle-time-millis: 300000
       stat-view-servlet:
         enabled: true
-        login-username: blade
-        login-password: 1qaz@WSX
+        login-username: 18185837450
+        login-password: 74500013
       web-stat-filter:
         enabled: true
         url-pattern: /*
@@ -115,7 +115,7 @@ oss:
   endpoint: https://oss-cn-chengdu.aliyuncs.com
   access-key: LTAI4GCNRML2EpFZxBWakWSc
   secret-key: 8u1spjDrT1hD2OaN9DS8NasSHipDfO
-  bucket-name: 000000-tbladex
+  bucket-name: tbladex
 # 短信配置
 sms:
   enabled: true