Răsfoiți Sursa

refactor(pay):优化微信支付分账与回调处理逻辑

-为避免重复处理,给微信退款回调方法添加可重入锁- 格式化代码空格和参数间距,提高代码整洁度
- 更新微信支付和退款通知接口地址至新域名
- 引入HashMap和ReentrantLock类以支持新增功能
- 修复字符串拼接中的空格问题,使描述更清晰
wzq 4 zile în urmă
părinte
comite
98bf713019

+ 4 - 3
national-motion-module-system/national-motion-system-biz/src/main/java/org/jeecg/modules/app/controller/OrderController.java

@@ -52,6 +52,7 @@ import java.io.IOException;
 import java.security.GeneralSecurityException;
 import java.text.ParseException;
 import java.util.Date;
+import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
 
@@ -85,7 +86,7 @@ public class OrderController {
     @Operation(summary = "学校场地预约-预览页")
     @GetMapping("/previewOrderPlaceSchool")
     public Result<OrderVO.PreviewOrderPlaceSchool> previewOrderPlaceSchool(@RequestParam("placeId") @Schema(description = "场地ID") String placeId,
-                                                                           @JsonFormat(timezone = "GMT+8",pattern = "yyyy-MM-dd")
+                                                                           @JsonFormat(timezone = "GMT+8", pattern = "yyyy-MM-dd")
                                                                            @DateTimeFormat(pattern = "yyyy-MM-dd")
                                                                            @RequestParam("startTime") @Schema(description = "当前选择日期(年月日)") Date startTime) {
         return Result.ok(appOrderService.previewOrderPlaceSchool(placeId, startTime));
@@ -180,7 +181,7 @@ public class OrderController {
     @Operation(summary = "订单-支付")
     @RepeatSubmit(serviceId = "payOrder", limitType = RepeatSubmit.Type.PARAM, lockTime = 3)
     @PutMapping("/payOrder")
-    public Result<UserPayForm> payOrder(@RequestParam("appOrderId") String appOrderId){
+    public Result<UserPayForm> payOrder(@RequestParam("appOrderId") String appOrderId) {
         return Result.ok(appOrderService.payOrder(appOrderId));
     }
 
@@ -255,7 +256,7 @@ public class OrderController {
      */
     @Operation(summary = "赛事订单退款")
     @GetMapping("/gameRefundOrder")
-    public Result<String> gameRefundOrder(@RequestParam(name = "orderCode", required = true) String orderCode,@RequestParam(name = "reason", required = true) String reason) {
+    public Result<String> gameRefundOrder(@RequestParam(name = "orderCode", required = true) String orderCode, @RequestParam(name = "reason", required = true) String reason) {
         return Result.OK(appOrderService.gameRefundOrder(orderCode, reason));
     }
 

+ 44 - 30
national-motion-module-system/national-motion-system-biz/src/main/java/org/jeecg/modules/pay/config/WeChatProfitSharingService.java

@@ -33,6 +33,7 @@ import java.security.InvalidKeyException;
 import java.security.NoSuchAlgorithmException;
 import java.security.cert.*;
 import java.util.*;
+import java.util.concurrent.locks.ReentrantLock;
 import java.util.stream.Collectors;
 
 import static java.lang.Thread.sleep;
@@ -57,6 +58,10 @@ public class WeChatProfitSharingService {
     private AppProfitSharingInfoMapper appProfitSharingInfoMapper;
     @Resource
     private ShopMoneyMapper shopMoneyMapper;
+
+    // 声明一个可重入锁
+    private final ReentrantLock lock = new ReentrantLock();
+
     /**
      * 添加分账接收方
      *
@@ -90,7 +95,7 @@ public class WeChatProfitSharingService {
                 "limit 1"));
         List<AppOrderProInfo> orderProInfoList = appOrderProInfoMapper.selectList(Wrappers.lambdaQuery(AppOrderProInfo.class).eq(AppOrderProInfo::getOrderId, appOrder.getId()).eq(AppOrderProInfo::getType, CommonConstant.ORDER_PRO_INFO_TYPE_6));
         BigDecimal insurePrice = BigDecimal.ZERO;
-        if (CollUtil.isNotEmpty(orderProInfoList)){
+        if (CollUtil.isNotEmpty(orderProInfoList)) {
             BigDecimal reduce = orderProInfoList.stream().map(AppOrderProInfo::getPrice).reduce(BigDecimal.ZERO, BigDecimal::add);
             insurePrice = insurePrice.add(reduce);
         }
@@ -119,7 +124,7 @@ public class WeChatProfitSharingService {
         List<Receiver> receivers = new ArrayList<>();
         //查询当前订单的分账接收方列表
         for (AppProfitSharingInfo receiverRecord : partyFunding) {
-            if (receiverRecord.getPreAmount() != 0){
+            if (receiverRecord.getPreAmount() != 0) {
                 Receiver receiver = new Receiver();
                 receiver.setType("MERCHANT_ID")
                         .setAccount(receiverRecord.getMchId())
@@ -187,7 +192,8 @@ public class WeChatProfitSharingService {
                     //List<WechatReceiver> wechatReceivers = (List<WechatReceiver>) res.get("receivers");
                     Gson gson = new Gson();
                     // 定义目标类型的TypeToken
-                    Type receiverListType = new TypeToken<List<WechatReceiver>>() {}.getType();
+                    Type receiverListType = new TypeToken<List<WechatReceiver>>() {
+                    }.getType();
                     // 转换
                     List<WechatReceiver> wechatReceivers = gson.fromJson(
                             // 将receivers转为JSON字符串
@@ -222,12 +228,12 @@ public class WeChatProfitSharingService {
      * @return JSONObject
      * @throws Exception
      */
-    public JSONObject profitSharings(String orderCode,String s) throws Exception {
+    public JSONObject profitSharings(String orderCode, String s) throws Exception {
         AppOrder appOrder = appOrderMapper.selectOne(Wrappers.lambdaQuery(AppOrder.class).eq(AppOrder::getOrderCode, orderCode).last(
                 "limit 1"));
         List<AppOrderProInfo> orderProInfoList = appOrderProInfoMapper.selectList(Wrappers.lambdaQuery(AppOrderProInfo.class).eq(AppOrderProInfo::getOrderId, appOrder.getId()).eq(AppOrderProInfo::getType, CommonConstant.ORDER_PRO_INFO_TYPE_6));
         BigDecimal insurePrice = BigDecimal.ZERO;
-        if (CollUtil.isNotEmpty(orderProInfoList)){
+        if (CollUtil.isNotEmpty(orderProInfoList)) {
             BigDecimal reduce = orderProInfoList.stream().map(AppOrderProInfo::getPrice).reduce(BigDecimal.ZERO, BigDecimal::add);
             insurePrice = insurePrice.add(reduce);
         }
@@ -256,7 +262,7 @@ public class WeChatProfitSharingService {
         List<Receiver> receivers = new ArrayList<>();
         //查询当前订单的分账接收方列表
         for (AppProfitSharingInfo receiverRecord : partyFunding) {
-            if (receiverRecord.getPreAmount() != 0){
+            if (receiverRecord.getPreAmount() != 0) {
                 Receiver receiver = new Receiver();
                 receiver.setType("MERCHANT_ID")
                         .setAccount(receiverRecord.getMchId())
@@ -310,7 +316,8 @@ public class WeChatProfitSharingService {
                     //List<WechatReceiver> wechatReceivers = (List<WechatReceiver>) res.get("receivers");
                     Gson gson = new Gson();
                     // 定义目标类型的TypeToken
-                    Type receiverListType = new TypeToken<List<WechatReceiver>>() {}.getType();
+                    Type receiverListType = new TypeToken<List<WechatReceiver>>() {
+                    }.getType();
                     // 转换
                     List<WechatReceiver> wechatReceivers = gson.fromJson(
                             gson.toJson(res.get("receivers")), // 将receivers转为JSON字符串
@@ -387,7 +394,8 @@ public class WeChatProfitSharingService {
                 if (ObjectUtil.isNotEmpty(res.get("receivers"))) {
                     Gson gson = new Gson();
                     // 定义目标类型的TypeToken
-                    Type receiverListType = new TypeToken<List<WechatReceiver>>() {}.getType();
+                    Type receiverListType = new TypeToken<List<WechatReceiver>>() {
+                    }.getType();
                     // 转换
                     List<WechatReceiver> wechatReceivers = gson.fromJson(
                             // 将receivers转为JSON字符串
@@ -438,7 +446,7 @@ public class WeChatProfitSharingService {
             map.put("out_return_no", "T" + orderCode);
             map.put("return_mchid", receiverRecord.getMchId());
             map.put("amount", receiverRecord.getAmount());
-            map.put("description", receiverRecord.getMchName() +"分账订单:"+ orderCode + "退还金额:" + receiverRecord.getAmount());
+            map.put("description", receiverRecord.getMchName() + "分账订单:" + orderCode + "退还金额:" + receiverRecord.getAmount());
 
             try {
                 JSONObject res = wechatPayV3Utils.sendPost(WechatUrlConstants.PAY_V3_RETURN_ORDER, JSONObject.from(map));
@@ -483,31 +491,37 @@ public class WeChatProfitSharingService {
     public Map<String, Object> wxPayRefundCallback(HttpServletRequest request, HttpServletResponse response, WechatRefundCallback refundCallback) {
 
         Map<String, Object> result = new HashMap<>();
-        // 2.签名验证
-        //验签及解析返回数据
-        JSONObject res = wechatPayV3Utils.getCallbackData(request);
-        if (res == null) {
+        if (lock.tryLock()) {
+            // 2.签名验证
+            //验签及解析返回数据
+            JSONObject res = wechatPayV3Utils.getCallbackData(request);
+            if (res == null) {
+                result.put("code", "FAIL");
+                result.put("message", "失败");
+                return result;
+            }
+            log.info("最终拿到的微信支付通知数据:" + res);
+
+            // 4.封装微信返回的数据
+            WechatCallbackRefundData refundData = getRefundCallbackData(res);
+            if ("SUCCESS".equals(refundData.getStatus())) {
+                // 执行业务逻辑
+                refundCallback.success(refundData);
+            } else {
+                // 特殊情况退款失败业务处理,退款到银行发现用户的卡作废或者冻结了,导致原路退款银行卡失败,可前往商户平台-交易中心,手动处理此笔退款
+                refundCallback.fail(refundData);
+            }
+
+            // 5.成功应答
+            response.setStatus(200);
+            result.put("code", "SUCCESS");
+            result.put("message", "成功");
+            return result;
+        } else {
             result.put("code", "FAIL");
             result.put("message", "失败");
             return result;
         }
-        log.info("最终拿到的微信支付通知数据:" + res);
-
-        // 4.封装微信返回的数据
-        WechatCallbackRefundData refundData = getRefundCallbackData(res);
-        if ("SUCCESS".equals(refundData.getStatus())) {
-            // 执行业务逻辑
-            refundCallback.success(refundData);
-        } else {
-            // 特殊情况退款失败业务处理,退款到银行发现用户的卡作废或者冻结了,导致原路退款银行卡失败,可前往商户平台-交易中心,手动处理此笔退款
-            refundCallback.fail(refundData);
-        }
-
-        // 5.成功应答
-        response.setStatus(200);
-        result.put("code", "SUCCESS");
-        result.put("message", "成功");
-        return result;
     }
 
     private static WechatCallbackRefundData getRefundCallbackData(JSONObject res) {

+ 4 - 2
national-motion-module-system/national-motion-system-biz/src/main/java/org/jeecg/modules/pay/config/WechatUrlConstants.java

@@ -17,10 +17,12 @@ public class WechatUrlConstants {
     public final static String PAY_V3_QUERY_OUT = "https://api.mch.weixin.qq.com/v3/pay/partner/transactions/out-trade-no/{out_trade_no}";
 
     //微信支付v3 支付通知接口地址
-    public final static String PAY_V3_NOTIFY = "https://admin.qlapp.cn/jeecgboot/app/order/wechatPayNotify";
+//    public final static String PAY_V3_NOTIFY = "https://admin.qlapp.cn/jeecgboot/app/order/wechatPayNotify";
+    public final static String PAY_V3_NOTIFY = "https://60deed35.r28.cpolar.top/jeecg-boot/app/order/wechatPayNotify";
 
     //微信支付v3 退款通知接口地址
-    public final static String PAY_V3_REFUND_NOTIFY = "https://admin.qlapp.cn/jeecgboot/app/order/callback/refundOrderNotify";
+//    public final static String PAY_V3_REFUND_NOTIFY = "https://admin.qlapp.cn/jeecgboot/app/order/callback/refundOrderNotify";
+    public final static String PAY_V3_REFUND_NOTIFY = "https://60deed35.r28.cpolar.top/jeecg-boot/app/order/callback/refundOrderNotify";
 
     //服务商 添加分账接收方
     public final static String PAY_V3_RECEIVERS_ADD = "https://api.mch.weixin.qq.com/v3/profitsharing/receivers/add";