支付平台架构

支持多种支付方式的支付平台架构,示例使用 Python Tornado 框架。

用到了工厂模式和模板方法模式。

工厂模式:子类的某个方法要根据情况来决定用什么类去实例化对象。

模板方法模式:用来定义算法的各个步骤,并将某些步骤交由子类实现。

流程

流程为:下单、用户付款、确认用户付款、发货。

  • 下单:客户端调用该接口,上传必要信息,如商品 ID、收货人,服务器创建订单,返回一个唯一的订单号。
  • 用户付款:付款方式由支付渠道提供。
  • 确认用户付款:一般有两种方式:回调与主动验单。
    • 回调:用户支付成功后,充值渠道发起请求到我方服务器。比如支付宝。
    • 主动验单:充值渠道将充值数据返回给客户端,客户端将其提交到服务器,服务器拿着数据去充值渠道验单。比如苹果支付、谷歌支付。
  • 通知发货。

设计

  • 充值渠道可以共用创建订单、发货的方法
  • 由于回调一般为 POST 请求,所以只能通过 URL 来区分不同的充值渠道,而不能使用相同的 URL 然后再通过参数来区分。
  • 在基类中定义需要实现的模板方法,由子类(具体的支付渠道)去具体实现。

所以整个基类的结构如下:

class AbstractPay(tornado.web.RequestHandler):

    def create_order(self):
        """创建订单"""
        pass

    def respond_callback(self):
        """响应支付方回调"""
        raise NotImplementedError()

    def verify_order(self):
        """向支付方验证订单"""
        raise NotImplementedError()

    def notify_delivery(self):
        """通知发货"""
        pass

raise NotImplementedError() 是需要子类去实现的方法,pass 的表示由基类实现,子类共用的的方法。

URL 如下

handlers = [
    ('/' + API_VERSION + 'create_order/', CreateOrderHandler),
    ('/' + API_VERSION + 'callback/' + '(?P<channel>[^\/]+)', RespondCallbackHandler),
    ('/' + API_VERSION + 'verify/' + '(?P<channel>[^\/]+)', VerifyHandler),
]

根据 channel 实例化对应的类,然后调用 respond_callbackverify_order 方法,验证成功后再通知发货。

响应回调的代码如下:

def post(self, channel):
    pay_channel = globals()[channel.title()]()
    pay_channel.respond_callback()

确保成功

需要确保我们的主动请求 —— 验证订单和通知发货一定成功。

  1. 在第一次请求失败后,隔一定时间再次发起请求,如果还是失败,增大等待间隔,再次发起请求,以此类推,直到一定次数之后,抛出异常。
  2. 增加定时任务,定期去验证订单和通知发货。

异常处理

所有支付渠道可以共用一个异常处理函数。异常处理顺序由具体到抽象,由自定义到内置。

这里以 Tornado 为例,在 AbstractPay 中重写 write_error() 即可。

使用时只需要在子类中抛出对应异常。

安全

流程如下:

  • 回调订单号应该存在并且为 等待支付 状态
  • 支付金额和创建订单时的金额一致
  • 商品 ID 一致
  • 验证签名

以上任何一个验证失败,则忽略该回调/验证数据。

  • 第一步为了防止多次发货
  • 第二三步确保购买的商品、付款的金额一致
  • 验证签名确保信息来源正确

由于各种渠道回传的数据不一致,所以这个由子类自己实现。

posted @ 2018-03-26 17:58  Jay54520  阅读(294)  评论(0编辑  收藏  举报