微信支付 apiV3 调用支付接口

WeChatPaymentApiV3.java
package com.ruoyi.business.payment;

import com.ruoyi.business.payment.dto.PayParam;
import com.ruoyi.business.payment.dto.RefundParam;
import com.wechat.pay.java.core.Config;
import com.wechat.pay.java.core.RSAAutoCertificateConfig;
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.core.util.PemUtil;
import com.wechat.pay.java.service.payments.app.AppService;
import com.wechat.pay.java.service.payments.h5.H5Service;
import com.wechat.pay.java.service.payments.app.model.*;
import com.wechat.pay.java.service.payments.model.Transaction;
import com.wechat.pay.java.service.payments.model.TransactionAmount;
import com.wechat.pay.java.service.refund.RefundService;
import com.wechat.pay.java.service.refund.model.AmountReq;
import com.wechat.pay.java.service.refund.model.CreateRequest;
import com.wechat.pay.java.service.refund.model.Refund;
import com.wechat.pay.java.service.refund.model.RefundNotification;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import javax.servlet.ServletInputStream;
import javax.servlet.http.HttpServletRequest;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.UnsupportedEncodingException;
import java.math.BigDecimal;
import java.security.*;
import java.util.*;

/**
 * 微信支付服务类
 */
@Service
@Slf4j
public class WeChatPaymentApiV3 {

    private static final String mchId = "16794"; // 商户号
    private static final String mchSerialNo = "5D7DB9B"; // 商户证书序列号
    //商户私钥 //https://pay.weixin.qq.com/wiki/doc/apiv3/wechatpay/wechatpay3_1.shtml
    private static final String privateKey = "-----BEGIN PRIVATE KEY-----\n" +
            "MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQDH0aut4gO2wjR1\n" +
            "PbGM84zoZ0b7usuf
            "PPYa5PypeYgcG2cuIWzJejQ=\n" +
            "-----END PRIVATE KEY-----";
    // 你的微信支付平台证书
    private static final String apiV3Key = "f2f4667bfeab47";

    private static final String appid="wxea8a";

    /** 商户API私钥路径 */
    //public static String privateKeyPath = "C:\\Users\\Administrator\\Desktop\\coupon\\wxpay\\apiclient_key.pem";

    /**
     * 获得H5客户端
     * @return
     */
    public AppService getAppService () {
        Config config =
                new RSAAutoCertificateConfig.Builder()
                        .merchantId(mchId)
                        .privateKey(privateKey)
                        //.privateKeyFromPath(privateKeyPath)
                        .merchantSerialNumber(mchSerialNo)
                        .apiV3Key(apiV3Key)
                        .build();
        AppService build = new AppService.Builder().config(config).build();
        return build;
    }

    public String pay(PayParam payParam) {
        String apiUrl = "http://1.94.66:80/admin";

        //apiUrl="http://7j6vva.natappfree.cc";

        BigDecimal bigDecimal = new BigDecimal(100);
        int payPrice = bigDecimal.multiply(new BigDecimal(payParam.getTotalAmount())).intValue();

        AppService appService = getAppService();

        //获取客户端
        PrepayRequest request = new PrepayRequest();
        Amount amount = new Amount();
        amount.setTotal(payPrice);


        //场景信息
        SceneInfo sceneInfo = new SceneInfo();
        sceneInfo.setPayerClientIp("1.196");

        request.setAmount(amount);
        request.setAppid(appid);
        request.setMchid(mchId);
        request.setDescription(payParam.getSubject());
        //request.setNotifyUrl("http://egevdr.natappfree.cc" + "/payment/weChatPay/payment/notify");
        request.setNotifyUrl(apiUrl + "/payment/weChatPay/payment/notify");
        request.setOutTradeNo(payParam.getOutTradeNo());
        request.setAttach(payParam.getPassbackParams());//携带其他参数
        request.setSceneInfo(sceneInfo);

        // 调用下单方法,得到应答
        PrepayResponse prepay = appService.prepay(request);
        return prepay.getPrepayId();
    }

