使用 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'"

我做的唯一改变是双引号现在在外面,这对我有用,但我显然是发布到不同的服务器

我能提供的唯一其他帮助是下载网络调试工具,例如 FiddlerCharles 代理并监控发送/接收的请求,这可能是您的代码中存在其他问题的情况。

希望我有所帮助:)

【讨论】:

"我所做的唯一改变是双引号现在在外面" — 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 是不是成功?

通过 cURL POST PHP 传递 JSON

php:使用 cURL 获取 url 内容(json)

使用 PHP、curl 解码从 Flickr API 返回的 json 字符串

PHP Curl json POST 不适合我

如何通过 cURL/PHP 使用 PUT 方法将 JSON 数据发送到 API