摘要
本文将会结合自己的实际步骤讲解如何使用微信SDK接入微信APIV3支付,同时会讲解期间的一些坑
本文将会结合自己的实际步骤讲解如何使用微信SDK接入微信APIV3支付,同时会讲解期间的一些坑
接入微信支付,要有微信商家平台账号(登录注册地址),微信公众平台账号(登录注册地址),本文使用微信小程序完成接入。
首先登录微信商家平台,进入"账户中心-->账户设置-->API安全",申请API证书(此证书为商户证书,跟下文的APIV3支付证书不一样),下载安装方式见官方文档:什么是商户API证书?如何获取商户API证书? (qq.com)
经过上面链接中的教程,你将会在本地得到如下三个文件:
我们将在下面用到这几个文件中的apiclient_key.pem
这一步至关重要,因为很多人接入的时候由于官方文档写的很笼统而忽略此步,再调用API的时候错误的使用第一步中生成的证书,导致签名验证微信返回的内容时不成功,而爆出如下的错误:应答的微信支付签名验证失败
关于这个错误,其实只需要按照本文的此步生成APIV3的支付证书即可。
在这里下载jar包
执行:“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的文件。
<!-- 微信支付API --> <dependency> <groupId>com.github.wechatpay-apiv3</groupId> <artifactId>wechatpay-apache-httpclient</artifactId> <version>0.4.4</version> </dependency>
其他方式引入方式以及最新版本的依赖参见官方仓库
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; }
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