问题
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