V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
V2EX 提问指南
shanghai1943
V2EX  ›  问与答

请教:多次支付问题如何规避

  •  
  •   shanghai1943 · 2022-04-14 11:14:24 +08:00 · 2187 次点击
    这是一个创建于 714 天前的主题,其中的信息可能已经有所发展或是发生改变。

    目前的支付流程是:选商品-下单-支付。

    假如在 H5 下单后,APP 端内也可以查到相应的订单。

    在支付页面有多个支付方式可以选择,有些支付方式还可以打开新的浏览器 tab 页去支付。

    目前遇到的问题是,假如在 H5 下单后,在支付页选了 A 支付方式,该支付方式打开了新的支付 tab 页,这时候又跑到 APP 端对该订单选择同样的支付方式去支付,相当于 H5 和 APP 端有两个可支付的 tab ,这时候这两个页面都可以完成支付,相当于这个订单被支付了两次。

    想到的一个思路是,支付链接之类的支付凭据,同个订单在有效期内不重复生成,相当于多端用的支付凭据都是同一份。

    这种思路似乎只能解决同一个支付方式的问题,如果是不同支付方式支付同一个订单的话,似乎又无解了,因为没法选了第一种支付方式后,已经打开了外部页面,再选择第二种方式的话,似乎没法将第一种支付方式的凭证删除或者设置过期之类的。

    想请问下大家有什么好的解决办法么?

    谢谢。

    23 条回复    2022-04-17 11:41:05 +08:00
    Chad0000
        1
    Chad0000  
       2022-04-14 11:17:41 +08:00 via iPhone   ❤️ 1
    订单保存正在使用的支付 ID ,其他想支付必须先取消这个支付请求。
    shanghai1943
        2
    shanghai1943  
    OP
       2022-04-14 11:35:22 +08:00
    @Chad0000 主要是没法探测到用户是否真正取消了。
    freeup
        3
    freeup  
       2022-04-14 11:41:22 +08:00
    由于第三方支付需要业务号,此业务号不可重复,如楼主所说,如果使用订单号做支付业务号,那么只能处理一种支付方法,如果使用订单号对应多个业务支付订单的话可以支持多支付方式,但是处理重复支付比较麻烦。。。

    综上所述。。。如果重复支付了,那就申请退一笔呗。。。这种情况应该比较少,除非有人就故意这么搞,
    复杂问题简单处理。。。。。
    Chad0000
        4
    Chad0000  
       2022-04-14 11:41:47 +08:00
    @shanghai1943

    1. 如果支付方有取消接口,那么发起第二次支付前,就可以提醒用户有一个支付还在进行中,是继续之前的支付还是重新发起。后者则取消之前的支付再重新发起。
    2. 如果没有取消接口,那么也提醒用户,用户非得支付两次这谁也阻止不了。不过基本上支付成功后,是可以检查订单是否支付,如果是多次支付,自动或手动提醒客服然后调用支付 API 撤销一笔自动返款的。
    3. 其实还有更极端的情况,比如首次支付实际上完成了,但因为支付接口有问题甚至是支付方与银行有问题没有及时正更新,那么还是会导致重复支付。这种也是需要走上面那种流程。

    不管怎样,支付成功后有异步流程去处理订单,如果此时已经有其他支付成功了的话,需要进入异常处理流程。完美避免重复支付也是不现实的。
    dddd1919
        5
    dddd1919  
       2022-04-14 11:55:30 +08:00
    为订单生成一条支付记录,包含支付流水号,支付方式,金额等支付信息,使用该数据发起支付
    killva4624
        6
    killva4624  
       2022-04-14 12:34:49 +08:00
    兜底方式:异步对账检查,如果有多种方式支付了同一个订单,对后支付的订单退款。
    如果重复出现了多次相同情况(同样时间或者同样商户)下的对账问题,那么就去挖一挖造成重复支付的实际场景,做相应的优化。
    archer2ee
        7
    archer2ee  
       2022-04-14 13:11:35 +08:00   ❤️ 1
    我们的方案是:
    1. 针对同一种支付方式,x 分钟内使用同一个支付链接,这样可以依赖第三方支付来保证同一个单只能支付一次;
    2. 针对不同的支付方式,下单流程没法避免,只能在支付回调来之后做处理,可以是同步做重复支付检查或异步对账,最终目的是把多支付的退款掉;
    dzdh
        8
    dzdh  
       2022-04-14 13:16:23 +08:00   ❤️ 1
    order
    id, order_id

    payment_order
    id, order_id, out_order_id

    每次 [去支付] 生成新的 payment_order, 传递 out_order_id, desc 传递 order_id 如果有

    支付回调 update payment_order 和 order 乐观锁更新+自动重试

    订单已经为 payment_success 的情况下, 又来了支付回调,且和当前 order 关联的 success_payment_order 不是同一笔的,自动退款。
    dzdh
        9
    dzdh  
       2022-04-14 13:17:42 +08:00
    同渠道+order 的,只生成一笔 payment_order

    这个看需求,如果订单有超时状态(微信、支付宝都有 timeout 参数),在订单过期后仍然可以创建新的 payment_order
    coala
        10
    coala  
       2022-04-14 13:23:59 +08:00
    多次支付无法规避

    楼上说的自动退款也是个办法!

    但是我这里自动退款也不行,是扫码缴费, 存在错缴费的人先缴费的情况, 自动退款可能退错.

    目前是手动等客户联系退款的, 页面上各种提示和信息展示, 实际场景优化, 还是有人两个人客气抢着缴费同时缴纳, 或者排队的时候后面的人错缴前面人的, 现在的多次缴费比例大概是 10 万分之一吧, 勉强接受
    unclemcz
        11
    unclemcz  
       2022-04-14 13:56:03 +08:00 via Android
    接入第三方支付没法规避,只能支付成功后在第三方回调支付信息时判断订单号是否已有支付记录,如果有重复记录,就把不是最早支付的其他支付退回。
    unclemcz
        12
    unclemcz  
       2022-04-14 14:04:47 +08:00
    @coala #10 自有系统有订单号,第三方支付系统有付款单号,每笔记录如何保存和关联是自己处理的,与第三方无关,所以自动退款是可以退的很精准的,不会退错。
    例如微信的支付有 order_id ,同时你自己系统会有 trade_no ,重复支付的话,trade_no 对应的是多条 order_id (不同第三方的支付单号),系统收到支付回调时判断是否已支付过,如果有支付记录,后台自动发起退款,按照原支付方式途径退回,以收到回调的时间为准来判断支付先后。
    codeMore
        13
    codeMore  
       2022-04-14 14:57:41 +08:00
    我们是先选支付方式,再下单。每笔订单只可能对应一个支付方式。
    coala
        14
    coala  
       2022-04-14 15:13:29 +08:00
    @unclemcz 是 trade_no 和 order_id 形式,

    单人多次付款自动退款是没啥问题

    同时两个人付款, 总是会存在一个钱退给谁的问题. 如果不管是退给谁都无所谓那就自动退款也没啥问题,

    同时两个人付款 如果只能退给错缴的人, 自动退款就 "失灵" 了, 如何判断谁才是错缴的? 感觉简直无解

    这个场景其实就是汽车缴费出场, 扫码直接付款
    错缴费的人 A 实际需要缴费的人 B, A 和 B 同时缴 B 的车牌的费用

    先收到了 A 的回调, B 的回调比较晚, 然后如果退了 B 的, A 就会投诉过来(A, B 互相不认识没有关系),
    因为 B 相当没有收费逃单了, A 缴纳了 B 的钱, 自己的又要付.

    电商那种思路的话之间退掉多付的就好了没啥问题,不存在一个 trade_no 退掉了多缴费的还有啥纠纷, 一般没有陌生人帮你付订单的, 并且就算给你退错款了, 也可以取消订单不给你发货这种手段

    汽车缴费到业务结束流程太快了, 最快的话付完钱 10 秒内就溜了, 退错了就没有什么补救手段都没有了,
    unclemcz
        15
    unclemcz  
       2022-04-14 15:25:56 +08:00 via Android
    @coala #14 不知我有没有理解到位,停车场出场交款有很多处理方式:
    一种是不识别车牌,道闸前生成二维码(支付码)支付一次抬杠一次,其他什么都不管,如果回调很慢,他只能等着因为没法抬杠。
    一种是到道闸前识别车牌,生成二维码(非支付码),扫码后显示车牌,确认后支付。
    一种是手工输入车牌然后支付,再出场。
    三种情况我觉得都很难支付错误,第一种需要排队,后面的人不会在前车还没出场时就扫码,后两种绑定车牌,也不可能。
    你们的停车场支付用的是其他模式吗?
    Jtyczc
        16
    Jtyczc  
       2022-04-14 15:55:00 +08:00
    4 楼和 7 楼已经讲完了。

    1 个订单本来就有 N 个支付记录

    最终一致性啊,手动去解决,不管哪个支付成功后,都会有一个补偿机制,延时去检查已经付完款的订单,按照实际金额退款。
    Jtyczc
        17
    Jtyczc  
       2022-04-14 15:56:58 +08:00
    @coala 15 楼的说法可以啊,你回调后直接抬杠了?不识别车牌号码再抬么。

    如果识别车牌号再抬杠,不就不管谁先回调也没事吧。
    XuYijie1216
        18
    XuYijie1216  
       2022-04-15 00:53:09 +08:00
    就说一个词,数据库悲观锁
    coala
        19
    coala  
       2022-04-15 13:08:34 +08:00
    @Jtyczc
    其实 3 种都有用到,

    是很难错, 但是总有些奇葩的人

    第一二种其实是差不多的
    "第一种需要排队" 后面的人真的会在前车还没出场时就扫码, 还有就是主驾驶和副驾驶同时抢着缴费的

    "液晶屏幕展示可变二维码, 强光下或者太小会有很多扫不出来的", 很多地方出口也会贴固定码,

    可以总结下: 后面的人真的会在前车还没出场时就扫码, 这个偶尔真有人干

    是很难支付错误, 但是量大了 就是有人抢别人的码, 就是有人不看车的照片和车牌, 直接缴费....
    coala
        20
    coala  
       2022-04-15 13:11:20 +08:00
    @Jtyczc 同一个车牌付了两次费 , 再次拍本来就是对的,
    并且车子拱到杆子底下的时候, 现在的主流方式其实已经拍不到车牌了 刚才 @错了

    @unclemcz 见楼上
    coala
        21
    coala  
       2022-04-15 13:24:05 +08:00
    @unclemcz 不管在那里都输入车牌缴费反而没什么问题, 但是有的人就是喜欢在杆子底下缴费出去 , 操作的还慢, 会导致出口堵.

    现在其实两种方式都提供, 你可扫场内码预交费, 也可到出口免输入车牌直接缴费,

    问题出在免输入车牌直接缴费这里, 有年龄大的人, 认为扫了就能缴费什么都不管...
    抢缴费这个问题其实是越来越少的 (码的位置调整让后车更难扫, 知道不能扫前车的人越来越多....)
    可能后面更少了, 也会转成自动退款模式, 或者每个停车场可配的可选自动退款或手动退款
    unclemcz
        22
    unclemcz  
       2022-04-15 13:56:56 +08:00   ❤️ 1
    @coala #21 主副驾抢着支付的问题,不是支付工具能解决的了的,支付工具只能解决掉重复支付的问题,就如去菜场买菜,碰到熟人硬要帮你付款,摊主没有办法解决“收对钱”的问题。
    第一种中固定码的这个问题,如果不能避免后车提前支付,就需要在整个解决方案中考虑把这种简单但落后的方式换掉,支付工具也解决不了。
    还有其实现在 ETC 支付也很成熟了,ETC 普及率也超过了 70%,可以考虑一下集成 ETC 支付,它的体验甚至比支付工具的无感知付还要好一些,还能解决帖子提到的问题。
    Jtyczc
        23
    Jtyczc  
       2022-04-17 11:41:05 +08:00
    @coala

    拍不到车牌的时候,那就只能手动补偿了,每次识别一个车牌做一个简易队列,车子拱到杆子底下的时候,它还在队列中,杆子升起下降就消费

    后面的人是可以提前支付,但是怎么抢码呢?哦,我知道了,你们抬杆那边支付的二维码居然没有单独做,导致别人在别的地方提前支付时,会抢码支付。。。
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   我们的愿景   ·   实用小工具   ·   1021 人在线   最高记录 6543   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 35ms · UTC 19:42 · PVG 03:42 · LAX 12:42 · JFK 15:42
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.