From 8444084e6aa11efa23287e7f82474ac22378a5c4 Mon Sep 17 00:00:00 2001
From: Pu Zhibing <393733352@qq.com>
Date: 星期二, 01 四月 2025 16:03:19 +0800
Subject: [PATCH] Merge remote-tracking branch 'origin/master'

---
 ruoyi-modules/ruoyi-order/src/main/java/com/ruoyi/order/controller/miniapp/NotifyController.java |  201 ++++++++++++++++++++++++++++++++++++++++++--------
 1 files changed, 169 insertions(+), 32 deletions(-)

diff --git a/ruoyi-modules/ruoyi-order/src/main/java/com/ruoyi/order/controller/miniapp/NotifyController.java b/ruoyi-modules/ruoyi-order/src/main/java/com/ruoyi/order/controller/miniapp/NotifyController.java
index 921b532..6574ab5 100644
--- a/ruoyi-modules/ruoyi-order/src/main/java/com/ruoyi/order/controller/miniapp/NotifyController.java
+++ b/ruoyi-modules/ruoyi-order/src/main/java/com/ruoyi/order/controller/miniapp/NotifyController.java
@@ -1,5 +1,6 @@
 package com.ruoyi.order.controller.miniapp;
 
+import com.alibaba.fastjson.JSONObject;
 import com.github.binarywang.wxpay.bean.ecommerce.*;
 import com.github.binarywang.wxpay.bean.notify.WxPayNotifyV3Response;
 import com.github.binarywang.wxpay.bean.profitsharingV3.ProfitSharingNotifyData;
@@ -11,13 +12,25 @@
 import com.github.binarywang.wxpay.v3.util.AesUtils;
 import com.google.gson.Gson;
 import com.google.gson.GsonBuilder;
+import com.ruoyi.common.core.domain.R;
 import com.ruoyi.common.core.web.controller.BaseController;
+import com.ruoyi.common.redis.service.RedisService;
+import com.ruoyi.order.domain.dto.WechatPaymentRefundDto;
+import com.ruoyi.order.domain.dto.WeixinPaymentNotifyDto;
+import com.ruoyi.order.domain.pojo.account.OrderRefund;
 import com.ruoyi.order.domain.vo.ProfitSharingNotifyNewResult;
+import com.ruoyi.order.domain.vo.WeixinPaymentNotifyVo;
+import com.ruoyi.order.domain.vo.WeixinPaymentRefundVo;
+import com.ruoyi.order.enums.RefundStatusEnum;
 import com.ruoyi.order.enums.WxPayNotifyEventTypeEnum;
+import com.ruoyi.order.enums.dict.IDict;
 import com.ruoyi.order.service.account.BackMessageService;
+import com.ruoyi.order.service.account.OrderRefundService;
 import com.ruoyi.order.service.order.OrderService;
+import com.ruoyi.order.util.HuiFuTianXiaUtil;
 import io.swagger.annotations.Api;
 import io.swagger.annotations.ApiOperation;
+import lombok.extern.log4j.Log4j2;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.web.bind.annotation.*;
 
@@ -25,10 +38,15 @@
 import javax.servlet.http.HttpServletRequest;
 import javax.servlet.http.HttpServletResponse;
 import java.io.IOException;
+import java.io.PrintWriter;
+import java.math.BigDecimal;
 import java.nio.charset.StandardCharsets;
 import java.security.GeneralSecurityException;
+import java.util.Collection;
+import java.util.Enumeration;
 import java.util.Map;
 import java.util.Objects;
