Stripe集成Symfony时报错:尝试获取非对象的'items'属性如何解决
报错原因
- 核心原因是
json_decode()执行后返回了非对象值(通常是null),后续强行访问$json_obj->items属性触发报错。触发场景主要包含以下几种:- 路由未限制请求方法:当前
@Route注解未指定methods={"POST"},当GET请求访问该地址时,php://input为空,json_decode直接返回null - 前端提交的JSON格式非法,或未携带
items字段,导致解析失败 - 代码未做JSON解析结果校验,无论解析成功与否都直接访问对象属性,缺少防御逻辑
- 路由未限制请求方法:当前
- 额外不规范点:控制器内直接调用
header()、echo输出、重复加载autoload.php、输出JSON后仍返回Twig模板响应,属于不符合Symfony开发规范的写法,也会引发额外输出冲突问题
修复方案
- 调整路由注解,限制仅接受POST请求
- 改用Symfony原生
Request对象获取请求载荷,替代手动读取php://input - 增加JSON解析结果校验,解析失败或缺少
items字段时直接返回错误响应 - 移除冗余的
vendor/autoload.php加载逻辑,改用JsonResponse返回接口结果,处理完支付逻辑后直接返回响应,避免后续模板渲染逻辑执行 - 完善异常捕获范围,覆盖Stripe抛出的相关异常
修复后参考代码:
<?php namespace App\Controller; use Symfony\Bundle\FrameworkBundle\Controller\AbstractController; use Symfony\Component\HttpFoundation\JsonResponse; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\Routing\Annotation\Route; // 密钥建议放在.env文件中通过$this->getParameter('stripe_secret_key')读取,不要硬编码在代码里 \Stripe\Stripe::setApiKey('你的Stripe密钥'); class CompraController extends AbstractController { /** * @Route("/compra", name="compra", methods={"POST"}) */ public function index(Request $request): JsonResponse { function calculateOrderAmount(array $items): int { // 替换为实际的订单金额计算逻辑 return 1400; } try { // 从Request对象获取JSON内容 $json_obj = json_decode($request->getContent()); // 校验解析结果和items字段 if (!$json_obj || !isset($json_obj->items) || !is_array($json_obj->items)) { return new JsonResponse(['error' => '无效的请求参数'], 400); } $paymentIntent = \Stripe\PaymentIntent::create([ 'amount' => calculateOrderAmount($json_obj->items), 'currency' => 'brl', ]); return new JsonResponse([ 'clientSecret' => $paymentIntent->client_secret, ]); } catch (\Exception $e) { return new JsonResponse(['error' => $e->getMessage()], 500); } } }
内容的提问来源于stack exchange,提问作者Pedro Cruz
相关产品推荐
相关产品推荐

