一个小小逻辑符的错误使用,资损几万块?

news2024/11/22 4:00:11

分享是最有效的学习方式。

博客:https://blog.ktdaddy.com/

故事

这是一个真实事件,三年前老猫负责公司的支付资产业务。为了响应上级号召,加强国央企之间的合作,公司新谈了一个支付对接的渠道(当然这个支付渠道其实很冷门的,也是为了对接而对接,具体哪个渠道也不方便透露),由于原始支付系统的第三方支付可拓展性设计得还不错的,所以老猫对接的也是比较快的,熟悉对方的对接文档之后对着编码就好了,差不多花了三天的时间就完成联调了。一切看似很顺利地上线了。

时隔几天,收到了一个快递包裹,是一袋价值53块钱的“原皮腰果”,当时诧异,翻看了各大消费平台,都没有之前的下单记录,后来和媳妇确认了一下,她也没有下单。“难道是某个崇拜哥的小姑娘送的?不能吧”当时心里美滋滋地yy着。

不过之后的一个客诉问题,引起了老猫的重视,老猫排查下来发现一个很重大的问题,钱款的扣除和实际的订单状态对不上。说白了就是订单完结了,但是账户资产并没有完成扣除。我瞬间明白了之前那个“原皮腰果”是怎么回事儿了,当时在生产测试渠道的时候,在公司内部商城提交了订单,但是并没有付款,然而订单却成功了。

再三确认之后,确实存在这一问题。一瞬间整个人心态崩了,头皮发麻,口干舌燥,心脏“突突突”。怎么办?怎么办?生产还不知道涉及多少单子,没办法,兜不住了,先把这件事情往上抛吧(向上级领导汇报)。

具体原因是什么呢?我们来看一下对接第三方支付的大概时序流程。

在这里插入图片描述

我们一般在对接第三方支付渠道的时候会有上面一些基本流程。

1、当我们内部生成待支付单之后会请求外部第三方支付渠道,此时第三方支付渠道内部会生成待支付单。

2、我们第三方支付单创建成功返回之后,一般内部系统会唤起收银台,然后用户确认支付。

3、第三方支付成功返回消息之后,整个支付就算已经完结了。

但是问题就出在了第三方支付渠道还有一个定时异步通知的任务,并且我们也对接了这个接口。这个异步通知的功能主要是会定时告知我们支付系统第三方支付单的状态。而且无论成功与否,都会轮询告知,例如,如果是待支付,对方会告知状态是0,如果已完成支付,对方会告知状态是1。我们拿到支付结果之后就会执行后续的订单完成流程。

收到异步通知之后的代码处理判断如下:

事故代码

    //校验交易状态
    if (!Objects.equals(notifyModel.getTradeStatus(), TradeStatus.SUCCESS.getCode())
            && amtConvertY(notifyModel.getTradeAmt()).compareTo(thirdPartyCharge.getAmount()) != 0) {
        LOGGER.error("交易状态不正确:{}", notifyModel.getOutTradeNo());
        throw new BusinessRuntimeException(Errors.PAY_NOTIFY_IS_FAIL);
    }

正确代码

    //校验交易状态
    if (!Objects.equals(notifyModel.getTradeStatus(), TradeStatus.SUCCESS.getCode())
            || amtConvertY(notifyModel.getTradeAmt()).compareTo(thirdPartyCharge.getAmount()) != 0) {
        LOGGER.error("交易状态不正确:{}", notifyModel.getOutTradeNo());
        throw new BusinessRuntimeException(Errors.PAY_NOTIFY_IS_FAIL);
    }

相信眼尖的小伙伴已经发现了,其实就是“||”和“&”的区别。第一种情况当对方告知状态为0的时候,其实并不会被拦截掉,而是直接走了往后的流程,于是悲剧就发生了。

