Skip to content

Commit b0d9c6c

Browse files
authored
🆕 #3717 【微信支付】商户转账新增免确认收款授权模式支持
1 parent 621b8dc commit b0d9c6c

File tree

5 files changed

+268
-4
lines changed

5 files changed

+268
-4
lines changed

docs/NEW_TRANSFER_API_SUPPORT.md

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
| **转账方式** | 批量转账 | 单笔转账 |
1818
| **场景支持** | 基础场景 | 丰富场景(如佣金报酬等) |
1919
| **撤销功能** | ❌ 不支持 | ✅ 支持 |
20+
| **授权模式** | 仅需确认模式 | ✅ 支持免确认授权模式 |
2021
| **适用范围** | 所有商户 | **新开通商户必须使用** |
2122

2223
### 2. 新版API功能列表
@@ -27,6 +28,30 @@
2728
**回调通知** - `parseTransferBillsNotifyResult()`
2829
**RSA加密** - 自动处理用户姓名加密
2930
**场景支持** - 支持多种转账场景ID
31+
**授权模式** - 支持免确认收款授权模式
32+
33+
### 3. 收款授权模式支持
34+
35+
**新增功能:免确认收款授权模式**
36+
37+
- **需确认收款授权模式**(默认):用户需要手动确认才能收款
38+
- **免确认收款授权模式**:用户授权后,收款无需确认,转账直接到账
39+
40+
#### 使用方法
41+
42+
```java
43+
// 免确认授权模式 - 提升用户体验
44+
TransferBillsRequest request = TransferBillsRequest.newBuilder()
45+
.receiptAuthorizationMode(WxPayConstants.ReceiptAuthorizationMode.NO_CONFIRM_RECEIPT_AUTHORIZATION)
46+
// 其他参数...
47+
.build();
48+
49+
// 需确认授权模式(默认)
50+
TransferBillsRequest request2 = TransferBillsRequest.newBuilder()
51+
.receiptAuthorizationMode(WxPayConstants.ReceiptAuthorizationMode.CONFIRM_RECEIPT_AUTHORIZATION)
52+
// 其他参数...
53+
.build();
54+
```
3055

3156
## 快速开始
3257

docs/NEW_TRANSFER_API_USAGE.md

Lines changed: 94 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,100 @@
1616
- **API前缀**: `/v3/fund-app/mch-transfer/transfer-bills`
1717
- **特点**: 单笔转账,支持更丰富的转账场景
1818

