编程语言
首页 > 编程语言> > c# – 使用api 1.1的Twitter POST问题

c# – 使用api 1.1的Twitter POST问题

作者:互联网

我们刚刚更改为Twitter api 1.1,现在推特不起作用&返回错误“远程服务器返回错误:(400)错误请求.”关于SO的研究表明它与身份验证有关,但我们发送的是accessToken& amp;我们刚从登录页面获得的秘密.这一切都适用于api 1.0.代码是 –

    public void Tweet(Action<string> 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<string, string>
        {
            { "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<string> 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<string, string>()
        {
            { "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<string,string>(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<string,string> 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<string,string> 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)未授权.最后与编码问题无关.

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

标签:c,twitter,oauth,bad-request
来源: https://codeday.me/bug/20190612/1228749.html