From 03dd384bb8b78f04eadcf619849b3687fa98c6c1 Mon Sep 17 00:00:00 2001
From: zhanglin <852614290@qq.com>
Date: 星期六, 22 七月 2023 18:19:47 +0800
Subject: [PATCH] 微信支付,支付与结果通知

---
 ruoyi-modules/ruoyi-order/src/main/java/com/ruoyi/order/controller/miniapp/NotifyController.java |  132 ++++++++++++++++++++++
 ruoyi-modules/ruoyi-order/src/main/java/com/ruoyi/order/domain/dto/WXPayNotifyDto.java           |   19 +++
 ruoyi-modules/ruoyi-order/src/main/java/com/ruoyi/order/service/impl/order/OrderServiceImpl.java |  133 ++++++++++++++++++++++
 ruoyi-modules/ruoyi-order/src/main/java/com/ruoyi/order/domain/dto/WXPayNotifyResourceDto.java   |   14 ++
 ruoyi-modules/ruoyi-order/pom.xml                                                                |    6 +
 5 files changed, 304 insertions(+), 0 deletions(-)

diff --git a/ruoyi-modules/ruoyi-order/pom.xml b/ruoyi-modules/ruoyi-order/pom.xml
index de0540b..09bad0d 100644
--- a/ruoyi-modules/ruoyi-order/pom.xml
+++ b/ruoyi-modules/ruoyi-order/pom.xml
@@ -114,6 +114,12 @@
             <version>0.4.9</version>
         </dependency>
 
+        <dependency>
+            <groupId>com.github.wechatpay-apiv3</groupId>
+            <artifactId>wechatpay-java</artifactId>
+            <version>0.2.10</version>
+        </dependency>
+
         <!-- 爬虫工具,抓取和解析html https://mvnrepository.com/artifact/org.jsoup/jsoup -->
         <dependency>
             <groupId>org.jsoup</groupId>
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
new file mode 100644
index 0000000..f885ddf
--- /dev/null
+++ b/ruoyi-modules/ruoyi-order/src/main/java/com/ruoyi/order/controller/miniapp/NotifyController.java
@@ -0,0 +1,132 @@
+package com.ruoyi.order.controller.miniapp;
+
+import com.ruoyi.common.core.domain.R;
+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.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 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.util.Map;
+
+/**
+ * @program: ruoyi
+ * @author: linqingsong
+ * @create: 2023-07-22 17:20
+ * @description: 成都软思同创科技有限公司
+ **/
+@Api(value = "微信通知控制", tags = "微信通知控制", description = "微信通知控制")
+@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 = "...";
+
+    @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();
+
+        PrivacyEncryptor encryptor = config.createEncryptor();
+        String wechatPayCertificateSerialNumber = encryptor.getWechatpaySerial();
+
+
+        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");
+
+        String requestBody="";
+
+        try {
+            BufferedReader reader = request.getReader();
+            String line = "";
+            StringBuffer inputString = new StringBuffer();
+            while ( (line = reader.readLine()) != null ) {
+                inputString.append(line);
+            }
+            if(inputString!=null && !"".equals(inputString)) {
+                requestBody = inputString.toString();
+            }
+            reader.close();
+        } catch (IOException e) {
+            e.printStackTrace();
+        }
+
+        RequestParam requestParam = new RequestParam.Builder()
+                .serialNumber(wechatPayCertificateSerialNumber)
+                .nonce(nonoc)
+                .signature(signature)
+                .timestamp(timestamp)
+                .body(requestBody)
+                .build();
+
+        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")){
+            String outTradeNo=transaction.getOutTradeNo();
+            orderService.payBack(outTradeNo);
+        }
+
+        Map map=new HashMap();
+        map.put("code","SUCCESS");
+        map.put("message","成功");
+
+        return map;
+    }
+
+}
diff --git a/ruoyi-modules/ruoyi-order/src/main/java/com/ruoyi/order/domain/dto/WXPayNotifyDto.java b/ruoyi-modules/ruoyi-order/src/main/java/com/ruoyi/order/domain/dto/WXPayNotifyDto.java
new file mode 100644
index 0000000..698fceb
--- /dev/null
+++ b/ruoyi-modules/ruoyi-order/src/main/java/com/ruoyi/order/domain/dto/WXPayNotifyDto.java
@@ -0,0 +1,19 @@
+package com.ruoyi.order.domain.dto;
+
+import lombok.Data;
+
+/**
+ * @program: ruoyi
+ * @author: linqingsong
+ * @create: 2023-07-22 17:23
+ * @description: 成都软思同创科技有限公司
+ **/
+@Data
+public class WXPayNotifyDto {
+    private String id;
+    private String create_time;
+    private String event_type;
+    private String resource_type;
+    private WXPayNotifyResourceDto resource;
+    private String summary;
+}
diff --git a/ruoyi-modules/ruoyi-order/src/main/java/com/ruoyi/order/domain/dto/WXPayNotifyResourceDto.java b/ruoyi-modules/ruoyi-order/src/main/java/com/ruoyi/order/domain/dto/WXPayNotifyResourceDto.java
new file mode 100644
index 0000000..cebb086
--- /dev/null
+++ b/ruoyi-modules/ruoyi-order/src/main/java/com/ruoyi/order/domain/dto/WXPayNotifyResourceDto.java
@@ -0,0 +1,14 @@
+package com.ruoyi.order.domain.dto;
+
+/**
+ * @program: ruoyi
+ * @author: linqingsong
+ * @create: 2023-07-22 17:25
+ * @description: 成都软思同创科技有限公司
+ **/
+public class WXPayNotifyResourceDto {
+    private String algorithm;
+    private String ciphertext;
+    private String associated_datal;
+    private String nonce;
+}
diff --git a/ruoyi-modules/ruoyi-order/src/main/java/com/ruoyi/order/service/impl/order/OrderServiceImpl.java b/ruoyi-modules/ruoyi-order/src/main/java/com/ruoyi/order/service/impl/order/OrderServiceImpl.java
index d610779..a3440b9 100644
--- a/ruoyi-modules/ruoyi-order/src/main/java/com/ruoyi/order/service/impl/order/OrderServiceImpl.java
+++ b/ruoyi-modules/ruoyi-order/src/main/java/com/ruoyi/order/service/impl/order/OrderServiceImpl.java
@@ -14,6 +14,7 @@
 import com.ruoyi.common.security.utils.SecurityUtils;
 import com.ruoyi.order.domain.dto.*;
 import com.ruoyi.order.domain.pojo.account.OrderRefund;
