api接口幂等

1,213 阅读4分钟

前端

置灰按钮

禁止多次点击提交按钮。

弹出提示框

在移动手机端,基本都是跳转到支付成功页面,但是pc电脑端,一般都是弹出一个提示框,有两个按钮1.支付成功,完成支付2.支付失败,因为异常。

为什么手机端是直接跳转成功页面,而电脑是弹出提示框,因为手机屏幕比较小,弹出提示框,不好操作。电脑屏幕比较大。

但是,本质作用都是一样,就是为了避免重复点击提交按钮,避免停留在当前页面但是因为刷新当前页面导致重复提交请求。

跳转到成功页面

即支付成功之后,跳转到支付成功页面。而不是一直在提交支付页面,因为可能会多次点击提交按钮。

还有可能是刷新页面,导致多次请求。当然,一般情况下,请求数据都是post提交。如果是get提交,那么就可能导致刷新当前页面的时候,重复提交。所以,如果跳转到成功页面,那么即使刷新当前页面,也没有关系。

这里的跳转成功页面,不是说真的支付成功,而是针对你的提交支付操作,已经成功了。具体是否成功,得看后台的处理和判断。


最佳实践和应用场景

比如,我们手机app扫码支付的时候,基本上都是跳转到支付成功页面。这种情况,都是微信h5。

基于token + 缓存

首先,要注意的是,这种解决方案是前端和后台结合。怎么个结合法?就是后台会生成token,并且会给到前端。


具体步骤是

1.客户端请求
2.后台生成token,给token到前端
3.客户端再次请求
4.后台从缓存取数据


几个问题

1.客户端的两次请求时机?
第一次是扫码。第二次是点击提交按钮。

2.缓存保存的是什么数据?
key/value,具体来说是token/order。即在后台使用token唯一标识order。

3.用什么存储?
缓存中间件。memcache或redis。


本质

本质是为了解决步骤3多次提交的时候,后台读的数据,始终是从缓存读,且读的数据是同一个数据。

后台

核心是检验数据是否存在。这里有两个核心的点。1.第一,数据。2.第二,校验。

数据?客户端必须提供1.客户端唯一id 2.数据唯一id。具体解释一下,我们本质是要确定哪个用户的哪个数据?怎么确定?userId/商家id,唯一确定用户。orderId唯一确定当前用户的数据,特别注意,这个orderId是客户端的订单id,服务器端会生成自己的orderId。我们必须确保二者在数据库里唯一,怎么确保?组合唯一索引约束。

如何校验?本质就是校验数据在数据库里是否存在。具体来说就是,sql:where merchantId=? and orderId=?。当然,我们也可以不校验,但是不校验的话,写入数据的时候,如果重复,就会报错。


上面的其实有点问题,就是存在一种情况,因为上面的是1.先读2后写,这里包含了两步操作,所以必然存在原子性问题。

就是在读和写之间,数据已经存在。那怎么办?

还能怎么解决。唯一的解决方法就是加锁。1.如果是单进程,就普通锁。2.如果是集群,那么就分布式锁。作用都是确保读和写是原子操作。


本质

核心是两点
1.数据库的组合唯一索引约束
2.校验数据在数据库里是否存在

聚合支付-扫码支付

聚合支付-扫码支付,本质上是二维码,没有真正的商家,即店家是没有自己的商家系统的。具体看这篇文章 juejin.cn/post/684490…

所以,聚合支付-扫码支付,校验数据在数据库里是否存在的时候,是检验商家号+支付公司订单号。即sql:select ... where merchantId=? and orderId=?

区别在哪里呢?如果商家有自己的商家系统,且请求数据的时候,传了商家订单号给上游,那么orderId就是客户端传过来的订单号;没有的话,就是支付公司自己的订单号。就这么简单!

参考

www.chilangedu.com/blog/100000…