充值系列——充值系统的架构(二)

时间:2024-04-06 21:12:04

一篇文章主要介绍了充值系统的基本概要说明和数据库设计。

这篇文章主要讨论充值的基本流程和系统架构。简单来说,充值的基本流程就是:玩家选择一个支付平台,选择这个平台下面出售的某个商品,付款成功后玩家会得到所购买的商品。

数据交互图

玩家客户端指的是浏览器或者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层的具体方法实现。