微信支付V3 JSAPI 调用微信失败记录 作者:pandali 时间:2021年09月06日 分类:PHP,计算机技术 字数:1820 warning: 这篇文章距离上次修改已过291天,其中的内容可能已经有所变动。 今天运营小伙伴反馈说当商品金额设置为1.16时,调起微信失败。 我们的接口使用的是Thinkphp 5.3 + Mysql 5.6进行的开发 数据库中商品的的价格字段是 `price` decimal(10,2) NOT NULL DEFAULT '0.00' COMMENT '付费金额', 因为微信支付的金额单位是分,所以需要将元转成分及1.16 * 100; 原本以为这样就可以了,结果微信报错,提示数据为 1.15999999... 刚开始没有反应过来,以为是微信数据转换的问题,后来才反应过来 decimal 的数据类型其实就是float 型 而float是浮点型,用来表示实数,其值是近似值。 所以使用intval(1.16 * 100) 进行转换,以为这样就可以了,结果返回的是 115 原因可参考[PHP 源码 — intval 函数源码分析][1] ``` PHP_FUNCTION(intval) { zval *num; zend_long base = 10; ZEND_PARSE_PARAMETERS_START(1, 2) Z_PARAM_ZVAL(num) Z_PARAM_OPTIONAL Z_PARAM_LONG(base) ZEND_PARSE_PARAMETERS_END(); if (Z_TYPE_P(num) != IS_STRING || base == 10) { RETVAL_LONG(zval_get_long(num)); return; } if (base == 0 || base == 2) { char *strval = Z_STRVAL_P(num); size_t strlen = Z_STRLEN_P(num); while (isspace(*strval) && strlen) { strval++; strlen--; } /* Length of 3+ covers "0b#" and "-0b" (which results in 0) */ if (strlen > 2) { int offset = 0; if (strval[0] == '-' || strval[0] == '+') { offset = 1; } if (strval[offset] == '0' && (strval[offset + 1] == 'b' || strval[offset + 1] == 'B')) { char *tmpval; strlen -= 2; /* Removing "0b" */ tmpval = emalloc(strlen + 1); /* Place the unary symbol at pos 0 if there was one */ if (offset) { tmpval[0] = strval[0]; } /* Copy the data from after "0b" to the end of the buffer */ memcpy(tmpval + offset, strval + offset + 2, strlen - offset); tmpval[strlen] = 0; RETVAL_LONG(ZEND_STRTOL(tmpval, NULL, 2)); efree(tmpval); return; } } } RETVAL_LONG(ZEND_STRTOL(Z_STRVAL_P(num), NULL, base)); } ``` 所以这里正确的转换是 intval(strval(1.16 * 100)) [1]: https://www.cnblogs.com/ishenghuo/p/11803114.html