Saturday, February 4, 2012

How to use Keith Palmer's PHP-DevKit to integrate a web app with Quickbooks Online

So here at Appguppy, we've been trying to enhance our e-commerce features to make it easier for our customers to sell stuff on their apps.  One of the initiatives is to integrate our system with Quickbooks so that people can easily pull in their products and sell the through their app.

For this we needed to use Intuit's Partner Platform and their SDK.  Unfortunately, they don't have a set of libraries for PHP, but since the IPP now allows oauth and XML, it is not too hard to integrate.  Still, there are dozens of object types and thousands of properties that we need to build in, and that's very time consuming.

So along comes a new version of Keith Palmer's excellent PHP-DevKit. Which finally supports oauth. The problem is, it's not immediately obvious how to use it.  Below is a step by step guide:

1. Download the latest devkit build. Unfortunately, its currently only available via SVN, so you'll have to install an SVN client and point it to this url:

svn checkout https://code.intuit.com/svn/repos/php_devkit
 
2.To create our simple app, we put it on a test server in our /var/www directory.  You should now have a file Quickbooks.php and a sub-directory Quickbooks under /var/www

3. Make sure you have mcrypt installed in PHP, you can check this with phpinfo().  If not, download and install it.

4. Make a new file index.php and put the following in the file:

require_once 'QuickBooks.php';


$token = 'sfewtw4et3w45sfsfsdfdsf';
$oauth_consumer_key = 'sfewtwsetsgsdsdfsdc';
$oauth_consumer_secret = 'dsffwe5tr4w5sdfsdfsdfsdfsdf';

// This is the URL of your OAuth auth handler page
$this_url = 'http://myserver/index.php';

// This is the URL to forward the user to after they have connected to IPP/IDS via OAuth
$that_url = 'http://myserver/other.php';

$dsn = 'mysql://test:test@localhost/quickbooks';

// You should set this to an encryption key specific to your app
$encryption_key = 'abcd1234';

// The user that's logged in
$the_username = 'your_app_username_here_2';

// The tenant that user is accessing within your own app
$the_tenant = 12345; 
if (!QuickBooks_Utilities::initialized($dsn))
  {
    // Initialize creates the neccessary database schema for queueing up requests and logging
    QuickBooks_Utilities::initialize($dsn);
  }

$IntuitAnywhere = new QuickBooks_IPP_IntuitAnywhere($dsn, $encryption_key, $oauth_consumer_key, $oauth_consumer_secret, $this_url, $that_url);

if ($IntuitAnywhere->handle($the_username, $the_tenant))
  {
    ; // The user has been connected, and will be redirected to $that_url automatically. 
  }
else
  {
    die('Oh no, something bad happened: ' . $IntuitAnywhere->errorNumber() . ': ' . $IntuitAnywhere->errorMessage());
  } 
  
Let's also make a file called other.php

require_once 'QuickBooks.php';


$token = 'sfewtw4et3w45sfsfsdfdsf';
$oauth_consumer_key = 'sfewtwsetsgsdsdfsdc';
$oauth_consumer_secret = 'dsffwe5tr4w5sdfsdfsdfsdfsdf';

// This is the URL of your OAuth auth handler page
$this_url = 'http://myserver/index.php';

// This is the URL to forward the user to after they have connected to IPP/IDS via OAuth
$that_url = 'http://myserver/other.php';

$dsn = 'mysql://test:test@localhost/quickbooks';

// You should set this to an encryption key specific to your app
$encryption_key = 'abcd1234';

// The user that's logged in
$the_username = 'your_app_username_here_2';

// The tenant that user is accessing within your own app
$the_tenant = 12345; 
if (!QuickBooks_Utilities::initialized($dsn))
  {
    // Initialize creates the neccessary database schema for queueing up requests and logging
    QuickBooks_Utilities::initialize($dsn);
  } 
 
// Set up the IPP instance                                                                                                                                                                                                    
$IPP = new QuickBooks_IPP($dsn);

// Set up our IntuitAnywhere instance                                                                                                                                                                                         
$IntuitAnywhere = new QuickBooks_IPP_IntuitAnywhere($dsn, $encryption_key, $oauth_consumer_key, $oauth_consumer_secret);

