使用 PHP cURL 发布 JSON
Posted
技术标签:
【中文标题】使用 PHP cURL 发布 JSON【英文标题】:POST JSON with PHP cURL 【发布时间】:2011-12-19 03:56:17 【问题描述】:我有以下php代码
curl_setopt($ch, CURLOPT_URL, $URL); curl_setopt($ch, CURLOPT_USERAGENT, $this->_agent); curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); curl_setopt($ch, CURLOPT_AUTOREFERER, true); curl_setopt($ch, CURLOPT_HEADER, 1); curl_setopt($ch, CURLOPT_HTTPHEADER, $this->_headers); curl_setopt($ch, CURLOPT_ENCODING , "gzip"); curl_setopt($ch, CURLOPT_VERBOSE, false); curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 1); curl_setopt($ch, CURLOPT_TIMEOUT, 120); curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false); curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 0); curl_setopt($ch, CURLOPT_COOKIEFILE, $this->_cookie_file_path); curl_setopt($ch, CURLOPT_COOKIEJAR, $this->_cookie_file_path); curl_setopt($ch, CURLOPT_POSTFIELDS, '"folderId":"1","parameters":"amount":3,"ascending":false,"offset":0,"sort":"date"' ); curl_setopt($ch, CURLOPT_POST, 1);但我不明白为什么不工作。我发布 JSON 的 API 表示未收到参数。我的代码有什么问题吗?我认为整个技巧在于 JSON 参数......我不确定如何发送它们,因为我看不到任何带有 http 分析器的“nave->value”对,因为它通常以简单的形式出现......只是没有任何“名称”的 JSON 代码。
【问题讨论】:
发送的 Content-Type 是什么?为什么不使用json_encode
?
@mario 我试过 curl_setopt($ch, CURLOPT_HTTPHEADER, array('Content-type: application/json'));并且也不工作。默认情况下,我将标题设置为 $headers = array("Expect:", );我看不出它如何与 json_encode 一起工作
您必须咨询 API 维护人员。我们只能猜测。
@mario 我在此链接上添加了调试信息(萤火虫),因为我无法在 SO 上发布它。它说它的格式不正确(虽然我尝试了几次“格式化它)pastebin.com/Ujdim8t8
如果你有使用这个接口并且实际工作的东西,然后使用代理并记录它:p 然后找出你的脚本有什么不同,并消除所有差异(提琴手代理非常适合它甚至支持伪造证书/MITM 攻击,用于监视 HTTPS 加密连接、解码 gzip/deflate 等)
【参考方案1】:
您尚未设置内容类型,因此帖子数据将作为表单数据发送。尝试将内容类型设置为 application/json。
如果这不起作用,请尝试用数组包装 json 字符串。
【讨论】:
我添加了 curl_setopt($ch, CURLOPT_HTTPHEADER, array('Content-type: application/json'));并且仍然无法正常工作 尝试使用 array('jsoncode') 作为 post 字段。如果这不起作用,您将需要提供请求标头或进行盲目猜测。 请提供调试信息(firebug)pastebin.com/Ujdim8t8 我在此链接上添加了调试信息(firebug),因为我无法在 SO 上发布它。它说它的格式不正确(尽管我尝试了几次“格式化它) 如果您从 PHP 提交,您应该看不到来自 Firebug 的 HTTP 请求/响应。尝试以下操作:1)将其添加到您的 curlopt -curl_setopt($ch, CURLINFO_HEADER_OUT, true);
2)在 curl_exec 之后,输出您发送的请求标头:var_dump(curl_getinfo($ch,CURLINFO_HEADER_OUT));
一旦我们可以看到您实际请求的内容,应该更容易说出原因你得到了错误。
我添加了来自 firebug 的 http 请求/响应,看看它应该如何工作。我的意思是我需要在 PHP 中模拟它。【参考方案2】:
如果:你使用 post 方法,你应该知道:
CURLOPT_POST TRUE 以执行常规 HTTP POST。这个 POST 是普通的 application/x-www-form-urlencoded 类型,最常用于 html 表单。
@见http://php.net/manual/en/function.curl-setopt.php
所以:你可以这样做:
$ar_form = array('name'=>'PHPJungle','age'=>66,'gender'=>'male');
$poststr = http_build_query($ar_form ); # important
$options[CURLOPT_HTTPGET] = false;
$options[CURLOPT_POST] = true;
$options[CURLOPT_POSTFIELDS] = $poststr ; //default type:application/x-www-from-urlencoded
curl_setopt_array ( $ch, $options );
# @todo your other codes
这是我用了很久的类。该类基于PHP cURL。 支持GET/POST,HTTP/HTTPS。
@见https://github.com/phpjungle/iHttp/
【讨论】:
我一般使用Fiddler来抓取http请求。Download-url:telerik.com/fiddler 很好的工具,支持代理等。【参考方案3】:$link = "http://test.domain/myquery";
$json = '"folderId":"1","parameters":"amount":3,"ascending":false,"offset":0,"sort":"date"';
$postdata = json_decode($json);
echo openurl($link, $postdata);
这作为 json decode 将 json 字符串转换为数组。
function openurl($url, $postvars = "")
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_POSTFIELDS, $postvars);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_TIMEOUT, '3');
$content = trim(curl_exec($ch));
curl_close($ch);
return $content;
【讨论】:
【参考方案4】:我不确定,这是否是解决方案,但在发布 json 时这对我有用,将 json 从
'"folderId":"1","parameters":"amount":3,"ascending":false,"offset":0,"sort":"date"'
到
"'folderId':'1','parameters':'amount':3,'ascending':false,'offset':0,'sort':'date'"
我做的唯一改变是双引号现在在外面,这对我有用,但我显然是发布到不同的服务器
我能提供的唯一其他帮助是下载网络调试工具,例如 Fiddler
或 Charles
代理并监控发送/接收的请求,这可能是您的代码中存在其他问题的情况。
希望我有所帮助:)
【讨论】:
"我所做的唯一改变是双引号现在在外面" — JSON 现在无效了。【参考方案5】:您可以使用它并替换为
curl_setopt($ch, CURLOPT_POSTFIELDS, '"folderId":"1","parameters":"amount":3,"ascending":false,"offset":0,"sort":"date"');
使用这个
$Parameters = array(
'MerchantCode' => $MerchantCode,
'PriceValue' => $amount,
'ReturnUrl' => $callback,
'InvoiceNumber' => $resnum,
);
curl_setopt($curl, CURLOPT_POSTFIELDS, json_encode($Parameters));
【讨论】:
【参考方案6】:如果您的 API 端点使用正文发送使用 json 数据的请求,您可以使用Guzzle,文档在此处doc。
use GuzzleHttp\Client;
$client = new Client();
$request = $this->client->post($url,array(
'content-type' => 'application/json'
),array());
$request->setBody($json_data);
$response = $request->send();
return $response;
希望这项工作。
【讨论】:
【参考方案7】:您可以按步骤制作:
$data = array(
'folderId'=>"1","parameters"=>array(
"amount"=>"3","ascending"=>false,"offset"=>0,"sort"=>"date"
)
);
$data_string = http_build_query($data);
$ch = curl_init();
curl_setopt($ch,CURLOPT_URL, $url);
curl_setopt($ch,CURLOPT_POST, count($data));
curl_setopt($ch,CURLOPT_POSTFIELDS, $data_string);
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 1);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, 0);
curl_setopt($ch, CURLOPT_HEADER, 0);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
$result = curl_exec($ch);
curl_close($ch);
$result = json_decode($result,true);
我不知道你是否需要标题。我认为默认情况下它已经是application/x-www-form-urlencode
如果不起作用,请尝试更改数组中的 $data
值。认为它有帮助。 :)
【讨论】:
【参考方案8】:您可以尝试如下。
基本上,如果我们有一个数据数组,那么它应该是 json encoded
使用 php json_encode
。您还应该在header
中添加content-type
,这可以在curl 中定义为curl_setopt($ch, CURLOPT_HTTPHEADER, array('Content-Type: application/json'));
$data = array("country"=>"US","states"=>array("MHASASAS"=>"MH","XYZABABA"=>"XYZ"));
$postdata = json_encode($data);
$ch = curl_init($URL);
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 0);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, 0);
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_POSTFIELDS, $postdata);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 1);
curl_setopt($ch, CURLOPT_HTTPHEADER, array('Content-Type: application/json'));
$result = curl_exec($ch);
curl_close($ch);
【讨论】:
如果您在代码块中添加一些 cmets 将不胜感激。 “基本上,如果我们有一个数据数组,那么它应该使用 php json_encode 进行 json 编码”——他们没有。它们有一个包含有效 JSON 的字符串文字。 “你还应该添加内容类型”——在对 2011 年问题的评论中:他们说他们这样做了。【参考方案9】:首先 请检查 curl http 状态码
$http_code= curl_get_info($exec_res,CURL_HTTP_CODE);
然后使用 post header API 服务器修改此请求标头集,添加记录器以记录这些请求信息。
【讨论】:
【参考方案10】:您可以像这样使用 curl 发布 json 数据:
使用命令提示符:
curl -X POST -H "Content-Type: application/json" -d '"folderId":"1","parameters":"amount":3,"ascending":false,"offset":0,"sort":"date"' $url
使用 PHP:
$data = array("folderId"=>"1","parameters"=>array("amount"=>3,"ascending"=>false,"offset"=>0,"sort"=>"date"));
$postdata = json_encode($data);
OR
$postdata = '"folderId":"1","parameters":"amount":3,"ascending":false,"offset":0,"sort":"date"';
$ch = curl_init($url);
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_POSTFIELDS, $postdata);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_HTTPHEADER, array('Content-Type: application/json'));
$result = curl_exec($ch);
curl_close($ch);
print_r($result);
【讨论】:
以上是关于使用 PHP cURL 发布 JSON的主要内容,如果未能解决你的问题,请参考以下文章
如何确定使用 PHP cURL 发布 JSON 是不是成功?