业务示例代码

更新时间:2025.09.26

1. 目标

通过本教程的学习,你应该可以:

2. 业务处理流程

2.1 申请退款

当交易发生之后一段时间内,由于买家或者卖家的原因需要退款时,卖家可以通过退款接口将支付款退还给买家,微信支付将在收到退款请求并且验证成功之后,按照退款规则将支付款按原路退到买家账户上。

申请退款需要3类信息:

  • 商户信息

    • 二级商户号

    • 平台APPID

    • 二级商户APPID

  • 原支付订单信息

    • 微信支付订单号或者商户订单号

    • 原订单金额

  • 退款信息

    • 商户退款单号:标识该平台商户下的退款单,同一个平台商户下不同商户退款单号表示不同的退款单

    • 退款原因

    • 退款金额

    • 退款出资信息

    • 退款回调URL

1package com.java.ecommerce.refund;
2
3import com.java.demo.CreateRefund; // 使用平台收付通申请退款接口https://pay.weixin.qq.com/doc/v3/partner/4012476892
4import static com.java.demo.CreateRefund.*;
5import com.java.utils.WXPayUtility; // 引用微信支付工具库,参考:https://pay.weixin.qq.com/doc/v3/partner/4014985777
6
7public class CreateRefundDemo {
8  // TODO: 请准备商户开发必要参数,参考:https://pay.weixin.qq.com/doc/v3/partner/4013080340
9  // 商户号,是由微信支付系统生成并分配给每个商户的唯一标识符,商户号获取方式参考
10  // https://pay.weixin.qq.com/doc/v3/partner/4013080340
11  private static String mchid = "19xxxxxxxx";
12  // 商户API证书序列号,如何获取请参考 https://pay.weixin.qq.com/doc/v3/partner/4013058924
13  private static String certificateSerialNo = "1DDE55AD98Exxxxxxxxxx";
14  // 商户API证书私钥文件路径,本地文件路径
15  private static String privateKeyFilePath = "/path/to/apiclient_key.pem";
16  // 微信支付公钥ID,如何获取请参考 https://pay.weixin.qq.com/doc/v3/partner/4013038589
17  private static String wechatPayPublicKeyId = "PUB_KEY_ID_xxxxxxxxxxxxx";
18  // 微信支付公钥文件路径,本地文件路径
19  private static String wechatPayPublicKeyFilePath = "/path/to/wxp_pub.pem";
20
21  public static void main(String[] args) {
22    CreateRefund ceateRefund = new CreateRefund(
23      mchid,
24      certificateSerialNo,
25      privateKeyFilePath,
26      wechatPayPublicKeyId,
27      wechatPayPublicKeyFilePath
28    );
29
30    CreateRefundRequest createRefundRequest = new CreateRefundRequest();
31    // 商户信息
32    createRefundRequest.subMchid = "1900000109";
33    createRefundRequest.spAppid = "wx8888888888888888";
34
35    // 原支付订单信息
36    createRefundRequest.transactionId = "4200000020202506035017900000";
37    createRefundRequest.amount = new RefundReqAmount();
38    createRefundRequest.amount.total = 800L;
39
40    // 退款信息
41    // 商户退款单号生成方式商户视实际情况生成,需要保证平台商户下全局唯一
42    createRefundRequest.outRefundNo = "4200000020202506035017900000_1";
43    createRefundRequest.reason = "成团退差价";
44    createRefundRequest.amount.refund = 200L;
45    // 如果是分账订单,并且未分账完结
46    // - 如果不添加amount.from参数,默认是从不可用余额出资
47    // - 如果添加了amount.from参数
48    // a. 如果amount.from只有一条记录,并且amount.from[0].account == AVAILABLE,
49    // 表示所有退款金额都是从可用余额出资,这个时候需要满足amount.from[0].amount == amount.refund
50    // 这个请求和不添加amount.from参数,同时createRefundRequest.fundsAccount =
51    // ReqFundsAccount.AVAILABLE的请求一致
52    // b. 如果amount.from只有一条记录,并且amount.from[0].account == UNAVAILABLE,
53    // 表示所有退款金额都是从不可用余额出资,这个时候需要满足amount.from[0].amount == amount.refund,
54    // c.
55    // 如果amount.from有两条记录,要求两个的account分别是AVAILABLE和UNAVAILABLE,同时两个的amount之和等于amount.refund,表示退款资金从可用余额账户和不可用余额账户出资退款
56    // d. 其他情况都是请求非法
57    // 使用例子如下:
58    // 1. 只从可用余额出资
59    // createRefundRequest.amount.from = new ArrayList<>();
60    // {
61    // FundsFromItem available = new FundsFromItem();
62    // available.account = Account.AVAILABLE;
63    // available.amount = 200L;
64    // createRefundRequest.amount.from.add(available);
65    // };
66    //
67    // 2. 分别从不可用余额出资50和可用余额出资150出资退款
68    // createRefundRequest.amount.from = new ArrayList<>();
69    // {
70    // FundsFromItem available = new FundsFromItem();
71    // available.account = Account.AVAILABLE;
72    // available.amount = 150L;
73    // createRefundRequest.amount.from.add(available);
74    // };
75    // {
76    // FundsFromItem unavailable = new FundsFromItem();
77    // unavailable.account = Account.UNAVAILABLE;
78    // unavailable.amount = 50L;
79    // createRefundRequest.amount.from.add(unavailable);
80    // };
81
82    // 退款成功,退款关闭,退款异常时需要微信支付通知商户商户,可以加上回调URL,退款到这几个状态时会调用这个URL通知商户
83    createRefundRequest.notifyUrl = "https://weixin.qq.com";
84
85    // 退款出资商户,默认都是二级子商户出资,如果开通了电商平台垫付功能,这里可以设置电商平台垫付退款
86    // createRefundRequest.refundAccount =
87    // RefundAccount.REFUND_SOURCE_PARTNER_ADVANCE;
88
89    // 退款出资账户
90    // 上面的amount.from中已经提到
91    // 如果是分账订单,并且未分账完结,并且想从可用余额出资退款是(默认是从不可用余额出资退款),可以设置如下
92    // createRefundRequest.fundsAccount = ReqFundsAccount.AVAILABLE;
93    // 注意:1. 如果设置了fundsAccount,同时amount.from中同时以不可用余额和可用余额出资退款,请求会非法
94    // 2. 其他情况设置了fundsAccount同时设了amount.from,以fundsAccount为主,忽略amount.from中的参数
95
96    Refund4Create refund4Create;
97    try {
98      refund4Create = ceateRefund.run(createRefundRequest);
99    } catch (WXPayUtility.ApiException e) {
100      // 申请退款处理异常处理逻辑
101      if (e.getErrorCode().equals("SYSTEM_ERROR")) {
102        // 错误:系统错误
103        // 解决方式:稍后原单重试
104        // 描述:微信支付系统失败,一定要原单重试,系统失败直接立即重试大概率还会是系统失败,建议等1分钟后再重试
105      } else if (e.getErrorCode().equals("FREQUENCY_LIMITED")) {
106        // 错误:限频报错
107        // 解决方式:稍后原单重试
108        // 描述: 退款接口频率限制,一定要原单重试,直接立即重试大概率还会是系统失败,建议等1分钟后再重试
109      } else if (e.getErrorCode().equals("MCH_NOT_EXISTS")) {
110        // 错误:二级子商户不存在
111        // 解决方式:检查输入的二级商户号是否填写正确,修改正确之后原单重试
112        // 描述:输入子商户账户不存在,需要填写存在的账户之后重试
113      } else if (e.getErrorCode().equals("USER_ACCOUNT_ABNORMAL")) {
114        // 错误:用户账户异常
115        // 解决方式:退款受理失败,商户可以自行处理退款,也可以登录商户平台进入交易中心发起异常退款
116        // 描述:用户注销或者被管控了,这笔订单已经不能发起退款,这个错误就不需要重试了
117      } else if (e.getErrorCode().equals("NOT_ENOUGH")) {
118        // 错误:账户余额不足
119        // 解决方式:商户充值之后原单重试
120        // 描述:商户账户余额不足,导致退款失败,商户充值之后一定要原单重试
121      } else if (e.getErrorCode().equals("NO_AUTH")) {
122        // 错误:无退款权限
123        // 解决方式:
124        // 1. 检查商户是否是被处罚:登录商户平台进入账户中心-违约记录查询是否违约记录,如果有按照上面的指引解决违约记录之后原单重试
125        // 2.
126        // 检查二级子商户是否已授权平台商户API退款权限:登录商户平台进入产品中心-特约商户授权产品,在特约商户列表中看看该二级商户是否存在并且授权状态为“已授权”,
127        // 如果不存在或者授权状态不是“已授权”就需要发起授权邀请,等二级商户审批之后重新查询一遍,授权状态为“已授权”之后再原单重试
128        // 描述:平台商户被处罚或者平台商户和二级子商户没有父子受理关系
129      } else if (e.getErrorCode().equals("SIGN_ERROR")) {
130        // 错误:签名错误
131        // 解决方式:检查平台商户证书序列号,证书私钥文件,公钥ID,公钥文件,同时确认下签名过程是不是按照微信支付的签名方式
132        // 描述:签名报错,需要确认签名材料和签名流程是否正确
133      } else if (e.getErrorCode().equals("PARAM_ERROR")) {
134        // 错误:参数错误
135        // 解决方式:按照报错返回的message,重新输入请求参数
136        // 描述:参数的类型,长度,或者必填选项没有填写等
137      } else if (e.getErrorCode().equals("INVALID_REQUEST")) {
138        // 错误:请求非法,请求参数正确,但是不符合退款业务规则
139        // 解决方式:根据具体message查看具体哪里不符合业务规则,如果可以修改参数达到符合业务规则的修改请求符合业务规则之后再原单重试
140        // 描述:不符合业务规则的场景如:
141        // - 交易时间超过365天,不允许发起退款
142        // - 一笔订单退款次数已经超过50次了,这笔订单不允许发起新的退款
143        // - 申请退款的金额超过了这笔订单剩余可退金额,不允许申请退款
144      } else {
145        // 其他类型错误:稍等一会后原单重试
146      }
147
148    }
149  }
150}

