PHP向API传输数组时触发400错误,请求排查问题根源
问题:Gravity Form数据同步CRM时API返回400错误
错误信息
{"error":{"httpStatusCode":400,"message":"Expected end of string, but instead reached end of data. Path: $.name | LineNumber: 2 | BytePositionInLine: 7.","messageType":"Error"},"response":null}
相关代码
add_filter( 'gform_after_submission', 'registrazone', 10, 2 ); function registrazone ( $entry, $form) { #FIXME: Hardcoded url $url2 = 'https://gogogogo.com/api/load'; #Assumption: The params below have already been verified. $topup_data2 = array("accept" => "text/plain", "token" => $token); #JSON encode the params $topup_str2 = json_encode($topup_data2); #Curl init $ch2 = curl_init(); curl_setopt($ch2, CURLOPT_URL, $url2); curl_setopt($ch2, CURLOPT_HTTPHEADER, array( 'Content-Type: application/json', 'Content-Length: '.strlen($topup_str2) ) ); $actual_link = "http://$_SERVER[HTTP_HOST]$_SERVER[REQUEST_URI]"; $note = "Contatto da pagina " . $actual_link; $valid_cellulare_b = rgar( $entry, '7' ); #I use JSON_NUMERIC_CHECK but thinks that error is for not "" so use strval $valid_cellulare_a = strval( $valid_cellulare_b ); $payload = json_encode( array( 'nome' => rgar( $entry, '3.3' ), 'cellulare'=>$valid_cellulare_a, 'email' => rgar( $entry, '5' ), 'nota' => $note, 'cognome' => rgar( $entry, '3.6' ), 'provinciaDomicilio' => rgar( $entry, '9' ), ), JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES ); echo "<pre>$payload</pre>"; curl_setopt($ch2, CURLOPT_POSTFIELDS, $payload); # Return response instead of printing. curl_setopt($ch2, CURLOPT_RETURNTRANSFER, 1); # Send request. $result2 = curl_exec($ch2); curl_close($ch2); # Print response. echo "<pre>$result2</pre>"; }
生成的Payload
{ "nome": "Joan", "cellulare": "349XXXXXXX", "email": "info@XXXXXX.com", "nota": "Contact from page https://gogogogogogo.com", "cognome": "Trello", "provinciaDomicilio": "GG" }
问题排查与修复方案
核心错误原因
- 字段名不匹配:API明确提示期望
$.name字段,但你发送的是nome(意大利语"名字"),字段名不匹配导致API无法正确解析数据。 - Content-Length设置错误:你手动设置的
Content-Length是$topup_str2的长度,但实际POST的是$payload,两者长度不一致,服务器读取数据时提前结束,触发JSON解析错误。 - Token传递方式错误:你将授权Token放在了未使用的
$topup_data2数组中,未正确传递到API请求里,可能导致授权验证问题(虽然当前错误未直接体现,但属于潜在问题)。
修复后的代码示例
add_filter( 'gform_after_submission', 'registrazone', 10, 2 ); function registrazone ( $entry, $form) { // FIXME: Hardcoded url $url2 = 'https://gogogogo.com/api/load'; // 假设$token已通过授权接口正确获取 $token = 'your_valid_token_here'; // Curl初始化 $ch2 = curl_init(); curl_setopt($ch2, CURLOPT_URL, $url2); // 设置正确的请求头:包含授权Token,Content-Type为JSON curl_setopt($ch2, CURLOPT_HTTPHEADER, array( 'Content-Type: application/json', "Authorization: Bearer $token" // 标准Bearer Token授权方式 )); $actual_link = "http://$_SERVER[HTTP_HOST]$_SERVER[REQUEST_URI]"; $note = "Contatto da pagina " . $actual_link; $valid_cellulare_b = rgar( $entry, '7' ); $valid_cellulare_a = strval( $valid_cellulare_b ); // 修正字段名:将nome改为API期望的name,其他字段需对照API文档确认 $payload = json_encode( array( 'name' => rgar( $entry, '3.3' ), 'cellulare' => $valid_cellulare_a, 'email' => rgar( $entry, '5' ), 'nota' => $note, 'lastName' => rgar( $entry, '3.6' ), // 假设cognome对应API的lastName,需确认文档 'provinciaDomicilio' => rgar( $entry, '9' ), ), JSON_UNESCAPED_SLASHES ); // 生产环境可去掉JSON_PRETTY_PRINT减少数据体积 // 调试用,生产环境建议注释 echo "<pre>$payload</pre>"; curl_setopt($ch2, CURLOPT_POSTFIELDS, $payload); curl_setopt($ch2, CURLOPT_RETURNTRANSFER, 1); curl_setopt($ch2, CURLOPT_POST, 1); // 显式设置POST请求 // 执行请求并捕获curl错误 $result2 = curl_exec($ch2); if(curl_errno($ch2)){ echo 'Curl错误: ' . curl_error($ch2); } curl_close($ch2); echo "<pre>$result2</pre>"; }
关键修复点
- 字段名对齐:严格按照CRM API文档的字段名传递数据,比如将
nome改为name,cognome需确认对应API的字段名(如lastName)。 - 移除手动Content-Length:让cURL自动计算并设置正确的Content-Length,避免长度不匹配问题。
- 规范Token传递:将Token放在HTTP请求头的
Authorization字段中,使用标准的Bearer {token}格式(除非API明确要求放在POST数据中)。 - 优化JSON编码:生产环境去掉
JSON_PRETTY_PRINT,减少请求数据体积,提升传输效率。
内容的提问来源于stack exchange,提问作者Giandomenico Viglione
相关产品推荐
相关产品推荐

