在PHP页面上将OAUTH API与CURL一起使用

时间:2018-10-11 11:57:56

标签: php curl oauth php-curl

我正在与一个PHP网站合作,希望将其集成到某些第三方API。

尤其是我正在考虑使用CURL与他们的服务器进行交互,但这与专家相比还很遥远,因此希望社区可以帮助我更好地了解自己的工作。

我不清楚-X和-d之类的选项,也不清楚如何在PHP页面上编写此命令的脚本? (不幸的是,在Google上搜索“ -d”非常棘手,因为这不属于搜索字符串的一部分)

我遇到的特定示例是请求访问令牌,提供给我的API文档是;

curl -X POST \
-d \ "grant_type=client_credentials&client_id=YOUR_CLIENT_ID&client_secret=YOUR_CLIENT_SECRET&scope=REQUESTED_SCOPES" \
'https://api.example.com/token'
  

grant_type- client_credentials

     

client_id-在安装过程中生成

     

client_secret-仅在安装过程中生成的Web应用程序

     

scope可选-逗号分隔值的列表,请参阅受支持的作用域

     

如果请求成功,访问令牌将返回到   回应:

 {
"access_token":"ACCESS_TOKEN",
"token_type":"Bearer",
"expires_in":3600
"scope":"REQUEST_SCOPES"
}

以上是指导,我已经完成了先决条件,因此可以确认客户端ID,机密和所需范围正确。

我在自己的PHP脚本中尝试了以下两种方法

$tk = curl_init();

curl_setopt($tk, CURLOPT_URL, "https://api.example.com/token");
curl_setopt($tk, CURLOPT_POST, 1);
curl_setopt($tk, CURL_HTTPHEADER, array('Content-Type: application/json'));
curl_setopt($tk, CURLOPT_POSTFIELDS, array( 'grant_type=client_credentials&client_id=myownid&client_secret=xyz123&scope=instrument'));

// grab URL and pass it to the browser
$result=curl_exec($tk);

// close cURL resource, and free up system resources
curl_close($tk);

$tk = curl_init();

curl_setopt($tk, CURLOPT_URL, "https://api.example.com/token?grant_type=client_credentials&client_id=myownid&client_secret=xyz123&scope=instrument");
curl_setopt($tk, CURLOPT_POST, 1);
curl_setopt($tk, CURL_HTTPHEADER, array('Content-Type: application/json'));

// grab URL and pass it to the browser
$result=curl_exec($tk);

// close cURL resource, and free up system resources
curl_close($tk);

这两个示例均产生以下错误;

  

{“ error_description”:“ grant_type参数为   缺少”,“错误”:“ invalid_request”}

在这个特定问题上的任何帮助,甚至只是了解我怎么了,给我一些正确语法的想法,将不胜感激!

谢谢大家的宝贵时间。

  • (请注意,为了安全起见,我已更改为“ example.com” 派对)

2 个答案:

答案 0 :(得分:0)

在php中查看以下cURL调用的示例代码。您需要更改域名而不是example.com,还需要为POSTFIELDS输入值。

$curl = curl_init();

curl_setopt_array($curl, array(
  CURLOPT_URL => "https://api.example.com/oauth/token",
  CURLOPT_RETURNTRANSFER => true,
  CURLOPT_ENCODING => "",
  CURLOPT_MAXREDIRS => 10,
  CURLOPT_TIMEOUT => 30,
  CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
  CURLOPT_CUSTOMREQUEST => "POST",
  CURLOPT_POSTFIELDS => "{\"grant_type\":\"client_credentials\",\"client_id\": \"YOUR_CLIENT_ID\",\"client_secret\": \"YOUR_CLIENT_SECRET\",\"scope\": \"instrument\"}",
  CURLOPT_HTTPHEADER => array(
    "content-type: application/json"
  ),
));

$response = curl_exec($curl);
$err = curl_error($curl);

curl_close($curl);

if ($err) {
  echo "cURL Error #:" . $err;
} else {
  echo $response;
}

答案 1 :(得分:0)

如果您想OO而不是使用cURL,则可能会更好。在Guzzle中首先需要:

composer require guzzlehttp/guzzle

创建一个ApiCredentials对象:

<?php

namespace Some\Company;

class ApiCredentials
{
    private $clientKey;

    private $clientSecret;

    private $proxy;

    private $baseUrl;

