YUCEL MORAN
YUCEL MORAN

Salesforce and Mulesoft experience

Yucel
Author

Share


Our Newsletter


Subscribe to get new post notifications.

* indicates required

Tags


Twitter


YUCEL MORAN

Mulesoft 3.9.1 Quickbooks Online authentication (Without QB connector)

YucelYucel

One more time, here's the strategy to get connected our Quikbooks Online application using Mulesoft without using the "QuickBooks Desktop Connector - Mule 3" that currently is listed in Exchange. Seems that version is outdated, as the API version that uses to connect to quickbooks is not working really anymore, plus of that, the latest runtime version for this connector is 3.5.

In this post, I want to demonstrate:

Is important to mention this schema is designed to be used for applications that will be running in batch mode, not that realtime is not supported but we will be able to pull some data from quickbooks, at least you'll have the base.

Let's jump into the steps:

  1. Create or have developer access to Intuit Developer portal. You can signup here
  2. Once we have access we should create an application in the portal (My apps > Create a new App)

3. We should select the "Just Start Coding" option and clic on Select APIs, then we can select Accounting and Payments check boxes.

4.Once the application is created we are gonna focus only in the second tab where the API keys are stored, we can see there's a Client ID and Client Secret

5. In the same tab we should see the Redirect URI section, in here we need to place our redirect URLs, for this sample http://localhost:8081/callback it's going to be the one we use, but you should replace it for the Cloudhub domain or your standalone one.

6. Get the Quickbooks Company ID or realmid. Here we need to clic in the same page the "View Sandbox" button and that will take us to the Quickbooks page.

Once there, we need to clic on the gear at the top of the page and select "Your Account"

And under the Company Information we should see the company Id

Until here we got the Quickbooks information we need to start working with our mulesoft application. So now we need:

  1. Create a Mulesoft application that cover to have maven and properties file as described in this post.

2.We are going to create different flows to handle every action.

Before to start the next diagram try to explain how the workflow is executed.

general authorization flow

Let's get our access code from quickbooks, so for this flow we need:

  1. Expose an HTTP endpoint and a HTTP static  Resource Handler as we need to show to the user the screen to clic the "Authorize button".
  2. Under our src>app folder we need to create new one called "web" and inside a file named dev.staticForm.html.  

the content of that file should look like this:

<html>
	<body>
		<h2><a href="https://appcenter.intuit.com/connect/oauth2?client_id=YOUR_CLIENT_ID6&redirect_uri=http://localhost:8081/callback&response_type=code&scope=com.intuit.quickbooks.accounting&state=gcv">Click to Authenticate</a></h2>
	</body>
</html>

If we run our application and go to http://localhost:8081/accessCode/ we should see this page:

Clic on the link and we should see:

Now we can clic on Connect and it should redirect to the SERVICE-CALLBACK FLOW.

Our mule flow looks like this:

This flow allows to use the access code we generated and generate an authorization code, also on this flow we need to make a refresh token to store it in the database

so the first we need to prepare the POST request for that we use a dataWeave component with this definition:

%dw 1.0
%output application/java
---
{
	grant_type:"authorization_code",
	code:flowVars.accessCode,
	redirect_uri: "http://localhost:8081/callback"
}

Next is our HTTP Request connector:

NOTE: For the Authorization Header value we need to pass CLIENT ID and SECRET, in this case those values are coming from the properties file.

Basic #[new String(org.apache.commons.codec.binary.Base64.encodeBase64(("${client_id}:${client_secret}").getBytes()))]

Allows to check in our database table if we have a value stored for out integration, if we have one then we can still refreshing the token and have a valid one. For this call we need this values:

%dw 1.0
%output application/java
---
{
	grant_type:"refresh_token",
	refresh_token:payload.refresh_token//coming from database
}

Allows to keep alive the refresh token so we can generate a new one and update it in the database

This is just one sample call we can make to demonstrate all is working. For this we can call this flow:

which basically retrieves the accessToken to make the call and we pass it in our HTTP Request connector:

For this call the endpoint changes depending of the environment (Sandbox / Production) for this sample: https://sandbox-quickbooks.api.intuit.com

The JSON response is:

{
  "Customer": {
    "Taxable": true,
    "BillAddr": {
      "Id": "2",
      "Line1": "4581 Finch St.",
      "City": "Bayshore",
      "CountrySubDivisionCode": "CA",
      "PostalCode": "94326",
      "Lat": "INVALID",
      "Long": "INVALID"
    },
    "ShipAddr": {
      "Id": "2",
      "Line1": "4581 Finch St.",
      "City": "Bayshore",
      "CountrySubDivisionCode": "CA",
      "PostalCode": "94326",
      "Lat": "INVALID",
      "Long": "INVALID"
    },
    "Job": false,
    "BillWithParent": false,
    "Balance": 239,
    "BalanceWithJobs": 239,
    "CurrencyRef": {
      "value": "USD",
      "name": "United States Dollar"
    },
    "PreferredDeliveryMethod": "Print",
    "domain": "QBO",
    "sparse": false,
    "Id": "1",
    "SyncToken": "0",
    "MetaData": {
      "CreateTime": "2018-09-14T16:48:43-07:00",
      "LastUpdatedTime": "2018-09-21T13:39:32-07:00"
    },
    "GivenName": "Amy",
    "FamilyName": "Lauterbach",
    "FullyQualifiedName": "Amy's Bird Sanctuary",
    "CompanyName": "Amy's Bird Sanctuary",
    "DisplayName": "Amy's Bird Sanctuary",
    "PrintOnCheckName": "Amy's Bird Sanctuary",
    "Active": true,
    "PrimaryPhone": {
      "FreeFormNumber": "(650) 555-3311"
    },
    "PrimaryEmailAddr": {
      "Address": "Birds@Intuit.com"
    },
    "DefaultTaxCodeRef": {
      "value": "2"
    }
  },
  "time": "2018-10-20T08:16:03.179-07:00"
}

You can take the whole sample code from this repository

Hope this sample helps, probably there's a few more options like using (mongo DB, sqlite) I would like some thoughts.

Author

Yucel

Comments