在线支付——如何防止订单重复支付?

【金三银四】每日一点面试题(Java--场景篇):如何防止订单重复支付的? 1、支付订单增加一个中间状态“支付中”,当同一个订单去支付的时候,先检查有没有状态为“支付中”的支付流水,当然支付(prepay)的时候要加个锁。2、支付中心这边要自己定义一个超时时间(比如:30秒),在此时间范围内如果没有收到支付成功回调,则应调用接口主动查询支付结果,比如10s、20s、30s查一次,如果在最大查询次数内没有查到结果,应做异常处理。支付成功以后,异步通知支付中心,支付中心更新自身支付订单状态,再通知业务应用,各业务再更新各自订单状态。这个时候有可能产生投诉,或者用户重复支付。 阅读详情

看看订单支付流程

我们来看看,电商订单支付的简要流程:

image.png

订单钱包支付流程

从下单/计算开始:

  1. 下单/结算:这一步虽然不是直接的支付起点,但是支付相关的金额等等信息都来自结算,此时订单的状态是未支付
  2. 申请支付:用户选择申请支付,客户端调用支付服务,此时在系统内产生一笔支付流水,这笔流水的状态是未支付
  3. 发起支付:支付服务调用三方支付,通常这种钱包类的支付,在发起支付这一步,会响应一些支付的链接,客户端会对链接进行对应的处理。
  4. 钱包支付:用户进行支付,通常是通过对应的钱包进行的,大家可以回忆一下自己在购物中,支付的过程,不同的端,对钱包支付的处理是不太一样的:京东PC端支付页
  5. APP端: 在国内,购物大部分都是在APP端,产品经理会想法设法把用户带到APP,为什么我的示例图都用京东,不用淘宝呢?因为我拿UC打开淘宝,会直接跳转APP。APP端的钱包支付,我们应该都非常熟悉,一般是拉起钱包,支付。APP支付
  6. WAP端:手机的网页站,WAP端的支付一般是直接拉起对应的钱包,如果拉起钱包失败,就跳转界面京东支付WAP端
  7. PC端:PC端,通常是打开收银台,展示一个二维码,通过钱包扫码支付,下面是京东的微信支付扫码页
  8. 支付回调:用户完成支付后,三方支付平台,会回调商户,通知支付结果。
  9. 同步订单状态:支付服务在确认支付完成后,会向订单服务同步支付的结果,订单服务变更订单的状态,由未支付-》待发货,客户端通过轮询、长连接,或者服务端主动推送的方式,在界面上变更订单状态。

我们再从支付流水的角度看一下支付状态的变化:

image.png

支付状态变化

  • 从未支付,到有支付结果的终态,中间还有一个中间状态支付中
  • 用户通过打开钱包--》完成支付--》支付回调,这段时间的支付流水就处于支付中

为什么要花这么多篇幅来讲支付的业务流程、交互过程呢?因为我认为,防止订单的重复支付,不止是技术上的问题,也是业务和产品上的问题。

为什么订单会重复支付

未防重导致的重复支付

我们可以看到PC端支付,是扫描二维码,这些二维码,就是对应相应的支付流水,假如用户重复点击支付,如果不做防重的的话,会生成两笔支付流水,也就是两个不同的二维码,要是用户分别扫了两个不同的支付码,那么毫无疑问,就会产生重复支付。

掉单导致的重复支付

“我明明付款了,为什么我的订单还没支付呢?”

image.png

黑我钱是吧

这就是所谓的“掉单”:

  • 外部掉单:三方支付的支付状态没有同步或者没有及时同步到商城,这叫外部掉单
  • 内部掉单:支付服务的状态没有同步到订单,或者客户端没有及时获取到订单状态,这叫内部掉单。

用户一看,自己付了款,结果商城里订单还未付款,但是又特别想要,可能就会再下一单,这样就重复支付了。

多渠道导致的重复支付

我们国内支付的体验还是非常快捷的,大家可能没有感觉,如果了解过海外支付的可能了解,很多支付的渠道,消耗的时间非常长。