2.2 查询退款

上面申请退款成功之后,说明微信支付成功受理了这笔退款,并不是已经退款到账,商户可以通过查询退款接口查询退款结果

退款单的状态机:

2.2.1 按商户退款单号查询单笔退款

1package com.java.ecommerce.refund;
2
3import com.java.demo.CreateRefund; // 使用平台收付通申请退款接口,见:https://pay.weixin.qq.com/doc/v3/partner/4012476892
4import static com.java.demo.CreateRefund.*;
5import com.java.demo.QueryRefundByOutRefundNo; // 使用平台收付通查询单笔退款(按商户退款单号)接口,见:https://pay.weixin.qq.com/doc/v3/partner/4012476911
6import static com.java.demo.QueryRefundByOutRefundNo.*;
7import com.java.demo.CreateAbnormalRefund; // 使用平台收付通发起异常退款接口,见:https://pay.weixin.qq.com/doc/v3/partner/4015181616
8import static com.java.demo.CreateAbnormalRefund.*;
9import com.java.utils.WXPayUtility; // 引用微信支付工具库,参考:https://pay.weixin.qq.com/doc/v3/partner/4014985777
10
11public class QueryRefundByOutRefundNoDemo {
12  // TODO: 请准备商户开发必要参数,参考:https://pay.weixin.qq.com/doc/v3/partner/4013080340
13  // 商户号,是由微信支付系统生成并分配给每个商户的唯一标识符,商户号获取方式参考
14  // https://pay.weixin.qq.com/doc/v3/partner/4013080340
15  private static String mchid = "19xxxxxxxx";
16  // 商户API证书序列号,如何获取请参考 https://pay.weixin.qq.com/doc/v3/partner/4013058924
17  private static String certificateSerialNo = "1DDE55AD98Exxxxxxxxxx";
18  // 商户API证书私钥文件路径,本地文件路径
19  private static String privateKeyFilePath = "/path/to/apiclient_key.pem";
20  // 微信支付公钥ID,如何获取请参考 https://pay.weixin.qq.com/doc/v3/partner/4013038589
21  private static String wechatPayPublicKeyId = "PUB_KEY_ID_xxxxxxxxxxxxx";
22  // 微信支付公钥文件路径,本地文件路径
23  private static String wechatPayPublicKeyFilePath = "/path/to/wxp_pub.pem";
24
25  public static void main(String[] args) {
26    QueryRefundByOutRefundNo client = new QueryRefundByOutRefundNo(
27      mchid,
28      certificateSerialNo,
29      privateKeyFilePath,
30      wechatPayPublicKeyId,
31      wechatPayPublicKeyFilePath
32    );
33
34    QueryRefundByOutRefundNoRequest request = new QueryRefundByOutRefundNoRequest();
35    request.outRefundNo = "4200000020202506035017900000_1";
36    request.subMchid = "1900000109";
37
38    try {
39      QueryRefundByOutRefundNo.Refund refund = client.run(request);
40      switch (refund.status) {
41        case "SUCCESS":
42          // 终态:退款成功(退款到账)
43          // 更新商户自己的业务单据状态为成功
44          // UpdateRefund2Succ();
45          break;
46        case "CLOSED":
47          // 终态:退款关闭
48          // 更新商户自己的业务单据状态为关闭
49          // UpdateRefund2Closed();
50          // 如果还需要退款,需要换单(换outRefundNo)重新申请退款
51          CreateRefund createRefund = new CreateRefund(
52            mchid,
53            certificateSerialNo,
54            privateKeyFilePath,
55            wechatPayPublicKeyId,
56            wechatPayPublicKeyFilePath
57          );
58
59          CreateRefundRequest createRefundRequest = new CreateRefundRequest();
60          // 其他参数和之前申请退款参数一样,只改商户退款单号
61          createRefundRequest.outRefundNo = "4200000020202506035017900000_2";
62          createRefund.run(createRefundRequest);
63
64          break;
65        case "PROCESSING":
66          // 非终态:退款处理中 - 还未到账,需要隔一段时间再来查询
67          break;
68        case "ABNORMAL":
69          // 非终态:退款异常 - 用户异常、用户被管控等原因不能原路退
70          // 可以用两种处理方式:
71          // 1. 商户登录商户平台进入交易中心发起异常退款,把钱退到用户指定的银行卡或者商户的银行
72          // 2. 请求异常退款API
73          // TODO: 请准备商户开发必要参数,参考:https://pay.weixin.qq.com/doc/v3/partner/4013080340
74          CreateAbnormalRefund createAbnormalRefund = new CreateAbnormalRefund(
75            mchid,
76            certificateSerialNo,
77            privateKeyFilePath,
78            wechatPayPublicKeyId,
79            wechatPayPublicKeyFilePath
80          );
81          CreateAbnormalRefundRequest abnormalRefundRequest = new CreateAbnormalRefundRequest();
82          abnormalRefundRequest.refundId = refund.refundId;
83          abnormalRefundRequest.subMchid = "1900000109";
84          abnormalRefundRequest.outRefundNo = "4200000020202506035017900000_1";
85          abnormalRefundRequest.type = AbnormalReceiveType.USER_BANK_CARD;
86          abnormalRefundRequest.bankType = "ICBC_DEBIT";
87          abnormalRefundRequest.bankAccount = createAbnormalRefund.encrypt("请填 用户的银行卡号");
88          abnormalRefundRequest.realName = createAbnormalRefund.encrypt("请填 收款用户姓名");
89          CreateAbnormalRefund.Refund abnormalRefund = createAbnormalRefund.run(abnormalRefundRequest);
90          // 发起异常退款成功之后,退款单会进入退款中,还是需要通过查单接口查询退款单的状态
91          break;
92        default:
93          // 非法状态
94          throw new IllegalArgumentException("微信支付退款单状态非法");
95      }
96    } catch (WXPayUtility.ApiException e) {
97      // 查询退款处理异常处理逻辑
98      if (e.getErrorCode().equals("RESOURCE_NOT_EXISTS")) {
99        // 错误:退款单不存在
100        // 解决方式:原参数申请退款
101        // 描述:退款受理没成功,原参数发起退款申请即可
102      } else if (e.getErrorCode().equals("SYSTEM_ERROR")) {
103        // 错我:系统错误
104        // 解决方式:稍后原单重试
105        // 描述:微信支付系统失败,直接立即重试大概率还会是系统失败,建议等1分钟后再重试
106      } else if (e.getErrorCode().equals("FREQUENCY_LIMITED")) {
107        // 错误:限频报错
108        // 处理逻辑:稍后原单重试
109        // 描述: 退款接口频率限制,直接立即重试大概率还会是系统失败,建议等1分钟后再重试
110      } else if (e.getErrorCode().equals("MCH_NOT_EXISTS")) {
111        // 错误:二级子商户不存在
112        // 处理逻辑:检查输入的二级商户号是否填写正确,修改正确之后原单重试
113        // 描述:输入子商户账户不存在,需要填写存在的账户之后重试
114      } else if (e.getErrorCode().equals("NO_AUTH")) {
115        // 错误:无退款权限
116        // 处理逻辑:检查平台商户是否退款权限,平台商户和二级子商户是否有父子受理关系,需要开通平台商户的退款权限和添加二级子商户的父子受理权限才能发起退款
117        // 描述:平台商户无退款权限或者平台商户和二级子商户没有父子受理关系
118      } else if (e.getErrorCode().equals("SIGN_ERROR")) {
119        // 错误:签名错误
120        // 处理逻辑:检查平台商户证书序列号,证书私钥文件,公钥ID,公钥文件,同时确认下签名过程是不是按照微信支付的签名方式
121        // 描述:签名报错,需要确认签名材料和签名流程是否正确
122      } else if (e.getErrorCode().equals("PARAM_ERROR")) {
123        // 错误:参数错误
124        // 处理逻辑:按照报错返回的message,重新输入请求参数
125        // 描述:参数的类型,长度,或者必填选项没有填写等
126      } else {
127        // 其他类型错误:稍等一会后原单重试
128      }
129    }
130  }
131}

