0

我們正試圖從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

回答

0

我寫Twitter的庫和應用程序在過去,和BST意見,我可以給你是使用現有的實現OAuth而不是嘗試寫你自己的。在新代碼中重新實現OAuth正在重新發明輪子,這是一個令你厭惡的輪子。有許多強大且成熟的OAuth庫是免費和/或開源的。

+0

感謝DWRoelands的信息,我們嘗試過,但無法找到任何支持DM的新Twitter API的庫。請讓我們知道你是否有任何特別的想法。任何幫助是極大的讚賞。 –

0

只是發生了絆倒你的查詢。我發佈了一個代碼(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);