我們的業務中,經常會遇到多渠道+多場景的的需求。多渠道我們可以理解為,多個服務商同時為我們某一個功能提供服務,多場景就是同一個服務商下面的多種服務,我們通過幾個例子來具體看下:
我們有個電商平臺,系統在付款時候彈出選項,讓使用者自主選擇支付寶/微信/京東白條等支付,那麼這裡的支付寶、微信、京東我們都可以理解為他是我們的渠道。
同時,既然接入了支付寶/微信等,我們的系統就不再會單單使用他們的一個支付功能,還會涉及到對賬、退款等等操作,那麼這些操作,我們稱之為場景。
類似的,有的公司需要將訂單進行推播,根據訂單型別,推播到淘寶、拼多多等。那麼淘寶和拼多多也屬於渠道,同樣的,有了下單,那麼還會有退單、訂單對賬等都屬於場景。通過這樣的案例分析下來,我們會發現,我們身邊有很多這樣的需求。如果針對這類需求,我們的程式碼缺少一些架構設計,那麼就會帶來很多問題,比如:
此類問題應該存在一些通用的解決方案,可以實現以下特點:
我們以下單支付為案例,通過時序圖的流程來梳理下我們的思路:
關於和三方請求的操作,一般就分為兩類:
請求三方系統的具體流程如下:
不同場景下,流程相同,但是還會存在一些差異點,我們總結一下:
不同回撥場景也可能會存在一些差異,我們總結一下:
多渠道多業務通過以上分析基本上都是可以列舉的,可以通過以下表格進行拓展:
程式碼已開源到Github:https://github.com/Shiyajian/mall-example
程式碼可能執行有問題,主要展示的是思路,下面是針對專案的講解。
通過案例分析,我們分析出來了通用和差異點,對於通用的部分,我們採用封裝成標準流程,差異的地方,我們定義拓展點介面,不同渠道方各自實現,每個渠道方的程式碼要物理隔離。
程式碼主要分為三部分:核心業務程式碼、架構程式碼、拓展實現程式碼。
主要使用策略模式,這裡通過介面進行抽象定義,程式碼主要分為三個部分:
拓展方式:
每個渠道商為一個package,裡面實現 call 和 callback 定義的介面即可,按需自己增加常數和工具類等;
通過 Manger 管理類進行查詢具體實現,並進行一定業務邏輯的編排,處理紀錄檔記錄,錯誤處理等通用流程。
需要呼叫渠道商介面的時候,通過以下方式進行呼叫:
@Override
public String pay(ChannelCodeEnum channelCode, Object args) {
// 1、建立支付單;
PayOrder payOrder = new PayOrder();
// 2、支付單入庫;
// 3、根據不同支付渠道,呼叫三方的支付單建立
ChannelCaller channelCaller = channelCallerManager.of(channelCode);
channelCaller.submitPay(payOrder);
// 4、更新三方訂單號入庫
// 5、返回前端喚醒引數
return payOrder.getPayParams();
}
渠道商介面回撥時候,通過下面方式進行引數的轉換,轉換完成後執行自己系統邏輯:
@RequestMapping("/pay/{channelCode}/{bizNo}")
public ResponseEntity<?> paySuccessCallback(HttpServletRequest request,
@PathVariable(value = "channelCode") String channelCode,
@PathVariable(value = "bizNo") String bizNo) {
log.info("進入[" + channelCode + "]支付成功回撥:bizNo:[" + bizNo + "] ");
ChannelCodeEnum channelCodeEnum = ChannelCodeEnum.ofCode(channelCode);
return channelCallbackHandlerManager.run(channelCodeEnum, () -> {
CallbackPayRequest payRequest = channelRequestParserManager.parse(channelCodeEnum, ChannelCallbackSceneEnum.PAY_CALLBACK, request, bizNo);
return payService.paySuccess(payRequest);
});
}
上面就是我在專案開發中,針對多渠道+多場景的一些思考及個人的程式碼設計。由於經驗有限,此方案不一定是最優方案,歡迎大家批評指正,感謝。
上份工作由於公司的資金鍊問題,失業了,現在找份工作,我簡單介紹下自己。
優勢:
劣勢: