一篇文章主要介绍了充值系统的基本概要说明和数据库设计。
这篇文章主要讨论充值的基本流程和系统架构。简单来说,充值的基本流程就是:玩家选择一个支付平台,选择这个平台下面出售的某个商品,付款成功后玩家会得到所购买的商品。
数据交互图
玩家客户端指的是浏览器或者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层的具体方法实现。