轉 微信支付-商戶如何處理微信申請退款、退款回調、查詢退款接口


本文由 簡悅 SimpRead 轉碼, 原文地址 mp.weixin.qq.com

點擊上面藍字關注公眾號喲~

坐穩了沒?起飛~

本文是【淺析微信支付】系列文章的第八篇,主要講解商戶如何處理微信申請退款、退款回調、查詢退款接口,其中有一些坑的地方,會着重強調。


淺析微信支付系列已經更新七篇了喲~,沒有看過的朋友們可以看一下哦。

淺析微信支付:查詢訂單和關閉訂單

淺析微信支付:支付結果通知

淺析微信支付:統一下單接口

在實際場景中,申請退款和退款回調接口是比較常用到的微信支付接口,這里我們會講 原路返回方式的退款,還有的是使用直接為用戶 付款到零錢、 現金紅包等方式來退款,此種情況主要會出現在客服退款時,不是全部退款的情況,也有的會出現在使用了 微信代金券-單品券的時候,因為單品券不能部分退款,所以只能走企業付款用戶的方式,以下我們主要講 原路返回退款。

PS:原路返回的意思就是,從你支付時的關聯支付單中扣款,微信會記錄相關數據,可以在客戶端通知中展示。

1、申請退款接口

以下為微信官方的 申請退款文檔:



1.  `https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=9_4`
    


1.1. 應用場景

當交易發生之后一段時間內,由於買家或者賣家的原因需要退款時,賣家可以通過退款接口將支付款退還給買家,微信支付將在收到退款請求並且驗證成功之后,按照退款規則將支付款按原路退到買家帳號上。



1.  `注意:`
    
2.  `1、交易時間超過一年的訂單無法提交退款`
    
3.  `2、微信支付退款支持單筆交易分多次退款,多次退款需要提交原支付訂單的商戶訂單號和設置不同的退款單號。申請退款總金額不能超過訂單金額。 一筆退款失敗后重新提交,請不要更換退款單號,請使用原商戶退款單號`
    
4.  `3、請求頻率限制:150qps,即每秒鍾正常的申請退款請求次數不超過150次`
    
5.  `錯誤或無效請求頻率限制:6qps,即每秒鍾異常或錯誤的退款申請請求不超過6次`
    
6.  `4、每個支付訂單的部分退款次數不能超過50次`
    


PS:以上限制一般情況下不會出現,但我們也必須寫入系統異常場景處理中,請求頻率可以使用隊列或增加延遲等方式來處理,部分退款此時不要超過微信的限制。

1.2. 接口鏈接



1.  `https://api.mch.weixin.qq.com/secapi/pay/refund`
    


1.3. 是否需要證書

請求需要雙向證書。

PS:關於微信證書,可以在 [商戶平台-賬戶中心-API安全] 去下載,此證書很多支付接口均需要使用,請將證書地址配置為常量,具體實現可以參考作者github源碼。

1.4. 調用接口

先看源碼,如下:



1.  `/**`
    
2.   `* [微信退款接口] - 保存調用的相關記錄`
    
3.   `* @param refundPayment 退款訂單的支付記錄`
    
4.   `* @param tradePayment 歷史付款單`
    
5.   `* @return map`
    
6.   `* @throws Exception e`
    
7.   `*`
    
8.   `* @author yclimb`
    
9.   `* @date 2018/6/21`
    
10.   `*/`
    
11.  `public Map<String,String> saveWxPayRefund(Payment refundPayment, Payment tradePayment) throws Exception {`
    
12.   `if (refundPayment == null || tradePayment == null) {`
    
13.   `return null;`
    
14.   `}`
    

16.   `// 微信訂單號/商戶訂單號,必須傳入其中一個,此處默認傳入商戶訂單號`
    
17.   `// 微信訂單號,微信生成的訂單號,在支付通知中有返回`
    
18.   `// String transaction_id = null;`
    
19.   `// 商戶訂單號,商戶系統內部訂單號,要求32個字符內,只能是數字、大小寫字母_-|*@ ,且在同一個商戶號下唯一。`
    
20.   `String out_trade_no = tradePayment.getFlowNumer();`
    