    /**
     * 申请退款
     * @param refundParam
     */
    public void refundOrder(RefundParam refundParam) {
        String apiUrl = "";
        BigDecimal bigDecimal = new BigDecimal(100);
        int total = bigDecimal.multiply(new BigDecimal(refundParam.getTotalAmount())).intValue();

        int refund = bigDecimal.multiply(new BigDecimal(refundParam.getTotalAmount())).intValue();

        Config config =
                new RSAAutoCertificateConfig.Builder()
                        .merchantId(mchId)
                        .privateKey(privateKey)
                        .merchantSerialNumber(mchSerialNo)
                        .apiV3Key(apiV3Key)
                        .build();
        RefundService service = new RefundService.Builder().config(config).build();

        //生成随机退款订单号
        String s = UUID.randomUUID().toString().replace("-","");

        CreateRequest request = new CreateRequest();

        //金额信息
        AmountReq amount = new AmountReq();
        amount.setCurrency("CNY");
        amount.setTotal(Long.valueOf(total));
        amount.setRefund(Long.valueOf(refund));

        request.setAmount(amount);
        request.setOutTradeNo(refundParam.getOutTradeNo());
        request.setOutRefundNo(s);
        //request.setNotifyUrl("http://egevdr.natappfree.cc" + "/payment/weChatPay/refund/notify");
        request.setNotifyUrl(apiUrl +"api" + "/payment/weChatPay/refund/notify");

        //发送请求
        Refund refund1 = service.create(request);
    }

    /**
     * 根据订单号查询订单信息,目前只返回了订单状态 https://pay.weixin.qq.com/wiki/doc/apiv3/apis/chapter3_3_2.shtml
     * @param orderNum
     * @return
     */
    public Map queryOrderByOutTradeNo(String orderNum) {
        AppService appService = getAppService();
        QueryOrderByOutTradeNoRequest request = new QueryOrderByOutTradeNoRequest();
        request.setMchid(mchId);
        request.setOutTradeNo(orderNum);

        Transaction transaction = appService.queryOrderByOutTradeNo(request);

        Map map=new HashMap();
        map.put("tradeState",transaction.getTradeState());
        /**
         * 交易状态,枚举值:
         * SUCCESS:支付成功
         * REFUND:转入退款
         * NOTPAY:未支付
         * CLOSED:已关闭
         * REVOKED:已撤销(仅付款码支付会返回)
         * USERPAYING:用户支付中(仅付款码支付会返回)
         * PAYERROR:支付失败(仅付款码支付会返回)
         */
        return map;
    }

    /**
     * 支付成功验签
     * @param request
     * @return
     */
    public Map paySuccessCheck(HttpServletRequest request) {
        Config config =
                new RSAAutoCertificateConfig.Builder()
                        .merchantId(mchId)
                        .privateKey(privateKey)
                        .merchantSerialNumber(mchSerialNo)
                        .apiV3Key(apiV3Key)
                        .build();

        // 从请求头中获取信息
        String timestamp                        = request.getHeader("Wechatpay-Timestamp");
        String nonce                            = request.getHeader("Wechatpay-Nonce");
        String signature                        = request.getHeader("Wechatpay-Signature");
        String singType                         = request.getHeader("Wechatpay-Signature-Type");
        String wechatPayCertificateSerialNumber = request.getHeader("Wechatpay-Serial");

        String requestBody = getRequestBody(request);

        // 构造 RequestParam
        RequestParam requestParam = new RequestParam.Builder()
                .serialNumber(wechatPayCertificateSerialNumber)
                .nonce(nonce)
                .signature(signature)
                .signType(singType)
                .timestamp(timestamp)
                .body(requestBody)
                .build();

        // 初始化解析器 NotificationParser
        NotificationParser parser = new NotificationParser((NotificationConfig) config);

        // 这个Transaction是微信包里面的
        Transaction decryptObject = parser.parse(requestParam, Transaction.class);

        TransactionAmount amount = decryptObject.getAmount();
        String outTradeNo = decryptObject.getOutTradeNo();
        String attach = decryptObject.getAttach();

        Map map=new HashMap();
        map.put("amount",amount.getTotal());
        map.put("outTradeNo",outTradeNo);
        map.put("attach",attach);
        return map;
    }

