前言

支付场景,是程序开发就常见的场景之一了,绝大多数公司是不具备支付资格的,所以就会引入第三方支付,支付宝支付,微信支付,银联支付,银企直连等等。所有代码都是面向钱编程,战战兢兢,如履薄冰。所以,写出一个高可用的支付程序是非常有必要的。

一、为什么支付要面向失败编程?

作为一个程序员,遇到过太多如下场景:明明各种测试都通过了,没有问题了,到了线上就各种问题频发?明明正常运行了很久的代码,怎么突然就出问题了?在支付场景中,那就更多了,问题各种各样,无处不在,比如支付出现了,长款、短款等等。

短款:是指银行出纳部门实际存入的现金少于记录的现金;简单点说是公司亏钱了;
长款:是指现金收支中实际存入的现金多于记录的现金的现象;简单点说是用户少收钱了。

对于支付场景中,造成钱出现问题情况,先不考虑对公司造成多大影响,只站在程序员个体角度,影响也同样巨大,企业的事故责任终究要落到程序员个人头上,而事故也往往会消耗组织对于个人的信任,直接或者间接地影响个人的发展,一次事故往往意味着程序员“一年白干”,或者其他更严重的结果。什么升职加薪,醒醒吧,不用想了!

做最危险的活,挨最疼的打。

当然,作为一个程序员,我们肯定不能因为种种原因,就不做了,或者就不做支付了,对吧?
那么,我们如何来提升支付场景代码可靠性呢?答案肯定有很多,我的答案是面向失败编程?
不同级别的程序员差异到底在哪里?
这个问题,我不说什么架构设计、领导力这些东西,就只说编程这一点,面向失败编程也是极其重要的一环。
业务开发的同学有时候可能会有迷之自信,觉得自己写的代码与老鸟们没有什么不同。实际上,编写正常流程的业务代码大家的差异不会太大,但是针对异常、边界、不确定性的处理才真正体现一个程序员的功力。高手们往往在长期的在各种问题的摩擦下,产生了大量问题的解决方案,形成了肌肉记忆,也可以说经验;遇到具体问题就会举一反三脑海里冒出诸多问题点,并且知道如何去规避,从而写出高可用的业务代码。
所以,面向失败编程,并慢慢形成自己独有的肌肉记忆,这是成为高手的必经之路!

二、方法论

答案就是面向对象六大原则:单一职责原则、开闭式原则、迪米特原则、里氏替换原则、依赖倒置原则,接口分离原则;这些你不知道么,肯定知道,对不对?但是在实际开发过程中,你能用多少呢?哪个不是说:进度这么赶,你跟我谈什么设计模式?先这样吧,后面再说吧!有没有中枪?
据我的经验来看,首次开发阶段阶段,不好好设计,不好好开发,后续基本或者极少去修改代码,如果换人接受,拿去优化代码几率趋近于零。
当然,我要说的答案不是这个,什么设计模式都是次要的,真正主要的是:作为一个程序员,要本着对程序有所追求的原则,才能写出优秀的代码。这就是我给出的方法论,只有在这个大前提下,才能让我们的代码,精益求精;没有这个大前提,多年开发下来,可能长的只是年龄。这是我这两年,悟出来的,相见恨晚!

三、支付流程简述

我们来看一下,阿里的支付的流程图:

一个支付场景,从用户发起支付请求,到一个支付的完结,有这么多的流程步骤。当然,如果我们考虑正常场景,那也简单,我们只要考虑正常情况就可以了,找个能看懂文档的开发就ok了,而且,99%的以上的情况,支付都是正常的;但是往往是极少概率发生的失败、异常往往给我们,给公司造成极大的损失;而且,异常处理要写的代码量,是正常情况的无数倍。
想象一下网络正常、数据库正常,公司环境正常,服务器正常等等,这些可能么,不可能?所以,一个好的支付代码,必须 要考虑非常多的失败情况。
比如上图第5步,请求支付宝,请求超时/请求断了,我们不知道,这个支付到底成功还是失败,怎么办?
1、等待回调,根据回调结果进行处理;
2、查询支付宝订单状态,进行处理;
3、对支付请求进行finally处理,增加中间状态,事后进行补偿处理;
……

四、面向支付失败编程

支付,面向失败编程,说了这么多,是不是有些怕怕的,其实,我们也没有必要对支付给吓倒,掌握一些诀窍,在一些关键步骤上,做好处理就行了;
come on,说一些鄙人的经验:
1、支付的时候,先确定钱没问题,然后再处理业务数据;
2、退款的时候,先处理业务,再退款;
3、分布式锁进行并发处理;
4、事务处理:写代码的时候,不要直接在方法上,加事务注解,遇到分布式场景,事务注解往往会引起一些奇怪的问题;要用事务的话,考虑缩小事务范围,手动提交事务,异常进行告警处理。
5、网络异常的考虑重试;
6、对于失败的请求,进行补偿处理;
7、每天对产生的账务,进行对账,监控报警;
总之,尽量把主动权(钱)控制在自己手里,即使出了问题,只要钱可控都好处理。

五、结语

支付:面向失败编程,更多的是在编程的时候,考虑如果失败了,怎么办?该如何处理。
还有面向失败并非只能用在支付场景;也并非什么场景都要用,比如你发一条消息推送,还去考虑各种各样的失败,就没有意义了;目的是增加系统可靠性;减少手动处理问题的情形。
说了这些,并不代表,我对支付已经多了解了,我只是想给大家传达一种未雨绸缪的思想;一种面向失败编程的思想;抛砖引玉,希望大家在今后的开发过程中,少犯错误而已。欢迎大家评论留言,大家互相学习。

参考文档:
向死而生:面向失败设计之道、术、技

【Java分享客栈】一个包装过简历的新同事写完微信支付引起事故后果断离职了

更多推荐

支付:面向失败编程