+import com.ruoyi.order.domain.pojo.account.PaymentMessage;
 import com.ruoyi.order.domain.pojo.order.ConsumerGoods;
 import com.ruoyi.order.domain.pojo.order.Order;
 import com.ruoyi.order.domain.pojo.order.OrderGoods;
@@ -24,6 +25,8 @@
 import com.ruoyi.order.service.order.OrderGoodsService;
 import com.ruoyi.order.service.order.OrderService;
 import com.ruoyi.order.service.order.UserServiceRecordService;
+import com.ruoyi.order.tools.request.pay.combine.CombineTransactionsJsRequest;
+import com.ruoyi.order.tools.service.ProfitsSharingService;
 import com.ruoyi.system.api.constant.AppErrorConstant;
 import com.ruoyi.system.api.constant.DelayTaskEnum;
 import com.ruoyi.system.api.constant.SecurityConstant;
@@ -39,6 +42,8 @@
 import com.ruoyi.system.api.domain.poji.sys.SysUser;
 import com.ruoyi.system.api.domain.vo.*;
 import com.ruoyi.system.api.service.*;
+import com.wechat.pay.java.service.payments.jsapi.JsapiServiceExtension;
+import com.wechat.pay.java.service.payments.jsapi.model.*;
 import org.redisson.api.RLock;
 import org.redisson.api.RedissonClient;
 import org.springframework.beans.factory.annotation.Autowired;
@@ -52,6 +57,10 @@
 import java.util.concurrent.TimeUnit;
 import java.util.function.Function;
 import java.util.stream.Collectors;
