如何設(shè)置異步通知地址
不同接口接收異步通知設(shè)置方式不同,可查看 哪些接口支持觸發(fā)異步。
設(shè)置 notify_url 接收異步
對于支付產(chǎn)生的交易,支付寶會根據(jù)原始支付 API 中傳入的異步通知地址 notify_url,通過 POST 請求的形式將支付結(jié)果作為參數(shù)通知到商家系統(tǒng),接口調(diào)用 SDK 設(shè)置 notify_url 傳參方式如下。
Alipay SDK(老版)
//Java版:
request.setNotifyUrl("商家自己的notify_url地址");
//PHP版:
$request->setNotifyUrl("商家自己的notify_url地址");
//.net版:
request.SetNotifyUrl("商家自己的notify_url地址");
//python版本:
request.notify_url="商家自己的notify_url地址"
//node.js版:
formData.addField('notifyUrl', '商家自己的notify_url地址');
Alipay Easy SDK(新版)
目前 Alipay Easy SDK 只支持 Java、PHP、.Net 語言,因此只有該 3 種語言有設(shè)置 notify_url 方式。
//Java版:
Factory.Payment.FaceToFace() // 調(diào)用asyncNotify擴(kuò)展方法,可以為每次API調(diào)用,設(shè)置獨(dú)立的異步商家自己的notify_url地址");
//PHP版:
Factory::payment()->FaceToFace() // 調(diào)用asyncNotify擴(kuò)展方法,可以為每次API調(diào)用,設(shè)置獨(dú)立的異步通知地址 // 此處設(shè)置的異步通知地址的優(yōu)先級高于全局Config中配置的異步通知地址 ->asyncNotify("商家自己的notify_url地址");
//.net版:
Factory.Payment.FaceToFace() // 調(diào)用AsyncNotify擴(kuò)展方法,可以為每此API調(diào)用,設(shè)置獨(dú)立的異步通知地址 // 此處設(shè)置的異步通知地址的優(yōu)先級高于全局Config中配置的異步通知地址 .AsyncNotify("商加自己的notify_url地址");
From 螞蟻訂閱接收異步
生活號、口碑、現(xiàn)金紅包、單筆轉(zhuǎn)賬接口等異步通知發(fā)送到對應(yīng) APPID 應(yīng)用的應(yīng)用網(wǎng)關(guān)中,通過 POST 請求的形式將支付結(jié)果作為參數(shù)通知到商家系統(tǒng)。
如何接收可查看各產(chǎn)品文檔上的異步說明。
異步通知返回參數(shù)介紹
支付寶查看支付寶開放平臺文檔中各接口的異步通知參數(shù)的詳細(xì)說明。
以 App 支付為例,返回的異步通知參數(shù)如下(以下示例報(bào)文僅供參考,實(shí)際返回的詳細(xì)報(bào)文請以實(shí)際返回為準(zhǔn))。
total_amount=2.00&buyer_id=20****7&body=大樂透2.1&trade_no=2016071921001003030200089909&refund_fee=0.00?ify_time=2016-07-19 14:10:49&subject=大樂透2.1&sign_type=RSA2&charset=utf-8?ify_type=trade_status_sync&out_trade_no=0719141034-6418&gmt_close=2016-07-19 14:10:46&gmt_payment=2016-07-19 14:10:47&trade_status=TRADE_SUCCESS&version=1.0&sign=kPbQIjX+xQc8F0/A6/AocELIjhhZnGbcBN6G4MM/HmfWL4ZiHM6fWl5NQhzXJusaklZ1LFuMo+lHQUELAYeugH8LYFvxnNajOvZhuxNFbN2LhF0l/KL8ANtj8oyPM4NN7Qft2kWJTDJUpQOzCzNnV9hDxh5AaT9FPqRS6ZKxnzM=&gmt_create=2016-07-19 14:10:44&app_id=20151*****3&seller_id=20881021****8?ify_id=4a91b7a78a503640467525113fb7d8bg8e
異步通知驗(yàn)簽
驗(yàn)簽流程
為了幫助開發(fā)者調(diào)用開放接口,支付寶提供了 開放平臺服務(wù)端 SDK 和 demo,包含 Java、PHP 和 .NET 等語言版本,封裝了簽名&驗(yàn)簽、HTTP 接口請求等基礎(chǔ)功能。為了避免驗(yàn)簽出錯(cuò)強(qiáng)烈建議先下載對應(yīng)語言版本的 SDK 并引入您的開發(fā)工程進(jìn)行快速接入。
驗(yàn)簽步驟
- 在通知返回參數(shù)列表中,除去 sign、sign_type 兩個(gè)參數(shù)外,凡是通知返回回來的參數(shù)皆是待驗(yàn)簽的參數(shù)。將剩下參數(shù)進(jìn)行 url_decode,然后進(jìn)行字典排序,組成字符串,得到待簽名字符串;
生活號異步通知組成的待驗(yàn)簽串里需要保留 sign_type 參數(shù)。 - 將簽名參數(shù)(sign)使用 base64 解碼為字節(jié)碼串;
- 使用 RSA 的驗(yàn)簽方法,通過簽名字符串、簽名參數(shù)(經(jīng)過 base64 解碼)及支付寶公鑰驗(yàn)證簽名。
- 驗(yàn)證簽名正確后,必須再嚴(yán)格按照如下描述校驗(yàn)通知數(shù)據(jù)的正確性。
在上述驗(yàn)證通過后,商家必須根據(jù)支付寶不同類型的業(yè)務(wù)通知,正確的進(jìn)行不同的業(yè)務(wù)處理,并且過濾重復(fù)的通知結(jié)果數(shù)據(jù)。
注意:
- 在支付寶的業(yè)務(wù)通知中,只有交易通知狀態(tài)為 TRADE_SUCCESS 或 TRADE_FINISHED 時(shí),支付寶才會認(rèn)定為買家付款成功。
- 如果簽約的產(chǎn)品支持退款,并且對應(yīng)的產(chǎn)品默認(rèn)支持能收到 TRADE_SUCCESS 或 TRADE_FINISHED 狀態(tài),該筆交易會先收到 TRADE_SUCCESS 交易狀態(tài),然后默認(rèn)12個(gè)月該筆交易會再次收到 TRADE_FINISHED 狀態(tài)。實(shí)際該筆交易只支付了一次,切勿認(rèn)為該筆交易支付兩次。
接口響應(yīng)
收到異步通知后,商家輸出 success 表示消息獲取成功,支付寶就會停止發(fā)送異步,如果輸出 fail,表示消息獲取失敗,支付寶會重新發(fā)送消息到異步地址。
建議在接收異步進(jìn)行驗(yàn)簽,如果驗(yàn)簽成功輸出 success,驗(yàn)簽失敗返回 fail,重新接收異步進(jìn)行處理。
響應(yīng)值 | 描述 | 是否重試 |
fail | 消息獲取失敗 | 重試 |
success | 消息獲取成功 | 不重試 |
異步通知交易狀態(tài)介紹
目前支付產(chǎn)品的交易狀態(tài)大致分以下4種:
- WAIT_BUYER_PAY:交易創(chuàng)建,等待買家付款。
- TRADE_CLOSED:在指定時(shí)間段內(nèi)未支付時(shí)關(guān)閉的交易或在交易完成全額退款成功時(shí)關(guān)閉的交易。
- TRADE_SUCCESS:商家簽約的產(chǎn)品支持退款功能的前提下,買家付款成功。
- TRADE_FINISHED:商家簽約的產(chǎn)品不支持退款功能的前提下,買家付款成功。或者,商家簽約的產(chǎn)品支持退款功能的前提下,交易已經(jīng)成功并且已經(jīng)超過可退款期限。
無法接收異步通知如何處理
收不到回調(diào)原因
- 異步通知發(fā)送地址錯(cuò)誤。notify_url、授權(quán)回調(diào)地址、應(yīng)用網(wǎng)關(guān)地址弄混了。
- 異步地址無法公網(wǎng)訪問。
- 異步地址設(shè)置方式錯(cuò)誤。notify_url 傳參,F(xiàn)rom 螞蟻消息設(shè)置地址方式。
- 接口默認(rèn)不觸發(fā)相關(guān)的狀態(tài)數(shù)據(jù)通知。
- 其實(shí)已經(jīng)收到(其實(shí)是驗(yàn)簽失敗返回為空),但是沒有做日志記錄或者沒有記錄到通知。
核實(shí)異步地址是否正常
- 可通過目前提供的 云排查日志 查詢對應(yīng)交易的異步回調(diào)數(shù)據(jù)內(nèi)容。
- 模擬 post 方式把云排查日志查詢到的數(shù)據(jù)發(fā)送到接收異步回調(diào)頁面,看異步頁面能否正常接收到 post 發(fā)送過來的數(shù)據(jù)。
- 根據(jù)設(shè)置異步方式不同,可參考:
- 通過設(shè)置 notify_url 接收異步,詳情可查看 收不到 notify_url 異步。
- 通過 From 螞蟻訂閱接收異步,詳情可查看 收不到 From 螞蟻消息。
為什么重復(fù)收到異步通知
重復(fù)收到異步通知主要是由于未返回 success 或異步通知不是同一個(gè)觸發(fā)條件導(dǎo)致。
未返回 success
每當(dāng)交易狀態(tài)改變時(shí),服務(wù)器異步通知頁面就會收到支付寶發(fā)來的處理結(jié)果通知,程序執(zhí)行完后必須打印輸出 success,可通過 云排查 查詢是否返回支付寶 success。
如果商家反饋給支付寶的字符不是 success 這 7 個(gè)字符,支付寶服務(wù)器會不斷重發(fā)通知,直到超過 24 小時(shí) 22 分鐘。一般情況下,25 小時(shí)以內(nèi)完成 8 次通知(通知的間隔頻率一般是:4m、10m、1h、2h、6h、15h)。
返回 success 示例代碼
以下僅展示 Java、PHP、.NET 語言的示例,其它開發(fā)語言也是直接輸出 success 即可。
JAVA
out.print("success");
PHP
echo "success";
.NET
Response.Write("success");
直接訪問你的異步頁面應(yīng)該是輸出(如下圖)中的 success 這 7 個(gè)字符。
注意:瀏覽器上點(diǎn)擊查看頁面源代碼,看到的是這個(gè) 7 個(gè)字符,有空格或者其它字符都會導(dǎo)致重復(fù)收到通知(建議大家做一下簡單的驗(yàn)證)。
特別注意:返回的是純文本內(nèi)容,不要包含 html 等標(biāo)簽。
異步通知不是同一個(gè)觸發(fā)條件
若在已經(jīng)返回 success 后還會收到支付寶異步回調(diào),請檢查通知內(nèi)容中的觸發(fā)條件是否是相同的。
如支付產(chǎn)品在交易狀態(tài)發(fā)生改變后,不同交易狀態(tài)也可能會觸發(fā)異步。
案例:若退款期限是 12 個(gè)月可退款,支付成功后,支付寶會發(fā)送 trade_success 的支付成功狀態(tài)的異步通知,在 12 個(gè)月后支付寶會再次發(fā)送 trade_finished 的交易結(jié)束狀態(tài)的異步通知,表示交易結(jié)束不允許退款。
注意:TRADE_SUCCESS 觸發(fā)的異步停止后,可能受異步觸發(fā)條件影響,TRADE_CLOSED 或者 TRADE_FINISHED 也會觸發(fā)異步。
異步通知的特性
- 必須保證服務(wù)器異步通知頁面(notify_url)上無任何字符,如空格、HTML 標(biāo)簽、開發(fā)系統(tǒng)自帶拋出的異常提示信息等。
- 支付寶是用 POST 方式發(fā)送通知信息,因此該頁面中獲取參數(shù)的方式,如:request.Form(out_trade_no)、$_POST[out_trade_no]。
- 支付寶主動發(fā)起通知,該方式才會被啟用。
- 只有在支付寶的交易管理中存在該筆交易,且發(fā)生了交易狀態(tài)的改變,支付寶才會通過該方式發(fā)起服務(wù)器通知(即時(shí)到賬交易狀態(tài)為 等待買家付款 的狀態(tài)默認(rèn)是不會發(fā)送通知的)。
- 該方式的調(diào)試與運(yùn)行必須在服務(wù)器上,即互聯(lián)網(wǎng)上能訪問。而且服務(wù)器間的交互不像頁面跳轉(zhuǎn)同步通知可以在頁面上顯示出來,這種交互方式是不可見的。
- 第一次交易狀態(tài)改變(即時(shí)到賬中此時(shí)交易狀態(tài)是交易完成)時(shí),不僅會返回同步處理結(jié)果,而且服務(wù)器異步通知頁面也會收到支付寶發(fā)來的處理結(jié)果通知。
- 程序執(zhí)行完后必須打印輸出 success。如果商家反饋給支付寶的字符不是 success 這 7 個(gè)字符,支付寶服務(wù)器會不斷重發(fā)通知,直到超過 24 小時(shí) 22 分鐘。一般情況下,25 小時(shí)以內(nèi)完成 8 次通知(通知的間隔頻率一般是:4m,10m,10m,1h,2h,6h,15h) 。
- 程序執(zhí)行完成后,該頁面不能執(zhí)行頁面跳轉(zhuǎn)。如果執(zhí)行頁面跳轉(zhuǎn),支付寶會收不到 success 字符,會被支付寶服務(wù)器判定為該頁面程序運(yùn)行出現(xiàn)異常,而重發(fā)處理結(jié)果通知。
- cookies、session 等在此頁面會失效,即無法獲取這些數(shù)據(jù)。
- 該方式的作用主要防止訂單丟失,即頁面跳轉(zhuǎn)同步通知沒有處理訂單更新,它則去處理。
- 當(dāng)商家收到服務(wù)器異步通知并打印出 success 時(shí),服務(wù)器異步通知參數(shù) notify_id 才會失效。也就是說在支付寶發(fā)送同一條異步通知時(shí)(包含商家并未成功打印出 success 導(dǎo)致支付寶重發(fā)數(shù)次通知),服務(wù)器異步通知參數(shù) notify_id 是不變的。
- 異步通知 header 是 Content-Type:application/x-www-form-urlencoded; text/html; charset=utf-8 ,不是按照 RFC2183 RFC1521 標(biāo)準(zhǔn)來的。