基于有限状态机与消息队列的三方支付系统补单实践

翠墨
• 阅读 548
作者:字节跳动技术团队
链接:https://juejin.cn/post/690332...
  1. 引言

======

在日常生活中,从线下的超市购物到线上的外卖点餐、电商网购等,支付无时无刻不在发生,不论是通过现金、pos 机刷卡还是微信支付宝等第三方支付。线上支付有着及时便捷一气呵成的极致体验,当然也有少数的时候体验不够丝滑,比如早期我们在 PC 版 12306 买火车票,当支付完成后,订单的支付状态却经常不能及时更新,会有一段时间的延迟,有时甚至会等待很长时间处在未支付状态。

在支付的过程中由于各种各样的原因(比如外部渠道处理出了问题,异步回调迟迟不来)导致流程走了一半停了下来,用户看到订单依然是未支付状态,会不知所措,此时就需要一种机制来推动完成这笔交易。本文就以三方支付系统中的补单机制为例,来介绍一种较为通用的单据补偿模式。

  1. 三方支付系统简介

============

1.1 什么是三方支付

所谓第三方支付,就是和各大银行签约,独立于商户和银行,具备一定实力和信誉保障的,为商户与消费者提供支付结算服务的第三方独立机构。它是处于买方和卖方之间具备公信力的第三方,承担担保人和资金托管人的角色。三方支付也可以称为虚拟账户支付,由消费者在第三方支付机构开设虚拟账户,并用虚拟账户中的资金进行支付。业界常见的三方支付有支付宝、微信支付、美团支付、京东支付等等。

1.2 三方支付中的交易&支付系统

交易是什么,最直观的描述就是“一手交钱、一手交货” ,交易会使买卖双方形成债权和债务关系。交易的存在是支付发生的前提,用户通过使用某种支付方式去完成交易。交易是支付流程的驱动者,根据具体场景组合不同的支付指令,来完成交易资金的转移。

支付是交易处理资金流的工具,目的是清偿债权和债务关系;支持多种支付方式(如银行卡支付、余额支付、优惠券组合支付、类似花呗的信用支付等),负责对接账务、会计、计费系统等资金处理能力,接收支付指令,驱动完成资金交换。将实际的支付行为(实际资金)与内部的记账(虚拟资金)相结合,保证虚实一致。

三方支付整体业务架构如图 1 所示,其中交易核心与支付核心在业务划分上处于"收单支付域",具备普通交易的收款、付款、退款及充值、转账与提现等常见功能,还包括了支撑电商业务的合单支付、担保与分账的能力。其中交易与支付核心都有一个异常查补模块,它囊括了所有业务的补偿流程,也是本文主要介绍的部分。基于有限状态机与消息队列的三方支付系统补单实践基于有限状态机与消息队列的三方支付系统补单实践基于有限状态机与消息队列的三方支付系统补单实践基于有限状态机与消息队列的三方支付系统补单实践基于有限状态机与消息队列的三方支付系统补单实践基于有限状态机与消息队列的三方支付系统补单实践基于有限状态机与消息队列的三方支付系统补单实践基于有限状态机与消息队列的三方支付系统补单实践基于有限状态机与消息队列的三方支付系统补单实践基于有限状态机与消息队列的三方支付系统补单实践基于有限状态机与消息队列的三方支付系统补单实践基于有限状态机与消息队列的三方支付系统补单实践基于有限状态机与消息队列的三方支付系统补单实践基于有限状态机与消息队列的三方支付系统补单实践基于有限状态机与消息队列的三方支付系统补单实践基于有限状态机与消息队列的三方支付系统补单实践

图 10. 异常补偿体系

  1. 总结

======

本文首先介绍了什么是补单,接着基于三方支付系统的实现完整阐述了补单机制的演进过程,最终演化为一种相对通用的异常处理模式,即基于消息队列、有限状态机与多重任务兜底的业务层最终一致性保障机制,供大家参考指正。

推荐阅读:

字节跳动总结的设计模式 PDF 火了,完整版开放分享

刷Github时发现了一本阿里大神的算法笔记!标星70.5K

如果能听懂这个网约车实战,哪怕接私活你都可以月入40K

为什么阿里巴巴的程序员成长速度这么快,看完他们的内部资料我懂了

程序员达到50W年薪所需要具备的知识体系。

关于【暴力递归算法】你所不知道的思路

看完三件事❤️

如果你觉得这篇内容对你还蛮有帮助,我想邀请你帮我三个小忙:

点赞,转发,有你们的 『点赞和评论』,才是我创造的动力。