21.   `// 商戶退款單號,商戶系統內部的退款單號,商戶系統內部唯一,只能是數字、大小寫字母_-|*@ ,同一退款單號多次請求只退一筆。`
    
22.   `String out_refund_no = refundPayment.getFlowNumer();`
    
23.   `// 訂單總金額,傳入參數單位為:元`
    
24.   `String total_fee = String.valueOf(tradePayment.getAmount());`
    
25.   `// 退款總金額,訂單總金額,傳入參數單位為:元`
    
26.   `String refund_fee = String.valueOf(refundPayment.getAmount());`
    
27.   `// 退款原因,若商戶傳入,會在下發給用戶的退款消息中體現退款原因`
    
28.   `String refund_desc = refundPayment.getBody();`
    

30.   `// 微信支付對象`
    
31.   `WXPay wxPay = new WXPay(WXPayConfigImpl.getInstance());`
    

33.   `// 微信退款接口`
    
34.   `Map<String, String> resultMap = wxPay.refund(refundUrl, null, out_trade_no, out_refund_no, total_fee, refund_fee, refund_desc);`
    
35.   `logger.info("saveWxPayRefund:resultMap:" + resultMap.toString());`
    

37.   `// 記錄付款流水`
    

40.   `// 下單失敗,進行處理`
    
41.   `if (WXPayConstants.FAIL.equals(resultMap.get(WXPayConstants.RETURN_CODE)) ||`
    
42.   `WXPayConstants.FAIL.equals(resultMap.get(WXPayConstants.RESULT_CODE))) {`
    

44.   `// 處理結果返回,無需繼續執行`
    
45.   `resultMap.put(WXPayConstants.RESULT_CODE, WXPayConstants.FAIL);`
    
46.   `resultMap.put(WXPayConstants.ERR_CODE_DES, resultMap.get(WXPayConstants.RETURN_MSG));`
    
47.   `return resultMap;`
    
48.   `}`
    

50.   `return resultMap;`
    
51.  `}`
    


以上為sdk退款調用示例代碼,有幾個參數需要我們注意:

字段名 變量名 必填 類型 描述
微信訂單號 transaction_id String(32) 微信生成的訂單號,在支付通知中有返回
商戶訂單號 outtradeno String(32) 商戶系統內部訂單號,要求32個字符內,只能是數字、大小寫字母_-
商戶退款單號 outrefundno String(64) 商戶系統內部的退款單號,商戶系統內部唯一,只能是數字、大小寫字母_-
退款金額 refund_fee Int 退款總金額,訂單總金額,單位為分,只能為整數
退款結果通知url notify_url String(256) 異步接收微信支付退款結果通知的回調地址,通知URL必須為外網可訪問的url,不允許帶參數,如果參數中傳了notify_url,則商戶平台上配置的回調地址將不會生效。

PS:推薦以上的參數都必填, notify_url參數可配置為環境常量,根據環境的不同配置調用不會的回調地址。

下面為具體的實際sdk wxPay.refund調用代碼:



1.  `/**`
    
2.   `* 作用:申請退款<br>`
    
3.   `* 場景:當交易發生之后一段時間內,由於買家或者賣家的原因需要退款時,賣家可以通過退款接口將支付款退還給買家,`
    
4.   `* 微信支付將在收到退款請求並且驗證成功之后,按照退款規則將支付款按原路退到買家帳號上。`
    
5.   `* 接口文檔地址:https://pay.weixin.qq.com/wiki/doc/api/wxa/wxa_api.php?chapter=9_4`
    
6.   `*`
    
7.   `* @param notify_url     回調地址`
    
8.   `* @param transaction_id 微信生成的訂單號,在支付通知中有返回`
    
9.   `* @param out_trade_no   商戶系統內部訂單號,要求32個字符內,只能是數字、大小寫字母_-|*@ ,且在同一個商戶號下唯一。`
    
10.   `* @param out_refund_no  商戶系統內部的退款單號,商戶系統內部唯一,只能是數字、大小寫字母_-|*@ ,同一退款單號多次請求只退一筆。`
    
11.   `* @param total_fee      訂單總金額,傳入參數單位為:元`
    
