http://westbrook.co.uk/authenticating-to-yahoo-public-apis-with-oauth/
Sometimes I find an API that is completely open and that makes my life really easy, but often, unfortunately we need to jump through some hoops to get to the free data. Recently I have been integrating to Yahoo Finance web-services (I am not covering the service or data detail here as there were a few hoops there too! but this is a great resource for Yahoo Finance), and for development purposes there is no need to authenticate at all, we can make free unauthenticated calls.
However for production purposes, the limits are as follows:
- Unauthenticated: up to 1,000 calls/day
- Authenticated: up to 100,000 calls/day
So if you need to make more than 1000 calls then we need to authenticate with Yahoo OAuth process. But digging into the docshere we see that we can use the “two-legged” OAuth authentication as opposed to “three-legged”. Essentially this means that we can use OAuth flows for system integration without going through the extra user authentication steps. We just need to supply our credentials, receive the oauth_token and then continue to make our requests.
Hoop 1 : Get a Yahoo API Key
- You need to have first a Yahoo account, these days thats not so common amongst tech types, as we all seem to prefer gmail.
- Create a “Project” here to represent you integration and generate an API key. Nothing is critical on this page, but select the free options.
- You now have the Consumer Secret & Consumer Key.
- Important: there seems to be some bug, the keys dont work unless you check at least one of the “select APIs for private user access” options at the bottom of the page, even though we don’t intend to use or authenticate to user data. So go and tick some of these. Note, your Consumer Key and Secret will change every time you modify this page. So store the consumer data only once you are done.
Hoop 2: Make a callout to get the OAuth request token
We make a httpRequest as below, with explanations of parameters where it is not obvious
public static void getRequestToken(){
loadConsumerSettings(); // get the key/secret from custom settings.
String resBody = ”;
Datetime nowTime = Datetime.now();
String oauthTimestamp = String.valueOf( (nowTime.getTime() / 1000) ); //to produce a unix time stamp like: ‘1406105798’
String oauthNonce = oauthTimestamp + String.valueOf(getRandomInt(1,9999)); //”number used once” — a unique number that we dont reuse
// build the url
String url = GET_REQUEST_TOKEN_BASE_URL
+ ‘?oauth_consumer_key=’ + OAUTH_CONSUMER_KEY
+ ‘&oauth_signature=’ + OAUTH_CONSUMER_SECRET + ‘%26′ // for request the secret is signature with & appended
+ ‘&oauth_signature_method=’ + OAUTH_SIGNATURE_METHOD
+ ‘&oauth_version=’ + OAUTH_VERSION
+ ‘&oauth_callback=’ + OAUTH_CALLBACK
+ ‘&oauth_timestamp=’ + oauthTimestamp
+ ‘&oauth_nonce=’ + oauthNonce;
// Prepare HTTP request
HTTPResponse httpRes;
HTTPRequest req = new HttpRequest();
req.setEndpoint(url);
req.setMethod(‘POST’);
req.setHeader(‘Content-Type’, ‘application/x-www-form-urlencoded’);
req.setHeader(‘Content-Length’, ‘0’); // we need to set a content length, but yahoo does not verify
//Make callout
HTTP http = new HTTP();
try{
httpRes = http.send(req);
resBody = httpRes.getBody();
}catch(system.Exception e) {
system.debug(‘>>>>>>> YahooOauth->getRequestToken : Exception During callout: ‘ + e);
}
// pull out the token & token secret
OAUTH_TOKEN = (resBody.substringAfter(‘oauth_token=’)).subStringBefore(‘&’);
OAUTH_TOKEN_SECRET = (resBody.substringAfter(‘oauth_token_secret=’)).subStringBefore(‘&’);
}
Hoop 3: Extract the OAuth response and build into the API call that you need.
In the OAuth call above we pull out and store the OAUTH_TOKEN & OAUTH_TOKEN_SECRET, we then need to send these as parameters for the final yahoo finance calls, so any future yahoo finance call needs to have the Oauth credentials appended, I create a utility class to add this to the callout url for reuse.
public String appendOauthToUrl(String url){
//add on the OAuth Authenticated bit
Datetime nowTime = Datetime.now();
String oauthTimestamp = String.valueOf( (nowTime.getTime() / 1000) ); //to produce a unix time stamp like: ‘1406105798’
String oauthNonce = oauthTimestamp + String.valueOf(LTAYS_YahooOauth.getRandomInt(1,9999));//”number used once” — a unique number that we dont reuse
url = url
+ ‘&oauth_consumer_key=’ + LTAYS_YahooOauth.OAUTH_CONSUMER_KEY
+ ‘&oauth_nonce’ + oauthNonce
+ ‘&oauth_signature=’ + LTAYS_YahooOauth.OAUTH_CONSUMER_SECRET + ‘%26′ + LTAYS_YahooOauth.OAUTH_TOKEN_SECRET
+ ‘&oauth_signature_method=’ + LTAYS_YahooOauth.OAUTH_SIGNATURE_METHOD
+ ‘&oauth_version=’ + LTAYS_YahooOauth.OAUTH_VERSION
+ ‘&oauth_timestamp=’ + oauthTimestamp
+ ‘&token=’ + LTAYS_YahooOauth.OAUTH_TOKEN ;
//+ ‘&oauth_token_secret=’ + LTAYS_YahooOauth.OAUTH_TOKEN_SECRET;
return url;
}
Runscope is a great tool for testing any callout process, allowing fast correction and familiarization with services, and saves a lot of debugging time over going straight into apex.
An example yahoo oauth callout dummy with parameter stubs:
An example yahoo callout dummy with parameter stubs: