<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          如何防止訂單重復(fù)支付?

          共 3403字,需瀏覽 7分鐘

           ·

          2022-07-12 21:48

          Hollis的新書限時折扣中,一本深入講解Java基礎(chǔ)的干貨筆記!

          我們來看看,電商訂單支付的簡要流程:

          訂單錢包支付流程

          從下單/計算開始:

          1. 下單/結(jié)算:這一步雖然不是直接的支付起點,但是支付相關(guān)的金額等等信息都來自結(jié)算,此時訂單的狀態(tài)是未支付

          2. 申請支付:用戶選擇申請支付,客戶端調(diào)用支付服務(wù),此時在系統(tǒng)內(nèi)產(chǎn)生一筆支付流水,這筆流水的狀態(tài)是未支付

          3. 發(fā)起支付:支付服務(wù)調(diào)用三方支付,通常這種錢包類的支付,在發(fā)起支付這一步,會響應(yīng)一些支付的鏈接,客戶端會對鏈接進(jìn)行對應(yīng)的處理。

          4. 錢包支付:用戶進(jìn)行支付,通常是通過對應(yīng)的錢包進(jìn)行的,大家可以回憶一下自己在購物中,支付的過程,不同的端,對錢包支付的處理是不太一樣的:

            京東PC端支付頁
            • APP端: 在國內(nèi),購物大部分都是在APP端,產(chǎn)品經(jīng)理會想法設(shè)法把用戶帶到APP,為什么我的示例圖都用京東,不用淘寶呢?因為我拿UC打開淘寶,會直接跳轉(zhuǎn)APP。

              APP端的錢包支付,我們應(yīng)該都非常熟悉,一般是拉起錢包,支付。

              APP支付
            • WAP端:手機的網(wǎng)頁站,WAP端的支付一般是直接拉起對應(yīng)的錢包,如果拉起錢包失敗,就跳轉(zhuǎn)界面

              京東支付WAP端
            • PC端:PC端,通常是打開收銀臺,展示一個二維碼,通過錢包掃碼支付,下面是京東的微信支付掃碼頁
          5. 支付回調(diào):用戶完成支付后,三方支付平臺,會回調(diào)商戶,通知支付結(jié)果。

          6. 同步訂單狀態(tài):支付服務(wù)在確認(rèn)支付完成后,會向訂單服務(wù)同步支付的結(jié)果,訂單服務(wù)變更訂單的狀態(tài),由未支付-》待發(fā)貨,客戶端通過輪詢、長連接,或者服務(wù)端主動推送的方式,在界面上變更訂單狀態(tài)。

          我們再從支付流水的角度看一下支付狀態(tài)的變化:

          支付狀態(tài)變化
          • 從未支付,到有支付結(jié)果的終態(tài),中間還有一個中間狀態(tài)支付中
          • 用戶通過打開錢包--》完成支付--》支付回調(diào),這段時間的支付流水就處于支付中

          為什么要花這么多篇幅來講支付的業(yè)務(wù)流程、交互過程呢?因為我認(rèn)為,防止訂單的重復(fù)支付,不止是技術(shù)上的問題,也是業(yè)務(wù)和產(chǎn)品上的問題。

          為什么訂單會重復(fù)支付

          未防重導(dǎo)致的重復(fù)支付

          我們可以看到PC端支付,是掃描二維碼,這些二維碼,就是對應(yīng)相應(yīng)的支付流水,假如用戶重復(fù)點擊支付,如果不做防重的的話,會生成兩筆支付流水,也就是兩個不同的二維碼,要是用戶分別掃了兩個不同的支付碼,那么毫無疑問,就會產(chǎn)生重復(fù)支付。

          掉單導(dǎo)致的重復(fù)支付

          “我明明付款了,為什么我的訂單還沒支付呢?”

          黑我錢是吧

          這就是所謂的“掉單”:

          • 外部掉單:三方支付的支付狀態(tài)沒有同步或者沒有及時同步到商城,這叫外部掉單
          • 內(nèi)部掉單:支付服務(wù)的狀態(tài)沒有同步到訂單,或者客戶端沒有及時獲取到訂單狀態(tài),這叫內(nèi)部掉單。

          用戶一看,自己付了款,結(jié)果商城里訂單還未付款,但是又特別想要,可能就會再下一單,這樣就重復(fù)支付了。

          多渠道導(dǎo)致的重復(fù)支付

          我們國內(nèi)支付的體驗還是非常快捷的,大家可能沒有感覺,如果了解過海外支付的可能了解,很多支付的渠道,消耗的時間非常長。

          比如用戶保羅選擇了一種支付方式Boleto,結(jié)果支付的網(wǎng)點離保羅他們村太遠(yuǎn)了,保羅又選擇了Paypal支付,保羅去趕集的時候,又順手去網(wǎng)點把Boleto的這一筆支付了,結(jié)果就重復(fù)支付了。

          這種情況大家可能很少遇到,我們可以用美團(tuán)下一個單,先打開微信支付,不要支付啊,接著回到美團(tuán),打開支付寶,用支付寶支付完成后,用微信接著支付,大家猜猜,兩筆支付是不是都能成功?答案是可以。

          美團(tuán)多渠道支付

          如何防止訂單重復(fù)支付

          加鎖

          不管是3.申請支付、還是5.支付回調(diào),都應(yīng)該以訂單維度加鎖,防止并發(fā)下的重復(fù)操作。

          加鎖,毫無疑問,也是分布式鎖,通常我們會選擇Redis分布式鎖。

          加鎖

          緩存結(jié)果

          申請支付成功,支付回調(diào)成功,都應(yīng)該緩存結(jié)果。

          再申請支付,收到成功回調(diào)的時候,都應(yīng)該先去檢查支付的狀態(tài)。

          在這里插入圖片描述

          支付中流水取消

          假如說,用戶重復(fù)支付了,再次申請支付的時候,如果已經(jīng)申請支付成功了,那么這筆支付肯定是要拒絕的。

          但是,要是已經(jīng)存在的這筆流水還在支付中呢?——我們不確定它是成功還是失敗,肯定是不能拒絕支付的,因為可能用戶支付失敗了,但是狀態(tài)還沒同步,這樣肯定是不行的。

          所以,我們可以取消掉正在支付中的流水,再進(jìn)行支付。

          支付中流水取消

          已支付流水退款

          現(xiàn)在又有新的問題了,假如發(fā)起支付的時候,有流水正在支付中,如果第三方支付平臺不支持取消支付,或者用戶新的支付是通過不同的渠道,我們希望盡可能提高用戶的支付成功率,怎么辦呢?

          我們可以在發(fā)起支付的時候,訂單還在支付中的情況下,允許用戶發(fā)起多筆支付,在支付回調(diào)的時候,檢查用戶是否已經(jīng)有成功流水,對后來的流水進(jìn)行退款處理。

          支付回調(diào)

          當(dāng)然,退款是個很危險的操作,畢竟錢退了,可就很難追回來,一定要做好風(fēng)險的控制。

          主動輪詢&重試防止掉單

          主動輪詢防止外部掉單

          如果因為故障沒有收到回調(diào),或者沒有及時收到回調(diào),就可能會發(fā)生所謂的外部掉單。

          防止外部掉單的關(guān)鍵,就在于,不能傻傻地只等三方的回調(diào)通知,而要主動去查詢,用戶發(fā)起支付的3s之后,就可以發(fā)起輪詢了,直到拿到支付流水的最終狀態(tài),主動輪詢,一般可以這么實現(xiàn):

          輪詢
          • 定時任務(wù)輪詢

            使用定時任務(wù),掃描表中支付中的流水,主動查詢支付的狀態(tài),定時任務(wù)的實現(xiàn)方式有很多,線程池、調(diào)度框架、分布式調(diào)度框架等等。

            定時任務(wù)輪詢的缺點有兩個:

            1. 對數(shù)據(jù)庫有一些壓力,觀察監(jiān)控,會發(fā)現(xiàn)定時任務(wù)掃表的時候,有時候會造成數(shù)據(jù)庫的一些“峰刺”
            2. 不便調(diào)整頻率,實際上,用戶發(fā)起一筆支付之后,一般都會在10s-1min中完成支付,越往后,用戶完成支付,所以輪詢梯度進(jìn)行,會更合理一些,輪詢的間隔可以設(shè)置成類似這種:3s,10s,30s,3min……
          • 延時消息輪詢

            另外一種方式就是使用延時消息,用戶發(fā)起支付之后,發(fā)送一個延時消息,消費到延時消息之后,查詢流水支付狀態(tài),沒有拿到最終狀態(tài),就再發(fā)一個延時消息。延時消息的好處是對數(shù)據(jù)庫的壓力沒有那么大,輪詢的梯度也可以進(jìn)行控制,缺點是實現(xiàn)起來復(fù)雜一些,而且要維護(hù)消息隊列。

          同步+異步防止內(nèi)部掉單

          支付服務(wù)在收到異步通知回調(diào)、或者主動輪詢到流水的最終狀態(tài)后,要通知訂單服務(wù)支付流水的變化,訂單服務(wù)同步更新訂單的狀態(tài),這個過程要盡可能保證通知成功,可以采用同步+異步的方式。

          • 同步調(diào)用:支付服務(wù)調(diào)用訂單服務(wù)的通知接口,有可能會因為網(wǎng)絡(luò)等等的原因失敗,也可以重試,但是根據(jù)經(jīng)驗,如果網(wǎng)絡(luò)出現(xiàn)一些波動,重試很可能也會失敗。
          • 異步通知:支付服務(wù)還應(yīng)該發(fā)送一個支付成功的消息,訂單服務(wù)可以利用消息隊列的重試機制,來盡可能保證支付狀態(tài)的同步。

          這里還有一個問題,客戶端如何同步這個狀態(tài)?因為可能服務(wù)端更新了訂單狀態(tài),但是客戶端的界面上還是未支付,得用戶主動刷新一下,才能拿到最新的狀態(tài),這樣明顯是不太合適的。

          服務(wù)端、客戶端的狀態(tài)同步,無非就:

          • 拉:很簡單,就是客戶端在用戶跳回訂單狀態(tài)頁的時候,輪詢一會,如果用戶完成支付,通常很短時間就能獲取到狀態(tài)的變更,當(dāng)然這種方式對客戶端的性能會有一些影響,而且很出現(xiàn)狀態(tài)同步“漏網(wǎng)之魚”的情況。
          • 推:推的實現(xiàn)有些麻煩,Web通常是用Websocket,對APP端的推送,一般采用第三方的推送平臺。

          客戶端支付盡可能不外跳

          不管從產(chǎn)品的角度,還是技術(shù)的角度,客戶端發(fā)起支付這一步,其實應(yīng)該盡可能地不要外跳,PC端使用支付服務(wù)生成的支付碼,而不是跳轉(zhuǎn);移動端網(wǎng)頁、APP在應(yīng)用內(nèi)展示支付頁,當(dāng)然這個是由第三方支付平臺決定的。

          在UC內(nèi)內(nèi)嵌支付寶

          不知道大家留意到了沒有,現(xiàn)在的支付寶,已經(jīng)做到了不用拉起錢包,在應(yīng)用內(nèi)就可以完成支付,這個對于商家的意義還是比較大的,對用戶體驗、支付成功率,都有正面的作用,相信以國內(nèi)的內(nèi)卷程度,其它支付供應(yīng)商,一定會“跟進(jìn)”的。


          好了,關(guān)于如何防止重復(fù)支付,就講到這里。對于支付,老三也只是初窺門徑,希望各位大佬不吝指教。



          參考:

          [1]. 服務(wù)端如何防止重復(fù)支付



          我的新書《深入理解Java核心技術(shù)》已經(jīng)上市了,上市后一直蟬聯(lián)京東暢銷榜中,目前正在6折優(yōu)惠中,想要入手的朋友千萬不要錯過哦~長按二維碼即可購買~


          長按掃碼享受6折優(yōu)惠


          往期推薦

          我在代碼里面故意留個漏洞,違法嗎?


          拼多多面試:如何用 Redis 統(tǒng)計獨立用戶訪問量?


          一個開發(fā)者自述:我是如何設(shè)計針對冷熱讀寫場景的 RocketMQ 存儲系統(tǒng)




          有道無術(shù),術(shù)可成;有術(shù)無道,止于術(shù)

          歡迎大家關(guān)注Java之道公眾號


          好文章,我在看??

          瀏覽 48
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          評論
          圖片
          表情
          推薦
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  久久一级视频 | 日韩欧美精品熟 | 午夜色视频| 人妻-X88AⅤ | 青草青在线 |