2.2.2 按微信支付退款单号查询单笔退款

和上面的商户退款单号查询流程一致,只不过查询接口切换到按 查询单笔退款(按微信支付退款单号) 

1package com.java.ecommerce.refund;
2
3import com.java.demo.QueryRefund; // 使用平台收付通查询单笔退款(按微信支付退款单号)接口,见:https://pay.weixin.qq.com/doc/v3/partner/4012476908
4import static com.java.demo.QueryRefund.*;
5
6public class QueryRefundByWxRefundNoDemo {
7  // TODO: 请准备商户开发必要参数,参考:https://pay.weixin.qq.com/doc/v3/partner/4013080340
8  // 商户号,是由微信支付系统生成并分配给每个商户的唯一标识符,商户号获取方式参考
9  // https://pay.weixin.qq.com/doc/v3/partner/4013080340
10  private static String mchid = "19xxxxxxxx";
11  // 商户API证书序列号,如何获取请参考 https://pay.weixin.qq.com/doc/v3/partner/4013058924
12  private static String certificateSerialNo = "1DDE55AD98Exxxxxxxxxx";
13  // 商户API证书私钥文件路径,本地文件路径
14  private static String privateKeyFilePath = "/path/to/apiclient_key.pem";
15  // 微信支付公钥ID,如何获取请参考 https://pay.weixin.qq.com/doc/v3/partner/4013038589
16  private static String wechatPayPublicKeyId = "PUB_KEY_ID_xxxxxxxxxxxxx";
17  // 微信支付公钥文件路径,本地文件路径
18  private static String wechatPayPublicKeyFilePath = "/path/to/wxp_pub.pem";
19
20  public static void main(String[] args) {
21    QueryRefund queryRefund = new QueryRefund(
22      mchid,
23      certificateSerialNo,
24      privateKeyFilePath,
25      wechatPayPublicKeyId,
26      wechatPayPublicKeyFilePath
27    );
28
29    QueryRefundRequest request = new QueryRefundRequest();
30    request.refundId = "50000000382019052709732678859";
31    request.subMchid = "1900000109";
32
33    Refund refund = queryRefund.run(request);
34    // 处理流程和上面的按商户退款单号查询单笔退款的一致
35    // xxx
36  }
37}

