大厂最佳实践 | Stripe 如何防止重复付款
为什么扣了我两笔钱?
2010年,美国加利福尼亚州的两兄弟打算创办一家公司,但他们发现建立网上支付十分困难。于是,他们决定开发一款在线支付服务,并将其命名为Stripe。

随着用户数量的不断增长,重复付费问题逐渐显现。所谓的重复付费指的是对同一笔交易错误地向用户收取了两次甚至多次费用。可能造成重复付费的原因很多,下面看一种典型的场景。
当客户端发送一个请求后,服务器已成功处理该请求。但在返回响应给客户端之前,由于网络故障导致响应没有成功发送给客户端。

但是客户端不知道请求已被成功处理,它只要没收到响应,就当作请求处理失败,因此就会重试,这种情况下就会出现重复付款。
除此之外,框架的一些重试机制同样会导致重复付费。
幂等 API
为了解决重复付费问题,他们决定采用最简单也是最有效的解决方案:他们决定将API设计成幂等的。
幂等 API可以保证同一个请求可以重试多次且不会产生副作用。这意味着即使经过多次重试,这些请求也只会被处理一次。Stripe 实现幂等 API 的方式如下:
1.幂等key
幂等key是一个唯一的标识符,用来标识每一次请求。通过使用幂等key,服务器可以识别出同一个请求,即使这个请求被重复发送多次,也只会处理一次。
客户端(比如用户的浏览器或手机应用)发起支付请求时,会生成一个唯一的字符串作为幂等key。这个字符串通常是一个UUID(通用唯一标识符)。此后客户端发送请求时需要将这个key随请求的 HTTP 头部一起发送。
POST /pay
Idempotency-Key: 123e4567-e89b-12d3-a456-426614174000
Content-Type: application/json
{"amount": 100,"currency": "USD","card_number": "4111111111111111","expiry_date": "12/23","cvv": "123"
}

服务端接收到请求后,先检查这个幂等key是否已经存在于数据库(或缓存)中,如果不存在,说明这是一个新的请求,服务器处理请求,并将幂等key和响应结果一起缓存在数据库中(如Redis)。如果幂等key存在于数据库中,说明这个请求之前已经被处理过了。服务器直接返回缓存中的处理结果,而不再重复处理。
如果服务器在处理请求时发生错误,他们会使用ACID数据库的事务回滚功能来撤销交易。幂等性key会在内存数据库中保留24小时(这个时间根据自己业务确定),以便在这个时间段内可以重试失败的请求。过了24小时后,幂等性key会被移除,这样可以减少存储成本,并允许在这个时间段后重复使用同一个key。
为了帮助您理解,我再举一个更具体的例子,假设你正在用Stripe支付一笔费用,但由于网络问题,没有响应回来,你以为付款失败了,于是你就重新点击了一次支付按钮。
-
第一次请求:服务器生成一个幂等性键 12345,并处理这个请求。请求成功后,响应会被缓存,并且幂等性键 12345 被存储在内存数据库中。
-
第二次请求:由于你不确定第一次是否成功,所以又发了一次请求。这次请求带着相同的幂等性键 12345。服务器查询内存数据库,发现这个请求已经处理过,因此直接返回缓存的响应,而不会再次处理请求。
2. 重试失败的请求
虽然使用幂等key之后,重试变的安全了,不会造成重复付费问题了,但是过多的重试请求可能会导致服务器过载。

