wechatpay-apiv3/wechatpay-java对接微信支付V3-亲测可用

前言

  因项目集成新项目,app嵌套业务板块实现对接后台新项目,新项目对接的是V2版本微信支付APP使用的sdk是V3版本,和后台对接微信V2版本不适配,app调用微信APP支付sdk提示签名错误,升级后台对接微信支付V3版本后解决微信SDK适配问题。

对接微信支付V3版本

微信支付V3-github:

https://github.com/wechatpay-apiv3/wechatpay-java

微信支付使用示例:

https://github.com/wechatpay-apiv3/wechatpay-java/tree/main/service/src/example/java/com/wechat/pay/java/service

wechatpay-apiv3/wechatpay-java对接微信支付V3-亲测可用_第1张图片

pom.xml 添加依赖



    com.github.wxpay
    wxpay-sdk
    0.0.3


    com.github.wechatpay-apiv3
    wechatpay-java
    0.2.17


    com.github.binarywang
    weixin-java-pay
    ${binarywang.weixin.java.version}

 微信app支付-发起支付 

import com.github.binarywang.wxpay.v3.util.PemUtils;
import com.github.binarywang.wxpay.v3.util.SignUtils;
import com.wechat.pay.java.core.Config;
import com.wechat.pay.java.core.RSAAutoCertificateConfig;
import com.wechat.pay.java.service.payments.app.AppService;
import com.wechat.pay.java.service.payments.app.model.Amount;
import com.wechat.pay.java.service.payments.app.model.PrepayRequest;
import com.wechat.pay.java.service.payments.app.model.PrepayResponse;


    public Map createPay(){
        Map returnMap = new HashMap<>();
        try {
            // 初始化微信支付配置工具类
            WXConfigUtil config = new WXConfigUtil();

            //更新证书配置,这里用官方sdk,不需要考虑时效性问题
            Config wxConfig = new RSAAutoCertificateConfig.Builder()
                    .merchantId(config.getMchID())
                    .privateKeyFromPath(config.getPrivateKeyFromPath())//微信v3-私钥路径 例:/app/www/cert/apiclient_key.pem
                    .merchantSerialNumber(config.getCertSerialNum())//微信v3证书序列号
                    .apiV3Key(config.getApiV3Key())//微信v3-apiV3Key
                    .build();


            AppService service = new AppService.Builder().config(wxConfig).build();


            PrepayRequest wxRequest = new PrepayRequest();
            wxRequest.setAppid(config.getAppID());//appId
            wxRequest.setMchid(config.getMchID());//商户id
            wxRequest.setDescription(goodsName);//备注
            wxRequest.setOutTradeNo(outTradeNo);//订单号
            wxRequest.setNotifyUrl(config.NOTIFY_URL_APP);//回调地址
            Amount amount = new Amount();
            amount.setTotal(totalPrice.multiply(BigDecimal.valueOf(100)).intValueExact());//支付金额
            wxRequest.setAmount(amount);
            //调用预支付接口
            PrepayResponse prepay = service.prepay(wxRequest);
            log.info("预支付:{}",prepay.toString());
            //主要返回以下5个参数(必须按照顺序,否则APP报错:-1)
            returnMap.put("appid", config.getAppID());
            returnMap.put("noncestr", this.create_nonce_str());
            returnMap.put("package","Sign=WXPay");
            returnMap.put("partnerid", config.getMchID());
            returnMap.put("prepayid", prepay.getPrepayId());
            //单位为秒
            returnMap.put("timestamp", String.valueOf(System.currentTimeMillis() / 1000));
            //签名
            // 此map用于客户端与微信服务器交互
            String beforeSign = String.format("%s\n%s\n%s\n%s\n", returnMap.get("appid"), returnMap.get("timestamp"), returnMap.get("noncestr"), returnMap.get("prepayid"));
            returnMap.put("sign",SignUtils.sign(beforeSign, PemUtils.loadPrivateKey(new FileInputStream(config.getPrivateKeyFromPath()))));
            return returnMap;
        } catch (Exception e) {
            e.printStackTrace();
            log.error("微信app支付v3异常:{}",e.getMessage());
        }
        return returnMap;
    }


	// 生成随机数
	public String create_nonce_str() {
		String chars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
		String res = "";
		for (int i = 0; i < 16; i++) {
			Random rd = new Random();
			res += chars.charAt(rd.nextInt(chars.length() - 1));
		}
		return res;
	}

