掃二維碼與項目經(jīng)理溝通
我們在微信上24小時期待你的聲音
解答本文疑問/技術咨詢/運營咨詢/技術建議/互聯(lián)網(wǎng)交流
今天得到一個項目的反饋:你們新增加的支付方式支付正常,但原來支付的流程總是付了錢卻沒反應。這消息本身是很常見的支付回調(diào)異常。而這個項目比較特殊,原來開發(fā)并不是我們,很多比較流程都是原來就有的,支付流程的業(yè)務邏輯也是比較復雜的,因此在新增加的流程中支付也調(diào)用原來的就已經(jīng)存在支付業(yè)務邏輯的(主要是不想動原來的核心流程,陳年老項目可不敢輕易動,哈哈);而且原來的支付流程一直都是通暢的,包括接入到原來支付模塊的新增流程也是正常的,說明已經(jīng)存在的支付業(yè)務邏輯是可用的。
其實支付回調(diào)異常是很常規(guī)的問題,一般來說是可以非??焖俣ㄎ坏?,最典型的兩個問題就是:1、支付商戶號異常更新導致異常;2、支付回調(diào)業(yè)務代碼執(zhí)行錯誤或邏輯錯誤。
首先,筆者注意到的是數(shù)據(jù)庫的支付訂單id號是間斷的,而id號本來是原來開發(fā)設置為自動自增的,理論上是連續(xù)的。說明在此過程中,有訂單會被刪除的過程。后面發(fā)現(xiàn)原來的支付業(yè)務邏輯確實會不停刪除支付訂單,基本邏輯就是二次發(fā)起支付會先刪除原來已經(jīng)存在但沒支付完成的訂單,然后生成新的支付訂單。本質(zhì)的目的就是為了刷新支付訂單號(可能原來的開發(fā)者是為了避免支付訂單超時等問題吧)。
但上述設計本身也是不夠優(yōu)雅的,比如刪除、新增數(shù)據(jù)的開銷比更新數(shù)據(jù)要大很多,同時不做任何判斷就直接刷新訂單號也不是優(yōu)雅的做法。
結(jié)合此前支付流程都是沒問題的,首先我們懷疑的是不是某個bug引起原來支付流程中刪除訂單+創(chuàng)建新訂單的(也就是刷新訂單號)問題,導致a訂單在用戶支付到銀聯(lián)商務這個支付平臺發(fā)送回調(diào)這個時間差內(nèi),系統(tǒng)錯誤的刪除了a訂單,而創(chuàng)建了新的b訂單,這樣回調(diào)的信息是a訂單,自然不能正常完成回調(diào)邏輯。
然而實際上通過程序debug模式的日志發(fā)現(xiàn),壓根就沒有查看到支付回調(diào)相關的日志,而其它所有操作流程的日志都是準確無誤的。
這個時候聯(lián)想到銀聯(lián)商務平臺后臺操作體驗與支付寶微信的差距很大,筆者甚至懷疑其銀聯(lián)商務這個支付平臺起來,懷疑是不是平臺的bug導致部分訂單回調(diào)消息沒有及時發(fā)送(差點就誤會了,哈哈)。但細想起來,人家那么大的平臺而且跟錢有關的東西不可能犯這么低級的錯誤。
所以再次查看了服務器nginx的日志,發(fā)現(xiàn)在nginx日志里面出現(xiàn)了支付回調(diào)的痕跡。而且發(fā)現(xiàn)返回的狀態(tài)碼是非常少見的499狀態(tài)碼。
大家一般常見的http狀態(tài)碼有2xx有200,3xx有301、302,4xx有401、404、403、405,5xx有500、502等等,但499狀態(tài)碼很少見。
大家都知道4xx狀態(tài)碼意味著客戶端的錯誤,比如401意味著用戶身份認證不通過,404意味著查找的資源不存在(非常常見的錯誤碼),403禁止訪問,405請求的方法被禁止。當然雖然說4xx狀態(tài)碼都說客戶端的錯誤,但實際上還是服務端沒有相關的資源或者客戶端的請求不符合服務端的要求。
通過查詢相關的資料得知:
499錯誤碼是由于客戶端發(fā)起請求后,一段時間內(nèi)沒有收到代理服務器的應答,導致連接失敗??赡茉虬ǎ?. 代理服務器認為客戶端發(fā)起的請求過于危險,所以主動給斷了; 2. 代理服務器實在么得辦法連接到其他服務,導致超時。
1、排除是由于銀聯(lián)商務平臺穩(wěn)定性問題。
不更改支付流程的任何邏輯,只是把回調(diào)通知地址改成其它服務器的某個回調(diào)接口地址。結(jié)果發(fā)現(xiàn)在新的回調(diào)地址都能返回200正常的狀態(tài)碼。所以可用排除時銀聯(lián)商務平臺發(fā)送的回調(diào)數(shù)據(jù)有啥問題的可能。
2、排除是由于回調(diào)信息被服務器拒絕。
因為之前是一直被回調(diào)信息請求到并完成整個業(yè)務流程的,而且這種正規(guī)的支付平臺原來開發(fā)者也沒必要做特別的限制。而且上面通知到其它接口也是正常的狀態(tài)碼,因此這個可能也可用排除。
3、排除是由于項目所在服務器配置的問題。
在當前服務器創(chuàng)建一個全新的空白項目,新項目就是提供一個回調(diào)接口,測試發(fā)現(xiàn)該新項目測試接口得到的結(jié)果是跟上面測試一樣正常的,因此也可用排除。
4、排除是由于整個項目底層框架對回調(diào)信息的錯誤處理。
在當前項目,新建一個空白控制器,提供一個空白的訪問接口。經(jīng)過回調(diào)測試發(fā)現(xiàn)跟上面的結(jié)果還是一樣,還是返回預期內(nèi)的結(jié)果。
排除了這么多,說明問題的根源還是在于原來開發(fā)者開發(fā)的這個支付回調(diào)邏輯中除了問題,很可能就是因為某種故障造成的請求超時。結(jié)果筆者發(fā)現(xiàn)原來開發(fā)者在處理回調(diào)信息的時候,非常復雜,走了很多完全跟項目業(yè)務邏輯關系不大的流程,而且拐彎抹角(我甚至懷疑這些代碼是不是東拼西湊來的)。結(jié)果通過不停斷點測試,外加溯源n層方法調(diào)用,發(fā)現(xiàn)了這么一段。
通過這么一段的邏輯我們可用判斷原開發(fā)者的邏輯:1、信息推送測試,但是在上線前竟然沒撤掉,也沒做任何處理;2、是不是信息非法提交的后門邏輯,畢竟這些信息都是姓名、身份證號碼、身份證照片等敏感信息。
?最終的問題所在也是出在這個地方,由于這里請求的外部接口之前是正常訪問的,而限制接口已經(jīng)失效了,再加上沒有做任何處理。而去剛好原來已經(jīng)有的支付流程的傳入?yún)?shù)在某些情況下剛好符合這段代碼的執(zhí)行條件,于是就執(zhí)行了這些業(yè)務邏輯。之前外部接口是正常的自然回調(diào)也是正常的,現(xiàn)在外部接口失效了,于是回調(diào)請求就一直卡著不動,銀聯(lián)商戶那邊作為客戶端也不會太傻,可能直接斷開服務鏈接,于是就造成了499返回碼。
看了這個案例你還敢隨隨便便使用某些來歷不明的源代碼么,即便你敢用,你還會覺得用這些不明來源的源代碼會幫你省錢嗎?即便有人愿意修改,這修改維護的代價可能比新開發(fā)還要大,因為接手的其它任何開發(fā)者可能排查各種坑所花的時間比自己新開發(fā)還要多。
我們在微信上24小時期待你的聲音
解答本文疑問/技術咨詢/運營咨詢/技術建議/互聯(lián)網(wǎng)交流