diff --git a/NEW_TRANSFER_API_SUPPORT.md b/NEW_TRANSFER_API_SUPPORT.md index c7e9eaf490..835ff7d518 100644 --- a/NEW_TRANSFER_API_SUPPORT.md +++ b/NEW_TRANSFER_API_SUPPORT.md @@ -17,6 +17,7 @@ | **转账方式** | 批量转账 | 单笔转账 | | **场景支持** | 基础场景 | 丰富场景(如佣金报酬等) | | **撤销功能** | ❌ 不支持 | ✅ 支持 | +| **授权模式** | 仅需确认模式 | ✅ 支持免确认授权模式 | | **适用范围** | 所有商户 | **新开通商户必须使用** | ### 2. 新版API功能列表 @@ -27,6 +28,30 @@ ✅ **回调通知** - `parseTransferBillsNotifyResult()` ✅ **RSA加密** - 自动处理用户姓名加密 ✅ **场景支持** - 支持多种转账场景ID +✅ **授权模式** - 支持免确认收款授权模式 + +### 3. 收款授权模式支持 + +**新增功能:免确认收款授权模式** + +- **需确认收款授权模式**(默认):用户需要手动确认才能收款 +- **免确认收款授权模式**:用户授权后,收款无需确认,转账直接到账 + +#### 使用方法 + +```java +// 免确认授权模式 - 提升用户体验 +TransferBillsRequest request = TransferBillsRequest.newBuilder() + .receiptAuthorizationMode(WxPayConstants.ReceiptAuthorizationMode.NO_CONFIRM_RECEIPT_AUTHORIZATION) + // 其他参数... + .build(); + +// 需确认授权模式(默认) +TransferBillsRequest request2 = TransferBillsRequest.newBuilder() + .receiptAuthorizationMode(WxPayConstants.ReceiptAuthorizationMode.CONFIRM_RECEIPT_AUTHORIZATION) + // 其他参数... + .build(); +``` ## 快速开始 diff --git a/NEW_TRANSFER_API_USAGE.md b/NEW_TRANSFER_API_USAGE.md index 9d1ac8254a..7b1a8da4ea 100644 --- a/NEW_TRANSFER_API_USAGE.md +++ b/NEW_TRANSFER_API_USAGE.md @@ -16,6 +16,100 @@ - **API前缀**: `/v3/fund-app/mch-transfer/transfer-bills` - **特点**: 单笔转账,支持更丰富的转账场景 +## 收款授权模式功能 + +### 授权模式说明 + +微信支付转账支持两种收款授权模式: + +#### 1. 需确认收款授权模式(默认) +- **常量**: `WxPayConstants.ReceiptAuthorizationMode.CONFIRM_RECEIPT_AUTHORIZATION` +- **特点**: 用户收到转账后需要手动点击确认才能到账 +- **适用场景**: 一般的转账场景 +- **用户体验**: 安全性高,但需要额外操作 + +#### 2. 免确认收款授权模式 +- **常量**: `WxPayConstants.ReceiptAuthorizationMode.NO_CONFIRM_RECEIPT_AUTHORIZATION` +- **特点**: 用户事先授权后,转账直接到账,无需确认 +- **适用场景**: 高频转账场景,如佣金发放、返现等 +- **用户体验**: 体验流畅,无需额外操作 +- **前提条件**: 需要用户事先进行授权 + +### 使用示例 + +#### 免确认授权模式转账 + +```java +TransferBillsRequest request = TransferBillsRequest.newBuilder() + .appid("your_appid") + .outBillNo("NO_CONFIRM_" + System.currentTimeMillis()) + .transferSceneId("1005") // 佣金报酬场景 + .openid("user_openid") + .transferAmount(200) // 2元 + .transferRemark("免确认收款转账") + .receiptAuthorizationMode(WxPayConstants.ReceiptAuthorizationMode.NO_CONFIRM_RECEIPT_AUTHORIZATION) + .userRecvPerception("Y") + .build(); + +try { + TransferBillsResult result = transferService.transferBills(request); + System.out.println("转账成功,直接到账:" + result.getTransferBillNo()); +} catch (WxPayException e) { + if ("USER_NOT_AUTHORIZED".equals(e.getErrCode())) { + System.err.println("用户未授权免确认收款,请先引导用户进行授权"); + } +} +``` + +#### 需确认授权模式转账(默认) + +```java +TransferBillsRequest request = TransferBillsRequest.newBuilder() + .appid("your_appid") + .outBillNo("CONFIRM_" + System.currentTimeMillis()) + .transferSceneId("1005") + .openid("user_openid") + .transferAmount(150) // 1.5元 + .transferRemark("需确认收款转账") + // .receiptAuthorizationMode(...) // 不设置时使用默认的确认模式 + .userRecvPerception("Y") + .build(); + +TransferBillsResult result = transferService.transferBills(request); +System.out.println("转账发起成功,等待用户确认:" + result.getPackageInfo()); +``` + +### 错误处理 + +使用免确认授权模式时,需要处理以下可能的错误: + +```java +try { + TransferBillsResult result = transferService.transferBills(request); +} catch (WxPayException e) { + switch (e.getErrCode()) { + case "USER_NOT_AUTHORIZED": + // 用户未授权免确认收款 + System.err.println("请先引导用户进行免确认收款授权"); + // 可以引导用户到授权页面 + break; + case "AUTHORIZATION_EXPIRED": + // 授权已过期 + System.err.println("用户授权已过期,请重新授权"); + break; + default: + System.err.println("转账失败:" + e.getMessage()); + } +} +``` + +### 使用建议 + +1. **高频转账场景**推荐使用免确认模式,提升用户体验 +2. **首次使用**需引导用户进行授权 +3. **处理异常**妥善处理授权相关异常,提供友好的错误提示 +4. **场景选择**根据业务场景选择合适的授权模式 + ## 使用新版转账API ### 1. 获取服务实例 diff --git a/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/transfer/TransferBillsRequest.java b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/transfer/TransferBillsRequest.java index 230e564e4b..2ac4b08c93 100644 --- a/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/transfer/TransferBillsRequest.java +++ b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/transfer/TransferBillsRequest.java @@ -87,6 +87,26 @@ public class TransferBillsRequest implements Serializable { @SerializedName("transfer_scene_report_infos") private List transferSceneReportInfos; + /** + * 收款授权模式 + *
+   * 字段名:收款授权模式
+   * 变量名:receipt_authorization_mode
+   * 是否必填:否
+   * 类型:string
+   * 描述:
+   *  控制收款方式的授权模式,可选值:
+   *  - CONFIRM_RECEIPT_AUTHORIZATION:需确认收款授权模式(默认值)
+   *  - NO_CONFIRM_RECEIPT_AUTHORIZATION:免确认收款授权模式(需要用户事先授权)
+   *  为空时,默认为需确认收款授权模式
+   * 示例值:NO_CONFIRM_RECEIPT_AUTHORIZATION
+   * 
+ * + * @see com.github.binarywang.wxpay.constant.WxPayConstants.ReceiptAuthorizationMode + */ + @SerializedName("receipt_authorization_mode") + private String receiptAuthorizationMode; + @Data @Builder(builderMethodName = "newBuilder") diff --git a/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/constant/WxPayConstants.java b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/constant/WxPayConstants.java index e8a6b6acb3..d936f0dc9e 100644 --- a/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/constant/WxPayConstants.java +++ b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/constant/WxPayConstants.java @@ -436,4 +436,25 @@ public static class CASH_MARKETING { } } + + /** + * 收款授权模式 + * + * @see 官方文档 + */ + @UtilityClass + public static class ReceiptAuthorizationMode { + /** + * 需确认收款授权模式(默认值) + * 用户需要手动确认才能收款 + */ + public static final String CONFIRM_RECEIPT_AUTHORIZATION = "CONFIRM_RECEIPT_AUTHORIZATION"; + + /** + * 免确认收款授权模式 + * 用户授权后,收款不需要确认,转账直接到账 + */ + public static final String NO_CONFIRM_RECEIPT_AUTHORIZATION = "NO_CONFIRM_RECEIPT_AUTHORIZATION"; + } + } diff --git a/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/example/NewTransferApiExample.java b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/example/NewTransferApiExample.java index 8d74e5a4ef..228234d589 100644 --- a/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/example/NewTransferApiExample.java +++ b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/example/NewTransferApiExample.java @@ -3,6 +3,7 @@ import com.github.binarywang.wxpay.bean.notify.SignatureHeader; import com.github.binarywang.wxpay.bean.transfer.*; import com.github.binarywang.wxpay.config.WxPayConfig; +import com.github.binarywang.wxpay.constant.WxPayConstants; import com.github.binarywang.wxpay.exception.WxPayException; import com.github.binarywang.wxpay.service.TransferService; import com.github.binarywang.wxpay.service.WxPayService; @@ -215,6 +216,100 @@ public void batchTransferExample() { } } + /** + * 使用免确认收款授权模式进行转账示例 + * 注意:使用此模式前,用户需要先进行授权 + */ + public void transferWithNoConfirmAuthModeExample() { + try { + // 构建转账请求,使用免确认收款授权模式 + TransferBillsRequest request = TransferBillsRequest.newBuilder() + .appid("wx1234567890123456") + .outBillNo("NO_CONFIRM_" + System.currentTimeMillis()) // 商户转账单号 + .transferSceneId("1005") // 转账场景ID(佣金报酬) + .openid("oUpF8uMuAJO_M2pxb1Q9zNjWeS6o") // 收款用户的openid + .transferAmount(200) // 转账金额,单位:分(此处为2元) + .transferRemark("免确认收款转账") // 转账备注 + .receiptAuthorizationMode(WxPayConstants.ReceiptAuthorizationMode.NO_CONFIRM_RECEIPT_AUTHORIZATION) + .userRecvPerception("Y") // 用户收款感知 + .build(); + + // 发起转账 + TransferBillsResult result = transferService.transferBills(request); + + System.out.println("=== 免确认授权模式转账成功 ==="); + System.out.println("商户单号: " + result.getOutBillNo()); + System.out.println("微信转账单号: " + result.getTransferBillNo()); + System.out.println("状态: " + result.getState()); + System.out.println("说明: 使用免确认授权模式,转账直接到账,无需用户确认"); + + } catch (WxPayException e) { + System.err.println("免确认授权转账失败: " + e.getMessage()); + System.err.println("错误代码: " + e.getErrCode()); + + // 可能的错误原因 + if ("USER_NOT_AUTHORIZED".equals(e.getErrCode())) { + System.err.println("用户未授权免确认收款,请先引导用户进行授权"); + } + } + } + + /** + * 使用需确认收款授权模式进行转账示例(默认模式) + */ + public void transferWithConfirmAuthModeExample() { + try { + // 构建转账请求,显式设置为需确认收款授权模式 + TransferBillsRequest request = TransferBillsRequest.newBuilder() + .appid("wx1234567890123456") + .outBillNo("CONFIRM_" + System.currentTimeMillis()) // 商户转账单号 + .transferSceneId("1005") // 转账场景ID + .openid("oUpF8uMuAJO_M2pxb1Q9zNjWeS6o") // 收款用户的openid + .transferAmount(150) // 转账金额,单位:分(此处为1.5元) + .transferRemark("需确认收款转账") // 转账备注 + .receiptAuthorizationMode(WxPayConstants.ReceiptAuthorizationMode.CONFIRM_RECEIPT_AUTHORIZATION) + .userRecvPerception("Y") // 用户收款感知 + .build(); + + // 发起转账 + TransferBillsResult result = transferService.transferBills(request); + + System.out.println("=== 需确认授权模式转账成功 ==="); + System.out.println("商户单号: " + result.getOutBillNo()); + System.out.println("微信转账单号: " + result.getTransferBillNo()); + System.out.println("状态: " + result.getState()); + System.out.println("packageInfo: " + result.getPackageInfo()); + System.out.println("说明: 使用需确认授权模式,用户需要手动确认才能收款"); + + } catch (WxPayException e) { + System.err.println("需确认授权转账失败: " + e.getMessage()); + } + } + + /** + * 权限模式对比示例 + * 展示两种权限模式的区别和使用场景 + */ + public void authModeComparisonExample() { + System.out.println("\n=== 收款授权模式对比 ==="); + System.out.println("1. 需确认收款授权模式 (CONFIRM_RECEIPT_AUTHORIZATION):"); + System.out.println(" - 这是默认模式"); + System.out.println(" - 用户收到转账后需要手动点击确认才能到账"); + System.out.println(" - 适用于一般的转账场景"); + System.out.println(" - 转账状态可能包含 WAIT_USER_CONFIRM 等待确认状态"); + + System.out.println("\n2. 免确认收款授权模式 (NO_CONFIRM_RECEIPT_AUTHORIZATION):"); + System.out.println(" - 用户事先授权后,转账直接到账,无需确认"); + System.out.println(" - 提升用户体验,减少操作步骤"); + System.out.println(" - 适用于高频转账场景,如佣金发放等"); + System.out.println(" - 需要用户先进行授权,否则会返回授权错误"); + + System.out.println("\n使用建议:"); + System.out.println("- 高频业务场景推荐使用免确认模式,提升用户体验"); + System.out.println("- 首次使用需引导用户进行授权"); + System.out.println("- 处理授权相关异常,提供友好的错误提示"); + } + /** * 使用配置示例 */ @@ -230,20 +325,29 @@ public static void main(String[] args) { // 创建示例实例 NewTransferApiExample example = new NewTransferApiExample(config); + // 权限模式对比说明 + example.authModeComparisonExample(); + // 运行示例 System.out.println("新版商户转账API使用示例"); System.out.println("==============================="); - // 1. 发起单笔转账 + // 1. 发起转账(使用免确认授权模式) + // example.transferWithNoConfirmAuthModeExample(); + + // 2. 发起转账(使用需确认授权模式) + // example.transferWithConfirmAuthModeExample(); + + // 3. 发起单笔转账(默认模式) example.transferExample(); - // 2. 查询转账结果 + // 4. 查询转账结果 // example.queryByOutBillNoExample(); - // 3. 撤销转账 + // 5. 撤销转账 // example.cancelTransferExample(); - // 4. 批量转账(传统API) + // 6. 批量转账(传统API) // example.batchTransferExample(); } } \ No newline at end of file