微信支付金额浮点分计算php,复盘微信支付金额不正确问题解决过程——PHP浮点型计算...
問(wèn)題
2017年9月份,商城項(xiàng)目在運(yùn)行過(guò)程中,購(gòu)買(mǎi)某商品時(shí)如果在下單時(shí)沒(méi)有完成付款,而是稍后再?gòu)摹皞€(gè)人中心-我的訂單”發(fā)起付款,則無(wú)法調(diào)起微信支付界面
思路
其他商品正常,說(shuō)明導(dǎo)致問(wèn)題的原因大概率是商品本身
只有從會(huì)員中心發(fā)起的付款存在此問(wèn)題,說(shuō)明大概率是會(huì)員中心的代碼存在問(wèn)題
需要先觀察問(wèn)題出現(xiàn)時(shí)“統(tǒng)一下單”是否能夠成功,檢查是否是參數(shù)問(wèn)題導(dǎo)致訂單無(wú)法在微信端創(chuàng)建
觀察統(tǒng)一下單返回值
result_code=FAIL
err_code=OUT_TRADE_NO_USED
err_code_des=商戶訂單號(hào)重復(fù)
微信官方對(duì)于此問(wèn)題的描述如下:
image.png
出現(xiàn)這個(gè)問(wèn)題的時(shí)候建議核查訂單號(hào)是否重復(fù)提交,但實(shí)際上在這個(gè)使用場(chǎng)景下,我們是“故意”重復(fù)提交訂單號(hào)的。因?yàn)閺臅?huì)員中心發(fā)起支付的時(shí)候訂單已經(jīng)創(chuàng)建了,系統(tǒng)會(huì)再次請(qǐng)求微信統(tǒng)一下單接口,即便如此,我們也沒(méi)有必要每一次請(qǐng)求支付都創(chuàng)建一個(gè)新的訂單號(hào)。
那為什么返回了這個(gè)錯(cuò)誤
我先給出結(jié)論再描述排錯(cuò)過(guò)程:
所謂的同一筆交易不能多次提交,實(shí)際上指的是在商品描述、標(biāo)價(jià)金額不相同的情況下,用同一個(gè)訂單號(hào)訪問(wèn)了統(tǒng)一下單接口。
image.png
這里的錯(cuò)誤實(shí)際上是因?yàn)?#xff1a;從會(huì)員中心發(fā)起支付時(shí)“標(biāo)價(jià)金額”與提交訂單時(shí)的不相同。
PHP浮點(diǎn)型運(yùn)算
以下是某位程序員寫(xiě)的微信支付代碼:
$total_fee = (int)($order_total * 100);
微信要求金額的單位必須為分,而數(shù)據(jù)庫(kù)中訂單金額單位是元,所以使用訂單金額*100是正確的做法。
訂單支付金額的計(jì)算非常復(fù)雜,所以單位轉(zhuǎn)化為分之后再轉(zhuǎn)化為整型,可以保證微信支付參數(shù)不出錯(cuò),也是正確的做法。
但這里面隱藏了一個(gè)問(wèn)題,還記得我們問(wèn)題發(fā)生的條件必須是“購(gòu)買(mǎi)某商品時(shí)”嗎?如果單獨(dú)購(gòu)買(mǎi)這個(gè)商品的話,訂單的金額是19.9。我們可以嘗試:
echo (int)(19.9 * 100);
// 結(jié)果為1989,而非1990
這就導(dǎo)致了訂單創(chuàng)建時(shí)給微信的支付數(shù)據(jù)是1990,而再次支付時(shí)卻是1980,所以接口返回了“訂單號(hào)重復(fù)”的錯(cuò)誤。
為什么會(huì)少了1分錢(qián)呢?PHP的官方文檔中是這么說(shuō):
image.png
隨后我又實(shí)驗(yàn)了很多數(shù)字,結(jié)果如下:
echo (int)(19.1 * 100);// 1910
echo (int)(19.2 * 100);// 1920
echo (int)(19.3 * 100);// 1930
echo (int)(19.4 * 100);// 1939 注意這里出現(xiàn)了問(wèn)題
echo (int)(19.5 * 100);// 1950
echo (int)(19.6 * 100);// 1960
echo (int)(19.7 * 100);// 1970
echo (int)(19.8 * 100);// 1980
這個(gè)問(wèn)題的產(chǎn)生,似乎存在規(guī)律,例如19.4、18.4和17.4轉(zhuǎn)化后是錯(cuò)誤的,而8.4轉(zhuǎn)化后返回了正確的結(jié)果。
更有趣的是:
echo (int)((19.8+0.1) * 100);
// 1990 注意此時(shí)結(jié)果是正確的
var_dump(19.9 == (19.8 + 0.1));
// false
調(diào)試過(guò)程
實(shí)際上這種奇怪的問(wèn)題排查起來(lái)沒(méi)有什么捷徑,無(wú)非就是打日志追蹤變量,最多也就是細(xì)心點(diǎn)罷了。
最終使用了一個(gè)比較討巧的方式解決了這個(gè)問(wèn)題,將代碼改為了:
$total_fee = (int)(($order_total + 0.00001) * 100);
至于更加嚴(yán)謹(jǐn)?shù)母↑c(diǎn)數(shù)計(jì)算方法,今后遇到的時(shí)候,再研究吧。
總結(jié)
以上是生活随笔為你收集整理的微信支付金额浮点分计算php,复盘微信支付金额不正确问题解决过程——PHP浮点型计算...的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: win10系统如何配置web服务器,Wi
- 下一篇: api限流