直接说一下最终的处理,最终其实还是比较幸运的。由于,我们本身已经对接了微信以及支付宝的支付渠道,再加上这个渠道的支付使用的频率还是非常少的,很多用户不太会使用这个渠道进行支付,所以最终盘算下来整个的资损金额差不多是3w左右,另外的是其中有个不幸中的万幸。是因为老猫在这之前做了一套资金追讨系统,该系统可以定位出那些用户“空手套白狼”了。并且能给这些用户生成对应的待支付订单,用户可以通过这些待支付订单最终完成资金的补偿付款,最终完成了资金了追讨。所以事后,完全盘点之后发现一共的资损是1600左右。

最终,也算是有惊无险。但是这次的经历给了老猫上了一课。

下面总结一下我们在做支付账务系统的过程中应该如何进行资金安全相关的设计,最终做到防患于未然。

在这里插入图片描述

资金安全设计

针对资金安全的问题,不限于通过技术手段避免资损,其实很多时候我们还需要结合数据核对、监控等措施,做到快速发现资损并且止损。下面我们来一一盘点一下资金安全设计的一些点,希望能给大家一些帮助。

资损风险分析

风险要素

在我们做支付资产系统的时候,我们其实需要好好盘点一下资损风险,这些风险可能来自于各个方面。下面涉及,

资金流:我们实际的产品业务中,尤其是支付资产的时候,其实往往会有很多类型的资产形态,可能是积分,可能是现金,当然还有可能是优惠券等等。看到这些金额的时候,我们需要确保上下游系统的一致性、金额计算的正确性、逆向金额不能大于正向金额等等。

交互:我们需要考虑客户端展示内容是否正确。尤其是小数点展示的精确位上,很容易出现客户端展现信息不全的问题,实际其实为99.99元,但是展示的时候却为99.9或者9.99。

资金规则:资金规则是为资产本身的产品形态规则,举个例子,发放优惠券这个行为,每个人发多少,发的时间点,发放的人数,发放的门槛等等。再比如某个积分资产的限额,其中又涵盖着日限额以及月限额。

异常:存在资损风险很多时候其实由于异常导致的,抛开系统本身异常之外,我们还要考虑网络抖动异常,其他服务异常。如果系统本身的事务处理不好,或者最终一致性没有做好,就很有可能造成资损。

技术风险

系统发生资损么,很大一部分就是系统没有设计好或者是编码过程中的粗心,例如上面老猫的真实案例。那么且抛开粗心这个人为因素,我们盘点一下本身技术风险,这些技术风险场景主要来源于多并发、幂等、分布式事务、上下游服务超时、数据计算精度、接口协议、校验逻辑的不严谨等等。

上面罗列的这些很多都为一致性的问题。我们一个个来看。

1、并发:多线程、同时对数据进行读写处理的时候,就有可能造成一致性的问题,例如用户资产重复支付,积分超发等等,如果在系统层面还用了缓存的话,还有可能存在缓存未刷新,导致数据库和缓存不一致的情况。

2、幂等:在支付资产系统中,接口幂等性是十分必要的,接口的幂等能够很大程度上避免(1)中提到的资产重复支付问题、下单重复问题以及网络重发问题。关于幂等详细设计,其实老猫在以前的文章中也有梳理,大家有兴趣的可以看这里【前任开发在代码里下毒,支付下单居然没加幂等】

3、服务超时:系统所依赖的服务执行结果返回慢,造成上下游数据状态不一致,例如核心的支付服务调用底层的资产服务进行扣款,结果由于资产扣款逻辑返回超时,导致两边数据不一致。

4、接口规范:尤其是对接第三方接口的时候,文档上的必填字段和非必填字段如果本身文档就有出入,可能就是致命的。

5、事务:其中包含本地事务以及分布式事务,研发在开发过程中对事务理解不够透彻,使用不严谨,最终导致数据不一致。

6、数据精度:主要在金额四舍五入的场景,最终导致精度丢失。或者上下游系统精度不一致。

防止资损

如果说想要彻底的避免资损,并不是一件容易的事情,系统链路复杂,任何一个环节出现问题都有可能导致最终的资损。我们虽然是技术,但是我们的眼光其实不能够仅仅局限在技术的眼光去看待资损这个事情,除了技术侧尽量规避资损发生之外,其实还有其他方案,例如下图。

