“輕輕一掃,立刻扣款”,解讀付款碼背后的原理

1 評(píng)論 8686 瀏覽 54 收藏 13 分鐘

生活中,我們?cè)絹?lái)越多地使用付款碼進(jìn)行支付,而付款碼看起來(lái)“平平無(wú)奇”,背后的產(chǎn)品設(shè)計(jì)還是大有門道的。因此本文就來(lái)揭曉付款碼的原理是什么?

前言

最近由于業(yè)務(wù)需求,需要開發(fā)付款碼功能,該接口底層將會(huì)聚合市面上主流錢包 APP 的付款碼功能,如微信支付、支付寶支付。

ps:付款碼支付別稱有很多,如微信支付端支付產(chǎn)品為付款碼支付(之前的文檔叫做刷卡支付),而支付寶端產(chǎn)品為當(dāng)面付-條支付,而有些文檔會(huì)稱為二維碼被掃支付。

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

可能有些同學(xué)對(duì)于付款碼支付這個(gè)聽起來(lái)很陌生,其實(shí)這個(gè)功能我們可能每天都在被使用。

像我們?cè)诒憷曩I個(gè)早飯,最后結(jié)賬時(shí),使用支付寶/微信支付付款。收銀員會(huì)讓我們展示支付寶/微信付款碼,然后使用掃碼槍獲取此碼,最后上送給微信/支付寶服務(wù)端完成一次扣款。

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

來(lái)源自支付寶官網(wǎng)

付款碼支付后臺(tái)調(diào)用流程如下:

01 付款碼支付詳細(xì)版流程

微信/支付寶付款碼支付調(diào)用流程大同小異,官網(wǎng)寫的都比較清楚,這里直接用支付寶的官網(wǎng)的流程。

從上面的流程可以看到,付款碼支付可以說(shuō)是一個(gè)同步的接口,即接口同步返回扣款結(jié)果,無(wú)需通過(guò)另外異步通知獲取結(jié)果。

不過(guò)這里我們需要注意,由于涉及安全風(fēng)控等問(wèn)題,付款碼支付過(guò)程用戶端可能需要輸入密碼確認(rèn)支付,此時(shí)付款碼接口將會(huì)返回等待用戶支付。

接入時(shí)務(wù)必這正確判斷返回信息,若返回以下結(jié)果,代表此時(shí)用戶正在輸入密碼。

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

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

支付寶官方文檔暫未找到相關(guān)規(guī)則,經(jīng)過(guò)測(cè)試當(dāng)支付金額大于 2000 ,需要輸入密碼。如果有熟悉其他驗(yàn)密規(guī)則的同學(xué),可以在評(píng)論區(qū)留言一下。

另外一點(diǎn)需要注意的是,微信/支付寶其他支付接口,支付成功之后,微信/支付寶服務(wù)端將會(huì)發(fā)送消息通知支付結(jié)果。但是付款碼不一樣,該接口是不會(huì)有消息通知。

所以如果付款碼支付若返回等待用戶輸入密碼,商家后臺(tái)服務(wù)必須定時(shí)調(diào)用調(diào)用微信支付/支付寶查詢接口,獲取支付結(jié)果。

02 撤銷支付

如果在一段時(shí)間內(nèi)比如 30s,輪詢查詢支付結(jié)果返回都是等待用戶支付,或者支付交易過(guò)程返回失敗或支付系統(tǒng)超時(shí),這兩種情況官方文檔都是建議立刻調(diào)用撤銷接口撤銷交易。

如果此訂單用戶支付失敗,撤銷接口將會(huì)訂單關(guān)閉;如果用戶支付成功,撤銷接口將會(huì)訂單資金退還給用戶。

也就是說(shuō)撤銷支付接口功能上等同與關(guān)閉訂單加上退款。雖然撤銷也具有退款功能,但是兩者存在比較大的區(qū)別:

支付類型限制:微信/支付寶撤銷支付僅能撤銷付款碼支付類型的訂單,而退款可以支持多種支付類型的訂單。

退款金額:撤銷接口只能是全額退款,而退款接口支持傳入金額,可以全額退款,也可以部分退款。

時(shí)間限制:

撤銷接口時(shí)間限制比較短,比如微信支付撤銷支持 7 天內(nèi)的訂單,而支付寶撤銷接口僅支持當(dāng)天的訂單。

但是退款接口可以支持較長(zhǎng)時(shí)間訂單退款,比如微信支付退款支持一年內(nèi)的訂單,而支付寶僅支持 3 個(gè)月內(nèi)訂單。

基于以上區(qū)別,其他正常支付的單如需實(shí)現(xiàn)相同功能請(qǐng)調(diào)用退款接口,官方文檔建議僅在異常的情況下才建議調(diào)用撤銷支付接口。

另外再說(shuō)一點(diǎn),有些地方這個(gè)功能接口稱為沖正接口,如下面工商二維碼支付。

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

03 撤銷支付相關(guān)問(wèn)題

由于撤銷支付,可能導(dǎo)致退款,也可能關(guān)閉訂單,接入之前一直有些問(wèn)題弄不清楚,在官方文檔處也沒有查詢到任何資料,沒辦法只好實(shí)測(cè)驗(yàn)證相關(guān)問(wèn)題。

由于規(guī)定,支付機(jī)構(gòu)不能直連微信/支付寶,所以以下測(cè)試基于銀聯(lián)微信/支付寶通道。

銀聯(lián)提供的接口與直連微信/支付寶存在些許差別,但是主要功能一樣。

1. 重復(fù)撤銷

通過(guò)實(shí)測(cè),微信/支付寶撤銷接口冪等實(shí)現(xiàn),重復(fù)撤銷返回結(jié)果一致。

