return_url 和 notify_url 有什麼區別?為什麼不能用支付回跳判斷支付成功
買家付款後跳回你的頁面,不代表錢已經到賬。本文對比同步回跳 return_url 與異步通知 notify_url,列出回跳缺失、提前或被偽造的真實場景,並給出判斷支付成功的正確做法。
return_url 是給買家看的:付款結束後,把買家的瀏覽器帶回你的網站。notify_url(或 Webhook)是給你的服務器的:支付平台確認結果後,從服務端直接通知你。
判斷一筆訂單是否支付成功,只能依據驗簽通過的異步通知,或者你的服務端主動查詢訂單的結果,不能依據瀏覽器回跳。 這條規則在幾乎所有支付平台都成立,下面解釋為什麼。
return_url 與 notify_url 的區別
return_url(同步回跳) | notify_url / Webhook(異步通知) | |
|---|---|---|
| 誰發起 | 買家的瀏覽器 | 支付平台的服務器 |
| 什麼時候發生 | 買家在收銀台操作結束、瀏覽器跳回時 | 平台確認支付結果之後 |
| 一定會發生嗎 | 不一定:買家可能關掉頁面 | 會,失敗還會按計劃重試 |
| 能被偽造嗎 | 能:任何人都可以手動打開這個地址 | 不能:請求帶簽名,沒有密鑰無法偽造 |
| 用來做什麼 | 展示結果頁、引導下一步 | 改訂單狀態、發貨、開通服務 |
為什麼瀏覽器回跳不可靠?
買家付了錢,卻沒有回來
用錢包付款時,買家常常是在另一個應用裏完成授權的。授權成功後他可能直接關掉了瀏覽器,或者手機切到了別的應用,你的 return_url 永遠不會被訪問。如果你的系統只在回跳時更新訂單,這筆錢就成了「收了款卻沒發貨」。
回來了,但錢還沒有確定
需要 3D Secure 驗證的銀行卡、需要掃碼或跳轉授權的錢包,都有一段「買家已經操作、結果尚未最終確定」的時間。買家回到你的頁面時,這筆支付可能仍在處理中,甚至最終失敗。
回跳地址可以被手動打開
return_url 只是一個普通網址。如果你的回跳頁面看到 ?paid=1 之類的參數就認為支付成功,任何人複製這個地址在瀏覽器裏打開,都能「支付成功」。
同一筆訂單可能經歷多次支付嘗試
買家在收銀台先選了一種方式、沒完成,又換了另一種,一張訂單在付款過程中可能先後對應多筆渠道支付。以「某一次回跳」為準,很容易和最終真正成功的那一筆對不上。
判斷支付成功的正確做法
下單時帶上 notify_url,或配置 Webhook 端點
正式環境裏,訂單必須有地方接收結果通知:要麼每筆訂單傳公網 HTTPS 的 notify_url,要麼在控制台配置訂閲了 payment.succeeded 的 Webhook 端點,否則下單會被拒絕。見 統一下單。
把買家重定向到收銀台
使用接口返回的 checkout_url。
回跳頁面只展示狀態,不改訂單
買家回到 return_url 時,頁面向你自己的後端詢問訂單狀態:已支付就展示成功;還在處理中就展示「正在確認支付結果」並稍後刷新。後端讀的是你自己的訂單表,必要時調用 訂單查詢 向平台核實。
收到驗簽通過的通知後再履約
驗簽、按事件 id 去重、在同一個事務裏更新訂單並開通服務,然後返回 2xx。細節見 支付回調重複通知怎麼辦。
回跳頁面的後端查詢大致是這樣:
curl "https://api.kukopay.com/v1/orders/TRD_9F3A2C7E..." \
-H "X-Api-Key: $KUKOPAY_API_KEY"返回的 status 為 paid 時才表示支付成功並已入賬;pending 表示仍在等待。
不要讓前端直接帶着 API Key 去查訂單。密鑰只能放在服務端,前端只問你自己的後端。
如果通知遲遲沒來
通知延遲或者全部失敗時,你還有兩條補救路徑:
- 主動查單。 訂單在你那邊一直是待支付,但買家説已經付了款?用訂單查詢接口問一次平台。
- 從事件接口補回。 KukoPay 的每一個支付結果都會先記錄成事件,推送只是一次送達嘗試。接收端宕機期間錯過的事件,可以用 事件接口 按時間範圍拉回來。
平台這一側也有兜底:後台對賬任務會持續核對未決的支付和退款,即使渠道的通知丟了、買家又關了頁面,平台也會重新讀取渠道結果,補入賬、補通知或關閉訂單。
兩個容易忽略的細節
訂單關閉後才到達的付款會被自動退回。 極少數情況下,買家的付款在訂單已經被另一筆付款支付、或已經超時關閉之後才到達。KukoPay 會把這筆錢全額原路退回買家,發送 payment.duplicate_refunded 通知,不影響商戶餘額,也不需要你處理。
對賬請用訂單號,不要用 payment_id。 因為一張訂單可能先後對應多筆渠道支付,訂單對象上的 payment_id 會變化。請以 trade_no / out_trade_no 和 payment.succeeded 事件對賬。
總結
return_url負責體驗,notify_url/ Webhook 負責結果;- 回跳可能不發生、可能太早、可能被偽造;
- 履約只看驗簽後的通知或服務端查單;
- 回跳頁面只讀狀態、不改狀態。
想親手驗證這些場景,可以在沙箱裏用需要 3D Secure 的測試卡 4000 0000 0000 3220,或者選擇錢包支付後在測試授權頁直接關掉瀏覽器,看看訂單是否仍然入賬、通知是否照常到達。測試卡列表見 沙箱測試。
在沙箱裏把它跑通
註冊商戶後即可申請測試密鑰,不需要等待資質審核。