1. 程式人生 > >充值系列——充值系統的架構(二)

充值系列——充值系統的架構(二)

一篇文章主要介紹了充值系統的基本概要說明和資料庫設計。

這篇文章主要討論充值的基本流程和系統架構。簡單來說,充值的基本流程就是:玩家選擇一個支付平臺,選擇這個平臺下面出售的某個商品,付款成功後玩家會得到所購買的商品。

資料互動圖

玩家客戶端指的是瀏覽器或者SDK。

上面資料互動圖中需要有幾點注意:

(1)玩家客戶端,遊戲伺服器,支付平臺這三者之間扮演的角色

遊戲伺服器只是提供資料的提供者和資料的處理者,遊戲伺服器不會直接把訂單提交給支付平臺. 訂單由玩家客戶端提交.

一般來說,如果是網頁支付,那麼客戶端就是瀏覽器,提交訂單資訊給支付平臺的方式有兩種:

A: 以HTML表單格式自動提交GET/POST請求 (使用javascript自動提交)

B:以URL訊號的方式重新跳轉

如果是SDK支付,那客戶端就是SDK,SDK首先需要從遊戲伺服器中獲取訂單資訊,然後把訂單資訊傳給支付平臺。

(2)支付平臺處理訂單之後如何通知遊戲伺服器和玩家客戶端。

一般來說,當支付平臺處理完訂單後,會有兩個動作:

A: 非同步通知遊戲的伺服器。把訂單的處理結果返回給遊戲伺服器,遊戲伺服器接收到這個資訊後,判斷如果支付成功,則把玩家購買的商品發給玩家(如發給玩家500金塊)。

B:同步通知客戶端。例如一般支付平臺支付處理完成後,頁面中會有一個“返回商家網站”的按鈕,點選這個按鈕的時候,就可以返回遊戲。這就是同步通知。

這裡,我們需要認識到的是,同步是不可靠的(使用者沒有點選),訂單必須在非同步的時候處理。還有一點需要注意的是,同步和非同步發生的時間不同。可能非同步處理慢於同步跳轉,所以在同步跳轉提示玩家充值資訊的時候(假設充值成功的話),我們會提示:“訂單成功,你購買的商品將在5分鐘內到賬!”。

基本流程圖

支付模組中,控制器需要提供三個方法:
(1)createOrder() 生成訂單
(2)respNotify() 非同步響應支付平臺的支付處理結果,驗證支付是否成功。同時處理支付成功後的資料。不同的支付平臺非同步響應的資料也會不一樣
(3) respReturn() 同步響應支付平臺的通知(如:玩家點選返回商家網站後,就會訪問到這個方法)

MVC模型圖

控制器方法

生成訂單,如果客戶端是瀏覽器,則是瀏覽器訪問createOrder方法,生成訂單後,頁面自動跳轉都支付平臺或者使用表單提交到支付平臺。如果客戶端是SDK,則由SDK訪問createOrder方法,然後返回給SDK一個包含訂單資訊的JSON,最後由SDK把訂單資訊提交給支付平臺。

function createOrderAction()
{
    // 玩家ID
    $uid = $this->getInt('uid');
    // 要購買的產品Id
    $productId = $this->getInt('product_id');
    // 當前充值渠道
    $channelId = $this->getInt('channel_id');
 
    // 其它資訊
    $postData = $this->getQueryPostx()
 
    // TODO 各種資料合法性驗證
 
    try {
        // 例項化操作物件
        $user = new Model($uid);
 
        // 例項化產品物件
        $product = new Model_Payment_Product($productId);
 
        // 例項化支付模型
        $payment = Model_Payment::factroy($channelId);
 
        $result = $payment->createOrder($user, $product, $payment, $postData);
    }
    // 輸出通知錯誤和異常
    catch (Exception $e) {
        $this->jsonx($e->getMessage(), 'error');
    }
 
    // 如果返回內容是一個URL,則直接跳轉
    if ($url = Model_Payment_Util::getUrlFromSignal($result)) {
        $this->redirect($url);
    }
    else {
        // 如果客戶端是SDK的話,以JSON的形式把訂單資訊輸出給SDK。
        exit($result);
    }
 
    // 注意:如果是表單自動提交,這提交過程發生在MODEL層。所以,控制器中只有兩種提交方式
}

非同步響應,這個函式是支付平臺處理支付完之後自動訪問的,所以,需要事先配置到支付平臺中去,例如 redirectUrl= www.example.com/order/respnotify/?channel_id=40;

function respNotifyAction() 
{
    // 注意,這個引數不是支付平臺提交過來的,而是自己配置的
    $channelId = $this->getInt('channel_id');
    $postData = $this->getQueryPostx();
 
    // TODO 各種數值驗證
 
    try {
        $payment = Model_Payment::factory($channelId);
        $payment->respnotify($postData);
    }     
    // 輸出通知錯誤和異常
    catch (Exception $e) {
        $this->jsonx($e->getMessage(), 'error');
    }
 
    // 需要把結果返回給支付平臺,例如360支付需要輸出“ok”,否則,360會繼續請求這個URL
    // 這是支付的具體細節問題,以後還會討論
    exit($result);
}

同步響應
也是需要事先在支付平臺配置好。同步響應和非同步響應都會處理支付的結果,驗證支付是否成功,主要的區別在於,同步響應後會有一些頁面表現,比如驗證支付成功後,觸發一個動作,提示玩家充值成功。

下一篇會講解支付模組MODLE層的具體方法實現。