dcs před 2 měsíci
rodič
revize
351f3c7d2f

+ 83 - 0
virgo.api/src/main/java/com/bosshand/virgo/api/workark/config/WxPayConfig.java

@@ -1,7 +1,19 @@
 package com.bosshand.virgo.api.workark.config;
 
+import com.wechat.pay.java.core.Config;
+import com.wechat.pay.java.core.RSAPublicKeyConfig;
+import com.wechat.pay.java.service.payments.jsapi.JsapiService;
+import com.wechat.pay.java.service.payments.nativepay.NativePayService;
+import com.wechat.pay.java.service.refund.RefundService;
 import org.springframework.beans.factory.annotation.Value;
+import org.springframework.context.annotation.Bean;
 import org.springframework.context.annotation.Configuration;
+import org.springframework.context.annotation.Primary;
+import org.springframework.core.io.ClassPathResource;
+
+import javax.annotation.PostConstruct;
+import java.io.BufferedReader;
+import java.io.InputStreamReader;
 
 
 @Configuration
@@ -106,4 +118,75 @@ public class WxPayConfig {
     public String getPublicKeyPath() {
         return publicKeyPath;
     }
+
+    public String getFileContent(String filePath) {
+        try {
+            ClassPathResource resource = new ClassPathResource(filePath);
+            try (BufferedReader reader = new BufferedReader(new InputStreamReader(resource.getInputStream()))) {
+                StringBuilder content = new StringBuilder();
+                String line;
+                while ((line = reader.readLine()) != null) {
+                    content.append(line).append("\n");
+                }
+                return content.toString();
+            }
+        } catch (Exception e) {
+            throw new RuntimeException("Error reading file: " + filePath, e);
+        }
+    }
+
+    private Config config;
+
+    /**
+     * RSAPublicKeyConfig 用于 API 请求加密和验签
+     */
+    @PostConstruct
+    private void initConfig(){
+        // 初始化商户配置
+        config = new RSAPublicKeyConfig.Builder()
+                        .merchantId(mchId)
+                        .privateKey(getFileContent(privateKeyPath))
+                        .publicKey(getFileContent(publicKeyPath))
+                        .publicKeyId(publicKeyId)
+                        .merchantSerialNumber(mchSerialNo)
+                        .apiV3Key(apiV3Key)
+                        .build();
+
+    }
+
+    /**
+     * Native支付
+     */
+    @Primary
+    @Bean()
+    public NativePayService nativePayService() {
+        return new NativePayService.Builder()
+                .config(config)
+                .build();
+    }
+
+    /**
+     * JSAPI支付
+     */
+    @Primary
+    @Bean()
+    public JsapiService jsapiService() {
+        return new JsapiService.Builder()
+                .config(config)
+                .build();
+    }
+
+    /**
+     * 申请退款
+     */
+    @Primary
+    @Bean
+    public RefundService refundService(){
+        return new RefundService.Builder()
+                .config(config)
+                .build();
+    }
+
+
+
 }

+ 24 - 2
virgo.api/src/main/java/com/bosshand/virgo/api/workark/controller/WxPayController.java

@@ -1,6 +1,8 @@
 package com.bosshand.virgo.api.workark.controller;
 
 
+import com.bosshand.virgo.api.workark.service.WechatPayValidatorForRequest;
+import com.bosshand.virgo.api.workark.service.WxPayJsApiService;
 import com.bosshand.virgo.api.workark.service.WxPayService;
 import com.bosshand.virgo.api.workark.util.HttpUtils;
 import com.bosshand.virgo.core.response.Response;