2.3 退款结果通知

如果商户申请退款时设置了notifyUrl,或者在商户平台-交易中心-交易管理-退款管理-退款配置 中设置了通知URL,那么退款状态变更为SUCCESS、CLOSED或者ABNORMAL后会通过HTTP POST方法回调到这个URL上

如果退款申请是设置了notifyUrl,同时退款配置中也设置了通知URL,已退款申请的URL为准

1package com.java.ecommerce.refund;
2
3import com.java.utils.WXPayUtility; // 引用微信支付工具库,参考:https://pay.weixin.qq.com/doc/v3/partner/4014985777
4import com.java.utils.WXPayUtility.Notification;
5import java.security.PublicKey;
6import okhttp3.Headers;
7import okhttp3.Response;
8import com.google.gson.annotations.SerializedName;
9
10public class RefundNotifyDemo {
11  // TODO: 请准备商户开发必要参数,参考:https://pay.weixin.qq.com/doc/v3/partner/4013080340
12  // 商户号,是由微信支付系统生成并分配给每个商户的唯一标识符,商户号获取方式参考
13  // https://pay.weixin.qq.com/doc/v3/partner/4013080340
14  private static String mchid = "19xxxxxxxx";
15  // 商户API证书序列号,如何获取请参考 https://pay.weixin.qq.com/doc/v3/partner/4013058924
16  private static String certificateSerialNo = "1DDE55AD98Exxxxxxxxxx";
17  // 商户API证书私钥文件路径,本地文件路径
18  private static String privateKeyFilePath = "/path/to/apiclient_key.pem";
19  // 微信支付公钥ID,如何获取请参考 https://pay.weixin.qq.com/doc/v3/partner/4013038589
20  private static String wechatPayPublicKeyId = "PUB_KEY_ID_xxxxxxxxxxxxx";
21  // 微信支付公钥文件路径,本地文件路径
22  private static String wechatPayPublicKeyFilePath = "/path/to/wxp_pub.pem";
23  // 商户APIv3密钥,如何获取请参考 https://pay.weixin.qq.com/doc/v3/partner/4013059095
24  private static String apiv3Key = "your apiv3 key";
25
26  public static class RefundAmount {
27    @SerializedName("total")
28    public Long total;
29
30    @SerializedName("refund")
31    public Long refund;
32
33    @SerializedName("payer_total")
34    public Long payerTotal;
35
36    @SerializedName("payer_refund")
37    public Long payerRefund;
38  }
39  public static class Refund {
40      @SerializedName("sp_mchid")
41      public String spMchid;
42
43      @SerializedName("sub_mchid")
44      public String subMchid;
45
46      @SerializedName("out_trade_no")
47      public String outTradeNo;
48
49      @SerializedName("transaction_id")
50      public String transactionId;
51
52      @SerializedName("out_refund_no")
53      public String outRefundNo;
54
55      @SerializedName("refund_id")
56      public String refundId;
57
58      @SerializedName("refund_status")
59      public String refundStatus;
60
61      @SerializedName("success_time")
62      public String successTime;
63
64      @SerializedName("user_received_account")
65      public String userReceivedAccount;
66
67      @SerializedName("amount")
68      public RefundAmount amount;
69
70      @SerializedName("refund_account")
71      public String refundAccount;
72  }
73
74  public void refundNotify(Response httpResponse) {
75    String refundNotifyStr = WXPayUtility.extractBody(httpResponse); // 微信支付退款通知的原始字符串
76    Headers headers = httpResponse.headers(); // 微信支付退款通知的Headers
77    PublicKey wechatPayPublicKey = WXPayUtility.loadPublicKeyFromPath(wechatPayPublicKeyFilePath);
78
79    Notification notification = WXPayUtility.parseNotification(
80        apiv3Key,
81        wechatPayPublicKeyId, wechatPayPublicKey, headers,
82        refundNotifyStr);
83
84    // 检查这个ID是否已经处理过了,ID是微信支付系统生成的唯一ID,每个ID只需要处理一次
85    // CheckIfIdProcessed(notification.getId());
86
87    // 解析退款单
88    Refund refund = WXPayUtility.fromJson(notification.getResource().getCiphertext(), Refund.class);
89
90    // 处理退款事件
91    switch (notification.getEventType()) {
92      case "REFUND.SUCCESS":
93        // 退款成功, 理论上退款单的状态是成功态,这里多做一次校验
94        if (refund.refundStatus.equals("SUCCESS")) {
95          // 退款成功, 处理退款成功逻辑
96          // UpdateRefund2Succ();
97        } else {
98          // 退款单状态非法,报错返回
99          throw new IllegalArgumentException("退款单状态非法");
100        }
101        break;
102      case "REFUND.ABNORMAL":
103        // 退款异常, 理论上退款单的状态应该是异常态,这里多做一次校验
104        if (refund.refundStatus.equals("ABNORMAL")) {
105          // 退款异常, 处理退款异常逻辑
106          // 可以和查单发现退款单异常处理逻辑一样,可以用两种处理方式:
107          // 1. 商户登录商户平台进入交易中心发起异常退款,把钱退到用户指定的银行卡或者商户的银行
108          // 2. 请求异常退款API
109          // UpdateRefund2Abnormal();
110        } else {
111          // 退款单状态非法,报错返回
112          throw new IllegalArgumentException("退款单状态非法");
113        }
114        break;
115      case "REFUND.CLOSED":
116        // 退款关闭, 理论上退款单的状态应该是关闭态,这里多做一次校验
117        if (refund.refundStatus.equals("CLOSED")) {
118          // 退款关闭, 处理退款关闭逻辑
119          // 可以和查单发现退款单关闭处理逻辑一样(如果还需要退款,需要换单之后重新发起退款)
120          // UpdateRefund2Closed();
121        } else {
122          // 退款单状态非法,报错返回
123          throw new IllegalArgumentException("退款单状态非法");
124        }
125        break;
126      default:
127        // 非法事件类型,报错返回
128        throw new IllegalArgumentException("退款事件非法");
129    }
130    
131  }
132
133}
134