APP整合微信APV3支付过程解析

求个关注和点赞!!!!!谢谢啦~~~~~~~~~~~~~~~~~~~~~

一、APP进行APIv3下单

1.官方文档:

开发指引-APP支付 | 微信支付商户平台文档中心 (qq.com)

2.根据官方文档给的SDK进入到相应的文档:

https://github.com/wechatpay-apiv3/wechatpay-java

3.在idea引入相应的maven依赖:

<dependency>
<groupId>com.github.wechatpay-apiv3</groupId>
<artifactId>wechatpay-java</artifactId>
<version>0.2.12</version>
</dependency>

这个依赖引入之后如果版本号飘红,就刷新maven即可

4.文档下面有Native下单样例,具体别的样例文档也已经给出:

https://github.com/wechatpay-apiv3/wechatpay-java/tree/main/service/src/example/java/com/wechat/pay/java/service/payments/app

当然,打不开不要急因为很卡很卡很卡很卡很卡......

5.找到相应的example,接下来我们根据每一行代码进行详细介绍:

// 一个商户号只能初始化一个配置,否则会因为重复的下载任务报错
// 创建 config 目的是为了提供给微信支付重要的配置信息
Config config =
new RSAAutoCertificateConfig.Builder()
// 商户号
.merchantId(wxUtil.mchId)
// 证书私钥地址:放在本地也可,服务器也可,但是一定起个英文名字放!!!
.privateKeyFromPath(wxUtil.privateKeyPath)
// 证书序列号
.merchantSerialNumber(wxUtil.mchSerialNo)
// v3密钥
.apiV3Key(wxUtil.apiV3Key)
.build();
// 构建 service,SDK里面配置了相应地与签名有关的操作,给我们开发者省了很大的力气
AppService service = new AppService.Builder().config(config).build();
// NativePayService service = new NativePayService.Builder().config(config).build();
// request.setXxx(val)设置所需参数,具体参数可见Request定义
PrepayRequest request = new PrepayRequest();
Amount amount = new Amount();
amount.setTotal(order.getPrice().intValue());
request.setAmount(amount);
request.setAppid(wxUtil.appId);
request.setMchid(wxUtil.mchId);
request.setDescription(order.getDescription());
request.setNotifyUrl(wxUtil.notifyDomain);
request.setOutTradeNo(order.getOrderSn());
// 调用下单方法,得到应答
PrepayResponse response = service.prepay(request);

6.至此其实就可以了,有几个方面需要注意一下:

1>>

java里面的密钥生成一般是128位,但是我们使用的这个方法里面所需要的密钥超过了128位,必须替换jdk里的相应jar包,可以去官网下载(我是用的jdk1.8):

JDK8的下载地址: http://www.oracle.com/technetwork/java/javase/downloads/jce8-download-2133166.html

去官网选择自己合适的版本即可。

下载完成之后,将%JDK_HOME%\jre\lib\security目录下的两个源文件替换掉即可。

替换之前记得备份一下,不成功的话就重启idea和刷新maven。

2>>

其他的SDK不一定安全,建议使用这个,或者自己根据官网的接口文档自己封装也可以。

APP下单封装的service有两个,使用哪一个都可以,但是注意他们的相应和接收都不一样,要一一对应即可。

 二、前台调起支付所需的签名

1.根据所需字段生成签名串

private static String generateSignature(SortedMap<Object, Object> needParams) {
StringBuilder signatureBuilder = new StringBuilder();

for (Object key : needParams.keySet()) {
String value = String.valueOf(needParams.get(key));
if (value.endsWith("\n")) {
signatureBuilder.append(key).append("=").append(value);
} else {
signatureBuilder.append(key).append("=").append(value).append("\n");
}
}

signatureBuilder.append("\n");

return signatureBuilder.toString();
}

格式大概是:

appid={wxLoginInfo.appId}
noncestr={随机生成的字符串}
prepayid={prepayId}
timeStamp={当前的时间戳}

这个亚子的字符串,每个参数之间用换行符进行分割

2.读取商户私钥的 pem 文件:

1>>所需maven依赖:

<!--        读取pem文件-->
<dependency>
<groupId>org.bouncycastle</groupId>
<artifactId>bcprov-jdk15on</artifactId>
<version>1.68</version>
</dependency>

代码表示:

private static PrivateKey readPrivateKey(String privateKeyPath) {
   // 这里的 privateKeyPath 指的是你本地或者服务器存放 pem 文件的路径
try (PEMParser pemParser = new PEMParser(new FileReader(privateKeyPath))) {
Object obj = pemParser.readObject();
if (obj instanceof PEMKeyPair) {
PEMKeyPair pemKeyPair = (PEMKeyPair) obj;
JcaPEMKeyConverter converter = new JcaPEMKeyConverter().setProvider(new BouncyCastleProvider());
KeyPair keyPair = converter.getKeyPair(pemKeyPair);
return keyPair.getPrivate();
} else if (obj instanceof PrivateKeyInfo) {
PrivateKeyInfo privateKeyInfo = (PrivateKeyInfo) obj;
JcaPEMKeyConverter converter = new JcaPEMKeyConverter().setProvider(new BouncyCastleProvider());
return converter.getPrivateKey(privateKeyInfo);
} else {
throw new IllegalArgumentException("Invalid private key format");
}
} catch (IOException e) {
// 异常处理
System.out.println("读取失败");
return null;
}
}

如果上述方法加载出来的私钥不正确的话可以通过官方文档给出的方式加载私钥:开发指引 - APP支付 | 微信支付商户文档中心 (qq.com)

PrivateKey merchantPrivateKey = PemUtil
.loadPrivateKey(new ByteArrayInputStream(privateKey.getBytes("utf-8")));

3.进行SHA256 with RSA签名,并对签名结果进行Base64编码得到签名值:

// SHA256withRSA 签名
Signature sign = Signature.getInstance("SHA256withRSA");
sign.initSign(privateKey);
sign.update(signature.getBytes(StandardCharsets.UTF_8));
byte[] signatureBytes = sign.sign();
// Base64 编码
String signRSA = Base64.getEncoder().encodeToString(signatureBytes);

 三、SDK 生成调起支付所需的签名

// SDK 参数生成签名
String message =
request.getAppid() + "\n" + Instant.now().getEpochSecond() + "\n" + getRandomString() + "\n" + prepayId + "\n";
String sign = signer.sign(message).getSign();

但是这里的 signer 需要初始化

Signer signer = config.createSigner();

上面的 config 是指的最开始商户信息进行初始化的那个 config 嗷!

具体文档可参照官方文档:

wechatpay-java/service/src/main/java/com/wechat/pay/java/service/payments/app/AppServiceExtension.java at main · wechatpay-apiv3/wechatpay-java · GitHub


posted @ 2023-12-14 09:50  xiaobaibao  阅读(281)  评论(0编辑  收藏  举报