如何构建自己的支付系统

Posted 凉茶方便面

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了如何构建自己的支付系统相关的知识,希望对你有一定的参考价值。

文章目录

业务场景

在电商网站以及其他服务性质的网站中,一般都需要自己的支付平台,以能够提供二维码支付、网银支付等功能。另外,除了能够进行支付以外,支付平台还要提供退款、对账等功能

对于支付功能而言,业务方需要告诉支付渠道对应的支付参数,而支付宝等渠道会根据参数生成支付页,供用户扫码支付。对于退款,支付渠道会要求业务方追溯原始的支付单,而且,退款不是任意时间都可以进行的,对于支付宝退款期限一般是支付时间内三个月,而微信、银联等渠道一般支持一年内的退款。对于对账,支付渠道会提供对账和支付单的查询接口,返回的结果可能是 json 或者 excel 文件,业务方可以根据自己的需求进行对应的解析处理,将其结构化存储。进行对账时,可以将对账文件的内容根据支付记录进行对照。

本文主要是介绍如何通过一种通用的方式构建自己的支付平台,该支付平台能够对接诸如,支付宝、微信、银联、百度钱包等第三方支付渠道。

名词解释

第三方渠道:指支付宝、微信、银联、度小满等第三方金融平台;

业务方:指自己的业务模块;

支付单:支付单分为两,渠道支付订单号和商户订单号,其中渠道支付订单号是第三方渠道生成的订单,而商户订单号是业务方自己生成业务的标识,进行外部对账以渠道支付订单号为准,进行内部对账时,以商户订单号为准;

退款单:与支付单对应,它会与原始支付单存在关联。

模块划分


如图所示(仅展示了支付逻辑),整个系统分为两个大模块:业务方和第三方渠道。

业务方承担的责任

  1. 存储第三方渠道支付地址、第三方需要回调的地址、与第三方约定好的加密密钥、对应的加密规则等信息;
  2. 接收用户请求,并根据用户请求的支付金额和内部存储的支付数据进行加密,并构建支付参数;
  3. 返回加密后的支付参数给业务方前端;
  4. 业务方前端根据支付参数,进行页面跳转和数据提交,从而进入第三方支付页;

第三方渠道的责任

  1. 接收业务方的支付请求,并根据业务方参数进行解密鉴权、以及根据参数中的回调地址进行回调;
  2. 接收业务方的退款请求;
  3. 对业务方提供对账单下载 api 等功能。

需要特殊说明的有三点:

  1. 业务方提交支付参数给第三方的逻辑除了通过 ajax 返回参数,由前端跳转的方式外,也可以直接在 body 中返回带有 javascripthtml 文件,直接跳转;
  2. 数据加密,一般支付渠道的文档都会单独提供数据加密章节,说明加密密钥的生成和配置,对于生成的私钥,最好是在本地加密存储,避免被外部攻击并被直接获取;
  3. 回调是一种异步的操作,当用户在第三方支付页扫码支付完成后,业务方无法感知支付结果,因此需要第三方渠道进行异步的回调。各种渠道的回调频率和回调要求也不太一样,不过大体是回调会发生在支付行为的24小时内,对于回调响应,有得渠道要求在 body 中返回 success,有的渠道要返回对应的 xml,具体的要参考对应的文档;

关于加密规范的说明

微信支付安全规范:https://pay.weixin.qq.com/wiki/doc/api/native.php?chapter=4_3
支付宝密钥配置章节:https://opendocs.alipay.com/open/291/105971

关于回调的说明

a. 支付宝异步回调说明和规范地址:https://opendocs.alipay.com/open/270/105902

程序执行完后必须打印输出“success”(不包含引号)。如果商户反馈给支付宝的字符不是 success 这7个字符,支付宝服务器会不断重发通知,直到超过24小时22分钟。一般情况下,25小时以内完成8次通知(通知的间隔频率一般是:4m,10m,10m,1h,2h,6h,15h);

b. 微信异步回调说明和规范地址:https://pay.weixin.qq.com/wiki/doc/api/native.php?chapter=9_7&index=8

后台通知交互时,如果微信收到商户的应答不符合规范或超时,微信会判定本次通知失败,重新发送通知,直到成功为止(在通知一直不成功的情况下,微信总共会发起多次通知,通知频率为15s/15s/30s/3m/10m/20m/30m/30m/30m/60m/3h/3h/3h/6h/6h - 总计 24h4m),但微信不保证通知最终一定能成功。

c. 银联异步回调说明和规范地址:https://open.unionpay.com/tjweb/acproduct/list?apiSvcId=449&index=3

(1)前台交易,下单后间隔0、1、2、4、8、16分钟发起查询,查到交易失败或者交易不存在就继续查,查到成功停止查询,第32分钟还没成功判定失败。另外也可在请求里加上payTimeout字段设置超时的时间,超过设置的时间就判定失败。
(2)后台交易,在收到同步应答后间隔0、1、2、4、8、16、32秒发查询,查到成功或失败状态、或者收到后台通知时停止查询。查到第64秒还是无结果的话(一般不会发生),等对账文件生成后再根据对账文件处理。

由此可以看出银联的异步回调时间相对较短,进行业务开发时,需要谨慎处理。

业务流程

