輕輕一掃,立刻扣款,付款碼背後的原理你不想知道嗎?|原創

樓下小黑哥發表於2020-04-16

前言

博文連結:https://sourl.cn/SsD3AM

最近由於業務需求,需要開發付款碼功能,該介面底層將會聚合市面上主流錢包 APP 的付款碼功能,如微信支付,支付寶支付。

ps:付款碼支付別稱有很多,如微信支付端支付產品為付款碼支付(之前的文件叫做刷卡支付),而支付寶端產品為當面付-條支付,而有些文件會成為二維碼被掃支付

下文統一使用微信的定義方式,統稱為付款碼支付。

可能有些同學對於付款碼支付這個聽起來很陌生,其實這個功能我們可能每天都在被使用。

像我們在便利店買個早飯,最後結賬時,使用支付寶/微信支付付款。收銀員會讓我們展示支付寶/微信付款碼,然後使用掃碼槍獲取此碼,最後上送給微信/支付寶服務端完成一次扣款。

以支付寶為例,具體使用者端支付流程如下:

來源自支付寶官網

付款碼支付後臺呼叫流程如下:

付款碼支付詳細版流程

微信/支付寶付款碼支付呼叫流程大同小異,官網寫的都比較清楚,這裡直接用支付寶的官網的流程。

img

從上面的流程可以看到,付款碼支付可以說是一個同步的介面,即介面同步返回扣款結果,無需通過另外非同步通知獲取結果。

不過這裡我們需要注意,由於涉及安全風控等問題,付款碼支付過程使用者端可能需要輸入密碼確認支付,此時付款碼介面將會返回等待使用者支付。

接入時務必這正確判斷返回資訊,若返回以下結果,代表此時使用者正在輸入密碼。

  • 微信支付: err_code=USERPAYING 或 err_code=SYSTEMERROR
  • 支付寶: code=10003 或 code=20000

微信付款碼支付在以下情況需要輸入密碼二次確認。

支付寶官方文件暫未找到相關規則,經過測試當支付金額大於 2000 ,需要輸入密碼。如果有熟悉其他驗密規則的同學,可以在評論區留言一下。

另外一點需要注意的是,微信/支付寶其他支付介面,支付成功之後,微信/支付寶服務端將會傳送訊息通知支付結果。但是付款碼不一樣,該介面是不會有訊息通知。

所以如果付款碼支付若返回等待使用者輸入密碼,商家後臺服務必須定時呼叫呼叫微信支付/支付寶查詢介面,獲取支付結果。

撤銷支付

如果在一段時間內比如 30s,輪詢查詢支付結果返回都是等待使用者支付,或者支付交易過程返回失敗或支付系統超時,這兩種情況官方文件都是建議立刻呼叫撤銷介面撤銷交易。

如果此訂單使用者支付失敗,撤銷介面將會訂單關閉;如果使用者支付成功,撤銷介面將會訂單資金退還給使用者。

也就是說撤銷支付介面功能上等同與關閉訂單加上退款。雖然撤銷也具有退款功能,但是兩者存在比較大的區別:

支付型別限制

微信/支付寶撤銷支付僅能撤銷付款碼支付型別的訂單,而退款可以支援多種支付型別的訂單。

退款金額

撤銷介面只能是全額退款,而退款介面支援傳入金額,可以全額退款,也可以部分退款。

時間限制

撤銷介面時間限制比較短,比如微信支付撤銷支援 7 天內的訂單,而支付寶撤銷介面僅支援當天的訂單。

但是退款介面可以支援較長時間訂單退款,比如微信支付退款支援一年內的訂單,而支付寶僅支援 3 個月內訂單。

基於以上區別,其他正常支付的單如需實現相同功能請呼叫退款介面,官方文件建議僅在異常的情況下才建議呼叫撤銷支付介面。

另外再說一點,有些地方這個功能介面稱為衝正介面,如下面工商二維碼支付。

0

實際上提供的功能與微信/支付寶撤銷類似,這裡需要各家支付公司提供文件具體研究。

撤銷支付相關問題

由於撤銷支付,可能導致退款,也可能關閉訂單,接入之前一直有些問題弄不清楚,在官方文件處也沒有查詢到任何資料,沒辦法只好實測驗證相關問題。

