我正在尝试为一个项目连接 eTrade 的 API。他们使用 OAuth v1 流程。我在流程的第一步 - 获取请求令牌时遇到了错误。可以在此处找到他们文档中的信息。
我得到的错误是 401-无效签名。
我一直在这里阅读 OAuth 流程并熟悉该流程。过去,我使用 PassportJS 进行 3rd 方集成。
所以 eTrade 为我提供了 4 个密钥——PROD_KEY、PROD_SECRET、SANDBOX_KEY、SANDBOX_SECRET。我现在正在使用沙盒密钥,因为我的生产密钥仍在等待中。
现在我的 API 上有一个端点,我将从客户端调用它来获取请求令牌。它的结构是这样的:
router.route('/auth/request').get(controller.request);
下面的控制器是我生成签名并尝试从 eTrade 请求令牌的地方。该控制器如下所示:
// controllers/auth.js
const axios = require('axios');
const { v1 } = require('uuid');
const crypto = require('crypto');
function generateSignature() {
const method = 'GET',
url = 'http://localhost/',
encodedUrl = encodeURIComponent(url),
paramaters = {
oauth_consumer_key: process.env.ETRADE_SANDBOX_API_KEY,
oauth_signature_method: 'HMAC-SHA1',
oauth_timestamp: Math.floor(Date.now() / 1000),
oauth_nonce: v1(),
oauth_callback: 'oob'
}
var ordered = {};
Object.keys(paramaters).sort().forEach((key) => {
ordered[key] = paramaters[key];
});
var encodedParameters = '';
for(k in ordered) {
const encodedValue = escape(ordered[k]);
const encodedKey = encodeURIComponent(k);
if(encodedParameters === '') {
encodedParameters += encodeURIComponent(`${encodedKey}=${encodedValue}`);
} else {
encodedParameters += encodeURIComponent(`&${encodedKey}=${encodedValue}`);
}
}
encodedParameters = encodeURIComponent(encodedParameters);
const signature_base_string = `${method}&${encodedUrl}&${encodedParameters}`;
const signing_key = `${process.env.ETRADE_SANDBOX_SECRET_KEY}`;
const signature = crypto.createHmac("SHA1", signing_key).update(signature_base_string).digest().toString('base64');
const encodedSignature = encodeURIComponent(signature);
return encodedSignature;
}
module.exports = {
request: async (req, res) => {
console.log('Fetching request token from etrade...');
try {
var response = await axios.get(`https://api.etrade.com/oauth/request_token`, {
params: {
oauth_consumer_key: process.env.ETRADE_SANDBOX_API_KEY,
oauth_signature_method: 'HMAC-SHA1',
oauth_signature: generateSignature(),
oauth_timestamp: Math.floor(Date.now() / 1000),
oauth_nonce: v1(),
oauth_callback: 'oob'
}
});
console.log('Fetched request token...', response.data);
} catch (error) {
console.log('Could not fetch request token...', error.response.data);
}
}
}
我已经按照互联网上的一些指南来帮助我了解签署请求的过程,但我似乎无法得到有效的回复。