Mar 31, 2014

Calling Out to a Google API with an Access Token

One of the best things about Google is that they have APIs for all their services. These APIs come handy when you are trying to integrate with Google from within Salesforce. I recently had to do just that, and thought I'd share some of what I've learned...

First of all, I quickly realized that I couldn't use the Google Data API Toolkit because Google Data APIs are part of an older generation of Google APIs that have authentication methods that are deprecated. Also the Google Data APIs don’t include some of the more interesting enterprise applications that Google has to offer. The newer Google APIs are SOAP based and you need to go through an OAuth 2.0 handshake to authenticate. I used the OAuth 2.0 for Web Server Applications flow, and didn't have too much issues with it (look for a future post on that).

Since Apex does not have a client library for the newer Google APIs, I had to download the WSDL for the resource I wanted to access. I had a couple of issues with wsdl2apex, but was able to get around them. However, after some poking around, I realized that the wsdl conversion didn't work too well after all and had to abandon that path (I think it is related to how wsdl2apex translates attributes and gets around reserved words).

My next move was to make the SOAP call with a normal http callout, which meant that I had to create the XML body to add to the callout. Most of the transaction was a no brainer, but I had a hell of a time figuring out how to include the access token in the SOAP XML. I found the documentation to be either confusing, old, or plain wrong (I did complain about it in one of the boards, and they made some changes since). After quite a bit of trials and errors, I finally got it right though.

So to spare you the extra time it took me to put this together, the following is a very quick sample method that shows you how to set the SOAP headers, including the access token. Please note that this code sample is very simplified - I jammed everything into one method and did not include coverage. Also, in my implementation I am using the XML stream writer to create the body, but in this case included the XML as a sting so it is easier to read.