微信小程序JSAPI支付 v3 版本 详解 附带源码
v2与v3的区别
V2版接口和V3版接口实际上是基于两种接口标准设计的两套接口。 目前大部分接口已升级为V3接口,其余V2接口后续也将逐步升级为V3接口
总的来说,v3支付是对v2版本的升级,不过目前来看,v3的支付对接和实现对开发者更加友好,并且支付更加安全。
请大家花点时间认真看下文档。指引文档,更新日志,sdk,api字典等,这些都很重要,避免在开发过程中,遇到很多不必要的麻烦。
文章。
交互图
- 拿prepay_id 拼接参数,生成签名,给到前端拉起支付(JSAPI调起支付API)
- 支付成功后,处理支付回调方法
这里就是后端需要做处理的流程,中间会涉及到 数字证书,秘钥,签名等加密解密出来,以及自己业务处理。
代码实现
官方提供了工具和SDK。先获取官方的SDK,java版本的来做项目开发。
wechatpay-apache-httpclient,适用于使用Apache HttpClient处理HTTP的Java开发者。 wechatpay-php(推荐)、wechatpay-guzzle-middleware,适用于PHP开发者。 wechatpay-go,适用于Go开发者
大家根据自己的语言去下载对应的SDK。并且好好看看sdk的使用方式。
maven依赖
<dependency> <groupId>com.github.wechatpay-apiv3</groupId> <artifactId>wechatpay-apache-httpclient</artifactId> <version>0.2.2</version> </dependency>
配置类:
@Bean public HttpClient wxHttpClient( @Value("${mchid}") String mchid, @Value("${mchSerialNo}") String mchSerialNo, PrivateKey merchantPrivateKey, AutoUpdateCertificatesVerifier autoUpdateCertificatesVerifier) { return WechatPayHttpClientBuilder.create() .withMerchant(mchid, mchSerialNo, merchantPrivateKey) .withValidator(new WechatPay2Validator(autoUpdateCertificatesVerifier)).build(); } /** * 加载平台证书(mchId:商户号,mchSerialNo:商户证书序列号,apiV3Key:V3密钥) */ @Bean public AutoUpdateCertificatesVerifier autoUpdateCertificatesVerifier( PrivateKey merchantPrivateKey, @Value("${mchid}") String mchid, @Value("${mchSerialNo}") String mchSerialNo, @Value("${v3Key}") String v3Key) throws UnsupportedEncodingException { return new AutoUpdateCertificatesVerifier( new WechatPay2Credentials(mchid, new PrivateKeySigner(mchSerialNo, merchantPrivateKey)), v3Key.getBytes("utf-8")); } /** * 加载商户私钥(privateKey:私钥字符串) */ @Bean public PrivateKey merchantPrivateKey(@Value("${privateKey}") String privateKey) throws UnsupportedEncodingException { return PemUtil.loadPrivateKey(new ByteArrayInputStream(privateKey.getBytes("utf-8"))); }
static final int KEY_LENGTH_BYTE = 32; static final int TAG_LENGTH_BIT = 128; @Value("${v3Key}") private String weChatV3Key; public String decryptToString(byte[] associatedData, byte[] nonce, String ciphertext) throws GeneralSecurityException, IOException { try { Cipher cipher = Cipher.getInstance("AES/GCM/NoPadding"); SecretKeySpec key = new SecretKeySpec(weChatV3Key.getBytes(StandardCharsets.UTF_8), "AES"); GCMParameterSpec spec = new GCMParameterSpec(TAG_LENGTH_BIT, nonce); cipher.init(Cipher.DECRYPT_MODE, key, spec); cipher.updateAAD(associatedData); return new String(cipher.doFinal(Base64.getDecoder().decode(ciphertext)), "utf-8"); } catch (NoSuchAlgorithmException | NoSuchPaddingException e) { throw new IllegalStateException(e); } catch (InvalidKeyException | InvalidAlgorithmParameterException e) { throw new IllegalArgumentException(e); } }
请求下单
获取下单的预支付id生成签名
签名方法
private String getSignStr(String appId, String timeStamp, String nonceStr, String packageValue) { return String.format("%s %s %s %s ", appId, timeStamp, nonceStr, packageValue); } public static String sign(String string, PrivateKey privateKey) { try { Signature sign = Signature.getInstance("SHA256withRSA"); sign.initSign(privateKey); sign.update(string.getBytes()); return Base64.getEncoder().encodeToString(sign.sign()); } catch (NoSuchAlgorithmException e) { throw new RuntimeException("当前Java环境不支持SHA256withRSA", e); } catch (SignatureException e) { throw new RuntimeException("签名计算失败", e); } catch (InvalidKeyException e) { throw new RuntimeException("无效的私钥", e); } }
这里可以看看官方文档对签名的介绍:
回调处理:
完整源码:
https://gitee.com/QuRenNen/spring-boot-integrate
spring-boot-wx-miniapp-integrat 项目中感兴趣可以看看。
上一篇:
uniapp开发微信小程序-2.页面制作