使用DotNetOpenAuth访问Yelp的OAuth 1.0a API

时间:2011-05-17 20:47:08

标签: c# asp.net oauth dotnetopenauth

有没有人使用DotNetOpenAuth成功使用DotNetOpenAuth访问Yelp's v2 api

在深入了解示例和来源之后,我就想到了这一点:

public class YelpConnector
{               
    private static readonly string YelpConsumerKey = ConfigurationManager.AppSettings["YelpConsumerKey"];
    private static readonly string YelpConsumerSecret = ConfigurationManager.AppSettings["YelpConsumerSecret"];
    private static readonly string YelpToken = ConfigurationManager.AppSettings["YelpToken"];
    private static readonly string YelpTokenSecret = ConfigurationManager.AppSettings["YelpTokenSecret"];
    private static readonly InMemoryTokenManager tokenManager = new InMemoryTokenManager(YelpConsumerKey, YelpConsumerSecret, YelpToken, YelpTokenSecret);
    private static readonly Uri YelpURLBase = new Uri("http://api.yelp.com/v2/");        
    private static readonly ServiceProviderDescription YelpServiceDescription = new ServiceProviderDescription {
        RequestTokenEndpoint = null,
        UserAuthorizationEndpoint = null,
        AccessTokenEndpoint = null,
        TamperProtectionElements = new ITamperProtectionChannelBindingElement[] { new HmacSha1SigningBindingElement() },
    };

    private static dynamic SearchBase(string queryString)
    {
        if (string.IsNullOrEmpty(queryString))
            throw new ArgumentNullException();
        var searchEndpoint = new MessageReceivingEndpoint(new Uri(YelpURLBase, "search?" + queryString), HttpDeliveryMethods.GetRequest | HttpDeliveryMethods.AuthorizationHeaderRequest);
        var consumer = new WebConsumer(YelpServiceDescription, tokenManager);
        try
        {
            using (IncomingWebResponse response = consumer.PrepareAuthorizedRequestAndSend(searchEndpoint, YelpToken))
            {
                string rs = response.GetResponseReader().ReadToEnd();
                dynamic js = SimpleJson.SimpleJson.DeserializeObject(rs);
                return js;
            }
        }
        catch (Exception e)
        {
            ErrorSignal.FromCurrentContext().Raise(e);
            return null;
        }            
    }
    internal class InMemoryTokenManager : IConsumerTokenManager
    {
        private Dictionary<string, string> tokensAndSecrets = new Dictionary<string, string>();

        public InMemoryTokenManager(string consumerKey, string consumerSecret, string token, string secret)
        {
            if (String.IsNullOrEmpty(consumerKey))
            {
                throw new ArgumentNullException("consumerKey");
            }
            this.tokensAndSecrets[token] = secret;
            this.ConsumerKey = consumerKey;
            this.ConsumerSecret = consumerSecret;
        }

        public string ConsumerKey { get; private set; }

        public string ConsumerSecret { get; private set; }

        public string GetTokenSecret(string token)
        {
            return this.tokensAndSecrets[token];
        }

        public void StoreNewRequestToken(UnauthorizedTokenRequest request, ITokenSecretContainingMessage response)
        {
            this.tokensAndSecrets[response.Token] = response.TokenSecret;
        }

        public void ExpireRequestTokenAndStoreNewAccessToken(string consumerKey, string requestToken, string accessToken, string accessTokenSecret)
        {
            this.tokensAndSecrets.Remove(requestToken);
            this.tokensAndSecrets[accessToken] = accessTokenSecret;
        }

        public TokenType GetTokenType(string token)
        {
            throw new NotImplementedException();
        }           
    }
 }

如果我传入以下QueryString limit=5&category_filter=movietheaters,bars,cafe,museums,danceclubs,parks&ll=37.78364455,-122.464104,我会得到一个异常,说“Precondition failed:value!= null”和一个堆栈跟踪:

at System.Diagnostics.Contracts.__ContractsRuntime.Requires[TException](Boolean condition, String message, String conditionText)
at DotNetOpenAuth.Messaging.MessagingUtilities.EscapeUriDataStringRfc3986(String value)
at DotNetOpenAuth.OAuth.ChannelElements.SigningBindingElementBase.ConstructSignatureBaseString(ITamperResistantOAuthMessage message, MessageDictionary messageDictionary)
at DotNetOpenAuth.OAuth.ChannelElements.HmacSha1SigningBindingElement.GetSignature(ITamperResistantOAuthMessage message)
at DotNetOpenAuth.OAuth.ChannelElements.SigningBindingElementBase.ProcessOutgoingMessage(IProtocolMessage message)
at DotNetOpenAuth.OAuth.ChannelElements.SigningBindingElementChain.ProcessOutgoingMessage(IProtocolMessage message)
at DotNetOpenAuth.Messaging.Channel.ProcessOutgoingMessage(IProtocolMessage message)
at DotNetOpenAuth.OAuth.ChannelElements.OAuthChannel.InitializeRequest(IDirectedProtocolMessage request)
at DotNetOpenAuth.OAuth.ConsumerBase.PrepareAuthorizedRequestAndSend(MessageReceivingEndpoint endpoint, String accessToken)
at MeetPpl.Helpers.SocialConnectors.YelpConnector.SearchBase(String queryString)