在这里插入图片描述

上图准确来说其实是一个防止资损,或者说尽量保证企业损失最小的一系列的手段以及方案。这些步骤,其实从时间上来看是不同的时间线。以下咱们来一一看一下。

1、技术规避:

技术侧我们当然要保证我们自身代码的严谨性。这里主要提及的还是上述所说的一致性的问题。我们在系统开发的过程中要挖掘系统可能出现问题的点,其中可能包含事务的使用、接口需要做好幂等设计,系统和系统交互过程中需要考虑接口的重试机制等等。当然这些都是咱们研发在实际开发的过程中需要注意的点。

2、对账发现:

很多时候,资产支付系统上线出问题,并不是直接的日志异常。这种异常可能还好,容易被发现,因为已经卡流程了。怕就是怕在不知不觉的情况下,看似风平浪静,其实内部数据已经一团乱麻。资损已经产生了,就像老猫上面遇到的这种情况。这种情况的发生其实主要还是由于没有做好相关的对账措施。从而导致了悲剧的发生。其实如果我们能够做到每日对账,可能问题就能及时被发现。

对账方式:我们可以从上层系统一路往下游系统进行对账。例如,我们有这样几个系统,例如,上层电商业务系统,订单系统,支付核心系统,第三方支付系统。那么我们对账的方式就如下。

在这里插入图片描述

咱进行对账的过程中,我们一般是系统之间进行两两单据对账,对账维护有两个方面,第一个是总数量,第一个是总金额。如果我们发现所有的系统能够两两账目对齐,那么系统就没有太大问题。

在这里插入图片描述

当然很多时候单据数量可能由于业务的原因是不对等的,所以这个时候可能还需要进行一定的数据清洗,然后才能进行对账处理。做得好点的话,可以将对不齐的单子能够自动告警,告警方式可以是短信或者邮件方式,当然也可以支持相关人员能够看到每日的对账看板。

这种对账的方式可以协助我们及时发现系统上的问题。老猫之前对接的那个渠道,其实还没有来得及做对账。因为那时候我也疏忽了,认为当前第三方渠道比较冷门,所以就偷个懒没有做对账。然而最终还是逃不过“墨菲定律”。所以咱们研发在做系统上的事儿的时候还是不要抱有任何的侥幸心理。

3、应急止损:

如果真的到了这一步,其实悲剧已经发生了,这个时候其实是比较考验心态的。因为系统漏洞已经造成了资损,并且资损还在持续。这时候内心就会燥热,像老猫那样口干舌燥,着急得像热锅上的蚂蚁。这个时候如果越想早点修复问题,可能越容易出错。很多时候人在着急得时候往往会病急乱投医。为了快速解决问题,修一下bug就直接上线。这种很容易导致错上加错。

所以当我们意识到问题已经发生了,就要向上汇报了,让上级知道这个事情,然后一起看一下问题的处理。这样的话多个人一起把控修复问题肯定比当事人一个人默默修复问题来得好。所谓“当局者迷旁观者清”是有道理的,这样也至少可以降低二次错误的概率。所以出现问题后,一定不能慌了手脚。唯一要做的就是冷静,然后一步步梳理处理的步骤。

当然如果有条件的话,可以根据当前的业务模式开发一个资金追讨系统来防范未然,当然这个系统真的希望是一辈子都用不上,然而这个系统可能是最后的一道屏障了。

总结

以上就是老猫的一段经历,大家可以当做乐子看个热闹。如果真的对你有所帮助,也希望能够得到你的点赞和收藏。当然,如果你也恰好维护同样的系统,对于这样的系统维护有其他新的认知,也欢迎大家能够在评论区留言。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1597293.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

IT精英的财富攻略:五大策略揭秘

