共计 2954 个字符,预计需要花费 8 分钟才能阅读完成。
这几年的工作中一直与支付打交到,借着 skr-shop 这个项目来与大家一起分享探索一下支付系统该怎么设计、怎么做。我们先从支付的一些常见流程出发分析,找出这些支付的共性,抽象后再去探讨具体的数据库设计、代码结构设计。
相关项目:
PHP 版本的支付 SDK
Go 版本的支付 SDK- 开发中
支付整体而言的一个流程是:给第三方发起了一笔交易,用户通过第三方完成支付,第三方告诉我支付成功,我把用户购买的产品给用户。
看似简单的流程,这里边不同的支付机构却有不同的处理。下面以我接触过的一些支付来总结一下
国内支付
国内的典型支付代表是:支付宝、微信、银行 (以招商银行为例),由于国内的支付都支持多种渠道的支付方式,为了描述简单,我们均以 pc 上的支付为例进行讲解。
支付宝
支付宝的接入是我觉得最简单的一种支付。对于在 PC 上的支付能力,支付宝提供了【电脑支付】。当用户下单后,商户系统根据支付宝的规则构建好一个 url,用户跳转到这个 url 后进入到支付宝的支付页面,然后完成支付流程。
在支付成功后,支付宝会通过 同步通知、异步通知 两种方式告诉商户系统支付成功,并且两种通知方式的结果都是可信的,而且异步通知的消息延迟也非常短暂。
对于退款流程,支付宝支持全额、部分退款。并且能够根据商户的退款单号区分是否是同一笔退款进而避免了重复退款的可能。支付的退款是调用后同步返回结果,不会异步通知。
微信支付
微信并没有提供真的 PC 支付能力,但是我们可以利用【扫码支付】来达成电脑支付的目的。扫码支付有两种模式,这里以模式二为例。
微信调用下单接口获取到这个二维码链接,然后用户扫码后,进入支付流程。完成支付后微信会 异步通知,但是这里并没有 同步通知,因此前端页面只能通过定时轮训的方式检查这笔交易是否支付,直到查询到成功、或者用户主动关闭页面。
退款流程与支付宝最大的不同是,有一个 异步通知 需要商户系统进行处理。
第一个不同点:
异步通知的接口需要处理多种不同类型的异步消息
招商银行
随着在线支付在国内的蓬勃发展,各家银行也是不断推出自己的在线支付能力。其中的佼佼者当属 招商银行。大家经常用的滴滴上面就有该支付方式,可以体验一下。
招商支付使用的是银行卡,因此首次用户必须进行绑卡。因此这里可能就多了一个流程,首先得记录用户是否绑过卡,然后用于签名的公钥会发生变化,需要定期更新。
招商所有平台的支付体验都是一致的,会跳转到招行的 H5 页面完成逻辑,支付成功后并不会自动跳回商户,也就是没有 同步通知,它的支付结果只会走异步通知流程,延迟非常短暂。
退款流程与支付宝一样,也是同步返回退款结果,没有异步通知。
第二个不同点:
支付前需要检查用户是否签约过,有签约流程
小结
国内在线支付流程相对都比较完善,接入起来也非常容易。需要注意的一点是:退款后之前支付的单子依然是支付成功状态,并不会变成退款状态。因为退款与支付属于不同的交易。
这一点基本上是国内在线支付的通用做法。
国际支付
国际支付的平台非常多,包括像支付宝、微信也在扩展这一块市场。我以我接触的几家支付做一个简单的总结。
WorldPay
这是比较出名的一家国际支付公司,它主要做的是银行卡支付,公司在英国
支付流程上,也是根据规则构建好请求的 url 后,直接跳转到 WorldPay 的页面,通过信用卡完成支付。这里比较麻烦的处理机制是:支付成功后,他首次给你的异步 / 同步消息通知并不能作为支付成功的依据。真的从银行确认划款成功后,才会给出真的支付成功通知。这中间还可能会异步通知告诉你支付请求被拒绝。最头痛的是不同状态的异步消息时间间隔都是按照分钟以上级别的延迟来计算
退款流程上,状态跟微信一样,需要通过异步消息来确认退款状态。其次它的不同点在于无法根据商户退款单号来确认是否已经发起过退款,因此对于它来说只要请求一次退款接口,那它就默认发起了一次退款。
第三、四不同点:
支付成功后的通知状态有多种,涉及到商户系统业务流程的特殊处理
退款不支持商户退款单号,无法支持防重复退款需要商户自己处理
Assist
这是俄罗斯的一家支付公司,这也是一家搞死人不偿命的公司,看下面介绍
它的支付发起是需要构建一个 form 表单,向它 post 支付相关的数据。成功后会跳转到它的支付页,用户完成支付即可。对于 同步通知,它需要用户手动触发跳回商户,与招商的逻辑很像,同步也仅仅是做返回并不会真的告知支付结果。异步通知 才是真的告知支付状态。比较恶心的是,支付时必须传入指定格式的商品信息,这会在部分退款时用到。
现在来说退款,退款也是与 WorldPay 一样,不支持商户的退款单号,因此防重方面也许自己的系统进行设计。并且如果是部分退款,需要传入指定的退款商品,这就会出现一个非常尴尬的局面:部分退款的金额与任何一个商品金额都对应不上,退款则会失败。
第五个不同点:
部分退款时需要传入部分退款的商品信息,并且金额要一致
Doku
接下来再来聊聊印尼的这家支付机构 doku。由于印尼这个国家信用卡的普及程度并不高,它的在线支付提供一种超商支付方式。
什么是超商支付呢?也就是用户在网络上完成下单后,会获取到一个二维码或者条形码。用户拿着这个条形码到超商(711、全家这种)通过收银员扫码,付现金给超商,完成支付流程。
这种方式带来的问题是,用户长时间不去支付,导致订单超时关单后才去付款。对整个业务流程以及用户体验带来很多伤害。
再来说退款,由于存在超商这种支付方式,导致这种支付无法支持在线自动退款,需要人工收集用户银行卡信息,然后完成转账操作。非常痛苦不堪。
第六个不同点:
线上没有付款,只有获取付款码,退款需要通过人工操作
AmazonPay
亚马逊出品,与支付宝非常类似。提供的是集成式的钱包流程。
支付时直接构建一个 url,然后跳转到亚马逊即可完成支付。它还提供一种授权模式,能够不用跳转 amazon,再商户端即完成支付。
支付成功后也会同步跳转,同步通知 的内容可以作为支付是否成功的判断依据。经过实际检查 异步通知 的到达会稍有延迟,大概 10s 以内。
退款方面也支持商户退款单号可以依赖此进行防重。但是退款的状态也是基于异步来的。
总结
这其中还有一些国际支付,如:PayPal、GooglePay、PayTM 等知名支付机构没有进行介绍,是因为基本它们的流程也都在上面的模式之中。我们后续的代码结构设计、数据库设计都基于满足上面的各种支付模型来完成设计。
最后,赠送大家一副脑图,这是接入一家支付时必须弄清楚的问题清单
下篇预告:《支付数据库与代码结构设计》
这是我们几个小伙伴利用业余时间思考的一些业务设计,如果有写的不对或者不完善的地方,希望大家多多评论,互相学习互相进步~
项目地址: https://github.com/skr-shop/m…
skr-shop 项目成员简介
排名不分先后,字典序
昵称
简介
个人博客
AStraw
研究生创业者, 现于小米科技海外商城组从事商城后端研发工作
——–
Dayu
Payment 开源作者,服务端开发者
dayutalk.cn
lwhcv
曾就职于百度 / 融 360, 现于小米科技海外商城组从事商城后端研发工作
——–
TIGERB
PHP 框架 EasyPHP 作者,拥有 A /B/ C 轮电商创业公司工作经验,现于小米科技海外商城组从事商城后端研发工作
TIGERB.cn