我已经在Zapier的示例代码库上构建了Zapier应用。一切进展顺利,希望获得刷新令牌。我在Postman中进行了刷新,并且正在使用完全相同的代码。首先使用access_token非常有效,而且在连接后的前10分钟进行帐户连接测试也很有效。之后,令牌到期,我希望zapier自动刷新它。
为什么当access_token和refresh_token API的uri和方法相同时,服务器会继续给我提供401代码,只是主体不同,但是基于邮递员的调用,这应该可以正常工作。
const to_json = require('xmljson').to_json;
const getAccessToken = (z, bundle) => {
const promise = z.request(`${process.env.BASE_URL}/oauth2/token`, {
method: 'POST',
body: {
//extra data pulled from the users query string
//accountDomain: bundle.cleanedRequest.querystring.accountDomain,
code: decodeURI(bundle.inputData.code),
client_id: process.env.CLIENT_ID,
client_secret: process.env.CLIENT_SECRET,
redirect_uri: '{{bundle.inputData.redirect_uri}}',
grant_type: 'authorization_code'
},
headers: {
'content-type': 'application/x-www-form-urlencoded'
}
});
// Needs to return at minimum, `access_token`, and if your app also does refresh, then `refresh_token` too
return promise.then((response) => {
if (response.status !== 200) {
throw new Error('Unable to fetch access token: ' + response.content);
}
const result = JSON.parse(response.content);
return {
access_token: result.access_token,
refresh_token: result.refresh_token
};
});
};
const refreshAccessToken = (z, bundle) => {
const promise = z.request(`${process.env.BASE_URL}/oauth2/token`, {
method: 'POST',
body: {
//extra data pulled from the users query string
//accountDomain: bundle.cleanedRequest.querystring.accountDomain,
refresh_token: bundle.authData.refresh_token,
client_id: process.env.CLIENT_ID,
client_secret: process.env.CLIENT_SECRET,
redirect_uri: '{{bundle.inputData.redirect_uri}}',
grant_type: 'refresh_token'
},
headers: {
'content-type': 'application/x-www-form-urlencoded'
}
});
// Needs to return at minimum, `access_token`, and if your app also does refresh, then `refresh_token` too
return promise.then((response) => {
if (response.status !== 200) {
throw new Error('Unable to refresh access token: ' + response.content);
}
const result = JSON.parse(response.content);
return {
access_token: result.access_token,
refresh_token: result.refresh_token
};
});
};
const testAuth = (z , bundle) => {
// Normally you want to make a request to an endpoint that is either specifically designed to test auth, or one that
// every user will have access to, such as an account or profile endpoint like /me.
const promise = z.request({
method: 'GET',
url: `${process.env.BASE_URL}/v1/888330/crm/Accounts`,
});
// This method can return any truthy value to indicate the credentials are valid.
// Raise an error to show
return promise.then((response) => {
if (response.status === 401) {
throw new Error('The access token you supplied is not valid');
}
to_json(response, function (error, data) {
const response = data;
});
return response.content;
});
};
module.exports = {
type: 'oauth2',
oauth2Config: {
// Step 1 of the OAuth flow; specify where to send the user to authenticate with your API.
// Zapier generates the state and redirect_uri, you are responsible for providing the rest.
// Note: can also be a function that returns a string
authorizeUrl: {
url: `${process.env.BASE_URL}/oauth2/auth`,
params: {
client_id: '{{process.env.CLIENT_ID}}',
state: '{{bundle.inputData.state}}',
redirect_uri: '{{bundle.inputData.redirect_uri}}',
response_type: 'code'
}
},
// Step 2 of the OAuth flow; Exchange a code for an access token.
// This could also use the request shorthand.
getAccessToken: getAccessToken,
// (Optional) If the access token expires after a pre-defined amount of time, you can implement
// this method to tell Zapier how to refresh it.
refreshAccessToken: refreshAccessToken,
// If you want Zapier to automatically invoke `refreshAccessToken` on a 401 response, set to true
autoRefresh: true
// If there is a specific scope you want to limit your Zapier app to, you can define it here.
// Will get passed along to the authorizeUrl
// scope: 'read,write'
},
// The test method allows Zapier to verify that the access token is valid. We'll execute this
// method after the OAuth flow is complete to ensure everything is setup properly.
test: testAuth,
// assuming "username" is a key returned from the test
connectionLabel: ''
};
Zapier引发的错误:
What happened (You are seeing this because you are an admin):
Starting POST request to https://start.exactonline.nl/api/oauth2/token/
Received 401 code from https://start.exactonline.nl/api/oauth2/token/ after 132ms
Received content "<html><head><title>Object moved</title><script type="text/javascript" src="/ruxitagentjs_ICA27SVafgh"
Got 401 calling POST https://start.exactonline.nl/api/oauth2/token/, triggering auth refresh.
Console logs:
Stack trace:
throwForStaleAuth (/var/task/node_modules/zapier-platform-core/src/http-middlewares/after/throw-for-stale-auth.js:10:11)
Object.collector.then.newOutput (/var/task/node_modules/zapier-platform-core/src/middleware.js:80:37)
bound (domain.js:301:14)
Object.runBound (domain.js:314:12)
Object.tryCatcher (/var/task/node_modules/bluebird/js/release/util.js:16:23)
Promise._settlePromiseFromHandler (/var/task/node_modules/bluebird/js/release/promise.js:512:31)
Promise._settlePromise (/var/task/node_modules/bluebird/js/release/promise.js:569:18)
Promise._settlePromise0 (/var/task/node_modules/bluebird/js/release/promise.js:614:10)
Promise._settlePromises (/var/task/node_modules/bluebird/js/release/promise.js:693:18)
Async._drainQueue (/var/task/node_modules/bluebird/js/release/async.js:133:16)
Async._drainQueues (/var/task/node_modules/bluebird/js/release/async.js:143:10)
Immediate.Async.drainQueues (/var/task/node_modules/bluebird/js/release/async.js:17:14)
runCallback (timers.js:794:20)
tryOnImmediate (timers.js:752:5)
processImmediate [as _immediateCallback] (timers.js:729:5)