张延森 hace 4 años
padre
commit
1eec76deea

+ 59
- 0
src/main/java/com/yunzhi/niucai/alipay/AlipayFactory.java Ver fichero

@@ -0,0 +1,59 @@
1
+package com.yunzhi.niucai.alipay;
2
+
3
+import com.alipay.api.AlipayClient;
4
+import com.alipay.api.DefaultAlipayClient;
5
+import com.yunzhi.niucai.alipay.vo.ITokenResolve;
6
+import com.yunzhi.niucai.entity.TaAlipay;
7
+import com.yunzhi.niucai.service.ITaAlipayService;
8
+import com.yunzhi.niucai.service.ITaShopAppService;
9
+import com.yunzhi.niucai.service.impl.TaShopAppServiceImpl;
10
+import org.springframework.beans.factory.InitializingBean;
11
+import org.springframework.beans.factory.annotation.Autowired;
12
+import org.springframework.beans.factory.annotation.Value;
13
+import org.springframework.stereotype.Component;
14
+
15
+import javax.annotation.Resource;
16
+
17
+@Component
18
+public class AlipayFactory implements InitializingBean {
19
+    private AlipayClient alipayClient;
20
+
21
+    @Resource(name = "taShopAppServiceImpl")
22
+    private ITokenResolve tokenResolve;
23
+
24
+    @Autowired
25
+    private Config config;
26
+
27
+    @Autowired
28
+    ITaShopAppService iTaShopAppService;
29
+
30
+    @Autowired
31
+    ITaAlipayService iTaAlipayService;
32
+
33
+    public PayService getService(Integer shopId) {
34
+        return new PayService(shopId, alipayClient, tokenResolve, config);
35
+    }
36
+
37
+    private AlipayClient getAlipayClient(Config config) {
38
+        return new DefaultAlipayClient(config.getApiURL(),
39
+                config.getAppid(),
40
+                config.getPrivateKey(),
41
+                config.getFormat(),
42
+                config.getCharset(),
43
+                config.getPublicKey(),
44
+                config.getSignType());
45
+    }
46
+
47
+    @Override
48
+    public void afterPropertiesSet() throws Exception {
49
+        // 写死, 取第一个
50
+        TaAlipay taAlipay = iTaAlipayService.getById(1);
51
+        this.config = new Config()
52
+                .setAppid(taAlipay.getAppid())
53
+                .setPrivateKey(taAlipay.getMerchantPrivateKey())
54
+                .setPublicKey(taAlipay.getAlipayPublicKey());
55
+
56
+        //
57
+        this.alipayClient = getAlipayClient(this.config);
58
+    }
59
+}

+ 21
- 0
src/main/java/com/yunzhi/niucai/alipay/Config.java Ver fichero

@@ -0,0 +1,21 @@
1
+package com.yunzhi.niucai.alipay;
2
+
3
+import lombok.Data;
4
+import lombok.experimental.Accessors;
5
+import org.springframework.boot.context.properties.ConfigurationProperties;
6
+import org.springframework.stereotype.Component;
7
+
8
+@Data
9
+@Accessors(chain = true)
10
+@Component
11
+@ConfigurationProperties(prefix = "alipay")
12
+public class Config {
13
+    String appid;
14
+    String privateKey;
15
+    String publicKey;
16
+    String format;
17
+    String charset;
18
+    String signType;
19
+    String apiURL;
20
+    String notifyURL;
21
+}

+ 94
- 0
src/main/java/com/yunzhi/niucai/alipay/PayService.java Ver fichero

