The QuickBooks-V3-PHP-SDK is giving me a hard time.
I'm trying to use it to sync invoice data. I can successfully get authorization using OAuth 2.0 and connect my client PHP web application to QuickBooks Online. However, while I can successfully make a getCompanyInfo call and receive the results, I can't make a getUserInfo call (or most of the other API calls for that matter), as it will complain about the "access token object" not being set yet.
While connecting to QuickBooks and getting authorization, everything seems to work accurately - and the access token object is successfully placed in the PHP Session. But for some reason, it complains when I try to get the UserInfo data, or use any of the other API calls.
Here's the error that I receive:
Fatal error: Uncaught QuickBooksOnline\API\Exception\SdkException: [0]: Can't get OAuth 2 Access Token Object. It is not set yet.
thrown in /compiled/src/Core/OAuth/OAuth2/OAuth2LoginHelper.php on line 129
Here's how I try to get the UserInfo:
$dataService->updateOAuth2Token($accessToken);
$OAuth2LoginHelper = $dataService->getOAuth2LoginHelper();
$result = $OAuth2LoginHelper->getUserInfo();
Again, getting the CompanyInfo works without any problems.
Does anyone have any idea what's going on?
Below I'm including the code from apiCall.php (from the HelloWorld example package, further edited by myself). This file is used to make requests through Ajax after I already connected to and received authorization from QuickBooks Online.
<?php
require_once(__DIR__ . '/vendor/autoload.php');
use QuickBooksOnline\API\Core\ServiceContext;
use QuickBooksOnline\API\DataService\DataService;
use QuickBooksOnline\API\Core\Http\Serialization\XmlObjectSerializer;
use QuickBooksOnline\API\Facades\Invoice;
session_start();
function makeAPICall()
{
// Create SDK instance
$config = include('config.php');
$dataService = DataService::Configure(array(
'auth_mode' => 'oauth2',
'ClientID' => $config['client_id'],
'ClientSecret' => $config['client_secret'],
'RedirectURI' => $config['oauth_redirect_uri'],
'scope' => $config['oauth_scope'],
'baseUrl' => "development"
));
/*
* Retrieve the accessToken value from session variable
*/
$accessToken = $_SESSION['sessionAccessToken'];
$dataService->throwExceptionOnError(true);
/*
* Update the OAuth2Token of the dataService object
*/
$dataService->updateOAuth2Token($accessToken);
//Get the requested data:
$action = filter_input(INPUT_GET, "action", FILTER_SANITIZE_SPECIAL_CHARS);
$method = "get$action";
switch($action){
case "CompanyInfo":
$result = $dataService->$method();
break;
case "UserInfo":
$OAuth2LoginHelper = $dataService->getOAuth2LoginHelper();
$result = $OAuth2LoginHelper->getUserInfo();
break;
case "InvoiceExample":
$allInvoices = $dataService->Query("SELECT * FROM Invoice");
$result = $allInvoices;
break;
}
var_dump($result);
return $result;
}
$result = makeAPICall();
?>
Anyone any idea what I'm doing wrong?
The Intuit (QuickBooks) support team provided the answer to me. In my ApiCall code above, I had to use the following code to make the UserInfo request:
$result = $OAuth2LoginHelper->getUserInfo($accessToken->getAccessToken(), 'development');
Obviously, if this would involve production keys, I would have to replace 'development' with 'production'.
Related
I am using twitter account activity api's to send/receive messages. In it i am facing problem in generating webhook. First time it was created successfully. In webhook file i am saving messages in database when each time message sent or received. But when I sent message nothing goes in database. Here is webhook file:
const APP_CONSUMER_SECRET = '**********';
// Example token provided by incoming GET request
if(isset($_REQUEST['crc_token'])) {
$token = $_REQUEST['crc_token'];
/**
* Creates a HMAC SHA-256 hash created from the app TOKEN and
* your app Consumer Secret.
* #param token the token provided by the incoming GET request
* #return string
*/
function get_challenge_response($token) {
$hash = hash_hmac('sha256', $token, APP_CONSUMER_SECRET, true);
$response = array(
'response_token' => 'sha256=' . base64_encode($hash)
);
return json_encode($response);
}
}else{
$feedData = file_get_contents('php://input');
$handleData = fopen('twitterDemo.txt', "w" );
fwrite($handleData,$feedData);
fclose($handleData);
$array = json_decode(file_get_contents('php://input'), true);
if (isset($array['direct_message_events'][0]['type']) && $array['direct_message_events'][0]['type'] == 'message_create' ) {
include_once ('config.php');
include_once ('database-queries.php');
$message = $array['direct_message_events'][0]['message_create']['message_data']['text'];
$sender = $array['direct_message_events'][0]['message_create']['sender_id'];
$from = $array['direct_message_events'][0]['message_create']['target']['recipient_id'];
$message_type = 'incoming';
$message_status = 'unread';
$userId = $sender;
$account_name = 'twitter';
$image_url = '';
if(isset($array['direct_message_events'][0]['message_create']['message_data']['attachment'])){
$image_url = "Not Image";
}
$data = array('to'=>$from, 'from'=>$sender, 'msg'=>$message,'image_url' =>$image_url);
insert($data, $account_name, $message_type, $message_status, $conn);
}
}
I thought there might be webhook problem so i deleted the existing app and create new one and set development environment label for it with new name. But for it when i tried to create webhook it gives me error:
[code] => 214 [message] => Webhook URL does not meet the requirements.
Invalid CRC token or json response format.
I dont know whats happening here now. I am using this api to create webhook url
$url = "https://example.com/twitter/webhook.php";
$result = $connection->post("account_activity/all/env_name/webhooks", ["url" => $url]);
Can anyone please help me this out. Any help will be appreciated.
Thanks!
I ran into the same error message.
The problem seem to be that the
if(isset($_REQUEST['crc_token']))
is not working anymore. Though the token is set. I don't know what is causing the problem but when I let the code just fetch the $_REQUEST['crc_token'] and create and print the hash its working.
But I see your code is not calling the get_challenge_response($token) function.
I think
print get_challenge_response($token)
may help? If the Webhook was deactivated by twitter you have to initiate another CRC check:
https://developer.twitter.com/en/docs/twitter-api/v1/accounts-and-users/subscribe-account-activity/guides/securing-webhooks
Your app can also trigger a CRC when needed by making a PUT request with your webhook id. Triggering a CRC is useful as you develop your webhook application, after deploying new code and restarting your service.
I am trying to build a simple MS Graph API call to get familiar with Graph.
However, I can't get it to work. MS Graph keeps giving the error that my token has expired, while it's not.
Code:
<?php
require_once('C:\inetpub\site6\vendor\autoload.php');
// Using newest version of TheNetworg Oauth2
$provider = new TheNetworg\OAuth2\Client\Provider\Azure([
'clientId' => '***************',
'clientSecret' => '**********',
'redirectUri' => 'https://app2.***/test.php'
]);
// Set to use v2 API, skip the line or set the value to Azure::ENDPOINT_VERSION_1_0 if willing to use v1 API
$provider->defaultEndPointVersion = TheNetworg\OAuth2\Client\Provider\Azure::ENDPOINT_VERSION_2_0;
$baseGraphUri = $provider->getRootMicrosoftGraphUri(null);
//echo $baseGraphUri;
$provider->tenant = '*********.onmicrosoft.com'; //Azure AD ID
$provider->authWithResource;
$provider->scope = $baseGraphUri . '/.default';
$token = $provider->getAccessToken('client_credentials', ['scope' => $provider->scope]);
// echo $token;
// Set up our request to the API
$ref= 'users/someuser#mytenant.com';
$response = $provider->get($ref, $token, $headers = []);
// Store the result as an object
$result = json_decode( $response->getBody() );
?>
But I keep getting ended up with error:
PHP Fatal error: Uncaught
League\OAuth2\Client\Provider\Exception\IdentityProviderException:
Your access token has expired. Please renew it before submitting the
request. in
C:\inetpub\site6\vendor\thenetworg\oauth2-azure\src\Provider\Azure.php:394
What am I doing wrong? When I google the error, I get a lot of results telling that I am trying to access MS Graph with an Azure AD Graph token, but when I do echo $baseGraphUri; I really tells me graph.microsoft.com.
I found out what the error is. Although I use "$baseGraphUri = $provider->getRootMicrosoftGraphUri(null);", the library still connects to the Azure AD API instead of the Microsoft Graph API. So it authenticates with the wrong kind (aud) of token.
Adding this line fixed the problem:
$provider->urlAPI = 'https://graph.microsoft.com/';
I want to connect Instagram Basic Display API with a website in order to display one user's post. But, when trying to authenticate the user (myself, for test purposes) I'm getting this error:
{"error_type": "OAuthException", "code": 400, "error_message": "Invalid redirect_uri"}
This is the PHP code I'm using for my request:
require_once 'ig_defines.php';
Class instagram_basic_display_api {
private $_appId = INSTAGRAM_APP_ID;
private $_appSecret = INSTAGRAM_APP_SECRET;
private $_redirectUrl = INSTAGRAM_APP_REDIRECT_URI;
private $_getCode = '';
private $_apiBaseUrl = 'https://api.instagram.com/';
public $authorizationUrl = '';
// called on class init
function __construct( $params ) {
// save instagram code
$this->_getCode = $params['get_code'];
// get an access token (code will follow)
// get authorization url
$this->_setAuthorizationUrl();
}
private function _setAuthorizationUrl() {
$getVars = array(
'app_id' => $this->_appId,
'redirect_uri' => $this->_redirectUrl,
'scope' => 'user_profile,user_media',
'response_type' => 'code'
);
// create url
$this->authorizationUrl = $this->_apiBaseUrl . 'oauth/authorize?' . http_build_query( $getVars );
}
}
private $_redirectUrl = INSTAGRAM_APP_REDIRECT_URI; is "http://google.com/" as suggested in this post. My OAuth Redirect URI in the facebook developer tools Instagram API settings is "http://google.com/" as well.
For testing I'm using my test webspace. The URL is something like http://mytestwebspace.de/instagram/news_ig_test.php. As you can see, it doesn't have SSL. The final page is going to, though. Could the lack of SSL be an issue?
EDIT: I forgot to add, I did try using http://mytestwebspace.de/instagram/news_ig_test.php as redirectUrl before, but I'm still getting the same error.
I'm not sure what the reason could be.
I can confirm, SSL is required. When using https://mytestwebspace.de/etc... , authentication works just fine. (Though it's not surprising, I didn't quite expect the solution to be that simple, thus why I opened a thread.)
I had a problem with updating user cover pic using php(zend framework) and Oauth.
I have added to my composer.json the following lines:
"require" : {
"google/auth": "0.7",
"google/apiclient" : "^2.0.0#RC"
}
After that I made composer-install + composer-update using and oppp I get the library inside my vendor.
I have configured my application inside google developing console, following the official tutorial by google :D
Now inside my controller I could easily request google web service using this method :
public function googleplusAction()
{
Zend_Loader::loadFile("HttpPost.class.php");
$client_id = "id_here";
$client_secret = "secret_here";
$application_name = "application_name_here";
$redirect_uri = "redirection_uri_here";
$oauth2_server_url = 'https://accounts.google.com/o/oauth2/auth';
$query_params = array(
'response_type' => 'code',
// The app needs to use Google API in the background
'client_id' => $client_id,
'redirect_uri' => $redirect_uri,
'scope' => 'https://www.googleapis.com/auth/userinfo.profile'
);
$forward_url = $oauth2_server_url . '?' . http_build_query($query_params);
header('Location: ' . $forward_url);
}
After that I get redirected to my redirection URI , and in the bar address I get a new variable 'code'.
Until now, I hope everything is fine , coming to the most important part , the controller of the redirection URI page , using the 'code' variable that I have talked about it before I tried to get an access token, but I was failed.
This is the method that should set a new cover picture on google plus :
$client_id = "client-id";
$client_secret = "g+-secret";
$application_name = "my-app-name";
$redirect_uri = "my-uri-on-g+";
$client = new Google_Client();
$client->setClientId($client_id);
$client->setClientSecret($client_secret);
$client->setRedirectUri($redirect_uri);
$service = new Google_Service_Oauth2($client);
$client->addScope(Google_Service_Oauth2::USERINFO_PROFILE);
$client->authenticate($_GET['code']); // I have the right code, and I am being authenticated
$plus = new Google_Service_Plus($client);
$person = $plus->people->get('me');
var_dump($person);
$pic = $this->session->image['generatedAbs'];
$gimg = new Google_Service_Plus_PersonCover();
$source = new Google_Service_Plus_PersonCoverCoverPhoto();
$source ->setUrl("$photo-that-i-wanted-to-put-on-g+");
$gimg->setCoverPhoto($source);
$person->setCover($gimg);}
So my questions are :
How can I change my google plus cover picture to a new png or JPEG picture that I have already in my project ?
inside the G+ library I found this method :
Google_Service_Plus_PersonCoverCoverPhoto();
inside a class called
Google_Service_Plus_PersonCover();
But how can I use it ?
I think that methods Google_Service_Plus_PersonCoverCoverPhoto() and Google_Service_Plus_PersonCover() are used by the client library to set it when the information is retrieved. It is not meant for you to be able to update the users cover on Google+, if that does work it will only update the class object which really there is no point in doing (IMO).
var_dump($person->Cover);
If you check the Plus.People documentation you will notice there are no update or patch methods. This is because its not possible to update a users information programmatically at this time.
Answer: Your inability to update the users cover picture has nothing to do with Oauth it has to do with the fact that this is not allowed by the API. Unfortunately it looks like you have done a lot of work for nothing this is why it is good to always consult the documentation before you begin you would have seen that it was not possible, and could have avoided a lot of unnecessary stress on yourself.
struggling to understand the oauth2 token and refresh token processes
ive got this code
$url = 'https://www.googleapis.com/oauth2/v3/token';
$data = array('client_id' => 'clientid', 'client_secret' => 'secret','refresh_token' => 'token','grant_type' => 'refresh_token');
$options = array(
'http' => array(
'header' => "Content-type: application/x-www-form-urlencoded",
'method' => 'POST',
'approval_prompt'=>'force',
'access_type'=>'offline',
'content' => http_build_query($data),
),
);
$context = stream_context_create($options);
$result = file_get_contents($url, false, $context);
that code above gives me an access token , and i followed this link suggested by one fellow stackoverflower, pinoyyid, BUT , im confunsed on how to correctly use the resulting access token to access drive and copy a file...
all the process ive seen usually involves $client = new Google_Client() and im not sure on how to use the whole POST http://..... thing, so basically i need to figure out if i use the access token i got with the code above in a new instance of google client, or i simply do a post to a url with necesary info ( which im not clear on also ) any help/clarification is appreciated guys really
EDIT #1
what i want to achieve is to allow the end user to access my drive via my webpage, to let them copy a spreadsheet in my drive , and access it via my website, to store data on the spreadsheet,the spreadsheet will always be on my drive, never on the end user
EDIT #2
code as per your posts is as follows, using the service account,,,,the files are inside that gmail account which i created on the api console a service account
<?php
require 'Google/autoload.php';
$client = new Google_Client();
// Replace this with your application name.
$client->setApplicationName("TEST");
// Replace this with the service you are using.
$service = new Google_Service_Drive($client);
// This file location should point to the private key file.
$key = file_get_contents($_SERVER['DOCUMENT_ROOT'] . '/number-privatekey.p12');
$user_to_impersonate = 'admin#testpr.com';
$cred = new Google_Auth_AssertionCredentials(
'number#developer.gserviceaccount.com',
array('https://www.googleapis.com/auth/drive'), ****//this here has to be drive not drive.file
$key,
'notasecret',
'http://oauth.net/grant_type/jwt/1.0/bearer',
$user_to_impersonate
);
$client->setAssertionCredentials($cred);
if ($client->getAuth()->isAccessTokenExpired()) {
$client->getAuth()->refreshTokenWithAssertion();
}
$originFileId = "longnumber";
$copyTitle = 'copied';
$newfile = copyFile($service, $originFileId, $copyTitle);
print_r($newfile);
function copyFile($service, $originFileId, $copyTitle)
{
$copiedFile = new Google_Service_Drive_DriveFile();
$copiedFile->setTitle($copyTitle);
try {
return $service->files->copy($originFileId, $copiedFile);
} catch (Exception $e) {
print "An error occurred: " . $e->getMessage();
}
return NULL;
}
?>
so got it working just now, ty all for your time guys really and edited my post to reflect the dang thing
If you want to give the end user access to your drive, you have to give your application authority to make API calls on behalf of a user (in this case you) in your domain. For this you have to set up a service account and generate a p12 key in the Google Developers Console. You have to enter the https://www.googleapis.com/auth/drive API scope in your Admin Console as well.
Full explanation and examples can be found here: https://developers.google.com/api-client-library/php/auth/service-accounts.
To achieve this you also need the Google API's client library: https://github.com/google/google-api-php-client (also mentioned in the Google manual).
Code example to let users make API calls on behalf of one of your accounts: https://developers.google.com/api-client-library/php/guide/aaa_oauth2_service