IT精英的财富攻略:五大策略揭秘 💸 数字化浪潮汹涌,IT技能成为职场的金钥匙🔑,更为智慧的IT人打开了赚钱的大门。如果你身怀网络维护与安全管理的绝技,那么这五大策略,正是你蓄势待发的赚钱法宝…

【Qt 学习笔记】Qt常用控件 | 按钮类控件Push Button的使用及说明

博客主页:Duck Bro 博客主页系列专栏:Qt 专栏关注博主,后期持续更新系列文章如果有错误感谢请大家批评指出,及时修改感谢大家点赞👍收藏⭐评论✍ Qt常用控件 | 按钮类控件Push Button的使用及说明 文章编号&#xff1…

09 - 镜像管理之:部署单点harbor

本次准备了3台机器:harbor-01、harbor-02、harbor-db,用于测试 单点模式、高可用模式 部署 harbor。 ip主机名规格操作系统说明192.168.217.136harbor-012c4gCentos7.9harbor 服务器,测试单点harbor192.168.217.135harbor-022c4gCentos7.9ha…

快速探索随机树-RRT

文章目录 简介原理算法运动规划的变体和改进简介 快速探索随机树(RRT)是一种算法,旨在通过随机构建空间填充树来有效搜索非凸高维空间。该树是从搜索空间随机抽取的样本中逐步构建的,并且本质上偏向于向问题的大型未搜索区域生长。RRT 由 Steven M. LaValle 和 James J. K…

数据库SQL语言实战(一)

目录 创建SQL表 题目一 题目二 题目三 插入数据 题目一 题目二 题目三 总结 创建SQL表 题目一 创建学生信息表(学生编号、姓名、性别、年龄、出生日期、院系名称、班级): test1_student:sid char 12 not null、nam…

Unity Shader之数学篇

一、坐标系 1、二维笛卡尔坐标系 屏幕坐标系是二维笛卡尔坐标系,OpenGL的屏幕坐标系原点在左下角,DirectX的屏幕坐标系原点在左上角。 2、三维笛卡尔坐标系 三维笛卡尔坐标系要区分是左手坐标系还是右手坐标系。 左手坐标系:举起你的左手…

3.Burp Suite 入门篇 —— 修改请求

目录 前言 官网注册 Burp 浏览器访问漏洞页面 登陆购物网站账号 修改请求包 漏洞挖掘 前言 本篇文章会教你如何用 Burp Proxy 修改截获的请求。 修改请求包是为了通过网站程序规定之外的方式请求,然后对比查看响应内容的变化,判断是否有漏洞存在…

Wpf 使用 Prism 实战开发Day20

备忘录功能页面完善以及优化 备忘录功能基本跟前一章节的待办事项差不多一至&#xff0c;就不再做过多的笔述了 一.备忘录功能完整页面源码 MemoView.xaml <UserControl x:Class"MyToDo.Views.MemoView"xmlns"http://schemas.microsoft.com/winfx/2006/xam…

src挖掘 | 未授权访问+密码重置

0x01系统初探 通过fofa对大学进行搜索 fofa:host"edu.cn" && status_code"200" 在随意的翻阅查看时&#xff0c;发现访问xxx.edu.cn登录页面会优先访问登录后的页面&#xff0c;再跳转至登录页面。盲猜应该是前端校验&#xff0c;可以通过抓包拦…

Qt5 编译oracle数据库驱动

库文件 1、Qt源码目录&#xff1a;D:\Qt5\5.15.2\Src\qtbase\src\plugins\sqldrivers\oci 2、oracle客户端SDK: https://www.oracle.com/database/technologies/instant-client/winx64-64-downloads.html 下载各版本中的如下压缩包&#xff0c;一定要版本相同的 将两个压缩包…

【基础物理实验】【AFM虚拟实验】基于AFM的物质表面微观结构及力学性质表征仿真实验(上)【北京航空航天大学】

基于AFM的物质表面微观结构及力学性质表征仿真实验 说明&#xff1a; 本次实验为本科生《基础物理实验》课程中的虚拟实验部分&#xff0c;在虚拟实验平台中进行。 一、实验目的&#xff1a; 1. 掌握AFM的基本成像原理及系统结构&#xff1b; 2. 掌握AFM的基本操作技巧及操…