12.   `* @param refund_fee     退款總金額,訂單總金額,傳入參數單位為:元`
    
13.   `* @param refund_desc    退款原因,若商戶傳入,會在下發給用戶的退款消息中體現退款原因`
    
14.   `* @return API返回數據`
    
15.   `* @throws Exception e`
    
16.   `*/`
    
17.  `public Map<String, String> refund(String notify_url, String transaction_id, String out_trade_no, String out_refund_no,`
    
18.   `String total_fee, String refund_fee, String refund_desc) throws Exception {`
    

20.   `/** 構造請求參數數據 **/`
    
21.   `Map<String, String> data = new HashMap<>();`
    

23.   `// 變量名        字段名 必填  類型  示例值 描述`
    
24.   `// 微信訂單號    二選一 String(32)  1.21775E+27 微信生成的訂單號,在支付通知中有返回`
    
25.   `if (transaction_id != null) {`
    
26.   `data.put("transaction_id", transaction_id);`
    
27.   `}`
    
28.   `// 商戶訂單號    String(32)  1.21775E+27 商戶系統內部訂單號,要求32個字符內,只能是數字、大小寫字母_-|*@ ,且在同一個商戶號下唯一。`
    
29.   `data.put("out_trade_no", out_trade_no);`
    
30.   `// 商戶退款單號    是   String(64)  1.21775E+27 商戶系統內部的退款單號,商戶系統內部唯一,只能是數字、大小寫字母_-|*@ ,同一退款單號多次請求只退一筆。`
    
31.   `data.put("out_refund_no", out_refund_no);`
    
32.   `// 訂單金額    是   Int 100 訂單總金額,單位為分,只能為整數,詳見支付金額`
    
33.   `data.put("total_fee", String.valueOf(new BigDecimal(total_fee).multiply(new BigDecimal(100)).setScale(2, BigDecimal.ROUND_HALF_UP).intValue()));`
    
34.   `// 退款金額    是   Int 100 退款總金額,訂單總金額,單位為分,只能為整數,詳見支付金額`
    
35.   `// 默認單位為分,系統是元,所以需要*100`
    
36.   `data.put("refund_fee", String.valueOf(new BigDecimal(refund_fee).multiply(new BigDecimal(100)).setScale(2, BigDecimal.ROUND_HALF_UP).intValue()));`
    
37.   `// 退款原因    否   String(80)  商品已售完   若商戶傳入,會在下發給用戶的退款消息中體現退款原因`
    
38.   `data.put("refund_desc", refund_desc);`
    
39.   `// 貨幣種類    否   String(8)   CNY 貨幣類型,符合ISO 4217標准的三位字母代碼,默認人民幣:CNY,其他值列表詳見貨幣類型`
    
40.   `data.put("refund_fee_type", WXPayConstants.FEE_TYPE_CNY);`
    
41.   `// 退款結果通知url    否   String(256) https://weixin.qq.com/notify/   異步接收微信支付退款結果通知的回調地址,通知URL必須為外網可訪問的url,不允許帶參數,如果參數中傳了notify_url,則商戶平台上配置的回調地址將不會生效。`
    
42.   `data.put("notify_url", notify_url);`
    

44.   `/** 以下參數為非必填參數 **/`
    
45.   `// 退款資金來源    否   String(30)  REFUND_SOURCE_RECHARGE_FUNDS    僅針對老資金流商戶使用;REFUND_SOURCE_UNSETTLED_FUNDS---未結算資金退款(默認使用未結算資金退款);REFUND_SOURCE_RECHARGE_FUNDS---可用余額退款`
    
46.   `// data.put("refund_account", null);`
    

49.   `/** 以下五個參數,在 this.fillRequestData 方法中會自動賦值 **/`
    
50.   `/*// 小程序ID  appid   是   String(32)  wxd678efh567hg6787  微信分配的小程序ID`
    
51.   `data.put("appid", WXPayConstants.APP_ID);`
    
52.   `// 商戶號    mch_id  是   String(32)  1230000109  微信支付分配的商戶號`
    
53.   `data.put("mch_id", WXPayConstants.MCH_ID);`
    