比如用户保罗选择了一种支付方式Boleto,结果支付的网点离保罗他们村太远了,保罗又选择了Paypal支付,保罗去赶集的时候,又顺手去网点把Boleto的这一笔支付了,结果就重复支付了。

这种情况大家可能很少遇到,我们可以用美团下一个单,先打开微信支付,不要支付啊,接着回到美团,打开支付宝,用支付宝支付完成后,用微信接着支付,大家猜猜,两笔支付是不是都能成功?答案是可以。

image.png

美团多渠道支付

如何防止订单重复支付

加锁

不管是3.申请支付、还是5.支付回调,都应该以订单维度加锁,防止并发下的重复操作。

加锁,毫无疑问,也是分布式锁,通常我们会选择Redis分布式锁。

加锁

 

缓存结果

申请支付成功,支付回调成功,都应该缓存结果。

再申请支付,收到成功回调的时候,都应该先去检查支付的状态。

image.png

在这里插入图片描述

支付中流水取消

假如说,用户重复支付了,再次申请支付的时候,如果已经申请支付成功了,那么这笔支付肯定是要拒绝的。

但是,要是已经存在的这笔流水还在支付中呢?——我们不确定它是成功还是失败,肯定是不能拒绝支付的,因为可能用户支付失败了,但是状态还没同步,这样肯定是不行的。

所以,我们可以取消掉正在支付中的流水,再进行支付。

image.png

支付中流水取消

已支付流水退款

现在又有新的问题了,假如发起支付的时候,有流水正在支付中,如果第三方支付平台不支持取消支付,或者用户新的支付是通过不同的渠道,我们希望尽可能提高用户的支付成功率,怎么办呢?

我们可以在发起支付的时候,订单还在支付中的情况下,允许用户发起多笔支付,在支付回调的时候,检查用户是否已经有成功流水,对后来的流水进行退款处理。

image.png

支付回调

当然,退款是个很危险的操作,毕竟钱退了,可就很难追回来,一定要做好风险的控制。

主动轮询&重试防止掉单

主动轮询防止外部掉单

如果因为故障没有收到回调,或者没有及时收到回调,就可能会发生所谓的外部掉单。

防止外部掉单的关键,就在于,不能傻傻地只等三方的回调通知,而要主动去查询,用户发起支付的3s之后,就可以发起轮询了,直到拿到支付流水的最终状态,主动轮询,一般可以这么实现:

image.png

轮询

  • 定时任务轮询使用定时任务,扫描表中支付中的流水,主动查询支付的状态,定时任务的实现方式有很多,线程池、调度框架、分布式调度框架等等。定时任务轮询的缺点有两个:
  • 对数据库有一些压力,观察监控,会发现定时任务扫表的时候,有时候会造成数据库的一些“峰刺”
  • 不便调整频率,实际上,用户发起一笔支付之后,一般都会在10s-1min中完成支付,越往后,用户完成支付,所以轮询梯度进行,会更合理一些,轮询的间隔可以设置成类似这种:3s,10s,30s,3min……
  • 延时消息轮询另外一种方式就是使用延时消息,用户发起支付之后,发送一个延时消息,消费到延时消息之后,查询流水支付状态,没有拿到最终状态,就再发一个延时消息。延时消息的好处是对数据库的压力没有那么大,轮询的梯度也可以进行控制,缺点是实现起来复杂一些,而且要维护消息队列。

同步+异步防止内部掉单

支付服务在收到异步通知回调、或者主动轮询到流水的最终状态后,要通知订单服务支付流水的变化,订单服务同步更新订单的状态,这个过程要尽可能保证通知成功,可以采用同步+异步的方式。

  • 同步调用:支付服务调用订单服务的通知接口,有可能会因为网络等等的原因失败,也可以重试,但是根据经验,如果网络出现一些波动,重试很可能也会失败。
  • 异步通知:支付服务还应该发送一个支付成功的消息,订单服务可以利用消息队列的重试机制,来尽可能保证支付状态的同步。

这里还有一个问题,客户端如何同步这个状态?因为可能服务端更新了订单状态,但是客户端的界面上还是未支付,得用户主动刷新一下,才能拿到最新的状态,这样明显是不太合适的。

