微信支付API v3接口使用应用篇
目录
- 前言
- 版本
- 应用
- 基础配置
- 1.申请商户API证书
- 2.设置接口密钥
- 3.下载平台证书
- 接口实测
- 微信支付API官方客户端
- 1.客户端
- 2.支付调起参数签名
- 3.回调通知
- 参考资料
前言
最近新项目中有涉及到微信支付相关接口业务的交互,毕竟原先开发接触过支付这块,轻车熟路。打开微信支付官方文档,好家伙,微信支付API 升级至v3版本了,心中一万匹草泥马奔涌而来,根据以往对微信开发文档的认识,赶紧倒杯水,喝一喝,压压惊。
喝完之后,开启了微信支付API v3的对接之路。
版本
jdk:1.8
wechatpay-apache-httpclient:0.2.2
应用
笔者以微信小程序支付接口为例展开说明,至于小程序注册、认证、微信支付注册本文概不说明。
基础配置
1.申请商户API证书
登录微信支付后台,进入账户中心,API安全设置,如下图
申请商户证书,如下图
点击“申请证书”按钮后,弹出生成API证书申请框,如下图
根据提示下载证书工具,当前页面不要关闭,下载证书工具后打开,如下图
点击“申请证书”按钮后,进入填写商户信息界面,商户信息经测试是自动填充的,如下图
点击“下一步”,进入复制请求串界面,如下图
将证书请求串进行复制,复制后回到上述微信支付后台申请API证书页面,将请求串进行复制,经测试自动帮你完成复制粘贴,请求串复制后点击“下一步”操作,进入复制证书串步骤,如下图
点击“复制证书串”,将复制的证书串粘贴至证书工具中,如下图
点击“下一步”完成商户证书的申请,如下图
商户API证书已生成,点击查看证书文件夹,即可查看证书信息,如下图
在微信支付商户后台可获取商户API证书序列号及证书有效期,如下图
2.设置接口密钥
设置API密钥,现阶段由于微信支付原先老接口并未全部升级至API v3版,涉及新老接口共存的情况,所以API密钥及APIV3密钥都需进行设置,新老接口请查阅微信支付开发文档
API v2老版本密钥设置
API v3密钥设置
3.下载平台证书
微信平台证书下载,查阅开发文档,微信已提供证书下载工具 如下图
关注本文末尾微信公众号,回复“666”获取常用开发工具包,内含常用开发组件及微信证书下载工具,节省翻墙下载时间。
下载平台证书至本地,执行命令
必需参数有:商户的私钥文件,即 -f (商户API证书中apiclient_key.pem文件路径)
证书解密的密钥,即 -k (微信支付后台设置的APIv3密钥)
商户号,即 -m (微信支付商户号,可在微信支付后台查阅)
保存证书的路径,即 -o (微信平台证书保存路径)
商户证书的序列号,即 -s (商户API证书,即上述第一步申请商户API证书序列号)
非必需参数有:微信支付证书,用于验签,即 -c完整命令如下java -jar CertificateDownloader-1.1.jar -k ${apiV3key} -m ${mchId} -f ${mchPrivateKeyFilePath} -s ${mchSerialNo} -o ${outputFilePath}
至此基础配置参数已准备就绪
接口实测
在请求接口之前先了解下接口中一些参数概念,首次接触最容易搞混的就是商户API证书和平台证书,如下图
微信支付API官方客户端
以往老吐槽微信支付接口文档不友好,没有sdk,现在API v3版本给你提供了一个客户端,这点还是可以点赞的,对于开发人员来说,demo代码直接拿过来,更改下配置参数就可以跑通,那简直是对程序员莫大的关怀,这方面阿里相对做的比较好
talk is cheap, show me the code
1.客户端
以post请求方式说明,get请求类似
private static String basePostRequest(String requestUrl,String requestJson) {CloseableHttpClient httpClient = null;CloseableHttpResponse response = null;HttpEntity entity = null;try {PrivateKey merchantPrivateKey = PemUtil.loadPrivateKey(new ByteArrayInputStream(privateKey.getBytes("utf-8")));X509Certificate wechatpayCertificate = PemUtil.loadCertificate(new ByteArrayInputStream(certificate.getBytes("utf-8")));ArrayList<X509Certificate> listCertificates = new ArrayList<>();listCertificates.add(wechatpayCertificate);httpClient = WechatPayHttpClientBuilder.create().withMerchant(mchId, mchSerialNo, merchantPrivateKey).withWechatpay(listCertificates).build();HttpPost httpPost = new HttpPost(requestUrl);// NOTE: 建议指定charset=utf-8。低于4.4.6版本的HttpCore,不能正确的设置字符集,可能导致签名错误StringEntity reqEntity = new StringEntity(requestJson, ContentType.create("application/json", "utf-8"));httpPost.setEntity(reqEntity);httpPost.addHeader("Accept", "application/json");response = httpClient.execute(httpPost);entity = response.getEntity();return EntityUtils.toString(entity);} catch (Exception e) {e.printStackTrace();} finally {// 关闭流}return null;}
方法中涉及参数说明
参数名 | 说明 |
---|---|
privateKey | 商户私钥(商户API证书apiclient_key.pem文件内容) |
certificate | 平台证书(通过CertificateDownloader下载的证书文件内容) |
mchId | 微信支付商户号 |
mchSerialNo | 商户API证书序列号 |
PemUtil.java类为com.wechat.pay.contrib.apache.httpclient.util.PemUtil
请求签名及应答签名校验该客户端均已帮你处理好,心中对微信支付开发文档有了一点点好感。根据具体接口方法传入接口地址及相应接口参数JSON数据即可完成接口联调测试。
2.支付调起参数签名
以小程序调起支付接口为例,简单说明参数签名方式,先看下文档中签名是怎么说的,如下图
/*** 微信支付-前端唤起支付参数* prepay_id=wx201410272009395522657a690389285100* @param packageStr 预下单接口返回数据 预支付交易会话标识 prepay_id* @return*/public static Map<String,Object> createPayParams(String packageStr) {Map<String,Object> resultMap = new HashMap<>();String nonceStr = StringUtil.getUUID();Long timestamp = System.currentTimeMillis() / 1000;String message = buildMessage(timestamp, nonceStr, packageStr);String signature = null;try {signature = sign(message.getBytes("utf-8"));} catch (UnsupportedEncodingException e) {e.printStackTrace();}resultMap.put("appId", appId);resultMap.put("timeStamp",timestamp.toString());resultMap.put("nonceStr",nonceStr);resultMap.put("package",packageStr);resultMap.put("signType","RSA");resultMap.put("paySign",signature);return resultMap;}/*** 微信支付-前端唤起支付参数-签名* @param message 签名数据* @return*/public static String sign(byte[] message) {try{Signature sign = Signature.getInstance("SHA256withRSA");sign.initSign(getPrivateKey(keyFilePath));sign.update(message);return Base64.getEncoder().encodeToString(sign.sign());} catch(Exception e) {e.printStackTrace();}return null;}/*** 微信支付-前端唤起支付参数-构建签名参数* @param nonceStr 签名数据* @return*/public static String buildMessage(long timestamp, String nonceStr, String packageStr) {return appId + "\n"+ timestamp + "\n"+ nonceStr + "\n"+ packageStr + "\n";}/*** 微信支付-前端唤起支付参数-获取商户私钥** @param filename 私钥文件路径 (required)* @return 私钥对象*/public static PrivateKey getPrivateKey(String filename) throws IOException {String content = new String(Files.readAllBytes(Paths.get(filename)), "utf-8");try {String privateKey = content.replace("-----BEGIN PRIVATE KEY-----", "").replace("-----END PRIVATE KEY-----", "").replaceAll("\\s+", "");KeyFactory kf = KeyFactory.getInstance("RSA");return kf.generatePrivate(new PKCS8EncodedKeySpec(Base64.getDecoder().decode(privateKey)));} catch (NoSuchAlgorithmException e) {throw new RuntimeException("当前Java环境不支持RSA", e);} catch (InvalidKeySpecException e) {throw new RuntimeException("无效的密钥格式");}}
方法中涉及参数说明
参数名 | 说明 |
---|---|
appId | 小程序appid |
keyFilePath | 商户API证书apiclient_key.pem路径 |
3.回调通知
回调通知涉及验签及解密
回调数据获取
String body = request.getReader().lines().collect(Collectors.joining());
验签
/*** 回调验签* https://pay.weixin.qq.com/wiki/doc/apiv3/wechatpay/wechatpay4_1.shtml* @param wechatpaySerial 回调head头部* @param wechatpaySignature 回调head头部* @param wechatpayTimestamp 回调head头部* @param wechatpayNonce 回调head头部* @param body 请求数据* @return*/public static boolean responseSignVerify(String wechatpaySerial, String wechatpaySignature, String wechatpayTimestamp, String wechatpayNonce, String body) {FileInputStream fileInputStream = null;try {String signatureStr = buildMessage(wechatpayTimestamp, wechatpayNonce, body);Signature signer = Signature.getInstance("SHA256withRSA");fileInputStream = new FileInputStream(weixin_platform_cert_path);X509Certificate receivedCertificate = loadCertificate(fileInputStream);signer.initVerify(receivedCertificate);signer.update(signatureStr.getBytes(StandardCharsets.UTF_8));return signer.verify(Base64.getDecoder().decode(wechatpaySignature));} catch (Exception e ) {e.printStackTrace();} finally {if (fileInputStream != null) {try {fileInputStream.close();} catch (IOException e) {e.printStackTrace();}}}return false;}/*** 回调验签-加载微信平台证书* @param inputStream* @return*/public static X509Certificate loadCertificate(InputStream inputStream) {try {CertificateFactory cf = CertificateFactory.getInstance("X509");X509Certificate cert = (X509Certificate) cf.generateCertificate(inputStream);cert.checkValidity();return cert;} catch (CertificateExpiredException e) {throw new RuntimeException("证书已过期", e);} catch (CertificateNotYetValidException e) {throw new RuntimeException("证书尚未生效", e);} catch (CertificateException e) {throw new RuntimeException("无效的证书", e);}}/*** 回调验签-构建签名数据* @param * @return*/public static String buildMessage(String wechatpayTimestamp, String wechatpayNonce, String body) {return wechatpayTimestamp + "\n"+ wechatpayNonce + "\n"+ body + "\n";}
方法中涉及参数说明
参数名 | 说明 |
---|---|
weixin_platform_cert_path | 微信平台证书路径 |
解密
// https://pay.weixin.qq.com/wiki/doc/apiv3/apis/chapter3_1_5.shtml
AesUtil wxAesUtil = new AesUtil(apiv3.getBytes());
String jsonStr = wxAesUtil.decryptToString("associated_data".getBytes(),"nonce".getBytes(),"ciphertext");
方法中涉及参数说明
参数名 | 说明 |
---|---|
apiv3 | 商户API v3密钥 |
associated_data | 附加数据 (微信回调通知数据中resource对象) |
nonce | nonce (微信回调通知数据中resource对象) |
ciphertext | 数据密文 (微信回调通知数据中resource对象) |
jsonStr | 对resource对象进行解密后,得到的资源对象数据 |
参考资料
微信支付开发文档
平台证书下载工具
微信支付API v3文档介绍
微信支付API客户端
微信支付API v3接口使用应用篇相关推荐
- 微信支付API V3版本JAVA开发指南
微信支付版本V3的Demo,在官方上下载下来,压根就是不能直接用的东西,你要想学会用,你就得一层一层的看源码,看文档,要求你事无巨细的做一个接入者. 如果接入API需要让人看源码来理解,我觉得是一件让 ...
- 微信支付API v3 Native支付
废话不多说直接上代码 不熟悉的直接私信我 依赖 <dependency><groupId>com.github.wechatpay-apiv3</groupId> ...
- 微信支付API v3签名与验签-APP支付问题
目录 使用API v3微信支付遇到的问题: 1.微信请求客户端配置 2.生成预付款订单 3.拼接字符串使用API v3签名 4.微信支付成功后通知 使用API v3微信支付遇到的问题: 1.jdk版本 ...
- 微信支付 API V3 JSAPI支付 JAVA下载账单
下载账单 写这个主要是太气人了,开发文档未写具体的代码示例.网上各种搜索了一天都是V2接口的示例V3的标题党,感觉被欺骗了,太气人了(V2接口有个参数APPID,具体业务使用了多个APPID所以不合适 ...
- 一文搞懂「微信支付 Api-v3」接口规则所有知识点
文章目录 简介 v2 与 v3 的区别 API 密钥设置 获取 API 证书 请求签名 示例代码 构造签名串 构造 HTTP 头中的 Authorization 获取证书序列号 通过工具获取 通过代码 ...
- Python3 微信支付(小程序支付)V3接口
起因: 因公司项目需要网上充值功能,从而对接微信支付,目前也只对接了微信支付的小程序支付功能,在网上找到的都是对接微信支付V2版本接口,与我所对接的接口版本不一致,无法使用,特此记录下微信支付完成功能 ...
- 微信支付api的服务器上,服务器微信支付接口笔记(与app端对接)
到这里,准备工作就算完成了. 支付流程步骤详解: 步骤1:用户在商户APP中选择商品,提交订单,选择微信支付. 这一步,app将相关订单信息提交给商户 步骤2:商户后台收到用户支付单,调用微信支付统一 ...
- Java微信支付API文档测试
Java微信支付API文档测试(注意用的微信开发文档是什么支付) 本人用的刷卡支付( 之前看错了,一直在看扫码支付,心塞 ),如图 首先,做一系列准备,获取appid等等,可以写在一个配置文件里面,如 ...
- APP 对接 java 微信支付统一下单接口
首先插入微信支付的时序图 统一下单时候的请求对象,需要把这个转为xml 文件格式所以需要在pom.xml 文件中导入 .和微信支付的sdk <dependency> <groupId ...
最新文章
- 关于pytorch--embedding的问题
- 偏差是什么?一文读懂偏差
- boost::intrusive::list用法的测试程序
- python网管系统_IT外包网管服务,Python密度聚类算法-DBSCAN实践
- 谭建荣院士:制造业与互联网融合需解决三大瓶颈
- 【转】高并发情况下的单例模式
- 大端模式和小端模式的再理解
- 为什么要用火狐浏览器
- Linux复制文件到某路径并重命名
- 英语单词12大前缀3大词性后缀
- 配备透明触摸屏 看3D全息投影概念手机
- 找不到sct文件解决方法:Could not open scatter descript
- 探索汇率变动与股票价格的关系
- 智慧路灯点亮新型城市
- 苹果手机相册怎么分类_电子相册怎么做?用手机app可以剪辑电子相册视频吗?...
- 华为海思 hikey970 详细介绍
- 香港电影中的演员:B字头(持续更新中)
- android 如何检查外部来源,Android是如何判断APK是否不明来源的
- UserData使用总结
- 云服务器查看操作系统,如何查看云服务器的操作系统
热门文章
- SecureCRT远程连接虚拟机
- htc+one+m8+联通+android+5,HTC One M9和HTC M8哪个好
- 【Linux】在Xilinx平台上实现UVC Gadget(2)- 解决dwc3驱动bug
- JMS之——ActiveMQ消息持久化
- 通过NTP协议进行时间同步
- python语言画四叶草的程序_python绘图四叶草_后端开发
- 商品id- item_id /条形码/skuid
- 【特征工程】Chap3 Text Data: Flatten, Filtering, Chunking
- jquery delay_jQuery delay()函数
- UOJ #11.【UTR #1】ydc的大树 题解