If you are interacting with Twitter, you hopefully know that the old 1.0 API (that didn’t need authentication) is being retired next week. So this sort of query won’t work anymore:
https://api.twitter.com/1/users/show.json?screen_name=britishboyindc
Instead, you have to authenticate against Twitter first, get a token, and then make you request(s). On the plus side, you get access to the far richer 1.1 API, which will let you do the query above for 100 accounts at once. So if you just need to update some basic stats every night for a few hundred accounts, this makes life much easier (when people complain about Limits in Salesforce – tell them to try Twitter’s API!)
The authentication instructions look a little intimidating compared with the previous method that didn’t involve any effort, but they are actually pretty straight forward to implement in Salesforce. I am using the Application Auth process, since I don’t need to post as a user.
First, generate your consumer key + consumer secret key per the instructions. I suggest storing them in a Custom Setting – I have one called social_media_settings to store the two keys.
Then you’ll need a method to generate the bearer:
private String getBearerToken() { //Encode them String keyencoded = EncodingUtil.urlEncode(socialsettings.API_Key__c, 'UTF-8'); String secretkeyencoded = EncodingUtil.urlEncode(socialsettings.API_Secret_Key__c, 'UTF-8'); //Create Final Key String String sFinal = keyencoded + ':' + secretkeyencoded; //Convert to Blob Blob headerValue = Blob.valueOf(sFinal); //Build Request HttpRequest req = new HttpRequest(); req.setEndpoint('https://api.twitter.com/oauth2/token'); req.setMethod('POST'); //Add Auth Header String authorizationHeader = 'Basic ' + EncodingUtil.base64Encode(headerValue); req.setHeader('Authorization', authorizationHeader); //You need to add this to the request - proved easy to miss in instructions... req.setBody('grant_type=client_credentials'); //Make request Http http = new Http(); HTTPResponse res = http.send(req); String stoken; //Parse JSON for Bearer Token JSONParser parser = JSON.createParser(res.getBody()); while (parser.nextToken() != null) { if (parser.getCurrentToken() == JSONToken.FIELD_NAME && parser.getText() == 'access_token'){ parser.nextToken(); stoken = parser.getText(); } } //Return Token so it can be used in next call return stoken; }
Now you have the a way to get the Bearer Code, you can authenticate your request like this:
private void submittotwitter () { HttpRequest req2 = new HttpRequest(); //I actually store the endpoint in the same custom setting and build dynamically, but for purposes of demo: req2.setEndpoint('https://api.twitter.com/1.1/users/lookup.json?screen_name=britishboyindc,salesforce'); req2.setMethod('GET'); //Call Bearer token Method //Note - unless invalidated, I believe you can store this and keep using it indefinitely, but again, to demo concept String authorizationHeader = 'Bearer ' + getBearerToken(); req2.setHeader('Authorization', authorizationHeader); Http http = new Http(); HTTPResponse res = http.send(req2); String sBody = res.getBody(); //I have a Twitter Results class to de-serialize the results into (See below) Map <String, TwitterResults> TwitterResultsMap = new Map<String, TwitterResults> (); //You can generate one here: http://json2apex.herokuapp.com/makeApex //I can then pass the results back as a return, or set the map as s public variable on the class //Use native JSON parser to turn results into a list of TwitterResults List tresults = TwitterResults.parse(sBody); //The key is set to be the twitter handle name that I am storing in SFDC For (TwitterResults t: tresults) { TwitterResultsMap.put(t.screen_name, t); } }
So now I have the result data (followers_count, statuses_count) for all the twitter handles I queried for a map I can reference and use to update my contacts in Salesforce. There is much more you can do of course!
public class TwitterResults { public Integer id; public Integer listed_count; public String screen_name; public String url; public Integer followers_count; public Integer friends_count; public Integer statuses_count; public static List<TwitterResults> parse(String json) { return (List<TwitterResults>) System.JSON.deserialize(json, List<TwitterResults>.class); }