From beeda8df0023376dbb2021148a021731dc4aedb0 Mon Sep 17 00:00:00 2001
From: jiangqs <jiangqs>
Date: 星期日, 06 八月 2023 11:29:10 +0800
Subject: [PATCH] Merge branch 'master' of ssh://sinata.cn:20202/java/HongRuiTang into master

---
 ruoyi-modules/ruoyi-order/src/main/java/com/ruoyi/order/controller/miniapp/NotifyController.java |  219 +++++++++++++++++++++++++++++++-----------------------
 1 files changed, 127 insertions(+), 92 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 5dc6de6..775d9da 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,38 +1,34 @@
 package com.ruoyi.order.controller.miniapp;
 
-import com.ruoyi.common.core.domain.R;
+import com.github.binarywang.wxpay.bean.ecommerce.*;
+import com.github.binarywang.wxpay.bean.notify.WxPayNotifyV3Response;
+import com.github.binarywang.wxpay.bean.profitsharingV3.ProfitSharingNotifyData;
+import com.github.binarywang.wxpay.bean.profitsharingV3.ProfitSharingNotifyResult;
+import com.github.binarywang.wxpay.exception.WxPayException;
+import com.github.binarywang.wxpay.service.ProfitSharingV3Service;
+import com.github.binarywang.wxpay.service.WxPayService;
+import com.github.binarywang.wxpay.v3.auth.Verifier;
+import com.github.binarywang.wxpay.v3.util.AesUtils;
+import com.google.gson.Gson;
+import com.google.gson.GsonBuilder;
 import com.ruoyi.common.core.web.controller.BaseController;
-import com.ruoyi.order.domain.dto.AppSureOrderDto;
-import com.ruoyi.order.domain.dto.WXPayNotifyDto;
-import com.ruoyi.order.domain.vo.AppSureOrderVo;
+import com.ruoyi.order.domain.vo.ProfitSharingNotifyNewResult;
+import com.ruoyi.order.enums.WxPayNotifyEventTypeEnum;
+import com.ruoyi.order.service.account.BackMessageService;
 import com.ruoyi.order.service.order.OrderService;
-import com.wechat.pay.contrib.apache.httpclient.notification.Notification;
-import com.wechat.pay.contrib.apache.httpclient.notification.NotificationHandler;
-import com.wechat.pay.contrib.apache.httpclient.notification.NotificationRequest;
-import com.wechat.pay.java.core.Config;
-import com.wechat.pay.java.core.RSAAutoCertificateConfig;
-import com.wechat.pay.java.core.RSAConfig;
-import com.wechat.pay.java.core.cipher.PrivacyEncryptor;
-import com.wechat.pay.java.core.notification.NotificationConfig;
-import com.wechat.pay.java.core.notification.NotificationParser;
-import com.wechat.pay.java.core.notification.RequestParam;
-import com.wechat.pay.java.service.partnerpayments.jsapi.model.Transaction;
 import io.swagger.annotations.Api;
 import io.swagger.annotations.ApiOperation;
-import net.bytebuddy.asm.Advice;
-import org.springframework.web.bind.annotation.RequestBody;
-import org.springframework.web.bind.annotation.RequestMapping;
-import org.springframework.web.bind.annotation.RequestMethod;
-import org.springframework.web.bind.annotation.RestController;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.*;
 
 import javax.annotation.Resource;
 import javax.servlet.http.HttpServletRequest;
 import javax.servlet.http.HttpServletResponse;
-import java.io.BufferedReader;
 import java.io.IOException;
 import java.nio.charset.StandardCharsets;
-import java.util.HashMap;
+import java.security.GeneralSecurityException;
 import java.util.Map;
+import java.util.Objects;
 
 /**
  * @program: ruoyi
@@ -44,88 +40,82 @@
 @RestController
 @RequestMapping("/app/notify")
 public class NotifyController extends BaseController {
-    /** 商户号 */
-    public static String merchantId = "";
-    /** 商户API私钥路径 */
-    public static String privateKeyPath = "";
-    /** 商户证书序列号 */
-    public static String merchantSerialNumber = "";
-    /** 微信支付平台证书路径 */
-    public static String wechatPayCertificatePath = "";
-    /** 商户APIV3密钥 */
-    public static String apiV3key = "...";
+
+    public static final String WECHAT_PAY_SERIAL = "Wechatpay-Serial";
+    public static final String WECHAT_PAY_SIGNATURE = "Wechatpay-Signature";
+    public static final String WECHAT_PAY_TIMESTAMP = "Wechatpay-Timestamp";
+    public static final String WECHAT_PAY_NONCE = "Wechatpay-Nonce";
+
+    private static final Gson GSON = new GsonBuilder().create();
 
     @Resource
     private OrderService orderService;
 
