So after reading the documentation of youtube api I have successfully make an oauth connection for youtube account on my server side app but I failed to find a solution on how to get channel views by using this data I obtained.
So my code looks like this (the PHP part):
class YouTube {
protected $token;
protected $params = [];
/**
* YouTube constructor.
*
* #param null $id
*/
public function __construct($id = null)
{
if ($id) {
$this->token = $this->getToken($id);
}
}
/**
* Get api authorization
*
* #return string
*/
public function getAuthorizationUrl()
{
// Make redirect
$this->params = [
'client_id' => '########',
'redirect_uri' => '######',
'scope' => 'https://gdata.youtube.com&',
'response_type'=> 'code&',
'access_type' => 'offline'
];
$redirect_url = 'https://accounts.google.com/o/oauth2/auth?' . http_build_query($this->params);
return $redirect_url;
}
/**
* Get API token and save account list to db
*
* #param $code
*
* #return \App\Models\DynamicDashboard\ThirdPartyAccounts
*/
public function getCallbackUrl($code)
{
// Grab the returned code and extract the access token.
$this->params = [
'code' => $code,
'client_id' => '####',
'client_secret' => '#####',
'redirect_uri' => '#######',
'grant_type' => 'authorization_code'
];
// Get access token
$command = 'curl --data "' . http_build_query($this->params) . '" https://accounts.google.com/o/oauth2/token';
exec($command, $resultToken);
$resultToken = json_decode($resultToken[0]);
// Do a request using the access token to get the list of accounts.
$command = 'curl -H "Authorization: Bearer ' . $resultToken->access_token . '" https://accounts.google.com/o/oauth2.json';
exec($command, $result);
$result = json_decode($result[0]);
// Save data to db
$account = new ThirdPartyAccounts();
$account->account_id = $result->identity->id;
$account->type = 'youtube';
$account->name = $result->identity->first_name . ' ' . $result->identity->last_name;
$account->extra_details = json_encode([
'access_token' => $resultToken->access_token,
'token_type' => $resultToken->token_type,
'expires_in' => $resultToken->expires_in,
'refresh_token' => $resultToken->refresh_token
]);
$account->save();
return $account;
}
/**
* Get API token
*
* #param $id
*
* #return mixed
*/
private function getToken($id)
{
$mainAccount = ThirdPartyAccounts::find($id);
$youtubeToken = json_decode($mainAccount->extra_details);
return $youtubeToken;
}
}
But I don't know how to make use of this data, I don't know how to write the method required to get the channel views for the last 30 days (with data for every day).
Sorry but I really don't know enough about api connection in order to understand what to do so if you would be so kind as to explain to me what to do any help would be welcomed. Thank you all in advance for your time!
You can use the reports.query method to do this. It lets you retrieve many different Analytics reports. Each request uses query parameters to specify a channel ID or content owner, a start date, an end date, and at least one metric. You can also provide additional query parameters, such as dimensions, filters, or sorting instructions.
There's an example in the link provided to retrieve last 30 days but it's written in App Script:
var analyticsResponse = YouTubeAnalytics.Reports.query(
'channel==' + channelId,
oneMonthAgoFormatted,
todayFormatted,
'views,likes,dislikes,shares',
{
dimensions: 'day',
sort: '-day'
});
To do this in PHP, I suggest looking at the Youtube PHP code samples. It is rife with guide and instructions.
Related
I am trying to link up with Walmart.io API to get some data from their resources. But I am stuck up in the first phase.
According to Walmart.io Quick Start Doc (https://walmart.io/docs/affiliate/quick-start-guide) I am supposed to follow following steps:
Create an account with Walmart.io
Create an application for Web Application
Generate a certificate ( According to their guide there should be some feature to autogenerate the certificate, but I didn't find it)
Upload public key to the application
We will get consumer id and key version using which along with private key, we can make a request. We need to add additional headers that includes Signature and Timestamp too.
So, I did everything, but it still isn't working.
I am using Open SSL to generate private and public key as suggested by them: https://walmart.io/key-tutorial
I tried avoiding -des3 so that it doesn't ask me for passphrase too, but it didn't work either.
Here is the script I tried with
curl --location --request GET 'https://developer.api.walmart.com/api-proxy/service/affil/product/v2/taxonomy' \
--header 'WM_SEC.KEY_VERSION: 2' \
--header 'WM_CONSUMER.ID: <Consumer_ID>' \
--header 'WM_CONSUMER.INTIMESTAMP: 1594389945813' \
--header 'WM_SEC.AUTH_SIGNATURE: W5PEHIew3LsnATk0zxJddeo416YEpMIjvk1b7lW9VMIZFx55erc/5df/FK9UtS5i48q057oASo0AX3SDd2hx+QSeyiX3FtLAgAgiZnGqQ6nJndySWgL5ih/GaUTXIC6dd048GFEZlC6axXdGoTWNzX9P0n/2DwLF9EtvMjdvjB1kum0z2xKz/lQGlvnjVkGK9sZdSUa5rfgxKSPi7ix+LRIJWYwt6mTKUlGz2vP1YjGcZ7gVwAs9o8iFC//0rHUWFwaEGrT0aZJtS7fvSFtKj5NRfemX4fwRO4cgBRxPWy9MRooQwXPmKxRP75PxHKTerv8X6HvRo0GdGut+2Krqxg==' \
And the response I get is
{
"details": {
"Description": "Could not authenticate in-request, auth signature : Signature verification failed: affil-product, version: 2.0.0, env: prod",
"wm_svc.version": "2.0.0",
"wm_svc.name": "affil-product",
"wm_svc.env": "prod"
}
}
Hope someone gives me some insight into this problem.
Thanks in advance
I've had this issue before, it looks like the format of the data you are trying to sign is incorrect.
In node, the content of the template string should look like this: ${consumerId}\n${timeStamp}\n${keyVersion}\n
Turns out it was issue with generated Signature (That explains why it worked after I changed the script.
Thus here is the script that worked fine:
<?php
use GuzzleHttp\Psr7;
use GuzzleHttp\Exception\RequestException;
class Walmart{
private $host;
private $consumer_id;
private $private_key_file;
private $headers;
private $sec_key_version;
private $client;
private $options;
public function __construct($config){
$this->host = $config['host'];
$this->consumer_id = $config['consumer_id'];
$this->private_key_file = $config['private_key_file'];
$this->sec_key_version = $config['sec_key_version'];
$this->options = array();
$this->client = new GuzzleHttp\Client();
}
public function lookup_product($publisher_id='', $ids='', $upc='', $format='json'){
$this->load_options();
$url_params = array(
'format' => $format,
);
if($publisher_id){
$url_params['publisher_id'] = $publisher_id;
}
if($ids){
$url_params['ids'] = $ids;
}
if($upc){
$url_params['upc'] = $upc;
}
$query = http_build_query($url_params);
$url = $this->host . '/product/v2/items?'.$query;
try {
$res = $this->client->request('GET', $url, $this->options);
$body = $res->getBody();
if($res->getStatusCode() == 200){
return $this->response(false, json_decode($body, true));
}else{
return $this->response(array(
'title' => 'Unable to get products',
'stack' => $body,
));
}
} catch (RequestException $e) {
$err = Psr7\str($e->getRequest());
if ($e->hasResponse()) {
$err .= Psr7\str($e->getResponse());
}
return $this->response(array(
'title' => 'Unable to get products',
'stack' => $err,
));
}
}
private function load_options(){
$timestamp = time()*1000;
$this->options = array(
'debug' => (defined("DEBUG") && DEBUG) ? true: false,
'headers' => array(
'WM_SEC.KEY_VERSION' => $this->sec_key_version,
'WM_CONSUMER.ID' => $this->consumer_id,
'WM_CONSUMER.INTIMESTAMP' => $timestamp,
'WM_SEC.AUTH_SIGNATURE' => $this->get_signature($timestamp),
)
);
}
private function get_signature($timestamp){
$message = $this->consumer_id."\n".$timestamp."\n".$this->sec_key_version."\n";
$pkeyid = openssl_pkey_get_private("file://".$this->private_key_file);
openssl_sign($message, $signature, $pkeyid, OPENSSL_ALGO_SHA256);
$signature = base64_encode($signature);
openssl_free_key($pkeyid);
return $signature;
}
private function response($err, $data=false){
return array(
'error' => $err,
'data' => $data,
);
}
}
Note: It uses guzzlehttp/guzzle library for HTTP Request
Here is a full example based on Abiral's post above:
<?php
/**
* Sample script to sign and send a request to the Walmart Affiliate Marketing API.
*
* https://walmart.io/docs/affiliate/introduction
*
* Usage:
* 1. Fill out the required variables at the top of this script.
* 2. Install dependencies via composer install.
* 3. Run via php index.php or by opening this script in a browser.
*
* Acknowledgements:
* Abiral Neupane at https://stackoverflow.com/a/62847241/1120652
* #gorenstein at https://gitter.im/IO-support/community?at=5f2e5d2051bb7d3380d9b58b
*/
include './vendor/autoload.php';
use \GuzzleHttp\Client;
/**
* Create an account at Walmart.io. Then create an application. Then follow the
* steps at https://walmart.io/key-tutorial to create a set of keys. Upload
* the public key (its contents start with BEGIN PUBLIC KEY) into the
* production environment of the application that you created.
*/
$consumer_id = 'Paste here the consumer id that you will see in your application details after pasting the public key';
$key = 'Paste here the private key. Full, including BEGIN and END PRIVATE KEY lines.';
$version = '1';
$timestamp = round(microtime(true) * 1000);
$message = $consumer_id . "\n" . $timestamp . "\n" . $version . "\n";
$pkeyid = openssl_pkey_get_private($key);
openssl_sign($message, $signature, $pkeyid, OPENSSL_ALGO_SHA256);
$signature = base64_encode($signature);
openssl_free_key($pkeyid);
$api = 'https://developer.api.walmart.com';
$product_resource = 'api-proxy/service/affil/product/v2/items/316226539';
$client = new Client(['base_uri' => $api]);
$response = $client->get($product_resource, [
'headers' => [
'WM_SEC.KEY_VERSION' => $version,
'WM_CONSUMER.ID' => $consumer_id,
'WM_CONSUMER.INTIMESTAMP' => $timestamp,
'WM_SEC.AUTH_SIGNATURE' => $signature,
]
]);
print_r(json_decode($response->getBody()->__toString()));
I published the above at https://github.com/juampynr/walmart-api-v2-php
I'm trying to create a web-based email client which gets all email data from google mail API. I'm using Slim3 for creating a restful API interface. To access google APIs, I'm using Google-API-PHP-Client (Google does have a rest API access and I really like it but I still haven't figured out how the authorization would work without using the PHP-client-library).
My main problem is how do I structure authentication part of it as google uses Oauth2 for login which gives a code. I can use a simple token based auth in Slim but then how do I achieve the following:
Authentication/Authorization with google.
Identifying new vs returning users.
Maintaining & Retaining both access and refresh tokens from google and local APIs
Since the API will be used on both mobile clients and web-browser, I can't use PHP's default sessions - I'm relying on database driven custom tokens.
How do I structure the APIs?
One way was to use google's token as the only token in the app - but it keeps changing every hour so How do I identify the user from token - calling google API for every incoming call doesn't seem like a graceful solution.
Any leads/links would be really helpful.
Thanks in advance
Note that there are 2 parts:
Authorization
Authentication
I recently created this very lightweight class for Authorization using Google, accessing its REST API. It is self-explanatory with the comments.
/**
* Class \Aptic\Login\OpenID\Google
* #package Aptic\Login\OpenID
* #author Nick de Jong, Aptic
*
* Very lightweight class used to login using Google accounts.
*
* One-time configuration:
* 1. Define what the inpoint redirect URIs will be where Google will redirect to upon succesfull login. It must
* be static without wildcards; but can be multiple as long as each on is statically defined.
* 2. Define what payload-data this URI could use. For example, the final URI to return to (the caller).
* 3. Create a Google Project through https://console.developers.google.com/projectselector/apis/credentials
* 4. Create a Client ID OAth 2.0 with type 'webapp' through https://console.developers.google.com/projectselector/apis/credentials
* 5. Store the 'Client ID', 'Client Secret' and defined 'Redirect URIs' (the latter one as defined in Step 1).
*
* Usage to login and obtain user data:
* 1. Instantiate a class using your stored Client ID, Client Secret and a Redirect URI.
* 2. To login, create a button or link with the result of ->getGoogleLoginPageURI() as target. You can insert
* an array of payload data in one of the parameters your app wants to know upon returning from Google.
* 3. At the Redirect URI, invoke ->getDataFromLoginRedirect(). It will return null on failure,
* or an array on success. The array contains:
* - sub string Google ID. Technically an email is not unique within Google's realm, a sub is.
* - email string
* - name string
* - given_name string
* - family_name string
* - locale string
* - picture string URI
* - hdomain string GSuite domain, if applicable.
* Additionally, the inpoint can recognize a Google redirect by having the first 6 characters of the 'state' GET
* parameter to be 'google'. This way, multiple login mechanisms can use the same redirect inpoint.
*/
class Google {
protected $clientID = '';
protected $clientSecret = '';
protected $redirectURI = '';
public function __construct($vClientID, $vClientSecret, $vRedirectURI) {
$this->clientID = $vClientID;
$this->clientSecret = $vClientSecret;
$this->redirectURI = $vRedirectURI;
if (substr($vRedirectURI, 0, 7) != 'http://' && substr($vRedirectURI, 0, 8) != 'https://') $this->redirectURI = 'https://'.$this->redirectURI;
}
/**
* #param string $vSuggestedEmail
* #param string $vHostedDomain Either a GSuite hosted domain, * to only allow GSuite domains but accept all, or null to allow any login.
* #param array $aPayload Payload data to be returned in getDataFromLoginRedirect() result-data on succesfull login. Keys are not stored, only values. Example usage: Final URI to return to after succesfull login (some frontend).
* #return string
*/
public function getGoogleLoginPageURI($vSuggestedEmail = null, $vHostedDomain = '*', $aPayload = []) {
$vLoginEndpoint = 'https://accounts.google.com/o/oauth2/v2/auth';
$vLoginEndpoint .= '?state=google-'.self::encodePayload($aPayload);
$vLoginEndpoint .= '&prompt=consent'; // or: select_account
$vLoginEndpoint .= '&response_type=code';
$vLoginEndpoint .= '&scope=openid+email+profile';
$vLoginEndpoint .= '&access_type=offline';
$vLoginEndpoint .= '&client_id='.$this->clientID;
$vLoginEndpoint .= '&redirect_uri='.$this->redirectURI;
if ($vSuggestedEmail) $vLoginEndpoint .= '&login_hint='.$vSuggestedEmail;
if ($vHostedDomain) $vLoginEndpoint .= '&hd='.$vHostedDomain;
return($vLoginEndpoint);
}
/**
* Call this function directly from the redirect URI, which is invoked after a call to getGoogleLoginPageURL().
* You can either provide the code/state GET parameters manually, otherwise it will be retrieved from GET automatically.
* Returns an array with:
* - sub string Google ID. Technically an email is not unique within Google's realm, a sub is.
* - email string
* - name string
* - given_name string
* - family_name string
* - locale string
* - picture string URI
* - hdomain string G Suite domain
* - payload array The payload originally provided to ->getGoogleLoginPageURI()
* #param null|string $vCode
* #param null|string $vState
* #return null|array
*/
public function getDataFromLoginRedirect($vCode = null, $vState = null) {
$vTokenEndpoint = 'https://www.googleapis.com/oauth2/v4/token';
if ($vCode === null) $vCode = $_GET['code'];
if ($vState === null) $vState = $_GET['state'];
if (substr($vState, 0, 7) !== 'google-') {
trigger_error('Invalid state-parameter from redirect-URI. Softfail on login.', E_USER_WARNING);
return(null);
}
$aPostData = [
'code' => $vCode,
'client_id' => $this->clientID,
'client_secret' => $this->clientSecret,
'redirect_uri' => $this->redirectURI,
'grant_type' => 'authorization_code'
];
curl_setopt_array($hConn = curl_init($vTokenEndpoint), [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_HEADER => false,
CURLOPT_FOLLOWLOCATION => true,
CURLOPT_USERAGENT => defined('PROJECT_ID') && defined('API_CUR_VERSION') ? PROJECT_ID.' '.API_CUR_VERSION : 'Aptic\Login\OpenID\Google PHP-class',
CURLOPT_AUTOREFERER => true,
CURLOPT_SSL_VERIFYPEER => false,
CURLOPT_POST => 1
]);
curl_setopt($hConn, CURLOPT_POSTFIELDS, http_build_query($aPostData));
$aResult = json_decode(curl_exec($hConn), true);
curl_close($hConn);
if (is_array($aResult) && array_key_exists('access_token', $aResult) && array_key_exists('refresh_token', $aResult) && array_key_exists('expires_in', $aResult)) {
$aUserData = explode('.', $aResult['id_token']); // Split JWT-token
$aUserData = json_decode(base64_decode($aUserData[1]), true); // Decode JWT-claims from part-1 (without verification by part-0).
if ($aUserData['exp'] < time()) {
trigger_error('Received an expired ID-token. Softfail on login.', E_USER_WARNING);
return(null);
}
$aRet = [
// 'access_token' => $aResult['access_token'],
// 'expires_in' => $aResult['expires_in'],
// 'refresh_token' => $aResult['refresh_token'],
'sub' => array_key_exists('sub', $aUserData) ? $aUserData['sub'] : '',
'email' => array_key_exists('email', $aUserData) ? $aUserData['email'] : '',
'name' => array_key_exists('name', $aUserData) ? $aUserData['name'] : '',
'given_name' => array_key_exists('given_name', $aUserData) ? $aUserData['given_name'] : '',
'family_name' => array_key_exists('family_name', $aUserData) ? $aUserData['family_name'] : '',
'locale' => array_key_exists('locale', $aUserData) ? $aUserData['locale'] : '',
'picture' => array_key_exists('picture', $aUserData) ? $aUserData['picture'] : '',
'hdomain' => array_key_exists('hd', $aUserData) ? $aUserData['hd'] : '',
'payload' => self::decodePayload($vState)
];
return($aRet);
} else {
trigger_error('OpenID Connect Login failed.', E_USER_WARNING);
return(null);
}
}
protected static function encodePayload($aPayload) {
$aPayloadHEX = [];
foreach($aPayload as $vPayloadEntry) $aPayloadHEX[] = bin2hex($vPayloadEntry);
return(implode('-', $aPayloadHEX));
}
/**
* You generally do not need to call this method from outside this class; only if you
* need your payload *before* calling ->getDataFromLoginRedirect().
* #param string $vStateParameter
* #return array
*/
public static function decodePayload($vStateParameter) {
$aPayload = explode('-', $vStateParameter);
$aRetPayload = [];
for($i=1; $i<count($aPayload); $i++) $aRetPayload[] = hex2bin($aPayload[$i]);
return($aRetPayload);
}
}
As soon as the function getDataFromLoginRedirect does return user data, your user is Authorized. This means you can now issue your own internal authentication token.
So, for Authentication, maintain your own data table of users with either sub or email as primary identifier and issue tokens for them, with appropriate expire mechanisms. The Google tokens themselves do not necessarily be stored, as they are only required for subsequent Google API calls; which depend on your use case. For your own application though, your own token mechanism will suffice for authentication.
To get back to your questions:
Authentication/Authorization with google.
Described above.
Identifying new vs returning users.
Can be determined by the existence of the user in your data table.
Maintaining & Retaining both access and refresh tokens from google and local APIs
Ask yourself the question whether you really need to. If so, you could either refresh upon every x requests, or refresh once the expiry time is in less than x minutes (i.e. this will be your application's timeout in that case). If you really require your tokens to remain valid, you should setup a daemon-mechanism that periodically refreshes your users tokens.
When I try to access phpmailer/get_outh_token.php to get refresh token server returns:
HTTP ERROR 500
Client ID, Secret key and redirect Uri are correct, and i am using it already in Wordpress.
I have downloaded last version of phpmailer, also tested with old version with same result.
I found what cause this, it is this part:
namespace League\OAuth2\Client\Provider;
When I remove it, then script loads with errors of course because
Provider namespace is not loaded.
Website working on PHP 7.
This is full code of get_outh_token.php, and it is original (just credentials are different of course):
<?php
error_reporting(E_ALL);
ini_set('display_errors', 'On');
/**
* Get an OAuth2 token from Google.
* * Install this script on your server so that it's accessible
* as [https/http]://<yourdomain>/<folder>/get_oauth_token.php
* e.g.: http://localhost/phpmail/get_oauth_token.php
* * Ensure dependencies are installed with 'composer install'
* * Set up an app in your Google developer console
* * Set the script address as the app's redirect URL
* If no refresh token is obtained when running this file, revoke access to your app
* using link: https://accounts.google.com/b/0/IssuedAuthSubTokens and run the script again.
* This script requires PHP 5.4 or later
* PHP Version 5.4
*/
namespace League\OAuth2\Client\Provider; //when i remove this line, than page load without 500, but with errors.
require 'vendor/autoload.php';
use League\OAuth2\Client\Provider\Exception\IdentityProviderException;
use League\OAuth2\Client\Token\AccessToken;
use League\OAuth2\Client\Tool\BearerAuthorizationTrait;
use Psr\Http\Message\ResponseInterface;
session_start();
//If this automatic URL doesn't work, set it yourself manually
$redirectUri = 'https://www.secret.co/phpmailer/get_oauth_token.php';
//These details obtained are by setting up app in Google developer console.
$clientId = 'secret.apps.googleusercontent.com';
$clientSecret = 'secret';
class Google extends AbstractProvider
{
use BearerAuthorizationTrait;
const ACCESS_TOKEN_RESOURCE_OWNER_ID = 'id';
/**
* #var string If set, this will be sent to google as the "access_type" parameter.
* #link https://developers.google.com/accounts/docs/OAuth2WebServer#offline
*/
protected $accessType;
/**
* #var string If set, this will be sent to google as the "hd" parameter.
* #link https://developers.google.com/accounts/docs/OAuth2Login#hd-param
*/
protected $hostedDomain;
/**
* #var string If set, this will be sent to google as the "scope" parameter.
* #link https://developers.google.com/gmail/api/auth/scopes
*/
protected $scope;
public function getBaseAuthorizationUrl()
{
return 'https://accounts.google.com/o/oauth2/auth';
}
public function getBaseAccessTokenUrl(array $params)
{
return 'https://accounts.google.com/o/oauth2/token';
}
public function getResourceOwnerDetailsUrl(AccessToken $token)
{
return ' ';
}
protected function getAuthorizationParameters(array $options)
{
if (is_array($this->scope)) {
$separator = $this->getScopeSeparator();
$this->scope = implode($separator, $this->scope);
}
$params = array_merge(
parent::getAuthorizationParameters($options),
array_filter([
'hd' => $this->hostedDomain,
'access_type' => $this->accessType,
'scope' => $this->scope,
// if the user is logged in with more than one account ask which one to use for the login!
'authuser' => '-1'
])
);
return $params;
}
protected function getDefaultScopes()
{
return [
'email',
'openid',
'profile',
];
}
protected function getScopeSeparator()
{
return ' ';
}
protected function checkResponse(ResponseInterface $response, $data)
{
if (!empty($data['error'])) {
$code = 0;
$error = $data['error'];
if (is_array($error)) {
$code = $error['code'];
$error = $error['message'];
}
throw new IdentityProviderException($error, $code, $data);
}
}
protected function createResourceOwner(array $response, AccessToken $token)
{
return new GoogleUser($response);
}
}
//Set Redirect URI in Developer Console as [https/http]://<yourdomain>/<folder>/get_oauth_token.php
$provider = new Google(
array(
'clientId' => $clientId,
'clientSecret' => $clientSecret,
'redirectUri' => $redirectUri,
'scope' => array('https://mail.google.com/'),
'accessType' => 'offline'
)
);
if (!isset($_GET['code'])) {
// If we don't have an authorization code then get one
$authUrl = $provider->getAuthorizationUrl();
$_SESSION['oauth2state'] = $provider->getState();
header('Location: ' . $authUrl);
exit;
// Check given state against previously stored one to mitigate CSRF attack
} elseif (empty($_GET['state']) || ($_GET['state'] !== $_SESSION['oauth2state'])) {
unset($_SESSION['oauth2state']);
exit('Invalid state');
} else {
// Try to get an access token (using the authorization code grant)
$token = $provider->getAccessToken(
'authorization_code',
array(
'code' => $_GET['code']
)
);
// Use this to get a new access token if the old one expires
echo 'Refresh Token: ' . $token->getRefreshToken();
}
I know this question is old, but I was having same issue.
All I did was to install league/oauth2-google via composer
composer require league/oauth2-google
This helped me figure it out
Hope it help some else.
I have recently received a Facebook developer notification:
Graph API v2.1 Upgrade Notice
foobarapplication has been making recent API calls to Graph API v2.0,
which will reach the end of the 2-year deprecation window on Monday,
August 8, 2016. Please migrate all calls to v2.1 or higher in order to
avoid potential broken experiences.
We recommend using our new Graph API Upgrade Tool to see which of your
calls are affected by this change as well as any replacement calls in
newer versions. You can also use our changelog to see the full list of
changes.
A year ago I have upgraded Facebook for the given PHP application, by extracting the PHP SDK and changing source-code usages. The login review was successful and there were no serious problems since then. However, the app needs to upgrade from Facebook API 2.0 soon. I have an idea as of how to achieve this, but am not sure whether I am correct. Let us consider the following functionalities:
FacebookRedirectLoginHelper class:
/**
* Stores CSRF state and returns a URL to which the user should be sent to
* in order to continue the login process with Facebook. The
* provided redirectUrl should invoke the handleRedirect method.
*
* #param array $scope List of permissions to request during login
* #param string $version Optional Graph API version if not default (v2.0)
* #param boolean $displayAsPopup Indicate if the page will be displayed as a popup
*
* #return string
*/
public function getLoginUrl($scope = array(), $version = null, $displayAsPopup = false)
{
$version = ($version ?: FacebookRequest::GRAPH_API_VERSION);
$this->state = $this->random(16);
$this->storeState($this->state);
$params = array(
'client_id' => $this->appId,
'redirect_uri' => $this->redirectUrl,
'state' => $this->state,
'sdk' => 'php-sdk-' . FacebookRequest::VERSION,
'scope' => implode(',', $scope)
);
if ($displayAsPopup)
{
$params['display'] = 'popup';
}
return 'https://www.facebook.com/' . $version . '/dialog/oauth?' .
http_build_query($params, null, '&');
}
/**
* Returns a URL to which the user should be sent to re-request permissions.
*
* #param array $scope List of permissions to re-request
* #param string $version Optional Graph API version if not default (v2.0)
*
* #return string
*/
public function getReRequestUrl($scope = array(), $version = null)
{
$version = ($version ?: FacebookRequest::GRAPH_API_VERSION);
$this->state = $this->random(16);
$this->storeState($this->state);
$params = array(
'client_id' => $this->appId,
'redirect_uri' => $this->redirectUrl,
'state' => $this->state,
'sdk' => 'php-sdk-' . FacebookRequest::VERSION,
'auth_type' => 'rerequest',
'scope' => implode(',', $scope)
);
return 'https://www.facebook.com/' . $version . '/dialog/oauth?' .
http_build_query($params, null, '&');
}
FacebookRequest class:
/**
* FacebookRequest - Returns a new request using the given session. optional
* parameters hash will be sent with the request. This object is
* immutable.
*
* #param FacebookSession $session
* #param string $method
* #param string $path
* #param array|null $parameters
* #param string|null $version
* #param string|null $etag
*/
public function __construct(
FacebookSession $session, $method, $path, $parameters = null, $version = null, $etag = null
)
{
$this->session = $session;
$this->method = $method;
$this->path = $path;
if ($version) {
$this->version = $version;
} else {
$this->version = static::GRAPH_API_VERSION;
}
$this->etag = $etag;
$params = ($parameters ?: array());
if ($session
&& !isset($params["access_token"])) {
$params["access_token"] = $session->getToken();
}
if (FacebookSession::useAppSecretProof()
&& !isset($params["appsecret_proof"])) {
$params["appsecret_proof"] = $this->getAppSecretProof(
$params["access_token"]
);
}
$this->params = $params;
}
FacebookCurlHttpClient class:
/**
* Detect versions of Curl which report incorrect header lengths when
* using Proxies.
*
* #return boolean
*/
private static function needsCurlProxyFix()
{
$ver = self::$facebookCurl->version();
$version = $ver['version_number'];
return $version < self::CURL_PROXY_QUIRK_VER;
}
My idea is as follows:
getLoginUrl is called from the application; a version of 2.6. should be specified from now on
I do not really use getReRequestUrl, so I will not make changes in the code for it
FacebookRequest will be instantiated with a $version of 2.6
needsCurlProxyFix will be left as it is
Basically, I will use the PHP lib released in 2014, but with specifying $version at calls. Is my approach feasible, or should I use a new client-side library?
As things turned out, my version was up to date and I did not need to do any changes for Facebook's upgrade to version 2.1. except changing the version name used.
This is killing me.I have done everything but not right as its not still giving me this error
Fatal error: Uncaught exception 'CFCredentials_Exception' with message 'No credentials were provided. I am trying to upload files to S3 using AWS sdk 1.6 example and jquery file upload plugin.I found an example on the wiki.
This is my file where I set the credentials awssdk.php from the wiki example
require_once 'sdk.class.php';
require_once 'utilities.class.php';
require_once 'credential.class.php';
if (!class_exists('CFCredentials'))require_once('credentials.class.php');
$name=null;
CFCredentials::set(array(
$name => array(
'key' => 'access key',
'secret' => 'secret key',
'certificate_authority' => false
),
'#default' => $name
));
if (!class_exists('S3'))require_once('S3.php');
$s3 = new AmazonS3();
I am quite sure I should't need so many files but as the errors suggested I had to add the dependency classes.But still I get the above error. I also tried to include the config.class.php file for credentials and still got this error.I have been spending a lot of time on this and now kind of frustrated with this AWS sdk.
I am a bit new to OO PHP and probably hence finding it difficult.Experts please suggest some solution to where I am wrong.
EDIT: I believe this class causes the issue,not sure how!!
class CFCredentials
{
/**
* The key used to specify the default credential set
*/
const DEFAULT_KEY = 'my key';
/**
* The key used to identify inherited credentials
*/
const INHERIT_KEY = 'my secret key';
/**
* Stores the credentials
*/
protected static $credentials = array();
/**
* Prevents this class from being constructed
*/
final private function __construct() {}
/**
* Stores the credentials for re-use.
*
* #param array $credential_sets (Required) The named credential sets that should be made available to the application.
* #return void
*/
// private $credential_sets = array('key' => 'xxxxxxxxxxxxxxxxxxxx','secret' => 'xxxxxxxxxxxxxxxxxxxxxxx/xxxxxxxxxxxxxxxx','certificate_authority' => false);
public static function set(array $credential_sets)
{
// Make sure a default credential set is specified or can be inferred
if (count($credential_sets) === 1)
{echo "in count if-->".self::DEFAULT_KEY;
$credential_sets[self::DEFAULT_KEY] = reset($credential_sets);
}
// Resolve any #inherit tags
foreach ($credential_sets as $credential_name => &$credential_set)
{
if (is_array($credential_set))
{
foreach ($credential_set as $credential_key => &$credential_value)
{
if ($credential_key === self::INHERIT_KEY)
{
if (!isset($credential_sets[$credential_value]))
{
throw new CFCredentials_Exception('The credential set, "' . $credential_value . '", does not exist and cannot be inherited.');
}
$credential_set = array_merge($credential_sets[$credential_value], $credential_set);
unset($credential_set[self::INHERIT_KEY]);
}
}
}
}
// Normalize the value of the #default credential set
if (isset($credential_sets[self::DEFAULT_KEY]))
{
$default = $credential_sets[self::DEFAULT_KEY];
if (is_string($default))
{
if (!isset($credential_sets[$default]))
{
throw new CFCredentials_Exception('The credential set, "' . $default . '", does not exist and cannot be used as the default credential set.');
}
$credential_sets[self::DEFAULT_KEY] = $credential_sets[$default];
}
}
// Store the credentials
self::$credentials = $credential_sets;
}
/**
* Retrieves the requested credentials from the internal credential store.
*
* #param string $credential_set (Optional) The name of the credential set to retrieve. The default value is set in DEFAULT_KEY.
* #return stdClass A stdClass object where the properties represent the keys that were provided.
*/
public static function get($credential_name = self::DEFAULT_KEY)
{
//echo $credential_name; exit;
// Make sure the credential set exists
if (!isset(self::$credentials[$credential_name]))
{
throw new CFCredentials_Exception('The credential set, "' . $credential_name . '", does not exist and cannot be retrieved.');
}
// Return the credential set as an object
return new CFCredential(self::$credentials[$credential_name]);
}
/**
* Retrieves a list of all available credential set names.
*
* #return CFArray A list of all available credential set names.
*/
public static function list_sets()
{
return new CFArray(array_keys(self::$credentials));
}
}
class CFCredentials_Exception extends Exception {}
Thank you
It seems like whatever tutorial you are following is making this unnecessarily difficult. Try this:
require_once 'sdk.class.php';
$s3 = new AmazonS3(array(
'key' => 'your_aws_access_key_id',
'secret' => 'your_aws_secret_key',
));
You shouldn't need to require any other files.
You have set all Credential well but still you have leave one credential 'default_cache_config' => ''
Just Put it in Credential array with some location for caching the default credential.
just have a look
$name=null;
CFCredentials::set(array(
$name => array(
'key' => 'access key',
'secret' => 'secret key',
'default_cache_config' => '/home/user/any location',
'certificate_authority' => false
),
'#default' => $name
));**