54.   `// 隨機字符串    nonce_str   是   String(32)  5K8264ILTKCH16CQ2502SI8ZNMTM67VS    隨機字符串,長度要求在32位以內。推薦隨機數生成算法`
    
55.   `data.put("nonce_str", nonce_str);`
    
56.   `// 簽名類型 sign_type   否   String(32)  MD5 簽名類型,默認為MD5,支持HMAC-SHA256和MD5。`
    
57.   `data.put("sign_type", WXPayConstants.MD5);`
    
58.   `// 簽名   sign    是   String(32)  C380BEC2BFD727A4B6845133519F3AD6    通過簽名算法計算得出的簽名值,詳見簽名生成算法`
    
59.   `data.put("sign", sign);*/`
    

61.   `// 微信退款接口`
    
62.   `Map<String, String> resultMap = this.refund(data);`
    

64.   `WXPayUtil.getLogger().info("wxPay.refund:" + resultMap);`
    

66.   `return resultMap;`
    
67.  `}`
    


以上已經詳細說明的具體的字段含義,有不明白的同學可以查看微信的官方文檔,具體的源碼可以查看作者的github。

這里有一個比較需要注意的點,在我們調用退款之后,會返回一些異常處理情況,官方文檔中收錄了一系列錯誤碼code,我們可以在系統中對其進行處理,這里就不細說了。

2、退款回調接口

以下為微信官方的 退款結果通知文檔:



1.  `https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=9_16&index=10`
    


2.1. 應用場景

當商戶申請的退款有結果后,微信會把相關結果發送給商戶,商戶需要接收處理,並返回應答。 對后台通知交互時,如果微信收到商戶的應答不是成功或超時,微信認為通知失敗,微信會通過一定的策略定期重新發起通知,盡可能提高通知的成功率,但微信不保證通知最終能成功。

(通知頻率為15/15/30/180/1800/1800/1800/1800/3600,單位:秒)

注意:同樣的通知可能會多次發送給商戶系統。商戶系統必須能夠正確處理重復的通知。 推薦的做法是,當收到通知進行處理時,首先檢查對應業務數據的狀態,判斷該通知是否已經處理過,如果沒有處理過再進行處理,如果處理過直接返回結果成功。在對業務數據進行狀態檢查和處理之前,要采用數據鎖進行並發控制,以避免函數重入造成的數據混亂。

特別說明:退款結果對重要的數據進行了加密,商戶需要用商戶秘鑰進行解密后才能獲得結果通知的內容

2.2. 接口鏈接

在申請退款接口中上傳參數“notify_url”以開通該功能 如果鏈接無法訪問,商戶將無法接收到微信通知。 通知url必須為直接可訪問的url,不能攜帶參數。



1.  `示例:notify_url:“https://pay.weixin.qq.com/wxpay/pay.action”`
    


2.3. 解密方式



1.  `解密步驟如下:` 
    
2.  `(1)對加密串A做base64解碼,得到加密串B`
    
3.  `(2)對商戶key做md5,得到32位小寫key* ( key設置路徑:微信商戶平台-->賬戶設置-->API安全-->密鑰設置 )`
    
4.  `(3)用key*對加密串B做AES-256-ECB解密(PKCS7Padding)`
    


PS:特別注意,如果要進行微信AES解密,因為GJ的進口管制限制,Java發布的運行環境包中的加解密有一定的限制。默認不允許256位密鑰的AES加解密,解決方法就是修改策略文件,我們需要從官方網站下載無限制權限策略文件,注意自己JDK的版本別下錯了。

jdk8的jce下載地址: https://www.oracle.com/technetwork/java/javase/downloads/jce8-download-2133166.html

將localpolicy.jar和USexportpolicy.jar這兩個文件替換%JREHOME%\lib\security和%JDK_HOME%\jre\lib\security下原來的文件,注意先備份原文件。

如果是jdk8,可能會遇到安全目錄下有 policy文件夾的情況,拿作者的電腦舉例,jdk路徑為 /opt/jdk1.8.0_152/jre/lib/security/policy,此目錄下有兩個子文件夾 limited、 limited,需要替換 limited文件夾下的文件 local_policy.jar、 US_export_policy.jar這兩個,最好先備份哦~!!!替換后重啟項目即可。

2.4. 調用接口

