• 小程序拼团业务,并发支付导致重复给用户返利bug


    今天遇到了一个线上的重大bug,小程序拼团业务,例如当一个团金额达到10000元时,这个团就表示拼团成功,但是在金额马上到达10000元瞬间,多个用户同时下单,支付完成微信后台调取callback接口,因为当成团的那一刻,给当前团的用户发送奖励,线程1正在发送奖励,还没有完成时,线程2又过来了,线程三,线程四同时过来,就会循环执行发送奖励代码,造成线上多个给用户返利,解决方案:
    把跟用户的交互不能交给用户来完成,要交给系统处理,写一个定时方法,定时查看哪个团拼成功了,然后给已拼成功但是还未发奖励的用户发送奖励,完美解决
    在这里插入代码片
    //已成团
    if (group.equals(1)) {

            //发放奖励
            List list = activityGroupRechargeOrderDaoService.query()
                                                                                        .eq("activity_group_recharge_team_id", team.getId())
                                                                                        .eq("status", 1)
                                                                                        .eq("send", 0)
                                                                                        .list();
    
            Map personMap = personDaoService.getMapByIds(list.stream().map(ActivityGroupRechargeOrder::getPersonId).collect(Collectors.toList()));
    
            for (ActivityGroupRechargeOrder vo : list) {
    
                //占比
                Double percent = NumberUtil.round(vo.getAmount().doubleValue() / team.getRecharge().doubleValue(), 5, RoundingMode.HALF_DOWN).doubleValue();
                //应到金额
                Double amount = NumberUtil.round(team.getReceipt() * percent, 0, RoundingMode.HALF_DOWN).doubleValue();
    
                //修改用户余额
                personDaoService.update()
                                .setSql(" balance = balance + " + amount)
                                .eq("id", vo.getPersonId())
                                .update();
    
                PersonBalanceLog log = new PersonBalanceLog();
                log.setId(IdUtil.objectId());
                log.setPersonId(vo.getPersonId());
                log.setOpera("+");
                log.setType(1);
                log.setAmount(amount);
                log.setTitle("拼团成功,团编号" + team.getOrderNo() + ",到账金额:" + log.getAmount() + "元");
                log.setSurplus(0.0);
                personBalanceLogDaoService.save(log);
    
                //已发放奖励
                activityGroupRechargeOrderDaoService.update()
                                                    .set("send", 1)
                                                    .eq("id", vo.getId())
                                                    .update();
    
                if (personMap.containsKey(vo.getPersonId())) {
    
                    Person person = personMap.get(vo.getPersonId());
    
                    WeChat.Message.mini("user")
                                  .openid(person.getOpenId())
                                  .template("X1UaO1H_iR3QVoB_Bar1C63nhWpEFtTv_VkWI9FmEP8")
                                  .option("thing3", "成功")
                                  .option("thing4", "拼团金额已到账~")
                                  .send();
                }
    
            }
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52

  • 相关阅读:
    【ELK日志收集系统】
    pandas笔记:显示中间的省略号
    国自然中标越来越难,怎样才能赢在起跑线上?
    【机器学习算法】关联规则-1 关联规则的概念,Apriori算法,实例和优缺点
    GPT实战系列-使用LangChain内部工具
    Day10 尚硅谷JUC——线程间通信
    安卓开发中ViewBinding的使用
    Redis简单介绍
    DRDS的介绍
    算法---滑动窗口练习-5(将x减到0的最小操作数)
  • 原文地址:https://blog.csdn.net/weixin_41184005/article/details/134075269