Răsfoiți Sursa

优化微信支付逻辑

woody 1 an în urmă
părinte
comite
289dd7f945

+ 13 - 27
framework-wechat/src/main/java/com/chelvc/framework/wechat/DefaultWechatHandler.java

@@ -87,8 +87,7 @@ public class DefaultWechatHandler implements WechatHandler {
     /**
      * 获取小程序schemeCode接口地址
      */
-    private static final String GENERATE_SCHEME_URL =
-            "https://api.weixin.qq.com/wxa/generatescheme?access_token=%s";
+    private static final String GENERATE_SCHEME_URL = "https://api.weixin.qq.com/wxa/generatescheme?access_token=%s";
 
     private final RestTemplate restTemplate;
     private final RedisTemplate<String, Object> redisTemplate;
@@ -131,14 +130,14 @@ public class DefaultWechatHandler implements WechatHandler {
     /**
      * 获取支付配置
      *
-     * @param mode 支付方式
+     * @param type 支付类型
      * @return 支付配置
      */
-    private WechatProperties.Payment getPayment(PayMode mode) {
+    private WechatProperties.Payment getPayment(String type) {
         List<WechatProperties.Payment> payments = this.properties.getPayments();
         WechatProperties.Payment payment = CollectionUtils.isEmpty(payments) ? null :
-                payments.stream().filter(config -> config.getMode() == mode).findAny().orElse(null);
-        return Objects.requireNonNull(payment, "Not support pay mode: " + mode);
+                payments.stream().filter(config -> Objects.equals(config.getType(), type)).findAny().orElse(null);
+        return Objects.requireNonNull(payment, "Not support payment type: " + type);
     }
 
     /**
@@ -152,7 +151,7 @@ public class DefaultWechatHandler implements WechatHandler {
         String mchid = Objects.requireNonNull(payment.getMchid(), "Wechat mchid unspecified");
         String callback = Objects.requireNonNull(payment.getCallback(), "Wechat callback unspecified");
         Map<String, String> parameters = Maps.newHashMap();
-        parameters.put("appid", this.getAppid(payment));
+        parameters.put("appid", payment.getAppid());
         parameters.put("mch_id", mchid);
         parameters.put("body", request.getComment());
         parameters.put("out_trade_no", request.getOrder());
@@ -168,19 +167,6 @@ public class DefaultWechatHandler implements WechatHandler {
         return parameters;
     }
 
-    /**
-     * 根据支付交易类型获取Appid
-     *
-     * @param payment 支付配置
-     * @return Appid
-     */
-    private String getAppid(WechatProperties.Payment payment) {
-        if (payment.getMode() == PayMode.APP || payment.getMode() == PayMode.NATIVE) {
-            return Objects.requireNonNull(payment.getPayid(), "Wechat payid unspecified");
-        }
-        return Objects.requireNonNull(this.properties.getAppid(), "Wechat appid unspecified");
-    }
-
     /**
      * 参数签名
      *
@@ -362,20 +348,20 @@ public class DefaultWechatHandler implements WechatHandler {
     }
 
     @Override
-    public String sign(@NonNull PayMode mode, @NonNull Map<String, String> parameters) {
-        return this.sign(this.getPayment(mode), parameters);
+    public String sign(@NonNull String type, @NonNull Map<String, String> parameters) {
+        return this.sign(this.getPayment(type), parameters);
     }
 
     @Override
-    public WechatUnifiedOrder unifiedorder(@NonNull PayMode mode, @NonNull WechatPayRequest request) {
+    public WechatUnifiedOrder unifiedorder(@NonNull String type, @NonNull WechatPayRequest request) {
         // 获取支付配置
-        WechatProperties.Payment payment = this.getPayment(mode);
+        WechatProperties.Payment payment = this.getPayment(type);
 
         // 构建请求参数
         Map<String, String> parameters = this.generatePaymentParameters(payment, request);
 
         // 如果是小程序支付则需要指定openid
-        if (mode == PayMode.JSAPI) {
+        if (payment.getMode() == PayMode.JSAPI) {
             parameters.put("openid", Objects.requireNonNull(request.getOpenid(), "openid unspecified"));
         }
 
@@ -412,8 +398,8 @@ public class DefaultWechatHandler implements WechatHandler {
         }
 
         // 构建微信统一下单信息
-        return WechatUnifiedOrder.builder().mode(mode).appid(result.get("appid")).mchid(result.get("mch_id"))
-                .nonce(result.get("nonce_str")).prepayid(result.get("prepay_id"))
+        return WechatUnifiedOrder.builder().mode(payment.getMode()).appid(result.get("appid"))
+                .mchid(result.get("mch_id")).nonce(result.get("nonce_str")).prepayid(result.get("prepay_id"))
                 .qrcode(result.get("code_url")).build();
     }
 }

+ 15 - 0
framework-wechat/src/main/java/com/chelvc/framework/wechat/DefaultWechatPublicHandler.java

@@ -63,6 +63,12 @@ public class DefaultWechatPublicHandler implements WechatPublicHandler {
      */
     private static final String USER_URL = "https://api.weixin.qq.com/cgi-bin/user/info/batchget?access_token=%s";
 
+    /**
+     * 获取微信网页令牌接口地址
+     */
+    private static final String CODE2TOKEN_URL = "https://api.weixin.qq.com/sns/oauth2/access_token" +
+            "?appid=%s&secret=%s&code=%s&grant_type=authorization_code";
+
     private final RestTemplate restTemplate;
     private final WechatHandler wechatHandler;
     private final WechatProperties.Public properties;
@@ -106,6 +112,15 @@ public class DefaultWechatPublicHandler implements WechatPublicHandler {
         return this.wechatHandler.refreshAccessToken(this.properties.getAppid(), this.properties.getSecret());
     }
 
+    @Override
+    public WechatWebToken code2token(@NonNull String code) {
+        String url = String.format(CODE2TOKEN_URL, this.properties.getAppid(), this.properties.getSecret(), code);
+        if (log.isDebugEnabled()) {
+            log.debug("Wechat request: {}", url);
+        }
+        return WechatUtils.execute(() -> this.restTemplate.getForObject(url, WechatWebToken.class));
+    }
+
     @Override
     public String decrypt(String ciphertext) {
         if (StringUtils.isEmpty(ciphertext)) {

+ 4 - 4
framework-wechat/src/main/java/com/chelvc/framework/wechat/WechatHandler.java

@@ -104,18 +104,18 @@ public interface WechatHandler {
     /**
      * 参数签名
      *
-     * @param mode       支付方式
+     * @param type       支付类型
      * @param parameters 签名参数
      * @return 签名信息
      */
-    String sign(PayMode mode, Map<String, String> parameters);
+    String sign(String type, Map<String, String> parameters);
 
     /**
      * 微信统一下单
      *
-     * @param mode    支付方式
+     * @param type    支付类型
      * @param request 支付请求参数
      * @return 微信统一下单信息
      */
-    WechatUnifiedOrder unifiedorder(PayMode mode, WechatPayRequest request);
+    WechatUnifiedOrder unifiedorder(String type, WechatPayRequest request);
 }

+ 8 - 0
framework-wechat/src/main/java/com/chelvc/framework/wechat/WechatPublicHandler.java

@@ -41,6 +41,14 @@ public interface WechatPublicHandler {
      */
     String refreshAccessToken();
 
+    /**
+     * 根据临时令牌获取微信令牌
+     *
+     * @param code 临时令牌
+     * @return 微信令牌
+     */
+    WechatWebToken code2token(String code);
+
     /**
      * 数据解密
      *

+ 56 - 0
framework-wechat/src/main/java/com/chelvc/framework/wechat/WechatWebToken.java

@@ -0,0 +1,56 @@
+package com.chelvc.framework.wechat;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+import lombok.AllArgsConstructor;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import lombok.NoArgsConstructor;
+import lombok.ToString;
+import lombok.experimental.SuperBuilder;
+
+/**
+ * 微信网页令牌
+ *
+ * @author Woody
+ * @date 2023/7/11
+ */
+@Data
+@SuperBuilder
+@NoArgsConstructor
+@AllArgsConstructor
+@ToString(callSuper = true)
+@EqualsAndHashCode(callSuper = true)
+public class WechatWebToken extends WechatResponse {
+    /**
+     * 用户授权的作用域,使用逗号(,)分隔
+     */
+    private String scope;
+
+    /**
+     * 用户唯一标识
+     */
+    private String openid;
+
+    /**
+     * 用户统一标识
+     */
+    private String unionid;
+
+    /**
+     * 访问令牌
+     */
+    @JsonProperty("access_token")
+    private String accessToken;
+
+    /**
+     * 刷新令牌
+     */
+    @JsonProperty("refresh_token")
+    private String refreshToken;
+
+    /**
+     * 访问令牌有效时长(秒)
+     */
+    @JsonProperty("expires_in")
+    private Long duration;
+}

+ 7 - 2
framework-wechat/src/main/java/com/chelvc/framework/wechat/config/WechatProperties.java

@@ -79,15 +79,20 @@ public class WechatProperties {
      */
     @Data
     public static class Payment {
+        /**
+         * 支付类型
+         */
+        private String type;
+
         /**
          * 支付方式
          */
         private PayMode mode;
 
         /**
-         * 支付ID
+         * AppID
          */
-        private String payid;
+        private String appid;
 
         /**
          * 商户标识