JudoPay支付接口金额格式错误排查:本地正常生产环境报错
问题场景
本地环境使用PHP Server SDK调用JudoPay卡支付接口功能正常,但生产环境(即使使用沙箱密钥)触发400错误:
Error: JudoPay ApiException (status code 400, error code 1, category 2) Sorry, we're unable to process your request. Please check your details and try again. Fields errors:
field "Amount" (code 6): Sorry, but the amount submitted does not match the decimal place requirements for the currency submitted. Please amend the format to meet the currency requirements.
相关支付代码:
$total_amount = $_SESSION['checkout_subtotal']; $total_amount += $delivery; // judopay payment creation $payment = $judopay->getModel('Payment'); // Generate unique references $consumerReference = generateGUID(); // Generate GUID for customer reference $paymentReference = generatePaymentReference('pay-'); // Generate payment reference $fixed_amount = (float) number_format($total_amount, 2, '.', ''); $payment->setAttributeValues( array( 'judoId' => $judoId, 'yourConsumerReference' => $consumerReference, 'yourPaymentReference' => $paymentReference, 'amount' => $fixed_amount, 'currency' => 'GBP', 'cardNumber' => $cardNumber, 'expiryDate' => $expiryDate, 'cv2' => $cv2, ) ); // judopay payment request creation and exceptions handling try { $response = $payment->create(); if ($response['result'] === 'Success') { echo json_encode(['success' => true, 'response' => $response]); } else { echo json_encode(['success' => false, 'response' => $response, 'error' => 'Payment failed: There were some problems while processing your payment.']); } } catch (\Judopay\Exception\ApiException $apiException) { echo json_encode([ 'success' => false, 'error' => $apiException->getSummary() ]); } catch (\Judopay\Exception\ValidationError $validationErrors) { // Required attributes are missing from the request echo json_encode([ 'success' => false, 'error' => $validationErrors->getSummary() ]); } catch (Exception $e) { // Returning JSON response with success as false and error message echo json_encode([ 'success' => false, 'error' => $e->getMessage() ]); }
已确认金额为保留两位小数的float类型(如7.98,货币为GBP),但问题仍未解决。
可行解决方案
1. 传递整数形式的最小货币单位
JudoPay接口支持接收以最小货币单位为单位的整数(GBP对应便士,1英镑=100便士),彻底规避浮点精度问题:
// 替换原金额计算逻辑 $total_amount = $_SESSION['checkout_subtotal'] + $delivery; $fixed_amount = (int)round($total_amount * 100); // 7.98英镑转成798便士
2. 保留金额为字符串格式
避免将格式化后的金额转为float,直接传递number_format返回的字符串,确保接口收到标准两位小数格式:
// 去掉(float)强制转换 $fixed_amount = number_format($total_amount, 2, '.', '');
3. 检查生产环境浮点精度
生产环境PHP的precision配置可能与本地不同,导致float值序列化后出现精度偏差。可临时添加调试输出对比数值:
var_dump($fixed_amount); // 查看实际传递给接口的数值
4. 提前对总金额做四舍五入
确保总金额计算后就是标准两位小数,避免后续格式化出现精度问题:
$total_amount = round($_SESSION['checkout_subtotal'] + $delivery, 2); $fixed_amount = number_format($total_amount, 2, '.', '');
内容的提问来源于stack exchange,提问作者Abdullah

