Stripe自定义支付流CalculateOrderAmount()函数PHP报错咨询
问题排查方向
- 前端抛出的
Unexpected end of JSON input错误,核心成因是后端接口返回了空响应、中途中断执行,没有输出合法的JSON结构,和前端本身逻辑无关,可按以下优先级排查:- 函数调用不匹配:当前定义的
CalculateOrderAmount()是无参函数,但创建PaymentIntent的代码中给函数传入了$json_obj->items作为参数,PHP会触发参数不匹配的警告,若未做错误捕获会直接中断脚本执行,前端拿到空响应后就会报JSON解析错误。 - 全局变量作用域失效:原实现中
CalculateOrderAmount()通过global关键字获取$price值,必须保证函数执行时,全局作用域的$price已经完成数据库查询赋值,否则会取到空值,触发后续逻辑报错中断。 - 数据库执行异常:原SQL直接拼接
$_SESSION['orderRef']值,没有做参数绑定,若session值为空、类型不匹配会直接导致SQL执行报错,脚本中断返回空响应。 - 响应输出缺失:原PaymentIntent创建逻辑完成后,没有将结果转成JSON格式输出给前端,前端自然无法解析到有效内容。
- 函数调用不匹配:当前定义的
正确实现指引
1. 重构金额计算函数
摒弃依赖全局变量的写法,将数据库连接、订单标识作为明确参数传入函数,同时做SQL参数绑定防注入,注意Stripe要求的金额为对应货币的最小粒度值(欧元的最小单位是分,计算结果需乘100转换):
function CalculateOrderAmount(PDO $dbh, string $orderRef): int { // 预处理SQL避免注入风险 $stmt = $dbh->prepare('SELECT COUNT(*) as card_count FROM card WHERE orderRef = :order_ref'); $stmt->bindParam(':order_ref', $orderRef, PDO::PARAM_STR); $stmt->execute(); $result = $stmt->fetch(PDO::FETCH_ASSOC); // 示例:单商品单价10欧元,转成分单位返回 return (int)$result['card_count'] * 10 * 100; }
2. 修正PaymentIntent创建流程
增加全局错误捕获、统一JSON输出逻辑,杜绝脚本中断导致的空响应:
<?php // 关闭错误直接输出,避免打乱JSON结构 ini_set('display_errors', 0); header('Content-Type: application/json'); session_start(); // 用到$_SESSION前必须初始化 try { // 初始化数据库连接 $dbh = new PDO( DB_DSN, DB_USER, DB_PASS ); $dbh->setAttribute( PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION ); // 解析前端POST的JSON入参 $json_str = file_get_contents('php://input'); $json_obj = json_decode($json_str, true); if (json_last_error() !== JSON_ERROR_NONE) { throw new Exception('Invalid request format'); } // 调用金额计算函数 $amount = CalculateOrderAmount($dbh, $_SESSION['orderRef']); // 创建PaymentIntent $paymentIntent = \Stripe\PaymentIntent::create([ 'amount' => $amount, 'currency' => 'eur', 'payment_method_types' => ['card'] ]); // 输出合法JSON响应给前端 echo json_encode([ 'clientSecret' => $paymentIntent->client_secret ]); exit; } catch (Exception $e) { // 异常时也返回合法JSON结构,避免空响应 http_response_code(400); echo json_encode([ 'error' => ['message' => $e->getMessage()] ]); exit; }
高频避坑提醒
- 开发阶段不要用
var_dump、echo输出调试内容,这类内容会混在JSON响应中,导致前端解析失败 - 不要使用欧元数值直接当Stripe的传入金额,必须转换为分的整数单位,否则会触发Stripe参数校验报错
- 不要依赖全局变量传值,跨作用域的依赖要通过函数参数明确传递,减少隐式作用域不匹配的问题
- 做入参、session值的非空校验,避免空值触发数据库执行报错
内容的提问来源于stack exchange,提问作者SosoK
相关产品推荐
相关产品推荐

