Skip to content

Commit 6311769

Browse files
authored
🆕 #3278【微信支付】 增加解析商家转账批次回调通知的方法
1 parent 222882d commit 6311769

File tree

4 files changed

+216
-0
lines changed

4 files changed

+216
-0
lines changed
Lines changed: 131 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,131 @@
1+
package com.github.binarywang.wxpay.bean.notify;
2+
3+
import com.google.gson.annotations.SerializedName;
4+
import lombok.Data;
5+
import lombok.NoArgsConstructor;
6+
7+
import java.io.Serializable;
8+
9+
/**
10+
* 商家转账批次回调通知
11+
* 文档见:https://pay.weixin.qq.com/docs/merchant/apis/batch-transfer-to-balance/transfer-batch-callback-notice.html
12+
*
13+
* @author Wang_Wong
14+
*/
15+
@Data
16+
@NoArgsConstructor
17+
public class WxPayTransferBatchesNotifyV3Result implements Serializable, WxPayBaseNotifyV3Result<WxPayTransferBatchesNotifyV3Result.DecryptNotifyResult> {
18+
private static final long serialVersionUID = -1L;
19+
/**
20+
* 源数据
21+
*/
22+
private OriginNotifyResponse rawData;
23+
/**
24+
* 解密后的数据
25+
*/
26+
private DecryptNotifyResult result;
27+
28+
@Data
29+
@NoArgsConstructor
30+
public static class DecryptNotifyResult implements Serializable {
31+
private static final long serialVersionUID = -1L;
32+
/**
33+
* <pre>
34+
* 字段名:直连商户号
35+
* 变量名:mchid
36+
* 是否必填:是
37+
* 类型:string[1,32]
38+
* 描述:
39+
* 直连商户的商户号,由微信支付生成并下发。
40+
* 示例值:1900000100
41+
* </pre>
42+
*/
43+
@SerializedName(value = "mchid")
44+
private String mchid;
45+
46+
/**
47+
* 【商家批次单号】
48+
* 商户系统内部的商家批次单号,在商户系统内部唯一
49+
*/
50+
@SerializedName(value = "out_batch_no")
51+
private String outBatchNo;
52+
53+
/**
54+
* 【微信批次单号】
55+
* 微信批次单号,微信商家转账系统返回的唯一标识
56+
*/
57+
@SerializedName(value = "batch_id")
58+
private String batchId;
59+
60+
/**
61+
* 【批次状态】
62+
* WAIT_PAY: 待付款确认。需要付款出资商户在商家助手小程序或服务商助手小程序进行付款确认
63+
* ACCEPTED:已受理。批次已受理成功,若发起批量转账的30分钟后,转账批次单仍处于该状态,可能原因是商户账户余额不足等。商户可查询账户资金流水,若该笔转账批次单的扣款已经发生,则表示批次已经进入转账中,请再次查单确认
64+
* PROCESSING:转账中。已开始处理批次内的转账明细单
65+
* FINISHED:已完成。批次内的所有转账明细单都已处理完成
66+
* CLOSED:已关闭。可查询具体的批次关闭原因确认
67+
*/
68+
@SerializedName(value = "batch_status")
69+
private String batchStatus;
70+
71+
/**
72+
* 【批次总笔数】
73+
* 转账总笔数。
74+
*/
75+
@SerializedName(value = "total_num")
76+
private Integer totalNum;
77+
78+
/**
79+
* 【批次总金额】
80+
* 转账总金额,单位为“分”。
81+
*/
82+
@SerializedName(value = "total_amount")
83+
private Integer totalAmount;
84+
85+
/**
86+
* 【转账成功金额】
87+
* 转账成功的金额,单位为“分”。当批次状态为“PROCESSING”(转账中)时,转账成功金额随时可能变化
88+
*/
89+
@SerializedName(value = "success_amount")
90+
private Integer successAmount;
91+
92+
/**
93+
* 【转账成功笔数】
94+
* 转账成功的笔数。当批次状态为“PROCESSING”(转账中)时,转账成功笔数随时可能变化
95+
*/
96+
@SerializedName(value = "success_num")
97+
private Integer successNum;
98+
99+
/**
100+
* 【转账失败金额】
101+
* 转账失败的金额,单位为“分”
102+
*/
103+
@SerializedName(value = "fail_amount")
104+
private Integer failAmount;
105+
106+
/**
107+
* 【转账失败笔数】
108+
* 转账失败的笔数
109+
*/
110+
@SerializedName(value = "fail_num")
111+
private Integer failNum;
112+
113+
/**
114+
* 【批次关闭原因】
115+
* 如果批次单状态为“CLOSED”(已关闭),则有关闭原因
116+
* 可选取值:
117+
* OVERDUE_CLOSE:系统超时关闭,可能原因账户余额不足或其他错误
118+
* TRANSFER_SCENE_INVALID:付款确认时,转账场景已不可用,系统做关单处理
119+
*/
120+
@SerializedName(value = "close_reason")
121+
private String closeReason;
122+
123+
/**
124+
* 【批次更新时间】
125+
* 遵循rfc3339标准格式,格式为yyyy-MM-DDTHH:mm:ss+TIMEZONE,yyyy-MM-DD表示年月日,T出现在字符串中,表示time元素的开头,HH:mm:ss.表示时分秒,TIMEZONE表示时区(+08:00表示东八区时间,领先UTC 8小时,即北京时间)。例如:2015-05-20T13:29:35+08:00表示北京时间2015年05月20日13点29分35秒。
126+
*/
127+
@SerializedName(value = "update_time")
128+
private String updateTime;
129+
130+
}
131+
}

