使用wechatpay-apache-httpclient接入微信ApiV3详细步骤

作者:青山常在人不老   阅读 (594)  |  收藏 (0)  |  点赞 (0)

摘要

本文将会结合自己的实际步骤讲解如何使用微信SDK接入微信APIV3支付,同时会讲解期间的一些坑


原文链接:使用wechatpay-apache-httpclient接入微信ApiV3详细步骤

接入微信支付,要有微信商家平台账号(登录注册地址),微信公众平台账号(登录注册地址),本文使用微信小程序完成接入。

一、生成商家证书

首先登录微信商家平台,进入"账户中心-->账户设置-->API安全",申请API证书(此证书为商户证书,跟下文的APIV3支付证书不一样),下载安装方式见官方文档:什么是商户API证书?如何获取商户API证书? (qq.com)

经过上面链接中的教程,你将会在本地得到如下三个文件:

image.png

我们将在下面用到这几个文件中的apiclient_key.pem

二、生成APIV3支付证书

这一步至关重要,因为很多人接入的时候由于官方文档写的很笼统而忽略此步,再调用API的时候错误的使用第一步中生成的证书,导致签名验证微信返回的内容时不成功,而爆出如下的错误:应答的微信支付签名验证失败

关于这个错误,其实只需要按照本文的此步生成APIV3的支付证书即可。

1、下载APIV3证书生成工具

这里下载jar包

2、执行命令生成V3证书

执行:“java -jar CertificateDownloader-1.1.jar -f 商户私钥文件路径 -k 证书解密的密钥 -m 商户号 -o 证书保存路径 -s 商户证书序列号”就行了。

这条命令的参数搞清楚3点:

a)“商户私钥文件路径”是账号中心->API安全->API证书中设置并下载的证书(就是其中的apiclient_key.pem,下载还会获得apiclient_cert.pem,我之前把这个当做支付证书了,其实不是,apiclient_cert.pem这用不着)

b)“商户证书序列号”这个东西也是设置API证书那里知道;

c)“证书解密的密钥”在账号中心->API安全->APIv3密钥中设置的(注意api密钥和apiv3密钥是2个东西)。

执行完了是个类似wechatpay_267E31F15F097EC70CC6B6C56919D2605966123D.pem的文件。

三、Java接入实现预订单生成

1、将wechatpay-apache-httpclient引入maven

<!-- 微信支付API -->
<dependency>
   <groupId>com.github.wechatpay-apiv3</groupId>
   <artifactId>wechatpay-apache-httpclient</artifactId>
   <version>0.4.4</version>
</dependency>

 其他方式引入方式以及最新版本的依赖参见官方仓库

2、自己创建一个微信支付工具类

package com.diyan.yihuijia.utils.pay.wechat;

import com.alibaba.fastjson.JSONObject;
import com.diyan.yihuijia.config.wechat.WeChatConfig;
import com.wechat.pay.contrib.apache.httpclient.WechatPayHttpClientBuilder;
import com.wechat.pay.contrib.apache.httpclient.util.PemUtil;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.util.EntityUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.io.ByteArrayInputStream;
import java.nio.charset.StandardCharsets;
import java.security.PrivateKey;
import java.security.cert.X509Certificate;
import java.util.ArrayList;

@Component
public class WXPayUtils {

    @Autowired
    private WeChatConfig weChatConfig;

    private static final String APPLICATION_JSON = "application/json";
    private static final String mchId = "商户号"; // 商户号
    private static final String mchSerialNo = "第一步申请完证书后,在API证书哪里点击管理证书就能看到"; // 商户证书序列号
    private static final String requestBody = "{\n"
            + "    \"stock_id\": \"9433645\",\n"
            + "    \"stock_creator_mchid\": \"1900006511\",\n"
            + "    \"out_request_no\": \"20190522_001中文11\",\n"
            + "    \"appid\": \"wxab8acb865bb1637e\"\n"
            + "}";
    // 你的商户私钥
    private static final String privateKey = "第一步中生成的apiclient_key.pem内容";
    // 你的微信支付平台证书
    private static final String certificate = "第二步中生成的wechatpay_267E31F15F097EC70CC6B6C56919D2605966123D.pem内容";
    private CloseableHttpClient httpClient;

