# 一、回調(diào)描述
當(dāng)商戶調(diào)用申請(qǐng)退款A(yù)PI接口或通過(guò)商戶平臺(tái)申請(qǐng)退款 (opens new window)后,微信支付會(huì)對(duì)訂單進(jìn)行退款,當(dāng)退款結(jié)果出來(lái)后,微信支付會(huì)通過(guò)POST的請(qǐng)求方式,向商戶預(yù)先設(shè)置的回調(diào)地址發(fā)送回調(diào)通知,讓商戶知曉這筆訂單的退款結(jié)果。
回調(diào)地址設(shè)置方式: 回調(diào)地址可以通過(guò)【申請(qǐng)退款A(yù)PI】接口中的“notify_url”參數(shù)設(shè)置,也可以在商戶平臺(tái)(交易中心>退款管理>退款配置)設(shè)置,優(yōu)先對(duì)接口設(shè)置的回調(diào)地址進(jìn)行回調(diào)。回調(diào)地址的設(shè)置規(guī)范和回調(diào)IP列表請(qǐng)參考文檔:回調(diào)通知注意事項(xiàng) (opens new window)。
# 二、回調(diào)處理步驟
# 1、商戶接收回調(diào)通知報(bào)文
微信支付會(huì)通過(guò)POST的方式向回調(diào)地址發(fā)送回調(diào)報(bào)文,回調(diào)報(bào)文的HTTP請(qǐng)求頭中會(huì)包含報(bào)文的簽名信息,用于后續(xù)驗(yàn)簽,具體如下:
參數(shù) | 描述 |
---|---|
Wechatpay-Serial | 驗(yàn)簽的“微信支付平臺(tái)證書(shū)”所對(duì)應(yīng)的平臺(tái)證書(shū)序列號(hào) |
Wechatpay-Signature | 驗(yàn)簽的簽名值 |
Wechatpay-Timestamp | 驗(yàn)簽的時(shí)間戳 |
Wechatpay-Nonce | 驗(yàn)簽的隨機(jī)字符串 |
回調(diào)通知的請(qǐng)求主體中會(huì)包含JSON格式的通知參數(shù),具體的通知參數(shù)列表如下:
# 通知參數(shù)
- id 必填 string(36)【通知ID】
回調(diào)通知的唯一編號(hào)。 - create_time 必填 string(32)【通知?jiǎng)?chuàng)建時(shí)間】
回調(diào)通知?jiǎng)?chuàng)建的時(shí)間,遵循rfc3339標(biāo)準(zhǔn)格式,格式為yyyy-MM-DDTHH:mm:ss+TIMEZONE,yyyy-MM-DD表示年月日,T出現(xiàn)在字符串中,HH:mm:ss表示時(shí)分秒,TIMEZONE表示時(shí)區(qū)(+08:00表示東八區(qū)時(shí)間,領(lǐng)先UTC 8小時(shí),即北京時(shí)間)。例如2015-05-20T13:29:35+08:00表示,北京時(shí)間2015年5月20日13點(diǎn)29分35秒。 - event_type 必填 string(32)【通知類型】通知的類型REFUND.SUCCESS:退款成功通知REFUND.ABNORMAL:退款異常通知,需商戶平臺(tái)手動(dòng)處理,參考交易退款方法介紹
REFUND.CLOSED:退款關(guān)閉通知。 - summary 必填 string(16)【回調(diào)摘要】
微信支付對(duì)回調(diào)內(nèi)容的摘要備注。 - resource_type 必填 string(32)【通知數(shù)據(jù)類型】
通知的資源數(shù)據(jù)類型,固定為encrypt-resource。 - resource 必填 object【通知資源數(shù)據(jù)】json格式,見(jiàn)示例
- 屬性
退款通知
1{2 "id":"EV-2018022511223320873",3 "create_time":"2018-06-08T10:34:56+08:00",4 "resource_type":"encrypt-resource",5 "event_type":"REFUND.SUCCESS",6 "summary":"退款成功",7 "resource" : {8 "original_type": "refund",9 "algorithm":"AEAD_AES_256_GCM",10 "ciphertext": "...",11 "associated_data": "",12 "nonce": "..."13 }14}
# 2、回調(diào)驗(yàn)簽與應(yīng)答
商戶接收到回調(diào)通知報(bào)文后,需在5秒內(nèi)完成對(duì)報(bào)文的驗(yàn)簽,并應(yīng)答回調(diào)通知。
# 2.1、對(duì)回調(diào)通知進(jìn)行驗(yàn)簽
驗(yàn)簽需使用請(qǐng)求頭中的【W(wǎng)echatpay-Timestamp】、【W(wǎng)echatpay-Nonce】以及請(qǐng)求主體中JSON格式的通知參數(shù)構(gòu)建出驗(yàn)簽串,然后使用【W(wǎng)echatpay-Serial】對(duì)應(yīng)的“微信支付平臺(tái)證書(shū) (opens new window)”對(duì)驗(yàn)簽串和【W(wǎng)echatpay-Signature】進(jìn)行驗(yàn)簽,確保接收的回調(diào)內(nèi)容是來(lái)自微信支付。
詳細(xì)驗(yàn)簽步驟請(qǐng)參考:非文件/圖片下載如何驗(yàn)證簽名 (opens new window)
微信支付會(huì)在極少數(shù)通知回調(diào)中返回以“WECHATPAY/SIGNTEST/”開(kāi)頭的錯(cuò)誤【W(wǎng)echatpay-Signature】,以檢測(cè)商戶系統(tǒng)是否正確驗(yàn)證簽名。商戶請(qǐng)參考:如何應(yīng)對(duì)簽名探測(cè)流量 (opens new window) 進(jìn)行處理。
# 2.2、對(duì)回調(diào)通知進(jìn)行應(yīng)答
商戶驗(yàn)簽后,根據(jù)驗(yàn)簽結(jié)果對(duì)回調(diào)進(jìn)行應(yīng)答:
驗(yàn)簽通過(guò):商戶需告知微信支付接收回調(diào)成功,HTTP應(yīng)答狀態(tài)碼需返回200或204,無(wú)需返回應(yīng)答報(bào)文。
驗(yàn)簽不通過(guò):商戶需告知微信支付接收回調(diào)失敗,HTTP應(yīng)答狀態(tài)碼需返回5XX或4XX,同時(shí)需返回以下應(yīng)答報(bào)文:
- code 必填 string(32)【返回狀態(tài)碼】
錯(cuò)誤碼,F(xiàn)AIL為回調(diào)接收失敗。 - message 選填 string(256)【返回信息】
返回信息,回調(diào)接收失敗原因。
應(yīng)答示例
1{ 2 "code": "FAIL",3 "message": "失敗"4}
微信支付接收到商戶的應(yīng)答后,會(huì)根據(jù)應(yīng)答結(jié)果做對(duì)應(yīng)的邏輯處理:
若商戶應(yīng)答回調(diào)接收成功,微信支付后續(xù)不再發(fā)送該回調(diào)內(nèi)容。若因網(wǎng)絡(luò)或其他原因,商戶收到了重復(fù)的回調(diào)通知,按正常業(yè)務(wù)流程應(yīng)答即可。
若商戶應(yīng)答回調(diào)接收失敗,或超時(shí)(5s)未應(yīng)答時(shí),微信支付會(huì)按照(15s/15s/30s/3m/10m/20m/30m/30m/30m/60m/3h/3h/3h/6h/6h)的頻次重復(fù)發(fā)送回調(diào)通知,最多發(fā)送15次。
# 3、對(duì)回調(diào)通知內(nèi)容進(jìn)行解密
為了保證業(yè)務(wù)信息的安全性,微信支付將業(yè)務(wù)信息進(jìn)行了AES-256-GCM加密,并通過(guò)參數(shù)resource將加密信息回調(diào)給商戶,商戶需要進(jìn)行解密后才能獲取到業(yè)務(wù)信息。
解密步驟如下:
- 獲取商戶平臺(tái)上設(shè)置的APIv3密鑰,記為key;
- 通過(guò)回調(diào)通知參數(shù)resource.algorithm確認(rèn)加密算法(目前僅支持AEAD_AES_256_GCM,算法的接口細(xì)節(jié),請(qǐng)參考:rfc5116 (opens new window))。
- 使用key與回調(diào)通知參數(shù)resource.nonce和resource.associated_data,對(duì)數(shù)據(jù)密文resource.ciphertext進(jìn)行解密,最終可得到JSON格式的業(yè)務(wù)信息。
解密示例代碼可參考文檔:如何解密回調(diào)報(bào)文 (opens new window)
注意
- 使用Java進(jìn)行回調(diào)解密,取JSON串內(nèi)的參數(shù)值時(shí),只需取引號(hào)內(nèi)的內(nèi)容進(jìn)行解密。例:"nonce":"123",只需取值123,不用取加上引號(hào)的"123"。
# resource解密后字段
- mchid 必填 string(32)【商戶號(hào)】調(diào)用支付分創(chuàng)單接口提交的商戶號(hào),商戶號(hào)需開(kāi)通支付分產(chǎn)品權(quán)限,且與appid有綁定關(guān)系,詳見(jiàn)直連商戶與AppID賬號(hào)關(guān)聯(lián)管理
。 - out_trade_no 必填 string(32)【商戶服務(wù)訂單號(hào)】 商戶系統(tǒng)內(nèi)部服務(wù)訂單號(hào),商戶在創(chuàng)建支付分接口中填入的out_order_no參數(shù),調(diào)用支付分查單接口時(shí)out_order_no字段和query_id字段必填一個(gè)(不允許都填寫(xiě)或都不填寫(xiě))。
- transaction_id 必填 string(32)【微信交易訂單號(hào)】 微信支付分扣款單的唯一標(biāo)識(shí),非0元結(jié)單且支付分渠道扣款成功后支付成功回調(diào)和查詢支付分訂單返回的收款信息明細(xì)collection.details中包含該字段。是微信支付下單后,產(chǎn)生的,微信支付內(nèi)部的原交易單號(hào)。
- out_refund_no 必填 string(64)【商戶訂單號(hào)】支付分輪詢扣款時(shí)生成的商戶訂單號(hào)。
- refund_id 必填 string(32)【微信支付退款號(hào)】 微信側(cè)返回的退款單唯一標(biāo)識(shí),由數(shù)字組成,50或52開(kāi)頭。
- refund_status 必填 string(32)【退款狀態(tài)】退款狀態(tài),枚舉值:SUCCESS:退款成功CLOSED:退款關(guān)閉ABNORMAL:退款異常,退款到銀行發(fā)現(xiàn)用戶的卡作廢或者凍結(jié)了,導(dǎo)致原路退款銀行卡失敗,可前往【商戶平臺(tái)
—>交易中心】,手動(dòng)處理此筆退款 - success_time 選填 string(64)【退款成功時(shí)間】
退款成功時(shí)間,退款狀態(tài)status為SUCCESS退款成功時(shí)返回該字段。遵循rfc3339標(biāo)準(zhǔn)格式,格式為yyyy-MM-DDTHH:mm:ss+TIMEZONE,yyyy-MM-DD表示年月日,T出現(xiàn)在字符串中,HH:mm:ss表示時(shí)分秒,TIMEZONE表示時(shí)區(qū)(+08:00表示東八區(qū)時(shí)間,領(lǐng)先UTC 8小時(shí),即北京時(shí)間)。例如2015-05-20T13:29:35+08:00表示,北京時(shí)間2015年5月20日13點(diǎn)29分35秒。 - user_received_account 必填 string(64)【退款入賬賬戶】退款單入賬方。
取值有以下幾種情況
退回銀行卡:{銀行名稱}{卡類型}{卡尾號(hào)}
退回支付用戶零錢:支付用戶零錢退還商戶:商戶基本賬戶商戶結(jié)算銀行賬戶
退回支付用戶零錢通:支付用戶零錢通
退回支付用戶銀行電子賬戶:支付用戶銀行電子賬戶
退回支付用戶零花錢:支付用戶零花錢
退回用戶經(jīng)營(yíng)賬戶:用戶經(jīng)營(yíng)賬戶
退回支付用戶來(lái)華零錢包:支付用戶來(lái)華零錢包
退回企業(yè)支付商戶:企業(yè)支付商戶 - amount 必填 object【金額信息】 訂單金額信息
- 屬性
對(duì)resource對(duì)象進(jìn)行解密后,得到的資源對(duì)象示例
1{2 "mchid": "1900000100",3 "transaction_id": "1008450740201411110005820873",4 "out_trade_no": "20150806125346",5 "refund_id": "50200207182018070300011301001",6 "out_refund_no": "7752501201407033233368018",7 "refund_status": "SUCCESS",8 "success_time": "2018-06-08T10:34:56+08:00",9 "user_received_account": "招商銀行信用卡0403",10 "amount" : {11 "total": 999,12 "refund": 999,13 "payer_total": 999,14 "payer_refund": 99915 }16}