@@ -0,0 +1,94 @@
1
+package com.yunzhi.niucai.alipay;
2
+
3
+
4
+import com.alibaba.fastjson.JSONObject;
5
+import com.alipay.api.AlipayApiException;
6
+import com.alipay.api.AlipayClient;
7
+import com.alipay.api.request.AlipayOpenAuthTokenAppRequest;
8
+import com.alipay.api.request.AlipayTradeAppPayRequest;
9
+import com.alipay.api.response.AlipayOpenAuthTokenAppResponse;
10
+import com.alipay.api.response.AlipayTradeAppPayResponse;
11
+import com.yunzhi.niucai.alipay.vo.ITokenResolve;
12
+import com.yunzhi.niucai.alipay.vo.PayParam;
13
+import lombok.extern.slf4j.Slf4j;
14
+
15
+import java.util.HashMap;
16
+import java.util.Map;
17
+
18
+@Slf4j
19
+public class PayService {
20
+    private ITokenResolve iTokenResolve;
21
+    private AlipayClient alipayClient;
22
+    private Config config;
23
+    private Integer shopId;
24
+
25
+    public PayService(Integer shopId, AlipayClient alipayClient, ITokenResolve iTokenResolve, Config config) {
26
+        this.shopId = shopId;
27
+        this.iTokenResolve = iTokenResolve;
28
+        this.alipayClient = alipayClient;
29
+        this.config = config;
30
+    }
31
+
32
+    /**
33
+     * 支付
34
+     * @param payParam
35
+     * @return
36
+     * @throws AlipayApiException
37
+     */
38
+    public AlipayTradeAppPayResponse Pay(PayParam payParam) throws AlipayApiException {
39
+        AlipayTradeAppPayRequest aliPayRequest = new AlipayTradeAppPayRequest();
40
+
41
+        String token = null;
42
+        if (this.iTokenResolve.isTokenExpired(this.shopId)) {
43
+            AlipayOpenAuthTokenAppResponse refreshResponse = refreshToken();
44
+            if (null != refreshResponse) {
45
+                token = refreshResponse.getAppAuthToken();
46
+            }
47
+        } else {
48
+            token = this.iTokenResolve.getAuthToken(this.shopId);
49
+        }
50
+
51
+        aliPayRequest.putOtherTextParam("app_auth_token", token);
52
+        aliPayRequest.setNotifyUrl(this.config.getNotifyURL());
53
+
54
+        if (null == payParam.getTimeoutExpress()) {
55
+            payParam.setTimeoutExpress("30m");
56
+        }
57
+
58
+        aliPayRequest.setBizContent(JSONObject.toJSONString(payParam));
59
+        try {
60
+            AlipayTradeAppPayResponse response = alipayClient.sdkExecute(aliPayRequest);
61
+            if (response.isSuccess()) {
62
+                return response;
63
+            } else {
64
+                log.error(String.format("支付宝下单失败, 商户ID %s : 错误码[%s], 错误说明[%s]", this.shopId, response.getSubCode(), response.getSubMsg()));
65
+                return null;
66
+            }
67
+        } catch (AlipayApiException e) {
68
+            log.error(String.format("使用支付宝下单失败: %s", e.getErrMsg()));
69
+            e.printStackTrace();
70
+            throw e;
71
+        }
72
+    }
73
+
74
+    private AlipayOpenAuthTokenAppResponse refreshToken() throws AlipayApiException {
75
+
76
+        AlipayOpenAuthTokenAppRequest request = new AlipayOpenAuthTokenAppRequest();
77
+
78
+        String refreshToken = this.iTokenResolve.getRefreshToken(this.shopId);
79
+        Map<String, String> param = new HashMap<String, String>() {{
80
+            put("grant_type", "refresh_token");
81
+            put("refresh_token", refreshToken);
82
+        }};
83
+
84
+        request.setBizContent(JSONObject.toJSONString(param));
85
+        AlipayOpenAuthTokenAppResponse response = alipayClient.execute(request);
86
+        if(response.isSuccess()){
87
+            this.iTokenResolve.refreshAuthToken(this.shopId, response.getAppAuthToken(), response.getAppRefreshToken(), response.getExpiresIn());
88
+            return response;
89
+        } else {
90
+            log.error(String.format("刷新支付宝 APP_AUTH_TOKEN 失败, 商户ID %s : 错误码[%s], 错误说明[%s]", this.shopId, response.getSubCode(), response.getSubMsg()));
91
+            return null;
92
+        }
93
+    }
94
+}

+ 32
- 0
src/main/java/com/yunzhi/niucai/alipay/vo/ITokenResolve.java Ver fichero

@@ -0,0 +1,32 @@
1
+package com.yunzhi.niucai.alipay.vo;
2
+
3
+public interface ITokenResolve {
4
+
5
+    /**
6
+     * Token 是否过期
7
+     * @param shopId
8
+     * @return
9
+     */
10
+    boolean isTokenExpired(Integer shopId);
11
+
12
+    /**
13
+     * 获取 Token
14
+     * @param shopId
15
+     * @return
16
+     */
17
+    String getAuthToken(Integer shopId);
18
+
19
+    /**
20
+     * 获取 refreshToken
21
+     * @param shopId
22
+     * @return
23
+     */
24
+    String getRefreshToken(Integer shopId);
25
+
26
+    /**
27
+     * 刷新 Token
28
+     * @param shopId
29
+     * @return
30
+     */
31
+    void refreshAuthToken(Integer shopId, String authToken, String refreshToken, String expiresIn);
32
+}

+ 30
- 0
src/main/java/com/yunzhi/niucai/alipay/vo/PayParam.java Ver fichero

