@be-link/ecommerce-trade-service-node-sdk 0.1.67 → 0.1.69
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/enums.js +1 -1
- package/modules/pos/orderQuery/types.d.ts +1 -1
- package/modules/ros/orderQuery/types.d.ts +4 -2
- package/package.json +1 -1
- package/utils/http.js +91 -94
package/enums.js
CHANGED
|
@@ -435,7 +435,7 @@ var ENUM_CN;
|
|
|
435
435
|
};
|
|
436
436
|
/** 退款方式中文映射 */
|
|
437
437
|
ENUM_CN.ReverseRefundWay = {
|
|
438
|
-
[ENUM.ReverseRefundWay.USER_MANUAL]: '
|
|
438
|
+
[ENUM.ReverseRefundWay.USER_MANUAL]: '商家审核退款',
|
|
439
439
|
[ENUM.ReverseRefundWay.FAST]: '极速退款',
|
|
440
440
|
[ENUM.ReverseRefundWay.MERCHANT_MANUAL]: '商家主动退款',
|
|
441
441
|
};
|
|
@@ -91,7 +91,7 @@ export declare namespace PosOrderQueryService {
|
|
|
91
91
|
orderIds?: string[];
|
|
92
92
|
sourceList?: ENUM.OrderSource[];
|
|
93
93
|
statusList?: ENUM.OrderStatus[];
|
|
94
|
-
|
|
94
|
+
isVerifyCoupon?: boolean;
|
|
95
95
|
refundStatusList?: ENUM.OrderRefundStatus[];
|
|
96
96
|
productPickList?: string[];
|
|
97
97
|
productDispatchList?: string[];
|
|
@@ -59,8 +59,10 @@ export declare namespace RosOrderQueryService {
|
|
|
59
59
|
reverseOrderIds?: string[];
|
|
60
60
|
/** 订单ID列表 */
|
|
61
61
|
orderIds?: string[];
|
|
62
|
-
/**
|
|
63
|
-
|
|
62
|
+
/** 是否核销券订单(true=核销券订单,false=非核销券订单) */
|
|
63
|
+
isVerifyCoupon?: boolean;
|
|
64
|
+
/** 订单来源列表 */
|
|
65
|
+
sourceList?: ENUM.OrderSource[];
|
|
64
66
|
/** 用户ID列表 */
|
|
65
67
|
userIds?: string[];
|
|
66
68
|
/** 门店ID列表 */
|
package/package.json
CHANGED
package/utils/http.js
CHANGED
|
@@ -1,37 +1,4 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
-
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
-
if (k2 === undefined) k2 = k;
|
|
4
|
-
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
-
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
-
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
-
}
|
|
8
|
-
Object.defineProperty(o, k2, desc);
|
|
9
|
-
}) : (function(o, m, k, k2) {
|
|
10
|
-
if (k2 === undefined) k2 = k;
|
|
11
|
-
o[k2] = m[k];
|
|
12
|
-
}));
|
|
13
|
-
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
-
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
-
}) : function(o, v) {
|
|
16
|
-
o["default"] = v;
|
|
17
|
-
});
|
|
18
|
-
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
-
var ownKeys = function(o) {
|
|
20
|
-
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
-
var ar = [];
|
|
22
|
-
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
-
return ar;
|
|
24
|
-
};
|
|
25
|
-
return ownKeys(o);
|
|
26
|
-
};
|
|
27
|
-
return function (mod) {
|
|
28
|
-
if (mod && mod.__esModule) return mod;
|
|
29
|
-
var result = {};
|
|
30
|
-
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
-
__setModuleDefault(result, mod);
|
|
32
|
-
return result;
|
|
33
|
-
};
|
|
34
|
-
})();
|
|
35
2
|
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
36
3
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
37
4
|
};
|
|
@@ -41,71 +8,101 @@ const axios_1 = __importDefault(require("axios"));
|
|
|
41
8
|
const uuid_1 = require("uuid");
|
|
42
9
|
const axios_retry_1 = __importDefault(require("axios-retry"));
|
|
43
10
|
const request_context_1 = require("@fastify/request-context");
|
|
44
|
-
const
|
|
11
|
+
const http_1 = __importDefault(require("http"));
|
|
12
|
+
const https_1 = __importDefault(require("https"));
|
|
13
|
+
// HTTP 连接池配置 - 支持 2000 QPS(响应时间 2秒)
|
|
14
|
+
const HTTP_CONFIG = {
|
|
15
|
+
maxSockets: 3000, // 每个 host 最大并发连接数
|
|
16
|
+
maxFreeSockets: 1000, // 保持空闲连接数(减少连接重建开销)
|
|
17
|
+
maxTotalSockets: 10000, // 所有 host 总连接数上限(支持多个服务同时调用)
|
|
18
|
+
keepAliveMsecs: 60000, // 保持连接60秒
|
|
19
|
+
timeout: 5000, // socket超时5秒
|
|
20
|
+
requestTimeout: 5000, // 请求超时5秒
|
|
21
|
+
retries: 0, // 不重试(失败直接返回)
|
|
22
|
+
retryBaseDelay: 200, // 基础重试延迟200ms
|
|
23
|
+
};
|
|
24
|
+
// 配置 HTTP/HTTPS Agent 以支持高并发连接池和 keepAlive
|
|
25
|
+
const httpAgent = new http_1.default.Agent({
|
|
26
|
+
keepAlive: true,
|
|
27
|
+
keepAliveMsecs: HTTP_CONFIG.keepAliveMsecs,
|
|
28
|
+
maxSockets: HTTP_CONFIG.maxSockets,
|
|
29
|
+
maxFreeSockets: HTTP_CONFIG.maxFreeSockets,
|
|
30
|
+
maxTotalSockets: HTTP_CONFIG.maxTotalSockets,
|
|
31
|
+
timeout: HTTP_CONFIG.timeout,
|
|
32
|
+
scheduling: 'lifo', // 后进先出调度(优先复用热连接,提高连接复用效率)
|
|
33
|
+
});
|
|
34
|
+
const httpsAgent = new https_1.default.Agent({
|
|
35
|
+
keepAlive: true,
|
|
36
|
+
keepAliveMsecs: HTTP_CONFIG.keepAliveMsecs,
|
|
37
|
+
maxSockets: HTTP_CONFIG.maxSockets,
|
|
38
|
+
maxFreeSockets: HTTP_CONFIG.maxFreeSockets,
|
|
39
|
+
maxTotalSockets: HTTP_CONFIG.maxTotalSockets,
|
|
40
|
+
timeout: HTTP_CONFIG.timeout,
|
|
41
|
+
scheduling: 'lifo', // 后进先出调度(优先复用热连接,提高连接复用效率)
|
|
42
|
+
});
|
|
43
|
+
// 配置 axios 默认使用这些 agent
|
|
44
|
+
axios_1.default.defaults.httpAgent = httpAgent;
|
|
45
|
+
axios_1.default.defaults.httpsAgent = httpsAgent;
|
|
46
|
+
axios_1.default.defaults.timeout = HTTP_CONFIG.requestTimeout;
|
|
47
|
+
axios_1.default.defaults.maxRedirects = 3; // 限制重定向次数
|
|
48
|
+
axios_1.default.defaults.maxContentLength = 50 * 1024 * 1024; // 50MB 最大响应大小
|
|
49
|
+
// 高并发场景下的智能重试配置
|
|
45
50
|
(0, axios_retry_1.default)(axios_1.default, {
|
|
46
|
-
retries:
|
|
51
|
+
retries: HTTP_CONFIG.retries,
|
|
47
52
|
retryCondition(error) {
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
+
// 重试临时错误和特定的网络错误
|
|
54
|
+
const status = error.response?.status;
|
|
55
|
+
const isNetworkError = error.code === 'ECONNRESET' ||
|
|
56
|
+
error.code === 'ETIMEDOUT' ||
|
|
57
|
+
error.code === 'ECONNREFUSED' ||
|
|
58
|
+
error.code === 'ENOTFOUND' ||
|
|
59
|
+
error.code === 'ENETUNREACH' ||
|
|
60
|
+
error.code === 'EAI_AGAIN';
|
|
61
|
+
const isServerError = status === 502 || status === 503 || status === 504;
|
|
62
|
+
const isRateLimited = status === 429;
|
|
63
|
+
const isTimeout = error.code === 'ECONNABORTED' || error.message?.includes('timeout');
|
|
64
|
+
return isNetworkError || isServerError || isRateLimited || isTimeout;
|
|
53
65
|
},
|
|
54
|
-
|
|
55
|
-
|
|
66
|
+
retryDelay: (retryCount, error) => {
|
|
67
|
+
// 指数退避 + 抖动
|
|
68
|
+
const status = error.response?.status;
|
|
69
|
+
// 如果是限流错误,延迟更长
|
|
70
|
+
if (status === 429) {
|
|
71
|
+
const retryAfter = error.response?.headers['retry-after'];
|
|
72
|
+
if (retryAfter) {
|
|
73
|
+
return parseInt(retryAfter) * 1000;
|
|
74
|
+
}
|
|
75
|
+
return 1000 + Math.random() * 1000; // 1-2秒
|
|
76
|
+
}
|
|
77
|
+
// 指数退避:200ms, 400ms, 800ms...
|
|
78
|
+
const exponentialDelay = HTTP_CONFIG.retryBaseDelay * Math.pow(2, retryCount - 1);
|
|
79
|
+
const jitter = Math.random() * 100; // 0-100ms 抖动
|
|
80
|
+
return Math.min(exponentialDelay + jitter, 3000); // 最多延迟3秒
|
|
56
81
|
},
|
|
82
|
+
shouldResetTimeout: true, // 重试时重置超时
|
|
57
83
|
});
|
|
58
84
|
async function callApi(url, request) {
|
|
59
|
-
|
|
60
|
-
const
|
|
61
|
-
const
|
|
62
|
-
const
|
|
63
|
-
const
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
const data = response.data;
|
|
83
|
-
console.error(`ecommerce-trade-service 异常: ${axiosError.message},requestId: ${requestId}`);
|
|
84
|
-
console.info('响应信息', data.message);
|
|
85
|
-
console.error('异常堆栈', (0, safe_stable_stringify_1.default)(error.stack));
|
|
86
|
-
// throw new Error(data.errorType + ' - ' + data.message)
|
|
87
|
-
throw error;
|
|
88
|
-
}
|
|
89
|
-
// 调用dns模块解析url
|
|
90
|
-
const dns = await Promise.resolve().then(() => __importStar(require('dns')));
|
|
91
|
-
const dnsPromise = new Promise((resolve, reject) => {
|
|
92
|
-
const lookupRes = dns.lookup(url, (err, address) => {
|
|
93
|
-
if (err) {
|
|
94
|
-
console.error(err.message);
|
|
95
|
-
reject(err);
|
|
96
|
-
}
|
|
97
|
-
console.info(`lookup: ${(0, safe_stable_stringify_1.default)(lookupRes)}`);
|
|
98
|
-
resolve(address);
|
|
99
|
-
});
|
|
100
|
-
});
|
|
101
|
-
try {
|
|
102
|
-
const address = await dnsPromise;
|
|
103
|
-
console.info(`address: ${(0, safe_stable_stringify_1.default)(address)}`);
|
|
104
|
-
}
|
|
105
|
-
catch (error) {
|
|
106
|
-
console.info(`error: ${(0, safe_stable_stringify_1.default)(error)}`);
|
|
107
|
-
}
|
|
108
|
-
console.error(`ecommerce-trade-service 未知异常: ${axiosError.message}`, error.stack);
|
|
109
|
-
throw error;
|
|
110
|
-
}
|
|
85
|
+
// 获取请求上下文
|
|
86
|
+
const ctx = request_context_1.requestContext.get('requestId') ? request_context_1.requestContext : null;
|
|
87
|
+
const requestId = ctx?.get('requestId') || ctx?.get('traceMessageId') || (0, uuid_1.v4)();
|
|
88
|
+
const pandoraUserId = ctx?.get('pandoraUserId') || '';
|
|
89
|
+
const beLinkUserId = ctx?.get('beLinkUserId') || '';
|
|
90
|
+
const pandoraRoleId = ctx?.get('pandoraRoleId') || '';
|
|
91
|
+
const realIp = ctx?.get('realIp') || '';
|
|
92
|
+
const response = await axios_1.default.post(url, request || {}, {
|
|
93
|
+
headers: {
|
|
94
|
+
'x-request-id': requestId,
|
|
95
|
+
'x-belink-pandora-userid': pandoraUserId,
|
|
96
|
+
'x-belink-userid': beLinkUserId,
|
|
97
|
+
'x-belink-pandora-roleid': pandoraRoleId,
|
|
98
|
+
'x-real-ip': realIp,
|
|
99
|
+
Connection: 'keep-alive',
|
|
100
|
+
'Content-Type': 'application/json;charset=utf-8',
|
|
101
|
+
},
|
|
102
|
+
timeout: HTTP_CONFIG.requestTimeout,
|
|
103
|
+
httpAgent,
|
|
104
|
+
httpsAgent,
|
|
105
|
+
});
|
|
106
|
+
const responseData = response.data;
|
|
107
|
+
return responseData.data;
|
|
111
108
|
}
|