扫二维码与项目经理沟通
我们在微信上24小时期待你的声音
解答本文疑问/技术咨询/运营咨询/技术建议/互联网交流
背景
今天一个即将完成的项目,测试童鞋跟开发童鞋讲微信支付出bug了,支付完成后订单却没有更新状态了。开发童鞋马上讲,这块代码这几天一直没更新啊,不一直都好好的么,测试就别给我添乱了。正当测试和开发准备“吵架”的时候我听到了,对他们说再测几遍。
结果开发自己拿起手机测试这个支付模块,发现没有任何问题,于是他准备怼回测试;但很不幸测试继续下单发现依然不对劲。结果他们两扯了几个来回,终于得到了一个共识,也就是发现了一个这样神奇的规律:
“开发测试的支付金额都是1元、1.5元、2元之类的,所以都是成功的,而测试没有回调成功的其中就有1.1元、1.11元之类的,而其他的金额也是回调成功的。”
分析
然后我就跟开发交代说看看日志,这肯定是异步回调出问题了!由于这位开发童鞋经验并不怎么丰富,于是马上就说如果回调错了,怎么可能跟逻辑有关系呢?他对我说:
“x哥,你帮我读读我的代码,看到底是哪里的问题?”
没办法,小伙伴遇到难题只能上呗,于是打开他的回调通知模块的代码,发现他在整个回调处理上做得还可以,按照了微信支付官方建议的安全措施去做支付后的校验,而校验中的一个校验规则便是订单需要支付的金额,跟这笔微信支付订单微信返回的金额是否一致,如果一致则通过该项校验,否则不通过。
而上面的问题刚好是跟金额有关系,首先先排除其他的校验规则,为了保险起见分析了多笔支付的回调数据日志,发现其他校验并没有问题。也就是问题就初步定位在金额校验这个步骤上面,如果这一步校验不通过后续更新订单以及其他相关操作都无法执行下去。
结果我发现他的校验处的核心代码为:if(100*$order['pay_feel']==$result['total_fee']){},其中$order是订单信息,而$result是解析微信服务器返回xml解析后的一个数组,而100是微信支付金额的一个比值,100代表1块钱,这个做过微信支付的同学都知道。
可能对于写惯了强类型语言(如java、python等)代码的人来讲,这不是一个好的代码,但实际上有很多phper写的代码都是这样写的,当然这是一种不是特别严谨的写法。但php作为一种弱类型语言,对于这样的问题它似乎很多时候都是“睁一只眼闭一只眼”。
解决
首先我们来看看下面几组php基础性的知识运行结果:
就是说111在默认情况下php把它当做int处理,而1.11以及它乘以一个数值是当做float来处理的,当然1.21或者1.2也是会当做float来处理的;可以自己多尝试几次。接下来我们要回顾编程的基础知识了。也就是=、==以及===的区别,至于他们的区别这里不多说,这里就说==比较的是什么?通俗地讲==我们只是比较值,而不比较类型,比如下面的几个结果:
也就是说,从理论上来讲,他上面的代码执行后的结果应该是能够达到我们的预期目的的,也就是==在这里是成立的。但事实上是:
其实这就是php作为弱类型语言的一些缺陷,实际上有的结果甚至在32位和64位处理器的电脑上执行的结果也不一致。这也就是说在面向这些问题的时候,我们应该往更加健壮的目标去发展,比如最基础的就是在判断前把两者的数据类型强制转换成为一致(同时请注意php分数计算的坑,哈哈),这个问题即可解决。
后语
其实如果大家了解甚至是写过很多诸如java、C之类的代码,就会对上述问题有更深层次的的了解,有兴趣的童鞋可以读读php的源代码。
我带过很多开发,我发现特别是一些开发新手,越是对这些非常基础的东西不屑一顾。认为这些东西太简单了,而我一直都强调的是基础非常重要,我觉得作为一个优秀的开发者,技术基础、经验、沟通、产品理解等等缺一不可。遗憾的是,很多开发者只在乎前沿的技术,而对其他的东西似乎都很不屑!
我们在微信上24小时期待你的声音
解答本文疑问/技术咨询/运营咨询/技术建议/互联网交流