7

一笔订单,但是误付了两笔钱!这种重复付款异常到底该如何解决?|原创

 3 years ago
source link: https://studyidea.cn/repeat-pay-error
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
100

封面送给我狗哥,今天终于大结局了!可伶我钦哥,这么惨了,最后还要把他写没了!!

Hello,下午好,我是楼下小黑哥~

今天的文章我们接着上次的话题,继续聊聊支付系统异常解决办法。

在上篇文章中「支付掉单异常解决方案」,我们主要提到的是支付过程中掉单的场景,用户明明付款成功,银行卡都扣款了,但是订单却还显示待付款。

而在今天的文章中,我们将聊到重复付款的异常,即同一笔订单,扣了用户两笔钱。

另外我们还将会提到另外一种异常,用户扣款成功,但是订单却支付失败的场景。

以上两种异常对于被扣款的用户来讲,使用体验极差,自己多付了钱,订单却还不成功。所以如果不及时处理这两类异常,那就真的等着被投诉吧。

重复付款异常

重复付款异常一般常见于网银支付,微信支付,支付宝等这类需要跳转到一个支付网关页(网银支付),或者跳转到钱包 APP(支付宝、微信),从而异步完成扣款的支付场景。

网银支付流程

这种支付场景下,只能通过接受异步通知才能知道支付结果,我们一般将其称为异步支付。

PS:有了异步支付,那么同步支付是什么?

其实同步支付指的就是调用支付接口之后,就可以立刻返回支付结果的,比如银行卡类快捷/代扣等支付就是同步支付。

当然也有一些奇葩的银行卡支付渠道,同步支付结果为受理成功,只能接受异步通知或者查询返回支付结果。

由于银行卡支付需要返回明确支付结果,对于这类渠道只能内部设计将异步转为同步,感兴趣可以看下之前历史文章:

架构设计|异步请求如何同步处理?

后台支付流程如下:

图片来自之前的文章:银行卡支付原理

网关支付

为什么会发生重复付款?

主要原因其实跟上次内部掉单异常一样,跟业务表设计有关。

上次我们提到,支付系统主要表结构如下:

100

在这个表结构下,只要支付订单未成功,商户就可以重复使用其内部同一订单号调用支付接口。

假设这样一个场景,用户在收银台支付时选择招行进行网银支付,当他点击支付之后,商户系统将会调用支付公司的网银接口。

这时支付系统内部将会创建一笔支付单以及关联的渠道订单,并且调用招行系统的接口。

然后用户的浏览器页面将会打开一个新页面,然后跳转到招行网站。

这时如果此时用户再次在收银台点击支付,将会再次调用支付系统接口。这时候由于支付单已存在,所以仅仅会再创建一条渠道订单记录,并且调用招行系统的接口。这时用户的浏览器将会再次打开一个招行的网站。

如果用户在两个招行网银页都完成支付,这时就发生了重复付款。

上面这种场景看起来有点傻,但是真实用户操作真的会发生。除了这种,博客园上的小伙伴还提到这么下面这种情况:

100

重复付款异常的主要的解决办法有两种,分为事前与事后。

事前主要的目是尽可能防止用户重复付款,主要解决办法为优化付款页面,尽可能做好提示。

第一种优化方式,付款页面直接跳转到第三方/银行的网银页面,不要打开新的页面去跳转。

网银同步跳转

这种方式可以防止用户误打开两个网银付款的页面,从而导致重复付款。

但是这里会有一个问题,银行网银页面付款成功之后,用户如何知道其在商户侧订单状态也成功了?

其实很简单,现在网银支付接口,一般都会有一个参数 return_url:同步跳转地址

来自支付宝开发文档

只要在接口传入这个地址,当支付成功之后,页面最终就会跳转到这个传入的地址,商户侧就可以在地址显示订单是否支付成功。

支付系统异常处理-同步跳转

上面我们提到,用户有可能会使用浏览器回退功能,跳转到支付页,从而导致重复付款。

对于这种情况,我们可以在其回退支付页时,首先向后台查询这笔订单支付结果,如果已支付成功,那就直接显示成功页面。

第二种优化,对于这种重新打开一个页面跳转到银行网站,我们可以在页面加入弹窗提示,询问用户是否已支付完成。

100

比如上面这种处理方式,当用户点击确认完成充值,可以马上向后台发起查询订单状态。

下面来聊聊事后的解决办法,其实解决办法很简单,发起内部退款,将多余支付的一笔反向退款回去

支付系统内部可以有个定时任务,定时扫描支付单下有多条成功渠道订单的记录,然后选择将重复支付渠道订单发起退款。

这种方式是支付公司系统内部的操作,不需要商户侧发起指令。

订单失效异常

这种场景一般常见于电商购物,秒杀等购物场景。当用户下单之后,页面将会开始倒计时,用户需要在有效期内支付成功。

100

假设用户点击跳转到支付宝,但是其没有立刻支付,而是停留了很久,在订单最后一秒时间内完成了支付,但是这个时候订单早已因为时间到期而被自动取消。

这样就发生用户扣款已经成功,但是订单却是失败或关闭的场景的。

另外还有一种情况,用户在有效期内支付成功,但是因为网络、内部应用等问题,支付结果的异步通知过了很久才收到,这时内部订单的早因为时间到期而被取消。

第一种解决办法,上送有效期给支付渠道。

一般支付接口都会有一个支付有效期的字段,表明这笔支付最晚可以支付的时间。如果超时未支付,这笔支付将会被关闭。

来自支付宝开发文档

当然一般情况下,如果未上送,这个字段内部一般会有个默认的有效期,比如 3 天,这个时间就比较长了。

所以当调用支付接口时,可以将订单剩余有效期传入支付接口。这样用户如果在超时时间内未完成支付,支付将会失败。

第二种解决办法,内部发起退款。

这个解决办法依然事后托底的解决办法,对于支付订单已关闭,但是支付却成功的情况,发起内部退款,将钱退给用户。

内部可以有个定时任务,定时扫描支付订单已关闭但是支付却成功的情况,然后发起退款指令。

最后用思维导图方式帮大家总结一下支付系统可能会碰到的异常。

100

对了,文末文章现在已经支持连续阅读了,想查看小黑哥之前写的关于支付其他文章,直接点击下一篇看个爽~


本文首发于: https://studyidea.cn/repeat-pay-error

欢迎关注我的公众号:小黑十一点半,获得日常干货推送。如果您对我的专题内容感兴趣,也可以关注我的博客:studyidea.cn

006tNbRwly1gbkqdpfkutj30p00dwn0a.jpg

About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK