@liuliang520500/jd-sdk
Version:
143 lines (121 loc) • 4.28 kB
JavaScript
const axios = require('axios');
const { sign } = require('./sign');
const API_BASE_DOMAIN = 'https://api.jd.com';
const API_ENDPOINT = '/routerjson';
function getCurrentTimestamp() {
const now = new Date();
const year = now.getFullYear();
const month = String(now.getMonth() + 1).padStart(2, '0');
const day = String(now.getDate()).padStart(2, '0');
const hours = String(now.getHours()).padStart(2, '0');
const minutes = String(now.getMinutes()).padStart(2, '0');
const seconds = String(now.getSeconds()).padStart(2, '0');
return `${year}-${month}-${day} ${hours}:${minutes}:${seconds}`;
}
class JdApiError extends Error {
constructor(code, message, subCode, subMessage) {
super(message);
this.name = 'JdApiError';
this.code = code;
this.subCode = subCode;
this.subMessage = subMessage;
}
}
class BaseApi {
constructor(config) {
this.appKey = config.appKey;
this.secretKey = config.secretKey;
this.accessToken = config.accessToken;
this.apiVersion = config.apiVersion || '1.0';
this.format = config.format || 'json';
this.domain = API_BASE_DOMAIN;
console.log('BaseApi初始化:');
console.log('- appKey:', this.appKey);
console.log('- accessToken是否设置:', this.accessToken ? '是' : '否');
}
getApiName() {
throw new Error('子类必须实现getApiName方法');
}
async execute(params = {}, options = {}) {
const timestamp = getCurrentTimestamp();
const systemParams = {
timestamp,
method: this.getApiName(),
app_key: this.appKey,
v: this.apiVersion,
sign_method: 'md5',
format: this.format
};
console.log('Execute方法中:');
console.log('- 方法名称:', this.getApiName());
console.log('- 传入参数:', JSON.stringify(params, (key, value) => {
// 过滤敏感信息
if (key === 'key' && typeof value === 'string') {
return value ? '已设置(长度:' + value.length + ')' : '未设置';
}
return value;
}, 2));
// access_token是系统参数,非必填
if (this.accessToken) {
console.log('- 添加系统参数access_token');
systemParams.access_token = this.accessToken;
} else {
console.log('- 不添加系统参数access_token');
}
// 这里是关键部分:检查参数中是否含有key,尤其是在positionReq对象内部
if (params.positionReq && typeof params.positionReq === 'object') {
console.log('- 发现positionReq对象:');
console.log(' - unionId:', params.positionReq.unionId);
console.log(' - key:', params.positionReq.key ? '已设置(长度:' + params.positionReq.key.length + ')' : '未设置');
console.log(' - unionType:', params.positionReq.unionType);
}
const jsonParams = JSON.stringify(params);
systemParams['360buy_param_json'] = jsonParams;
systemParams.sign = sign(this.secretKey, systemParams);
const url = `${this.domain}${API_ENDPOINT}`;
try {
// 打印请求参数,便于调试
console.log('请求参数:', {
url,
systemParams: {
...systemParams,
sign: '已生成',
'360buy_param_json': '已生成'
}
});
const response = await axios.post(url, null, {
params: systemParams,
timeout: options.timeout || 30000,
headers: {
'Content-Type': 'application/x-www-form-urlencoded',
'Cache-Control': 'no-cache'
}
});
const result = response.data;
const responseKey = this.getResponseKey();
console.log('API响应结果:', JSON.stringify(result, null, 2));
if (result.error_response) {
const error = result.error_response;
throw new JdApiError(
error.code,
error.zh_desc || '未知错误',
error.sub_code,
error.sub_msg
);
}
return result[responseKey] || result;
} catch (error) {
if (error instanceof JdApiError) {
throw error;
}
throw new Error(`API请求失败: ${error.message}`);
}
}
getResponseKey() {
return this.getApiName().replace(/\./g, '_') + '_response';
}
}
module.exports = {
BaseApi,
JdApiError
};