V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
LLaMA
V2EX  ›  程序员

退款到用户在网站的余额,退款前先把订单金额改为 0, commit 后再给用户加余额是不是就没有重复退款的风险了?还要考虑用户用多线程之类的手段重复退款吗?

  •  
  •   LLaMA · 2023-03-18 11:15:43 +08:00 · 3013 次点击
    这是一个创建于 622 天前的主题,其中的信息可能已经有所发展或是发生改变。
    18 条回复    2023-03-19 12:18:54 +08:00
    neoblackcap
        1
    neoblackcap  
       2023-03-18 12:06:38 +08:00
    这个流程跟一般会计准则很不相符,从经验来看非常有可能出问题。
    订单信息不应该改动,最多是更新状态。订单应该是一个状态机,至于你是不是要加锁来实现稳定的状态变更,那么看你实际的需要
    gchuyun
        2
    gchuyun  
       2023-03-18 12:58:01 +08:00 via iPhone
    这样做有些反逻辑,修改金额为 0 本质上和修改状态为已退款有什么区别呢?
    maggch97
        3
    maggch97  
       2023-03-18 13:37:56 +08:00 via Android
    显然没解决问题,不还是有可能并发读订单金额?
    mmdsun
        4
    mmdsun  
       2023-03-18 13:42:33 +08:00 via iPhone
    在你判断“之前是否退款”的时候加锁。
    Rehtt
        5
    Rehtt  
       2023-03-18 13:53:38 +08:00
    数据库操作吗,加事务
    yxzblue
        6
    yxzblue  
       2023-03-18 13:55:37 +08:00
    新增负数金额的退单记录。
    wudaye
        7
    wudaye  
       2023-03-18 14:37:23 +08:00
    咋就不愿意加个分布式锁呢,你们并发有那么高吗
    ragnaroks
        8
    ragnaroks  
       2023-03-18 16:14:41 +08:00
    已经产生的订单不要去动它,创建一个新的以 id 为外键的退款表
    forgottencoast
        9
    forgottencoast  
       2023-03-18 16:24:08 +08:00
    数据库的问题数据库就可以解决,事务。
    Ericcccccccc
        10
    Ericcccccccc  
       2023-03-18 16:31:21 +08:00
    加锁呀...
    hefish
        11
    hefish  
       2023-03-18 16:34:24 +08:00
    楼上的大大们,我觉着 OP 能想出这个办法,也是花了不少功夫了。可能他并不知道数据库可以加锁,加事务。可以用别的组件加分布式的锁,等等。 总的来说,这个办法咋一看,还是可行的,就是并发高了感觉危险。
    zjsxwc
        12
    zjsxwc  
       2023-03-18 16:36:17 +08:00 via Android
    余额是动态每条记录 sum 出来的(可以缓存优化、可以定期归结上个月余额清除冗余记录),而不应该直接修改某个值。
    FawkesV
        13
    FawkesV  
       2023-03-18 17:03:55 +08:00
    退款操作对订单数据不能改。
    增加一个退款表,关联订单 ID ,订单表订单状态字段增加退款中(中间态),已退款(完成态)。
    操作时增加事务。和锁,可以使用数据库的悲观锁,毕竟简单就能实现。或者用 redis 锁,也就是分布式锁。
    考虑多线程重复意思是防止用户并发请求是吧,能够防止这个的只有锁。事务是为了保证最终一致性。
    wellerman
        14
    wellerman  
       2023-03-18 21:00:11 +08:00
    最简单就是退款后台审核,一般很少有退款,如果有很多那更应该通过审核退款。

    正常主要流程应该是:
    1. 更改原订单状态
    2. 拿到第 1 步成功值后,创建支付流水退款订单
    3. 更新余额(和第 2 步在一个事务中处理)
    ggvm
        15
    ggvm  
       2023-03-18 22:21:30 +08:00
    需要设置多重保险,然后设置兜底的方案。

    例如,可以从数据库表 scheme 上防范出现这种错误:

    退款记录表中,需要有原订单编号 id 字段(且设置为 unique key ),如果产生重复的退款,因为 unique 的原因无法插入数据表中,因此不会出现重复退款增加金额的情况。

    具体问题具体分析,多假设多测试才是王道。
    cheng6563
        16
    cheng6563  
       2023-03-19 11:11:47 +08:00
    订单金额改 0 后,改可以余额之前,服务 /服务器 /网络 炸了怎么办?
    LLaMA
        17
    LLaMA  
    OP
       2023-03-19 11:35:32 +08:00
    @cheng6563 #16 少退了能找客服处理,多退了估计没几个客户会找客服
    Jtyczc
        18
    Jtyczc  
       2023-03-19 12:18:54 +08:00 via Android
    加个退款表吧,订单表加状态,退款中,退款完成。
    退款表,申请状态:待处理,同意退款,拒绝退款
    退款状态:退款中,未到账,已到账
    1.用户发起了退款申请,
    1.1 不存在关联的待处理的退款单,那么订单进入退款中,新增一条待处理的退款数据…

    手机码字不想写了,总的来说,以前我司订单中的退款中,只是一个业务流程,具体退款还要看退款表

    等后台人员同意退款了,那么肯定是调用微信 /支付宝的退款接口,然后推荐表就是同意退款和退款中,

    真正到账后,才更新已到账,同时订单也更新为退款完成。

    当然以上不适用财务打款退款。
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   2414 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 24ms · UTC 01:01 · PVG 09:01 · LAX 17:01 · JFK 20:01
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.