We are trying to implement Twitter new DM API from Salesforce. We are sending our the JSON request in the body as mentioned in documentation but the legacy method for Oauth authorization is not working. Any help is greatly appreciated.
To add, I am sending a DM from salesforce to twitter, So
1) I am setting the request body in JSON.
2) I am doing a POST.
3) I am hitting the endpoint at ‘https://api.twitter.com/1.1/direct_messages/events/new.json‘
4) Oauth2, getting the access token(successfully)
5) Setting header as (‘Content-Type’, ‘application/json’).
6) Creating Authorization header as twitter mentions using consumer key, Nonce, Signature, Signature method, Timestamp, Version. Building the same as in “Guide” section of developer.twitter.com/en/docs/basics/authentication/guides/
7) On running the error code “{“errors”:[{“code”:32,”message”:”Could not authenticate you.”}]}”.
Another important information that I had been using twitter old API to send DM that works perfect, only difference is it sends the request body in URL parameters instead of JSOn body but the authorization method remains same. As some new Functionality can only be achieved via Twitter New API and according to documentation the body needs to be sent via JSON format. Therefore the request part is changed but authorization is same.
Sample code:-
String accTok = 'redacted';
String conKey = 'redacted';
String conSec = 'redacted';
String accTokSec = 'redacted';
String theTweet = 'Hello world!';
String screenName ='some_test_username';
String jsonString = TwitterJsonReqGenerator.generateJSON(theTweet, screenName);
system.debug('JSON string ='+jsonString);
httpRequest newReq = new httpRequest();
newReq.setBody(jsonString);
newReq.setMethod('POST');
newReq.setEndpoint('https://api.twitter.com/1.1/direct_messages/events/new.json');
//Generate Nonce
string oAuth_nonce = EncodingUtil.base64Encode(blob.valueOf(string.valueOf(Crypto.getRandomInteger()+system.now().getTime())+string.valueOf(Crypto.getRandomInteger()))).replaceAll('[^a-z^A-Z^0-9]','');
map<String, String> heads = new map<String, String>{
'oauth_token'=>accTok,
'oauth_version'=>'1.0',
'oauth_nonce'=>oAuth_nonce,
'oauth_consumer_key'=>conKey,
'oauth_signature_method'=>'HMAC-SHA1',
'oauth_timestamp'=>string.valueOf(system.now().getTime()/1000)
};
//Alphabetize
string[] paramHeads = new string[]{};
paramHeads.addAll(heads.keySet());
paramHeads.sort();
string params = '';
for(String encodedKey : paramHeads){
params+=encodedKey+'%3D'+heads.get(encodedKey)+'%26';
}
//params+='status'+percentEncode('='+percentEncode(theTweet));
params+=percentEncode(theTweet);
//Build the base string
string sigBaseString = newReq.getMethod().toUpperCase()+'&'+EncodingUtil.urlEncode(newReq.getEndpoint(),'UTF-8')+'&'+params;
system.debug('signatureBaseString == '+sigBaseString);
//calculate signature
string sigKey = EncodingUtil.urlEncode(conSec,'UTF-8')+'&'+EncodingUtil.urlEncode(accTokSec,'UTF-8');
blob mac = crypto.generateMac('hmacSHA1', blob.valueOf(sigBaseString), blob.valueOf(sigKey));
string oauth_signature = EncodingUtil.base64Encode(mac);
heads.put(EncodingUtil.urlEncode('oauth_signature','UTF-8'), EncodingUtil.urlEncode(oauth_signature,'UTF-8'));
//build the authorization header
paramHeads.clear();
paramHeads.addAll(heads.keySet());
paramHeads.sort();
string oAuth_Body = 'OAuth ';
for(String key : paramHeads){
oAuth_Body += key+'="'+heads.get(key)+'", ';
}
oAuth_Body = oAuth_Body.subString(0, (oAuth_Body.length() - 2));
newReq.setHeader('Authorization', oAuth_Body);
system.debug('Authroization Header == '+oAuth_Body);
newReq.setHeader('Content-Type', 'application/json');
httpResponse httpRes = new http().send(newReq);
String response = httpRes.getBody();
system.debug(response);
Thanks
Prateek
2
Answers
I’ve written Twitter libraries and applications in the past, and the bst advice that I can give you is to use an existing implementation of OAuth instead of attempting to write your own. Re-implementing OAuth in new code is re-inventing the wheel, and it’s a wheel that hates you. There are a number of robust and mature OAuth libraries that are free and/or open source.
Just happened to stumble on your query. I am posting a code(C#) (though it is a bit late) which worked for me to send DM to Twitter using the new API. Hope this helps. Thanks to Danny Tuppeny’s blog
To call: