AWS Lambda 上的 Quickbooks API 应用程序:OAuth 仅连接一次
Quickbooks API App on AWS Lambda: OAuth only connects once
我正在使用连接到 QBO 的 AWS Lambda API。
我的目标是每天通过 lambda cron 触发器实现此 运行。
Here is a gist of the oauth service I wrote >>
intuit-oauth version: 3.0.2
Node.js version 12
为了启动 OAuth,我从 QBO 游乐场获得了一个新的刷新令牌,并将其存储在 JSON 文件中。之后,我将刷新令牌写入更新的 JSON 文件。我看到这个工作正常,我从这个项目中休息了大约一个星期,当我回到它时,我的 JSON 文件中的当前刷新令牌让我可以正常访问它。但这当然只是在本地。
当我 运行 在本地测试时,它每次都能完美运行,在我将其部署到 AWS 后,如果我不等待超过几分钟进行测试,它可能会运行一次或两次。如果我等待大约 15 分钟,我会收到以下错误:
PopsicleError: Unable to connect to "https://oauth.platform.intuit.com/oauth2/v1/tokens/bearer"
at Request.error (/var/task/node_modules/intuit-oauth/node_modules/popsicle/dist/request.js:41:16)
at ClientRequest.<anonymous> (/var/task/node_modules/intuit-oauth/node_modules/popsicle/dist/index.js:131:39)
at ClientRequest.emit (events.js:326:22)
at ClientRequest.EventEmitter.emit (domain.js:483:12)
at TLSSocket.socketErrorListener (_http_client.js:427:9)
at TLSSocket.emit (events.js:314:20)
at TLSSocket.EventEmitter.emit (domain.js:483:12)
at emitErrorNT (internal/streams/destroy.js:92:8)
at emitErrorAndCloseNT (internal/streams/destroy.js:60:3)
at processTicksAndRejections (internal/process/task_queues.js:84:21) {
cause: Error: connect ETIMEDOUT 54.148.164.32:443
at TCPConnectWrap.afterConnect [as oncomplete] (net.js:1144:16) {
errno: 'ETIMEDOUT',
code: 'ETIMEDOUT',
syscall: 'connect',
address: '54.148.164.32',
port: 443
},
code: 'EUNAVAILABLE',
popsicle: Request {
Url: Url {
protocol: 'https:',
slashes: true,
auth: null,
host: 'oauth.platform.intuit.com',
port: null,
hostname: 'oauth.platform.intuit.com',
hash: null,
search: null,
query: [Object: null prototype] {},
pathname: '/oauth2/v1/tokens/bearer',
path: '/oauth2/v1/tokens/bearer',
href: 'https://oauth.platform.intuit.com/oauth2/v1/tokens/bearer'
},
rawHeaders: [
'Authorization',
'Basic QUJJd1JpUHdLVlFJcmhiUzJ6bjNvOXNWS2lHTHFuRk0yT2d4bHhXRlpHRWJ6Z1kyNlM6N2RsdUVIN1hKNE5Rb1JHbG1qWTFmZ0VvTGt4ZjdreHM1WjNVdmcxVA==',
'Content-Type',
'application/x-www-form-urlencoded',
'Accept',
'application/json',
'User-Agent',
'Intuit-OAuthClient-JS_3.0.2_Linux_4.14.209-112.339.amzn2.x86_64_linux',
'Content-Length',
'89',
'Accept-Encoding',
'gzip,deflate'
],
middleware: [ [Function], [Function] ],
opened: true,
aborted: false,
uploaded: 1,
downloaded: 0,
timeout: 0,
method: 'POST',
body: 'grant_type=refresh_token&refresh_token=AB11620585757X1ISX92Nj7a5o2kHSwY2nO7cKmcJYvcGND8Qu',
events: [Object: null prototype] { abort: [Array] },
transport: { use: [Array], abort: [Function: abort], open: [Function: open] },
_promise: Promise { <rejected> [Circular] },
_raw: ClientRequest {
_events: [Object: null prototype],
_eventsCount: 2,
_maxListeners: undefined,
outputData: [],
outputSize: 0,
writable: true,
_last: true,
chunkedEncoding: false,
shouldKeepAlive: false,
_defaultKeepAlive: true,
useChunkedEncodingByDefault: true,
sendDate: false,
_removedConnection: false,
_removedContLen: false,
_removedTE: false,
_contentLength: null,
_hasBody: true,
_trailer: '',
finished: true,
_headerSent: true,
socket: [TLSSocket],
connection: [TLSSocket],
_header: 'POST /oauth2/v1/tokens/bearer HTTP/1.1\r\n' +
'Authorization: Basic QUJJd1JpUHdLVlFJcmhiUzJ6bjNvOXNWS2lHTHFuRk0yT2d4bHhXRlpHRWJ6Z1kyNlM6N2RsdUVIN1hKNE5Rb1JHbG1qWTFmZ0VvTGt4ZjdreHM1WjNVdmcxVA==\r\n' +
'Content-Type: application/x-www-form-urlencoded\r\n' +
'Accept: application/json\r\n' +
'User-Agent: Intuit-OAuthClient-JS_3.0.2_Linux_4.14.209-112.339.amzn2.x86_64_linux\r\n' +
'Content-Length: 89\r\n' +
'Accept-Encoding: gzip,deflate\r\n' +
'Host: oauth.platform.intuit.com\r\n' +
'Connection: close\r\n' +
'\r\n',
_keepAliveTimeout: 0,
_onPendingData: [Function: noopPendingOutput],
agent: [Agent],
socketPath: undefined,
method: 'POST',
insecureHTTPParser: undefined,
path: '/oauth2/v1/tokens/bearer',
_ended: false,
res: null,
aborted: true,
timeoutCb: null,
upgradeOrConnect: false,
parser: null,
maxHeadersCount: null,
reusedSocket: false,
host: 'oauth.platform.intuit.com',
protocol: 'https:',
[Symbol(kCapture)]: false,
[Symbol(kNeedDrain)]: false,
[Symbol(corked)]: 0,
[Symbol(kOutHeaders)]: [Object: null prototype]
},
uploadLength: 89,
uploadedBytes: 89
},
error: 'Unable to connect to "https://oauth.platform.intuit.com/oauth2/v1/tokens/bearer"',
authResponse: AuthResponse {
token: Token {
realmId: '',
token_type: '',
access_token: '',
refresh_token: '',
expires_in: 0,
x_refresh_token_expires_in: 0,
id_token: '',
latency: 60000,
createdAt: 1611935355498
},
response: '',
body: '',
json: null,
intuit_tid: ''
},
intuit_tid: '',
originalMessage: 'Unable to connect to "https://oauth.platform.intuit.com/oauth2/v1/tokens/bearer"',
error_description: ''
}
来自评论:
Lambda 容器将在几分钟不活动后被销毁,并且对磁盘或全局内存所做的任何更改都不会在这段空闲时间后跨调用甚至在其他线程中持久保存。
在当前示例中,Quickbooks 刷新令牌存储在磁盘中,不会持久保存,原始 lambda zip 中的刷新令牌将用于后续调用。
我正在使用连接到 QBO 的 AWS Lambda API。
我的目标是每天通过 lambda cron 触发器实现此 运行。
Here is a gist of the oauth service I wrote >>
intuit-oauth version: 3.0.2
Node.js version 12
为了启动 OAuth,我从 QBO 游乐场获得了一个新的刷新令牌,并将其存储在 JSON 文件中。之后,我将刷新令牌写入更新的 JSON 文件。我看到这个工作正常,我从这个项目中休息了大约一个星期,当我回到它时,我的 JSON 文件中的当前刷新令牌让我可以正常访问它。但这当然只是在本地。
当我 运行 在本地测试时,它每次都能完美运行,在我将其部署到 AWS 后,如果我不等待超过几分钟进行测试,它可能会运行一次或两次。如果我等待大约 15 分钟,我会收到以下错误:
PopsicleError: Unable to connect to "https://oauth.platform.intuit.com/oauth2/v1/tokens/bearer"
at Request.error (/var/task/node_modules/intuit-oauth/node_modules/popsicle/dist/request.js:41:16)
at ClientRequest.<anonymous> (/var/task/node_modules/intuit-oauth/node_modules/popsicle/dist/index.js:131:39)
at ClientRequest.emit (events.js:326:22)
at ClientRequest.EventEmitter.emit (domain.js:483:12)
at TLSSocket.socketErrorListener (_http_client.js:427:9)
at TLSSocket.emit (events.js:314:20)
at TLSSocket.EventEmitter.emit (domain.js:483:12)
at emitErrorNT (internal/streams/destroy.js:92:8)
at emitErrorAndCloseNT (internal/streams/destroy.js:60:3)
at processTicksAndRejections (internal/process/task_queues.js:84:21) {
cause: Error: connect ETIMEDOUT 54.148.164.32:443
at TCPConnectWrap.afterConnect [as oncomplete] (net.js:1144:16) {
errno: 'ETIMEDOUT',
code: 'ETIMEDOUT',
syscall: 'connect',
address: '54.148.164.32',
port: 443
},
code: 'EUNAVAILABLE',
popsicle: Request {
Url: Url {
protocol: 'https:',
slashes: true,
auth: null,
host: 'oauth.platform.intuit.com',
port: null,
hostname: 'oauth.platform.intuit.com',
hash: null,
search: null,
query: [Object: null prototype] {},
pathname: '/oauth2/v1/tokens/bearer',
path: '/oauth2/v1/tokens/bearer',
href: 'https://oauth.platform.intuit.com/oauth2/v1/tokens/bearer'
},
rawHeaders: [
'Authorization',
'Basic QUJJd1JpUHdLVlFJcmhiUzJ6bjNvOXNWS2lHTHFuRk0yT2d4bHhXRlpHRWJ6Z1kyNlM6N2RsdUVIN1hKNE5Rb1JHbG1qWTFmZ0VvTGt4ZjdreHM1WjNVdmcxVA==',
'Content-Type',
'application/x-www-form-urlencoded',
'Accept',
'application/json',
'User-Agent',
'Intuit-OAuthClient-JS_3.0.2_Linux_4.14.209-112.339.amzn2.x86_64_linux',
'Content-Length',
'89',
'Accept-Encoding',
'gzip,deflate'
],
middleware: [ [Function], [Function] ],
opened: true,
aborted: false,
uploaded: 1,
downloaded: 0,
timeout: 0,
method: 'POST',
body: 'grant_type=refresh_token&refresh_token=AB11620585757X1ISX92Nj7a5o2kHSwY2nO7cKmcJYvcGND8Qu',
events: [Object: null prototype] { abort: [Array] },
transport: { use: [Array], abort: [Function: abort], open: [Function: open] },
_promise: Promise { <rejected> [Circular] },
_raw: ClientRequest {
_events: [Object: null prototype],
_eventsCount: 2,
_maxListeners: undefined,
outputData: [],
outputSize: 0,
writable: true,
_last: true,
chunkedEncoding: false,
shouldKeepAlive: false,
_defaultKeepAlive: true,
useChunkedEncodingByDefault: true,
sendDate: false,
_removedConnection: false,
_removedContLen: false,
_removedTE: false,
_contentLength: null,
_hasBody: true,
_trailer: '',
finished: true,
_headerSent: true,
socket: [TLSSocket],
connection: [TLSSocket],
_header: 'POST /oauth2/v1/tokens/bearer HTTP/1.1\r\n' +
'Authorization: Basic QUJJd1JpUHdLVlFJcmhiUzJ6bjNvOXNWS2lHTHFuRk0yT2d4bHhXRlpHRWJ6Z1kyNlM6N2RsdUVIN1hKNE5Rb1JHbG1qWTFmZ0VvTGt4ZjdreHM1WjNVdmcxVA==\r\n' +
'Content-Type: application/x-www-form-urlencoded\r\n' +
'Accept: application/json\r\n' +
'User-Agent: Intuit-OAuthClient-JS_3.0.2_Linux_4.14.209-112.339.amzn2.x86_64_linux\r\n' +
'Content-Length: 89\r\n' +
'Accept-Encoding: gzip,deflate\r\n' +
'Host: oauth.platform.intuit.com\r\n' +
'Connection: close\r\n' +
'\r\n',
_keepAliveTimeout: 0,
_onPendingData: [Function: noopPendingOutput],
agent: [Agent],
socketPath: undefined,
method: 'POST',
insecureHTTPParser: undefined,
path: '/oauth2/v1/tokens/bearer',
_ended: false,
res: null,
aborted: true,
timeoutCb: null,
upgradeOrConnect: false,
parser: null,
maxHeadersCount: null,
reusedSocket: false,
host: 'oauth.platform.intuit.com',
protocol: 'https:',
[Symbol(kCapture)]: false,
[Symbol(kNeedDrain)]: false,
[Symbol(corked)]: 0,
[Symbol(kOutHeaders)]: [Object: null prototype]
},
uploadLength: 89,
uploadedBytes: 89
},
error: 'Unable to connect to "https://oauth.platform.intuit.com/oauth2/v1/tokens/bearer"',
authResponse: AuthResponse {
token: Token {
realmId: '',
token_type: '',
access_token: '',
refresh_token: '',
expires_in: 0,
x_refresh_token_expires_in: 0,
id_token: '',
latency: 60000,
createdAt: 1611935355498
},
response: '',
body: '',
json: null,
intuit_tid: ''
},
intuit_tid: '',
originalMessage: 'Unable to connect to "https://oauth.platform.intuit.com/oauth2/v1/tokens/bearer"',
error_description: ''
}
来自评论: Lambda 容器将在几分钟不活动后被销毁,并且对磁盘或全局内存所做的任何更改都不会在这段空闲时间后跨调用甚至在其他线程中持久保存。
在当前示例中,Quickbooks 刷新令牌存储在磁盘中,不会持久保存,原始 lambda zip 中的刷新令牌将用于后续调用。