使用api 1.1的Twitter POST问题

我们刚刚更改为Twitter api 1.1,现在Tweeting不起作用并返回错误“远程服务器返回错误:(400)错误请求。” 关于SO的研究表明它与身份validation有关,但我们正在发送我们刚刚从登录页面获得的accessToken和secret。 这一切都适用于api 1.0。 代码是 –

public void Tweet(Action response, string message) { StringBuilder sb = new StringBuilder(); sb.Append("POST&"); sb.Append(Uri.EscapeDataString(_postUrl)); sb.Append("&"); string oauthNonce = Convert.ToBase64String(new ASCIIEncoding().GetBytes(DateTime.Now.Ticks.ToString())); string timeStamp = MakeTimestamp(); var dict = new SortedDictionary { { "oauth_consumer_key", _oAuthConfig.ConsumerKey }, { "oauth_nonce", oauthNonce }, { "oauth_signature_method", "HMAC-SHA1" }, { "oauth_timestamp", timeStamp }, { "oauth_token", _accessToken }, { "oauth_version", "1.0" }, }; foreach (var keyValuePair in dict) { sb.Append(Uri.EscapeDataString(string.Format("{0}={1}&", keyValuePair.Key, keyValuePair.Value))); } string encodedMessage = EscapeAdditionalChars(Uri.EscapeDataString(message)); sb.Append(Uri.EscapeDataString("status=" + encodedMessage)); string signatureBaseString = sb.ToString(); // create the signature string signatureKey = Uri.EscapeDataString(_oAuthConfig.ConsumerSecret) + "&" + Uri.EscapeDataString(_accessTokenSecret); var hmacsha1 = new HMACSHA1(new ASCIIEncoding().GetBytes(signatureKey)); string signatureString = Convert.ToBase64String(hmacsha1.ComputeHash(new ASCIIEncoding().GetBytes(signatureBaseString))); // create the headers string authorizationHeaderParams = String.Empty; authorizationHeaderParams += "OAuth "; authorizationHeaderParams += "oauth_consumer_key=\"" + _oAuthConfig.ConsumerKey + "\", "; authorizationHeaderParams += "oauth_nonce=\"" + oauthNonce + "\", "; authorizationHeaderParams += "oauth_signature=\"" + Uri.EscapeDataString(signatureString) + "\", "; authorizationHeaderParams += "oauth_signature_method=\"" + "HMAC-SHA1" + "\", "; authorizationHeaderParams += "oauth_timestamp=\"" + timeStamp + "\", "; authorizationHeaderParams += "oauth_token=\"" + _accessToken + "\", "; authorizationHeaderParams += "oauth_version=\"" + "1.0" + "\""; string messageToPost = EscapeAdditionalChars(SpacesToPlusSigns(message)); // initialise the WebClient WebClient client = new WebClient(); client.Headers [HttpRequestHeader.Authorization] = authorizationHeaderParams; client.UploadDataCompleted += (s, eArgs) => { if (eArgs.Error == null) response(DefaultSuccessMessage()); else response(eArgs.Error.Message); }; try { Uri uri = new Uri(_postUrl); try { client.UploadDataAsync(uri, "POST", Encoding.UTF8.GetBytes("status=" + messageToPost)); } catch (WebException e) { Log.Info("TwitterService->Tweet web error: " + e.Message); response(DefaultErrorMessage()); } catch (Exception e) { // Can happen if we had already favorited this status Log.Info("TwitterService->Tweet error: " + e.Message); response(DefaultErrorMessage()); } } catch (WebException e) { Log.Info("TwitterService->Tweet web error 2: " + e.Message); response(DefaultErrorMessage()); } catch (Exception e) { Log.Info("TwitterService->Tweet error 2: " + e.Message); response(DefaultErrorMessage()); } } 

基本上,我希望能够在不使用任何第三方库(例如Twitterizer)的情况下发推文(即使TweetStation似乎被api 1.1打破) – 当然它不会那么难!

任何帮助都非常感激,因为它现在感觉有点像砖墙 – 我也是c#的新手,这没有帮助……

编辑显示以前不清楚的代码。

终于找到了解决方案,和大多数这些东西一样,它非常简单。 代码如下 –

  public void Tweet(Action response, string message) { StringBuilder sb = new StringBuilder(); sb.AppendFormat ("status={0}", PercentEncode(message)); string content = sb.ToString(); HttpWebRequest request = (HttpWebRequest)WebRequest.Create(_postUrl); request.Headers.Add("Authorization", AuthorizeRequest(_accessToken, _accessTokenSecret, "POST", new Uri(_postUrl), content)); request.ContentType = "application/x-www-form-urlencoded"; request.ServicePoint.Expect100Continue = false; request.Method = "POST"; try { try { using (Stream stream = request.GetRequestStream()) { Byte[] streamContent = Encoding.UTF8.GetBytes("status=" + PercentEncode(message)); stream.Write(streamContent, 0, streamContent.Length); } HttpWebResponse webResponse = (HttpWebResponse)request.GetResponse(); string contents = ""; using (Stream stream = webResponse.GetResponseStream()) using (StreamReader reader = new StreamReader(stream)) { contents = reader.ReadToEnd(); } Console.WriteLine("Twitter response: " + contents); response(DefaultSuccessMessage()); } catch (WebException e) { Log.Info("TwitterService->Tweet web error: " + e.Message); response(DefaultErrorMessage()); } catch (Exception e) { // Can happen if we had already favorited this status Log.Info("TwitterService->Tweet error: " + e.Message); response(DefaultErrorMessage()); } } catch (WebException e) { Log.Info("TwitterService->Tweet web error 2: " + e.Message); response(DefaultErrorMessage()); } catch (Exception e) { Log.Info("TwitterService->Tweet error 2: " + e.Message); response(DefaultErrorMessage()); } } private string AuthorizeRequest(string oauthToken, string oauthTokenSecret, string method, Uri uri, string data) { string oauthNonce = Convert.ToBase64String(new ASCIIEncoding().GetBytes(DateTime.Now.Ticks.ToString())); var headers = new Dictionary() { { "oauth_consumer_key", _oAuthConfig.ConsumerKey }, { "oauth_nonce", oauthNonce }, { "oauth_signature_method", "HMAC-SHA1" }, { "oauth_timestamp", MakeTimestamp() }, { "oauth_token", oauthToken }, { "oauth_verifier", PercentEncode(_authorizationVerifier) }, { "oauth_version", "1.0A" } }; var signatureHeaders = new Dictionary(headers); // Add the data and URL query string to the copy of the headers for computing the signature if (data != null && data != "") { var parsed = HttpUtility.ParseQueryString(data); foreach (string k in parsed.Keys) { signatureHeaders.Add(k, PercentEncode(parsed [k])); } } var nvc = HttpUtility.ParseQueryString(uri.Query); foreach (string key in nvc) { if (key != null) signatureHeaders.Add(key, PercentEncode(nvc [key])); } string signature = MakeSignature (method, uri.GetLeftPart(UriPartial.Path), signatureHeaders); string compositeSigningKey = MakeSigningKey(_oAuthConfig.ConsumerSecret, oauthTokenSecret); string oauth_signature = MakeOAuthSignature(compositeSigningKey, signature); headers.Add ("oauth_signature", PercentEncode(oauth_signature)); return HeadersToOAuth(headers); } private static string PercentEncode (string s) { var sb = new StringBuilder (); foreach (byte c in Encoding.UTF8.GetBytes (s)) { if ((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || (c >= '0' && c <= '9') || c == '-' || c == '_' || c == '.' || c == '~') sb.Append ((char) c); else { sb.AppendFormat ("%{0:X2}", c); } } return sb.ToString (); } private static string MakeTimestamp () { return ((long) (DateTime.UtcNow - _unixBaseTime).TotalSeconds).ToString (); } private static string MakeSignature (string method, string base_uri, Dictionary headers) { var items = from k in headers.Keys orderby k select k + "%3D" + PercentEncode (headers [k]); return method + "&" + PercentEncode (base_uri) + "&" + string.Join ("%26", items.ToArray ()); } private static string MakeSigningKey (string consumerSecret, string oauthTokenSecret) { return PercentEncode (consumerSecret) + "&" + (oauthTokenSecret != null ? PercentEncode (oauthTokenSecret) : ""); } private static string MakeOAuthSignature (string compositeSigningKey, string signatureBase) { var sha1 = new HMACSHA1 (Encoding.UTF8.GetBytes (compositeSigningKey)); return Convert.ToBase64String (sha1.ComputeHash (Encoding.UTF8.GetBytes (signatureBase))); } private static string HeadersToOAuth (Dictionary headers) { return "OAuth " + String.Join (",", (from x in headers.Keys select String.Format ("{0}=\"{1}\"", x, headers [x])).ToArray ()); } 

使用Twitter api 1.0,我使用WebClient发布,这不适用于api 1.1,似乎这样做的原因是你不能设置ContentType或ServicePoint.Expect100Continue属性 – 没有这些设置为我已经设置了它们,请求被发送回(401)未授权。 最后与编码问题无关。

感谢其他人的各种助手方法。

我有完全相同的问题:

这正是您需要在此处执行的操作:

使用Twitter API 1.1 oAuthvalidation并请求用户的时间表

我已经为此创建了一个项目: https : //github.com/andyhutch77/oAuthTwitterTimeline

它还包括MVC,Web应用程序和控制台演示。

我遇到了这个问题,或者至少有一个类似的(从我的noob角度来看),最近我正在构建一个应用程序。 似乎为我解决的问题(在查看dev.twitter.com上的工具之后)只是为了摆脱参数名称周围的引号 ,以便(在您的情况下):

我注意到你的参数名称实际上没有引号。 但是,让我感到困惑的是你两次发送身份validation详细信息(因此我的错误post。)它对我有用而没有这样做,我用Google搜索了一下,发现: https : //dev.twitter.com/discussions/12322#comment- 27120 ,其确认这可能是产生认证错误的问题。

400表示您未经过身份validation。 我建议获取用户上下文。

https://dev.twitter.com/docs/auth/oauth#user-context