@@ -28,6 +30,12 @@ public class WxPayController {
     @Autowired
     WxPayService wxPayService;
 
+    @Autowired
+    WxPayJsApiService wxPayJsApiService;
+
+    @Autowired
+    WechatPayValidatorForRequest wechatPayValidatorForRequest;
+
     /**
      * Native下单
      * @param orderNo
@@ -44,6 +52,20 @@ public class WxPayController {
         return Response.ok(map);
     }
 
+    /**
+     * JSAPI支付下单
+     * @param orderNo
+     * @return
+     * @throws Exception
+     */
+    @ApiOperation("提交订单,返回小程序支付所需参数")
+    @PostMapping("/jsapi/{orderNo}/{openid}")
+    public Response jsapiPay(@PathVariable String orderNo, @PathVariable String openid) throws Exception {
+
+        log.info("发起支付请求 JSAPI");
+        return Response.ok(wxPayJsApiService.jsapiPay(orderNo, openid));
+    }
+
     /**
      * 支付通知
      * 微信支付通过支付通知接口将用户支付成功消息通知给商户
@@ -65,7 +87,7 @@ public class WxPayController {
             log.info("支付通知的id ===>" + requestId);
 
             //签名的验证
-            if(false){
+            if(wechatPayValidatorForRequest.payNotify(request)){
 
                 log.error("通知验签失败");
                 //失败应答
@@ -169,7 +191,7 @@ public class WxPayController {
             log.info("支付通知的id ===>" + requestId);
 
             //签名的验证
-            if(false){
+            if(wechatPayValidatorForRequest.refundNotify(request)){
 
                 log.error("通知验签失败");
                 //失败应答

+ 103 - 0
virgo.api/src/main/java/com/bosshand/virgo/api/workark/dto/WechatPayDto.java

@@ -0,0 +1,103 @@
+package com.bosshand.virgo.api.workark.dto;
+
+import com.fasterxml.jackson.annotation.JsonFormat;
+
+import java.util.Date;
+
+/**
+ * 前端微信支付所需参数
+ */
+public class WechatPayDto {
+
+    /**
+     * 需要支付的小程序id
+     */
+    private String appid;
+
+    /**
+     * 时间戳(当前的时间)
+     */
+    private String timeStamp;
+
+    /**
+     * 随机字符串,不长于32位。
+     */
+    private String nonceStr;
+
+    /**
+     * 小程序下单接口返回的prepay_id参数值,提交格式如:prepay_id=***
+     */
+    private String prepayId;
+
+    /**
+     * 过期时间
+     */
+    @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
+    private Date prepayIdFailureTime;
+
+    /**
+     * 签名类型,默认为RSA,仅支持RSA。
+     */
+    private String signType;
+
+    /**
+     * 签名,使用字段appId、timeStamp、nonceStr、package计算得出的签名值
+     */
+    private String paySign;
+
+    public String getAppid() {
+        return appid;
+    }
+
+    public void setAppid(String appid) {
+        this.appid = appid;
+    }
+
+    public String getTimeStamp() {
+        return timeStamp;
+    }
+
+    public void setTimeStamp(String timeStamp) {
+        this.timeStamp = timeStamp;
+    }
+
+    public String getNonceStr() {
+        return nonceStr;
+    }
+
+    public void setNonceStr(String nonceStr) {
+        this.nonceStr = nonceStr;
+    }
+
+    public String getPrepayId() {
+        return prepayId;
+    }
+
+    public void setPrepayId(String prepayId) {
+        this.prepayId = prepayId;
+    }
+
+    public Date getPrepayIdFailureTime() {
+        return prepayIdFailureTime;
+    }
+
+    public void setPrepayIdFailureTime(Date prepayIdFailureTime) {
+        this.prepayIdFailureTime = prepayIdFailureTime;
+    }
+
+    public String getSignType() {
+        return signType;
+    }
+
+    public void setSignType(String signType) {
+        this.signType = signType;
+    }
+
+    public String getPaySign() {
+        return paySign;
+    }
+
+    public void setPaySign(String paySign) {
+        this.paySign = paySign;
+    }
+}

+ 27 - 0
virgo.api/src/main/java/com/bosshand/virgo/api/workark/model/OrderInfo.java

@@ -65,6 +65,17 @@ public class OrderInfo {
     @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
     private Date codeUrlFailureTime;
 
+    /**
+     * 订单预支付交易会话标识
+     */
+    private String prepayId;
+
+    /**
+     * 订单预支付交易会话标识过期时间
+     */
+    @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
+    private Date prepayIdFailureTime;
+
     /**
      * 订单支付状态
      */
@@ -203,6 +214,22 @@ public class OrderInfo {
         this.codeUrlFailureTime = codeUrlFailureTime;
     }
 
+    public String getPrepayId() {
+        return prepayId;
+    }
+
+    public void setPrepayId(String prepayId) {
+        this.prepayId = prepayId;
+    }
+
+    public Date getPrepayIdFailureTime() {
+        return prepayIdFailureTime;
+    }
+
+    public void setPrepayIdFailureTime(Date prepayIdFailureTime) {
+        this.prepayIdFailureTime = prepayIdFailureTime;
+    }
+
     public String getOrderStatus() {
         return orderStatus;
     }

+ 19 - 1
virgo.api/src/main/java/com/bosshand/virgo/api/workark/service/OrderInfoService.java

@@ -155,7 +155,25 @@ public class OrderInfoService {
         OrderInfo orderInfo = orderInfoDao.getOrderNo(orderNo);
         orderInfo.setCodeUrl(codeUrl);
         // 设置110分钟过期
-        Instant instant = Instant.now().minus(Duration.ofMinutes(110));
+        Instant instant = Instant.now().plus(Duration.ofMinutes(110));
+        ZonedDateTime zonedDateTime = instant.atZone(ZoneId.systemDefault());
+        Date date = Date.from(zonedDateTime.toInstant());
+        orderInfo.setCodeUrlFailureTime(date);
+        orderInfoDao.update(orderInfo);
+        return orderInfo;
+    }
+
+    /**
+     * 存储订单预支付交易会话标识prepay_id
+     * @param orderNo
+     * @param prepayId
+     * @return OrderInfo
+     */
+    public OrderInfo savePrepayId(String orderNo, String prepayId) {
+        OrderInfo orderInfo = orderInfoDao.getOrderNo(orderNo);
+        orderInfo.setPrepayId(prepayId);
+        // 设置110分钟过期
+        Instant instant = Instant.now().plus(Duration.ofMinutes(110));
         ZonedDateTime zonedDateTime = instant.atZone(ZoneId.systemDefault());
         Date date = Date.from(zonedDateTime.toInstant());
         orderInfo.setCodeUrlFailureTime(date);

+ 54 - 0
virgo.api/src/main/java/com/bosshand/virgo/api/workark/service/WechatPayValidatorForRequest.java

@@ -0,0 +1,54 @@
+package com.bosshand.virgo.api.workark.service;
+
+import com.bosshand.virgo.api.workark.util.WeChatUtil;
+import com.wechat.pay.java.core.exception.ValidationException;
+import com.wechat.pay.java.core.notification.NotificationParser;
+import com.wechat.pay.java.service.payments.model.Transaction;
+import com.wechat.pay.java.service.refund.model.RefundNotification;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.springframework.stereotype.Service;
+
+import javax.annotation.Resource;
+import javax.servlet.http.HttpServletRequest;
+import java.io.IOException;
+
+@Service
+public class WechatPayValidatorForRequest {
+
+    private final static Log log = LogFactory.getLog(WechatPayValidatorForRequest.class);
+
+    @Resource
+    private NotificationParser notificationParser;
+
+    public boolean payNotify(HttpServletRequest request) {
+        Transaction transaction;
+        try {
+            transaction = notificationParser.parse(WeChatUtil.handleNodifyRequestParam(request), Transaction.class);
+            if (transaction.getTradeState() == Transaction.TradeStateEnum.SUCCESS){
+                return true;
+            }
+            return false;
+        } catch (ValidationException | IOException e) {
+            // 签名验证失败
+            log.error("签名验证失败: " + e);
+            return false;
+        }
+    }
+
+    public boolean refundNotify(HttpServletRequest request) {
+        try {
+            RefundNotification parse = notificationParser.parse(WeChatUtil.handleNodifyRequestParam(request), RefundNotification.class);
+            if ("SUCCESS".equals(parse.getRefundStatus())){
+                return true;
+            }
+            return false;
+        } catch (IOException e) {
+            // 通知验签失败
+            log.error("通知验签失败: " + e);
+            return false;
+        }
+    }
+
+
+}

+ 122 - 0
virgo.api/src/main/java/com/bosshand/virgo/api/workark/service/WxPayJsApiService.java

@@ -0,0 +1,122 @@
+package com.bosshand.virgo.api.workark.service;
+
+import com.bosshand.virgo.api.service.QuartzService;
+import com.bosshand.virgo.api.workark.config.WxPayConfig;
+import com.bosshand.virgo.api.workark.dto.WechatPayDto;
+import com.bosshand.virgo.api.workark.enums.wxpay.WxNotifyType;
+import com.bosshand.virgo.api.workark.model.OrderInfo;
+import com.bosshand.virgo.api.workark.util.WeChatUtil;
+import com.wechat.pay.java.core.util.NonceUtil;
+import com.wechat.pay.java.service.payments.jsapi.JsapiService;
+import com.wechat.pay.java.service.payments.jsapi.model.Amount;
+import com.wechat.pay.java.service.payments.jsapi.model.Payer;
+import com.wechat.pay.java.service.payments.jsapi.model.PrepayRequest;
+import com.wechat.pay.java.service.payments.jsapi.model.PrepayResponse;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
+import org.springframework.util.StringUtils;
+
+import javax.annotation.Resource;
+import java.math.BigDecimal;
+import java.util.Date;
+import java.util.stream.Collectors;
+import java.util.stream.Stream;
+
+@Service
+public class WxPayJsApiService {
+
+    @Resource
+    private WxPayConfig wxPayConfig;
+
+    @Autowired
+    private OrderInfoService orderInfoService;
+
+    @Autowired
+    private QuartzService quartzService;
+
+    @Resource
+    private JsapiService jsapiService;
+
+    private final static Log log = LogFactory.getLog(WxPayJsApiService.class);
+
+    /**
+     * 前端微信支付所需参数
+     */
+    private WechatPayDto getWechatPayDto(String prepayId, Date prepayIdFailureTime) {
+        WechatPayDto wechatPayDto = new WechatPayDto();
+        wechatPayDto.setAppid(wxPayConfig.getAppid());
+        wechatPayDto.setTimeStamp(String.valueOf(System.currentTimeMillis() / 1000));
+        wechatPayDto.setNonceStr(NonceUtil.createNonce(32));
+        wechatPayDto.setPrepayId("prepay_id=" + prepayId);
+        wechatPayDto.setPrepayIdFailureTime(prepayIdFailureTime);
+        wechatPayDto.setSignType("RSA");
+        wechatPayDto.setPaySign(WeChatUtil.getSign(
+                Stream.of(wxPayConfig.getAppid(),
+                        wechatPayDto.getTimeStamp(),
+                        wechatPayDto.getNonceStr(),
+                        wechatPayDto.getPrepayId()).collect(Collectors.joining("\n", "", "\n")),
+                wxPayConfig.getFileContent(wxPayConfig.getPrivateKeyPath()),
+                wxPayConfig.getMchSerialNo()));
+        return wechatPayDto;
+    }
+
+    /**
+     * 创建订单,调用JSAPI支付接口
+     */
+    @Transactional(rollbackFor = Exception.class)
+    public WechatPayDto jsapiPay(String orderNo, String openid) {
+        log.info("获取订单");
+
+        // 生成订单
+        OrderInfo orderInfo = orderInfoService.getOrderNo(orderNo);
+        String prepayId = orderInfo.getPrepayId();
+        if (orderInfo != null && !StringUtils.isEmpty(prepayId)) {
+            log.info("订单已存在,prepay_id 已保存");
+            return getWechatPayDto(prepayId, orderInfo.getPrepayIdFailureTime());
+        }
+
+        log.info("调用统一下单API");
+
+        PrepayRequest request = new PrepayRequest();
+        request.setAppid(wxPayConfig.getAppid());
+        request.setMchid(wxPayConfig.getMchId());
+        request.setDescription(orderInfo.getTitle());
+        request.setNotifyUrl(wxPayConfig.getNotifyDomain().concat(WxNotifyType.NATIVE_NOTIFY.getType()));
+        request.setOutTradeNo(orderInfo.getOrderNo());
+
+        Payer payer = new Payer();
+        payer.setOpenid(openid);
+        request.setPayer(payer);
+
+        // 元 转换 分
+        BigDecimal multiplier = new BigDecimal("100");
+        // 使用multiply方法乘以100
+        BigDecimal result = orderInfo.getTotalFee().multiply(multiplier);
+
+        Amount amount = new Amount();
+        amount.setTotal(result.intValue());
+        amount.setCurrency("CNY");
+        request.setAmount(amount);
+
+        // 调用下单方法,得到应答
+        PrepayResponse response = jsapiService.prepay(request);
+
+        // 返回 prepay_id
+        prepayId = response.getPrepayId();
+
+        //保存 prepay_id
+        OrderInfo orderInfo1 = orderInfoService.savePrepayId(orderInfo.getOrderNo(), prepayId);
+
+        //支付超时关闭订单
+        quartzService.executeWxPayCloseOrderTask(orderInfo1);
+
+        //将 WechatPayDto 中的值返回小程序就可以唤起支付页面 也就是输入密码页面
+        return getWechatPayDto(prepayId, orderInfo1.getPrepayIdFailureTime());
+
+    }
+
+
+}

+ 11 - 51
virgo.api/src/main/java/com/bosshand/virgo/api/workark/service/WxPayService.java

@@ -12,8 +12,6 @@ import com.bosshand.virgo.api.workark.model.RefundInfo;
 import com.bosshand.virgo.api.workark.util.AesUtil;
 import com.bosshand.virgo.api.workark.util.QrRcodeGenUtil;
 import com.google.gson.Gson;
-import com.wechat.pay.java.core.Config;
-import com.wechat.pay.java.core.RSAPublicKeyConfig;
 import com.wechat.pay.java.service.payments.model.Transaction;
 import com.wechat.pay.java.service.payments.nativepay.NativePayService;
 import com.wechat.pay.java.service.payments.nativepay.model.*;
@@ -25,15 +23,12 @@ import com.wechat.pay.java.service.refund.model.Refund;
 import org.apache.commons.logging.Log;
 import org.apache.commons.logging.LogFactory;
 import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.core.io.ClassPathResource;
 import org.springframework.stereotype.Service;
 import org.springframework.transaction.annotation.Transactional;
 import org.springframework.util.StringUtils;
 
 import javax.annotation.Resource;
-import java.io.BufferedReader;
 import java.io.IOException;
-import java.io.InputStreamReader;
 import java.math.BigDecimal;
 import java.nio.charset.StandardCharsets;
 import java.security.GeneralSecurityException;
@@ -60,39 +55,15 @@ public class WxPayService {
     @Autowired
     private QuartzService quartzService;
 
-    private final ReentrantLock lock = new ReentrantLock();
+    @Resource
+    private NativePayService nativePayService;
 
-    private final static Log log = LogFactory.getLog(WxPayService.class);
+    @Resource
+    private RefundService refundService;
 
-    public String getFileContent(String filePath) {
-        try {
-            ClassPathResource resource = new ClassPathResource(filePath);
-            try (BufferedReader reader = new BufferedReader(new InputStreamReader(resource.getInputStream()))) {
-                StringBuilder content = new StringBuilder();
-                String line;
-                while ((line = reader.readLine()) != null) {
-                    content.append(line).append("\n");
-                }
-                return content.toString();
-            }
-        } catch (Exception e) {
-            throw new RuntimeException("Error reading file: " + filePath, e);
-        }
-    }
+    private final ReentrantLock lock = new ReentrantLock();
 
-    private Config getConfig(){
-        // 初始化商户配置
-        Config config =
-                new RSAPublicKeyConfig.Builder()
-                        .merchantId(wxPayConfig.getMchId())
-                        .privateKey(getFileContent(wxPayConfig.getPrivateKeyPath()))
-                        .publicKey(getFileContent(wxPayConfig.getPublicKeyPath()))
-                        .publicKeyId(wxPayConfig.getPublicKeyId())
-                        .merchantSerialNumber(wxPayConfig.getMchSerialNo())
-                        .apiV3Key(wxPayConfig.getApiV3Key())
-                        .build();
-        return config;
-    }
+    private final static Log log = LogFactory.getLog(WxPayService.class);
 
     /**
      * 创建订单,调用Native支付接口
@@ -121,9 +92,6 @@ public class WxPayService {
 
         log.info("调用统一下单API");
 
-        // 初始化服务
-        NativePayService service = new NativePayService.Builder().config(getConfig()).build();
-
         PrepayRequest request = new PrepayRequest();
         request.setAppid(wxPayConfig.getAppid());
         request.setMchid(wxPayConfig.getMchId());
@@ -142,7 +110,7 @@ public class WxPayService {
         request.setAmount(amount);
 
         // 调用下单方法,得到应答
-        PrepayResponse response = service.prepay(request);
+        PrepayResponse response = nativePayService.prepay(request);
 
         // 使用微信扫描 code_url 对应的二维码
         codeUrl = response.getCodeUrl();
@@ -171,14 +139,12 @@ public class WxPayService {
 
         log.info("关单接口的调用,订单号 ===>"+ orderNo);
 
-        NativePayService service = new NativePayService.Builder().config(getConfig()).build();
-
         CloseOrderRequest request = new CloseOrderRequest();
 
         request.setMchid(wxPayConfig.getMchId());
         request.setOutTradeNo(orderNo);
 
-        service.closeOrder(request);
+        nativePayService.closeOrder(request);
     }
 
     /**
@@ -230,13 +196,11 @@ public class WxPayService {
 
         log.info("查单接口调用 ===>" + orderNo);
 
-        NativePayService service = new NativePayService.Builder().config(getConfig()).build();
-
         QueryOrderByOutTradeNoRequest request = new QueryOrderByOutTradeNoRequest();
         request.setMchid(wxPayConfig.getMchId());
         request.setOutTradeNo(orderNo);
 
-        Transaction transaction = service.queryOrderByOutTradeNo(request);
+        Transaction transaction = nativePayService.queryOrderByOutTradeNo(request);
 
         String name = transaction.getTradeState().name();
 
@@ -262,8 +226,6 @@ public class WxPayService {
 
         log.info("调用退款API");
 
-        RefundService service = new RefundService.Builder().config(getConfig()).build();
-
         CreateRequest request = new CreateRequest();
 
         request.setOutTradeNo(orderNo);//订单编号
@@ -284,7 +246,7 @@ public class WxPayService {
 
         request.setAmount(amount);
 
-        Refund refund1 = service.create(request);
+        Refund refund1 = refundService.create(request);
 
         //更新订单状态
         orderInfoService.updateStatusByOrderNo(orderNo, OrderStatus.REFUND_PROCESSING);
@@ -302,14 +264,12 @@ public class WxPayService {
 
         log.info("查询退款接口调用 ===>"+ refundNo);
 
-        RefundService service = new RefundService.Builder().config(getConfig()).build();
-
         QueryByOutRefundNoRequest request = new QueryByOutRefundNoRequest();
 
         request.setOutRefundNo(refundNo);
         request.setSubMchid(wxPayConfig.getMchId());
 
-        Refund refund = service.queryByOutRefundNo(request);
+        Refund refund = refundService.queryByOutRefundNo(request);
 
         return JSONObject.toJSONString(refund);
 

+ 72 - 0
virgo.api/src/main/java/com/bosshand/virgo/api/workark/util/WeChatUtil.java

@@ -0,0 +1,72 @@
+package com.bosshand.virgo.api.workark.util;
+
+import com.wechat.pay.java.core.cipher.RSASigner;
+import com.wechat.pay.java.core.cipher.SignatureResult;
+import com.wechat.pay.java.core.notification.RequestParam;
+import com.wechat.pay.java.core.util.PemUtil;
+
+import javax.servlet.ServletInputStream;
+import javax.servlet.http.HttpServletRequest;
+import java.io.BufferedReader;
+import java.io.IOException;
+import java.io.InputStreamReader;
+import java.security.PrivateKey;
+
+public class WeChatUtil {
+
+    public static String getSign(String signatureStr, String privateKeyPath, String merchantSerialNumber) {
+        PrivateKey privateKey = PemUtil.loadPrivateKeyFromString(privateKeyPath);
+        RSASigner rsaSigner = new RSASigner(merchantSerialNumber, privateKey);
+        SignatureResult signatureResult = rsaSigner.sign(signatureStr);
+        return signatureResult.getSign();
+    }
+
+    /**
+     * 构造 RequestParam 回调的时候获取请求头
+     */
+    public static RequestParam handleNodifyRequestParam(HttpServletRequest request) throws IOException {
+        // 请求头Wechatpay-Signature
+        String signature = request.getHeader("Wechatpay-Signature");
+        // 请求头Wechatpay-nonce
+        String nonce = request.getHeader("Wechatpay-Nonce");
+        // 请求头Wechatpay-Timestamp
+        String timestamp = request.getHeader("Wechatpay-Timestamp");
+        // 微信支付证书序列号
+        String serial = request.getHeader("Wechatpay-Serial");
+        // 构造 RequestParam
+        return new RequestParam.Builder()
+                .serialNumber(serial)
+                .nonce(nonce)
+                .signature(signature)
+                .timestamp(timestamp)
+                .body(getRequestBody(request))
+                .build();
+
+    }
+
+    public static String getRequestBody(HttpServletRequest request) throws IOException {
+        ServletInputStream stream;
+        BufferedReader reader = null;
+        StringBuilder sb = new StringBuilder();
+        try {
+            stream = request.getInputStream();
+            // 获取响应
+            reader = new BufferedReader(new InputStreamReader(stream));
+            String line;
+            while ((line = reader.readLine()) != null) {
+                sb.append(line);
+            }
+        } catch (IOException e) {
+            throw new IOException("读取返回支付接口数据流出现异常!");
+        } finally {
+            if (reader != null) {
+                reader.close();
+            }
+        }
+        return sb.toString();
+    }
+
+
+
+}
+

+ 4 - 0
virgo.api/src/main/resources/mapper/OrderInfoMapper.xml

@@ -15,6 +15,8 @@
         <result column="totalFee" property="totalFee"/>
         <result column="codeUrl" property="codeUrl"/>
         <result column="codeUrlFailureTime" property="codeUrlFailureTime"/>
+        <result column="prepayId" property="prepayId"/>
+        <result column="prepayIdFailureTime" property="prepayIdFailureTime"/>
         <result column="orderStatus" property="orderStatus"/>
         <result column="status" property="status"/>
         <result column="paymentType" property="paymentType"/>
@@ -188,6 +190,8 @@
             <if test="title!=null">title=#{title},</if>
             <if test="codeUrl!=null">codeUrl=#{codeUrl},</if>
             <if test="codeUrlFailureTime!=null">codeUrlFailureTime=#{codeUrlFailureTime},</if>
+            <if test="prepayId!=null">prepayId=#{prepayId},</if>
+            <if test="prepayIdFailureTime !=null">prepayIdFailureTime=#{prepayIdFailureTime},</if>
             <if test="orderStatus!=null">orderStatus=#{orderStatus},</if>
             <if test="paymentType!=null">paymentType=#{paymentType},</if>
             <if test="updateTime==null">updateTime=now(),</if>