@@ -0,0 +1,30 @@
1
+package com.yunzhi.niucai.alipay.vo;
2
+
3
+import com.alibaba.fastjson.annotation.JSONField;
4
+import io.swagger.annotations.ApiModel;
5
+import io.swagger.annotations.ApiModelProperty;
6
+import lombok.Data;
7
+import lombok.experimental.Accessors;
8
+
9
+
10
+@ApiModel(description = "支付宝下单参数")
11
+@Data
12
+@Accessors(chain = true)
13
+public class PayParam {
14
+
15
+    @ApiModelProperty("总金额, 单位元, 2位小数到分")
16
+    @JSONField(name = "total_amount")
17
+    private String totalAmount;
18
+
19
+    @ApiModelProperty("商品的标题")
20
+    @JSONField(name = "subject")
21
+    private String subject;
22
+
23
+    @ApiModelProperty("唯一订单号")
24
+    @JSONField(name = "out_trade_no")
25
+    private String outTradeNo;
26
+
27
+    @ApiModelProperty("逾期时间 取值范围:5m~15d。m-分钟,h-小时,d-天")
28
+    @JSONField(name = "timeout_express")
29
+    private String timeoutExpress;
30
+}

+ 3
- 0
src/main/java/com/yunzhi/niucai/entity/TaShopApp.java Ver fichero

@@ -56,4 +56,7 @@ public class TaShopApp implements Serializable {
56 56
 
57 57
     @ApiModelProperty(value = "对应的alipay应用")
58 58
     private Integer alipayId;
59
+
60
+    @ApiModelProperty(value = "Token 有效期, 单位秒")
61
+    private String expiresIn;
59 62
 }

+ 23
- 26
src/main/java/com/yunzhi/niucai/service/impl/TaAlipayServiceImpl.java Ver fichero

@@ -6,6 +6,9 @@ import com.alipay.api.DefaultAlipayClient;
6 6
 import com.alipay.api.request.AlipayTradeAppPayRequest;
7 7
 import com.alipay.api.response.AlipayTradeAppPayResponse;
8 8
 import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
9
+import com.yunzhi.niucai.alipay.AlipayFactory;
10
+import com.yunzhi.niucai.alipay.PayService;
11
+import com.yunzhi.niucai.alipay.vo.PayParam;
9 12
 import com.yunzhi.niucai.common.CommConstants;
10 13
 import com.yunzhi.niucai.common.ResponseBean;
11 14
 import com.yunzhi.niucai.entity.TaAlipay;
@@ -41,8 +44,8 @@ public class TaAlipayServiceImpl extends ServiceImpl<TaAlipayMapper, TaAlipay> i
41 44
     @Autowired
42 45
     private ITaOrderService taOrderService;
43 46
 
44
-    @Value("${aliPay.notifyUrl}")
45
-    private String aliPayNotifyUrl;
47
+    @Autowired
48
+    private AlipayFactory alipayFactory;
46 49
 
47 50
     @Autowired
48 51
     private TaAlipayMapper taAlipayMapper;
@@ -56,32 +59,26 @@ public class TaAlipayServiceImpl extends ServiceImpl<TaAlipayMapper, TaAlipay> i
56 59
      */
57 60
     @Override