// Get our OAuth credentials from the database                                                                                                                                                                                
$creds = $IntuitAnywhere->load($the_username, $the_tenant);

// Tell the framework to load some data from the OAuth store                                                                                                                                                                  
$IPP->authMode(
               QuickBooks_IPP::AUTHMODE_OAUTH,
               $the_username,
               $creds);

// Print the credentials we're using                                                                                                                                                                                          
print_r($creds);

// This is our current realm                                                                                                                                                                                                  
$realm = $creds['qb_realm'];

// Load the OAuth information from the database                                                                                                                                                                               
if ($Context = $IPP->context())
  {
    // Set the DBID                                                                                                                                                                                                           
    $IPP->dbid($Context, 'something');

    // Set the IPP flavor                                                                                                                                                                                                     
    $IPP->flavor($creds['qb_flavor']);

    // Get the base URL if it's QBO                                                                                                                                                                                           
    if ($creds['qb_flavor'] == QuickBooks_IPP_IDS::FLAVOR_ONLINE)
      {
        $IPP->baseURL($IPP->getBaseURL($Context, $realm));
      }

    print('Base URL is [' . $IPP->baseURL() . ']' . "\n\n");
     $CustomerService = new QuickBooks_IPP_Service_Customer();

    $perpage = 3;
    for ($page = 1; $page <= 3; $page++)
      {
        print('PAGE ' . $page . "\n\n");

        $list = $CustomerService->findAll($Context, $realm, null, null, $page, $perpage);

        foreach ($list as $Customer)
          {
            print('Name [' . $Customer->getName() . ']' . "\n\n");
          }

        print("\n\n\n");
      }

    print("\n\n\n\n");
    print('Request [' . $IPP->lastRequest() . ']');
    print("\n\n\n\n");
    print('Response [' . $IPP->lastResponse() . ']');
    print("\n\n\n\n");
  }
else
  {
    die('Unable to load a context...?');
  }
 