由於規定,支付機構不能直連微信/支付寶,所以以下測試基於銀聯微信/支付寶通道。

銀聯提供的介面與直連微信/支付寶存在些許差別,但是主要功能一樣。

重複撤銷

通過實測,微信/支付寶撤銷介面冪等實現,重複撤銷返回結果一致。

不過需要注意需要正確判斷撤銷的返回結果。

比如微信撤銷介面成功判斷還需要結合 recall 欄位,支付寶也有類似欄位。

訂單狀態

微信/支付寶訂單狀態處理不太一致,微信訂單狀態比較複雜:

微信支付訂單狀態機

也就是說,付款碼訂單一旦被撤銷成功,再次查詢訂單,狀態將會返回為已撤銷(REVOKED)

另外微信對於付款碼支付訂單有限制,是無法呼叫關閉訂單介面關閉訂單,所以在付款碼的場景中,是不存在訂單狀態為 CLOSED—已關閉

接下來說下支付寶的狀態,支付寶文件沒要給出類似的訂單狀態機,我根據官方一些文件,以及一些測試結果總結出下方訂單狀態圖。

所以支付寶的付款碼訂單一旦撤銷成功,再次查詢原單狀態將會返回 TRADE_CLOSED

對賬檔案資料

當天產生交易之後,次日我們需要拉取微信/支付寶對賬檔案,逐一核對資料,防止少賬,多賬問題。

對賬設計流程可以參考之前寫過的文章:

聊聊對賬系統的設計方案

微信/支付寶對賬檔案只會記錄交易成功的訂單,所以未支付的訂單被撤銷是不會出現在對賬檔案中。但是如果支付成功了,然後又被撤銷成功,將會在對賬檔案中產生兩筆記錄,一筆正交易,一筆反向退款記錄。

正交易與普通的退款的記錄都比較好識別,一般可以使用我們上送給微信支付寶訂單號。但是撤銷導致退款記錄,我們無法僅用一個單號識別,我們需要結合另外的欄位區分判斷。

微信對賬檔案撤銷產生那筆退款,交易狀態為 REVOKED,所以我們可以採用商戶訂單號加交易狀態識別出一條記錄是否為撤銷產生退款記錄。

上面銀聯訂單號可以當做是微信支付寶內部產生訂單號

支付寶對賬檔案比較麻煩,撤銷產生的退款記錄不能跟微信根據交易狀態區分。從對賬檔案上看支付寶撤銷產生退款與普通退款介面產生退款記錄是一樣的。

仔細研究對賬檔案可以發現一些區別,撤銷導致退款記錄退款批次與正交易支付寶內部訂單號是一致的。而正常退款記錄,退款批次號是由商戶自己上送的。所以我們可以以此篩選出撤銷產生的退款記錄。

撤銷失敗

極端情況下,有可能產生多次撤銷都失敗的奇葩情況,那怎麼辦?

這種情況下就不用往系統自動處理方向考慮了,通過線下人工介入處理吧,畢竟這種概率太低了。引用知乎@天順的文章中一句話:

很多時候人工保障比你動腦筋想異常中的異常如何系統自動處理來得反而高效和低成本

這句話大家仔細品,越品越有道理!

Reference

非同步通知如何判斷對應哪筆退款交易

對賬與退款

撤銷介面retry_flag欄位說明

退款介面、關閉介面和撤銷介面的區別

最後說一句(求點贊)

付款碼支付接入其實比較簡單,主要難點在於撤銷介面引入之後對於現有的系統的改造,比如撤銷成功的訂單之後,是直接修改原單的成功狀態到撤銷狀態,還是說再建立一條撤銷記錄?還有對賬系統核對時,對端記錄可能比本端多,如何核對?這些問題大家在接入之後一定結合現有系統好好思考一下。

最後,文章難免存在一些疏漏,大家如果發現,可以在評論區留言指出,謝謝支援。

如果你也在從事支付,或者正在對接支付,歡迎加我微信,一起討論問題,一起成長~

歡迎關注我的公眾號:程式通事,獲得日常乾貨推送。如果您對我的專題內容感興趣,也可以關注我的部落格:studyidea.cn

相關文章