微信app支付-支付成功回调验签


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 javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import java.io.BufferedReader;
import java.io.ByteArrayOutputStream;
import java.io.InputStream;
import java.io.StringReader;
import java.math.BigDecimal;
import java.nio.charset.StandardCharsets;
import java.text.SimpleDateFormat;
import java.util.*;

    @Override
    @GlobalTransactional(rollbackFor = Exception.class)
    public String notifyWeiXinPay(HttpServletRequest request, HttpServletResponse response) {
        log.info("------支付成功,进入回调notifyWeiXinPay------");

        try {
            Map return_data = new HashMap();

            WxPayAppNotifyDTO wxPayAppNotifyDTO = new WxPayAppNotifyDTO();
            if (request.getHeader("Wechatpay-Signature") != null) {//V3版本
                wxPayAppNotifyDTO.setPayVersionType(23);
                // 请求头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");
                // 签名方式
                String signType = request.getHeader("Wechatpay-Signature-Type");
                //请求body
                BufferedReader br = request.getReader();
                String str = null;
                StringBuilder sb = new StringBuilder();
                while ((str = br.readLine()) != null) {
                    sb.append(str);
                }
                br.close();


                // 初始化微信支付配置工具类
                WXConfigUtil config = new WXConfigUtil();

                // 构造 RequestParam
                RequestParam requestParam = new RequestParam.Builder()
                        .serialNumber(serial)
                        .nonce(nonce)
                        .signature(signature)
                        .timestamp(timestamp)
                        .signType(signType)
                        .body(String.valueOf(sb))
                        .build();


                // 2. 如果你仍在使用微信支付平台证书,则使用 RSAAutoCertificateConfig
                NotificationConfig wxConfig = new RSAAutoCertificateConfig.Builder()
                        .merchantId(config.getMchID())
                        .privateKeyFromPath(config.getPrivateKeyFromPath())
                        .merchantSerialNumber(config.getCertSerialNum())
                        .apiV3Key(config.getApiV3Key())
                        .build();

                // 初始化 NotificationParser
                NotificationParser parser = new NotificationParser(wxConfig);
                // 以支付通知回调为例,验签、解密并转换成 Transaction
                log.info("验签参数:{}", requestParam);
                Transaction transaction = parser.parse(requestParam, Transaction.class);
                log.info("验签成功!-支付回调结果:{}", transaction.toString());

                wxPayAppNotifyDTO.setOutTradeNo(transaction.getOutTradeNo());
                wxPayAppNotifyDTO.setMchId(transaction.getMchid());
                wxPayAppNotifyDTO.setTotalFee(transaction.getAmount().getTotal().toString());
                wxPayAppNotifyDTO.setTransactionId(transaction.getTransactionId());

            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return "success";
    }

wechatpay-apiv3/wechatpay-java对接微信支付V3-亲测可用_第2张图片

微信app支付-退款 

import com.wechat.pay.java.core.Config;
import com.wechat.pay.java.core.RSAAutoCertificateConfig;
import com.wechat.pay.java.core.http.*;
import com.wechat.pay.java.core.http.HttpClient;
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;   
 /**
     * 退款申请
     *
     * @param request 请求参数
     * @return Refund
     * @throws HttpException 发送HTTP请求失败。例如构建请求参数失败、发送请求失败、I/O错误等。包含请求信息。
     * @throws ValidationException 发送HTTP请求成功,验证微信支付返回签名失败。
     * @throws ServiceException 发送HTTP请求成功,服务返回异常。例如返回状态码小于200或大于等于300。
     * @throws MalformedMessageException 服务返回成功,content-type不为application/json、解析返回体失败。
     */
    public Boolean create(CreateRequest request) {
        try{

            String requestPath = "https://api.mch.weixin.qq.com/v3/refund/domestic/refunds";
            // 初始化微信支付配置工具类
            WXConfigUtil config = new WXConfigUtil();

            //更新证书配置,这里用官方sdk,不需要考虑时效性问题
            Config wxConfig = new RSAAutoCertificateConfig.Builder()
                    .merchantId(config.getMchID())
                    .privateKeyFromPath(config.getPrivateKeyFromPath())
                    .merchantSerialNumber(config.getCertSerialNum())
                    .apiV3Key(config.getApiV3Key())
                    .build();
            HttpHeaders headers = new HttpHeaders();
            headers.addHeader(com.wechat.pay.java.core.http.Constant.ACCEPT, MediaType.APPLICATION_JSON.getValue());
            headers.addHeader(com.wechat.pay.java.core.http.Constant.CONTENT_TYPE, MediaType.APPLICATION_JSON.getValue());
            HttpRequest httpRequest =
                    new HttpRequest.Builder()
                            .httpMethod(HttpMethod.POST)
                            .url(requestPath)
                            .headers(headers)
                            .body(new JsonRequestBody.Builder().body(com.wechat.pay.java.core.util.GsonUtil.toJson(request)).build())
                            .build();

            HttpClient httpClient = new DefaultHttpClientBuilder().config(wxConfig).build();

            HttpResponse httpResponse = httpClient.execute(httpRequest, Refund.class);
            httpResponse.getServiceResponse();
        return true;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return false;
    }

    
    //填写参数调用退款
    public Boolean weChatRefund(){
        CreateRequest request = new CreateRequest();

        AmountReq amountReq = new AmountReq();
        amountReq.setTotal(Long.parseLong(PayToolUtil.getMoney(allMoney.toString())));
        amountReq.setRefund(Long.parseLong(PayToolUtil.getMoney(money.toString())));
        amountReq.setCurrency("CNY");
        request.setAmount(amountReq);

        request.setOutRefundNo(refundOrderId);
        request.setTransactionId(paymentOtherNumber);

        return create(request);
    }

你可能感兴趣的:(微信,java,微信开放平台)