    public void setup() {
        PrivateKey merchantPrivateKey = PemUtil.loadPrivateKey(privateKey);
        X509Certificate wechatPayCertificate = PemUtil.loadCertificate(
                new ByteArrayInputStream(certificate.getBytes(StandardCharsets.UTF_8)));

        ArrayList<X509Certificate> listCertificates = new ArrayList<>();
        listCertificates.add(wechatPayCertificate);

        WechatPayHttpClientBuilder builder = WechatPayHttpClientBuilder.create()
                .withMerchant(mchId,mchSerialNo, PemUtil.loadPrivateKey(privateKey))
                .withWechatPay(listCertificates);
        httpClient = builder.build();
    }
    /**
     *wxMchid商户号
     *wxCertno证书编号
     *wxCertPath证书地址
     *wxPaternerKey   v3秘钥
     *url jsapi下单地址
     *body 构造好的消息体
     */
    public JSONObject doPostWexinV3(String url, String body) {
        if (httpClient == null) {
            setup();
        }

        HttpPost httpPost  = new HttpPost(url);
        httpPost.addHeader("Content-Type","application/json;chartset=utf-8");
        httpPost.addHeader("Accept", "application/json");
        try{
            if(body==null){
                throw  new IllegalArgumentException("data参数不能为空");
            }
            StringEntity stringEntity = new StringEntity(body,"utf-8");
            httpPost.setEntity(stringEntity);
            // 直接执行execute方法,官方会自动处理签名和验签,并进行证书自动更新
            HttpResponse httpResponse = httpClient.execute(httpPost);
            HttpEntity httpEntity = httpResponse.getEntity();

            if(httpResponse.getStatusLine().getStatusCode() == 200){
                String jsonResult = EntityUtils.toString(httpEntity);
                return JSONObject.parseObject(jsonResult);
            }else{
                System.err.println("微信支付错误信息"+EntityUtils.toString(httpEntity));
            }
        }catch (Exception e){
            e.printStackTrace();
        }
        return null;
    }

3、编写测试方法,调用微信V3接口生成预支付订单号

package com.xxx.xxx;

import com.alibaba.fastjson.JSONObject;
import com.xxxx.x.utils.pay.wechat.WXPayUtils;
import lombok.extern.slf4j.Slf4j;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;

/**
 * 参考文档: https://wechatpay-api.gitbook.io/wechatpay-api-v3/chang-jian-wen-ti/zheng-shu-xiang-guan#ru-he-cha-kan-zheng-shu-xu-lie-hao
 * 小程序支付: https://pay.weixin.qq.com/wiki/doc/apiv3/apis/chapter3_5_1.shtml
 */
@SpringBootTest
@Slf4j
public class TestWXOrderClass {

    @Autowired
    private WXPayUtils wxPayUtils;

    @Test
    public void testPay() {
        JSONObject jsonObject = buildWxJsApiPayJson('你的公众平台小程序等appid', '商户id', "测试商品描述",
                "20220304215501111", "https://www.baidu.com", "2",
                "用户在你的公众平台下的唯一标识,登录后能获取");
        JSONObject jsonObject1 = wxPayUtils.doPostWexinV3("https://api.mch.weixin.qq.com/v3/pay/transactions/jsapi", jsonObject.toJSONString());
        System.out.println(jsonObject1.toJSONString());
    }


    /**
     * 构造微信JsApi付款的json
     * @param appid
     * @param mchid
     * @param description
     * @param out_trade_no
     * @param notify_url
     * @param amount
     * @return
     */
    public JSONObject buildWxJsApiPayJson(String appid , String mchid ,
                                                 String description ,
                                                 String out_trade_no ,
                                                 String notify_url ,
                                                 String amount,
                                                 String openId){

        //订单金额json
        JSONObject amountJson = new JSONObject();
        amountJson.put("total",Integer.valueOf(amount));
        amountJson.put("currency","CNY");

        //支付者json
        JSONObject payerJson = new JSONObject();
        payerJson.put("openid",openId);

        //基础信息json
        JSONObject json = new JSONObject();
        json.put("appid",appid);
        json.put("mchid",mchid);
        json.put("description",description);
        json.put("out_trade_no",out_trade_no);
        json.put("notify_url",notify_url);
        json.put("amount",amountJson);
        json.put("payer",payerJson);
        return json;
    }

}

好了,通过上面步骤就能完整生成微信预支付订单,如果有问题请下面留言,或者加我微信号:gpf_18253

分类   Spring boot 开发
字数   6968

博客标签    接入微信ApiV3   wechatpay-apache-httpclient  

评论