可用JavaScript API请求转PHP Curl后返回空响应,求排查问题
问题描述
我有一段可正常运行的JavaScript API调用代码:
var headers = { Authorization: "Bearer " + MY_ACCESS_TOKEN }; var requestParams = { method: "POST", contentType: "application/json", headers: headers, payload: JSON.stringify({ query: 'query {adSet(id: "' + MY_ADSET_ID + '") {insights(timeRange: {from: "2023-08-01T00:00:00Z", until: "2023-08-10T23:59:59Z"}timeIncrement: DAILY) {timestamps reports {impressions conversions offerwallImpressions offerwallAverageRank spend}}}}' }) var response = UrlFetchApp.fetch(MY_API_ENDPOINT, requestParams); var data = JSON.parse(response);
将其转换为PHP Curl实现后,API仅返回空响应。已知my_curl函数用于获取$MY_ACCESS_TOKEN时可正常工作,请问我哪里出错了?
我的PHP代码:
$postdata = json_encode('query: query {adSet(id: "' . $MY_ADSET_ID . '") {insights(timeRange: {from: "2023-08-01T00:00:00Z", until: "2023-08-10T23:59:59Z"} timeIncrement: DAILY) {timestamps reports {impressions conversions offerwallImpressions offerwallAverageRank spend}}}}'); $endpoint = $MY_API_ENDPOINT; $headers = array ( "Content-Type: application/json", "Authorization: Bearer " . $MY_ACCESS_TOKEN, $postdata ); $data = my_curl ($endpoint, $headers); var_dump ($data); function my_curl ($endpoint, $headers) { $ch = curl_init (); curl_setopt ($ch, CURLOPT_URL, $endpoint); curl_setopt ($ch, CURLOPT_POST, 1); curl_setopt ($ch, CURLOPT_HTTPHEADER, $headers); curl_setopt ($ch, CURLOPT_HEADER, false); curl_setopt ($ch, CURLOPT_RETURNTRANSFER, true); $server_output = curl_exec($ch); curl_close ($ch); $json = json_decode ($server_output, true); return ($json); }
错误分析与修正
你的PHP代码存在三个关键错误,导致API返回空响应:
- POST请求体放置位置错误:你把请求体
$postdata塞进了请求头数组里,这不符合HTTP协议规范。在PHP Curl中,POST请求体需要通过CURLOPT_POSTFIELDS参数单独设置,而不是放在请求头中。 - JSON编码格式错误:JavaScript代码是将包含
query键的对象转为JSON,而你直接对字符串'query: ...'做JSON编码,生成的是不符合API要求的JSON字符串,而非JSON对象。 - 转义字符错误:代码中的
"是HTML转义的双引号,在PHP字符串中应直接使用"或转义的\",否则会导致GraphQL查询语句格式失效。
修正后的PHP代码
// 构造正确的GraphQL查询语句,使用原生双引号 $query = 'query {adSet(id: "' . $MY_ADSET_ID . '") {insights(timeRange: {from: "2023-08-01T00:00:00Z", until: "2023-08-10T23:59:59Z"} timeIncrement: DAILY) {timestamps reports {impressions conversions offerwallImpressions offerwallAverageRank spend}}}}'; // 按照JavaScript的逻辑,将包含query键的数组转为JSON $postdata = json_encode(['query' => $query]); $endpoint = $MY_API_ENDPOINT; // 请求头仅保留Content-Type和Authorization $headers = array( "Content-Type: application/json", "Authorization: Bearer " . $MY_ACCESS_TOKEN ); // 传递postdata参数给curl函数 $data = my_curl($endpoint, $headers, $postdata); var_dump($data); function my_curl($endpoint, $headers, $postdata) { $ch = curl_init(); curl_setopt($ch, CURLOPT_URL, $endpoint); curl_setopt($ch, CURLOPT_POST, 1); curl_setopt($ch, CURLOPT_HTTPHEADER, $headers); // 设置POST请求体 curl_setopt($ch, CURLOPT_POSTFIELDS, $postdata); curl_setopt($ch, CURLOPT_HEADER, false); curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); // 可选:开启调试模式,查看curl请求详情 curl_setopt($ch, CURLOPT_VERBOSE, true); $verboseLog = fopen('php://temp', 'w+'); curl_setopt($ch, CURLOPT_STDERR, $verboseLog); $server_output = curl_exec($ch); // 调试时可打印日志排查问题 rewind($verboseLog); $logContent = stream_get_contents($verboseLog); // echo "Curl日志:\n" . $logContent . "\n"; // 检查curl是否执行出错 if(curl_errno($ch)){ echo 'Curl错误: ' . curl_error($ch); } curl_close($ch); fclose($verboseLog); $json = json_decode($server_output, true); return $json; }
额外调试建议
- 开启
CURLOPT_VERBOSE可以查看完整的curl请求日志,帮助定位API返回空响应的具体原因(如权限验证失败、查询语法错误等)。 - 确认
$MY_ADSET_ID和$MY_API_ENDPOINT变量的取值与JavaScript代码完全一致。
内容的提问来源于stack exchange,提问作者Adrien Hingert
相关产品推荐
相关产品推荐