服务端、客户端的状态同步,无非就拉和推:

  • 拉:很简单,就是客户端在用户跳回订单状态页的时候,轮询一会,如果用户完成支付,通常很短时间就能获取到状态的变更,当然这种方式对客户端的性能会有一些影响,而且很出现状态同步“漏网之鱼”的情况。
  • 推:推的实现有些麻烦,Web通常是用Websocket,对APP端的推送,一般采用第三方的推送平台。

客户端支付尽可能不外跳

不管从产品的角度,还是技术的角度,客户端发起支付这一步,其实应该尽可能地不要外跳,PC端使用支付服务生成的支付码,而不是跳转;移动端网页、APP在应用内展示支付页,当然这个是由第三方支付平台决定的。

image.png

在UC内内嵌支付宝

不知道大家留意到了没有,现在的支付宝,已经做到了不用拉起钱包,在应用内就可以完成支付,这个对于商家的意义还是比较大的,对用户体验、支付成功率,都有正面的作用,相信以国内的内卷程度,其它支付供应商,一定会“跟进”的。


好了,关于如何防止重复支付,就讲到这里。对于支付,老三也只是初窥门径,希望各位大佬不吝指教。

初学订单-支付流程(思路) 订单支付流程思路 使用沙箱支付接口 阅读详情

相关推荐

大聪明教你学Java | 在支付模块中如何防止掉单和重复支付

最近大聪明加入了一个智慧运输平台建设的项目组(下面就简称运输平台),在运输平台中除了运输板块的功能以外,最重要的就是支付模块的功能,毕竟涉及到了金钱💴的交易,所以要尽可能的做到万无一失。关于支付模块的功能,我们经常听到两个问题“掉单”和“重复支付”,他们都是支付过程中的大问题,我们也要尽可能的避免此类问题的出现。那么今天大聪明就和大家分享一下,如何有效的在支付模块中避免出现“掉单”和“重复支付”的问题。

不肯过江东丶 2826

如何防止重复下单

系统异常时 666 请求到了,单号更成 666,接着 888 请求到了,单号又更新成 888,但是 666 更新成功的响应丢了,调用方没收到成功响应,自动重试,再次发起 666 请求,单号又被更新成 666了,这数据显然就错了!更新订单服务,通过一个版本号机制,每次更新数据前校验版本号,更新数据同时自增版本号,这样的方式,来解决 ABA 问题,确保更新订单服务的幂等性。创建订单服务,可通过预生成订单号,然后利用 DB 的订单号唯一约束,避免重复写入订单,实现创建订单服务的幂等性。最简单的:DB 事务。

qq_38470315的博客 3127

7步揭秘大厂如何防止订单重复支付:技术策略与实践

在电商和在线支付日益普及的今天,订单重复支付成为了一个常见的问题。用户在支付过程中可能会因为网络延迟、操作失误等原因多次提交支付请求,导致订单被重复支付。这对商家来说不仅会造成经济损失,还可能引发用户的不满和信任危机。通过本文的详细介绍,你应该已经明白了大厂是如何防止订单重复支付的。唯一订单号生成:确保订单的唯一性。订单状态管理:记录订单状态,防止重复支付。支付中间状态:使用锁确保支付的原子性。超时处理:主动查询支付结果,确保及时更新订单状态。异步通知与接口幂等性:保证接口的幂等性,忽略重复通知。

java专栏 1025

java项目中,如何解决用户重复提交订单进行支付

支付模块为防止用户重复下单购买套餐做唯一标识进行防重处理。具体实现逻辑:当用户点击购买发起选购套餐时,后台支付服务通过UUID中的randomUUID方法生成唯一标识和套餐信息一起带到前端同时使用map集合存入后台(使用用户id作为键,每个用户之间数据互不影响),用户选好套餐后点击支付按钮后,会发起订单支付请求,控制层会前端带有的唯一标识是否与后台用户存储的标识相同,相同的话进入支付界面,同时清除后台存储的唯一标识,不同则提示用户请勿重复下单!,如图所示:

czg724218的博客 1386

SSM框架集成支付宝支付功能实战教程

