在 PHP 页面上使用 OAUTH API 和 CURL
Using OAUTH API with CURL on a PHP page
我正在使用一个 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- Generated during setup
client_secret - Web apps only, generated during setup
scope Optional - List of comma separated values, see supported scopes
If the request is successful, an access token will be returned in the
response:
{
"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 parameter is
missing","error":"invalid_request"}
任何关于这个特定问题的帮助,甚至只是理解我怎么会出错,给我一些正确语法的想法,都将不胜感激!
提前感谢大家的宝贵时间。
- (请注意,为了 3 号的安全,我已更改为 "example.com"
党)
查看下面 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;
}
如果您想使用 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 class:
<?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;
}
}
还有一个访问令牌class:
<?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
它也会处理刷新访问令牌等。
我正在使用一个 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- Generated during setup
client_secret - Web apps only, generated during setup
scope Optional - List of comma separated values, see supported scopes
If the request is successful, an access token will be returned in the response:
{
"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 parameter is missing","error":"invalid_request"}
任何关于这个特定问题的帮助,甚至只是理解我怎么会出错,给我一些正确语法的想法,都将不胜感激!
提前感谢大家的宝贵时间。
- (请注意,为了 3 号的安全,我已更改为 "example.com" 党)
查看下面 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;
}
如果您想使用 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 class:
<?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;
}
}
还有一个访问令牌class:
<?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
它也会处理刷新访问令牌等。