首页 > 编程语言 >[不靠谱程序员]订单付款成功后,不是先改状态,而是...

[不靠谱程序员]订单付款成功后,不是先改状态,而是...

时间:2023-10-18 20:44:33浏览次数:68  
标签:... 先改 商户 状态 付款 程序员 记账 付款单 paymentOrder

做过税地系统或三方支付或对接过银行支付通道的朋友应该清楚,我们的支付系统在调用银行通道获取到付款单的终态后,涉及到记账、结算、通知下游商户等业务逻辑。这其中,有一项默认的操作是,更新付款单的状态。

并且,应该先变更状态,变更状态成功后,然后再去执行其他业务逻辑。

我们在参与一次代码评审时,就发现了不靠谱的事情。开发人员先发起异步记账,然后才是更新付款单状态。

    /**
     * 订单完成的业务逻辑封装
     * @param paymentOrder 付款单对象
     * @param payResult 付款结果
     */
    void handlePaymentCompletion(PaymentOrder paymentOrder, PaymentResult payResult){
        if (PaymentOrderStatusEnum.isFinalState(payResult.getStatus())){
            return;
        }

        // 订单完成,异步记账
        accounting(paymentOrder);

        // 持久化更新订单付款状态
        updateOrderPayResult(paymentOrder, payResult);

        // 异步通知下游商户系统
        notifyMerchant(paymentOrder);
    }

 

那么,这会出现什么后果呢?

假如持久化记账完成了,商户的账户余额也变更了,但是,变更付款单状态时,由于字段超长等某些原因导致异常,程序中断,付款单状态未能持久化变更,也就是说,此时数据库里付款单的状态依然是“付款中”。那么,定时查单任务(或查单延迟消息队列)在下一次调度时还会读取到这一笔“付款中”的交易,然后继续查询银行通道,通道返回终态后,又开始执行记账逻辑,这为重复记账埋下了种子。

重复记账会产生什么后果呢?

①如果付款单是付款失败,商户账户可用余额会增加。重复记账,就会出现余额异常翻倍增加,意味着商户可以用增加的这笔“意外之财”继续付款。这是资金风险的原罪。

②如果付款单是付款成功,商户账户可用余额减少。重复记账,就会导致商户余额异常成倍减少,意味着商户无法继续付款。我(商户)明明给你充钱了,你却告诉我余额不足,不让我用,我投诉你!

因此,这个顺序颠倒的代码逻辑是不是很可怕?支付系统最怕这种资金风险。上面说的定时任务只是一方面,回调或并发场景下也同样会导致这个资金隐患。

 

借助这个案例,来强调一下,业务处理流程的先后顺序是很重要的,一定要摸索清楚。日常开发中养成严谨的好习惯,关键时刻才能彰显靠谱。

 

ref:§ 业务校验,注意各个校验的先后顺序。

 

【EOF】欢迎大家关注我的微信公众号「靠谱的程序员」,让我们一起做靠谱的程序员。

标签:...,先改,商户,状态,付款,程序员,记账,付款单,paymentOrder
From: https://www.cnblogs.com/buguge/p/17773278.html

相关文章

  • 运算符 列名*1.1 case when... then ..when.. then ..else.. end
    selectENAMEas'姓名',SALas'原始工资',(SAL*1.1)as'涨工资10%'fromempwherejob='MANAGER';  #经理涨薪%10,销售涨薪%50其余不变需要使用casewhenthenwhenthenelseendselectename,job,salas'原来的薪水'......
  • 【每日一记】ACL基本概念(匹配流量、路由条目、书写、规则.....)
    个人名片:......
  • 第一写代码博客送上程序员语录
    岁月在不经意中流逝,在程序员节日到来之际,你是不是不太清楚程序员祝福语怎么写呢?下面是励志的句子小编为大家整理的“程序员节的文案标语”,仅供参考,希望能为您提供参考!程序员节的文案标语1.1234567,弹奏出了美好生活的奇妙乐章。aBcdEFG,键出了未来精采多姿的人生。1001011,谱写出高科......
  • Vue中 三个点 ... 的用法
    Vue中三个点...的用法主要是操作数组和对象一、操作数组//1.把数组中的元素孤立起来letiArray=['1','2','3'];console.log(...iArray);//打印结果123//2.在数组中添加元素letiArray=['1','2','3'];console.log(['0&......
  • 叮!你有一份1024程序员节的通关秘籍待查收!
    突破性的变革往往源自一瞬间面对大模型的挑战你,或许也能成为下一个关键人物值此1024程序员节之际文心大模型携手飞桨以“超级码力碰撞未来”为主题,发起4大活动准备了一场专属于开发者们的惊喜盛会带你通关,碰撞未来!一起度过一个快乐而又充实的程序员节!AIShow·碰撞出创意10......
  • Javascript报错:Uncaught TypeError: $(...).slide is not a function
    检查网站的时候,发现网页出现一个报错,UncaughtTypeError:$(...).slideisnotafunction同时,平时没有问题的轮播图,也不轮播了。检查并解决步骤如下: 1.顺着错误提示点过去,发现就是slide函数无法运行。查看相关介绍,表示是jq文件进行了重复引用,且版本不同 如下图相关资料描......
  • 切片展开操作符...
    packagemainimport"fmt"funcmain(){ slice:=[]int{1,2,3,4,5} fork,v:=rangeslice{ ifv==4{ slice=append(slice[:k],slice[k+1:]...) } } fmt.Println(slice) /* 在切片字面量中,切片展开操作符...可以用于将一个切片的所有元素展开......
  • #yyds干货盘点# LeetCode程序员面试金典:H 指数 II
    题目:给你一个整数数组 citations ,其中 citations[i] 表示研究者的第 i 篇论文被引用的次数,citations 已经按照 升序排列 。计算并返回该研究者的h 指数。h指数的定义:h代表“高引用次数”(highcitations),一名科研人员的 h 指数是指他(她)的(n 篇论文中)总共有 h 篇论......
  • #yyds干货盘点# LeetCode程序员面试金典:分发饼干
    1.简述:假设你是一位很棒的家长,想要给你的孩子们一些小饼干。但是,每个孩子最多只能给一块饼干。对每个孩子 i,都有一个胃口值 g[i],这是能让孩子们满足胃口的饼干的最小尺寸;并且每块饼干 j,都有一个尺寸 s[j] 。如果 s[j] >=g[i],我们可以将这个饼干 j 分配给孩子 i ,这个孩......
  • ....
    eyJ2ZXJzaW9uIjoxLjMsImZlYXR1cmVzIjp7ImxvY2F0aW9uIjp7InJvb20iOnRydWUsIm91dHNpZGUiOnRydWUsIndvcmxkIjp0cnVlLCJzcGFjZVNoaXAiOnRydWV9fSwic3RvcmVzIjp7Indvb2QiOjExNzAzLCJ0ZWV0aCI6MTk5LCJiYWl0Ijo1NzIsImZ1ciI6MTQ0NDAsIm1lYXQiOjM0NzEsInNjYWxlcyI6MTMwLCJjbG90aCI6MzE......