SSM(Spring + SpringMVC + MyBatis)框架是Java Web开发领域内的重要工具集合,它将企业级应用开发中经常用到的几个组件无缝整合,以提供更为高效和规范的开发方式。它包括了Spring的依赖注入和事务管理特性、SpringMVC的前端控制器模式,以及MyBatis的数据库访问对象(DAO)实现。通过这种整合,开发者可以更加专注于业务逻辑的实现,而将常见的非功能性需求交由SSM框架来管理。

weixin_34779181的博客 981

小白学电路之cadance搭建buffer电路

Buffer(缓冲器)是一种放大器或驱动电路,主要用于隔离输入和输出,以防止负载对前级电路造成干扰或影响。本文作者在电路方面是小白水平,目前正在学习,有不足之处欢迎指正。3.创建新的cellview,对此buffer进行仿真验证。2.创建buffer的symbol。电路中的V2的详细参数。

weixin_58051657的博客 1988

如何防止订单重复支付?

大家好,我是老三,想必大家对在线支付都不陌生,今天和大家聊聊如何防止订单重复支付。

三分恶的博客 2277

Voxel Hashing技术解析:如何解决TSDF内存爆炸问题?

本文深入解析Voxel Hashing技术如何有效解决TSDF内存爆炸问题。通过动态内存分配和空间哈希函数设计,该技术将内存占用降低96.6%,同时保持高精度重建。文章详细介绍了GPU加速实现、现代系统演进及实践指南,为实时3D重建提供工程解决方案。

m2n3b4v5c6的博客 713

服务端如何防止订单重复支付?

上一篇:深夜看了张一鸣的微博,让我越想越后怕来源:废物大师兄地址:www.cnblogs.com/cjsblog/p/14516909.html如图是一个简化的下单流程,首先是提交订单,然...

emprere的博客 146

ARM架构UOS实战:从源码编译Qt 5.15.2到定制Qt Creator的全流程解析

本文详细解析了在ARM架构统信UOS系统上,从源码编译Qt 5.15.2到定制Qt Creator开发环境的完整流程。内容涵盖环境准备、依赖部署、源码配置、编译优化、错误处理及IDE集成,旨在帮助开发者在国产化平台上构建自主可控的高性能Qt开发环境,解决特定ARM平台的兼容性与性能优化问题。

mango的博客 411

【面试题】MySQL索引相关的面试题(红黑树,hash,B树,B+树)

自己整理了几个面试题分享给大家 问题1:红黑树为什么那样设计? 首先聊一下二叉搜索树,主要特点是左节点比根节点小,右节点比根节点大,并且左右子树都是二叉搜索树。缺点是在极端情况下,比如插入都是有序的,就会出现退化的情况有序序列树退化成链表。 二叉搜索树 退化成链表的二叉搜索树 此时,要想让树的节点平均分布就需要平衡树了,红黑树就是平衡树的一种(平衡二叉搜索树)。然后,一棵树的查询性能取决...

Mr_黑_ 的博客 4044

服务端如何防止订单重复支付

概述 如图是一个简化的下单流程,首先是提交订单,然后是支付。 支付的话,一般是走支付网关(支付中心),然后支付中心与第三方支付渠道(微信、支付宝、银联)交互。 支付成功以后,异步通知支付中心,支付中心更新自身支付订单状态,再通知业务应用,各业务再更新各自订单状态。 这个过程中经常可能遇到的问题是掉单,无论是超时未收到回调通知也好,还是程序自身报错也好。 总之由于各种各样的原因,没有如期收到通知并正确的处理后续逻辑等等,都会造成用户支付成功了,但是服务端这边订单状态没更新。 这个时候有可能产生

HY1273383167的博客 515

C# 上位机 YOLO 实战:从数据采集到目标识别的全流程拆解

本文以工业螺栓缺陷检测为例,完整拆解了C#上位机+YOLO从数据采集到目标识别的全流程。数据采集:保证图像质量,线程安全采集,必要时归档数据;预处理:适配YOLO模型输入格式,复用对象减少内存开销;推理解析:正确解析张量结果,过滤低置信度目标;落地环节:可视化展示结果,实现工业交互和日志记录。