19+
## 收款授权模式功能
20+
21+
### 授权模式说明
22+
23+
微信支付转账支持两种收款授权模式:
24+
25+
#### 1. 需确认收款授权模式(默认)
26+
- **常量**: `WxPayConstants.ReceiptAuthorizationMode.CONFIRM_RECEIPT_AUTHORIZATION`
27+
- **特点**: 用户收到转账后需要手动点击确认才能到账
28+
- **适用场景**: 一般的转账场景
29+
- **用户体验**: 安全性高,但需要额外操作
30+
31+
#### 2. 免确认收款授权模式
32+
- **常量**: `WxPayConstants.ReceiptAuthorizationMode.NO_CONFIRM_RECEIPT_AUTHORIZATION`
33+
- **特点**: 用户事先授权后,转账直接到账,无需确认
34+
- **适用场景**: 高频转账场景,如佣金发放、返现等
35+
- **用户体验**: 体验流畅,无需额外操作
36+
- **前提条件**: 需要用户事先进行授权
37+
38+
### 使用示例
39+
40+
#### 免确认授权模式转账
41+
42+
```java
43+
TransferBillsRequest request = TransferBillsRequest.newBuilder()
44+
.appid("your_appid")
45+
.outBillNo("NO_CONFIRM_" + System.currentTimeMillis())
46+
.transferSceneId("1005") // 佣金报酬场景
47+
.openid("user_openid")
48+
.transferAmount(200) // 2元
49+
.transferRemark("免确认收款转账")
50+
.receiptAuthorizationMode(WxPayConstants.ReceiptAuthorizationMode.NO_CONFIRM_RECEIPT_AUTHORIZATION)
51+
.userRecvPerception("Y")
52+
.build();
53+
54+
try {
55+
TransferBillsResult result = transferService.transferBills(request);
56+
System.out.println("转账成功,直接到账:" + result.getTransferBillNo());
57+
} catch (WxPayException e) {
58+
if ("USER_NOT_AUTHORIZED".equals(e.getErrCode())) {
59+
System.err.println("用户未授权免确认收款,请先引导用户进行授权");
60+
}
61+
}
62+
```
63+
64+
#### 需确认授权模式转账(默认)
65+
66+
```java
67+
TransferBillsRequest request = TransferBillsRequest.newBuilder()
68+
.appid("your_appid")
69+
.outBillNo("CONFIRM_" + System.currentTimeMillis())
70+
.transferSceneId("1005")
71+
.openid("user_openid")
72+
.transferAmount(150) // 1.5元
73+
.transferRemark("需确认收款转账")
74+
// .receiptAuthorizationMode(...) // 不设置时使用默认的确认模式
75+
.userRecvPerception("Y")
76+
.build();
77+
78+
TransferBillsResult result = transferService.transferBills(request);
79+
System.out.println("转账发起成功,等待用户确认:" + result.getPackageInfo());
80+
```
81+
82+
### 错误处理
83+
84+
使用免确认授权模式时,需要处理以下可能的错误:
85+
86+
```java
87+
try {
88+
TransferBillsResult result = transferService.transferBills(request);
89+
} catch (WxPayException e) {
90+
switch (e.getErrCode()) {
91+
case "USER_NOT_AUTHORIZED":
92+
// 用户未授权免确认收款
93+
System.err.println("请先引导用户进行免确认收款授权");
94+
// 可以引导用户到授权页面
95+
break;
96+
case "AUTHORIZATION_EXPIRED":
97+
// 授权已过期
98+
System.err.println("用户授权已过期,请重新授权");
99+
break;
100+
default:
101+
System.err.println("转账失败:" + e.getMessage());
102+
}
103+
}
104+
```
105+
106+
### 使用建议
107+
108+
1. **高频转账场景**推荐使用免确认模式,提升用户体验
109+
2. **首次使用**需引导用户进行授权
110+
3. **处理异常**妥善处理授权相关异常,提供友好的错误提示
111+
4. **场景选择**根据业务场景选择合适的授权模式
112+
19113
## 使用新版转账API
20114

21115
### 1. 获取服务实例

weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/transfer/TransferBillsRequest.java

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,26 @@ public class TransferBillsRequest implements Serializable {
8787
@SerializedName("transfer_scene_report_infos")
8888
private List<TransferSceneReportInfo> transferSceneReportInfos;
8989

90+
/**
91+
* 收款授权模式
92+
* <pre>
93+
* 字段名:收款授权模式
94+
* 变量名:receipt_authorization_mode
95+
* 是否必填:否
96+
* 类型:string
97+
* 描述:
98+
* 控制收款方式的授权模式,可选值:
99+
* - CONFIRM_RECEIPT_AUTHORIZATION:需确认收款授权模式(默认值)
100+
* - NO_CONFIRM_RECEIPT_AUTHORIZATION:免确认收款授权模式(需要用户事先授权)
101+
* 为空时,默认为需确认收款授权模式
102+
* 示例值:NO_CONFIRM_RECEIPT_AUTHORIZATION
103+
* </pre>
104+
*
105+
* @see com.github.binarywang.wxpay.constant.WxPayConstants.ReceiptAuthorizationMode
106+
*/
107+
@SerializedName("receipt_authorization_mode")
108+
private String receiptAuthorizationMode;
109+
90110

91111
@Data
92112
@Builder(builderMethodName = "newBuilder")

weixin-java-pay/src/main/java/com/github/binarywang/wxpay/constant/WxPayConstants.java

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -524,4 +524,25 @@ public static class CASH_MARKETING {
524524
}
525525

526526
}
527+
528+
/**
529+
* 收款授权模式
530+
*
531+
* @see <a href="https://pay.weixin.qq.com/doc/v3/merchant/4014399293">官方文档</a>
532+
*/
533+
@UtilityClass
534+
public static class ReceiptAuthorizationMode {
535+
/**
536+
* 需确认收款授权模式(默认值)
537+
* 用户需要手动确认才能收款
538+
*/
539+
public static final String CONFIRM_RECEIPT_AUTHORIZATION = "CONFIRM_RECEIPT_AUTHORIZATION";
540+
541+
/**
542+
* 免确认收款授权模式
543+
* 用户授权后,收款不需要确认,转账直接到账
544+
*/
545+
public static final String NO_CONFIRM_RECEIPT_AUTHORIZATION = "NO_CONFIRM_RECEIPT_AUTHORIZATION";
546+
}
547+
527548
}