关注公众号 『 Java斗帝 』,不定期分享原创知识。

同时可以期待后续文章ing🚀

点赞
收藏
评论区
推荐文章
blmius blmius
4年前
MySQL:[Err] 1292 - Incorrect datetime value: ‘0000-00-00 00:00:00‘ for column ‘CREATE_TIME‘ at row 1
文章目录问题用navicat导入数据时,报错:原因这是因为当前的MySQL不支持datetime为0的情况。解决修改sql\mode:sql\mode:SQLMode定义了MySQL应支持的SQL语法、数据校验等,这样可以更容易地在不同的环境中使用MySQL。全局s
美凌格栋栋酱 美凌格栋栋酱
7个月前
Oracle 分组与拼接字符串同时使用
SELECTT.,ROWNUMIDFROM(SELECTT.EMPLID,T.NAME,T.BU,T.REALDEPART,T.FORMATDATE,SUM(T.S0)S0,MAX(UPDATETIME)CREATETIME,LISTAGG(TOCHAR(
Easter79 Easter79
3年前
thinkcmf+jsapi 实现微信支付
首先从小程序端接收订单号、金额等参数,然后后台进行统一下单,把微信支付的订单号返回,在把订单号发送给前台,前台拉起支付,返回参数后更改支付状态。。。回调publicfunctionnotify(){$wechatDb::name('wechat')where('status',1)find();
Stella981 Stella981
3年前
React Hooks实现异步请求实例—useReducer、useContext和useEffect代替Redux方案
<blockquote本文是学习了2018年新鲜出炉的ReactHooks提案之后,针对<strong异步请求数据</strong写的一个案例。注意,本文假设了:<br1.你已经初步了解<codehooks</code的含义了,如果不了解还请移步<ahref"https://reactjs.org/docs/hooksintro.html
Wesley13 Wesley13
3年前
Java面试
<divclass"htmledit\_views"id"content\_views"<pid"maintoc"<strong目录</strong</p<pid"Java%E5%9F%BA%E7%A1%80%EF%BC%9Atoc"style"marginleft:40px;"<ahref"Java%E5%
Stella981 Stella981
3年前
DOIS 2019 DevOps国际峰会北京站来袭~
DevOps国际峰会是国内唯一的国际性DevOps技术峰会,由OSCAR 联盟指导、DevOps时代社区与高效运维社区联合主办,共邀全球80余名顶级专家畅谈DevOps体系与方法、过程与实践、工具与技术。会议召开时间:2019070508:00至2019070618:00结束会议召开地点:北京主办单位:DevOps
Stella981 Stella981
3年前
RabbitMQ 消息中间件搭建详解
1.RabbitMQ简介消息中间件也可以称消息队列,是指用高效可靠的消息传递机制进行与平台无关的数据交流,并基于数据通信来进行分布式系统的集成。通过提供消息传递和消息队列模型,可以在分布式环境下扩展进程的通信。RabbitMQ是使用Erlang语言开发的开源消息队列系统,基于AMQP协议来实现。AMQP的主要特征是面向消息、队列、路由(包
Wesley13 Wesley13
3年前
mysql数据库的查询
1、“查”——之单表查询INSERTINTOstudent2(name,grade,gender)VALUES('songjiang',40,'男'),('wuyong',100,'男'),('qinming',90,'男'),('husanniang',88,'女'),('sunerniang',66,'女'),('wus
Stella981 Stella981
3年前
Python数据结构与算法——双端队列Dequeue
!(https://oscimg.oschina.net/oscnet/fa1ed5efabdf40f390081750e73ed60e.png)点击上方蓝字关注我们双端队列Dequeue双端队列是一种有序的数据集,与队列相似,但双端队列的两端都可以作为队首
Stella981 Stella981
3年前
DevOps世界中的软件开发
!(https://oscimg.oschina.net/oscnet/f40e68cbfe8148deb00f040b4e917a0a.jpg)在整个软件开发过程中,开发人员通常需要花费大量时间来修复错误和漏洞,以便一切按计划进行交付。但是,通过DevOps实践,可以更轻松地管理和保护这些问题。这是由于以下事实:使用DevOps实践的软
Easter79 Easter79
3年前
SwiftUI 跨组件数据传递
作者:Cyandev,iOS和MacOS开发者,目前就职于字节跳动0x00前言众所周知,SwiftUI的开发模式与React、Flutter非常相似,即都是声明式UI,由数据驱动(产生)视图,视图也会与数据自动保持同步,框架层会帮你处理“绑定”的问题。在声明式UI中不存在命令式地让一个视图变成xxx