支付系統(tǒng)返回碼設(shè)計及映射避坑指南

0 評論 1665 瀏覽 6 收藏 13 分鐘

在支付系統(tǒng)的構(gòu)建與管理中,返回碼的設(shè)計和映射是確保交易順暢進行的關(guān)鍵環(huán)節(jié)。本文將深入探討支付系統(tǒng)返回碼的重要性、常見問題及其解決方案,旨在幫助開發(fā)者和支付系統(tǒng)管理者避免潛在的陷阱,提升用戶體驗,并確保交易的準確性和安全性。


我在支付行業(yè)呆了十來年,和返回碼映射導(dǎo)致的線上生產(chǎn)問題交手無數(shù)次,有很多是因為影響用戶體驗,也有一些直接導(dǎo)致了線上資損,所以有必要開一篇小文聊一下。

一、返回碼還是錯誤碼

有些人喜歡用“返回碼”,有些人喜歡用“錯誤碼”。兩者本質(zhì)相同,都是用于標(biāo)識通信或交易的狀態(tài)。但我更傾向于使用“返回碼”,因為它不僅涵蓋錯誤狀態(tài),還包括成功狀態(tài),而成功并非錯誤,所以使用“返回碼”更為合適。

二、返回碼的本質(zhì)

我很喜歡探尋事物的本質(zhì),那么返回碼的本質(zhì)是什么?我覺得是解決2個問題:

  1. 標(biāo)識單一系統(tǒng)內(nèi)的業(yè)務(wù)處理結(jié)果:在一個單一系統(tǒng)內(nèi),如何表達業(yè)務(wù)處理的結(jié)果,比如參數(shù)不對,余額不足,還是成功等。
  2. 完成異構(gòu)系統(tǒng)或應(yīng)用之間的處理結(jié)果同步:在多個系統(tǒng)之間如何同步業(yè)務(wù)處理的結(jié)果,比如渠道的結(jié)果同步給支付平臺的網(wǎng)關(guān)系統(tǒng),網(wǎng)關(guān)系統(tǒng)同步給支付引擎等。

三、返回碼最核心的關(guān)注點

返回碼最核心的關(guān)注點也只有2個:

  1. 同一系統(tǒng)內(nèi)定義是否足夠清晰明確。減少歧義,減少誤解。
  2. 異構(gòu)系統(tǒng)或應(yīng)用之間的映射是否足夠準確。映射不好,輕則影響用戶體驗,重則有資損。

四、曾經(jīng)碰到過的坑

踩過的坑很多,大致可以歸為以下幾類:

  1. 對客映射不準確,導(dǎo)致用戶持續(xù)重試失敗,影響用戶體驗。比如“余額不足”或“風(fēng)控不過”,返回給用戶“系統(tǒng)異常,請重試”,有些用戶就瘋狂地重試。
  2. 外部渠道沒有明確成功或失敗,內(nèi)部映射成明確成功或失敗,造成資損。比如:

支付同步請求渠道響應(yīng)還沒有回來,發(fā)起了查詢,查詢返回“訂單不存在”,直接推進失敗,但最后銀行扣款成功。

退款同步請求渠道響應(yīng)返回“系統(tǒng)異?!?,直接推進到失敗,但最后銀行退款成功。

3. 外部渠道有雙層返回碼,沒有做完整判斷。比如第1層只表示接口是否成功(通信層面),第2層才是表示業(yè)務(wù)是否成功,但是只判斷了接口層面,就推進了內(nèi)部訂單的業(yè)務(wù)狀態(tài)。

4. 返回碼制定過于籠統(tǒng)或太細。

五、最佳實踐

5.1. 基本原則

  • 制定統(tǒng)一返回碼規(guī)范:在團隊或公司層面制定統(tǒng)一的返回碼規(guī)范,明確各個返回碼的含義,確保各模塊一致性。
  • 嚴格遵守返回碼定義:研發(fā)人員在編碼時,應(yīng)嚴格按照規(guī)范返回對應(yīng)的返回碼,確保返回碼與實際狀態(tài)匹配。明確成功才推進成功,明確失敗才推進失敗,其它全部按“未知”處理。
  • 區(qū)分接口/通信成功與業(yè)務(wù)成功
  • 流入到平臺的(支付、充值等),謹慎映射到成功。從平臺流出的(提現(xiàn),代發(fā)等),謹慎映射到失敗。

