Accessing Yelp's OAuth 1.0a API with DotNetOpenAuth

南笙酒味 提交于 2019-12-14 01:03:46

问题


Has anyone had success using DotNetOpenAuth to access Yelp's v2 api using DotNetOpenAuth?

After digging through the examples and the source, this is what I came up with:

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

If I pass in the following QueryString limit=5&category_filter=movietheaters,bars,cafe,museums,danceclubs,parks&ll=37.78364455,-122.464104, I get an exception saying "Precondition failed.: value != null" and a stacktrace of:

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)

Any suggestions? Am I on the right trail?


回答1:


I struggled with this issue for 1 whole day before giving up on dotnetopenauth. I found a very simple way to search yelp using the oauth library of http://www.twitterizer.net/ . Simply download the lite version of twitterizer and use my sample code below.

Download link is 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();
    }



回答2:


You can use RestSharp api: https://github.com/JustinBeckwith/YelpSharp in combination with OAuthBase: http://oauth.googlecode.com/svn/code/csharp/OAuthBase.cs. In YelpSharp implementation change Yelp.cs class method makeRequest with this:

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

Test like this:

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


来源:https://stackoverflow.com/questions/6036934/accessing-yelps-oauth-1-0a-api-with-dotnetopenauth

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!