cbs-4px-merchant-cli 0.0.8 → 0.0.11
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/README.4px.md +5 -5
- package/README.cainiao.md +5 -5
- package/README.md +5 -5
- package/dist/cli.js +92 -25
- package/dist/cli.js.map +1 -1
- package/dist/commands/address.d.ts +7 -1
- package/dist/commands/address.js +29 -10
- package/dist/commands/address.js.map +1 -1
- package/dist/commands/auth.d.ts +1 -0
- package/dist/commands/auth.js +87 -0
- package/dist/commands/auth.js.map +1 -1
- package/dist/commands/config.d.ts +9 -2
- package/dist/commands/config.js +45 -12
- package/dist/commands/config.js.map +1 -1
- package/dist/commands/custody.d.ts +38 -0
- package/dist/commands/custody.js +176 -0
- package/dist/commands/custody.js.map +1 -0
- package/dist/commands/onboarding.d.ts +16 -7
- package/dist/commands/onboarding.js +73 -18
- package/dist/commands/onboarding.js.map +1 -1
- package/dist/commands/order.d.ts +23 -6
- package/dist/commands/order.js +60 -30
- package/dist/commands/order.js.map +1 -1
- package/dist/commands/platform.d.ts +8 -0
- package/dist/commands/platform.js +10 -1
- package/dist/commands/platform.js.map +1 -1
- package/dist/commands/problem.js +1 -1
- package/dist/commands/problem.js.map +1 -1
- package/dist/commands/product.d.ts +3 -0
- package/dist/commands/product.js +3 -0
- package/dist/commands/product.js.map +1 -1
- package/dist/services/api-client.d.ts +53 -12
- package/dist/services/api-client.js +235 -47
- package/dist/services/api-client.js.map +1 -1
- package/dist/types/index.d.ts +170 -12
- package/dist/utils/run-command.d.ts +6 -0
- package/dist/utils/run-command.js +13 -0
- package/dist/utils/run-command.js.map +1 -1
- package/package.json +1 -1
- package/skill/SKILL.md +16 -11
- package/skill/package.json +2 -1
- package/skill/reference/auth.md +20 -1
- package/skill/reference/custody.md +193 -0
- package/skill/reference/index.md +5 -2
- package/skill/reference/onboarding.md +79 -52
- package/skill/reference/order.md +84 -34
- package/skill/reference/platform.md +1 -1
- package/skill/reference/product.md +3 -0
- package/dist/digital-employee-skills/cbs-4px-merchant-cli-order-fulfillment.zip +0 -0
- package/dist/digital-employee-skills/cbs-cainiao-merchant-cli-order-fulfillment.zip +0 -0
|
@@ -1,6 +1,34 @@
|
|
|
1
1
|
import axios from 'axios';
|
|
2
|
-
import { ApiError, DryRunSignal } from '../errors.js';
|
|
2
|
+
import { ApiError, BportalError, DryRunSignal } from '../errors.js';
|
|
3
3
|
const API_PREFIX = '/api/merchant/tools';
|
|
4
|
+
const AGENTZ_API_KEY_GENERATE_PATH = '/api/agentz/apikey/generate';
|
|
5
|
+
/**
|
|
6
|
+
* 后端以 `@Body` 绑定(整体 JSON 反序列化)的端点,必须走 {@link ApiClient.postJson}。
|
|
7
|
+
*
|
|
8
|
+
* 这类端点收到表单串会在 `JSON.parseObject` 处抛异常,后端统一兜成
|
|
9
|
+
* `SYSTEM_ERROR / 系统繁忙,请稍后再试`——症状是「不传参侥幸能通、一传参就报系统繁忙」,
|
|
10
|
+
* 极难从错误信息反推。故在 `post()` 里对照本清单做开发期断言,写错立即报错而不是发出去。
|
|
11
|
+
*
|
|
12
|
+
* 新增工具时:后端方法签名是 `@Body XxxRequest` 就登记到这里并用 `postJson`;
|
|
13
|
+
* 是 `@Param` 就用 `post`。路径为 API_PREFIX 之后的部分。
|
|
14
|
+
*/
|
|
15
|
+
const JSON_BODY_PATHS = new Set([
|
|
16
|
+
'/order/list',
|
|
17
|
+
'/order/create',
|
|
18
|
+
'/order/edit',
|
|
19
|
+
'/product-recommendation',
|
|
20
|
+
'/shipping-fee/calculate',
|
|
21
|
+
'/problem/list',
|
|
22
|
+
'/problem/suggestions',
|
|
23
|
+
'/problem/intercepted/list',
|
|
24
|
+
'/service/claim/order/list',
|
|
25
|
+
'/service-order/aftersale/list',
|
|
26
|
+
'/service-order/check/list',
|
|
27
|
+
'/service-order/complaint/list',
|
|
28
|
+
'/finance/fee/daily/list',
|
|
29
|
+
'/finance/recharge/list',
|
|
30
|
+
'/finance/recharge/offline/list',
|
|
31
|
+
]);
|
|
4
32
|
/**
|
|
5
33
|
* Params whose values must never be echoed back to the terminal.
|
|
6
34
|
*
|
|
@@ -10,13 +38,21 @@ const API_PREFIX = '/api/merchant/tools';
|
|
|
10
38
|
* transcripts. Masking applies to the printed copy only — the request itself
|
|
11
39
|
* still carries the real value.
|
|
12
40
|
*/
|
|
13
|
-
const SENSITIVE_PARAMS = new Set(['certNumber', 'bankCard', 'authCode', 'mobile']);
|
|
41
|
+
const SENSITIVE_PARAMS = new Set(['certNumber', 'legalCertNumber', 'bankCard', 'authCode', 'mobile']);
|
|
14
42
|
/**
|
|
15
43
|
* 嵌套 JSON body 同样需要递归遮蔽敏感字段,否则订单的
|
|
16
44
|
* `receiver.mobile`、`sender.phone` 会被 `--dry-run` / `--verbose`
|
|
17
45
|
* 原样写入终端回滚区和平台日志。
|
|
18
46
|
*/
|
|
19
|
-
const SENSITIVE_BODY_KEYS = new Set([
|
|
47
|
+
const SENSITIVE_BODY_KEYS = new Set([
|
|
48
|
+
'certNumber',
|
|
49
|
+
// 法人身份证号与企业证件号同级敏感,遗漏会让企业实名的 --dry-run 明文回显
|
|
50
|
+
'legalCertNumber',
|
|
51
|
+
'bankCard',
|
|
52
|
+
'authCode',
|
|
53
|
+
'mobile',
|
|
54
|
+
'phone',
|
|
55
|
+
]);
|
|
20
56
|
function maskSensitive(params) {
|
|
21
57
|
const out = {};
|
|
22
58
|
for (const [k, v] of Object.entries(params)) {
|
|
@@ -44,6 +80,26 @@ function toForm(params) {
|
|
|
44
80
|
}
|
|
45
81
|
return form;
|
|
46
82
|
}
|
|
83
|
+
/**
|
|
84
|
+
* 企业证件类型的数字值 → 枚举名,与后端 `OrganCertTypeEnum` 一一对应。
|
|
85
|
+
* 企业实名同时传 certType 与 certTypeEnum,两者不一致时以哪个为准并不确定,
|
|
86
|
+
* 所以 CLI 只收数字,枚举名统一从这里推导。
|
|
87
|
+
*/
|
|
88
|
+
const ORGAN_CERT_TYPE_ENUMS = {
|
|
89
|
+
0: 'CRED_ORG_USCC',
|
|
90
|
+
1: 'CRED_ORG_CODE',
|
|
91
|
+
2: 'CRED_ORG_REGCODE',
|
|
92
|
+
3: 'CRED_ORG_BUSINESS_REGISTTATION_CODE',
|
|
93
|
+
4: 'CRED_ORG_TAX_REGISTTATION_CODE',
|
|
94
|
+
5: 'CRED_ORG_LEGAL_PERSON_CODE',
|
|
95
|
+
6: 'CRED_ORG_ENT_LEGAL_PERSON_CODE',
|
|
96
|
+
7: 'CRED_ORG_SOCIAL_REG_CODE',
|
|
97
|
+
8: 'CRED_ORG_PRIVATE_NON_ENT_REG_CODE',
|
|
98
|
+
9: 'CRED_ORG_FOREIGN_ENT_REG_CODE',
|
|
99
|
+
10: 'CRED_ORG_GOV_APPROVAL',
|
|
100
|
+
11: 'CODE_ORG_CUSTOM',
|
|
101
|
+
12: 'CRED_ORG_UNKNOWN',
|
|
102
|
+
};
|
|
47
103
|
export class ApiClient {
|
|
48
104
|
config;
|
|
49
105
|
verbose;
|
|
@@ -53,6 +109,16 @@ export class ApiClient {
|
|
|
53
109
|
this.verbose = options?.verbose ?? false;
|
|
54
110
|
this.dryRun = options?.dryRun ?? false;
|
|
55
111
|
}
|
|
112
|
+
/** 返回今天日期 yyyy-MM-dd,与 bportal MCP Server 的 defaultEndDate 对齐 */
|
|
113
|
+
todayDate() {
|
|
114
|
+
return new Date().toISOString().slice(0, 10);
|
|
115
|
+
}
|
|
116
|
+
/** 返回 N 天前的日期 yyyy-MM-dd,与 bportal MCP Server 的 defaultStartDate 对齐 */
|
|
117
|
+
recentDate(days) {
|
|
118
|
+
const d = new Date();
|
|
119
|
+
d.setDate(d.getDate() - days);
|
|
120
|
+
return d.toISOString().slice(0, 10);
|
|
121
|
+
}
|
|
56
122
|
async createHttp(withAuth) {
|
|
57
123
|
const baseURL = await this.config.resolveBaseUrl();
|
|
58
124
|
const headers = {
|
|
@@ -65,6 +131,37 @@ export class ApiClient {
|
|
|
65
131
|
}
|
|
66
132
|
return axios.create({ baseURL, headers, timeout: 15000 });
|
|
67
133
|
}
|
|
134
|
+
/**
|
|
135
|
+
* Uses the AgentZ access token only to mint the merchant API Key. The token
|
|
136
|
+
* must never be persisted, returned, or printed because it belongs to the
|
|
137
|
+
* host Agent client rather than this CLI.
|
|
138
|
+
*/
|
|
139
|
+
async generateAgentzApiKey(accessToken) {
|
|
140
|
+
const baseURL = await this.config.resolveBaseUrl();
|
|
141
|
+
const http = axios.create({
|
|
142
|
+
baseURL,
|
|
143
|
+
headers: {
|
|
144
|
+
'Content-Type': 'application/json',
|
|
145
|
+
'X-Source': 'cli',
|
|
146
|
+
Authorization: `Bearer ${accessToken}`,
|
|
147
|
+
},
|
|
148
|
+
timeout: 15000,
|
|
149
|
+
});
|
|
150
|
+
if (this.verbose) {
|
|
151
|
+
process.stderr.write(`> POST ${baseURL}${AGENTZ_API_KEY_GENERATE_PATH}\n`);
|
|
152
|
+
process.stderr.write('> Authorization: Bearer ****\n');
|
|
153
|
+
}
|
|
154
|
+
const res = await http.post(AGENTZ_API_KEY_GENERATE_PATH);
|
|
155
|
+
if (this.verbose) {
|
|
156
|
+
process.stderr.write(`< ${res.status} ${res.statusText}\n`);
|
|
157
|
+
}
|
|
158
|
+
const response = res.data;
|
|
159
|
+
const apiKey = response.data?.apiKey;
|
|
160
|
+
if (response.result !== 0 || !apiKey) {
|
|
161
|
+
throw new ApiError(response.code ?? 'AGENTZ_API_KEY_GENERATION_FAILED', response.message ?? 'AgentZ API Key 生成失败', '请确认 AgentZ 登录态有效后重试');
|
|
162
|
+
}
|
|
163
|
+
return apiKey;
|
|
164
|
+
}
|
|
68
165
|
async get(path, params, withAuth) {
|
|
69
166
|
if (this.dryRun) {
|
|
70
167
|
const info = await this.dryRunInfo(path, params, withAuth);
|
|
@@ -91,6 +188,9 @@ export class ApiClient {
|
|
|
91
188
|
return resp.data;
|
|
92
189
|
}
|
|
93
190
|
async post(path, params, withAuth) {
|
|
191
|
+
if (JSON_BODY_PATHS.has(path.slice(API_PREFIX.length))) {
|
|
192
|
+
throw new BportalError(`${path} 在后端以 @Body 绑定,必须调用 postJson();用 post() 发表单会被兜成 SYSTEM_ERROR`, 'CLIENT_BUG', '这是 CLI 代码缺陷,请把该调用改为 postJson()');
|
|
193
|
+
}
|
|
94
194
|
if (this.dryRun) {
|
|
95
195
|
const info = await this.dryRunPostInfo(path, params, withAuth);
|
|
96
196
|
console.log(JSON.stringify(info, null, 2));
|
|
@@ -122,9 +222,12 @@ export class ApiClient {
|
|
|
122
222
|
/**
|
|
123
223
|
* 发送 JSON body 的 POST。
|
|
124
224
|
*
|
|
125
|
-
*
|
|
126
|
-
*
|
|
127
|
-
*
|
|
225
|
+
* 用于后端以 `@Body` 绑定的接口(order create/edit、problem order list、
|
|
226
|
+
* custody 全部、onboarding 的实名与开通品牌接口)。后端的 `@Body` 解析器直接
|
|
227
|
+
* 对原始 body 做 `JSON.parseObject`,收到表单串会抛
|
|
228
|
+
* `Failed to parse JSON body as ...`,因此这类接口不能走 `post()`。
|
|
229
|
+
* 其余接口必须继续调用 `post()`,因为 Solon 的 `@Param` 从表单取值,
|
|
230
|
+
* 发送 JSON body 会返回 400。
|
|
128
231
|
*/
|
|
129
232
|
async postJson(path, body, withAuth) {
|
|
130
233
|
if (this.dryRun) {
|
|
@@ -224,6 +327,8 @@ export class ApiClient {
|
|
|
224
327
|
body.customerOrderNo = request.customerOrderNo;
|
|
225
328
|
if (request.fpxTrackNo)
|
|
226
329
|
body.fpxTrackNo = request.fpxTrackNo;
|
|
330
|
+
if (request.queryDateType)
|
|
331
|
+
body.queryDateType = request.queryDateType;
|
|
227
332
|
if (request.queryStartDate)
|
|
228
333
|
body.queryStartDate = request.queryStartDate;
|
|
229
334
|
if (request.queryEndDate)
|
|
@@ -232,14 +337,37 @@ export class ApiClient {
|
|
|
232
337
|
body.productCode = request.productCode;
|
|
233
338
|
if (request.destinationCountry)
|
|
234
339
|
body.destinationCountry = request.destinationCountry;
|
|
340
|
+
if (request.consigneeName)
|
|
341
|
+
body.consigneeName = request.consigneeName;
|
|
342
|
+
if (request.buyerId)
|
|
343
|
+
body.buyerId = request.buyerId;
|
|
344
|
+
if (request.isPrint)
|
|
345
|
+
body.isPrint = request.isPrint;
|
|
346
|
+
if (request.odaConfirm)
|
|
347
|
+
body.odaConfirm = request.odaConfirm;
|
|
348
|
+
if (request.interceptStatus)
|
|
349
|
+
body.interceptStatus = request.interceptStatus;
|
|
350
|
+
if (request.changeNoStatus)
|
|
351
|
+
body.changeNoStatus = request.changeNoStatus;
|
|
352
|
+
if (request.isHistory)
|
|
353
|
+
body.isHistory = request.isHistory;
|
|
235
354
|
if (request.pageNum != null)
|
|
236
355
|
body.pageNum = request.pageNum;
|
|
237
356
|
if (request.pageSize != null)
|
|
238
357
|
body.pageSize = request.pageSize;
|
|
239
|
-
return this.
|
|
358
|
+
return this.postJson(`${API_PREFIX}/order/list`, body, true);
|
|
240
359
|
}
|
|
241
|
-
async listAddressBook() {
|
|
242
|
-
|
|
360
|
+
async listAddressBook(request) {
|
|
361
|
+
const body = {};
|
|
362
|
+
if (request.addressType)
|
|
363
|
+
body.addressType = request.addressType;
|
|
364
|
+
if (request.keyword)
|
|
365
|
+
body.keyword = request.keyword;
|
|
366
|
+
if (request.pageNum != null)
|
|
367
|
+
body.pageNum = request.pageNum;
|
|
368
|
+
if (request.pageSize != null)
|
|
369
|
+
body.pageSize = request.pageSize;
|
|
370
|
+
return this.post(`${API_PREFIX}/address-book/list`, body, true);
|
|
243
371
|
}
|
|
244
372
|
async searchDestinationCountry(key, productCode) {
|
|
245
373
|
const body = { key };
|
|
@@ -256,14 +384,20 @@ export class ApiClient {
|
|
|
256
384
|
async editOrder(request) {
|
|
257
385
|
return this.postJson(`${API_PREFIX}/order/edit`, request, true);
|
|
258
386
|
}
|
|
259
|
-
|
|
260
|
-
|
|
387
|
+
/** 草稿转预报。传客户订单号,后端按单号反查主键。 */
|
|
388
|
+
async forecastOrder(orderNos) {
|
|
389
|
+
return this.post(`${API_PREFIX}/order/forecast`, { orderNos }, true);
|
|
390
|
+
}
|
|
391
|
+
/** 取消订单。传单号,后端按单号反查主键。 */
|
|
392
|
+
async cancelOrder(orderNos, cancelReason) {
|
|
393
|
+
return this.post(`${API_PREFIX}/order/cancel`, { orderNos, cancelReason }, true);
|
|
261
394
|
}
|
|
262
|
-
|
|
263
|
-
|
|
395
|
+
/** 申请拦截。传单号,后端按单号反查主键。 */
|
|
396
|
+
async interceptOrder(orderNos) {
|
|
397
|
+
return this.post(`${API_PREFIX}/order/intercept`, { orderNos }, true);
|
|
264
398
|
}
|
|
265
|
-
async
|
|
266
|
-
return this.post(`${API_PREFIX}/order/
|
|
399
|
+
async uninterceptOrder(orderNos) {
|
|
400
|
+
return this.post(`${API_PREFIX}/order/unintercept`, { orderNos }, true);
|
|
267
401
|
}
|
|
268
402
|
async searchProduct(key, countryCode) {
|
|
269
403
|
const body = { key };
|
|
@@ -284,7 +418,7 @@ export class ApiClient {
|
|
|
284
418
|
body.isBattery = request.isBattery;
|
|
285
419
|
if (request.declareValue != null)
|
|
286
420
|
body.declareValue = request.declareValue;
|
|
287
|
-
return this.
|
|
421
|
+
return this.postJson(`${API_PREFIX}/product-recommendation`, body, true);
|
|
288
422
|
}
|
|
289
423
|
async listAvailableProducts(country, startCity) {
|
|
290
424
|
const body = { country };
|
|
@@ -312,7 +446,7 @@ export class ApiClient {
|
|
|
312
446
|
body.isBattery = request.isBattery;
|
|
313
447
|
if (request.declareValue != null)
|
|
314
448
|
body.declareValue = request.declareValue;
|
|
315
|
-
return this.
|
|
449
|
+
return this.postJson(`${API_PREFIX}/shipping-fee/calculate`, body, true);
|
|
316
450
|
}
|
|
317
451
|
async getEstimatedDeliveryTime(countryCode, productCode) {
|
|
318
452
|
return this.get(`${API_PREFIX}/estimated-delivery-time`, { countryCode, productCode }, true);
|
|
@@ -332,7 +466,7 @@ export class ApiClient {
|
|
|
332
466
|
body.pageNum = request.pageNum;
|
|
333
467
|
if (request.pageSize != null)
|
|
334
468
|
body.pageSize = request.pageSize;
|
|
335
|
-
return this.
|
|
469
|
+
return this.postJson(`${API_PREFIX}/service/claim/order/list`, body, true);
|
|
336
470
|
}
|
|
337
471
|
// ==================== Problem / Abnormal ====================
|
|
338
472
|
async listProblemOrder(request) {
|
|
@@ -343,15 +477,14 @@ export class ApiClient {
|
|
|
343
477
|
body.abnormalStatus = request.abnormalStatus;
|
|
344
478
|
if (request.abnormalType)
|
|
345
479
|
body.abnormalType = request.abnormalType;
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
body.endDate = request.endDate;
|
|
480
|
+
// 与 bportal MCP Server 保持一致:未传日期时默认查近 7 天
|
|
481
|
+
body.startDate = request.startDate || this.recentDate(7);
|
|
482
|
+
body.endDate = request.endDate || this.todayDate();
|
|
350
483
|
if (request.pageNum != null)
|
|
351
484
|
body.pageNum = request.pageNum;
|
|
352
485
|
if (request.pageSize != null)
|
|
353
486
|
body.pageSize = request.pageSize;
|
|
354
|
-
return this.
|
|
487
|
+
return this.postJson(`${API_PREFIX}/problem/order/list`, body, true);
|
|
355
488
|
}
|
|
356
489
|
async getProblemSuggestions(request) {
|
|
357
490
|
const body = {};
|
|
@@ -359,7 +492,7 @@ export class ApiClient {
|
|
|
359
492
|
body.items = JSON.stringify(request.items);
|
|
360
493
|
if (request.orderNoItems)
|
|
361
494
|
body.orderNoItems = request.orderNoItems.join(',');
|
|
362
|
-
return this.
|
|
495
|
+
return this.postJson(`${API_PREFIX}/problem/suggestions`, body, true);
|
|
363
496
|
}
|
|
364
497
|
async listProblemNotify(pageNum, pageSize) {
|
|
365
498
|
const body = {};
|
|
@@ -393,6 +526,8 @@ export class ApiClient {
|
|
|
393
526
|
body.customerOrderNo = request.customerOrderNo;
|
|
394
527
|
if (request.fpxTrackNo)
|
|
395
528
|
body.fpxTrackNo = request.fpxTrackNo;
|
|
529
|
+
if (request.queryDateType)
|
|
530
|
+
body.queryDateType = request.queryDateType;
|
|
396
531
|
if (request.queryStartDate)
|
|
397
532
|
body.queryStartDate = request.queryStartDate;
|
|
398
533
|
if (request.queryEndDate)
|
|
@@ -401,7 +536,7 @@ export class ApiClient {
|
|
|
401
536
|
body.pageNum = request.pageNum;
|
|
402
537
|
if (request.pageSize != null)
|
|
403
538
|
body.pageSize = request.pageSize;
|
|
404
|
-
return this.
|
|
539
|
+
return this.postJson(`${API_PREFIX}/problem/intercepted/list`, body, true);
|
|
405
540
|
}
|
|
406
541
|
// ==================== Service Center ====================
|
|
407
542
|
async listServiceOrderAftersale(request) {
|
|
@@ -422,7 +557,7 @@ export class ApiClient {
|
|
|
422
557
|
body.pageNum = request.pageNum;
|
|
423
558
|
if (request.pageSize != null)
|
|
424
559
|
body.pageSize = request.pageSize;
|
|
425
|
-
return this.
|
|
560
|
+
return this.postJson(`${API_PREFIX}/service-order/aftersale/list`, body, true);
|
|
426
561
|
}
|
|
427
562
|
async listServiceOrderCheck(request) {
|
|
428
563
|
const body = {};
|
|
@@ -440,7 +575,7 @@ export class ApiClient {
|
|
|
440
575
|
body.pageNum = request.pageNum;
|
|
441
576
|
if (request.pageSize != null)
|
|
442
577
|
body.pageSize = request.pageSize;
|
|
443
|
-
return this.
|
|
578
|
+
return this.postJson(`${API_PREFIX}/service-order/check/list`, body, true);
|
|
444
579
|
}
|
|
445
580
|
async listServiceOrderComplaint(request) {
|
|
446
581
|
const body = {};
|
|
@@ -458,7 +593,7 @@ export class ApiClient {
|
|
|
458
593
|
body.pageNum = request.pageNum;
|
|
459
594
|
if (request.pageSize != null)
|
|
460
595
|
body.pageSize = request.pageSize;
|
|
461
|
-
return this.
|
|
596
|
+
return this.postJson(`${API_PREFIX}/service-order/complaint/list`, body, true);
|
|
462
597
|
}
|
|
463
598
|
async getServiceOrderCheckDetail(serviceNo) {
|
|
464
599
|
const body = { serviceNo };
|
|
@@ -512,7 +647,7 @@ export class ApiClient {
|
|
|
512
647
|
body.pageNum = pageNum;
|
|
513
648
|
if (pageSize != null)
|
|
514
649
|
body.pageSize = pageSize;
|
|
515
|
-
return this.
|
|
650
|
+
return this.postJson(`${API_PREFIX}/finance/fee/daily/list`, body, true);
|
|
516
651
|
}
|
|
517
652
|
async getUnbilledFeeDetail(businessNo, currencyCode) {
|
|
518
653
|
const body = { businessNo, currencyCode };
|
|
@@ -542,7 +677,7 @@ export class ApiClient {
|
|
|
542
677
|
body.pageNum = pageNum;
|
|
543
678
|
if (pageSize != null)
|
|
544
679
|
body.pageSize = pageSize;
|
|
545
|
-
return this.
|
|
680
|
+
return this.postJson(`${API_PREFIX}/finance/recharge/list`, body, true);
|
|
546
681
|
}
|
|
547
682
|
async listOfflineRechargeRecord(businessSystem, currency, tradeNo, status, startDate, endDate, pageNum, pageSize) {
|
|
548
683
|
const body = {};
|
|
@@ -562,7 +697,7 @@ export class ApiClient {
|
|
|
562
697
|
body.pageNum = pageNum;
|
|
563
698
|
if (pageSize != null)
|
|
564
699
|
body.pageSize = pageSize;
|
|
565
|
-
return this.
|
|
700
|
+
return this.postJson(`${API_PREFIX}/finance/recharge/offline/list`, body, true);
|
|
566
701
|
}
|
|
567
702
|
async getBilledFeeDetail(businessNo) {
|
|
568
703
|
const body = { businessNo };
|
|
@@ -697,6 +832,33 @@ export class ApiClient {
|
|
|
697
832
|
async listProblemNotifyType() {
|
|
698
833
|
return this.get(`${API_PREFIX}/problem/notify-type/list`, {}, true);
|
|
699
834
|
}
|
|
835
|
+
// ==================== Custody (异常托管) ====================
|
|
836
|
+
/**
|
|
837
|
+
* 查询指定异常单支持的回复方式(走货/退件/改带电/改产品等)。
|
|
838
|
+
* bportal 端点使用 @Body,因此走 postJson。
|
|
839
|
+
*/
|
|
840
|
+
async getAbnormalityHelp(reasonCode, orderNo) {
|
|
841
|
+
return this.postJson(`${API_PREFIX}/custody/abnormality-help`, { reasonCode, orderNo }, true);
|
|
842
|
+
}
|
|
843
|
+
/**
|
|
844
|
+
* 查询指定异常单可更换的带电产品列表及差价。
|
|
845
|
+
*/
|
|
846
|
+
async queryElectricProducts(orderNo) {
|
|
847
|
+
return this.postJson(`${API_PREFIX}/custody/electric-products`, { orderNo }, true);
|
|
848
|
+
}
|
|
849
|
+
/**
|
|
850
|
+
* 获取 AI 推荐的异常处理建议(含推荐产品及差价)。
|
|
851
|
+
*/
|
|
852
|
+
async getAIAbnormalSuggest(orderNo, reasonCode) {
|
|
853
|
+
return this.postJson(`${API_PREFIX}/custody/ai-suggest`, { orderNo, reasonCode }, true);
|
|
854
|
+
}
|
|
855
|
+
/**
|
|
856
|
+
* 提交改带电或改产品方案。
|
|
857
|
+
* 写操作——会真实改变订单的物流产品。
|
|
858
|
+
*/
|
|
859
|
+
async submitProductChange(orderNo, pkCode) {
|
|
860
|
+
return this.postJson(`${API_PREFIX}/custody/change-product`, { orderNo, pkCode }, true);
|
|
861
|
+
}
|
|
700
862
|
// ==================== Platform Order (平台拉单) ====================
|
|
701
863
|
async listSellerAccounts(pageNum, pageSize) {
|
|
702
864
|
const body = {};
|
|
@@ -717,12 +879,18 @@ export class ApiClient {
|
|
|
717
879
|
body.pageSize = pageSize;
|
|
718
880
|
return this.post(`${API_PREFIX}/platformOrder/syncRecord/list`, body, true);
|
|
719
881
|
}
|
|
720
|
-
async listPlatformOrders(status, keyword, pageNum, pageSize) {
|
|
882
|
+
async listPlatformOrders(status, keyword, filters, pageNum, pageSize) {
|
|
721
883
|
const body = {};
|
|
722
884
|
if (status != null)
|
|
723
885
|
body.status = status;
|
|
724
886
|
if (keyword)
|
|
725
887
|
body.keyword = keyword;
|
|
888
|
+
if (filters) {
|
|
889
|
+
for (const [k, v] of Object.entries(filters)) {
|
|
890
|
+
if (v)
|
|
891
|
+
body[k] = v;
|
|
892
|
+
}
|
|
893
|
+
}
|
|
726
894
|
if (pageNum != null)
|
|
727
895
|
body.pageNum = pageNum;
|
|
728
896
|
if (pageSize != null)
|
|
@@ -748,7 +916,7 @@ export class ApiClient {
|
|
|
748
916
|
body.bankCard = request.bankCard;
|
|
749
917
|
if (request.isAgent != null)
|
|
750
918
|
body.isAgent = request.isAgent;
|
|
751
|
-
return this.
|
|
919
|
+
return this.postJson(`${API_PREFIX}/onboarding/indiv-auth`, body, true);
|
|
752
920
|
}
|
|
753
921
|
async checkAuthCode(request) {
|
|
754
922
|
const body = {
|
|
@@ -759,18 +927,38 @@ export class ApiClient {
|
|
|
759
927
|
body.authType = request.authType;
|
|
760
928
|
if (request.isAgent != null)
|
|
761
929
|
body.isAgent = request.isAgent;
|
|
762
|
-
return this.
|
|
930
|
+
return this.postJson(`${API_PREFIX}/onboarding/check-auth-code`, body, true);
|
|
763
931
|
}
|
|
932
|
+
/**
|
|
933
|
+
* 企业实名认证:服务端把企业证件、法人、认证方式与完整注册地址一并校验,
|
|
934
|
+
* 因此这里整体组装后再发出,缺字段时由命令层提前拦截而不是靠服务端报错。
|
|
935
|
+
*/
|
|
764
936
|
async startOrganRealNameAuth(request) {
|
|
765
937
|
const body = {
|
|
766
938
|
name: request.name,
|
|
767
939
|
certNumber: request.certNumber,
|
|
940
|
+
certType: request.certType,
|
|
941
|
+
authType: request.authType,
|
|
942
|
+
agentAccountId: request.agentAccountId,
|
|
943
|
+
legalName: request.legalName,
|
|
944
|
+
countryCode: request.countryCode,
|
|
945
|
+
alpha2Code: request.alpha2Code,
|
|
946
|
+
country: request.country,
|
|
947
|
+
state: request.state,
|
|
948
|
+
city: request.city,
|
|
949
|
+
county: request.county,
|
|
950
|
+
address: request.address,
|
|
768
951
|
};
|
|
769
|
-
|
|
770
|
-
|
|
771
|
-
|
|
772
|
-
|
|
773
|
-
|
|
952
|
+
// 服务端 certTypeEnum 与 certType 是同一含义的两种写法,由 certType 推导可
|
|
953
|
+
// 避免两者互相矛盾;超出枚举范围时留空,服务端允许 null。
|
|
954
|
+
const certTypeEnum = request.certTypeEnum ?? ORGAN_CERT_TYPE_ENUMS[request.certType];
|
|
955
|
+
if (certTypeEnum)
|
|
956
|
+
body.certTypeEnum = certTypeEnum;
|
|
957
|
+
if (request.legalCertNumber)
|
|
958
|
+
body.legalCertNumber = request.legalCertNumber;
|
|
959
|
+
if (request.legalCertType != null)
|
|
960
|
+
body.legalCertType = request.legalCertType;
|
|
961
|
+
return this.postJson(`${API_PREFIX}/onboarding/organ-auth`, body, true);
|
|
774
962
|
}
|
|
775
963
|
async openBrandAndApplyContract(request) {
|
|
776
964
|
const body = {
|
|
@@ -792,7 +980,7 @@ export class ApiClient {
|
|
|
792
980
|
body.county = request.county;
|
|
793
981
|
if (request.cLegalName)
|
|
794
982
|
body.cLegalName = request.cLegalName;
|
|
795
|
-
return this.
|
|
983
|
+
return this.postJson(`${API_PREFIX}/onboarding/open-brand`, body, true);
|
|
796
984
|
}
|
|
797
985
|
async authSaveGAT(request) {
|
|
798
986
|
const body = {
|
|
@@ -829,11 +1017,7 @@ export class ApiClient {
|
|
|
829
1017
|
body.countyCode = request.countyCode;
|
|
830
1018
|
if (request.address)
|
|
831
1019
|
body.address = request.address;
|
|
832
|
-
return this.
|
|
833
|
-
}
|
|
834
|
-
/** amount is in cents — the backend rejects yuan. */
|
|
835
|
-
async checkRemitAmount(flowId, amount) {
|
|
836
|
-
return this.post(`${API_PREFIX}/onboarding/check-remit`, { flowId, amount }, true);
|
|
1020
|
+
return this.postJson(`${API_PREFIX}/onboarding/gat-auth`, body, true);
|
|
837
1021
|
}
|
|
838
1022
|
async queryOnboardingProgress() {
|
|
839
1023
|
return this.get(`${API_PREFIX}/onboarding/progress`, {}, true);
|
|
@@ -858,8 +1042,12 @@ export class ApiClient {
|
|
|
858
1042
|
body.pageSize = pageSize;
|
|
859
1043
|
return this.post(`${API_PREFIX}/onboarding/contracts`, body, true);
|
|
860
1044
|
}
|
|
861
|
-
|
|
862
|
-
|
|
1045
|
+
/**
|
|
1046
|
+
* `status` 必填,取自 `contract list`:服务端会重新查合同详情并以实际状态为准,
|
|
1047
|
+
* 详情未返回状态时用它兜底,所以状态码只能来自列表,不能猜。
|
|
1048
|
+
*/
|
|
1049
|
+
async getContractSignUrl(contractCode, status) {
|
|
1050
|
+
return this.post(`${API_PREFIX}/onboarding/contract-sign-url`, { contractCode, status }, true);
|
|
863
1051
|
}
|
|
864
1052
|
}
|
|
865
1053
|
//# sourceMappingURL=api-client.js.map
|