所以这个问题已经被问了好几次了,但我相信我终于把问题归结为问题所在。我在Angular中使用Yelp API,它需要OAuth 1.0a才能访问。像大多数做这种实现的人一样,我使用以下代码:
.factory('YelpApi', ['$http',
function ($http) {
var randomString = function (length, chars) {
var result = '';
for (var i = length; i > 0; --i) {
result += chars[Math.round(Math.random() * (chars.length - 1))];
}
return result;
};
var retrieveYelp = function (name, callback) {
var method = 'GET';
var url = 'http://api.yelp.com/v2/search';
var params = {
callback: 'angular.callbacks._0',
ll: /* hidden */,
radius_filter: '3219',
oauth_consumer_key: /* hidden */, // consumer key
oauth_token: /* hidden */, //Token
oauth_signature_method: 'HMAC-SHA1',
oauth_timestamp: new Date().getTime(),
oauth_nonce: randomString(32, '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ'),
term: name || 'food',
actionlinks: true
}; // end params
var consumerSecret = /* hidden */; //Consumer Secret
var tokenSecret = /* hidden */; //Token Secret
var signature =
oauthSignature.generate(
method,
url,
params,
consumerSecret,
tokenSecret,
{ encodeSignature: false }
);
// end signature
params['oauth_signature'] = signature;
console.log('inside yelpapi factory');
console.log('Term searched for: ' + params.term);
$http.jsonp(url, { params : params })
.then(callback, function(err) {
console.log('An error occured: ', err);
});
console.log("inside end of yelpapi factory");
}; // end retrieveYelp
return {
retrieveYelp: retrieveYelp
};
} // end function
]) // end factory
问题是:
使用'angular.callbacks._0'
作为回调使其第一次工作,因为它强制它使用第一个回调,但会中断后续请求。实际上,您应该使用JSON_CALLBACK
来适当地增加回调,但这会破坏一切。Yelp生成的错误是"无效签名"。我认为这是由于Angular直到之后的才替换JSON_CALLBACK
,从而导致预期签名与实际签名不同。我正在使用这个签名生成器。
如何绕过这一点,确保Angular在确保正确生成签名的同时正确增加回调
我找到了一种丑陋的方法来解决这个问题。在下面的文章中,有一个关于如何创建自己的拦截器来增加jsonp回调参数(angular.callbacks._0,angular.cacallbacks._1等)的描述
如何自定义angularjs-jsonp回调名称?
这种一对一的解决方案在我的情况下不起作用。对于必须创建oauth签名的yelp和查询,param回调应该分别包含在签名中,然后在执行jsonp请求之前应该已经递增。
因此,在我的服务中,在进行签名和jsonp请求之前,我只调用计数器来生成新的增量。
在您的情况下,我建议更改您的代码如下:
var retrieveYelp = function (name, callback) {
// GENERATE increment and use it in the params
var callbackId = angular.callbacks.counter.toString(36);
var method = 'GET';
var url = 'http://api.yelp.com/v2/search';
var params = {
callback: 'angular.callbacks._' + callbackId,
ll: /* hidden */,
radius_filter: '3219',
oauth_consumer_key: /* hidden */, // consumer key
oauth_token: /* hidden */, //Token
oauth_signature_method: 'HMAC-SHA1',
oauth_timestamp: new Date().getTime(),
oauth_nonce: randomString(32, '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ'),
term: name || 'food',
actionlinks: true
};
我同意,我发现这个解决方案并不是超级愚蠢,但至少它有效,而且似乎没有副作用。