因為退款回調接口是咋們系統被動接收微信的消息,所以此處和支付回調接口一致,也是使用了流的方式,格式為xml,下面我們來看代碼:



1.  `/**`
    
2.   `* 退款結果通知`
    
3.   `* <p>`
    
4.   `* 在申請退款接口中上傳參數“notify_url”以開通該功能`
    
5.   `* 如果鏈接無法訪問,商戶將無法接收到微信通知。`
    
6.   `* 通知url必須為直接可訪問的url,不能攜帶參數。示例:notify_url:“https://pay.weixin.qq.com/wxpay/pay.action”`
    
7.   `* <p>`
    
8.   `* 當商戶申請的退款有結果后,微信會把相關結果發送給商戶,商戶需要接收處理,並返回應答。`
    
9.   `* 對后台通知交互時,如果微信收到商戶的應答不是成功或超時,微信認為通知失敗,微信會通過一定的策略定期重新發起通知,盡可能提高通知的成功率,但微信不保證通知最終能成功。`
    
10.   `* (通知頻率為15/15/30/180/1800/1800/1800/1800/3600,單位:秒)`
    
11.   `* 注意:同樣的通知可能會多次發送給商戶系統。商戶系統必須能夠正確處理重復的通知。`
    
12.   `* 推薦的做法是,當收到通知進行處理時,首先檢查對應業務數據的狀態,判斷該通知是否已經處理過,如果沒有處理過再進行處理,如果處理過直接返回結果成功。在對業務數據進行狀態檢查和處理之前,要采用數據鎖進行並發控制,以避免函數重入造成的數據混亂。`
    
13.   `* 特別說明:退款結果對重要的數據進行了加密,商戶需要用商戶秘鑰進行解密后才能獲得結果通知的內容`
    
14.   `* @param request req`
    
15.   `* @param response resp`
    
16.   `* @return res xml`
    
17.   `*`
    
18.   `* @author yclimb`
    
19.   `* @date 2018/6/21`
    
20.   `*/`
    
21.  `@ApiOperation(value = "微信支付|微信退款回調接口", httpMethod = "POST", notes = "該鏈接是通過【微信退款API】中提交的參數notify_url設置,如果參數中傳了notify_url,則商戶平台上配置的回調地址將不會生效。")`
    
22.  `@RequestMapping("/refund")`
    
23.  `public void refund(HttpServletRequest request, HttpServletResponse response) {`
    

25.   `String resXml = "";`
    
26.   `InputStream inStream;`
    
27.   `try {`
    

29.   `inStream = request.getInputStream();`
    
30.   `ByteArrayOutputStream outSteam = new ByteArrayOutputStream();`
    
31.   `byte[] buffer = new byte[1024];`
    
32.   `int len = 0;`
    
33.   `while ((len = inStream.read(buffer)) != -1) {`
    
34.   `outSteam.write(buffer, 0, len);`
    
35.   `}`
    
36.   `WXPayUtil.getLogger().info("refund:微信退款----start----");`
    

38.   `// 獲取微信調用我們notify_url的返回信息`
    
39.   `String result = new String(outSteam.toByteArray(), "utf-8");`
    
40.   `WXPayUtil.getLogger().info("refund:微信退款----result----=" + result);`
    

42.   `// 關閉流`
    
43.   `outSteam.close();`
    
44.   `inStream.close();`
    

46.   `// xml轉換為map`
    
47.   `Map<String, String> map = WXPayUtil.xmlToMap(result);`
    
48.   `if (WXPayConstants.SUCCESS.equalsIgnoreCase(map.get(WXPayConstants.RETURN_CODE))) {`
    

50.   `WXPayUtil.getLogger().info("refund:微信退款----返回成功");`
    

53.   `/** 以下字段在return_code為SUCCESS的時候有返回: **/`
    
54.   `// 加密信息:加密信息請用商戶秘鑰進行解密,詳見解密方式`
    
55.   `String req_info = map.get("req_info");`
    

57.   `/**`
    
58.   `* 解密方式`
    
59.   `* 解密步驟如下:`
    
60.   `* (1)對加密串A做base64解碼,得到加密串B`
    
