|
| 1 | +# 微信支付新版商户转账API使用指南 |
| 2 | + |
| 3 | +## 概述 |
| 4 | + |
| 5 | +从2025年1月15日开始,微信支付推出了新版的商户转账API。新开通的商户号只能使用最新版本的商户转账接口。WxJava 已经完整支持新版转账API。 |
| 6 | + |
| 7 | +## API对比 |
| 8 | + |
| 9 | +### 传统转账API (仍然支持) |
| 10 | +- **服务类**: `MerchantTransferService` |
| 11 | +- **API前缀**: `/v3/transfer/batches` |
| 12 | +- **特点**: 支持批量转账,一次可以转账给多个用户 |
| 13 | + |
| 14 | +### 新版转账API (2025.1.15+) |
| 15 | +- **服务类**: `TransferService` |
| 16 | +- **API前缀**: `/v3/fund-app/mch-transfer/transfer-bills` |
| 17 | +- **特点**: 单笔转账,支持更丰富的转账场景 |
| 18 | + |
| 19 | +## 使用新版转账API |
| 20 | + |
| 21 | +### 1. 获取服务实例 |
| 22 | + |
| 23 | +```java |
| 24 | +// 获取WxPayService实例 |
| 25 | +WxPayService wxPayService = new WxPayServiceImpl(); |
| 26 | +wxPayService.setConfig(config); |
| 27 | + |
| 28 | +// 获取新版转账服务 |
| 29 | +TransferService transferService = wxPayService.getTransferService(); |
| 30 | +``` |
| 31 | + |
| 32 | +### 2. 发起转账 |
| 33 | + |
| 34 | +```java |
| 35 | +// 构建转账请求 |
| 36 | +TransferBillsRequest request = TransferBillsRequest.newBuilder() |
| 37 | + .appid("your_appid") // 应用ID |
| 38 | + .outBillNo("T" + System.currentTimeMillis()) // 商户转账单号 |
| 39 | + .transferSceneId("1005") // 转账场景ID(佣金报酬) |
| 40 | + .openid("user_openid") // 用户openid |
| 41 | + .userName("张三") // 收款用户姓名(可选,需要加密) |
| 42 | + .transferAmount(100) // 转账金额(分) |
| 43 | + .transferRemark("佣金报酬") // 转账备注 |
| 44 | + .notifyUrl("https://your-domain.com/notify") // 回调地址(可选) |
| 45 | + .userRecvPerception("Y") // 用户收款感知(可选) |
| 46 | + .build(); |
| 47 | + |
| 48 | +try { |
| 49 | + TransferBillsResult result = transferService.transferBills(request); |
| 50 | + System.out.println("转账成功,微信转账单号:" + result.getTransferBillNo()); |
| 51 | + System.out.println("状态:" + result.getState()); |
| 52 | +} catch (WxPayException e) { |
| 53 | + System.err.println("转账失败:" + e.getMessage()); |
| 54 | +} |
| 55 | +``` |
| 56 | + |
| 57 | +### 3. 查询转账结果 |
| 58 | + |
| 59 | +```java |
| 60 | +// 通过商户单号查询 |
| 61 | +String outBillNo = "T1642567890123"; |
| 62 | +TransferBillsGetResult result = transferService.getBillsByOutBillNo(outBillNo); |
| 63 | + |
| 64 | +// 通过微信转账单号查询 |
| 65 | +String transferBillNo = "1000000000000000000000000001"; |
| 66 | +TransferBillsGetResult result2 = transferService.getBillsByTransferBillNo(transferBillNo); |
| 67 | + |
| 68 | +System.out.println("转账状态:" + result.getState()); |
| 69 | +System.out.println("转账金额:" + result.getTransferAmount()); |
| 70 | +``` |
| 71 | + |
| 72 | +### 4. 撤销转账 |
| 73 | + |
| 74 | +```java |
| 75 | +// 撤销转账(仅在特定状态下可撤销) |
| 76 | +String outBillNo = "T1642567890123"; |
| 77 | +TransferBillsCancelResult cancelResult = transferService.transformBillsCancel(outBillNo); |
| 78 | +System.out.println("撤销结果:" + cancelResult.getState()); |
| 79 | +``` |
| 80 | + |
| 81 | +### 5. 处理回调通知 |
| 82 | + |
| 83 | +```java |
| 84 | +// 在回调接口中处理通知 |
| 85 | +@PostMapping("/transfer/notify") |
| 86 | +public String handleTransferNotify(HttpServletRequest request) throws Exception { |
| 87 | + String notifyData = StreamUtils.copyToString(request.getInputStream(), StandardCharsets.UTF_8); |
| 88 | + |
| 89 | + // 构建签名头 |
| 90 | + SignatureHeader header = new SignatureHeader(); |
| 91 | + header.setTimeStamp(request.getHeader("Wechatpay-Timestamp")); |
| 92 | + header.setNonce(request.getHeader("Wechatpay-Nonce")); |
| 93 | + header.setSignature(request.getHeader("Wechatpay-Signature")); |
| 94 | + header.setSerial(request.getHeader("Wechatpay-Serial")); |
| 95 | + |
| 96 | + try { |
| 97 | + TransferBillsNotifyResult notifyResult = transferService.parseTransferBillsNotifyResult(notifyData, header); |
| 98 | + |
| 99 | + // 处理业务逻辑 |
| 100 | + String outBillNo = notifyResult.getOutBillNo(); |
| 101 | + String state = notifyResult.getState(); |
| 102 | + |
| 103 | + System.out.println("转账单号:" + outBillNo + ",状态:" + state); |
| 104 | + |
| 105 | + return "SUCCESS"; |
| 106 | + } catch (WxPayException e) { |
| 107 | + System.err.println("验签失败:" + e.getMessage()); |
| 108 | + return "FAIL"; |
| 109 | + } |
| 110 | +} |
| 111 | +``` |
| 112 | + |
| 113 | +## 重要参数说明 |
| 114 | + |
| 115 | +### 转账场景ID (transfer_scene_id) |
| 116 | +- **1005**: 佣金报酬(常用) |
| 117 | +- 其他场景ID需要在商户平台申请 |
| 118 | + |
| 119 | +### 转账状态 |
| 120 | +- **PROCESSING**: 转账中 |
| 121 | +- **SUCCESS**: 转账成功 |
| 122 | +- **FAILED**: 转账失败 |
| 123 | +- **REFUNDED**: 已退款 |
| 124 | + |
| 125 | +### 用户收款感知 (user_recv_perception) |
| 126 | +- **Y**: 用户会收到微信转账通知 |
| 127 | +- **N**: 用户不会收到微信转账通知 |
| 128 | + |
| 129 | +## 新旧API对比总结 |
| 130 | + |
| 131 | +| 特性 | 传统API (MerchantTransferService) | 新版API (TransferService) | |
| 132 | +|------|----------------------------------|---------------------------| |
| 133 | +| 发起方式 | 批量转账 | 单笔转账 | |
| 134 | +| API路径 | `/v3/transfer/batches` | `/v3/fund-app/mch-transfer/transfer-bills` | |
| 135 | +| 场景支持 | 基础转账场景 | 丰富的转账场景 | |
| 136 | +| 回调通知 | 支持 | 支持 | |
| 137 | +| 撤销功能 | 不支持 | 支持 | |
| 138 | +| 适用商户 | 所有商户 | 新开通商户必须使用 | |
| 139 | + |
| 140 | +## 注意事项 |
| 141 | + |
| 142 | +1. **新开通的商户号**: 必须使用新版API (`TransferService`) |
| 143 | +2. **转账场景ID**: 需要在商户平台申请相应的转账场景 |
| 144 | +3. **用户姓名加密**: 如果传入用户姓名,会自动进行RSA加密 |
| 145 | +4. **回调验签**: 建议开启回调验签以确保安全性 |
| 146 | +5. **错误处理**: 妥善处理各种异常情况 |
| 147 | + |
| 148 | +通过以上指南,您可以轻松使用WxJava的新版商户转账API功能。 |
0 commit comments