【Modelsim】保持波形格式重编译and波形的保存与查看

文章目录 保持原波形格式重编译波形的保持与查看保存波形打开工程查看波形 保持原波形格式重编译 Modelsim 仿真设置好波形格式后&#xff0c;若需要修改代码并保持原波形格式重新查看波形&#xff0c;只需将文件重新编译后仿真即可。 1.修改代码后Project页面的代码状态变成…

特氟龙(PFA)实验室器具有哪些?

PFA 是被称为塑料王&#xff0c;具有出众的化学耐受性&#xff0c;并且可在出色的温度范围内执行工作。 PFA 呈半透明&#xff0c;柔韧&#xff0c;并且由于其高密度重量有点重。PFA 具有惰性和低粘合性&#xff0c;溶出物和痕量金属含量较低。它具有较宽的含氟聚合物温度范围…

3.00 版本来了!DolphinDB V2.00.12 V3.00.0 正式发布!

一文带你了解 DolphinDB 全新版本升级&#xff01; 本次更新后&#xff0c;3.00.0版本将成为 DolphinDB 的最新版&#xff0c;2.00.12版本变更为稳定版&#xff0c;此前发布的1.30.23版本将成为1.30系列的最后一个版本。接下来&#xff0c;带大家一起看看 DolphinDB V2.00.12 …

Directory Monitor:全方位监控文件系统变动的专业利器

目录 一、软件介绍 二、软件功能 三、软件特点 四、安装说明 五、使用说明 一、软件介绍 Directory Monitor是一款强大易用的实时文件系统监视工具&#xff0c;它由Michael Humpa开发&#xff0c;专为满足用户监控特定目录下文件和子目录变化的需求。无论是为了保障系统安…

[蓝桥杯 2019 国 B] 解谜游戏

[蓝桥杯 2019 国 B] 解谜游戏 题目背景 题目描述 小明正在玩一款解谜游戏。谜题由 24 24 24 根塑料棒组成&#xff0c;其中黄色塑料棒 4 4 4 根&#xff0c;红色 8 8 8 根&#xff0c;绿色 12 12 12 根 (后面用 Y 表示黄色、R 表示红色、G 表示绿色)。初始时这些塑料棒排…

游戏实践:扫雷

一.游戏介绍 虽然很多人玩过这个游戏&#xff0c;但还是介绍一下。在下面的格子里&#xff0c;埋的有10颗雷&#xff0c;我们通过鼠标点击的方式&#xff0c;点出你认为不是雷的地方&#xff0c;等到把所有没有雷的格子点完之后&#xff0c;及视为游戏胜利。 上面的数字的意思…

租用马来西亚服务器:稳定高效的网络选择

马来西亚首都是吉隆坡。作为一个新兴的多元化经济国家&#xff0c;也属于亚洲四小龙之一。地理位置优越&#xff0c;中间隔着南中国海。一部分是北接泰国的位于马来半岛的西马来西亚&#xff0c;另一部分则是东马来西亚&#xff0c;在婆罗洲岛的北部。这种地理位置有利于促进该…

Qt | 事件第一节(QApplication、QGuiApplication、QCoreApplication)

一、QApplication、QGuiApplication、QCoreApplication 简介 1、继承关系见下图,其中左侧为顶级父类 2、一个程序中只能有一个 QCoreApplication 及其子类的对象。 3、QCoreApplication:主要提供无 GUI 程序的事件循环。 4、QGuiApplication:用于管理 GUI 程序的控制流和…

LangChain学习笔记与样程

LangChain 是一个开源的机器学习工具库&#xff0c;专门用于构建和部署基于语言的应用程序。这个库提供了一系列工具和接口&#xff0c;使开发者能够轻松地整合和使用大型语言模型&#xff0c;例如 OpenAI 提供的 GPT。LangChain 的核心特点包括模块化设计、灵活性和易用性&…