我们首先实现一个类似于PayPal、Venmo、支付宝类型的支付系统,我们之后再考虑不同领域中的扩展。
让我们从系统设计的基本方法SNAKE原则来切入。
很多人做系统设计,往往陷入一个误区,一开始就想设计一个完美的系统,但这存粹是自己折腾自己,甚至让系统设计变得遥不可及。
抓取核心,支付系统有两个基本场景:
收款
付款
这个也正好应对着系统设计的两大基本操作:读与写。仔细想想,生产者与消费者模型是不是也是一个道理?
如果一个支付平台,每天只有10,000名用户,那么折合到一天的86,400秒,平均每秒收款和付款的操作都会是个位数,因此是一个很简单的问题,一台服务器足矣。
我们再来看看模块的组成,在整个Backend的架构中,需要一个对外的接口模块处理各种请求。如果简单实现,只需要在自己内部启动对用户数据进行简单的加减即可。
那么数据呢?一个简单的方法是使用MySQL的数据库,创建一个用户表。除了基本的用户信息外,保存用户当前的金额。当用户之间转账的时候,我们只需要使用事务来操作即可。
一个支付系统就是这么简单吗?
当然不是,一个理想中的支付系统是长这个样子的:
或者是这个样子呢?
我们有很多地方需要考虑,简单的罗列一下:
如何处理用户从银行转账的情况?
如果全球六十亿人每人给你转账一元钱,会发生什么?
如何让你的支付系统支持购买商品?
如何支持用户的积分系统,以及积分换金钱的功能?
有一天用户突然不能支付了,你觉得哪里出了问题?
全世界60亿人,平均一人给你钱需要2秒,也就是120亿秒,2亿分钟,330多万个小时,14万天,380年.恭喜你,过380年之后你就是亿万富翁,lz当时竟然无言以对。
全世界60亿人,平均一人给你钱需要2秒,也就是120亿秒,2亿分钟,330多万个小时,14万天,380年.恭喜你,过380年之后你就是亿万富翁,lz当时竟然无言以对。
如果短信是支付宝发的,按照短信网关2分钱一条(很便宜很便宜了)算,我们要付出2400万的短信费用…
假如假设都成立,那么「同时」12亿交易量是逆天的DDOS,比最近的双11都猛1000倍以上,在没有做提前准备的前提下,会把支付系统直接击垮,启动应急响应,而同时11T数据量更可以直接拖垮目前世界上任何一条主干网使其不可用。不过无论如何,写段子的人把2秒去乘以60亿是绝对错误的,一个人2秒,1万个人也是2秒。什么时候是瓶颈呢,CPU,存储,网络,都有可能成为瓶颈,阿里的架构是彻头彻尾的分布式,应用到服务器到网络都可以扩展,按我理解是没有单点的,只有供应商管理这块最难做,好在支付宝支付不用去网银,运营商扛住了的话,有提前准备的话,阿里应该能在不超过3个小时处理完这些交易队列。站在挑战人类极限的立场,能提高到多快,现在的分布式还能有多大的扩展空间,我不知道,再扩大10倍可能可以,再扩大100倍有可能就有阻碍。回答完了小题最后再来回答题干:转账请求到达服务器时,不管服务器垮没垮运营都必然会触发交易量异常报警,随后阿里会启动反洗钱流程,喜闻乐见地,这笔钱一分也拿不到,题中的“我”还会被带走。
一些关键点
耗时操作全部扔到队列里异步去执行
支付记录页面搜索数据区分冷热数据,三个月以内的数据作为热数据存mysql,更早的数据作为冷数据,除了移动到单独的表存储外,另外索引一份到搜索引擎提供检索功能
应对API接口高并发,1.限流。开发完成后根据线上环境的压测结果,设置单台机子接口的请求频率,避免引起整个业务线的雪崩。2.降级。针对超过限流的请求,直接把请求数据丢到队列里,用来削峰值流量,返回给调用方排队中的状态,然后队列处理完成以后回调调用方通知处理结果。
一些难点
系统强依赖消息队列服务来进行系统之间解耦和削峰。因此要保证消息的可靠性。其中需要开启消息的确认机制,队列和消息的持久化,尽量避免服务器宕机或者队列服务死掉时丢消息的情况出现。
关于一次请求或者说一次完整支付的生命周期内所经历的多种状态的设计和管理。比如接收申请,开始处理,风控核验,核验通过进入支付队列等待支付,支付申请已提交银行,银行返回的所有状态的处理。。。这些状态的细化。会是这个业务的复杂点
6.系统演进过程
以下可能是在这个项目的生命周期内,所要完成的迭代过程。
初级阶段,单节点服务(或者多节点服务,nginx做负载),多数据库节点,来扛量。根据业务增长情况,前期主要靠堆机子解决,在堆机子的同时,向中级阶段演进。
中级阶段,将系统瓶颈模块独立出来到单独的服务器上,在这些服务的入口处套上API网关,预期是KONG,利用API网关来做一些安全认证,请求限流,健康检查,熔断,日志,监控等基本功能。
高级阶段,将系统独立的模块拿go语言重写,独立成微服务来做。搭建微服务的底层基础设施,比如实现服务注册与发现,服务治理,服务监控等功能,正式过渡到微服务架构中来。
更高级一点,云原生应用阶段。微服务升级成服务网格。所有的微服务都删掉服务基础设施的代码,使业务代码轻量化。其他需要保证服务正常的非业务功能交由服务网格来管理。服务网格以边车的模式运行在每一个微服务的节点上,我们只用关心我们的业务代码,服务网格通过流量拦截帮我们解决服务之间的调度问题。
聚合支付:
原因:支付账户和银行账户垂直交叉
服务(>=):支付通道服务、集合对账服务、技术对接服务、差错处理服务、运行维护服务以及其他增值服务等服务内容
支付服务其实需要一套完整的业务系统,包括且不限于账务系统、账户系统、路由系统、风控/反欺诈系统、运营系统等,要为商户提供完整的“一站式”支付服务
企业级支付突围:
加强支付渠道能力,提供更完善的基础支付服务
拓展支付场景,提供场景下的支付解决方案:红包、打赏、平台分账、增值服务
提供安全稳定的支付服务
支付市场未来格局:
电子支付账户的多维化呈现不可逆转之势
利用自身的技术与服务集成能力,越来越多的技术供应商开始着眼于聚合支付领域
聚合支付的系统安全技术已日益成熟,让企业无论大小,都能获得安全、稳定、便捷的支付系统
支付系统的专业与商业
支付的商业化探索:
从功能到场景的转换:广告、粉丝经济、社区电商、平台类商城
支付场景的构建:账户体系、营销功能、层级管理、账务管理
收费服务:好的服务一定是需要利润支撑的、低价值的数据增长会对发展带来致命的影响、付费是对可从事商业模式的认可
从功能到场景的转变:
支付方式:网关、快捷、支付账户、信用分期;支付账户 和 银行账户
支付服务:身份认证、银行卡信息认证、海关报关、物流信息查询
场景:C2B2B、C2B2C、B2B2C、B2B2B;功能 -》组织成场景 -》用户黏性和付费意愿 -》创造交易
互联网的消费中,有很大比例的冲动型消费,通过优惠券可以有效的刺激用户的消费意愿
账户系统(应该具备):现金账户系统,卡券账户系统,支付系统和帐号系统
支付营销:
用户对于货币电子红包的接受度已经达到了 88.3% 的高度
没人再敢拿互联网的流量红利来说事了
不同行业支付系统设计
映客APP:
区别化对待的优惠机制:从优惠策略层面引导用户关注微信服务号,鼓励用户进行大额充值(还有首充)
微信红包提现(当时没有手续费)
设置不同账户出口:消费、提现
用兑换比例控制运营成本
紧扣用户消费线的经验值系统
教育行业:
互联已经形成,支付还会远吗?
体验机制:小额定金 / 免费试课;教育是一个双向选择、互相信任的过程;支付行为本身就能让平台的存在感骤增
饥饿营销:限量预售;让预售行为本身就带有自传播性
优惠券机制:打造口口相传的熟人效应;最重要的获客渠道之一
重线上,规范线下流程:线上专家、拜师,线下资质认证、退款保障等
社区 + 消费(母婴):
想法很美好,现实很骨感:市场大,但是做好难
先做社区,在做电商:打赏 -》 余额 -》 不能提现,只能消费
抱团:非标产品的促销与拼团机制结合起来
用会员制建立核心用户群:‘专家组’
旅游 app:
利用出行场景的周期性,增强消费转化:APP 的平均打开间隔和日启动次数可以看出其使用场景和用户特性
支持第三方支付账号登录
绑定渠道,争取渠道用户流量:‘银联专属’
利用互联网优势,打造消费体验生态链:优惠卡券前置,引导用户消费行为;多个账户体系,满足多样人群;加强支付环节体验设计
相关问题:
没有接查询接口进行支付结果确认
支付后执行的逻辑没有提取出来,在同步和异步函数中都写了一遍(DRY, Don’t repeat yourself )
支付后执行的逻辑全到写到支付 sdk 中,需要 sdk 自己判断支付场景(应该抽象出商户模式)
项目依赖 WEB_LIB 常量来加载第三方 sdk(短信、支付、二维码), 导致依赖没有统一管理. php 项目应当用好 composer 来管理依赖
数据库事务 是必须要加的,除了防止支付渠道的异步、同步同时到达,也要防止业务系统内部的并行操作
支付场景:
分期订单首付
还款
优惠券
支付方式交互字典:统一使用账务系统中记录的支付方式, 避免子系统见不统一
设计方案:独立出支付系统
支付系统当做支付渠道,包含一套 sdk 可以供业务系统使用,sdk 包括 4 部分内容:下单、同步、异步、查询
需要考虑 2 点:
支付网关前置、后置:采取后置,这样业务系统只用给支付系统发起请求,用户在支付系统提供的页面选择支付方式
支付后的逻辑由业务系统还是支付系统处理:支付成功后支付系统通知业务系统,由业务系统完成支付之后的逻辑
最终细化设计如下:
业务系统只用展示 ‘去支付’ 按钮,并传递相应支付参数和用户可以使用的支付方式给支付系统,支付系统验证后生成 PayOrder,支付系统按照业务系统传递的 order_no 进行去重
支付系统展示收银台(需要 设计 + 前端 支持)
根据用户选择的支付方式,调起支付渠道
接收支付渠道的同步和异步通知,解析出支付结果,更新 PayOrder 后转发给业务系统
对接支付渠道查询接口,异步通知业务系统结果
安全:和业务交互的接口都进行验签
支付流水记录:PayOrder 跟踪一笔支付单全部生命周期
支付系统前期工作:代码拆分,进行分层
分层设计
pay-gateway(支付网关) / pay-task(后台任务) -》pay-lib(支付公共库) -》php-lib(基础公共库)
确定 代码分层依赖关系 后,实现起来的难点主要在于一个接一个业务项目的 拆分 代码,并清理支付方式中的业务代码
支付系统网关 - pay-gateway
业务系统和支付系统API交互约定规则:
返回:json 格式,6 位 code + message,成功返回 000000,失败返回 28xxxx(支付系统错误码段)
验参:必填参数、参数长度(大部分参数会落地到存储层),返回第一条匹配失败的信息
验签:添加 sign 字段进行签名、验签
收单接口
业务系统向支付系统收单接口发起请求
支付系统收单接口 验参、验签、去重(商户号 + 订单号),验证通过后生成 支付流水记录(PayOrder)
展示支付方式给用户,用户选择后,通过支付渠道 sdk 调起支付
注意:只有一种支付方式时,直接通过支付渠道 sdk 调起支付,不显示支付方式选择页面
同步接口
支付系统接收到支付渠道的同步通知,通过支付渠道 sdk 获取支付结果,更新支付流水记录
支付系统跳转到业务系统下单时提供的 return_url,并带上支付信息
支付系统 - 异步接口
支付系统接收到支付渠道的异步通知,通过支付 sdk 获取支付结果,更新支付流水记录
支付系统向业务系统发送异步通知
查询接口
业务通过下单使用的单号,调用支付系统支付查询接口获取支付结果
业务系统和支付系统属于内网交互,可靠性更高,可以考虑不做
支付系统后台任务 - pay-task
查询支付渠道支付结果
通过支付 sdk 查询接口获取支付结果,更新支付流水记录
获取结果后向支付系统发送异步通知(需要和之前的异步通知进行去重处理)
数据层设计
增加 PayOrder 用来跟踪支付单
日志
增加专用支付日志, 打在关键节点上:
支付系统:收到业务系统下单请求、给支付渠道发送下单请求、支付渠道同步请求、支付渠道异步请求、调用支付渠道查询接口
业务系统:发起支付、同步通知、异步通知
支付系统伴随着电子商务的出现而出现,为各类电子商务经营活动实现在线收付款交易以及管理交易资金等功能,是具有一定独立性的内部系统模块。
平台:开展电子商务经济活动的主体。
业务系统:实现平台用户注册、商品定价、营销活动等相关功能。
平台与业务系统的关系:业务系统将用户购买行为通过各种交易订单的形式进行记录,并交付支付系统进行处理,最终由支付系统完成收款与付款。
根据央行的现行规定,人民币交易处理仅限于银行及第三方持牌支付机构,因此支付系统在实现上述功能时,需要通过外部银行、第三方持牌支付机构完成交易资金处理。因此,支付系统需要具备:
统一封装处理的交易接口,以对接外部交易渠道,为业务系统实现交易订单处理的功能。
根据业务系统设置的资金分配规则,在一笔交易有多个收款方参与的情况下根据资金分配规则完成交易资金的自动化清分与结算,而后通过已对接的外部交易渠道完成划付。
账务数据记录功能,上述的交易、清分、结算形成的资金变动信息,需要支付系统通过账务数据记录功能加以记录,对交易资金进行统计并完成交易资金核对等财会工作。
二、支付系统架构
支付系统的主要职责是处理业务系统发起的所有交易请求,包含收银台、交易系统、支付核心等模块,根据各模块不同的功能职责,可以将支付系统分为业务层和支付层两部分。
业务层负责为业务系统提供收付款的操作界面以及处理业务系统提交的交易请求;
支付层负责通过支付渠道实时处理完成资金的收付款、记录参与交易的账户间资金流转情况并按照预定规则对账户所属资金进行拆分与合并。
(1)收银台
收银台即用户日常付款前选择渠道的页面,是支付平台提供的基本功能之一,主要职责是协助业务平台完成支付交易,向用户提供一致的交易体验。一般情况下,根据不同终端类型定制标准化的收银台给到外部进行调用,保证各终端体验一致且针对各端特定需求、场景来展现不同的支付方式。
①收银台的业务场景(边界)一般分为付款与充值两部分:
付款即通过各类支付方式针对业务订单发起付款,例如:用户在天猫店购买一件衣服,确认订单后自动跳转至支付宝,引导用户选择对应的方式(余额、花呗、银行卡等)进行付款。
充值即用户对账户进行余额充值,例如:用户登录支付宝、微信或其他商户自有钱包系统对账户余额进行充值。
②支付渠道的服务模型,分为以下几个要点:
服务模型的概念:从支付公司角度来看,服务模型是决定商户可以使用的交易形式(担保收单、即时到账等)、支付产品(快捷、网银、代扣、POS 等)、签约方式、阶段周期(T+0、T+1、T+N 等)以及费率等核心问题的综合体;
从电商平台角度来看,电商公司内部使用的支付系统与支付机构相比复杂度较低,可通过参考支付公司服务模型,梳理不同业务、不同交易类型、不同结算周期以及不同支付渠道等复杂需求,搭建合理且满足业务需求的服务模型,例如充值类交易,具有商城属性的业务可配置担保收单或即时到账等交易类型。
服务模型的维度:
行业/服务维度:即从业务角度出发对支付产品进行划分。
例如:蚂蚁金融面向行业输出交易、结算、会员、安全等服务,且为不同的服务等级划定标准,贯穿所有内部系统;普通非支付公司(以电商为例),提供即时到账、担保收单等,基本上能满足大多数的业务场景。
商品维度:针对不同行业的交易标的,由于交易价格、成本与利润差异大,因此在业务层面不同的支付渠道要有不同的可用性标准。
一般情况下,商品本身与市场或行业挂钩,例如喜马拉雅在接入微信/支付宝时,业务所在行业为视频影音属于虚拟商品,因此接入费率为 1%,结算周期为 T+7。
由此可得,支付公司针对不同商品本身的特性(例如风险等因素)在费率和结算周期上会进行一定的控制;同时,针对高风险行业会在支付方式、渠道层进行限制。
市场维度:此处「市场」指的是指引客户使用支付产品服务的场所,它可能是支付产品本身,亦可能为相关公司或平台的网站。例如某集团子公司、某公司投资的公司以及与该公司无关的外部公司等等,可分为集团、内部以及外部等维度。
客户维度:此处「客户」指的是服务的具体使用者。可分为个人客户及企业客户,通过支付系统内的会员系统进行区分。
付款方维度:付款方在整个业务过程中未核心角色,针对付款方用户的特征应建立以支付渠道收款方维度的模型,例如付款方的账户模型、安装是否正式、证书等级等要素都决定着付款方的付款流程。
支付渠道维度:在电商平台,跳转到支付系统是,收银台根据付款方的参数规则,进而对该笔支付在收银台内可使用的支付渠道进行选择。例如充值账户余额不允许使用信用卡时,收银台在付款方付款时仅可展现借记卡等支付方式,喜马拉雅在于支付宝等第三方支付公司交互式,下单接口里一般含有做借贷分离的参数,该参数起到的作用就是可以指定付款方即用户不可使用借记卡或信用卡。
业务渠道维度:业务端使用的入口,代表着客户或者业务方和支付系统的交互方式。例如通过 PC 端跳转到收银台、通过 App 跳转到收银台以及纯接口形式跳转等等。
支付渠道各类配置:
渠道配置:抽象收银台支付方式大类(第三方、网银储蓄卡、网银信用卡、信用类(花呗、白条)等),对应每个大类下配置对应的落地渠道,再分别对适用场景进行匹配( App、H5、PC 端、公众号等等),不同的场景下应对应不同的支付方式。
渠道参数配置:在业务进行中根据公司的具体情况,部分业务可能独立运营,因此在独立运营过程中财务需要就独立业务传入各支付渠道对应的密钥及商户 ID 等关键参数信息,以满足业务方需要支付系统根据不同商户信息调用对应渠道收款主体的需求。
(2)交易系统
交易系统本身是作为支付系统外部处理业务逻辑的外围系统。由于支付核心系统本身并非面向业务端且业务逻辑的多变性与复杂性,支付系统为了兼顾稳定并能够为业务端提供灵活支持,因此需要在支付系统外层搭建面向业务端处理交易逻辑的交易系统。交易系统处理业务端的各种交易类型后,将业务信息转化为支付系统可识别的支付订单并导入。
以担保交易为例,C 端用户在天猫购买一件商品,成功支付后商家进行发货,用户确认收货后平台将货款结算给商家。此处设计到「担保交易支付」以及「确认收货」环节,与支付系统内部的支付与结算步骤一一对应:
用户付款成功后对应交易的付款成功状态;
用户确认收货后对应交易的成功状态。
从支付和收货缓解可以看出,担保收单交易就是讲支付系统的支付基础能力包装后对外支持业务的一款产品。
交易系统的职责:
交易系统作为支付系统的入口:
首先需要对接上层业务系统;
其次将支付系统的支付能力抽象出来,对外提供各类交易方式,例如下单、支付、修改金额、确认结算、退款、关闭交易以及查询等能力;
最后,交易系统需要对各种交易类型进行定义,例如担保交易、即时到账、充值、提现等类型。
交易系统的场景(边界):
下单:生成交易订单,确定交易参与;
退款:针对已支付的订单进行退款,退款金额不得大于实际支付金额,积分的退款退回原积分账户,同时针对退款交易类型,会生成交易订单号,关联入款订单;
修改金额:修改交易金额,对应生成新的支付订单;
查询:查询交易结果、支付结果;
通知:通知上层业务系统交易状态;
算费:通过算费子系统计算每笔订单的手续费。
交易系统的交易类型:
即时到账交易:买家在电商平台选择购买商品下单,付款成功后金额直接入卖家支付账户或者卖家银行账户;
担保收单交易:买家在电商平台选择购买商品下单,有部分金额为担保金额,买家付款成功后,担保部分进入平台方中间担保账户,未担保金额直接入卖家支付账户或者卖家银行账户;
收单退款交易:买卖双方在达成退款协议后,可针对及时到账交易,订金下定等已支付交易由商户平台发起退款请求;
普通转账交易:当平台方需要对会员进行转账时,通过此接口实现金额的转移;
合并支付交易:多笔交易订单合并(并笔)付款,适用于购物车针对不同商家生成订单的场景;
下订交易:卖家和买家达成购买协议,先行支付部分订金,该部分订金在最终付款的时候可以被使用;
提现:客户将支付账户的余额提到客户绑定的银行卡账户,基于支付账户单笔或者批量付款;
冻结解冻:在交易前通过冻结能力将用户的部分资金冻结,保障交易能正常进行,也可以由于某些原因(账户被盗、司法案件、反洗钱等),冻结用户资金操作,保证用户的资金安全;
充值:基于支付账户做余额充值,将用户的银行卡账户资金充到用户的支付账户余额。
交易系统的交易特性归类:
①实效性:
全额实时到账:即时到账类交易,付款后实时到账;
部分确认支付、部分即时到账:担保收单类交易,这里分为部分担保的场景,只有指定金额部分需要确认结算;
全额确认支付:全额担保交易,电商交易场景下需用户确认收货后才会将全部货款结算给卖家。
②交易系统的支付形式:
单笔支付交易:单笔支付行为,用户基于一笔订单发起付款;
合并支付交易:多笔合并支付行为,用户基于多笔订单发起合并付款;
③业务类型:
收单交易:支付入款类型交易,付款人收款人分别是两个角色;
充值交易:账户充值类交易,付款人和收款人都是同一个人,由外部账户到内部账户;
出款交易:基于账户做提现,付款人和收款人都是同一个人,由内部账户到外部账户;
退款交易:收单入款交易的反向流程。
(3)会员系统
会员系统是完整的支付平台内极其重要的基础模块之一,负责管理支付系统内部的交易主体。会员系统保存了客户在支付系统内部账号的实体信息,为客户建立了统一的、以会员 ID 为标识的会员基本信息、关系信息(会员和账户、会员和操作人、会员与银行卡)视图。
一般情况,会员在支付系统内部分为个人会员和企业会员(默认企业会员有商户权限),以电商平台为例,C 端用户为个人会员,B 端商户为企业会员:
通常,企业会员会配置一定的业务参数,比如结算周期、接口权限、支付方式配置等(开通商户权限的情况下);
在大多数互联网公司,支付系统仅需要对接支付渠道的模块,在没有独立平台化的情况下,不太会出现需要独立的账户体系。
(1)支付核心
下方的内容介绍了支付核心的职责、边界以及系统架构三个部分。
支付核心的职责:
支付系统的职责为通过支付核心与后端清结算、会计、账务等系统的统一协作,让前端支付产品可以更关注产品本身的逻辑,而减少对清分、对账、储值等后端服务的考量及动作;同时通过标准化的支付指令定义,统一前端支付产品的支付请求接口,提供适应各类产品使用的基础支付服务。
支付核心的边界:
支付服务:负责对后端支付系统的接口进行业务包装,同时实现使用多个支付方式进行组合支付的功能;
支付服务流程:对各支付类型的支付服务流程进行定义,具体定义为充值、提现、内转支付(转账)、退款等原子类型,并实现对基础服务的流程编排;
支付指令:发起订单后,通过协议和协议明细项加工得出支付指令,需具备进行后续操作处理的全部要素信息;
支付协议:根据产品设立支付协议,因此支付协议的关键要素包含产品码及支付编码,定义着产品的处理流程、收付款信息、对应的支付渠道信息。
支付核心的系统架构:
将交易和支付分开,主要是为了体现出支付系统的核心支付功能,能够为会员提供丰富的支付服务:支付核心定义原子支付类型;服务层提供支付业务能力,例如出款、转账、红包、代金券、余额、现金等;产品层能够更加关注产品本身的逻辑,将后端标准化的逻辑交由支付层和清算层来处理,这样就能做到灵活和标准兼顾。
(2)账务核心
账务核心的功能为,根据前端业务系统的要求设计相匹配的账户类型、管理各类账户、记录账户资金变动等,同时,按照公司内部的财会规范提供反映各账户间交易资金变化情况的会计数据;并且负责将自身记录账务流水与支付渠道结算资金和结算流水进行核对,对对账结果中出现的差错交易进行差错处理。
(3)清算核心
清算核心负责维护客户参与交易时的清分、结算规则,并按照已配置的规则完成交易资金的清分与结算操作。