    public function __construct(string $clientKey, string $clientSecret, string $proxy = '', string $baseUrl = 'https://api.somewhere.com')
    {
        $this->clientKey = $clientKey;
        $this->clientSecret = $clientSecret;
        $this->proxy = $proxy;
        $this->baseUrl = $baseUrl;
    }

    public function getClientKey(): string
    {
        return $this->clientKey;
    }

    public function getClientSecret(): string
    {
        return $this->clientSecret;
    }

    public function getProxy(): string
    {
        return $this->proxy;
    }

    public function getBaseUrl(): string
    {
        return $this->baseUrl;
    }
}

现在创建一个ApiService类:

<?php

namespace Some\Company;

use DateTime;
use GuzzleHttp\Client;

class ApiService
{
    const API_TOKEN_ENDPOINT = '/token';

    private $baseUrl;

    private $client;

    private $accessToken;

    private $credentials;

    public function __construct(ApiCredentials $credentials)
    {
        $this->baseUrl = $credentials->getBaseUrl();
        $options = $this->initOptions($credentials);
        $this->client = new Client($options);
        $this->credentials = $credentials;
    }

    private function initOptions(ApiCredentials $credentials) : array
    {
        $options = [
            'base_uri' => $this->baseUrl,
            'verify'  => false,
        ];
        if ($credentials->getProxy() !== '') {
            $options = \array_merge($options, ['proxy' => [
                'https' => $credentials->getProxy(),
            ]]);
        }

        return $options;
    }

    private function hasAccessToken() : bool
    {
        return $this->accessToken instanceof AccessToken && $this->accessToken->getExpires() > new DateTime();
    }

    private function getAccessToken() : AccessToken
    {
        return $this->accessToken;
    }

    private function getCredentials(): ApiCredentials
    {
        return $this->credentials;
    }

    private function refreshAccessToken()
    {
        $client = $this->getClient();
        $response = $client->post(
            $this->baseUrl . self::API_TOKEN_ENDPOINT, [
            'headers' => [
                'Content-Type' => 'application/x-www-form-urlencoded',
            ],
            'form_params' => [
                'grant_type' => 'client_credentials',
                'client_id' => $this->getCredentials()->getClientKey(),
                'client_secret' => $this->getCredentials()->getClientSecret(),
                'scope' => 'put your scopes in here',
            ],
        ]);
        $json = $response->getBody()->getContents();
        $this->accessToken = new AccessToken($json);
    }

    private function getClient() : Client
    {
        return $this->client;
    }

    private function validateToken()
    {
        if (!$this->hasAccessToken()) {
            $this->refreshAccessToken();
        }
    }

    public function getSomeEndpointData(string $someParam = 'whatever') : string
    {
        $this->validateToken();

        $response = $this->getClient()->get(
            $this->baseUrl . '/get/some/data/' . $someParam, [
            'headers' => [
                'Authorization' => 'Bearer ' . $this->getAccessToken()->getToken(),
            ],
            'query' => [
                'additional' => 'this creates stuff like ?additional=whatever',
            ],
        ]);
        $json = $response->getBody()->getContents();

        return $json;
    }

}

还有一个访问令牌类:

<?php

namespace Some\Company;

use DateTime;

class AccessToken
{
    private $token;

    private $scope;

    private $type;

    private $expires;

    public function __construct(string $tokenJson)
    {
        $token = \json_decode($tokenJson, true);
        $keys = [
            'access_token', 'scope', 'token_type', 'expires_in',
        ];

        $this->token = $token['access_token'];
        $this->scope = $token['scope'];
        $this->type = $token['token_type'];
        $date = new DateTime('+' .$token['expires_in'] . ' seconds');
        $this->expires = $date;
    }

    public function getToken(): string
    {
        return $this->token;
    }

    public function getScope(): string
    {
        return $this->scope;
    }

    public function getType(): string
    {
        return $this->type;
    }

    public function getExpires(): DateTime
    {
        return $this->expires;
    }
}

现在,要使用这些东西:

<?php

use Some\Company\ApiCredentials;
use Some\Company\ApiService;

$clientKey = 'client key key here';
$clientSecret = 'client secret here';
$proxy = 'tcp://199.199.132.132:80'; // optional

$creds = new ApiCredentials($clientKey, $clientSecret, $proxy);
$apiService = new ApiService($creds);

$results = $apiService->getSomeEndpointData('whatever'); // returns json

它还将处理刷新的访问令牌等。