weixin-java-pay/src/main/java/com/github/binarywang/wxpay/example/NewTransferApiExample.java

Lines changed: 108 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
import com.github.binarywang.wxpay.bean.notify.SignatureHeader;
44
import com.github.binarywang.wxpay.bean.transfer.*;
55
import com.github.binarywang.wxpay.config.WxPayConfig;
6+
import com.github.binarywang.wxpay.constant.WxPayConstants;
67
import com.github.binarywang.wxpay.exception.WxPayException;
78
import com.github.binarywang.wxpay.service.TransferService;
89
import com.github.binarywang.wxpay.service.WxPayService;
@@ -215,6 +216,100 @@ public void batchTransferExample() {
215216
}
216217
}
217218

219+
/**
220+
* 使用免确认收款授权模式进行转账示例
221+
* 注意:使用此模式前,用户需要先进行授权
222+
*/
223+
public void transferWithNoConfirmAuthModeExample() {
224+
try {
225+
// 构建转账请求,使用免确认收款授权模式
226+
TransferBillsRequest request = TransferBillsRequest.newBuilder()
227+
.appid("wx1234567890123456")
228+
.outBillNo("NO_CONFIRM_" + System.currentTimeMillis()) // 商户转账单号
229+
.transferSceneId("1005") // 转账场景ID(佣金报酬)
230+
.openid("oUpF8uMuAJO_M2pxb1Q9zNjWeS6o") // 收款用户的openid
231+
.transferAmount(200) // 转账金额,单位:分(此处为2元)
232+
.transferRemark("免确认收款转账") // 转账备注
233+
.receiptAuthorizationMode(WxPayConstants.ReceiptAuthorizationMode.NO_CONFIRM_RECEIPT_AUTHORIZATION)
234+
.userRecvPerception("Y") // 用户收款感知
235+
.build();
236+
237+
// 发起转账
238+
TransferBillsResult result = transferService.transferBills(request);
239+
240+
System.out.println("=== 免确认授权模式转账成功 ===");
241+
System.out.println("商户单号: " + result.getOutBillNo());
242+
System.out.println("微信转账单号: " + result.getTransferBillNo());
243+
System.out.println("状态: " + result.getState());
244+
System.out.println("说明: 使用免确认授权模式,转账直接到账,无需用户确认");
245+
246+
} catch (WxPayException e) {
247+
System.err.println("免确认授权转账失败: " + e.getMessage());
248+
System.err.println("错误代码: " + e.getErrCode());
249+
250+
// 可能的错误原因
251+
if ("USER_NOT_AUTHORIZED".equals(e.getErrCode())) {
252+
System.err.println("用户未授权免确认收款,请先引导用户进行授权");
253+
}
254+
}
255+
}
256+
257+
/**
258+
* 使用需确认收款授权模式进行转账示例(默认模式)
259+
*/
260+
public void transferWithConfirmAuthModeExample() {
261+
try {
262+
// 构建转账请求,显式设置为需确认收款授权模式
263+
TransferBillsRequest request = TransferBillsRequest.newBuilder()
264+
.appid("wx1234567890123456")
265+
.outBillNo("CONFIRM_" + System.currentTimeMillis()) // 商户转账单号
266+
.transferSceneId("1005") // 转账场景ID
267+
.openid("oUpF8uMuAJO_M2pxb1Q9zNjWeS6o") // 收款用户的openid
268+
.transferAmount(150) // 转账金额,单位:分(此处为1.5元)
269+
.transferRemark("需确认收款转账") // 转账备注
270+
.receiptAuthorizationMode(WxPayConstants.ReceiptAuthorizationMode.CONFIRM_RECEIPT_AUTHORIZATION)
271+
.userRecvPerception("Y") // 用户收款感知
272+
.build();
273+
274+
// 发起转账
275+
TransferBillsResult result = transferService.transferBills(request);
276+
277+
System.out.println("=== 需确认授权模式转账成功 ===");
278+
System.out.println("商户单号: " + result.getOutBillNo());
279+
System.out.println("微信转账单号: " + result.getTransferBillNo());
280+
System.out.println("状态: " + result.getState());
281+
System.out.println("packageInfo: " + result.getPackageInfo());
282+
System.out.println("说明: 使用需确认授权模式,用户需要手动确认才能收款");
283+
284+
} catch (WxPayException e) {
285+
System.err.println("需确认授权转账失败: " + e.getMessage());
286+
}
287+
}
288+
289+
/**
290+
* 权限模式对比示例
291+
* 展示两种权限模式的区别和使用场景
292+
*/
293+
public void authModeComparisonExample() {
294+
System.out.println("\n=== 收款授权模式对比 ===");
295+
System.out.println("1. 需确认收款授权模式 (CONFIRM_RECEIPT_AUTHORIZATION):");
296+
System.out.println(" - 这是默认模式");
297+
System.out.println(" - 用户收到转账后需要手动点击确认才能到账");
298+
System.out.println(" - 适用于一般的转账场景");
299+
System.out.println(" - 转账状态可能包含 WAIT_USER_CONFIRM 等待确认状态");
300+
301+
System.out.println("\n2. 免确认收款授权模式 (NO_CONFIRM_RECEIPT_AUTHORIZATION):");
302+
System.out.println(" - 用户事先授权后,转账直接到账,无需确认");
303+
System.out.println(" - 提升用户体验,减少操作步骤");
304+
System.out.println(" - 适用于高频转账场景,如佣金发放等");
305+
System.out.println(" - 需要用户先进行授权,否则会返回授权错误");
306+
307+
System.out.println("\n使用建议:");
308+
System.out.println("- 高频业务场景推荐使用免确认模式,提升用户体验");
309+
System.out.println("- 首次使用需引导用户进行授权");
310+
System.out.println("- 处理授权相关异常,提供友好的错误提示");
311+
}
312+
218313
/**
219314
* 使用配置示例
220315
*/
@@ -230,20 +325,29 @@ public static void main(String[] args) {
230325
// 创建示例实例
231326
NewTransferApiExample example = new NewTransferApiExample(config);
232327

328+
// 权限模式对比说明
329+
example.authModeComparisonExample();
330+
233331
// 运行示例
234332
System.out.println("新版商户转账API使用示例");
235333
System.out.println("===============================");
236334

237-
// 1. 发起单笔转账
335+
// 1. 发起转账(使用免确认授权模式)
336+
// example.transferWithNoConfirmAuthModeExample();
337+
338+
// 2. 发起转账(使用需确认授权模式)
339+
// example.transferWithConfirmAuthModeExample();
340+
341+
// 3. 发起单笔转账(默认模式)
238342
example.transferExample();
239343

240-
// 2. 查询转账结果
344+
// 4. 查询转账结果
241345
// example.queryByOutBillNoExample();
242346

243-
// 3. 撤销转账
347+
// 5. 撤销转账
244348
// example.cancelTransferExample();
245349

246-
// 4. 批量转账(传统API)
350+
// 6. 批量转账(传统API)
247351
// example.batchTransferExample();
248352
}
249353
}

0 commit comments

Comments
 (0)