模块划分只是对业务模块之间的交互逻辑和需要关注的点进行了简要描述,本节会对各个细分场景进行详细说明,指出其中的业务细节。

支付


支付的逻辑在文章最开始也已经做了部分的说明,本节将更详细的进行说明。

支付的流程一般是:支付由用户发起,直接请求业务方,业务方根据自身存储的 appId,加密私钥,回调地址等参数生成返回数据,并由前端跳转第三方支付界面。用户需要在第三方支付页面完成支付,支付完成后,第三方支付渠道会根据业务方提交的回调地址进行前台回调,该回调地址最好是业务方后端,因为这是用户支付完成之后的同步结果,根据该结果,业务方可以设置支付状态,设置完成后,可以页面跳转至支付成功页。

这里需要说明下前台回调,前台回调是即时通知业务方用户支付结果的方法,收到该回调,可以直接检查支付单在第三方的支付状态,并将本地的支付单设置为支付成功。

而后台回调相当于定时任务在进行处理,算是一种兜底方案,另外对于某些支付可能只有后台回调,因此后台回调的接收页非常有必要。

另外需要注意的是,业务方可以接收一些前端信息,如对于下单支付而言,前端希望用户支付完成后跳转到订单列表页,就可以将订单列表的 url 交个业务方后端,在第三方渠道进行前台回调时,根据支付单 id 查询到原始支付信息,并根据该 url 将页面重定向至订单列表页。

微信二维码支付

微信二维码支付对应微信支付渠道里的 Native 支付,根据 Native 支付的官方文档:https://pay.weixin.qq.com/wiki/doc/api/native.php?chapter=6_3,目前有两种实现方式:生成固定产品的二维码(由后台配置回调地址),由客户扫一扫后通过回调业务方生成支付单;业务方生成2个小时有效期的二维码给客户扫描(提供回调地址),客户扫一扫后,回调业务方,业务方更新支付单状态。

微信二维码扫描的逻辑和其他渠道的支付逻辑差别较大,但是也可以通过改造实现通用的支付逻辑。如,当用户支付,跳转第三方页面时,改为跳转静态支付页,并将参数填写至 url 中,动态获取二维码地址,并后台生成二维码。之后的逻辑就和其他支付渠道的逻辑类似,用户支付完成后,根据最初后台生成二维码时向微信提供的回调地址进行回调。

退款


退款逻辑相对简单:用户发起退款,业务方收到请求后,查询本地的支付记录,根据支付记录构建参数,同步调用第三方渠道进行退款。

需要注意的地方有两点

  1. 本地支付记录是用户的原始支付信息,退款时需要关联该信息。因此一般的做法是,按照用户的支付记录按照时间倒排,对 top N 个支付记录进行退款(需满足用户指定的金额),因此这里会存在部分退款的情况;
  2. 部分渠道的退款是同步操作,部分退款是异步操作,一般发起退款请求到第三方后,第三方会校验退款参数,并将校验结果返回给业务方,业务方可以等待第三方渠道定时进行后端回调(退款时指定了该接口地址),也可以本地使用定时任务定时获取第三方退款单的状态。当然也可以认为发起退款后,第三方渠道校验返回成功时就认为退款完成了,但是这会导致用户的钱未到账时,平台的退款状态就已经是已完成了;
  3. 支付宝部分细分渠道的退款是按照当前已支付的支付单退款的总金额进行返回的,因此在进行核对时,需要自行加总本地已退款的金额和本次退款的金额和回调金额进行对比。

对账

对账逻辑更加简单,一般是本地支付服务起单独的线程,每天定时跑任务从支付渠道下载对账文件,然后将对账文件进行解析,并存储至数据库。为了方便追溯,避免导入错误的数据,应该尽可能的将原始对账文件存储至文件存储服务。至于具体的对账文件的格式和解析方案可以参考对应的渠道文档。

除了文件下载外,还可以进行额外的对账,比如支付系统和财务系统的对账,对支付系统的实际支付、退款记录对比财务系统中的记录,比较二者的差异。另外还可以增加人工对账,避免实际资金流水和支付系统的数据不一致。

避坑指南

  1. 支付功能不是个人用户能够申请的,需要是企业用户;
  2. 支付系统一般在内网,要访问外网最好通过 nginx 代理,并增加服务白名单,避免非法的端口扫描;
  3. 支付系统的数据最好和用户的资金数据做好分离,对于譬如退款类的业务,一笔退款可能对应多笔原始支付,此时如果数据混杂在一起,不利于业务拓展。

原文地址:https://mp.weixin.qq.com/s?__biz=MzUzNTk0MDU5MQ==&mid=2247483697&idx=1&sn=1c6adda3819148bf547c7ed77e227cba&chksm=fafc9db1cd8b14a7ecccee0a7092a849251af08d53b3ad86854d7be7d727cc55cfd5ce47218b&token=1571158946&lang=zh_CN#rd

欢迎关注我的公众号:我的搬砖日记,我会定时分享自己的学习历程。

以上是关于如何构建自己的支付系统的主要内容,如果未能解决你的问题,请参考以下文章

如何构建延迟任务调度系统

如何做一个对账系统

如何做一个对账系统

如何做一个对账系统

电商积分支付系统构建经验与总结

财务对账系统设计