【问题标题】:POST JSON with PHP cURL使用 PHP cURL 发布 JSON
【发布时间】: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 等)

标签: php curl


【解决方案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);
            

            【讨论】:

              猜你喜欢
              • 2020-12-09
              • 1970-01-01
              • 1970-01-01
              • 2016-08-10
              • 1970-01-01
              • 2011-03-31
              • 2010-10-23
              • 2012-06-20
              相关资源
              最近更新 更多