因此系统重试使用了指数退避算法:每次重试之间的等待时间会逐次增加。
此外,为了防止大量客户端同时发起重试请求,导致服务器过载。还在指数退避的基础上给重试等待时间增加了随机时间,这称为抖动。
为了更好的理解指数退避算法和抖动,举两个例子来说明。
示例1:指数退避
第一个例子是用来解释指数退避算法,假如你在用Stripe支付,但服务器暂时不可用,导致请求失败。
- 第一次请求失败:系统等待1秒后重试。
- 第二次请求失败:系统等待2秒后重试。
- 第三次请求失败:系统等待4秒后重试。
- 依次类推,等待时间逐次增加。
示例2:抖动
这个例子是用来解释抖动。假设有很多用户同时在用Stripe支付,服务器暂时不可用。
- 用户A的请求失败后,系统会根据指数退避算法等待一段时间,然后加上一个随机的额外等待时间。例如,第一次等待1秒加0.5秒的随机时间(总共1.5秒)。
- 用户B的请求失败后,系统等待1秒加0.3秒的随机时间(总共1.3秒)。
- 用户C的请求失败后,系统等待1秒加0.7秒的随机时间(总共1.7秒)。
由于加入了抖动,不同用户的重试时间就会有所不同,这样可以防止服务器在同一时间受到大量重试请求的冲击,从而减轻服务器的压力,防止过载。
幂等性对于可靠的在线支付至关重要。它给系统带来了安全性和更好的用户体验。Stripe,作为全球最大的在线支付服务提供商之一,正是通过这样的方法确保其支付系统的可靠性和稳定性。
相关文章:
大厂最佳实践 | Stripe 如何防止重复付款
为什么扣了我两笔钱? 2010年,美国加利福尼亚州的两兄弟打算创办一家公司,但他们发现建立网上支付十分困难。于是,他们决定开发一款在线支付服务,并将其命名为Stripe。 随着用户数量的不断增长,重复付费问题…...
Raspberry Pi Pico 2 上实现:实时机器学习(ML)音频噪音抑制功能
Arm 公司的首席软件工程师 Sandeep Mistry 为我们展示了一种全新的巧妙方法: 在 Raspberry Pi Pico 2 上如何将音频噪音抑制应用于麦克风输入。 机器学习(ML)技术彻底改变了许多软件应用程序的开发方式。应用程序开发人员现在可以为所需系统整…...
安全自动化和编排:如何使用自动化工具和编排技术来提高安全操作效率。(第二篇)
深入理解Kubernetes环境中的安全自动化与编排(第二篇) 1. 引言 Kubernetes作为现代容器编排平台的主流选择,正在被越来越多的企业用于部署和管理其容器化应用。在Kubernetes环境中实施安全自动化与编排,既能够提升系统的安全性&…...
HarmonyOS WebView
HarmonyOS WebView Web组件提供基础的前端页面加载的能力,包括加载网络页面、本地页面、html格式文本数据。Web组件提供丰富的页面交互的方式,包括:设置前端页面深色模式,新窗口中加载页面,位置权限管理,C…...
解决elementUI表格里嵌套输入框,检验时错误信息被遮挡
1.表格 自定义错误信息显示div <el-form-item label"租赁价格" prop"supplierId"><el-table-column prop"salePrice" label"销售价" align"center"><template slot-scope"scope"><el-form-…...
Unity读取Android外部文件
最近近到个小需求,需要读Android件夹中的图片.在这里做一个记录. 首先读写部分,这里以图片为例子: 一读写部分 写入部分: 需要注意的是因为只有这个地址支持外部读写,所以这里用到的地址都以 :Application.persistentDataPath为地址起始. private Texture2D __CaptureCamera…...
【5.3 python中的元组】
5.3 python中的元组 Python中的元组(Tuple)是一种用于存储多个项目(可以是不同类型)的序列数据结构,但它与列表(List)不同,主要区别在于元组是不可变的(immutable&#…...
Debezium报错处理系列之第116篇:Caused by: java.lang.NumberFormatException: null
Debezium报错处理系列之第116篇:Caused by: java.lang.NumberFormatException: null 一、完整报错二、错误原因三、解决方法Debezium从入门到精通系列之:研究Debezium技术遇到的各种错误解决方法汇总: Debezium从入门到精通系列之:百篇系列文章汇总之研究Debezium技术遇到的…...
【启明智显技术分享】工业级HMI芯片Model3C/Model3A开发过程中问题记录笔记二
一、Model3C/Model3A芯片介绍 Model3C/Model3A是启明智显针对工业、行业以及车载产品市场推出的一款高性能、低成本的工业级HMI(Human-Machine Interface,人机界面)芯片。两颗芯片硬件PIN TO PIN;区别在于内置的PSRAM大小不同。该…...
Python 函数返回yield还是return?这是个问题
如果你刚入门 Python,你可能之前没有遇到过yield。虽然它看起来很奇怪,但它是你编码工具库中的一个重要工具。在成为 Python 大师的道路上,你必须掌握它。 返回列表的函数 假设有一个函数,它可以一次性生成一系列值,…...
Linux系统性能调优
Linux系统性能调优是一个复杂而细致的过程,涉及硬件、软件、内核参数、进程管理等多个方面。以下将从多个角度详细介绍Linux系统性能调优的技巧,旨在帮助用户提升系统的运行效率和稳定性。 一、硬件层面的调优 内存升级: 增加物理内存可以减…...
PHPStorm 环境配置与应用详解
大家好,我是程序员小羊! 前言: PHPStorm 是 JetBrains 出品的一款专业 PHP 集成开发环境(IDE),凭借其智能的代码补全、调试功能、深度框架支持和前端开发工具,为用户提供了丰富的功能和工具…...
前端各种文本文件预览 文本编辑excel预览编辑 pdf预览word预览 excel下载pdf下载word下载
前端各种文本文件预览 文本编辑excel预览编辑 pdf预览word预览 excel下载pdf下载word下载 各种文本文件预览(pdf, xlsx, docx, cpp, java, sql, py, vue, html, js, json, css, xml, rust, md, txt, log, fa, fasta, tsv, csv 等各种文本文件) 其中 除p…...
【Qt】QPluginLoader 类学习
文章目录 一、简介二、常用方法2.1 构造函数2.2 动态加载方法——load()2.3 检查是否加载成功——isLoaded()2.4 访问插件中的根组件——instance()2.5 卸载插件——unload() 一、简介 QPluginLoader 类在运行时加载插件。 QPluginLoader 提供对Qt插件的访问。Qt插件存储在共享…...
DataGear 企业版 1.2.0 发布,数据可视化分析平台
DataGear 企业版 1.2.0 已发布,欢迎体验! http://datagear.tech/pro/ 企业版 1.2.0 修复严重漏洞,新增文件源管理模块,新增JWT统一登录支持,MQTT数据集主题支持通配符,具体更新内容如下: 新增…...
为啥https比http慢
Https有ssl的握手 HTTP没有 HTTPS TCP 和HTTP 的TCP 时间差不是很大 HTTPS请求中,ssl所占的时间比例是请求时间总和93.37%, HTTPS请求中,ssl的请求会是tcp请求的14倍,而HTTP中没有这个问题 建议:对安全要求不是很高的,不要使用https请求 图例...
软件测试需要具备的基础知识【功能测试】---后端知识(三)
您好,我是程序员小羊! 前言 为了更好的学习软件测试的相关技能,需要具备一定的基础知识。需要学习的基础知识包括: 1、计算机基础 2、前端知识 3、后端知识 4、软件测试理论 后期分四篇文章进行编写,这是第三篇 …...
详解 Redis 队列 实现
Redis 是一个高性能的键值存储系统,它的多种数据结构使其能够以不同方式实现队列,包括普通队列、延时队列和异步队列的介绍和示例。 介绍 Redis 的 List 数据结构可以用来实现普通的队列。 生产者使用 LPUSH 或 RPUSH 命令将消息添加到列表的头部或尾部…...
分析SQL的count(*)并优化
最近优化过几个慢查询接口的性能,总结了一些心得体会拿出来跟大家一起分享一下,希望对你会有所帮助。 我们使用的数据库是Mysql8,使用的存储引擎是Innodb。这次优化除了优化索引之外,更多的是在优化count(*)。 通常情况下&#…...
Java学习日记(day18)
一、软件的结构 C/S (Client - Server 客户端-服务器端) 典型应用:QQ软件 ,飞秋,印象笔记。 特点: 必须下载特定的客户端程序。服务器端升级,客户端升级。 B/S (Broswer -Server 浏览器端- 服务器端&a…...
既然有 HTTP 协议,为什么还要有 RPC?
HTTP 和 RPC 都能解决网络通信问题,但它们的设计初衷和适用场景截然不同。简单来说,HTTP 是为了通用性和跨平台设计的(像万能的集装箱),而 RPC 是为了极致的性能和开发效率设计的(像工厂内部的高速流水线&a…...
链式前向星:高效图存储的进阶指南
1. 为什么需要链式前向星? 当你第一次接触图论算法时,可能会被邻接矩阵和邻接表搞得晕头转向。我刚开始学图论的时候,就经常在这两种存储方式之间纠结。邻接矩阵写起来简单,一个二维数组就能搞定,但当节点数超过10000时…...
WSABuilds旧版本归档:如何获取v2311及更早版本安装包
WSABuilds旧版本归档:如何获取v2311及更早版本安装包 【免费下载链接】WSABuilds Run Windows Subsystem For Android on your Windows 10 and Windows 11 PC using prebuilt binaries with Google Play Store (MindTheGapps) and/or Magisk or KernelSU (root solu…...
亚洲美女-造相Z-Turbo惊艳案例分享:高还原度旗袍/汉服/都市职场风人像生成
亚洲美女-造相Z-Turbo惊艳案例分享:高还原度旗袍/汉服/都市职场风人像生成 最近在玩一个挺有意思的AI模型,叫“亚洲美女-造相Z-Turbo”。这名字听起来有点技术范儿,但说白了,它就是个专门生成亚洲女性人像的AI工具。 你可能用过…...
阅读书源校验工具verifyBookSource v2.0避坑指南:如何避免无效书源和重复书源
verifyBookSource v2.0 高效书源管理实战:从校验到优化的完整指南 在数字阅读日益普及的今天,一个优质的书源库能显著提升阅读体验。然而,面对海量书源,如何快速筛选有效内容、剔除重复资源,成为许多阅读爱好者的痛点。…...
视频解析工具:高效获取无水印视频的技术实践与生态构建
视频解析工具:高效获取无水印视频的技术实践与生态构建 【免费下载链接】douyin-downloader 项目地址: https://gitcode.com/GitHub_Trending/do/douyin-downloader 在数字内容创作与研究领域,视频资源的高效获取已成为基础需求。然而平台访问限…...
仅剩最后23套田间网关固件兼容包!Python农业物联网部署必备的8个设备驱动补丁(含Raspberry Pi 5专用版)
第一章:田间网关固件兼容包的农业物联网部署意义 在农业物联网(Agri-IoT)规模化落地过程中,田间网关作为边缘侧核心枢纽,承担着多源异构传感器数据汇聚、协议转换、本地决策与上云协同等关键职能。然而,我国…...
别再纠结在线辨识了!聊聊永磁同步电机(PMSM)离线参数自学习的完整流程与避坑指南
永磁同步电机离线参数辨识实战:从理论到工程落地的全流程解析 在电机控制领域,参数辨识一直是个让人又爱又恨的话题。尤其是当项目从实验室走向量产时,那些在仿真中运行良好的算法,往往会因为实际电机参数的偏差而表现失常。我曾亲…...
SpringBoot 接口全维度性能优化指南
文章目录: 前言 一、背景 1.1 为什么必须做 SpringBoot 接口优化? 1.2 接口优化的核心目标 1.3 本文适用范围 二、核心原理 2.1 接口请求全流程(瓶颈定位核心) 2.2 核心优化原理总览 2.3 优化优先级(生产环境…...
SDMatte在电商场景落地:商品主图自动去背景+透明PNG生成完整工作流
SDMatte在电商场景落地:商品主图自动去背景透明PNG生成完整工作流 1. 电商场景中的图像处理痛点 在电商运营中,商品主图的质量直接影响转化率。传统处理方式面临三大难题: 人工成本高:专业设计师处理一张图平均耗时15-30分钟边…...
