PHP cURL发送JSON请求返回400错误:schema不正确,如何解决?
问题分析与解决方案
这个问题我遇到过类似的,核心原因大概率是Authorization头的格式处理错误,再加上一些容易忽略的细节,导致服务器返回了看似JSON格式错误的400响应。咱们一步步拆解:
问题出在哪?
认证头的自动转换差异
你在curl命令里写Authorization: login:password时,curl会自动把login:password转换成Basic认证的标准格式——也就是先做base64编码,再加上Basic前缀。但PHP的cURL不会帮你做这个转换,直接传login:password的话,服务器根本无法识别这个认证信息,可能直接拒绝请求,返回的400错误只是服务器抛出的通用提示,而非真的JSON格式有问题。JSON编码的潜在隐患
虽然你用了json_encode,但如果$number或$msg包含特殊字符(比如未转义的引号、控制字符),可能导致编码失败或生成不符合API要求的JSON,这也会触发schema错误。重复设置URL的冗余操作
你先通过curl_init($url)初始化了URL,之后又用CURLOPT_URL覆盖成config('kajaki.sms_url'),虽然不会直接报错,但容易混淆,建议统一设置方式。
修正后的完整代码
$number = "+48667421797"; $msg = "Great app! Thank you!"; $url = config('kajaki.sms_url'); // 构建请求体数组 $fields = [ 'phone' => $number, 'msg' => $msg, ]; // 确保JSON编码有效,添加错误检查 $data = json_encode($fields); if ($data === false) { die('JSON编码失败: ' . json_last_error_msg()); } // 手动构建标准Basic认证头 $login = 'login'; $password = 'password'; $authHeader = 'Authorization: Basic ' . base64_encode("$login:$password"); // 整理请求头,加入Content-Length帮助服务器识别请求体大小 $headers = [ 'Content-Type: application/json', $authHeader, 'Content-Length: ' . strlen($data) ]; // 初始化cURL并设置选项 $ch = curl_init($url); curl_setopt($ch, CURLOPT_POST, true); curl_setopt($ch, CURLOPT_POSTFIELDS, $data); curl_setopt($ch, CURLOPT_HTTPHEADER, $headers); curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); // 开发环境可临时关闭SSL验证(生产环境务必开启) // curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false); // curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false); // 执行请求并处理结果 $response = curl_exec($ch); if (curl_errno($ch)) { die('Curl执行错误: ' . curl_error($ch)); } $httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE); curl_close($ch); // 输出调试信息 echo "HTTP状态码: $httpCode\n"; echo "响应内容: $response\n";
关键优化点说明
- 修复认证头:手动将账号密码转成base64编码的Basic格式,和curl命令的自动行为保持一致,确保服务器能正确识别认证信息。
- 添加JSON编码检查:避免因数据问题生成无效JSON,提前排查编码错误。
- 加入Content-Length头:帮助服务器准确读取请求体,减少解析时的异常。
- 统一URL设置:直接在
curl_init里传入正确的URL,避免冗余操作。
内容的提问来源于stack exchange,提问作者Gacek
相关产品推荐
相关产品推荐

