掃二維碼與項(xiàng)目經(jīng)理溝通
我們?cè)谖⑿派?4小時(shí)期待你的聲音
解答本文疑問(wèn)/技術(shù)咨詢/運(yùn)營(yíng)咨詢/技術(shù)建議/互聯(lián)網(wǎng)交流
最近接手了客戶一個(gè)去年花了一年時(shí)間找省外某軟件公司開發(fā)的一套智能硬件項(xiàng)目,客戶反饋說(shuō)支付的時(shí)候存在報(bào)錯(cuò),而且強(qiáng)調(diào)以前是沒(méi)有問(wèn)題的。這種情況也是我們最不喜歡接手第三方開發(fā)后的項(xiàng)目升級(jí)維護(hù)的,因?yàn)檫@個(gè)項(xiàng)目在此時(shí)我們壓根還沒(méi)涉及修改原來(lái)系統(tǒng)的相關(guān)模塊,也就不可能是我們的迭代工作造成系統(tǒng)的異常。
根據(jù)分析,這個(gè)錯(cuò)誤信息是系統(tǒng)根據(jù)支付系統(tǒng)接口反饋的錯(cuò)誤信息,這種錯(cuò)誤如果支付配置信息沒(méi)問(wèn)題,往往就是發(fā)送的數(shù)據(jù)本身有問(wèn)題。當(dāng)筆者根據(jù)客戶反饋的信息進(jìn)行分析后發(fā)現(xiàn),這個(gè)訂單的金額是一個(gè)特別的數(shù)字1.1元(這個(gè)系統(tǒng)實(shí)際正式使用的時(shí)候金額都是正整數(shù),不會(huì)是小數(shù))??吹竭@個(gè)立馬就想到是數(shù)字計(jì)算的問(wèn)題了,結(jié)果查看原系統(tǒng)支付模塊的源代碼,發(fā)現(xiàn)還真是這樣的。
兩個(gè)環(huán)節(jié)導(dǎo)致該問(wèn)題出現(xiàn):
1、由于本系統(tǒng)使用的是銀聯(lián)在線支付通道(聚合銀行卡、微信、支付寶等支付方式),但對(duì)于技術(shù)對(duì)接上的金額部分,跟微信一樣采用的是以分為單位,比如1.1元,傳給系統(tǒng)的數(shù)據(jù)應(yīng)該是110的整數(shù)。而原來(lái)的開發(fā)人員直接把浮點(diǎn)型的金額數(shù)據(jù)乘以100(即金額*100)。
2、在系統(tǒng)向銀聯(lián)在線發(fā)送支付請(qǐng)求是,需要對(duì)內(nèi)容數(shù)據(jù)轉(zhuǎn)化成json字符串,在php中使用json_encode方法。
安裝我們正常的數(shù)學(xué)邏輯,1.1元換算成分,就是乘以100就行了結(jié)果肯定等于110,也是我們想要的數(shù)據(jù)了。然而在php中,浮點(diǎn)運(yùn)算是存在精度的問(wèn)題的,甚至不同php版本運(yùn)算得到的結(jié)果是不一樣的。比如就以例子中1.1舉例。在PHP7.4版本中得到的結(jié)果如下:
期望的結(jié)果應(yīng)該是{“amount”:110},而實(shí)際得到的結(jié)果卻是{“amount”:110.00000000000001}。而且不同的php軟件版本和不同的數(shù)字得到的結(jié)果正確與否的結(jié)果也不同,比如同樣的是php7.4版本下,1.20通過(guò)計(jì)算得到的結(jié)果跟預(yù)期一樣是{“amount”:120}。
所以,這種異常的結(jié)果沒(méi)有確定的規(guī)律可言,而且跟我們所需要的預(yù)期結(jié)果并不一致,于是在程序計(jì)算中必然會(huì)存在某些金額導(dǎo)致出錯(cuò)的情況。
如何解決?
解決的辦法就是在進(jìn)行數(shù)學(xué)運(yùn)算的時(shí)候,我們可以利用一些高精度的計(jì)算函數(shù)來(lái)完成。比如我們之前就介紹過(guò)的BC高精度計(jì)算類(關(guān)于這個(gè)類的基本使用可以參考我們幾年前分享的文章《利用PHP高精確度運(yùn)算BC函數(shù)庫(kù)解決小數(shù)計(jì)算異常問(wèn)題》),當(dāng)然除此之外還有更多的工具和方法??偠灾?,我們遇到此類場(chǎng)景的時(shí)候切不可隨意為之,否則會(huì)讓自己或者你的協(xié)作者掉進(jìn)大大的坑里。
我們?cè)谖⑿派?4小時(shí)期待你的聲音
解答本文疑問(wèn)/技術(shù)咨詢/運(yùn)營(yíng)咨詢/技術(shù)建議/互聯(lián)網(wǎng)交流