    public Map refundSuccessCheck(HttpServletRequest request) {
        Config config =
                new RSAAutoCertificateConfig.Builder()
                        .merchantId(mchId)
                        .privateKey(privateKey)
                        .merchantSerialNumber(mchSerialNo)
                        .apiV3Key(apiV3Key)
                        .build();

        // 从请求头中获取信息
        String timestamp                        = request.getHeader("Wechatpay-Timestamp");
        String nonce                            = request.getHeader("Wechatpay-Nonce");
        String signature                        = request.getHeader("Wechatpay-Signature");
        String singType                         = request.getHeader("Wechatpay-Signature-Type");
        String wechatPayCertificateSerialNumber = request.getHeader("Wechatpay-Serial");

        String requestBody = getRequestBody(request);

        // 构造 RequestParam
        RequestParam requestParam = new RequestParam.Builder()
                .serialNumber(wechatPayCertificateSerialNumber)
                .nonce(nonce)
                .signature(signature)
                .signType(singType)
                .timestamp(timestamp)
                .body(requestBody)
                .build();

        // 初始化解析器 NotificationParser
        NotificationParser parser = new NotificationParser((NotificationConfig) config);

        // 这个Transaction是微信包里面的
        RefundNotification decryptObject = parser.parse(requestParam, RefundNotification.class);

        com.wechat.pay.java.service.refund.model.Amount amount = decryptObject.getAmount();
        String outTradeNo = decryptObject.getOutTradeNo();

        Map map=new HashMap();
        map.put("amount",amount.getTotal());
        map.put("outTradeNo",outTradeNo);
        return map;
    }

    // 获取请求头里的数据
    private String getRequestBody(HttpServletRequest request) {
        StringBuffer sb = new StringBuffer();
        try (
                ServletInputStream inputStream = request.getInputStream();
                BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream));
        ) {
            String line;
            while ((line = reader.readLine()) != null) {
                sb.append(line);
            }
        } catch (IOException e) {
            System.out.println("读取数据流异常:"+e);
        }
        return sb.toString();
    }

    /**
     * 组装支付参数
     * @param appid
     * @param privateKey
     * @param prepayId
     * @return
     */
    public Map getPayParameter(String prepayId){
        Map<String,String> map=new HashMap<>();
        map.put("appId",appid);
        map.put("partnerId",mchId);
        map.put("prepayId",prepayId);
        map.put("packageValue","Sign=WXPay");
        map.put("nonceStr",UUID.randomUUID().toString().replace("-",""));
        map.put("timeStamp",String.valueOf(new Date().getTime()));

        String s = map.get("appId") + "\n" + map.get("timeStamp") + "\n" + map.get("nonceStr") + "\n" + map.get("prepayId") + "\n";
        try {
            PrivateKey privateKey1 = PemUtil.loadPrivateKeyFromString(privateKey);
            Signature sign = Signature.getInstance("SHA256withRSA");
            sign.initSign(privateKey1);
            sign.update(s.getBytes("utf-8"));
            String string = Base64.getEncoder().encodeToString(sign.sign());
            map.put("sign",string);
            return map;
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
        } catch (InvalidKeyException e) {
            e.printStackTrace();
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        } catch (SignatureException e) {
            e.printStackTrace();
        }
        return null;
    }
}

调用方法

 //微信支付
            String pay = weChatPaymentApiV3.pay(payParam);
            Map payParameter = weChatPaymentApiV3.getPayParameter(pay);
            rmap.put("pay",payParameter);

回调处理

package com.ruoyi.web.controller.paymentnotify;