+import java.util.concurrent.TimeUnit;
 
 /**
  * @program: ruoyi
@@ -39,6 +57,7 @@
 @Api(value = "微信通知控制", tags = "微信通知控制", description = "微信通知控制")
 @RestController
 @RequestMapping("/app/notify")
+@Log4j2
 public class NotifyController extends BaseController {
 
     public static final String WECHAT_PAY_SERIAL = "Wechatpay-Serial";
@@ -56,39 +75,52 @@
     @Resource
     private BackMessageService backMessageService;
 
+    @Resource
+    private OrderRefundService orderRefundService;
+
+    @Resource
+    private RedisService redisService;
+
     @PostMapping(value = "/payNotify")
     @ApiOperation(value = "微信支付/退款通知")
     public String payNotify(@RequestBody String notifyData, HttpServletRequest request, HttpServletResponse response) throws WxPayException {
 
         // 获取请求头
-        SignatureHeader signatureHeader = getSignatureHeader(response);
+        SignatureHeader signatureHeader = getSignatureHeader(request);
+
+        log.info("微信支付/退款通知:  {}", notifyData);
 
         NotifyResponse responseData = GSON.fromJson(notifyData, NotifyResponse.class);
         String eventType = responseData.getEventType();
 
         int resultType = 1;
-        String resultMessage = "";
-        if(WxPayNotifyEventTypeEnum.TRANSACTION_SUCCESS.getCode().equals(eventType)){
-            PartnerTransactionsNotifyResult notifyResult = wxService.getEcommerceService().parsePartnerNotifyResult(notifyData, signatureHeader);
-            PartnerTransactionsResult result = notifyResult.getResult();
-            // 支付通知回调
-            if("SUCCESS".equals(result.getTradeState())){
-                orderService.payBack(result);
-            }
-            resultMessage = GSON.toJson(notifyResult);
-        } else if(WxPayNotifyEventTypeEnum.REFUND_SUCCESS.getCode().equals(eventType)
-            || WxPayNotifyEventTypeEnum.REFUND_ABNORMAL.getCode().equals(eventType)
-            || WxPayNotifyEventTypeEnum.REFUND_CLOSED.getCode().equals(eventType)){
+        String resultMessage = notifyData;
 
-            RefundNotifyResult result = wxService.getEcommerceService().parseRefundNotifyResult(notifyData, signatureHeader);
-            orderService.orderRefundBack(result);
-            resultType = 2;
-            resultMessage = GSON.toJson(result);
+        try {
+            if (WxPayNotifyEventTypeEnum.TRANSACTION_SUCCESS.getCode().equals(eventType)) {
+                PartnerTransactionsNotifyResult notifyResult = wxService.getEcommerceService().parsePartnerNotifyResult(notifyData, signatureHeader);
+                PartnerTransactionsResult result = notifyResult.getResult();
+                // 支付通知回调
+                if ("SUCCESS".equals(result.getTradeState())) {
+                    orderService.payBack(result, BigDecimal.ONE);
+                }
+                resultMessage = GSON.toJson(notifyResult);
+            } else if (WxPayNotifyEventTypeEnum.REFUND_SUCCESS.getCode().equals(eventType)
+                    || WxPayNotifyEventTypeEnum.REFUND_ABNORMAL.getCode().equals(eventType)
+                    || WxPayNotifyEventTypeEnum.REFUND_CLOSED.getCode().equals(eventType)) {
+
+                RefundNotifyResult result = this.parseRefundNotifyResult(notifyData, signatureHeader);
+                orderService.orderRefundBack(result);
+                resultType = 2;
+                resultMessage = GSON.toJson(result);
+            }
+
+        }catch (Exception e){
+            e.printStackTrace();
+            log.info("微信支付/退款通知异常:  {}", e.getMessage());
         }
         // 保存支付/退款回调信息
         backMessageService.saveBackMessage(resultType, resultMessage);
-
-
         return WxPayNotifyV3Response.success("成功");
     }
 
@@ -97,21 +129,26 @@
     public String profitSharingNotify(@RequestBody String notifyData, HttpServletRequest request, HttpServletResponse response) throws WxPayException {
         ProfitSharingV3Service sharingV3Service = wxService.getProfitSharingV3Service();
         // ProfitSharingNotifyResult
+        log.info("微信分账通知:  {}", notifyData);
 
         // 获取请求头
-        SignatureHeader signatureHeader = getSignatureHeader(response);
-
+        SignatureHeader signatureHeader = getSignatureHeader(request);
 
         ProfitSharingNotifyNewResult notifyResult = getProfitSharingNotifyData(notifyData, signatureHeader);
         ProfitSharingNotifyResult result = notifyResult.getResult();
+        String eventType = "-1";
+        String resultMessage = notifyData;
+        try {
+            eventType = notifyResult.getRawData().getEventType();
+            if (WxPayNotifyEventTypeEnum.PROFIT_SHARING_SUCCESS.getCode().equals(eventType)) {
+                // 分账通知回调
+                orderService.profitSharingBack(result);
+            }
 
-        String eventType = notifyResult.getRawData().getEventType();
-        if(WxPayNotifyEventTypeEnum.PROFIT_SHARING_SUCCESS.getCode().equals(eventType)){
-            // 分账通知回调
-            orderService.profitSharingBack(result);
+            resultMessage = GSON.toJson(notifyResult);
+        }catch (Exception e){
+            log.info("微信分账通知通知异常:  {}", e.getMessage());
         }
-
-        String resultMessage = GSON.toJson(notifyResult);
         // 保存记录分账回调信息
         backMessageService.saveBackMessage(3, resultMessage);
 
@@ -149,6 +186,24 @@
         }
     }
 
+    private RefundNotifyResult parseRefundNotifyResult(String notifyData, SignatureHeader header) throws WxPayException {
+
+        NotifyResponse response = GSON.fromJson(notifyData, NotifyResponse.class);
+        NotifyResponse.Resource resource = response.getResource();
+        String cipherText = resource.getCiphertext();
+        String associatedData = resource.getAssociatedData();
+        String nonce = resource.getNonce();
+        String apiV3Key = this.wxService.getConfig().getApiV3Key();
+        try {
+            String result = AesUtils.decryptToString(associatedData, nonce, cipherText, apiV3Key);
+            RefundNotifyResult notifyResult = GSON.fromJson(result, RefundNotifyResult.class);
+            notifyResult.setRawData(response);
+            return notifyResult;
+        } catch (GeneralSecurityException | IOException e) {
+            throw new WxPayException("解析报文异常!", e);
+        }
+    }
+
     private boolean verifyNotifySign(SignatureHeader header, String data) throws WxPayException {
         String beforeSign = String.format("%s\n%s\n%s\n",
                 header.getTimeStamp(),
@@ -162,12 +217,94 @@
                 beforeSign.getBytes(StandardCharsets.UTF_8), header.getSigned());
     }
 
-    private SignatureHeader getSignatureHeader(HttpServletResponse response){
+    private SignatureHeader getSignatureHeader(HttpServletRequest request){
         SignatureHeader signatureHeader = new SignatureHeader();
-        signatureHeader.setSerialNo(response.getHeader(WECHAT_PAY_SERIAL));
-        signatureHeader.setSigned(response.getHeader(WECHAT_PAY_SIGNATURE));
-        signatureHeader.setNonce(response.getHeader(WECHAT_PAY_NONCE));
-        signatureHeader.setTimeStamp(response.getHeader(WECHAT_PAY_TIMESTAMP));
+        signatureHeader.setSerialNo(request.getHeader(WECHAT_PAY_SERIAL));
+        signatureHeader.setSigned(request.getHeader(WECHAT_PAY_SIGNATURE));
+        signatureHeader.setNonce(request.getHeader(WECHAT_PAY_NONCE));
+        signatureHeader.setTimeStamp(request.getHeader(WECHAT_PAY_TIMESTAMP));
+
+        log.info("timeStamp:{}   nonce : {}   signed:{}  serialNo:{}",
+                signatureHeader.getTimeStamp(),
+                signatureHeader.getNonce(),
+                signatureHeader.getSigned(),
+                signatureHeader.getSerialNo());
+
         return signatureHeader;
     }
+
+
+
+    @RequestMapping(value = "/wechatPaymentCallback", method = RequestMethod.POST)
+    @ApiOperation(value = "微信支付通知(汇付天下)")
+    public void wechatPaymentCallback(WeixinPaymentNotifyDto dto, HttpServletResponse response){
+        R<WeixinPaymentNotifyVo> r = HuiFuTianXiaUtil.weixinPaymentNotify(dto);
+        if(r.getCode() == 200){
+            WeixinPaymentNotifyVo data = r.getData();
+            String transStat = data.getTransStat();
+            if("S".equals(transStat)){
+                PartnerTransactionsResult transaction = new PartnerTransactionsResult();
+                transaction.setOutTradeNo(data.getReqSeqId());
+
+                //防止回调频繁导致时间处理异常
+                Object cacheObject = redisService.getCacheObject(data.getReqSeqId());
+                if(null == cacheObject){
+                    redisService.setCacheObject(data.getReqSeqId(), "", 10L, TimeUnit.SECONDS);
+                }else{
+                    return;
+                }
+                //开始处理业务数据
+                orderService.payBack(transaction, data.getFeeFlag() == 1 ? BigDecimal.ZERO : new BigDecimal(data.getFeeAmount()));
+
+                response.setStatus(200);
+                PrintWriter out = null;
+                try {
+                    out = response.getWriter();
+                    out.print("RECV_ORD_ID_" + data.getReqSeqId());
+                    out.flush();
+                } catch (IOException e) {
+                    e.printStackTrace();
+                }finally {
+                    out.close();
+                }
+
+            }
+        }
+    }
+
+
+
+    @RequestMapping(value = "/wechatPaymentRefundCallback", method = RequestMethod.POST)
+    @ApiOperation(value = "微信支付退款通知(汇付天下)")
+    public void wechatPaymentRefundCallback(WechatPaymentRefundDto dto, HttpServletResponse response){
+        R<WeixinPaymentRefundVo> r = HuiFuTianXiaUtil.weixinPaymentRefundNotify(dto);
+        if(r.getCode() == 200){
+            WeixinPaymentRefundVo data = r.getData();
+            String transStat = data.getTransStat();
+            if("S".equals(transStat)){
+                //开始处理业务数据
+                String reqSeqId = data.getReqSeqId();
+                OrderRefund orderRefund = orderRefundService.getById(reqSeqId);
+                if(null != orderRefund && orderRefund.getRefundStatus() != 2){
+                    orderRefund.setWxRefundId(data.getPartyOrderId());
+                    orderRefund.setBackTime(data.getTransDate() + data.getTransTime());
+                    orderRefund.setRefundStatus(2);
+                    orderRefundService.saveOrUpdate(orderRefund);
+                }
+
+                response.setStatus(200);
+                PrintWriter out = null;
+                try {
+                    out = response.getWriter();
+                    out.print("RECV_ORD_ID_" + data.getReqSeqId());
+                    out.flush();
+                } catch (IOException e) {
+                    e.printStackTrace();
+                }finally {
+                    out.close();
+                }
+
+            }
+        }
+    }
 }

--
Gitblit v1.7.1