58 61
     public ResponseBean orderPaying(TaOrder taOrder, TaShopApp taShopApp) throws AlipayApiException {
59
-        TaAlipay taAlipay = taAlipayMapper.selectById(taShopApp.getAlipayId());
62
+        PayService payService = alipayFactory.getService(taOrder.getShopId());
63
+
60 64
         String outTradeNo = "ALI" + System.currentTimeMillis() + randomString(5);
61
-        AlipayClient alipayClient = new DefaultAlipayClient("https://openapi.alipay.com/gateway.do", taAlipay.getAppid(), taAlipay.getMerchantPrivateKey(), "json", "GBK", taAlipay.getAlipayPublicKey(), "RSA2");
62
-        AlipayTradeAppPayRequest aliPayRequest = new AlipayTradeAppPayRequest();
63
-        aliPayRequest.putOtherTextParam("app_auth_token", taShopApp.getAppAuthToken());
64
-        aliPayRequest.setNotifyUrl(aliPayNotifyUrl);
65
-        aliPayRequest.setBizContent("{" +
66
-                "\"timeout_express\":\"30m\"," +
67
-                "\"total_amount\":\""+taOrder.getCharge() / 100 +"\"," +
68
-                "\"subject\":\"支付宝支付\"," +
69
-                "\"out_trade_no\":\""+outTradeNo+"\"," +
70
-                "  }");
71
-        AlipayTradeAppPayResponse response = alipayClient.sdkExecute(aliPayRequest);
72
-        if(response.isSuccess()){
73
-            // 更新商户订单号并改为支付中
74
-            taOrder.setOutTradeNo(outTradeNo);
75
-            taOrder.setStatus(CommConstants.SRTATUS_PAYING);
76
-            taOrder.setUpdateDate(LocalDateTime.now());
77
-            taOrderService.updateById(taOrder);
78
-            // 更新token是最后使用时间
79
-            taShopApp.setUpdateTokenDate(LocalDateTime.now());
80
-            iTaShopAppService.updateById(taShopApp);
81
-        } else {
82
-            System.out.println("调用失败");
65
+        String subject = "支付宝支付";
66
+        String totalAmount = String.format("%.2f", (float) taOrder.getCharge() / 100);
67
+        PayParam payParam = new PayParam()
68
+                .setOutTradeNo(outTradeNo)
69
+                .setSubject(subject)
70
+                .setTotalAmount(totalAmount);
71
+
72
+        AlipayTradeAppPayResponse response = payService.Pay(payParam);
73
+        if (null == response) {
74
+            return null;
83 75
         }
84
-        return ResponseBean.success(response);
76
+
77
+        taOrder.setOutTradeNo(outTradeNo);
78
+        taOrder.setStatus(CommConstants.SRTATUS_PAYING);
79
+        taOrderService.updateById(taOrder);
80
+
81
+        return null;
85 82
     }
86 83
 
87 84
     /**

+ 45
- 1
src/main/java/com/yunzhi/niucai/service/impl/TaShopAppServiceImpl.java Ver fichero

@@ -1,11 +1,16 @@
1 1
 package com.yunzhi.niucai.service.impl;
2 2
 
3
+import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
4
+import com.yunzhi.niucai.alipay.vo.ITokenResolve;
5
+import com.yunzhi.niucai.common.StringUtils;
3 6
 import com.yunzhi.niucai.entity.TaShopApp;
4 7
 import com.yunzhi.niucai.mapper.TaShopAppMapper;
5 8
 import com.yunzhi.niucai.service.ITaShopAppService;
6 9
 import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
7 10
 import org.springframework.stereotype.Service;
8 11
 
12
+import java.time.LocalDateTime;
13
+
9 14
 /**
10 15
  * <p>
11 16
  * 门店应用表  服务实现类
@@ -15,6 +20,45 @@ import org.springframework.stereotype.Service;
15 20
  * @since 2020-09-23
16 21
  */
17 22
 @Service
18
-public class TaShopAppServiceImpl extends ServiceImpl<TaShopAppMapper, TaShopApp> implements ITaShopAppService {
23
+public class TaShopAppServiceImpl extends ServiceImpl<TaShopAppMapper, TaShopApp> implements ITaShopAppService, ITokenResolve {
24
+
25
+    @Override
26
+    public boolean isTokenExpired(Integer shopId) {
27
+        TaShopApp taShopApp = getByShopId(shopId);
28
+        String expires = taShopApp.getExpiresIn();
29
+        if (StringUtils.isEmpty(expires)) {
30
+            expires = "0";
31
+        }
32
+
33
+        long expiresIn = Long.parseLong(expires);
34
+        return taShopApp.getUpdateTokenDate().plusSeconds(expiresIn).isBefore(LocalDateTime.now());
35
+    }
36
+
37
+    private TaShopApp getByShopId(Integer shopId) {
38
+        QueryWrapper<TaShopApp> queryWrapper = new QueryWrapper<>();
39
+        queryWrapper.eq("shop_id", shopId);
40
+        
41
+        return getOne(queryWrapper);
42
+    }
43
+
44
+    @Override
45
+    public String getAuthToken(Integer shopId) {
46
+        return getByShopId(shopId).getAppAuthToken();
47
+    }
48
+
49
+    @Override
50
+    public String getRefreshToken(Integer shopId) {
51
+        return getByShopId(shopId).getAppRefreshToken();
52
+    }
53
+
54
+    @Override
55
+    public void refreshAuthToken(Integer shopId, String authToken, String refreshToken, String expiresIn) {
56
+        TaShopApp taShopApp = getByShopId(shopId);
57
+        taShopApp.setAppAuthToken(authToken);
58
+        taShopApp.setAppRefreshToken(refreshToken);
59
+        taShopApp.setExpiresIn(expiresIn);
60
+        taShopApp.setUpdateTokenDate(LocalDateTime.now());
19 61
 
62
+        updateById(taShopApp);
63
+    }
20 64
 }

+ 10
- 0
src/main/resources/application.yml Ver fichero

@@ -27,6 +27,16 @@ aliyun:
27 27
     bucketName: njcj
28 28
     bucketURL: https://njcj.oss-cn-shanghai.aliyuncs.com
29 29
 
30
+###
31
+alipay:
32
+  appid:
33
+  privateKey:
34
+  publicKey:
35
+  apiURL: https://openapi.alipay.com/gateway.do
36
+  format: json
37
+  charset: UTF-8
38
+  signType: RSA2
39
+
30 40
 ###
31 41
 weixin:
32 42
   miniapp: