-
-
Notifications
You must be signed in to change notification settings - Fork 9k
在JsapiResult中添加prepayId字段并提供静态工厂方法实现解耦 #3798
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: develop
Are you sure you want to change the base?
Conversation
Co-authored-by: binarywang <1343140+binarywang@users.noreply.github.com>
Co-authored-by: binarywang <1343140+binarywang@users.noreply.github.com>
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pull request overview
本 PR 通过在 JsapiResult 中添加 prepayId 字段并提供静态工厂方法,解决了微信支付 V3 API 中用户无法存储和复用预支付交易会话标识的问题,同时实现了订单创建与支付签名生成的解耦。
主要变更:
- 在
JsapiResult类中添加prepayId字段,使用户能够获取并存储预支付交易会话标识 - 新增两个静态工厂方法
getJsapiPayInfo()和getAppPayInfo(),支持使用已存储的 prepay_id 重新生成支付签名 - 修正了 code_url 字段注释中的变量名错误
Reviewed changes
Copilot reviewed 2 out of 2 changed files in this pull request and generated 3 comments.
| File | Description |
|---|---|
| weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/result/WxPayUnifiedOrderV3Result.java | 在 JsapiResult 中添加 prepayId 字段;新增 getJsapiPayInfo() 和 getAppPayInfo() 静态工厂方法用于解耦场景;修正 code_url 注释错误 |
| weixin-java-pay/src/test/java/com/github/binarywang/wxpay/bean/result/WxPayUnifiedOrderV3ResultTest.java | 新增完整的测试用例,覆盖 prepayId 字段的设置、静态工厂方法的功能以及解耦场景的使用 |
| public static JsapiResult getJsapiPayInfo(String prepayId, String appId, PrivateKey privateKey) { | ||
| String timestamp = String.valueOf(System.currentTimeMillis() / 1000); | ||
| String nonceStr = SignUtils.genRandomStr(); | ||
| JsapiResult jsapiResult = new JsapiResult(); | ||
| jsapiResult.setAppId(appId).setTimeStamp(timestamp) | ||
| .setPackageValue("prepay_id=" + prepayId).setNonceStr(nonceStr) | ||
| .setPrepayId(prepayId) | ||
| //签名类型,默认为RSA,仅支持RSA。 | ||
| .setSignType("RSA").setPaySign(SignUtils.sign(jsapiResult.getSignStr(), privateKey)); | ||
| return jsapiResult; | ||
| } | ||
|
|
||
| /** | ||
| * <pre> | ||
| * 根据已有的prepay_id生成APP支付所需的参数对象(解耦版本) | ||
| * 应用场景: | ||
| * 1. 用户已经通过createPartnerOrderV3或unifiedPartnerOrderV3获取了prepay_id | ||
| * 2. 用户希望存储prepay_id用于后续复用 | ||
| * 3. 支付失败后,使用存储的prepay_id重新生成支付签名信息 | ||
| * | ||
| * 使用示例: | ||
| * // 步骤1:创建订单并获取prepay_id | ||
| * WxPayUnifiedOrderV3Result result = wxPayService.unifiedPartnerOrderV3(TradeTypeEnum.APP, request); | ||
| * String prepayId = result.getPrepayId(); | ||
| * // 存储prepayId到数据库... | ||
| * | ||
| * // 步骤2:需要支付时,使用存储的prepay_id生成支付信息 | ||
| * WxPayUnifiedOrderV3Result.AppResult payInfo = WxPayUnifiedOrderV3Result.getAppPayInfo( | ||
| * prepayId, appId, mchId, wxPayService.getConfig().getPrivateKey() | ||
| * ); | ||
| * </pre> | ||
| * | ||
| * @param prepayId 预支付交易会话标识 | ||
| * @param appId 应用ID | ||
| * @param mchId 商户号 | ||
| * @param privateKey 商户私钥,用于签名 | ||
| * @return APP支付所需的参数对象 | ||
| */ | ||
| public static AppResult getAppPayInfo(String prepayId, String appId, String mchId, PrivateKey privateKey) { | ||
| String timestamp = String.valueOf(System.currentTimeMillis() / 1000); | ||
| String nonceStr = SignUtils.genRandomStr(); | ||
| AppResult appResult = new AppResult(); | ||
| appResult.setAppid(appId).setPrepayId(prepayId).setPartnerId(mchId) | ||
| .setNoncestr(nonceStr).setTimestamp(timestamp) | ||
| //暂填写固定值Sign=WXPay | ||
| .setPackageValue("Sign=WXPay") | ||
| .setSign(SignUtils.sign(appResult.getSignStr(), privateKey)); | ||
| return appResult; | ||
| } |
Copilot
AI
Dec 20, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
静态工厂方法 getJsapiPayInfo 和 getAppPayInfo 与实例方法 getPayInfo 中的逻辑存在重复。建议将重复的签名生成逻辑提取为私有方法以提高代码可维护性。
例如,可以创建私有方法:
buildJsapiResult(String prepayId, String appId, PrivateKey privateKey)buildAppResult(String prepayId, String appId, String mchId, PrivateKey privateKey)
然后在实例方法 getPayInfo 和静态方法中都调用这些私有方法。
| public static JsapiResult getJsapiPayInfo(String prepayId, String appId, PrivateKey privateKey) { | ||
| String timestamp = String.valueOf(System.currentTimeMillis() / 1000); | ||
| String nonceStr = SignUtils.genRandomStr(); | ||
| JsapiResult jsapiResult = new JsapiResult(); | ||
| jsapiResult.setAppId(appId).setTimeStamp(timestamp) | ||
| .setPackageValue("prepay_id=" + prepayId).setNonceStr(nonceStr) | ||
| .setPrepayId(prepayId) | ||
| //签名类型,默认为RSA,仅支持RSA。 | ||
| .setSignType("RSA").setPaySign(SignUtils.sign(jsapiResult.getSignStr(), privateKey)); | ||
| return jsapiResult; | ||
| } |
Copilot
AI
Dec 20, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
静态工厂方法缺少对输入参数的空值验证。如果传入 null 参数(如 prepayId、appId 或 privateKey),可能导致 NullPointerException 或生成无效的签名数据。
建议在方法开始处添加参数验证,例如:
if (prepayId == null || appId == null || privateKey == null) {
throw new IllegalArgumentException("prepayId, appId 和 privateKey 不能为空");
}或者使用 Objects.requireNonNull() 进行验证。
| public static AppResult getAppPayInfo(String prepayId, String appId, String mchId, PrivateKey privateKey) { | ||
| String timestamp = String.valueOf(System.currentTimeMillis() / 1000); | ||
| String nonceStr = SignUtils.genRandomStr(); | ||
| AppResult appResult = new AppResult(); | ||
| appResult.setAppid(appId).setPrepayId(prepayId).setPartnerId(mchId) | ||
| .setNoncestr(nonceStr).setTimestamp(timestamp) | ||
| //暂填写固定值Sign=WXPay | ||
| .setPackageValue("Sign=WXPay") | ||
| .setSign(SignUtils.sign(appResult.getSignStr(), privateKey)); | ||
| return appResult; | ||
| } |
Copilot
AI
Dec 20, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
静态工厂方法 getAppPayInfo 缺少对输入参数的空值验证。如果传入 null 参数(如 prepayId、appId、mchId 或 privateKey),可能导致 NullPointerException 或生成无效的签名数据。
建议在方法开始处添加参数验证,例如:
if (prepayId == null || appId == null || mchId == null || privateKey == null) {
throw new IllegalArgumentException("prepayId, appId, mchId 和 privateKey 不能为空");
}或者使用 Objects.requireNonNull() 进行验证。
微信支付V3的
createPartnerOrderV3接口返回的JsapiResult对象缺少prepay_id字段,导致用户无法存储并复用该标识,支付失败时必须重新下单。主要修改
JsapiResult中添加prepayId字段:使createPartnerOrderV3等方法返回的对象包含预支付交易会话标识getJsapiPayInfo(String prepayId, String appId, PrivateKey privateKey)- 根据已有prepay_id生成JSAPI支付参数getAppPayInfo(String prepayId, String appId, String mchId, PrivateKey privateKey)- 根据已有prepay_id生成APP支付参数使用示例
原有方式(现在可以获取prepay_id)
解耦方式(推荐用于支付重试场景)
兼容性
完全向后兼容,现有代码无需修改。
Original prompt
✨ Let Copilot coding agent set things up for you — coding agent works faster and does higher quality work when set up for your repo.