这里只有干货:从 Modbus 通信到 MES 对接,从 YOLO 训练到工控机部署,带你搞定工业软件开发全流程。 1454

如何防止订单重复支付

我们可以看到 PC 端支付,是扫描二维码,这些二维码,就是对应相应的支付流水,假如用户重复点击支付,如果不做防重的的话,会生成两笔支付流水,也就是两个不同的二维码,要是用户分别扫了两个不同的支付码,那么毫无疑问,就会产生重复支付。不知道大家留意到了没有,现在的支付宝,已经做到了不用拉起钱包,在应用内就可以完成支付,这个对于商家的意义还是比较大的,对用户体验、支付成功率,都有正面的作用,相信以国内的内卷程度,其它支付供应商,一定会“跟进”的。:很简单,就是客户端在用户跳回订单状态页的时候,轮询一会。

qq_38470315的博客 5369

基于 STM32 的智慧图书馆智能控制系统设计与实现

智慧图书馆智能控制系统集成环境调控、安全监控、借阅管理与信息推送功能,通过 STM32 主控芯片联动传感器、执行器及云平台,实现图书馆智能化管理。系统架构分为感知层(传感器)、控制层(STM32 主控)、执行层(继电器 / 显示屏)及云端层(数据交互),支持温度自动调节、灯光自控、火情安防监控、天气推送及 RFID 借还书管理。本系统通过 STM32 实现多传感器融合与设备控制,结合 RFID 与云平台技术,构建了集环境智能调控、安全监控、便捷借阅于一体的智慧图书馆解决方案。

weixin_42300449的博客 2203

DeepLabv3+改进专栏

🔥【DeepLabv3+改进专栏!探索语义分割新高度】🌟 你是否在为图像分割的精度与效率发愁?📢 本专栏重磅推出:✅ 独家改进策略:融合注意力机制、轻量化设计与多尺度优化✅ 即插即用模块:ASPP+升级、解码器。

AIcurator的博客 2576

支付安全:大厂如何防止订单重复支付的揭秘

在如今数字支付横行的时代,我们常常在购物、服务支付等场景中使用在线支付。然而,你可曾想过,背后的支付系统是如何确保你的订单不会被重复支付,保障交易安全的呢?本文将带你深入了解大厂是如何通过巧妙的设计和多层次的防护机制来避免订单重复支付的。

Karka_的博客 2174

ROS2 Nav2 - 模型预测路径积分控制器(MPPI)

这是一个预测控制器(局部轨迹规划器),用于实现模型预测路径积分(MPPI)算法,以跟踪具有自适应避障功能的路径。它包含基于插件的 critic 函数,可影响算法的行为。它由 Aleksei Budyakov 创建,由 Steve Macenski 为 Nav2 进行改编和开发。该插件实现了 nav2_core::Controller(控制器)接口,可在整个导航堆栈中作为控制器服务器的动作服务器(controller_server)中的局部轨迹规划器使用。据测定,该控制器可在中等英特尔处理器(第四代 i5)上

机器人控制与仿真应用 3909

支付安全:大厂如何防止订单重复支付的揭秘_订单系统 防重复支付

在如今数字支付横行的时代,我们常常在购物、服务支付等场景中使用在线支付。然而,你可曾想过,背后的支付系统是如何确保你的订单不会被重复支付,保障交易安全的呢?本文将带你深入了解大厂是如何通过巧妙的设计和多层次的防护机制来避免订单重复支付的。

baimao__Ch的博客 1729

汉书HE8,好用的汇编代码编写工具

汉书HE8,好用的汇编代码编写工具早期编写汇编代码所用功能强大

Statistics and Machine Learning Toolbox

Statistics and Machine Learning Toolbox(带书签),MATLAB统计学习工具

上一篇: 阿里的24W字Java面试复盘指南,GitHub已标星80k
下一篇: 耗时半月,给大家搞来了今年上半年碰到的大厂Java面试题合集
跟着我学Java
博客等级 码龄6年 660粉丝 1341原创
评论 1
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值