weixin-java-pay/src/main/java/com/github/binarywang/wxpay/service/WxPayService.java

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -980,6 +980,17 @@ WxPayRefundQueryResult refundQuery(String transactionId, String outTradeNo, Stri
980980
*/
981981
WxPayRefundNotifyV3Result parseRefundNotifyV3Result(String notifyData, SignatureHeader header) throws WxPayException;
982982

983+
/**
984+
* 解析商家转账批次回调通知
985+
* https://pay.weixin.qq.com/docs/merchant/apis/batch-transfer-to-balance/transfer-batch-callback-notice.html
986+
*
987+
* @param notifyData
988+
* @param header
989+
* @return
990+
* @throws WxPayException
991+
*/
992+
WxPayTransferBatchesNotifyV3Result parseTransferBatchesNotifyV3Result(String notifyData, SignatureHeader header) throws WxPayException;
993+
983994
/**
984995
* 解析服务商模式退款结果通知
985996
* 详见https://pay.weixin.qq.com/wiki/doc/apiv3_partner/apis/chapter4_1_11.shtml

weixin-java-pay/src/main/java/com/github/binarywang/wxpay/service/impl/BaseWxPayServiceImpl.java

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -432,6 +432,11 @@ public WxPayRefundNotifyV3Result parseRefundNotifyV3Result(String notifyData, Si
432432
return this.baseParseOrderNotifyV3Result(notifyData, header, WxPayRefundNotifyV3Result.class, WxPayRefundNotifyV3Result.DecryptNotifyResult.class);
433433
}
434434

435+
@Override
436+
public WxPayTransferBatchesNotifyV3Result parseTransferBatchesNotifyV3Result(String notifyData, SignatureHeader header) throws WxPayException {
437+
return this.baseParseOrderNotifyV3Result(notifyData, header, WxPayTransferBatchesNotifyV3Result.class, WxPayTransferBatchesNotifyV3Result.DecryptNotifyResult.class);
438+
}
439+
435440
@Override
436441
public WxPayPartnerRefundNotifyV3Result parsePartnerRefundNotifyV3Result(String notifyData, SignatureHeader header) throws WxPayException {
437442
return this.baseParseOrderNotifyV3Result(notifyData, header, WxPayPartnerRefundNotifyV3Result.class, WxPayPartnerRefundNotifyV3Result.DecryptNotifyResult.class);

weixin-java-pay/src/test/java/com/github/binarywang/wxpay/service/impl/BaseWxPayServiceImplTest.java

Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -841,6 +841,75 @@ public String testParseRefundNotifyV3Result(HttpServletRequest request, HttpServ
841841
return WxPayNotifyV3Response.success("成功");
842842
}
843843

844+
/**
845+
* 商家转账批次回调通知
846+
* https://pay.weixin.qq.com/docs/merchant/apis/batch-transfer-to-balance/transfer-batch-callback-notice.html
847+
*
848+
* @return
849+
* @throws Exception
850+
*/
851+
@Test
852+
public String parseTransferBatchesNotifyV3Result() throws Exception {
853+
854+
String body = "{\n" +
855+
" \"id\": \"1c8192d8-aba1-5898-a79c-7d3abb72eabe\",\n" +
856+
" \"create_time\": \"2023-08-16T16:43:27+08:00\",\n" +
857+
" \"resource_type\": \"encrypt-resource\",\n" +
858+
" \"event_type\": \"MCHTRANSFER.BATCH.FINISHED\",\n" +
859+
" \"summary\": \"商家转账批次完成通知\",\n" +
860+
" \"resource\": {\n" +
861+
" \"original_type\": \"mch_payment\",\n" +
862+
" \"algorithm\": \"AEAD_AES_256_GCM\",\n" +
863+
" \"ciphertext\": \"zTBf6DDPzZSoIBkoLFkC+ho97QrqnT6UU/ADM0tJP07ITaFPek4vofQjmclLUof78NqrPcJs5OIBl+gnKKJ4xCxcDmDnZZHvev5o1pk4gwtJIFIDxbq3piDr4Wq6cZpvGPPQTYC8YoVRTdVeeN+EcuklRrmaFzv8wCTSdI9wFJ9bsxtLedhq4gpkKqN5fbSguQg9JFsX3OJeT7KPfRd6SD1gu4Lpw5gwxthfOHcYsjM/eY5gaew8zzpN6mMUEJ1HqkNuQgOguHBxFnqFPiMz+Iadw7X38Yz+IgfUkOhN1iuvMhGYKbwKJ7rTiBVvGGpF6Wse1zFKgSiTLH2RnUAMkkHmxqk+JhbQKZpSWr6O8BfhHO1OKg7hpcHZtOJKNMjIF62WYDVf36w1h8h5fg==\",\n" +
864+
" \"associated_data\": \"mch_payment\",\n" +
865+
" \"nonce\": \"DdF3UJVNQaKT\"\n" +
866+
" }\n" +
867+
"}";
868+
WxPayTransferBatchesNotifyV3Result transferBatchesNotifyV3Body = GSON.fromJson(body, WxPayTransferBatchesNotifyV3Result.class);
869+
log.info(GSON.toJson(transferBatchesNotifyV3Body));
870+
871+
// 处理业务逻辑 ...
872+
873+
return WxPayNotifyV3Response.success("成功");
874+
}
875+
876+
// 测试
877+
public static void main(String[] args){
878+
String body = "{\n" +
879+
" \"id\": \"1c8192d8-aba1-5898-a79c-7d3abb72eabe\",\n" +
880+
" \"create_time\": \"2023-08-16T16:43:27+08:00\",\n" +
881+
" \"resource_type\": \"encrypt-resource\",\n" +
882+
" \"event_type\": \"MCHTRANSFER.BATCH.FINISHED\",\n" +
883+
" \"summary\": \"商家转账批次完成通知\",\n" +
884+
" \"resource\": {\n" +
885+
" \"original_type\": \"mch_payment\",\n" +
886+
" \"algorithm\": \"AEAD_AES_256_GCM\",\n" +
887+
" \"ciphertext\": \"zTBf6DDPzZSoIBkoLFkC+ho97QrqnT6UU/ADM0tJP07ITaFPek4vofQjmclLUof78NqrPcJs5OIBl+gnKKJ4xCxcDmDnZZHvev5o1pk4gwtJIFIDxbq3piDr4Wq6cZpvGPPQTYC8YoVRTdVeeN+EcuklRrmaFzv8wCTSdI9wFJ9bsxtLedhq4gpkKqN5fbSguQg9JFsX3OJeT7KPfRd6SD1gu4Lpw5gwxthfOHcYsjM/eY5gaew8zzpN6mMUEJ1HqkNuQgOguHBxFnqFPiMz+Iadw7X38Yz+IgfUkOhN1iuvMhGYKbwKJ7rTiBVvGGpF6Wse1zFKgSiTLH2RnUAMkkHmxqk+JhbQKZpSWr6O8BfhHO1OKg7hpcHZtOJKNMjIF62WYDVf36w1h8h5fg==\",\n" +
888+
" \"associated_data\": \"mch_payment\",\n" +
889+
" \"nonce\": \"DdF3UJVNQaKT\"\n" +
890+
" }\n" +
891+
"}";
892+
OriginNotifyResponse transferBatchesNotifyV3Body = GSON.fromJson(body, OriginNotifyResponse.class);
893+
log.info(GSON.toJson(transferBatchesNotifyV3Body));
894+
895+
String decryptNotifyResult = "{\n" +
896+
" \"out_batch_no\": \"bfatestnotify000033\",\n" +
897+
" \"batch_id\": \"131000007026709999520922023081519403795655\",\n" +
898+
" \"batch_status\": \"FINISHED\",\n" +
899+
" \"total_num\": 2,\n" +
900+
" \"total_amount\": 200,\n" +
901+
" \"success_amount\": 100,\n" +
902+
" \"success_num\": 1,\n" +
903+
" \"fail_amount\": 100,\n" +
904+
" \"fail_num\": 1,\n" +
905+
" \"mchid\": \"2483775951\",\n" +
906+
" \"update_time\": \"2023-08-15T20:33:22+08:00\"\n" +
907+
"}";
908+
WxPayTransferBatchesNotifyV3Result.DecryptNotifyResult notifyResult = GSON.fromJson(decryptNotifyResult, WxPayTransferBatchesNotifyV3Result.DecryptNotifyResult.class);
909+
log.info(GSON.toJson(notifyResult));
910+
911+
}
912+
844913
@Test
845914
public void testWxPayNotifyV3Response() {
846915
System.out.println(WxPayNotifyV3Response.success("success"));

0 commit comments

Comments
 (0)