61.   `* (2)對商戶key做md5,得到32位小寫key* ( key設置路徑:微信商戶平台(pay.weixin.qq.com)-->賬戶設置-->API安全-->密鑰設置 )`
    
62.   `* (3)用key*對加密串B做AES-256-ECB解密(PKCS7Padding)`
    
63.   `*/`
    
64.   `String resultStr = AESUtil.decryptData(req_info);`
    

66.   `// WXPayUtil.getLogger().info("refund:解密后的字符串:" + resultStr);`
    
67.   `Map<String, String> aesMap = WXPayUtil.xmlToMap(resultStr);`
    

70.   `/** 以下為返回的加密字段: **/`
    
71.   `//    商戶退款單號  是   String(64)  1.21775E+27 商戶退款單號`
    
72.   `String out_refund_no = aesMap.get("out_refund_no");`
    
73.   `//    退款狀態    是   String(16)  SUCCESS SUCCESS-退款成功、CHANGE-退款異常、REFUNDCLOSE—退款關閉`
    
74.   `String refund_status = aesMap.get("refund_status");`
    
75.   `//    商戶訂單號   是   String(32)  1.21775E+27 商戶系統內部的訂單號`
    
76.   `String out_trade_no = aesMap.get("out_trade_no");`
    
77.   `/*//    微信訂單號   是   String(32)  1.21775E+27 微信訂單號`
    
78.   `String transaction_id = null;`
    
79.   `//    微信退款單號  是   String(32)  1.21775E+27 微信退款單號`
    
80.   `String refund_id = null;`
    
81.   `//    訂單金額    是   Int 100 訂單總金額,單位為分,只能為整數,詳見支付金額`
    
82.   `String total_fee = null;`
    
83.   `//    應結訂單金額  否   Int 100 當該訂單有使用非充值券時,返回此字段。應結訂單金額=訂單金額-非充值代金券金額,應結訂單金額<=訂單金額。`
    
84.   `String settlement_total_fee = null;`
    
85.   `//    申請退款金額  是   Int 100 退款總金額,單位為分`
    
86.   `String refund_fee = null;`
    
87.   `//    退款金額    是   Int 100 退款金額=申請退款金額-非充值代金券退款金額,退款金額<=申請退款金額`
    
88.   `String settlement_refund_fee = null;*/`
    

90.   `// 退款是否成功`
    
91.   `if (!WXPayConstants.SUCCESS.equals(refund_status)) {`
    
92.   `resXml = resFailXml;`
    
93.   `} else {`
    
94.   `// 通知微信.異步確認成功.必寫.不然會一直通知后台.八次之后就認為交易失敗了.`
    
95.   `resXml = resSuccessXml;`
    
96.   `isSuccess = true;`
    
97.   `}`
    

99.   `// 根據付款單號查詢付款記錄 out_refund_no`
    

101.   `// 付款記錄修改 & 記錄付款日志`
    
102.   `if (payment != null) {`
    
103.   `WXPayUtil.getLogger().error("refund:微信支付回調:修改支付單");`
    
104.   `} else {`
    
105.   `WXPayUtil.getLogger().error("refund:微信支付回調:找不到對應的支付單");`
    
106.   `}`
    

109.   `} else {`
    
110.   `WXPayUtil.getLogger().error("refund:支付失敗,錯誤信息:" + map.get(WXPayConstants.RETURN_MSG));`
    
111.   `resXml = resFailXml;`
    
112.   `}`
    

114.   `} catch (Exception e) {`
    
115.   `WXPayUtil.getLogger().error("refund:微信退款回調發布異常:", e);`
    
116.   `} finally {`
    
117.   `try {`
    
118.   `// 處理業務完畢`
    
119.   `BufferedOutputStream out = new BufferedOutputStream(response.getOutputStream());`
    
120.   `out.write(resXml.getBytes());`
    
121.   `out.flush();`
    
122.   `out.close();`
    
123.   `} catch (IOException e) {`
    
124.   `WXPayUtil.getLogger().error("refund:微信退款回調發布異常:out:", e);`
    
125.   `}`
    
126.   `}`
    
127.  `}`
    


