在PHP中使用ChannelAdvisor REST API-请求在CURL中不起作用

在PHP中使用ChannelAdvisor REST API-请求在CURL中不起作用,php,rest,curl,channeladvisor,Php,Rest,Curl,Channeladvisor,我想集成使用SOAP凭据流 根据他们的文档,我在PostMan(Chrome浏览器中的rest客户端)中设置了如下内容: private function curlPOST($endpoint, $fields = array()) { // Open connection $ch = curl_init(); // Set the url, number of POST vars, POST data curl_setopt($ch, CURLOPT_USER

我想集成使用SOAP凭据流

根据他们的文档,我在
PostMan
(Chrome浏览器中的rest客户端)中设置了如下内容:

private function curlPOST($endpoint, $fields = array())
{
    // Open connection
    $ch = curl_init();

    // Set the url, number of POST vars, POST data
    curl_setopt($ch, CURLOPT_USERPWD, $this->config['api_app_id'] .':'. $this->config['api_shared_secret']);
    curl_setopt($ch, CURLOPT_URL, self::BASE_URL . $endpoint);
    curl_setopt($ch, CURLOPT_POST, count($fields));
    curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query($fields, '', '&'));
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
    curl_setopt($ch, CURLOPT_HTTPHEADER, array(
        'Content-Type: application/x-www-form-urlencoded'
    ));
    curl_setopt($ch, CURLOPT_VERBOSE, true);
    $verbose = fopen('php://temp', 'w+');
    curl_setopt($ch, CURLOPT_STDERR, $verbose);

    // Execute post request
    $result = curl_exec($ch);

    // Debug error
    if ($result === FALSE) {
        printf("cUrl error (#%d): %s<br>\n", curl_errno($ch), htmlspecialchars(curl_error($ch)));
        rewind($verbose);
        $verboseLog = stream_get_contents($verbose);
        echo "Verbose information:\n<pre>", htmlspecialchars($verboseLog), "</pre>\n";
    }
    @fclose($verbose);

    // Close connection
    curl_close($ch);

    // Finished
    return $result;
}

当我做剩下的;rest api服务器返回预期的响应:

因此,我尝试使用以下类在PHP中复制此内容:

<?php

class ChannelAdvisorREST {

    /**
     * ChannelAdvisor constants & properties
     */
    const BASE_URL = 'https://api.channeladvisor.com/v1';
    private $config;

    /**
     * Class constructor
     */
    public function __construct()
    {
        $this->config = \Config::get('channeladvisor');
    }

    // TEST
    public function test($accountId)
    {
        // var_dump($this->config);

        var_dump(self::getAccessToken($accountId));
    }
    // TEST

    /**
     * Method to get access token from rest server.
     *
     * @param $accountId
     * @return string
     */
    private function getAccessToken($accountId)
    {
        return self::curlPOST('/oauth2/token', [
            'client_id' => $this->config['api_app_id'],
            'grant_type' => 'soap',
            'scope' => 'inventory',
            'developer_key' => $this->config['api_developer_key'],
            'password' => $this->config['api_password'],
            'account_id' => $accountId
        ]);
    }

    /**
     * Method to generate a HTTP POST request
     *
     * @param $endpoint
     * @param $fields
     * @return string
     */
    private function curlPOST($endpoint, $fields = array())
    {
        // Open connection
        $ch = curl_init();

        // Set the url, number of POST vars, POST data
        curl_setopt($ch, CURLOPT_USERPWD, $this->config['api_app_id'] .':'. $this->config['api_shared_secret']);
        curl_setopt($ch, CURLOPT_URL, self::BASE_URL . $endpoint);
        curl_setopt($ch, CURLOPT_POST, count($fields));
        curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query($fields, '', '&'));
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
        curl_setopt($ch, CURLOPT_HTTPHEADER, array(
            'Content-Type: application/x-www-form-urlencoded'
        ));

        // Execute post request
        $result = curl_exec($ch);

        // Close connection
        curl_close($ch);