不過(guò)需要注意需要正確判斷撤銷的返回結(jié)果。

比如微信撤銷接口成功判斷還需要結(jié)合 recall 字段,支付寶也有類似字段。

2. 訂單狀態(tài)

微信/支付寶訂單狀態(tài)處理不太一致,微信訂單狀態(tài)比較復(fù)雜:

微信支付訂單狀態(tài)機(jī)

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

另外微信對(duì)于付款碼支付訂單有限制,是無(wú)法調(diào)用關(guān)閉訂單接口關(guān)閉訂單,所以在付款碼的場(chǎng)景中,是不存在訂單狀態(tài)為 CLOSED—已關(guān)閉。

接下來(lái)說(shuō)下支付寶的狀態(tài),支付寶文檔沒要給出類似的訂單狀態(tài)機(jī),我根據(jù)官方一些文檔,以及一些測(cè)試結(jié)果總結(jié)出下方訂單狀態(tài)圖。

所以支付寶的付款碼訂單一旦撤銷成功,再次查詢?cè)瓎螤顟B(tài)將會(huì)返回 TRADE_CLOSED

3. 對(duì)賬文件數(shù)據(jù)

當(dāng)天產(chǎn)生交易之后,次日我們需要拉取微信/支付寶對(duì)賬文件,逐一核對(duì)數(shù)據(jù),防止少賬,多賬問(wèn)題。

對(duì)賬設(shè)計(jì)流程可以參考之前寫過(guò)的文章:《聊聊對(duì)賬系統(tǒng)的設(shè)計(jì)方案》

微信/支付寶對(duì)賬文件只會(huì)記錄交易成功的訂單,所以未支付的訂單被撤銷是不會(huì)出現(xiàn)在對(duì)賬文件中。但是如果支付成功了,然后又被撤銷成功,將會(huì)在對(duì)賬文件中產(chǎn)生兩筆記錄,一筆正交易,一筆反向退款記錄。

正交易與普通的退款的記錄都比較好識(shí)別,一般可以使用我們上送給微信支付寶訂單號(hào)。但是撤銷導(dǎo)致退款記錄,我們無(wú)法僅用一個(gè)單號(hào)識(shí)別,我們需要結(jié)合另外的字段區(qū)分判斷。

微信對(duì)賬文件撤銷產(chǎn)生那筆退款,交易狀態(tài)為 REVOKED,所以我們可以采用商戶訂單號(hào)加交易狀態(tài)識(shí)別出一條記錄是否為撤銷產(chǎn)生退款記錄。

上面銀聯(lián)訂單號(hào)可以當(dāng)做是微信支付寶內(nèi)部產(chǎn)生訂單號(hào)

支付寶對(duì)賬文件比較麻煩,撤銷產(chǎn)生的退款記錄不能跟微信根據(jù)交易狀態(tài)區(qū)分。從對(duì)賬文件上看支付寶撤銷產(chǎn)生退款與普通退款接口產(chǎn)生退款記錄是一樣的。

仔細(xì)研究對(duì)賬文件可以發(fā)現(xiàn)一些區(qū)別,撤銷導(dǎo)致退款記錄退款批次與正交易支付寶內(nèi)部訂單號(hào)是一致的。而正常退款記錄,退款批次號(hào)是由商戶自己上送的。所以我們可以以此篩選出撤銷產(chǎn)生的退款記錄。

4. 撤銷失敗

極端情況下,有可能產(chǎn)生多次撤銷都失敗的奇葩情況,那怎么辦?

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

很多時(shí)候人工保障比你動(dòng)腦筋想異常中的異常如何系統(tǒng)自動(dòng)處理來(lái)得反而高效和低成本

這句話大家仔細(xì)品,越品越有道理!

Reference

異步通知如何判斷對(duì)應(yīng)哪筆退款交易

對(duì)賬與退款

撤銷接口retry_flag字段說(shuō)明

退款接口、關(guān)閉接口和撤銷接口的區(qū)別

最后

付款碼支付接入其實(shí)比較簡(jiǎn)單,主要難點(diǎn)在于撤銷接口引入之后對(duì)于現(xiàn)有的系統(tǒng)的改造,比如撤銷成功的訂單之后,是直接修改原單的成功狀態(tài)到撤銷狀態(tài),還是說(shuō)再創(chuàng)建一條撤銷記錄?還有對(duì)賬系統(tǒng)核對(duì)時(shí),對(duì)端記錄可能比本端多,如何核對(duì)?這些問(wèn)題大家在接入之后一定結(jié)合現(xiàn)有系統(tǒng)好好思考一下。

最后,文章難免存在一些疏漏,大家如果發(fā)現(xiàn),可以在評(píng)論區(qū)留言指出,謝謝支持。

如果你也在從事支付,或者正在對(duì)接支付,歡迎加我微信,一起討論問(wèn)題,一起成長(zhǎng)~

 

作者:樓下小黑哥;微信公號(hào)@程序通事,支付行業(yè),后端技術(shù)

本文由 @樓下小黑哥 原創(chuàng)發(fā)布于人人都是產(chǎn)品經(jīng)理。未經(jīng)許可,禁止轉(zhuǎn)載

題圖來(lái)自Unsplash,基于CC0協(xié)議

更多精彩內(nèi)容,請(qǐng)關(guān)注人人都是產(chǎn)品經(jīng)理微信公眾號(hào)或下載App
評(píng)論
評(píng)論請(qǐng)登錄
  1. 個(gè)人覺得撤銷退款記錄可以對(duì)原訂單進(jìn)行標(biāo)識(shí),但需要?jiǎng)?chuàng)建一天新的記錄

    回復(fù)