5.2. 三級返回碼體系

外部商戶對接支付平臺,支付平臺內(nèi)部有自己的業(yè)務(wù)處理,同時還對接了外部的很多渠道,所以需要管理三套返回碼

  • 提供給商戶OpenAPI使用的返回碼:這塊可以直接參考微信支付、支付寶等機構(gòu)的門戶網(wǎng)站。
  • 內(nèi)部各應(yīng)用使用的標(biāo)準返回碼:用于內(nèi)部業(yè)務(wù)的處理。
  • 渠道返回碼:外部渠道提供的返回碼,每個渠道都不一樣,需要映射到內(nèi)部標(biāo)準返回碼。

為什么需要三層?主要有3個原因:

  1. 內(nèi)部應(yīng)用使用的標(biāo)準返回碼需要精確,便于內(nèi)部系統(tǒng)運行的監(jiān)控。
  2. 給商戶OpenAPI的返回碼需要業(yè)務(wù)語義明確,但不能過于精確。比如內(nèi)部出現(xiàn)“卡的有效期不正確”,對外則是“卡號或持卡人或有效期不正確”,避免輪詢攻擊。
  3. 外部渠道返回碼不能全部一對一映射到內(nèi)部,因為外部渠道太多,容易膨脹。

5.3. 商戶OpenAPI返回碼設(shè)計

這部分建議直接參考微信支付、支付寶或者ISO20022標(biāo)準,這幾家代表了行業(yè)的最高水準。

一般來說最少有兩個字段:resultCode和message,一個表示碼,一個表示碼的描述。

也可以增加一個參數(shù)result,使用S,F(xiàn),U表示業(yè)務(wù)狀態(tài)的成功、失敗、未知。

如果是查詢類接口,一定要明確說明是接口成功,還是業(yè)務(wù)成功。

5.4. 內(nèi)部標(biāo)準返回碼設(shè)計

支付平臺內(nèi)部也分了不同域,建議使用一個共同的規(guī)范,比如:RS+子系統(tǒng)編號+錯誤級別+具體返回碼。具體如下圖所示:

支付系統(tǒng)返回碼設(shè)計及映射避坑指南_v0.2

說明:

  • 1-2位:固定值RS,Result縮寫。
  • 3-5位:子系統(tǒng)編號。比如001:收銀支付,002:會員等??煞奖愣ㄎ荒膫€系統(tǒng)出的問題。
  • 6位:錯誤類或等級。比如:0:正常,1:業(yè)務(wù)級異常,2:系統(tǒng)級異常。
  • 7-9位:各業(yè)務(wù)線自己定。比如:1xx:參數(shù)相關(guān),2xx:數(shù)據(jù)庫相關(guān),3xx:賬戶狀態(tài)/Token狀態(tài)相關(guān)等。
  • 這樣的好處在于,每個子域或子系統(tǒng)既有全局的規(guī)范,又有自己的靈活性,減少溝通成本。
  • 注意:上面只是寫了resultCode,還需要有message,用于描述這個碼代表什么語義。
  • 核心代碼(注:使用chatGPT o1生成,請自行增刪):
public interface IResultCode {
    String getResultCode();
    String getMessage();
}
public enum PaymentResultCode implements IResultCode {
    SUCCESS( "0000", "success"),
    FAIL("2998", "fail"),
    SYSTEM_ERROR("2999","system error"),
    // 額度相關(guān) 11XX
    INSUFFICIENT_FUND("1101", "insufficient fund"),
    // 風(fēng)控相關(guān) 12XX
    RISK_REJECTED("1201", "risk rejected"),
    // DB相關(guān) 21XX    ;
    private static final String PREFIX = "RS";
    private static final String SYSTEM_CODE = "101";
    private String codeNumber;
    private String message;
    @Override
    public String getResultCode() {
        return PREFIX + SYSTEM_CODE + codeNumber;
    }
    @Override
    public String getMessage() {
        return message;
    }
    PaymentResultCode(String codeNumber, String message) {
        this.codeNumber = codeNumber;
        this.message = message;
    }
}