        // Finished
        return $result;
    }
}
两件事:

  • 确保发送的标题与浏览器发送的标题相同。例如,我在您的代码中看不到授权头,而该头对于在服务器端授权请求可能非常关键。此外,对于范围,您使用“库存”而不是“订单库存”。在这个练习中要非常严格

  • 不在数组中测试post数据,而是根据您自己的情况记录查询字符串,这样您就知道CURL尝试将数组转换为查询字符串不会有任何问题(注意,CURL、array和query string都可以)

  • 因此,最容易测试的方法是:

    client_id=1234&grant_type=soap&scope=order%20inventory...etc add other variables...
    
    两件事:

  • 确保发送的标题与浏览器发送的标题相同。例如,我在您的代码中看不到授权头,而该头对于在服务器端授权请求可能非常关键。此外,对于范围,您使用“库存”而不是“订单库存”。在这个练习中要非常严格

  • 不在数组中测试post数据,而是根据您自己的情况记录查询字符串,这样您就知道CURL尝试将数组转换为查询字符串不会有任何问题(注意,CURL、array和query string都可以)

  • 因此,最容易测试的方法是:

    client_id=1234&grant_type=soap&scope=order%20inventory...etc add other variables...
    

    我发现了问题所在。问题是由于我的php没有配置
    curl.cainfo

    我通过将以下调试代码添加到我的
    curlPOST
    方法中发现了这一点,如下所示:

    private function curlPOST($endpoint, $fields = array())
    {
        // Open connection
        $ch = curl_init();
    
        // Set the url, number of POST vars, POST data
        curl_setopt($ch, CURLOPT_USERPWD, $this->config['api_app_id'] .':'. $this->config['api_shared_secret']);
        curl_setopt($ch, CURLOPT_URL, self::BASE_URL . $endpoint);
        curl_setopt($ch, CURLOPT_POST, count($fields));
        curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query($fields, '', '&'));
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
        curl_setopt($ch, CURLOPT_HTTPHEADER, array(
            'Content-Type: application/x-www-form-urlencoded'
        ));
        curl_setopt($ch, CURLOPT_VERBOSE, true);
        $verbose = fopen('php://temp', 'w+');
        curl_setopt($ch, CURLOPT_STDERR, $verbose);
    
        // Execute post request
        $result = curl_exec($ch);
    
        // Debug error
        if ($result === FALSE) {
            printf("cUrl error (#%d): %s<br>\n", curl_errno($ch), htmlspecialchars(curl_error($ch)));
            rewind($verbose);
            $verboseLog = stream_get_contents($verbose);
            echo "Verbose information:\n<pre>", htmlspecialchars($verboseLog), "</pre>\n";
        }
        @fclose($verbose);
    
        // Close connection
        curl_close($ch);
    
        // Finished
        return $result;
    }
    

    这帮助我用我的php找到了问题所在。

    我发现了问题所在。问题是由于我的php没有配置
    curl.cainfo

    我通过将以下调试代码添加到我的
    curlPOST
    方法中发现了这一点,如下所示:

    private function curlPOST($endpoint, $fields = array())
    {
        // Open connection
        $ch = curl_init();
    
        // Set the url, number of POST vars, POST data
        curl_setopt($ch, CURLOPT_USERPWD, $this->config['api_app_id'] .':'. $this->config['api_shared_secret']);
        curl_setopt($ch, CURLOPT_URL, self::BASE_URL . $endpoint);
        curl_setopt($ch, CURLOPT_POST, count($fields));
        curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query($fields, '', '&'));
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
        curl_setopt($ch, CURLOPT_HTTPHEADER, array(
            'Content-Type: application/x-www-form-urlencoded'
        ));
        curl_setopt($ch, CURLOPT_VERBOSE, true);
        $verbose = fopen('php://temp', 'w+');
        curl_setopt($ch, CURLOPT_STDERR, $verbose);
    
        // Execute post request
        $result = curl_exec($ch);
    
        // Debug error
        if ($result === FALSE) {
            printf("cUrl error (#%d): %s<br>\n", curl_errno($ch), htmlspecialchars(curl_error($ch)));
            rewind($verbose);
            $verboseLog = stream_get_contents($verbose);
            echo "Verbose information:\n<pre>", htmlspecialchars($verboseLog), "</pre>\n";
        }
        @fclose($verbose);
    
        // Close connection
        curl_close($ch);
    
        // Finished
        return $result;
    }
    

    这有助于我追踪我的php问题。

    我的post man测试中的
    授权
    标题用于基本身份验证凭证,这些凭证在php中使用
    CURLOPT_USERPWD设置
    -这不一样吗?
    scope
    字段接受
    orders inventory
    以及
    inventory
    (我认为问题不在这里)。我已经测试了我的帖子数据,它是一个字符串。忽略了CURLOPT_USERPWD,看起来不错。如果您也测试了post数据的字符串,那么我看不出它会往哪里去。然后,我建议通过firebug或http头跟踪http流,并检查是否存在一个或多个重定向,以及在这些重定向过程中是否使用特定值设置了cookie。这也是相当普遍的做法。如果在浏览器中是这样,那么在php代码中也实现这个功能。我已经找到了答案。查看我的答案。我的post-man测试中的
    授权
    标题用于基本身份验证凭据,这些凭据是在php中使用
    CURLOPT_USERPWD
    设置的-这不一样吗?
    scope
    字段接受
    orders inventory
    以及
    inventory
    (我认为问题不在这里)。我已经测试了我的帖子数据,它是一个字符串。忽略了CURLOPT_USERPWD,看起来不错。如果您也测试了post数据的字符串,那么我看不出它会往哪里去。然后,我建议通过firebug或http头跟踪http流,并检查是否存在一个或多个重定向,以及在这些重定向过程中是否使用特定值设置了cookie。这也是相当普遍的做法。如果在浏览器中是这样,那么在php代码中也实现这个功能。我已经找到了答案。看看我的答案。