-    @RequestMapping(value = "/payNotify", method = RequestMethod.POST)
-    @ApiOperation(value = "微信支付通知")
-    public Map payNotify(HttpServletRequest request, HttpServletResponse response) {
-        Config config =
-                new RSAConfig.Builder()
-                        .merchantId(merchantId)
-                        .privateKeyFromPath(privateKeyPath)
-                        .merchantSerialNumber(merchantSerialNumber)
-                        .wechatPayCertificatesFromPath(wechatPayCertificatePath)
-                        .build();
+    @Autowired
+    private WxPayService wxService;
+    @Resource
+    private BackMessageService backMessageService;
 
-        PrivacyEncryptor encryptor = config.createEncryptor();
-        String wechatPayCertificateSerialNumber = encryptor.getWechatpaySerial();
+    @PostMapping(value = "/payNotify")
+    @ApiOperation(value = "微信支付/退款通知")
+    public String payNotify(@RequestBody String notifyData, HttpServletRequest request, HttpServletResponse response) throws WxPayException {
 
+        // 获取请求头
+        SignatureHeader signatureHeader = getSignatureHeader(response);
 
-        String nonoc=request.getHeader("Wechatpay-Nonce");
-        String signature=request.getHeader("Wechatpay-Signature");
-        String timestamp=request.getHeader("Wechatpay-Timestamp");
-        String serial=request.getHeader("Wechatpay-Serial");
-        String signatureType=request.getHeader("Wechatpay-Signature-Type");
+        NotifyResponse responseData = GSON.fromJson(notifyData, NotifyResponse.class);
+        String eventType = responseData.getEventType();
 
-        String requestBody="";
-
-        try {
-            BufferedReader reader = request.getReader();
-            String line = "";
-            StringBuffer inputString = new StringBuffer();
-            while ( (line = reader.readLine()) != null ) {
-                inputString.append(line);
+        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);
             }
-            if(inputString!=null && !"".equals(inputString)) {
-                requestBody = inputString.toString();
-            }
-            reader.close();
-        } catch (IOException e) {
-            e.printStackTrace();
+            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 = wxService.getEcommerceService().parseRefundNotifyResult(notifyData, signatureHeader);
+            orderService.orderRefundBack(result);
+            resultType = 2;
+            resultMessage = GSON.toJson(result);
+        }
+        // 保存支付/退款回调信息
+        backMessageService.saveBackMessage(resultType, resultMessage);
+
+
+        return WxPayNotifyV3Response.success("成功");
+    }
+
+    @PostMapping(value = "/profitSharingNotify")
+    @ApiOperation(value = "微信分账通知")
+    public String profitSharingNotify(@RequestBody String notifyData, HttpServletRequest request, HttpServletResponse response) throws WxPayException {
+        ProfitSharingV3Service sharingV3Service = wxService.getProfitSharingV3Service();
+        // ProfitSharingNotifyResult
+
+        // 获取请求头
+        SignatureHeader signatureHeader = getSignatureHeader(response);
+
+
+        ProfitSharingNotifyNewResult notifyResult = getProfitSharingNotifyData(notifyData, signatureHeader);
+        ProfitSharingNotifyResult result = notifyResult.getResult();
+
+        String eventType = notifyResult.getRawData().getEventType();
+        if(WxPayNotifyEventTypeEnum.PROFIT_SHARING_SUCCESS.getCode().equals(eventType)){
+            // 分账通知回调
+            orderService.profitSharingBack(result);
         }
 
-        RequestParam requestParam = new RequestParam.Builder()
-                .serialNumber(wechatPayCertificateSerialNumber)
-                .nonce(nonoc)
-                .signature(signature)
-                .timestamp(timestamp)
-                .body(requestBody)
-                .build();
+        String resultMessage = GSON.toJson(notifyResult);
+        // 保存记录分账回调信息
+        backMessageService.saveBackMessage(3, resultMessage);
 
-        NotificationConfig notifiConfig = new RSAAutoCertificateConfig.Builder()
-                .merchantId(merchantId)
-                .privateKeyFromPath(privateKeyPath)
-                .merchantSerialNumber(merchantSerialNumber)
-                .apiV3Key(apiV3key)
-                .build();
-
-        NotificationParser parser = new NotificationParser(notifiConfig);
-
-        Transaction transaction = parser.parse(requestParam, Transaction.class);
-
-
-        String tradeStateEnum=transaction.getTradeState().toString();
-        if(tradeStateEnum.equals("success")){
-            orderService.payBack(transaction);
-        }
-
-        Map map=new HashMap();
-        map.put("code","SUCCESS");
-        map.put("message","成功");
-
-        return map;
+        return WxPayNotifyV3Response.success("成功");
     }
 
     @RequestMapping(value = "/shareNotify", method = RequestMethod.POST)
@@ -135,4 +125,49 @@
         return null;
     }
 
+    public ProfitSharingNotifyNewResult getProfitSharingNotifyData(String notifyData, SignatureHeader header) throws WxPayException {
+        if (Objects.nonNull(header) && !this.verifyNotifySign(header, notifyData)) {
+            throw new WxPayException("非法请求,头部信息验证失败");
+        }
+        ProfitSharingNotifyData response = GSON.fromJson(notifyData, ProfitSharingNotifyData.class);
+
+        ProfitSharingNotifyData.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);
+            ProfitSharingNotifyResult profitSharingResult = GSON.fromJson(result, ProfitSharingNotifyResult.class);
+
+            ProfitSharingNotifyNewResult notifyResult = new ProfitSharingNotifyNewResult();
+            notifyResult.setRawData(response);
+            notifyResult.setResult(profitSharingResult);
+            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(),
+                header.getNonce(),
+                data);
+        Verifier verifier = this.wxService.getConfig().getVerifier();
+        if (verifier == null) {
+            throw new WxPayException("证书检验对象为空");
+        }
+        return verifier.verify(header.getSerialNo(),
+                beforeSign.getBytes(StandardCharsets.UTF_8), header.getSigned());
+    }
+
+    private SignatureHeader getSignatureHeader(HttpServletResponse response){
+        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));
+        return signatureHeader;
+    }
 }

--
Gitblit v1.7.1