import com.github.binarywang.wxpay.bean.notify.WxPayNotifyResponse;
import com.github.binarywang.wxpay.bean.notify.WxPayOrderNotifyResult;
import com.github.binarywang.wxpay.bean.notify.WxPayRefundNotifyResult;
import com.github.binarywang.wxpay.config.WxPayConfig;
import com.github.binarywang.wxpay.exception.WxPayException;
import com.github.binarywang.wxpay.service.WxPayService;
import com.github.binarywang.wxpay.service.impl.WxPayServiceImpl;
import com.ruoyi.business.payment.WeChatPayment;
import com.ruoyi.business.payment.event.PaymentEvent;
import com.ruoyi.common.utils.StringUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.servlet.http.HttpServletResponse;
import java.math.BigDecimal;
import java.util.HashMap;
import java.util.Map;

/**
 * 商城支付项微信支付的回调接口
 */
@Slf4j
@RestController
@RequestMapping("/payment/weChatPay")
public class WeChatPayNotify {
    @Autowired
    private ApplicationEventPublisher publisher;
    /**
     * 微信支付/充值回调
     */
    @PostMapping("/payment/notify")
    public String  renotify(@RequestBody String xmlData) {
        try {
            WxPayConfig payConfig = new WxPayConfig();
            payConfig.setAppId(WeChatPayment.appId);
            payConfig.setMchId(WeChatPayment.mchId);
            payConfig.setMchKey(WeChatPayment.mchKey);
            payConfig.setKeyPath(WeChatPayment.keyPath);
            // 可以指定是否使用沙箱环境
            payConfig.setUseSandboxEnv(false);
            WxPayService wxPayService = new WxPayServiceImpl();
            wxPayService.setConfig(payConfig);

            WxPayOrderNotifyResult notifyResult = wxPayService.parseOrderNotifyResult(xmlData);
            String orderId = notifyResult.getOutTradeNo();
            String attach = notifyResult.getAttach();

            //获取回传参数paymentType
            Map<String,String> map=new HashMap<>();
            if(StringUtils.isNotBlank(attach)){
                String[] split = StringUtils.split(attach, ";");
                for (int i=0;i<split.length;i++){
                    String[] split1 = StringUtils.split(split[i], "=");
                    map.put(split1[0],split1[1]);
                }
            }

            publisher.publishEvent(new PaymentEvent(this, orderId,0,map));
            return WxPayNotifyResponse.success("OK");
        } catch (WxPayException e) {
            log.error(e.getMessage());
            return WxPayNotifyResponse.fail(e.getMessage());
        }

    }

    /**
     * 微信退款回调
     */
    @PostMapping("/refund/notify")
    @Transactional(rollbackFor=Exception.class)
    public String parseRefundNotifyResult(@RequestBody String xmlData, HttpServletResponse response) {
        try {
            WxPayConfig payConfig = new WxPayConfig();
            payConfig.setAppId(WeChatPayment.appId);
            payConfig.setMchId(WeChatPayment.mchId);
            payConfig.setMchKey(WeChatPayment.mchKey);
            payConfig.setKeyPath(WeChatPayment.keyPath);
            // 可以指定是否使用沙箱环境
            payConfig.setUseSandboxEnv(false);
            WxPayService wxPayService = new WxPayServiceImpl();
            wxPayService.setConfig(payConfig);

            WxPayRefundNotifyResult result = wxPayService.parseRefundNotifyResult(xmlData);
            String orderId = result.getReqInfo().getOutTradeNo();
            Integer refundFee1 = result.getReqInfo().getRefundFee();
            //退款金额
            BigDecimal refundFee = new BigDecimal(refundFee1).divide(new BigDecimal("100"));

            publisher.publishEvent(new PaymentEvent(this, orderId,1,null));
            return WxPayNotifyResponse.success("OK");
        } catch (WxPayException e) {
            log.error(e.getMessage());
            return WxPayNotifyResponse.fail(e.getMessage());
        }
    }
}

与项目集成可参考

https://blog.csdn.net/qq_31683775/article/details/132381519

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值