此前,已设计过多应用多平台支付模块的基础开篇。传送门
本篇,准备对接微信V3AppApi支付基础模块,并基于此模块实现具体的业务功能逻辑。
实现思路
一、前期准备工作
1、申请证书
- 后台管理选择“API安全“”,进入“API证书管理”进行“申请证书”操作
- 下载并打开证书生成工具,按照步骤一步步操作
- 最终会在本地文件夹中生成下图文件
- 生成密钥证书
java -jar CertificateDownloader-1.2.0-jar-with-dependencies.jar -f 商户私钥文件路径
-k 证书解密的密钥 -m 商户号 -o 证书保存路径 -s 商户证书序列号
- “商户私钥文件路径”通过“账号中心->API安全->API证书”中设置并下载的证书(就是其中的apiclient_key.pem)
- “商户证书序列号”在“账号中心->API安全->API证书”中;
- “证书解密的密钥”在“账号中心->API安全->APIv3密钥”中。
二、后端功能开发
1、定义yml配置文件
- 需求分析,思路梳理
通过阅读微信V3App 文档,梳理以下参数需要动态配置。商户Id、商户密钥、商户证书序列号、商户私钥key、安卓app id。其中,由于商户私钥内容比较大,我准备采用文件路径配置方式存储,其他的则采用yml形式配置。
- 配置示例如下
1、yml配置示例
2、密钥文件配置示例
2、实现下单扩展
- 引用V3支付jar
<!-- 微信支付sdk -->
<dependency>
<groupId>com.github.wechatpay-apiv3</groupId>
<artifactId>wechatpay-java</artifactId>
<version>0.2.10</version>
</dependency>
- 代码实现如下
package com.flycoding.biz.order.factory.impl.wx.v3;
import com.alibaba.fastjson.JSONObject;
import com.flycoding.biz.order.config.OrderDictConfig;
import com.flycoding.biz.order.config.extend.PaymentExtend;
import com.flycoding.biz.order.entity.OrderInfo;
import com.flycoding.biz.order.enums.PayWay;
import com.flycoding.biz.order.factory.impl.base.BasePaymentFactory;
import com.flycoding.biz.order.utils.PayUtils;
import com.flycoding.drivenlibrary.engine.config.constants.DrivenConstants;
import com.flycoding.drivenlibrary.factory.OpenPlatformConfig;
import com.flycoding.utillibrary.java.IDGenerate;
import com.wechat.pay.java.core.RSAAutoCertificateConfig;
import com.wechat.pay.java.core.cipher.SignatureResult;
import com.wechat.pay.java.service.payments.app.AppService;
import com.wechat.pay.java.service.payments.app.model.Amount;
import com.wechat.pay.java.service.payments.app.model.PrepayRequest;
import com.wechat.pay.java.service.payments.app.model.PrepayResponse;
import java.math.BigDecimal;
/**
* 微信app支付 v3
*
* @author 赵屈犇
* @version 1.0
* @date 创建时间: 2023/3/23 19:41
* @Copyright(C): 2023 by 赵屈犇
*/
@PaymentExtend(OrderDictConfig.PayWay.WX_APP_API_V3)
public class WxAppV3PaymentFactory extends BasePaymentFactory<JSONObject> {
@Override
protected JSONObject placeOrder(OrderInfo orderInfo, OpenPlatformConfig platform) throws Exception {
// 商户 id
String mchId = platform.getConfig(DrivenConstants.PlatformConstants.WxConstants.MCH_ID);
// 安卓app id
String appId = platform.getConfig(DrivenConstants.PlatformConstants.WxConstants.ANDROID_APP_ID);
// 获取支付配置
RSAAutoCertificateConfig config = PayUtils.getWxAppV3Config(platform);
// 构建service
AppService service = new AppService.Builder().config(config).build();
// request.setXxx(val)设置所需参数,具体参数可见Request定义
PrepayRequest request = new PrepayRequest();
Amount amount = new Amount();
amount.setTotal(orderInfo.getPayMoney().multiply(new BigDecimal(100)).intValue());
request.setAmount(amount);
request.setAppid(appId);
request.setMchid(mchId);
request.setDescription(orderInfo.getOrderName());
request.setAttach(orderInfo.getOrderNum());
request.setNotifyUrl(PayUtils.getNotifyUrl(PayWay.WX_APP_API_V3) + "/" + orderInfo.getOrderNum());
request.setOutTradeNo(orderInfo.getOrderNum());
// 调用下单方法,得到应答
PrepayResponse response = service.prepay(request);
String prepayId = response.getPrepayId();
//时间戳
Long timestamp = System.currentTimeMillis()/ 1000;
//随机串
String nonceStr = IDGenerate.getUUId();
// 签名
SignatureResult sign = config.createSigner().sign(buildMessage(appId, timestamp, nonceStr, prepayId));
JSONObject payResult = new JSONObject();
payResult.put("appId", appId);
payResult.put("partnerId", mchId);
payResult.put("sign", sign.getSign());
payResult.put("prepayId", prepayId);
payResult.put("nonceStr", nonceStr);
payResult.put("timestamp", timestamp);
payResult.put("package", "Sign=WXPay");
return payResult;
}
private String buildMessage(String appId, long timestamp, String nonceStr, String prepayId) {
return appId + "\n"
+ timestamp + "\n"
+ nonceStr + "\n"
+ prepayId + "\n";
}
}
三、支付回调
- 实现回调代码
package com.flycoding.biz.order.api.notify.wx.v3;
import com.flycoding.biz.order.api.notify.base.BasePayNotifyExtend;
import com.flycoding.biz.order.config.OrderResponseConfig;
import com.flycoding.biz.order.entity.OrderInfo;
import com.flycoding.biz.order.entity.wx.v3.WxV3AppNotifyBO;
import com.flycoding.biz.order.utils.PayUtils;
import com.flycoding.drivenlibrary.context.RequestContextHolder;
import com.flycoding.drivenlibrary.engine.annotation.api.Api;
import com.flycoding.drivenlibrary.enums.dictionary.ContentType;
import com.flycoding.drivenlibrary.factory.OpenPlatformConfig;
import com.wechat.pay.java.core.RSAAutoCertificateConfig;
import com.wechat.pay.java.core.notification.NotificationParser;
import com.wechat.pay.java.core.notification.RequestParam;
import com.wechat.pay.java.service.payments.model.Transaction;
import java.math.BigDecimal;
/**
* 微信APP V3 支付回调通知
*
* @author 赵屈犇
* @version 1.0
* @date 创建时间: 2023/7/23 16:50
* @Copyright(C): 2023 by 赵屈犇
*/
@Api(apiUrl = "notify/{orderNum}", apiName = "微信APP V3 支付回调", moduleUrl = "pay/wxAppApi/v3", isVerifyToken = false, isVerifyLogin = false,
isEncryptedResult = false, isDecryptParams = false, isStartAuth = false, isParseRequestBody = false,
responseCode = OrderResponseConfig.WX_V3_NOTIFY_RESPONSE, requestContentType = ContentType.NOT_VERIFY
)
public class WxAppV3NotifyExtend extends BasePayNotifyExtend<WxV3AppNotifyBO> {
@Override
protected boolean isPaySuccess(OrderInfo orderInfo, OpenPlatformConfig platform) throws Exception {
// 获取支付配置
RSAAutoCertificateConfig config = PayUtils.getWxAppV3Config(platform);
// 构造 RequestParam
RequestParam requestParam = new RequestParam.Builder()
.serialNumber(getRequestHeader("Wechatpay-Serial"))
.nonce(getRequestHeader("Wechatpay-Nonce"))
.signature(getRequestHeader("Wechatpay-Signature"))
.timestamp(getRequestHeader("Wechatpay-Timestamp"))
.body(RequestContextHolder.getAttributes().getRequestBody())
.build();
// 初始化 NotificationParser
NotificationParser parser = new NotificationParser(config);
// 以支付通知回调为例,验签、解密并转换成 Transaction
Transaction transaction = parser.parse(requestParam, Transaction.class);
if (Transaction.TradeStateEnum.SUCCESS == transaction.getTradeState()) {
BigDecimal payMoney = BigDecimal.valueOf(transaction.getAmount().getTotal() / 100d);
getRequestParams().setPayMoney(payMoney);
return true;
}
return false;
}
}
三、Android功能开发
1、引入jar
// 微信SDK相关
api 'com.tencent.mm.opensdk:wechat-sdk-android:+'
2、实现调用函数
/**
* 调用微信支付
*
* @param context
* @param wxPayResult
* @param extData
*/
public void payWxpay(Context context, JSONObject wxPayResult, String extData) {
PayReq payReq = new PayReq();
payReq.appId = wxPayResult.getString("appId");
payReq.partnerId = wxPayResult.getString("partnerId");
payReq.prepayId = wxPayResult.getString("prepayId");
payReq.nonceStr = wxPayResult.getString("nonceStr");
payReq.timeStamp = wxPayResult.getString("timestamp");
payReq.packageValue = wxPayResult.getString("package");
payReq.sign = wxPayResult.getString("sign");
payReq.extData = extData;
getWXApi(context).sendReq(payReq);
}