上一篇文章主要说明充值的执行逻辑和控制层的设计,这篇文章主要讨论充值业务层的具体实现。
正如上一篇文章所说到的,生成订单需要如下几个步骤:
(1)实例化操作人 (操作人)
(2)实例化产品模型 (获取产品的详细信息)
(3)实例化订单模型 (生成一笔状态为“交易中”的订单)
(4)实例化支付平台模型 (把生成的订单返回给客户端,并引导用于去充值平台)
一个完整的充值系统需要完善以上4个基本的模型类。详细的UML图如下:
支付平台依赖操作人类,订单类,产品类,助手类。
class Model_Payment
{
// 对应关系为:'渠道ID' => '渠道类名'
private static $_channels = array(
'10' => 'alipay',
'20' => 'applestore'
);
// 缺省的充值渠道
const DEFAULT_CHANNEL_ID = 40;
public function factory($channelId)
{
if isset(self::$_channels[$channelId]) : throws('渠道不合法');
$className = 'Model_Payment_Channel_' . ucfirst(self::$_chanels[$channelId]);
return new $className;
}
}
function createOrder(Model_User $user, Model_Payment_Product $product, array $extraData = array())
{
if (! $product instanceof Model_Payment_ProductNull) {
if ($product['channel_id'] != $this->_channelId) {
throw new Model_Payment_Exception_Common(_('购买的产品和当前充值渠道不匹配'));
}
}
// 执行新增订单
$orderResult = $this->_insertOrder($user, $product, $extraData);
// 组装生成订单后的返回结果
return $this->_buildCreateReturn($orderResult, $product);
}
protected function _insertOrder(Model_User $user, Model_Payment_Product $product, array $extraData = array())
{
$setArr = array(
'status' => Model_Payment_Order::STATUS_UNPAID, // 未支付
'create_time' => $GLOBALS['_DATE'],
'uid' => $user['uid'],
'product_name' => $product['name'],
// 此处省略其他订单信息
'channel_id' => $this->_channelId, // 充值渠道
);
if (! $orderSn = Model_Payment_Order::create($setArr)) {
throw new Model_Payment_Exception_Common(_('保存订单失败'));
}
return array(
'order_sn' => $orderSn, // 必须返回订单详细
}
我方组装生成订单后的返回结果 protected function _buildCreateReturn(array $orderResult, Model_Payment_Product $product)
{
return json_encode(array(
'status' => 'success',
'productId' => $product['id'], // 我方产品Id
'thirdProductId' => $product['third_product_id'], // 对应第三方平台的产品Id
'totalPrice' => $orderResult['total_price'], // 订单总价
'orderSn' => $orderResult['order_sn'], // 内部订单流水号
'subject' => $product['name'], // 订单名称
'description' => _('购买') . $product['name'], // 订单备注
));
}
public function create($setArr)
{
// 生成新的订单流水号 (这个方法在这个系列(一)中有说明)
$orderSn = self::createSn();
$setArr['order_sn'] = $orderSn;
// 下单时间
if (! isset($setArr['create_time'])) {
$setArr['create_time'] = $GLOBALS['_DATE'];
}
if (! Dao('Order_Orders')->insert($setArr)) {
return false;
}
return $orderSn;
}
function __construct($orderSn)
{
if (! $orderSn) {
throw new Model_Payment_Exception_Common('Invalid OrderSn');
}
if (! $this->_prop = Dao('Order_Orders')->get($orderSn)) {
throw new Model_Payment_Exception_Common(_('订单信息不存在。') . 'OrderSn:' . $orderSn);
}
}
function __construct($productId = 0)
{
if ($productId < 1) {
throw new Model_Payment_Exception_Common('Invalid ProductId');
}
if (! $this->_prop = Dao('Order_Product')->get($productId)) {
throw new Model_Payment_Exception_Common(_('购买的产品不存在') . 'ProductId:' . $productId);
}
// 拼接产品名称(因为多语言版本)
$this->_prop['name'] = _('手机大航海') . $this->_prop['gold_value'] . _('金块');
}
function getListByChannel($channelId)
{
return Dao('Order_Product')->getListByChannel($channelId);
}
function buildRequestForm($action, array $params, $method, $btnName = null)
{
$html = "";
$html .= "";
return $html;
}