以上代碼詳細解釋了如何接收微信回調數據和解碼數據,具體的 AESUtil.decryptData(req_info)請參考作者源碼,文末有地址,這里就不細講了。

具體的退款接收參數請參考微信官方文檔,需要注意的是 商戶退款單號和 微信退款單號,此兩個參數是修改和記錄退款的必要憑證。

3、查詢退款

以下為微信官方的 查詢退款文檔:



1.  `https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=9_5`
    


3.1. 應用場景

提交退款申請后,通過調用該接口查詢退款狀態。退款有一定延時,用零錢支付的退款20分鍾內到賬,銀行卡支付的退款3個工作日后重新查詢退款狀態。

注意:如果單個支付訂單部分退款次數超過20次請使用退款單號查詢

3.2. 接口鏈接



1.  `https://api.mch.weixin.qq.com/pay/refundquery`
    


3.3. 是否需要證書

不需要

3.4. 調用接口

注意:當一個訂單部分退款超過10筆后,商戶用微信訂單號或商戶訂單號調退款查詢API查詢退款時,默認返回前10筆和 total_refund_count(訂單總退款次數)。商戶需要查詢同一訂單下超過10筆的退款單時,可傳入訂單號及offset來查詢,微信支付會返回offset及后面的10筆,以此類推。當商戶傳入的offset超過 total_refund_count,則系統會返回報錯 PARAM_ERROR

舉例:



1.  `一筆訂單下的退款單有36筆,當商戶想查詢第25筆時,可傳入訂單號及offset=24,微信支付平台會返回第25筆到第35筆的退款單信息,或商戶可直接傳入退款單號查詢退款`
    


以下為調用方式:



1.  `private void doRefundQuery() {`
    
2.   `// 四選一,微信訂單號查詢的優先級是: refund_id > out_refund_no > transaction_id > out_trade_no`
    
3.   `HashMap<String, String> data = new HashMap<String, String>();`
    
4.   `// 商戶訂單號`
    
5.   `data.put("out_trade_no", out_trade_no);`
    
6.   `// 微信訂單號`
    
7.   `data.put("transaction_id", out_trade_no);`
    
8.   `// 商戶退款單號` 
    
9.   `data.put("out_refund_no", out_trade_no);`
    
10.   `// 微信退款單號` 
    
11.   `data.put("refund_id", out_trade_no);`
    
12.   `try {`
    
13.   `Map<String, String> r = wxpay.refundQuery(data);`
    
14.   `System.out.println(r);`
    
15.   `} catch (Exception e) {`
    
16.   `e.printStackTrace();`
    
17.   `}`
    
18.  `}`
    


PS:微信訂單號查詢的優先級是: refundid > outrefundno > transactionid > outtradeno

需要注意的是,查詢退款時,需要注意退款返回的錯誤碼,如果出現錯誤,需要及時同步商戶系統中的退款數據。

結語

以上為 申請退款、退款回調接口、查詢退款相關的解釋和源碼,特別需要注意的是接收退款時的解密方式和替換安全文件,小伙伴們一定要注意哦,具體的源碼可以看作者的github,里面對每個方法有詳細的注釋。

預告:下一篇文章 下載對賬單和資金賬單,敬請期待!!!

如果想要提前一覽源碼的小伙伴,可以先看看我的 github,地址如下:

https://github.com/YClimb/wxpay-sdk/blob/master/README.md

加作者私人微信,作者微信號如下 yclimb,標明 微信支付 可拉入微信支付討論群與小伙伴一起探討哦,一定要標明 微信支付 哦~

到此本文就結束了,關注公眾號查看更多推送!!!


更多文章推薦:

淺析微信支付:查詢訂單和關閉訂單

淺析微信支付:支付結果通知

淺析微信支付:統一下單接口

淺析微信支付:微信公眾號網頁授權

淺析微信支付:開發前的准備

淺析微信支付:微信支付簡單介紹(小程序、公眾號、App、H5)

Redis設置key/value的規則定義和注意事項(附工具類)

Spring+Dubbo集成Redis的兩種解決方案


- END -

你的點贊和轉發 = 作者的無限動力

圖片

讓我們盪起雙槳

在知識的海洋里自由翱翔

長按二維碼

關注一波~

圖片


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM