我通过OAuth连接到第三方API,Intuit Quickbooks,以获取用户的凭据。我已根据需要实现了回调,并且可以成功获取凭据。在回调中,我调用了一个meteor方法函数来使用作为参数传入的凭据更新当前登录用户的配置文件。但是,Meteor无法找到用户。
我尝试过使用Meteor.Async和BindEnvironment,但我遇到了同样的问题。当API返回回调时,是否可以知道哪个用户向第三方API发起了请求?
var stuff;
Router.route('/requestToken', { name: 'requestoken', where: 'server' })
.get(function (req,res) {
var QuickBooks = require('node-quickbooks');
var request = require('request');
var qs = require('querystring');
var consumerKey = 'xxxxx',
consumerSecret = 'xxxxx'
var postBody = {
url: QuickBooks.REQUEST_TOKEN_URL,
oauth: {
callback: 'http://localhost:3000/callback/',
consumer_key: consumerKey,
consumer_secret: consumerSecret
}
}
console.log('abt to request')
request.post(postBody, function (e, r, data) {
var requestToken = qs.parse(data)
stuff = requestToken.oauth_token_secret;
console.log(requestToken)
res.writeHead(301, {
'Location': QuickBooks.APP_CENTER_URL + requestToken.oauth_token
});
res.end();
})
})
.post(function () {
// POST
})
.put(function () {
// PUT
})
Router.route('/callback', { name:'callback' , where: 'server' })
.get(function () {
var req = this.request;
var res = this.response;
var QuickBooks = require('node-quickbooks');
var request = require('request');
var qs = require('querystring');
var consumerKey = 'xxxxx',
consumerSecret = 'xxxxx'
var postBody = {
url: QuickBooks.ACCESS_TOKEN_URL,
oauth: {
consumer_key: consumerKey,
consumer_secret: consumerSecret,
token: req.query.oauth_token,
token_secret: stuff,
verifier: req.query.oauth_verifier,
realmId: req.query.realmId
}
}
request.post(postBody, Meteor.bindEnvironment(function (e, r, data) {
var accessToken = qs.parse(data)
qbo = new QuickBooks(consumerKey,
consumerSecret,
accessToken.oauth_token,
accessToken.oauth_token_secret,
postBody.oauth.realmId,
true, // use the Sandbox
true); // turn debugging on
// test out account access
qbo.findAccounts(function(_, accounts) {
accounts.QueryResponse.Account.forEach(function(account) {
console.log(account.Name)
})
});
// save the access token somewhere on behalf of the logged in user
var userCred = {
token:accessToken.oauth_token,
secret:accessToken.oauth_token_secret,
real:postBody.oauth.realmId
}
console.log("about to call addQB details");
console.log(userCred);
//this method simply adds the userCred to the current logged in user's profile.
//Whenever the method below is called from here, it never finds the user. However when called from the client it works well.
//Is it possibe to know logged user from a 3rd party API callback? / How can I go about this?
Meteor.call("addUserQb",userCred);
}));
res.end('<!DOCTYPE html><html lang="en"><head></head><body><script>window.opener.location.reload(); window.close();</script></body></html>')
})
.post(function () {
// POST
})
.put(function () {
// PUT
})
方法如下。 (当从客户端使用假凭证obj作为参数调用时,该方法很有效。但是在上面的路由器中从回调调用时不会获得用户)
addUserQb:function(obj){
Meteor.users.update(Meteor.userId(), {
$set:{
'profile.token': obj.token,
'profile.secret': obj.secret,
'profile.realmId' : obj.real
}
} );
}
答案 0 :(得分:1)
考虑一下这里发生了什么:服务器本身没有userId。从客户端调用的方法是通过DDP协议调用的,DDP协议是由客户端创建并与userId关联的持久连接,因此这些方法确实在其上下文中获得了userId。
来自路由器设置的路径的http请求与任何DDP会话都没有关联,也不能有userId。 bindEnvironment()在这里没有帮助,它只适用于与最初通过DDP调用的方法相关联的nodejs光纤中运行的回调函数。
您有来自其他服务器的回调 http请求。这是通过不同的路由进行的,与将原始请求发送给Oauth提供程序的服务器方法没有任何关联。
解决方案:您需要将userId信息添加到Quickbooks的请求中,可能在回调URL中,这样当Quickbooks Oauth服务器进行回调时,您可以从请求中提取userId。