微信V2平台证书切换V3公钥支付
·
在微信商家平台,账户中心-API安全中,开启V3公钥,记录公钥ID,并下载公钥证书
项目里引入jar包,pom
<dependency>
<groupId>com.github.wechatpay-apiv3</groupId>
<artifactId>wechatpay-java</artifactId>
<version>0.2.17</version>
</dependency>
以APP支付为例:
public String appPrepay(int orderFee,String orderNo,String notifyUrl,String desc,long orderId) {
// 可以根据实际情况使用publicKeyFromPath或publicKey加载公钥
Config config =
new RSAPublicKeyConfig.Builder()
.merchantId("1900007291") //微信支付的商户号
.privateKeyFromPath("/Users/yourname/yourpath/apiclient_key.pem") // 商户API证书私钥的存放路径
.publicKeyFromPath("/Users/yourname/yourpath/pub_key.pem") //微信支付公钥的存放路径
.publicKeyId("PUB_KEY_ID_00000000000000000000000000000000") //微信支付公钥ID
.merchantSerialNumber("5157F09EFDC096DE15EBE81A47057A72********") //商户API证书序列号
.apiV3Key("F09E**") //APIv3密钥
.build();
AppServiceExtension appServiceExtension = new AppServiceExtension.Builder().config(config).build();
PrepayRequest appRequest = new PrepayRequest();
Amount amount = new Amount();
amount.setTotal(orderFee);
appRequest.setAmount(amount);
amount.setTotal(orderFee);
appRequest.setAmount(amount);
appRequest.setMchid(commonParamsService.getWxPayMchId());
appRequest.setAppid(commonParamsService.getWxOpenPlatformAppId());
appRequest.setOutTradeNo(orderNo);
appRequest.setNotifyUrl(sysConfigService.getHooplyAppApiUri()+notifyUrl);
appRequest.setDescription(desc);
PrepayWithRequestPaymentResponse res = appServiceExtension.prepayWithRequestPayment(appRequest);
return res;
}
回调,微信商家证书切换过程中,如果回调切换为到100%则需要支持证书与公钥验签,即使下单时已经将公钥ID放入请求头中,回调也会有概率使用证书验签,所以在未到100%之前要兼容两种方式验签,
public Transaction paymentsNotifyPl(HttpServletRequest request) throws IOException {
String body = getRequestBody(request);
String wechatpayNonce = request.getHeader("Wechatpay-Nonce");
String wechatSignature = request.getHeader("Wechatpay-Signature");
String wechatTimestamp = request.getHeader("Wechatpay-Timestamp");
String serialNumber = request.getHeader("Wechatpay-Serial");
String wechatpaySignatureType = request.getHeader("Wechatpay-Signature-Type");
log.info("wechatpayNonce:{},wechatSignature:{},wechatTimestamp:{},serialNumber:{},wechatpaySignatureType:{}",wechatpayNonce,wechatSignature,wechatTimestamp,serialNumber,wechatpaySignatureType);
// 构造 RequestParam
RequestParam requestParam = new RequestParam.Builder()
.serialNumber(serialNumber)
.nonce(wechatpayNonce)
.signature(wechatSignature)
.timestamp(wechatTimestamp)
.body(body)
.build();
// 如果已经初始化了 NotificationConfig,可直接使用
// 没有的话,则构造一个。以下多种 Config 根据情况选择一种即可:
// 1. 如果你使用的是微信支付公私钥,则使用 RSAPublicKeyNotificationConfig
NotificationConfig config = new RSACombinedNotificationConfig.Builder()
.merchantId(commonParamsService.getWxPayMchId())
.privateKeyFromPath(commonParamsService.getWxV3PaymentPrivateKeyPath())
.merchantSerialNumber(commonParamsService.getWxV3MerchantSerialNumber())
.publicKeyFromPath(commonParamsService.getWxV3WechatpayPublicKeyPath())
.publicKeyId(commonParamsService.getWxV3WechatpayPublicKeyId())
.apiV3Key(commonParamsService.getWxV3ApiV3Key())
.build();
// 初始化 NotificationParser
NotificationParser parser = new NotificationParser(config);
try {
Transaction transaction = parser.parse(requestParam, Transaction.class);
return transaction;
} catch (ValidationException e) {
// 签名验证失败,返回 401 UNAUTHORIZED 状态码
log.error("sign verification failed", e);
throw new DistRuntimeException(HttpStatus.UNAUTHORIZED.value(),"sign verification failed");
} catch (MalformedMessageException e) {
log.error("MalformedMessageException", e);
throw new DistRuntimeException(HttpStatus.BAD_REQUEST.value(),"MalformedMessageException");
}
}
更多推荐


所有评论(0)