5.5. 渠道返回碼映射

每個渠道的返回碼都是不一樣的,所以需要設(shè)計外部渠道返回碼映射到內(nèi)部標(biāo)準返回碼。需要遵守幾個原則:

  1. 只有明確成功,才能映射到成功。
  2. 只有明確失敗,才能映射到失敗。比如渠道返回:訂單不存在,或者系統(tǒng)異常,不能直接映射到失敗,因為有可能會成功。
  3. 涉及個人敏感信息或內(nèi)部系統(tǒng)敏感信息的,需要轉(zhuǎn)成模糊返回碼和描述出去,不能給最終用戶展示精確信息。比如內(nèi)部一個系統(tǒng)宕機,不能直接把異常拋出去。有效期錯誤也需要映射成“卡號或姓名或有效期不正確”。
  4. 與敏感信息無關(guān)的,越準確越好,避免用戶無謂的重試。比如余額不足,就不要映射成“系統(tǒng)異常,請重試”。
  5. 查詢類接口,務(wù)必要區(qū)分是接口成功,還是業(yè)務(wù)成功。

具體的技術(shù)實現(xiàn),通過使用映射表就足夠,加到緩存中,增加運算速度。如果找不到映射關(guān)系,就全部轉(zhuǎn)到一個默認的返回碼上面,同時對這個默認返回碼做監(jiān)控,定期把這些沒有做映射的返回碼映射到正確的返回碼上面去。避免應(yīng)該把類似“余額不足”映射成了“系統(tǒng)異常請重試”的場景。

5.6. 返回碼監(jiān)控與告警

大部分團隊都會監(jiān)控成功率,只有少數(shù)團隊會監(jiān)控返回碼或定期分析返回碼。然而當(dāng)交易量足夠大時,成功率的波動可能只有0.5%,很難看出異常,而如果去分析返回碼,則可以快速看出并定位問題。

一般來說,有幾個建議:

  1. 實時監(jiān)控返回碼的突變異常。比如:最近10分鐘,某個返回碼突然增加50%,或者比明天突然增加50%等。都需要介入看看。
  2. 定期觀察返回碼曲線表。如果某個返回碼連續(xù)多天持續(xù)在上升,一般都是有問題的。
  3. 建立返回碼全鏈路映射大盤。比如渠道返回“余額不足”或“風(fēng)控不通過”,映射到用戶展示“系統(tǒng)異常,請重試”,那就有問題。而且類似這種情況還非常常見。
  4. 定期分析用戶支付行為。以前在分析用戶行為時,發(fā)現(xiàn)同一用戶重試了20多次,最后排查發(fā)現(xiàn),就是返回碼映射不準確,導(dǎo)致用戶無謂的重試。

六、結(jié)束語

卷用戶體驗和成功率時,往往需要于細微處見真章,而返回碼的設(shè)計和映射就是如此。做得不好,輕則影響用戶體驗,重則資損。

希望對大家在設(shè)計標(biāo)準返回碼及映射時有所啟發(fā),也歡迎點贊轉(zhuǎn)發(fā)。

這是《圖解支付系統(tǒng)設(shè)計與實現(xiàn)》專欄系列文章中的第(48)篇。歡迎和我一起深入解碼支付系統(tǒng)的方方面面。

作者:隱墨星辰,公眾號:隱墨星辰

本文由 @隱墨星辰 原創(chuàng)發(fā)布于人人都是產(chǎn)品經(jīng)理。未經(jīng)作者許可,禁止轉(zhuǎn)載

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

該文觀點僅代表作者本人,人人都是產(chǎn)品經(jīng)理平臺僅提供信息存儲空間服務(wù)

更多精彩內(nèi)容,請關(guān)注人人都是產(chǎn)品經(jīng)理微信公眾號或下載App
評論
評論請登錄
  1. 目前還沒評論,等你發(fā)揮!