当前位置: 首页 > news >正文

电商项目之同一笔单多次收款成功

在这里插入图片描述

1 问题背景

有个收单系统(简称S系统),作用是收单,相当于支付渠道,能够作为第三方服务对接其他支付平台。电商系统(简称A系统)与S系统是隔离的。A系统发起支付请求给S系统,S系统包装一下(AB站逻辑)再发起支付请求给Stripe。Stripe系统处理完逻辑后会跳回到发起支付时传过去的returnUrlreturnUrl到达的前端页面会通过js代码发起请求(假设请求路径是/pull/pay/result)给S系统,S系统会拉取支付结果。如下图所示:

在这里插入图片描述

问题出现在步骤4,导致A系统的订单状态无法及时翻转。买家看见未支付成功,就第二次发起支付,导致Stripe后台出现了同一笔单多次收款成功。

这个问题,在买家角度去看,核心是支付结果没有及时翻转。在卖家角度去看,买家后续会发起拒付,导致卖家的收款账号被封的可能性提高。

2 前言

本篇为笔者遇到的真实案例

3 S系统的设计初衷

S系统设计的初衷是为了保护商家的收款账号不被封(业务是做不发货业务),因此S系统暂时没有做webhook订阅(如果要做,要做好ab逻辑),导致无法及时从Stripe拿到订单的支付结果,只能依靠自己主动查询。因此在订单状态翻转这块无法100%保证时效性。

由于业务类型不同,S系统在设计之初就做了重点倾斜。针对不发货业务,核心是保护收款账号,收到款就行。针对仿品、普货这些业务,核心是订单状态的翻转,因为卖家要发货。

S系统无法同时兼顾两类不同的业务,必须要有所倾斜。

4 思考产生问题的原因

分别从业务角度、技术角度去分析产生问题的原因(产生bug的场景),并思考对应的解决方案

业务上:

  1. 客户做什么业务?仿品、普货属于都要发货的类型;不发货业务是属于不发货的类型。如果是不发货类型,由于要保护收款账号从而没有接入webhook及时反转订单状态,因此在时效上无法100%保证翻转订单状态。因此,如果是做仿品、普货的业务,无法保证及时翻转订单状态。如实告知客户系统设计如此,建议客户采用另外的收款渠道,而不是采用S系统

  2. 客户投放什么国家?因为问题的核心是没有调用到S系统的接口,是否存在网络问题,导致调不通?需要询问客户投放什么国家,因为S系统没有做全球加速,可能会存在某些国家访问S系统失败。

技术上:

  1. webhook是否有发送成功?可以做个重试机制发送webhook,但必须限制最大发送次数。

  2. 主动拉取支付结果的延迟消息是否生效?根据排查结果,买家发起第一次支付会投递1个延迟时间为10min的消息给MQ,而买家在4min后又发起支付并且支付成功了。而等到MQ开始消费时,买家已经支付完并成功了。因此,我们可以降低延迟时间,比如1min,并且在消费时如果还是拉取到未支付成功,可以再投递一个延迟时间为3min、5min的MQ(查询频率递减)

5 解决方案

  1. 如实跟客户阐述S系统的设计初衷,并将风险告知。(如订单状态无法及时翻转)
  2. 如果是由于网络问题导致流程图中的步骤4 调用/pull/pay/result/报错,需要询问客户投放的国家,看看该国家是否与S系统之间存在网络问题,根据情况 让运维加入全球加速,但是经济成本会增加。
  3. 针对异步延迟拉取支付结果,可以提高拉取频率,或降低延迟时间
  4. 做一个定时调度,将当天内待支付的订单,每隔1min都拉取支付结果
  5. 实现同一笔订单不能支付多次,这样就杜绝Stripe后台出现同一笔单多次收款成功
  6. 针对流程图中的步骤4 调用/pull/pay/result/,前端页面引入监控机制(监控前端页面在调接口的时候是否报错了),但是项目经济成本会提升。同时调用改接口可以加入重试机制。

5 总结

发生生产级别的问题,先不要慌,要从业务角度、技术角度思考什么场景会导致该问题发生?有解决方法吗?运用任何数据去分析排查并结合现有情况给出解决方案。处理问题的方法论见电商项目之处理生产级别问题的方法论。

相关文章:

  • OpenFeign总结
  • 【Linux】基础IO --- 系统级文件接口、文件描述符表、文件控制块、fd分配规则、重定向…
  • 计算机网络01_---软考高级系统架构师010
  • 【Linux】冯诺依曼体系结构与操作系统概念理解
  • 【c语言进阶】枚举与联合体的基本知识大全
  • Python与Matlab混合编程案例
  • 排列的时候如何避免重复?
  • 芒果改进YOLOv5系列:原创结合Conv2Formers改进结构,Transformer 风格的卷积网络视觉基线模型,超越ConvNeXt结构
  • 利用Windows系统服务进行权限提升
  • WebAssembly编译之(2)-Ubuntu搭建WASM编译环境
  • InstanceNorm LayerNorm
  • yolo结构介绍
  • 最详细、最仔细、最清晰的几道python习题及答案(建议收藏哦)
  • C语言:数组
  • Python装饰器使用方法详解
  • Android 架构优化~MVP 架构改造
  • Angular 响应式表单之下拉框
  • iBatis和MyBatis在使用ResultMap对应关系时的区别
  • JavaScript函数式编程(一)
  • mysql外键的使用
  • React-Native - 收藏集 - 掘金
  • SegmentFault 2015 Top Rank
  • SpiderData 2019年2月25日 DApp数据排行榜
  • Theano - 导数
  • Webpack入门之遇到的那些坑,系列示例Demo
  • WebSocket使用
  • windows下使用nginx调试简介
  • 给自己的博客网站加上酷炫的初音未来音乐游戏?
  • 构建二叉树进行数值数组的去重及优化
  • 机器学习 vs. 深度学习
  • 理解IaaS, PaaS, SaaS等云模型 (Cloud Models)
  • 前端技术周刊 2018-12-10:前端自动化测试
  • 如何利用MongoDB打造TOP榜小程序
  • 如何使用Mybatis第三方插件--PageHelper实现分页操作
  • 腾讯视频格式如何转换成mp4 将下载的qlv文件转换成mp4的方法
  • MiKTeX could not find the script engine ‘perl.exe‘ which is required to execute ‘latexmk‘.
  • [Shell 脚本] 备份网站文件至OSS服务(纯shell脚本无sdk) ...
  • 整理一些计算机基础知识!
  • ​2021半年盘点,不想你错过的重磅新书
  • ​ssh-keyscan命令--Linux命令应用大词典729个命令解读
  • ​猴子吃桃问题:每天都吃了前一天剩下的一半多一个。
  • ###项目技术发展史
  • #中国IT界的第一本漂流日记 传递IT正能量# 【分享得“IT漂友”勋章】
  • $NOIp2018$劝退记
  • (aiohttp-asyncio-FFmpeg-Docker-SRS)实现异步摄像头转码服务器
  • (M)unity2D敌人的创建、人物属性设置,遇敌掉血
  • (附源码)springboot电竞专题网站 毕业设计 641314
  • (一) springboot详细介绍
  • (原創) 系統分析和系統設計有什麼差別? (OO)
  • (转)LINQ之路
  • .NET 6 在已知拓扑路径的情况下使用 Dijkstra,A*算法搜索最短路径
  • .net core使用ef 6
  • .net framework 4.0中如何 输出 form 的name属性。
  • .NetCore部署微服务(二)
  • /deep/和 >>>以及 ::v-deep 三者的区别