有什么建议吗?我在正确的路上吗?

2 个答案:

答案 0 :(得分:5)

在放弃dotnetopenauth之前,我在这个问题上挣扎了整整一天。我找到了一种使用http://www.twitterizer.net/的oauth库搜索yelp的简单方法。只需下载精简版twitterizer并使用我的示例代码。

下载链接为http://www.twitterizer.net/files/Twitterizer2lite-2.3.2.zip

    public static string search()
    {
        string yelpSearchURL = "http://api.yelp.com/v2/search?term=food&location=San+Francisco";
        string yelpConsumerKey = "your key";
        string yelpConsumerSecret = "your secret";
        string yelpRequestToken = "your token";
        string yelpRequestTokenSecret = "your token secret";

        Twitterizer.OAuthTokens ot = new Twitterizer.OAuthTokens();
        ot.AccessToken = yelpRequestToken;
        ot.AccessTokenSecret = yelpRequestTokenSecret;
        ot.ConsumerKey = yelpConsumerKey;
        ot.ConsumerSecret = yelpConsumerSecret;

        string formattedUri = String.Format(CultureInfo.InvariantCulture,
                             yelpSearchURL, "");
        Uri url = new Uri(formattedUri);
        Twitterizer.WebRequestBuilder wb = new Twitterizer.WebRequestBuilder(url, Twitterizer.HTTPVerb.GET, ot);
        System.Net.HttpWebResponse wr = wb.ExecuteRequest();
        StreamReader sr = new StreamReader(wr.GetResponseStream());
        return sr.ReadToEnd();
    }

答案 1 :(得分:2)

您可以将RestSharp api:https://github.com/JustinBeckwith/YelpSharp与OAuthBase结合使用:http://oauth.googlecode.com/svn/code/csharp/OAuthBase.cs。 在YelpSharp实现中,使用以下方法更改 Yelp.cs 类方法 makeRequest

protected string makeRequest(string area, string id, Dictionary<string, string> parameters)
        {
            // build the url with parameters
            var url = area;

            if (!String.IsNullOrEmpty(id)) url += "/" + HttpUtility.UrlEncode(id);

            if (parameters != null)
            {
                bool firstp = true;
                string[] keys = parameters.Keys.ToArray();
                foreach (string _key in keys)
                {
                    if (firstp) url += "?";
                    else url += "&";

                    firstp = false;
                    //Double URL encode "&" to prevent restsharp from treating the second half of the string as a new parameter
                    parameters[_key] = parameters[_key].Replace("&", "%26");
                    parameters[_key] = parameters[_key].Replace("+", "%2B");
                    parameters[_key] = parameters[_key].Replace(" ", "%2B");

                    url += _key + "=" + parameters[_key]; //HttpUtility.UrlEncode(parameters[_key]);
                }
            }

            var client = new RestClient(rootUri);

            var request = new RestRequest(Method.GET);

            OAuthBase oAuth = new OAuthBase();
            string nonce = oAuth.GenerateNonce();
            string timeStamp = oAuth.GenerateTimeStamp();
            string normalizedUrl;
            string normalizedRequestParameters;

            string sig = oAuth.GenerateSignature(new Uri(string.Format("{0}/{1}", client.BaseUrl, url)),
                options.ConsumerKey, options.ConsumerSecret,
                options.AccessToken, options.AccessTokenSecret,
                "GET", timeStamp, nonce, out normalizedUrl, out normalizedRequestParameters);

            sig = HttpUtility.UrlEncode(sig);

            request.Resource = string.Format(area);

            if (parameters != null)
            {
                foreach (var p in parameters)
                {
                    request.AddParameter(p.Key, p.Value);
                }
            }

            request.AddParameter("oauth_consumer_key", options.ConsumerKey);
            request.AddParameter("oauth_token", options.AccessToken);
            request.AddParameter("oauth_nonce", nonce);
            request.AddParameter("oauth_timestamp", timeStamp);
            request.AddParameter("oauth_signature_method", "HMAC-SHA1");
            request.AddParameter("oauth_version", "1.0");
            request.AddParameter("oauth_signature", sig);

            var response = client.Execute(request);

            return response.Content;
        }

像这样测试:

public void testYelp()
{
    string _term = "food";
            string _location = "San Francisco";


            var o = Credentials.GetOptions();
            var y = new Yelp(o);

            var searchOptions = new SearchOptions();
            searchOptions.GeneralOptions = new GeneralOptions()
            {
                term = _term
            };

            searchOptions.LocationOptions = new LocationOptions()
            {
                location = _location
            };


            var results = y.Search(searchOptions);
}