zhanglin
2023-07-22 03dd384bb8b78f04eadcf619849b3687fa98c6c1
微信支付,支付与结果通知
2个文件已修改
3个文件已添加
304 ■■■■■ 已修改文件
ruoyi-modules/ruoyi-order/pom.xml 6 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-modules/ruoyi-order/src/main/java/com/ruoyi/order/controller/miniapp/NotifyController.java 132 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-modules/ruoyi-order/src/main/java/com/ruoyi/order/domain/dto/WXPayNotifyDto.java 19 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-modules/ruoyi-order/src/main/java/com/ruoyi/order/domain/dto/WXPayNotifyResourceDto.java 14 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-modules/ruoyi-order/src/main/java/com/ruoyi/order/service/impl/order/OrderServiceImpl.java 133 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
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>
ruoyi-modules/ruoyi-order/src/main/java/com/ruoyi/order/controller/miniapp/NotifyController.java
New file
@@ -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;
    }
}
ruoyi-modules/ruoyi-order/src/main/java/com/ruoyi/order/domain/dto/WXPayNotifyDto.java
New file
@@ -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;
}
ruoyi-modules/ruoyi-order/src/main/java/com/ruoyi/order/domain/dto/WXPayNotifyResourceDto.java
New file
@@ -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;
}
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 创建活动订单