目录

  • 前言
  • 版本
  • 应用
    • 基础配置
      • 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接口使用应用篇相关推荐

  1. 微信支付API V3版本JAVA开发指南

    微信支付版本V3的Demo,在官方上下载下来,压根就是不能直接用的东西,你要想学会用,你就得一层一层的看源码,看文档,要求你事无巨细的做一个接入者. 如果接入API需要让人看源码来理解,我觉得是一件让 ...

  2. 微信支付API v3 Native支付

    废话不多说直接上代码  不熟悉的直接私信我 依赖 <dependency><groupId>com.github.wechatpay-apiv3</groupId> ...

  3. 微信支付API v3签名与验签-APP支付问题

    目录 使用API v3微信支付遇到的问题: 1.微信请求客户端配置 2.生成预付款订单 3.拼接字符串使用API v3签名 4.微信支付成功后通知 使用API v3微信支付遇到的问题: 1.jdk版本 ...

  4. 微信支付 API V3 JSAPI支付 JAVA下载账单

    下载账单 写这个主要是太气人了,开发文档未写具体的代码示例.网上各种搜索了一天都是V2接口的示例V3的标题党,感觉被欺骗了,太气人了(V2接口有个参数APPID,具体业务使用了多个APPID所以不合适 ...

  5. 一文搞懂「微信支付 Api-v3」接口规则所有知识点

    文章目录 简介 v2 与 v3 的区别 API 密钥设置 获取 API 证书 请求签名 示例代码 构造签名串 构造 HTTP 头中的 Authorization 获取证书序列号 通过工具获取 通过代码 ...

  6. Python3 微信支付(小程序支付)V3接口

    起因: 因公司项目需要网上充值功能,从而对接微信支付,目前也只对接了微信支付的小程序支付功能,在网上找到的都是对接微信支付V2版本接口,与我所对接的接口版本不一致,无法使用,特此记录下微信支付完成功能 ...

  7. 微信支付api的服务器上,服务器微信支付接口笔记(与app端对接)

    到这里,准备工作就算完成了. 支付流程步骤详解: 步骤1:用户在商户APP中选择商品,提交订单,选择微信支付. 这一步,app将相关订单信息提交给商户 步骤2:商户后台收到用户支付单,调用微信支付统一 ...

  8. Java微信支付API文档测试

    Java微信支付API文档测试(注意用的微信开发文档是什么支付) 本人用的刷卡支付( 之前看错了,一直在看扫码支付,心塞 ),如图 首先,做一系列准备,获取appid等等,可以写在一个配置文件里面,如 ...

  9. APP 对接 java 微信支付统一下单接口

    首先插入微信支付的时序图 统一下单时候的请求对象,需要把这个转为xml 文件格式所以需要在pom.xml 文件中导入 .和微信支付的sdk <dependency> <groupId ...

最新文章

  1. 关于pytorch--embedding的问题
  2. 偏差是什么?一文读懂偏差
  3. boost::intrusive::list用法的测试程序
  4. python网管系统_IT外包网管服务,Python密度聚类算法-DBSCAN实践
  5. 谭建荣院士:制造业与互联网融合需解决三大瓶颈
  6. 【转】高并发情况下的单例模式
  7. 大端模式和小端模式的再理解
  8. 为什么要用火狐浏览器
  9. Linux复制文件到某路径并重命名
  10. 英语单词12大前缀3大词性后缀
  11. 配备透明触摸屏 看3D全息投影概念手机
  12. 找不到sct文件解决方法:Could not open scatter descript
  13. 探索汇率变动与股票价格的关系
  14. 智慧路灯点亮新型城市
  15. 苹果手机相册怎么分类_电子相册怎么做?用手机app可以剪辑电子相册视频吗?...
  16. 华为海思 hikey970 详细介绍
  17. 香港电影中的演员:B字头(持续更新中)
  18. android 如何检查外部来源,Android是如何判断APK是否不明来源的
  19. UserData使用总结
  20. 云服务器查看操作系统,如何查看云服务器的操作系统

热门文章

  1. SecureCRT远程连接虚拟机
  2. htc+one+m8+联通+android+5,HTC One M9和HTC M8哪个好
  3. 【Linux】在Xilinx平台上实现UVC Gadget(2)- 解决dwc3驱动bug
  4. JMS之——ActiveMQ消息持久化
  5. 通过NTP协议进行时间同步
  6. python语言画四叶草的程序_python绘图四叶草_后端开发
  7. 商品id- item_id /条形码/skuid
  8. 【特征工程】Chap3 Text Data: Flatten, Filtering, Chunking
  9. jquery delay_jQuery delay()函数
  10. UOJ #11.【UTR #1】ydc的大树 题解