+
+import com.wechat.pay.java.core.Config;
+import com.wechat.pay.java.core.RSAConfig;
+import com.wechat.pay.java.service.payments.jsapi.JsapiService;
 
 /**
  * <p>
@@ -106,8 +115,28 @@
     @Resource
     private RedisService redisService;
 
+    @Resource
+    private ProfitsSharingService profitsSharingService;
+
     @Autowired
     private RedissonClient redissonClient;
+
+    /** 商户号 */
+    public static String merchantId = "";
+    /** 商户API私钥路径 */
+    public static String privateKeyPath = "";
+    /** 商户证书序列号 */
+    public static String merchantSerialNumber = "";
+    /** 微信支付平台证书路径 */
+    public static String wechatPayCertificatePath = "";
+    /** 微信支付 APIv3 密钥 */
+    public static String apiV3Key = "";
+    /** 微信支付APPID */
+    public static String appId="";
+    /** 微信支付商户ID */
+    public static String mchId="";
+    /** 通知地址 */
+    public static String notifyUrl="";
 
     /**
      * @description: buyGoods
@@ -664,6 +693,37 @@
         appPlaceOrderVo.setOrderId(orderId);
         appPlaceOrderVo.setOrderNo(orderNo);
         // 调用支付
+       /* CombineTransactionsJsRequest request=new CombineTransactionsJsRequest();
+        request.setCombineAppid();
+        request.setCombineMchid();
+        profitsSharingService.combineTransactions(request);*/
+
+       //构建预下单支付对象
+        PrepayRequest request = new PrepayRequest();
+        Amount amount = new Amount();
+        amount.setTotal(Integer.parseInt(order.getPayMoney().multiply(new BigDecimal(100)).toString()));
+        request.setAmount(amount);
+        request.setAppid(this.appId);
+        request.setMchid(this.mchId);
+        request.setDescription(order.getGoodsInfo());
+        request.setNotifyUrl(this.notifyUrl);
+        request.setOutTradeNo(order.getOrderId());
+        Payer payer = new Payer();        payer.setOpenid("oLTPCuN5a-nBD4rAL_fa********");
+
+        request.setPayer(payer);
+
+
+        //返回前端唤醒支付结果信息
+        PrepayWithRequestPaymentResponse res = this.getJsApIResponse(request);
+
+        appPlaceOrderVo.setAppId(this.appId);
+        appPlaceOrderVo.setTimeStamp(res.getTimeStamp());
+        appPlaceOrderVo.setNonceStr(res.getNonceStr());
+        appPlaceOrderVo.setPackageStr(res.getPackageVal());
+        appPlaceOrderVo.setTradeType(res.getSignType());
+        appPlaceOrderVo.setPaySign(res.getPaySign());
+
+
         //减去优惠券
         if(memberCouponSJ!=null){
             remoteCouponService.useMemberCoupon(memberCouponSJ.toString());
@@ -684,6 +744,79 @@
     }
 
     /**
+     *
+     * 功能描述: 预下单,返回支付数据prePayId
+     *
+     * 构建对象参考
+     *     PrepayRequest request = new PrepayRequest();
+     *     Amount amount = new Amount();
+     *     amount.setTotal(100);
+     *     request.setAmount(amount);
+     *     request.setAppid("wxa9d9651ae******");
+     *     request.setMchid("190000****");
+     *     request.setDescription("测试商品标题");
+     *     request.setNotifyUrl("https://notify_url");
+     *     request.setOutTradeNo("out_trade_no_001");
+     *     Payer payer = new Payer();
+     *     payer.setOpenid("oLTPCuN5a-nBD4rAL_fa********");
+     *     request.setPayer(payer);
+     *
+     * @auther: linqingsong
+     * @date: 2023/7/22 16:13
+     */
+    /*public String getPrePayId(PrepayRequest request) {
+        Config config =
+                new RSAConfig.Builder()
+                        .merchantId(merchantId)
+                        .privateKeyFromPath(privateKeyPath)
+                        .merchantSerialNumber(merchantSerialNumber)
+                        .wechatPayCertificatesFromPath(wechatPayCertificatePath)
+                        .build();
+        JsapiService service = new JsapiService.Builder().config(config).build();
+        PrepayResponse response = service.prepay(request);
+        return response.getPrepayId();
+    }*/
+
+
+    /**
+     *
+     * 功能描述: 预下单,并返回前端需要换起支付的字符串
+     *
+     * 构建对象参考
+     *      *     PrepayRequest request = new PrepayRequest();
+     *      *     Amount amount = new Amount();
+     *      *     amount.setTotal(100);
+     *      *     request.setAmount(amount);
+     *      *     request.setAppid("wxa9d9651ae******");
+     *      *     request.setMchid("190000****");
+     *      *     request.setDescription("测试商品标题");
+     *      *     request.setNotifyUrl("https://notify_url");
+     *      *     request.setOutTradeNo("out_trade_no_001");
+     *      *     Payer payer = new Payer();
+     *      *     payer.setOpenid("oLTPCuN5a-nBD4rAL_fa********");
+     *      *     request.setPayer(payer);
+     *
+     *
+     * @auther: linqingsong
+     * @date: 2023/7/22 16:53
+     */
+    public PrepayWithRequestPaymentResponse getJsApIResponse(PrepayRequest request){
+        Config config =
+                new RSAConfig.Builder()
+                        .merchantId(merchantId)
+                        .privateKeyFromPath(privateKeyPath)
+                        .merchantSerialNumber(merchantSerialNumber)
+                        .wechatPayCertificatesFromPath(wechatPayCertificatePath)
+                        .build();
+        JsapiServiceExtension service = new JsapiServiceExtension.Builder().config(config).build();
+
+        PrepayWithRequestPaymentResponse response = service.prepayWithRequestPayment(request);
+
+        return response;
+    }
+
+
+    /**
      * @param appPlaceActivityDto
      * @return AppPlaceOrderVo
      * @description 创建活动订单

--
Gitblit v1.7.1