Twitter新的DM API,传统的授权方法不起作用

Twitter新的DM API,传统的授权方法不起作用

问题描述:

我们正试图从Salesforce实施Twitter新的DM API。如文档中所述,我们正在发送我们的JSON请求,但Oauth授权的传统方法不起作用。任何帮助是极大的赞赏。Twitter新的DM API,传统的授权方法不起作用

要添加,我发送一个DM从销售队伍到Twitter,所以 1)我设置JSON的请求正文。 2)我正在做一个POST。 3)我在'https://api.twitter.com/1.1/direct_messages/events/new.json' 4)Oauth2,获取访问令牌(成功) 5)将头部设置为('Content-Type','application/json')。 6)使用使用者密钥,Nonce,签名,签名方法,时间戳,版本,Twitter创建授权标头。建立与developer.twitter.com/en/docs/basics/authentication/guides/ 的“指南”部分相同的内容7)运行错误代码“{”errors“:[{”code“:32,”message “:“无法验证您的身份。”}]}”。

另一个重要的信息,我一直在使用Twitter旧API发送完美的DM,唯一的区别是它发送请求体的URL参数而不是JSOn正文,但授权方法保持不变。由于一些新功能只能通过Twitter New API实现,并且根据文档需要通过JSON格式发送主体。因此请求部分被更改,但授权相同。

示例代码: -

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); 

感谢 Prateek

+0

你能发布您的代码通过编辑这个问题? –

+0

嗨迪玛,谢谢你的回复。 –

+1

你应该考虑添加关于你的问题的信息,比如什么不工作。另外,您应该考虑添加有关该项目的信息,例如您使用的是哪种技术。代码示例也真的很感激在这种情况下 – Nicolas

我写Twitter的库和应用程序在过去,和BST意见,我可以给你是使用现有的实现OAuth而不是尝试写你自己的。在新代码中重新实现OAuth正在重新发明*,这是一个令你厌恶的*。有许多强大且成熟的OAuth库是免费和/或开源的。

+0

感谢DWRoelands的信息,我们尝试过,但无法找到任何支持DM的新Twitter API的库。请让我们知道你是否有任何特别的想法。任何帮助是极大的赞赏。 –

只是发生了绊倒你的查询。我发布了一个代码(c#)(虽然有点晚),这对我来说使用新API将DM发送到twitter是很有用的。希望这可以帮助。由于Danny Tuppeny's blog

namespace TweetApp.Droid 
{ 
class TweetDM 
{ 
    const string TwitterApiBaseUrl = "https://api.twitter.com/1.1/"; 
    readonly string consumerKey, consumerKeySecret, accessToken, accessTokenSecret; 
    readonly HMACSHA1 sigHasher; 
    readonly DateTime epochUtc = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc); 

    public TweetDM(string consumerKey, string consumerKeySecret, string accessToken, string accessTokenSecret) 
    { 
     this.consumerKey = consumerKey; 
     this.consumerKeySecret = consumerKeySecret; 
     this.accessToken = accessToken; 
     this.accessTokenSecret = accessTokenSecret; 

     sigHasher = new HMACSHA1(new ASCIIEncoding().GetBytes(string.Format("{0}&{1}", consumerKeySecret, accessTokenSecret))); 
    } 

    public Task<string> Tweet(string text, string recipientID) 
    { 
     JSONObject jasonobject = new JSONObject 
     { 
      @event = new TwitterEvent 
      { 
       type = "message_create", 
       message_create = new msg_create 
       { 
        target = new tgt 
        { 
         recipient_id = recipientID 
        }, 
        message_data = new msg_data 
        { 
         text = text 
        } 
       }, 
      } 
     }; 

     var JsonString =JsonConvert.SerializeObject(jasonobject); 


     var data4Auth = new Dictionary<string, string> { 
     }; 
     return PrepareAuth("direct_messages/events/new.json", data4Auth, JsonString); 
     } 

    Task<string> PrepareAuth(string url, Dictionary<string, string> data4Auth, string JsonString) 
    { 
     var fullUrl = TwitterApiBaseUrl + url; 

     var timestamp = (int)((DateTime.UtcNow - epochUtc).TotalSeconds); 

     data4Auth.Add("oauth_consumer_key", consumerKey); 
     data4Auth.Add("oauth_signature_method", "HMAC-SHA1"); 
     data4Auth.Add("oauth_timestamp", timestamp.ToString()); 
     data4Auth.Add("oauth_nonce", "a"); // Required, but Twitter doesn't appear to use it, so "a" will do. 
     data4Auth.Add("oauth_token", accessToken); 
     data4Auth.Add("oauth_version", "1.0"); 

     // Generate the OAuth signature and add it to our payload. 
     data4Auth.Add("oauth_signature", GenerateSignature(fullUrl, data4Auth)); 

     // Build the OAuth HTTP Header from the data. 
     string oAuthHeader = GenerateOAuthHeader(data4Auth); 

     // Setting Content details 
     var JsonData = new StringContent(JsonString, Encoding.UTF8, "application/json"); 
     return SendRequest(fullUrl, oAuthHeader, JsonData); 
    } 

    string GenerateSignature(string url, Dictionary<string, string> data) 
    { 
     var sigString = string.Join(
      "&", 
      data 
       .Union(data) 
       .Select(kvp => string.Format("{0}={1}", Uri.EscapeDataString(kvp.Key), Uri.EscapeDataString(kvp.Value))) 
       .OrderBy(s => s) 
     ); 

     var fullSigData = string.Format(
      "{0}&{1}&{2}", 
      "POST", 
      Uri.EscapeDataString(url), 
      Uri.EscapeDataString(sigString.ToString()) 
     ); 

     return Convert.ToBase64String(sigHasher.ComputeHash(new ASCIIEncoding().GetBytes(fullSigData.ToString()))); 
    } 

    string GenerateOAuthHeader(Dictionary<string, string> data) 
    { 
     return "OAuth " + string.Join(
      ", ", 
      data 
       .Where(kvp => kvp.Key.StartsWith("oauth_")) 
       .Select(kvp => string.Format("{0}=\"{1}\"", Uri.EscapeDataString(kvp.Key), Uri.EscapeDataString(kvp.Value))) 
       .OrderBy(s => s) 
     ); 
    } 

    async Task<string> SendRequest(string fullUrl, string oAuthHeader, StringContent jsondata) 
    { 
     using (var http = new HttpClient()) 
     { 
      http.DefaultRequestHeaders.Add("Authorization", oAuthHeader); 
      var httpResp = await http.PostAsync(fullUrl, jsondata); 
      var respBody = await httpResp.Content.ReadAsStringAsync(); 
      return respBody; 
     } 
    } 
} 
// Classes for creating JSON body 
public class JSONObject 
{ 
    public TwitterEvent @event; 
} 
    public class TwitterEvent 
{ 
    public string type; 
    public msg_create message_create; 
    } 
public class msg_create 
{ 
    public tgt target; 
    public msg_data message_data; 
} 
public class tgt 
{ 
    public string recipient_id; 
} 
public class msg_data 
{ 
    public string text; 
} 
} 

要拨打:

var twitter = new TweetDM(consumerKey, consumerKeySecret, accessToken, accessTokenSecret); 
await twitter.Tweet(textBox1.Text, textBox2.Text);