5. Now, a little aside on how oauth works with PHP-DevKit -
  • The first request is made by the original php page (in our case index.php - but you can specify whatever you want in $this_url) to the oauth server with your oauth consumer secret and and oauth consumer key (I'll tell you how to get those in a sec).  This is done by the handle() function in the IntuitAnywhere object.
  • The handle() function then redirects the user to the authentication URL, which shows one of those login/connect screens to the user (like you see when you use a Twitter app).  
  • Once the user accepts the app, Intuit sends the user back to the page they were on (it will return to whatever is in $this_url -- in our case index.php).  This time the handle() function sees that there is a token in the HTTP request and saves the token.  It then redirects the user to another page ($that_url, or in our case other.php).
  • In other.php, we re-initialize the IntuitAnywhere object, but instead of using handle() to get the token, we use load() to load the token that was saved in the previous step.
  • We then create an IPP object specifying that we're using oauth, and that will provide us with a context from which to make calls.
6. Now let's make this thing work.  First, get your token, oauth consumer key and oauth consumer secret from Intuit's Developer Center under Manage Apps -> (click on your Dev Master app) -> "App Tokens and Keys".  In both index.php and other.php set the lines marked in purple above to those values.

7. Replace myserver (marked in green) in both files to your server URL.   Also update the Mysql username and password (marked in blue) to yours

8. Create a database in mysql called quickbooks. This will be used to save tokens.  All the tables will be created automatically by PHP Devkit.

9. That's it - now point your browser to http://myserver/index.php - it should redirect to the Intuit Anywhere authorization screen. Users can enter their username and password there and click to authorize your app. Once they do, it will go to other.php and you should see a list of customers for that user.

Hopefully this makes oauth with devkit a bit easier to get started.

39 comments:

  1. hi,

    i am confused on where to get the value for $the_tenant variable...please help...

    thanks in advance...

    ReplyDelete
  2. Raymond- the $the_tenant variable is something YOU provide- it's your OWN unique identifier for that particular customer/tenant of your web application.

    e.g. if you identify your customers with a unique #, then put your unique customer # there. If you identify them with a domain name (e.g. "their-company.your-website.com") then you could pass in their subdomain.

    ReplyDelete
  3. hi,

    I am confused where will configure the $the_tenant value for my customers?

    ReplyDelete
  4. Hi Raymond- did you read my comment above and look at the example code? All you have to do is set the $the_tenant variable to your unique identifier for your customer (e.g. your customer ID or customer primary key value). If you look in the example files, it's set in the example_ipp_config.php file.

    ReplyDelete
  5. Looks like I get a

    Error Code: internal_error
    Message: Error getting application from request token

    error when visiting index.php... I can't seem to figure it out! Any suggestions?

    ReplyDelete
  6. Egavas - please use our FORUMS for support:
    * https://idnforums.intuit.com/
    OR
    * http://www.consolibyte.com/forum/

    You will have to post your code so we know what you're doing.

    ReplyDelete
  7. I am getting error "Fatal error: Class 'QuickBooks_IPP_IntuitAnywhere' not found"

    Please help me out.

    Thanks in advance!!!

    ReplyDelete
  8. Pawanvir - if you're having trouble, you should post on the forums. The forums are the best avenue for technical support. http://www.consolibyte.com/forum/ You should consider posting your code so that we can see what you're doing.
    - Keith

    ReplyDelete
  9. Hi Keith

    Thanks for replying. I will have Pawanvir to show the code. However i would like to know your views as what we are trying to achieve is possible.

    We are using core php to create our custom shopping cart and trying to connect it to clients QuickBooks Software. However we never used quickbooks. I read on some forums that it will be done through some web connector, however they are asp.net based. Pl. advise if the solutions is still possible in php and what will be the steps involved.

    Thanks

    Vikram
    www.antechindia.com

    ReplyDelete
  10. Vikram,

    If you are building a custom, one-off shopping cart *for a single customer* then you should be using the Web Connector, not IPP. Again, post on our forums or the Intuit forums if you need more details.

    If you are building an SaaS application which allows many of your end-users to connect their QuickBooks files to your app, and you charge a recurring fee for it, then Intuit Anywhere is the appropriate choice.

    ReplyDelete
  11. Also - the Web Connector is completely language agnostic, since it communicates via SOAP. Thus, the fact that they are ASP.NET based has absolutely no bearing on anything what-so-ever.

    ReplyDelete
  12. HI,

    I have added the customer trough the API(example_ipp_ids_add.php).
    I also get response with customer added-{NG-5330401}.

    But i am unable to view the customer at https://appcenter.intuit.com/Home/DevHome

    ReplyDelete
  13. Prakash - PLEASE USE OUR FORUMS FOR SUPPORT:
    * https://idnforums.intuit.com/
    OR
    * http://www.consolibyte.com/forum/

    You will have to post your code so we know what you're doing.

    ReplyDelete
  14. Perfect tutorial for beginners to connect to QB.

    ReplyDelete
  15. In order to install mycrypt on Mac, please visit the following link:-
    http://www.coolestguyplanettech.com/how-to-install-mcrypt-for-php-on-mac-osx-lion-10-7-development-server/

    ReplyDelete
  16. Hi

    php_devkit gives error in Aes.php as like
    Notice: unserialize() [function.unserialize]: Error at offset 0 of 78 bytes in

    Please give the solution of it

    ReplyDelete
  17. Santosh - PLEASE USE OUR FORUMS FOR SUPPORT:
    * https://idnforums.intuit.com/
    OR
    * http://www.consolibyte.com/forum/

    You will have to post your code so we know what you're doing.

    ReplyDelete
  18. Hi

    i download code :

    php_devkit

    now i cant understand how to start set up code or how to use this code??

    what i need to do that i make a one online shopping cart system. when customer purchase order than invoice also generate in quickbook... i need a quickbook online so can u pls help me or guide me how to do???

    ReplyDelete
  19. POST ON THE FORUMS IF YOU NEED SUPPORT. THIS IS NOT AN APPROPRIATE AVENUE FOR GETTING SUPPORT.

    * https://idnforums.intuit.com/
    OR
    * http://www.consolibyte.com/forum/

    You will have to post your code so we know what you're doing.

    ReplyDelete
  20. Hi Keith,

    I have also integrated this code in my application. But I am not able getting any customer details. Please tell me what we have to input in "$encryption_key" variable and "$the_tenant" variable.
    Waiting for your response.

    Thanks!

    ReplyDelete
  21. *** IF YOU NEED SUPPORT, YOU NEED TO ASK ON THE FORUMS: http://www.consolibyte.com/forum/ ***

    If you ask on the forums, you will get a prompt, detailed response. I can NOT provide support via this comment board thing.

    - Keith

    ReplyDelete
  22. Hi Keith,

    I am just asking only what value we have to pass for these 2 variables.

    Thanks!

    ReplyDelete
  23. Look, I'm not trying to be mean here - the bottom line is just that this comment board is just not a good way to provide support. Comments posted on this blog aren't searchable, they mangle code snippets, they aren't separated into relevant topics, and the answers posted here just generally don't benefit the community as a whole, because very few people are going to see the comments here.

    For that reason, we don't provide support via this board.

    If you want support, PLEASE PLEASE PLEASE ask on the forums. We're a small open-source project team, and we simply can't waste our time answering your questions here when all they do is make a mess of everything we say. If you at all value our contributions to the open-source community, please be appreciative of that and ask your questions on the forums.

    ReplyDelete
  24. Buy Youtube Subscribers
    Beautiful sentences, words succinct, the story theme anacreontic, the article development is very curious feeling

    ReplyDelete
  25. I have gone through the url that you have mentioned (http://www.consolibyte.com/forum/),
    but it was saying BLOCKED..!

    i am very much in need of integrating QB Online..!

    Can you help me over this issue pelase...!

    ReplyDelete
    Replies
    1. Lucki - if you get that message, it also shows you an e-mail address to email and your IP address. Send an email to that address with your IP address, and we'll unblock you. It's likely because someone was/is using your IP to send SPAM.

      Delete
    2. This comment has been removed by the author.

      Delete
    3. This comment has been removed by the author.

      Delete
  26. Hi Keith,
    I know posting here is absurd, but i was stuck with the issue and i could not access (http://www.consolibyte.com/forum/),

    I am having an issue,
    Fatal error: Class 'OAuth' not found in D:\wamp\www\QB\Core\RestCalls\SyncRestHandler.php on line 194

    I couldnot find the class.

    so could you please help me reagarding this issue.
    i am very in need of it. (laxman2021@gmail.com)

    ReplyDelete
  27. Lucki - I will respond via e-mail.

    ReplyDelete
  28. I have configured the QuickBooks now how actually it shuld be integrated with the existing PHP CMS application the Example index.php and all are working but noiw i have live php files how to integrated our database with QuickBooks Please Let me know as i am facing my deadlines

    ReplyDelete
  29. Do i need to install the Web Connector or just use this Framework that will work for me i have just installed the framework for PHP CMS application but then how to keep it in Sync with my database please let me know..

    ReplyDelete
  30. Hello Keith,
    I have started to work on quickbook.Following step i have done-
    1.Download v3-php-sdk-2.0.5 (1)
    2.Download quickbooks-devkit
    3.Under build folder(after extract of quickbook).
    I create index.php ,other.php.
    4.Create a account on developer.intuit.com and update the secreet key token in my files.
    Please tell me next step.
    Thanks

    ReplyDelete
  31. Please read my comments above -- IF YOU NEED SUPPORT, PLEASE ASK ON OUR FORUMS: http://www.consolibyte.com/forum/

    I'm sorry, but I can not provide support via this webpage. Ask on the forums instead.

    ReplyDelete
  32. Nice blog...Very useful information is providing by ur blog. Great beginning php tutorials Very clear and helpful for beginners.

    ReplyDelete
  33. I purchased palmer’s products online from Awesome bazar. Awesome Bazar provides best competitive prices product and fast delivery process . Really very nice service of awesome bazar, Awesome bazaar best Shopping destination. Find At https://awesomebazar.com/brands/palmer-s/

    ReplyDelete
  34. after doing the complete configuration when i run the index.php using PHP SDK from github after clicking on connect to quickbook button it gives me the following error

    Oops! An error has occurred.
    Please close this window and try again.

    Error Code: internal_error
    Message: Error getting application from request token


    You can contact us for further assistance. Error Id:ixnkryec2iu513ef45f3f5xv-66016491

    Your help will be appreciated

    ReplyDelete