求助:Laravel Omnipipay调用PayPal Rest API遇金额校验validation_error
解决Omnipipay调用PayPal Rest API的金额验证错误
这个错误「Item amount must add up to specified amount subtotal (or total if amount details not specified)」本质是PayPal的金额一致性校验失败——它要求所有商品项的金额总和必须与你指定的subtotal(如果提供了金额明细)或total(如果没提供明细)完全匹配。结合你的场景(商品25.00+运费4.99=总计29.99),可以按以下步骤排查修复:
1. 正确拆分金额参数,明确传递明细
PayPal Rest API在涉及运费、税费等额外费用时,需要你明确区分商品总价(subtotal)、运费(shipping)和总金额(total),而不是只传总金额。同时必须保证:
- 所有商品项的
price * quantity总和 =subtotal subtotal + shipping(如果有税费还要加tax)=total
在Omnipipay中,你需要这样构建请求参数:
$gateway = Omnipipay::create('PayPal_Rest'); $gateway->setClientId('你的Client ID'); $gateway->setSecret('你的Secret'); $gateway->setTestMode(true); // 沙箱环境保持开启,生产环境关闭 $response = $gateway->purchase([ 'amount' => '29.99', // 总金额 'currency' => 'USD', // 根据你的实际币种调整 'returnUrl' => 'https://www.**/offer/1/pay/success', 'cancelUrl' => 'https://www.**/offer/1/pay/cancel', // 商品项必须和subtotal严格匹配 'items' => [ [ 'name' => '你的商品名称', 'quantity' => 1, 'price' => '25.00', 'currency' => 'USD', ], ], 'subtotal' => '25.00', // 商品总价,必须等于items的金额总和 'shipping' => '4.99', // 运费 ])->send();
2. 规避PHP浮点精度问题
虽然你设置了serialize_precision=-1,但浮点数在序列化传递时仍可能出现精度丢失(比如25.00 + 4.99在底层可能被解析为29.989999999999995),导致PayPal端校验不通过。所有金额参数都用字符串传递是最稳妥的方式,避免浮点运算带来的误差。
3. 验证完整请求体
如果还是报错,建议开启Omnipipay的日志功能,查看实际发送给PayPal的请求体,确认:
items数组中每个商品的amount(price*quantity)总和是否确实等于subtotalamount对象下的total、subtotal、shipping是否完全匹配你的预期值
比如PayPal期望的请求体结构应该类似:
{ "intent": "sale", "payer": { "payment_method": "paypal" }, "transactions": [ { "amount": { "total": "29.99", "currency": "USD", "details": { "subtotal": "25.00", "shipping": "4.99" } }, "item_list": { "items": [ { "name": "你的商品名称", "quantity": "1", "price": "25.00", "currency": "USD" } ] } } ], "redirect_urls": { "return_url": "https://www.**/offer/1/pay/success", "cancel_url": "https://www.**/offer/1/pay/cancel" } }
确认以上几点后,PayPal的金额校验应该就能通过了。
内容的提问来源于stack exchange,提问作者Alexander S.
相关产品推荐
相关产品推荐

