Skip to content

feat(pay): add merchant transfer user authorization APIs#4051

Open
zhangzhao0219 wants to merge 1 commit into
binarywang:developfrom
zhangzhao0219:weixin-java-pay.add-user-authorization
Open

feat(pay): add merchant transfer user authorization APIs#4051
zhangzhao0219 wants to merge 1 commit into
binarywang:developfrom
zhangzhao0219:weixin-java-pay.add-user-authorization

Conversation

@zhangzhao0219

Copy link
Copy Markdown

本次在 weixin-java-pay 模块中补充了微信支付商家转账免确认收款授权相关接口,完善“发起授权、授权回调、查询授权状态、授权后转账、解除授权”的使用链路。

主要改动:
新增发起转账并完成免确认收款授权接口:
transferBillsWithAuthorization(...)

新增发起免确认收款授权接口:
userConfirmAuthorization(...)

新增用户授权后转账接口:
transferBillsAfterAuthorization(...)

新增免确认收款授权结果通知解析方法:
parseUserAuthorizationNotifyResult(...)

新增商户侧授权单号查询授权结果接口:
getUserConfirmAuthorizationByOutAuthorizationNo(...)

新增解除免确认收款授权接口:
closeUserConfirmAuthorization(...)

新增对应的请求/响应实体类,并补充授权信息参数校验,避免必要授权字段缺失时继续发起请求。
新增兼容性测试,覆盖接口路径、请求体、响应解析、参数校验和回调解析类型绑定。

@binarywang

Copy link
Copy Markdown
Owner

@codex 请帮忙review一下

@binarywang

Copy link
Copy Markdown
Owner

auggie review

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 1dce300d35

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment on lines +89 to +90
@SerializedName("close_reason")
private String closeReason;

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge 按 close_info 解析关闭通知

在授权状态为 CLOSED 的回调里,微信支付文档的解密资源把关闭信息放在 close_info 对象下(包含 close_timeclose_reason),不是顶层 close_reason 字段;当前模型会让 Gson 把关闭原因解析成 null,同时完全丢失关闭时间,商户无法区分用户关闭还是商户 API 关闭授权。建议像 UserConfirmAuthorizationResult.CloseInfo 一样增加 @SerializedName("close_info") 的嵌套对象。

Useful? React with 👍 / 👎.

* @return PreTransferWithAuthorizationResult 发起结果
* @throws WxPayException .
*/
PreTransferWithAuthorizationResult transferBillsWithAuthorization(PreTransferWithAuthorizationRequest request) throws WxPayException;

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge 为新增 TransferService 方法提供 default 实现

TransferService 是公开接口,这里及下面新增的多个抽象方法会让已有的第三方 TransferService 实现类在升级本库后出现源码编译失败,或在旧二进制实现被调用新增方法时触发 AbstractMethodError。如果希望这次特性保持兼容,应把这些新增接口声明为 default 方法并委托/抛出明确异常,避免破坏已有实现。

Useful? React with 👍 / 👎.

Comment on lines +64 to +65
@SerializedName("notify_url")
private String notifyUrl;

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge 不要在授权后转账请求中序列化 notify_url

用户授权后转账接口的请求体只包含 appid/out_bill_no/transfer_scene_id/user_name/transfer_amount/transfer_remark/user_recv_perception/transfer_scene_report_infos/authorization_id/sponsor_mchid/out_authorization_no,并没有 notify_url;如果调用方像普通转账一样设置这里的 notifyUrlGSON.toJson(request) 会把多余字段发给微信支付,容易被接口按参数错误拒绝。建议移除此字段或确保该接口不会序列化它。

Useful? React with 👍 / 👎.

StringBuilder url = new StringBuilder();
url.append(this.payService.getPayBaseUrl())
.append("/v3/fund-app/mch-transfer/user-confirm-authorization/out-authorization-no/")
.append(outAuthorizationNo);

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P3 Badge URL 编码授权单号路径参数

out_authorization_no 文档只声明为商户内部的 string(32),不像转账单号那样限制为纯字母数字;当商户侧授权单号包含 /?、空格或非 ASCII 字符时,直接拼到路径里会改变 URL 结构或生成非法请求,查询/关闭授权都会打到错误地址。建议对路径段做 URL path encoding 后再追加。

Useful? React with 👍 / 👎.

@augmentcode

augmentcode Bot commented Jun 10, 2026

Copy link
Copy Markdown
🤖 Augment PR Summary

Summary: This PR extends weixin-java-pay to support the WeChat Pay “商家转账免确认收款授权” end-to-end flow (apply authorization, handle callbacks, query/close authorization, and transfer after authorization).

Changes:

  • Added new request/response beans for “pre-transfer-with-authorization”, “user-confirm-authorization”, “transfer after authorization”, authorization query/close, and notify payloads.
  • Extended TransferService with new API methods covering authorization initiation, status lookup, authorization close, transfer calls, and notify parsing.
  • Implemented the new endpoints in TransferServiceImpl, including RSA encryption for sensitive user_name fields and use of Wechatpay-Serial where required.
  • Added local parameter validation for key authorization parameters to fail fast before making requests.
  • Added a compatibility test suite validating endpoint paths, request bodies, response parsing, parameter checks, and notify parsing type binding.

Technical Notes: Notify parsing reuses the existing v3 signature verification + AES-256-GCM resource decryption pipeline via baseParseOrderNotifyV3Result.

🤖 Was this summary useful? React with 👍 or 👎

@augmentcode augmentcode Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Review completed. 2 suggestions posted.

Fix All in Augment

Comment augment review to trigger a new review at any time.

// ===================== 用户授权免确认模式相关接口实现 =====================

@Override
public UserConfirmAuthorizationResult userConfirmAuthorization(UserConfirmAuthorizationRequest request) throws WxPayException {

@augmentcode augmentcode Bot Jun 10, 2026

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

userConfirmAuthorization directly posts GSON.toJson(request) without validating request (or required fields like outAuthorizationNo/appid/openid/transferSceneId/userDisplayName/authorizationNotifyUrl), so callers can accidentally send an invalid (or null) payload and only fail at the API side. Consider adding the same fast-fail parameter checks you added for the other new authorization-related APIs.

Severity: medium

Fix This in Augment

🤖 Was this useful? React with 👍 or 👎, or 🚀 if it prevented an incident/outage.

*
* <p>CLOSE_VIA_MCH_API:商户通过 API 主动关闭;USER_CLOSE:用户主动关闭。</p>
*/
@SerializedName("close_reason")

@augmentcode augmentcode Bot Jun 10, 2026

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Per the WeChat Pay “免确认收款授权结果通知” spec, when state=CLOSED the decrypted resource contains a close_info object (with close_reason/close_time), not a top-level close_reason; this model will silently drop close details. This can cause CLOSED notifications to lose the reason/time information during parsing.

Severity: medium

Fix This in Augment

🤖 Was this useful? React with 👍 or 👎, or 🚀 if it prevented an incident/outage.

@binarywang

Copy link
Copy Markdown
Owner

麻烦楼主处理下review建议,如果确认不需要做什么,点下面的resolve按钮即可

@binarywang binarywang added this to the 4.8.5 milestone Jun 13, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants