cbs-4px-merchant-cli 0.0.9 → 0.0.12

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.
Files changed (55) hide show
  1. package/README.4px.md +5 -5
  2. package/README.cainiao.md +5 -5
  3. package/README.md +5 -5
  4. package/dist/cli.js +150 -32
  5. package/dist/cli.js.map +1 -1
  6. package/dist/commands/address.d.ts +7 -1
  7. package/dist/commands/address.js +29 -10
  8. package/dist/commands/address.js.map +1 -1
  9. package/dist/commands/auth.d.ts +1 -0
  10. package/dist/commands/auth.js +87 -0
  11. package/dist/commands/auth.js.map +1 -1
  12. package/dist/commands/config.js +120 -20
  13. package/dist/commands/config.js.map +1 -1
  14. package/dist/commands/onboarding.d.ts +21 -7
  15. package/dist/commands/onboarding.js +95 -18
  16. package/dist/commands/onboarding.js.map +1 -1
  17. package/dist/commands/order.d.ts +38 -6
  18. package/dist/commands/order.js +251 -35
  19. package/dist/commands/order.js.map +1 -1
  20. package/dist/commands/platform.d.ts +50 -0
  21. package/dist/commands/platform.js +108 -6
  22. package/dist/commands/platform.js.map +1 -1
  23. package/dist/commands/product.d.ts +3 -0
  24. package/dist/commands/product.js +3 -0
  25. package/dist/commands/product.js.map +1 -1
  26. package/dist/commands/update.js +124 -3
  27. package/dist/commands/update.js.map +1 -1
  28. package/dist/errors.d.ts +29 -1
  29. package/dist/errors.js +11 -1
  30. package/dist/errors.js.map +1 -1
  31. package/dist/services/api-client.d.ts +49 -13
  32. package/dist/services/api-client.js +231 -45
  33. package/dist/services/api-client.js.map +1 -1
  34. package/dist/services/binary-source.d.ts +30 -0
  35. package/dist/services/binary-source.js +88 -0
  36. package/dist/services/binary-source.js.map +1 -0
  37. package/dist/services/binary-update.d.ts +62 -0
  38. package/dist/services/binary-update.js +179 -0
  39. package/dist/services/binary-update.js.map +1 -0
  40. package/dist/services/install-detector.d.ts +13 -1
  41. package/dist/services/install-detector.js +20 -1
  42. package/dist/services/install-detector.js.map +1 -1
  43. package/dist/types/index.d.ts +199 -12
  44. package/dist/utils/run-command.d.ts +6 -0
  45. package/dist/utils/run-command.js +13 -0
  46. package/dist/utils/run-command.js.map +1 -1
  47. package/package.json +7 -1
  48. package/skill/SKILL.md +14 -12
  49. package/skill/package.json +1 -1
  50. package/skill/reference/auth.md +20 -1
  51. package/skill/reference/index.md +3 -3
  52. package/skill/reference/onboarding.md +121 -52
  53. package/skill/reference/order.md +216 -36
  54. package/skill/reference/platform.md +85 -2
  55. package/skill/reference/product.md +3 -0
@@ -1,5 +1,5 @@
1
1
  import { ConfigManager } from './config-manager.js';
2
- import type { GlobalOptions, TrackDetailDTO, LabelPrintDTO, OrderDetailResp, ProductRecommendDTO, ProductRecommendRequest, ClaimListResp, ClaimListRequest, OrderListRequest, OrderListResp, OrderAddressResp, CountrySearchResp, ProductSearchResp, TrackSubscriptionResp, ProductListResp, ProductDetailResp, FreightTrialResp, ProblemListRequest, ProblemListResp, AbnormalSuggestRequest, BatchAbnormalSuggestResponse, NotifyProblemListResp, ArrearOrderListResp, ServiceRepairOrderListRequest, RepairOrderListResp, ServiceOrderListRequest, ServiceOrderListResp, ServiceDetailResp, HandleRecordListResp, DssClaimDetailResp, ClaimReasonListResp, AccountBalanceResp, BillListResp, DailyFeeListResp, UnbilledDetailResp, UnbilledListResp, RechargeRecordListResp, TransferRecordListResp, FeeDetailResp, MaterialApplyListResp, MaterialDetailResp, MaterialQuotaResp, CollectAddressListResp, NoticeListResp, NoticeDetailResp, MessageListResp, MessageDetailResp, UnreadMessageCountResp, CargoKindListResp, CommodityListResp, HsCodeListResp, CustomerDeclareResp, FrozenRecordListResp, NotifyTypeListResp, SellerAccountListResp, PlatformOrderSyncResp, SyncOrderRecordListResp, PlatformOrderListResp, PlatformOrderDetailResp, IndivAuthRequest, CheckAuthCodeRequest, OrganAuthRequest, OpenBrandRequest, GATAuthRequest, OnboardingProgressResp, AuthScheduleResp, CustomerTypeItem, BrandAndAuthItem, ContractListResp, CreateOrderRequest, CreateOrderResp, EditOrderRequest, EditOrderResp, ForecastOrderResp, CancelOrderResp, InterceptOrderResp, AbnormalityHelpResp, ElectricProductResp, AIAbnormalSuggestResp } from '../types/index.js';
2
+ import type { GlobalOptions, TrackDetailDTO, LabelPrintDTO, OrderDetailResp, OrderFieldRulesResp, ProductRecommendDTO, ProductRecommendRequest, ClaimListResp, ClaimListRequest, OrderListRequest, OrderListResp, OrderAddressResp, AddressBookListRequest, CountrySearchResp, ProductSearchResp, TrackSubscriptionResp, ProductListResp, ProductDetailResp, FreightTrialResp, ProblemListRequest, ProblemListResp, AbnormalSuggestRequest, BatchAbnormalSuggestResponse, NotifyProblemListResp, ArrearOrderListResp, ServiceRepairOrderListRequest, RepairOrderListResp, ServiceOrderListRequest, ServiceOrderListResp, ServiceDetailResp, HandleRecordListResp, DssClaimDetailResp, ClaimReasonListResp, AccountBalanceResp, BillListResp, DailyFeeListResp, UnbilledDetailResp, UnbilledListResp, RechargeRecordListResp, TransferRecordListResp, FeeDetailResp, MaterialApplyListResp, MaterialDetailResp, MaterialQuotaResp, CollectAddressListResp, NoticeListResp, NoticeDetailResp, MessageListResp, MessageDetailResp, UnreadMessageCountResp, CargoKindListResp, CommodityListResp, HsCodeListResp, CustomerDeclareResp, FrozenRecordListResp, NotifyTypeListResp, SellerAccountListResp, PlatformOrderSyncResp, SyncOrderRecordListResp, PlatformOrderListResp, PlatformOrderDetailResp, IndivAuthRequest, CheckAuthCodeRequest, OrganAuthRequest, OpenBrandRequest, GATAuthRequest, OnboardingProgressResp, AuthScheduleResp, CustomerTypeItem, BrandAndAuthItem, ContractListResp, CreateOrderRequest, CreateOrderResp, EditOrderRequest, EditOrderResp, ForecastOrderResp, CancelOrderResp, InterceptOrderResp, AbnormalityHelpResp, ElectricProductResp, AIAbnormalSuggestResp, PlatformOrderUpdateResp, PlatformOrderPushFailure } from '../types/index.js';
3
3
  export declare class ApiClient {
4
4
  private readonly config;
5
5
  private readonly verbose;
@@ -10,14 +10,23 @@ export declare class ApiClient {
10
10
  /** 返回 N 天前的日期 yyyy-MM-dd,与 bportal MCP Server 的 defaultStartDate 对齐 */
11
11
  private recentDate;
12
12
  private createHttp;
13
+ /**
14
+ * Uses the AgentZ access token only to mint the merchant API Key. The token
15
+ * must never be persisted, returned, or printed because it belongs to the
16
+ * host Agent client rather than this CLI.
17
+ */
18
+ generateAgentzApiKey(accessToken: string): Promise<string>;
13
19
  private get;
14
20
  private post;
15
21
  /**
16
22
  * 发送 JSON body 的 POST。
17
23
  *
18
- * 仅用于后端以 `@Body` 绑定的接口(当前为 `order create` 和
19
- * `order edit`)。其他接口必须继续调用 `post()`,因为 Solon 的
20
- * `@Param` 从表单取值,发送 JSON body 会返回 400。
24
+ * 用于后端以 `@Body` 绑定的接口(order create/edit、problem order list、
25
+ * custody 全部、onboarding 的实名与开通品牌接口)。后端的 `@Body` 解析器直接
26
+ * 对原始 body 做 `JSON.parseObject`,收到表单串会抛
27
+ * `Failed to parse JSON body as ...`,因此这类接口不能走 `post()`。
28
+ * 其余接口必须继续调用 `post()`,因为 Solon 的 `@Param` 从表单取值,
29
+ * 发送 JSON body 会返回 400。
21
30
  */
22
31
  private postJson;
23
32
  /** 生成 JSON body 请求的 dry-run 预览,不发送网络请求。 */
@@ -31,16 +40,27 @@ export declare class ApiClient {
31
40
  listTrackSubscriptionByProduct(productCode?: string, countryCode?: string, pageNum?: number, pageSize?: number): Promise<TrackSubscriptionResp>;
32
41
  getLabelPrint(orderNo: string): Promise<LabelPrintDTO>;
33
42
  getOrderDetail(orderNo: string): Promise<OrderDetailResp>;
43
+ /**
44
+ * 查询下单字段规则(必填性的权威来源)。
45
+ *
46
+ * 必填由规则库按 (产品, 目的国, 客户) 配置,同一字段在不同产品下结论不同,
47
+ * 因此建单前必须查询而不能沿用本地清单。
48
+ */
49
+ getOrderFieldRules(productCode: string, country: string, requiredOnly?: boolean): Promise<OrderFieldRulesResp>;
34
50
  listOrders(request: OrderListRequest): Promise<OrderListResp>;
35
- listAddressBook(): Promise<OrderAddressResp>;
51
+ listAddressBook(request: AddressBookListRequest): Promise<OrderAddressResp>;
36
52
  searchDestinationCountry(key: string, productCode?: string): Promise<CountrySearchResp>;
37
53
  /** JSON body,`status: 'D'` 表示保存草稿而不预报。 */
38
54
  createOrder(request: CreateOrderRequest): Promise<CreateOrderResp>;
39
55
  /** JSON body;仅草稿和已取消订单可编辑。 */
40
56
  editOrder(request: EditOrderRequest): Promise<EditOrderResp>;
41
- forecastOrder(orderIds: string): Promise<ForecastOrderResp>;
42
- cancelOrder(orderIds: string, cancelReason: string): Promise<CancelOrderResp>;
43
- interceptOrder(orderIds: string): Promise<InterceptOrderResp>;
57
+ /** 草稿转预报。传客户订单号,后端按单号反查主键。 */
58
+ forecastOrder(orderNos: string): Promise<ForecastOrderResp>;
59
+ /** 取消订单。传单号,后端按单号反查主键。 */
60
+ cancelOrder(orderNos: string, cancelReason: string): Promise<CancelOrderResp>;
61
+ /** 申请拦截。传单号,后端按单号反查主键。 */
62
+ interceptOrder(orderNos: string): Promise<InterceptOrderResp>;
63
+ uninterceptOrder(orderNos: string): Promise<InterceptOrderResp>;
44
64
  searchProduct(key: string, countryCode?: string): Promise<ProductSearchResp>;
45
65
  getProductRecommend(request: ProductRecommendRequest): Promise<ProductRecommendDTO>;
46
66
  listAvailableProducts(country: string, startCity?: string): Promise<ProductListResp>;
@@ -106,21 +126,37 @@ export declare class ApiClient {
106
126
  listSellerAccounts(pageNum?: number, pageSize?: number): Promise<SellerAccountListResp>;
107
127
  syncPlatformOrders(sellerAccountId: string, timeFrom: string, timeTo: string): Promise<PlatformOrderSyncResp>;
108
128
  listPlatformSyncRecords(pageNum?: number, pageSize?: number): Promise<SyncOrderRecordListResp>;
109
- listPlatformOrders(status?: number, keyword?: string, pageNum?: number, pageSize?: number): Promise<PlatformOrderListResp>;
110
- pushPlatformOrders(ids: string): Promise<unknown>;
129
+ listPlatformOrders(status?: number, keyword?: string, filters?: Record<string, string | undefined>, pageNum?: number, pageSize?: number): Promise<PlatformOrderListResp>;
130
+ updatePlatformOrders(ids: string[], fields?: Record<string, string | undefined>): Promise<PlatformOrderUpdateResp>;
131
+ /**
132
+ * 推送平台订单。返回的是**失败明细数组**,空数组即全部成功。
133
+ * 已推送的单会被后端按状态拒绝并出现在返回里(防重复建物流单)。
134
+ */
135
+ pushPlatformOrders(ids: string): Promise<PlatformOrderPushFailure[] | null>;
111
136
  getPlatformOrderDetail(id: string): Promise<PlatformOrderDetailResp>;
112
137
  /** Returns the flowId that `checkAuthCode` needs. */
113
138
  startIndivRealNameAuth(request: IndivAuthRequest): Promise<string>;
114
139
  checkAuthCode(request: CheckAuthCodeRequest): Promise<string>;
140
+ /**
141
+ * 企业实名认证:服务端把企业证件、法人、认证方式与完整注册地址一并校验,
142
+ * 因此这里整体组装后再发出,缺字段时由命令层提前拦截而不是靠服务端报错。
143
+ */
115
144
  startOrganRealNameAuth(request: OrganAuthRequest): Promise<string>;
116
145
  openBrandAndApplyContract(request: OpenBrandRequest): Promise<string>;
146
+ /**
147
+ * 重复入驻场景下通知当前客户对应的销售(钉钉卡片)。
148
+ * 客户编码由服务端从 API Key 上下文取,通知内容服务端写死,本接口无入参、无返回数据。
149
+ */
150
+ notifyRepeatEnterSaler(): Promise<void>;
117
151
  authSaveGAT(request: GATAuthRequest): Promise<string>;
118
- /** amount is in cents — the backend rejects yuan. */
119
- checkRemitAmount(flowId: string, amount: number): Promise<string>;
120
152
  queryOnboardingProgress(): Promise<OnboardingProgressResp>;
121
153
  queryAuthSchedule(): Promise<AuthScheduleResp>;
122
154
  queryCustomerType(): Promise<CustomerTypeItem[]>;
123
155
  queryBrandAndAuth(customerType?: string): Promise<BrandAndAuthItem[]>;
124
156
  getContractList(pageNum?: number, pageSize?: number): Promise<ContractListResp>;
125
- getContractSignUrl(contractCode: string): Promise<string>;
157
+ /**
158
+ * `status` 必填,取自 `contract list`:服务端会重新查合同详情并以实际状态为准,
159
+ * 详情未返回状态时用它兜底,所以状态码只能来自列表,不能猜。
160
+ */
161
+ getContractSignUrl(contractCode: string, status: number): Promise<string>;
126
162
  }
@@ -1,6 +1,35 @@
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
+ '/order/field/rules',
20
+ '/product-recommendation',
21
+ '/shipping-fee/calculate',
22
+ '/problem/list',
23
+ '/problem/suggestions',
24
+ '/problem/intercepted/list',
25
+ '/service/claim/order/list',
26
+ '/service-order/aftersale/list',
27
+ '/service-order/check/list',
28
+ '/service-order/complaint/list',
29
+ '/finance/fee/daily/list',
30
+ '/finance/recharge/list',
31
+ '/finance/recharge/offline/list',
32
+ ]);
4
33
  /**
5
34
  * Params whose values must never be echoed back to the terminal.
6
35
  *
@@ -10,13 +39,21 @@ const API_PREFIX = '/api/merchant/tools';
10
39
  * transcripts. Masking applies to the printed copy only — the request itself
11
40
  * still carries the real value.
12
41
  */
13
- const SENSITIVE_PARAMS = new Set(['certNumber', 'bankCard', 'authCode', 'mobile']);
42
+ const SENSITIVE_PARAMS = new Set(['certNumber', 'legalCertNumber', 'bankCard', 'authCode', 'mobile']);
14
43
  /**
15
44
  * 嵌套 JSON body 同样需要递归遮蔽敏感字段,否则订单的
16
45
  * `receiver.mobile`、`sender.phone` 会被 `--dry-run` / `--verbose`
17
46
  * 原样写入终端回滚区和平台日志。
18
47
  */
19
- const SENSITIVE_BODY_KEYS = new Set(['certNumber', 'bankCard', 'authCode', 'mobile', 'phone']);
48
+ const SENSITIVE_BODY_KEYS = new Set([
49
+ 'certNumber',
50
+ // 法人身份证号与企业证件号同级敏感,遗漏会让企业实名的 --dry-run 明文回显
51
+ 'legalCertNumber',
52
+ 'bankCard',
53
+ 'authCode',
54
+ 'mobile',
55
+ 'phone',
56
+ ]);
20
57
  function maskSensitive(params) {
21
58
  const out = {};
22
59
  for (const [k, v] of Object.entries(params)) {
@@ -44,6 +81,26 @@ function toForm(params) {
44
81
  }
45
82
  return form;
46
83
  }
84
+ /**
85
+ * 企业证件类型的数字值 → 枚举名,与后端 `OrganCertTypeEnum` 一一对应。
86
+ * 企业实名同时传 certType 与 certTypeEnum,两者不一致时以哪个为准并不确定,
87
+ * 所以 CLI 只收数字,枚举名统一从这里推导。
88
+ */
89
+ const ORGAN_CERT_TYPE_ENUMS = {
90
+ 0: 'CRED_ORG_USCC',
91
+ 1: 'CRED_ORG_CODE',
92
+ 2: 'CRED_ORG_REGCODE',
93
+ 3: 'CRED_ORG_BUSINESS_REGISTTATION_CODE',
94
+ 4: 'CRED_ORG_TAX_REGISTTATION_CODE',
95
+ 5: 'CRED_ORG_LEGAL_PERSON_CODE',
96
+ 6: 'CRED_ORG_ENT_LEGAL_PERSON_CODE',
97
+ 7: 'CRED_ORG_SOCIAL_REG_CODE',
98
+ 8: 'CRED_ORG_PRIVATE_NON_ENT_REG_CODE',
99
+ 9: 'CRED_ORG_FOREIGN_ENT_REG_CODE',
100
+ 10: 'CRED_ORG_GOV_APPROVAL',
101
+ 11: 'CODE_ORG_CUSTOM',
102
+ 12: 'CRED_ORG_UNKNOWN',
103
+ };
47
104
  export class ApiClient {
48
105
  config;
49
106
  verbose;
@@ -75,6 +132,37 @@ export class ApiClient {
75
132
  }
76
133
  return axios.create({ baseURL, headers, timeout: 15000 });
77
134
  }
135
+ /**
136
+ * Uses the AgentZ access token only to mint the merchant API Key. The token
137
+ * must never be persisted, returned, or printed because it belongs to the
138
+ * host Agent client rather than this CLI.
139
+ */
140
+ async generateAgentzApiKey(accessToken) {
141
+ const baseURL = await this.config.resolveBaseUrl();
142
+ const http = axios.create({
143
+ baseURL,
144
+ headers: {
145
+ 'Content-Type': 'application/json',
146
+ 'X-Source': 'cli',
147
+ Authorization: `Bearer ${accessToken}`,
148
+ },
149
+ timeout: 15000,
150
+ });
151
+ if (this.verbose) {
152
+ process.stderr.write(`> POST ${baseURL}${AGENTZ_API_KEY_GENERATE_PATH}\n`);
153
+ process.stderr.write('> Authorization: Bearer ****\n');
154
+ }
155
+ const res = await http.post(AGENTZ_API_KEY_GENERATE_PATH);
156
+ if (this.verbose) {
157
+ process.stderr.write(`< ${res.status} ${res.statusText}\n`);
158
+ }
159
+ const response = res.data;
160
+ const apiKey = response.data?.apiKey;
161
+ if (response.result !== 0 || !apiKey) {
162
+ throw new ApiError(response.code ?? 'AGENTZ_API_KEY_GENERATION_FAILED', response.message ?? 'AgentZ API Key 生成失败', '请确认 AgentZ 登录态有效后重试');
163
+ }
164
+ return apiKey;
165
+ }
78
166
  async get(path, params, withAuth) {
79
167
  if (this.dryRun) {
80
168
  const info = await this.dryRunInfo(path, params, withAuth);
@@ -96,11 +184,14 @@ export class ApiClient {
96
184
  }
97
185
  const resp = res.data;
98
186
  if (!resp.success) {
99
- throw new ApiError(resp.errCode, resp.errMsg, '请检查单号是否正确、API Key 是否有对应权限,或稍后重试');
187
+ throw new ApiError(resp.errCode, resp.errMsg, '请检查单号是否正确、API Key 是否有对应权限,或稍后重试', resp.data);
100
188
  }
101
189
  return resp.data;
102
190
  }
103
191
  async post(path, params, withAuth) {
192
+ if (JSON_BODY_PATHS.has(path.slice(API_PREFIX.length))) {
193
+ throw new BportalError(`${path} 在后端以 @Body 绑定,必须调用 postJson();用 post() 发表单会被兜成 SYSTEM_ERROR`, 'CLIENT_BUG', '这是 CLI 代码缺陷,请把该调用改为 postJson()');
194
+ }
104
195
  if (this.dryRun) {
105
196
  const info = await this.dryRunPostInfo(path, params, withAuth);
106
197
  console.log(JSON.stringify(info, null, 2));
@@ -125,16 +216,19 @@ export class ApiClient {
125
216
  }
126
217
  const resp = res.data;
127
218
  if (!resp.success) {
128
- throw new ApiError(resp.errCode, resp.errMsg, '请检查参数是否正确、API Key 是否有对应权限,或稍后重试');
219
+ throw new ApiError(resp.errCode, resp.errMsg, '请检查参数是否正确、API Key 是否有对应权限,或稍后重试', resp.data);
129
220
  }
130
221
  return resp.data;
131
222
  }
132
223
  /**
133
224
  * 发送 JSON body 的 POST。
134
225
  *
135
- * 仅用于后端以 `@Body` 绑定的接口(当前为 `order create` 和
136
- * `order edit`)。其他接口必须继续调用 `post()`,因为 Solon 的
137
- * `@Param` 从表单取值,发送 JSON body 会返回 400。
226
+ * 用于后端以 `@Body` 绑定的接口(order create/edit、problem order list、
227
+ * custody 全部、onboarding 的实名与开通品牌接口)。后端的 `@Body` 解析器直接
228
+ * 对原始 body 做 `JSON.parseObject`,收到表单串会抛
229
+ * `Failed to parse JSON body as ...`,因此这类接口不能走 `post()`。
230
+ * 其余接口必须继续调用 `post()`,因为 Solon 的 `@Param` 从表单取值,
231
+ * 发送 JSON body 会返回 400。
138
232
  */
139
233
  async postJson(path, body, withAuth) {
140
234
  if (this.dryRun) {
@@ -159,7 +253,7 @@ export class ApiClient {
159
253
  }
160
254
  const resp = res.data;
161
255
  if (!resp.success) {
162
- throw new ApiError(resp.errCode, resp.errMsg, '请检查订单字段是否完整、产品与目的国是否匹配,或稍后重试');
256
+ throw new ApiError(resp.errCode, resp.errMsg, '请检查订单字段是否完整、产品与目的国是否匹配,或稍后重试', resp.data);
163
257
  }
164
258
  return resp.data;
165
259
  }
@@ -226,6 +320,18 @@ export class ApiClient {
226
320
  async getOrderDetail(orderNo) {
227
321
  return this.get(`${API_PREFIX}/order/detail`, { orderNo }, true);
228
322
  }
323
+ /**
324
+ * 查询下单字段规则(必填性的权威来源)。
325
+ *
326
+ * 必填由规则库按 (产品, 目的国, 客户) 配置,同一字段在不同产品下结论不同,
327
+ * 因此建单前必须查询而不能沿用本地清单。
328
+ */
329
+ async getOrderFieldRules(productCode, country, requiredOnly) {
330
+ const body = { productCode, country };
331
+ if (requiredOnly)
332
+ body.requiredOnly = true;
333
+ return this.postJson(`${API_PREFIX}/order/field/rules`, body, true);
334
+ }
229
335
  async listOrders(request) {
230
336
  const body = {};
231
337
  if (request.statusName)
@@ -234,6 +340,8 @@ export class ApiClient {
234
340
  body.customerOrderNo = request.customerOrderNo;
235
341
  if (request.fpxTrackNo)
236
342
  body.fpxTrackNo = request.fpxTrackNo;
343
+ if (request.queryDateType)
344
+ body.queryDateType = request.queryDateType;
237
345
  if (request.queryStartDate)
238
346
  body.queryStartDate = request.queryStartDate;
239
347
  if (request.queryEndDate)
@@ -242,14 +350,37 @@ export class ApiClient {
242
350
  body.productCode = request.productCode;
243
351
  if (request.destinationCountry)
244
352
  body.destinationCountry = request.destinationCountry;
353
+ if (request.consigneeName)
354
+ body.consigneeName = request.consigneeName;
355
+ if (request.buyerId)
356
+ body.buyerId = request.buyerId;
357
+ if (request.isPrint)
358
+ body.isPrint = request.isPrint;
359
+ if (request.odaConfirm)
360
+ body.odaConfirm = request.odaConfirm;
361
+ if (request.interceptStatus)
362
+ body.interceptStatus = request.interceptStatus;
363
+ if (request.changeNoStatus)
364
+ body.changeNoStatus = request.changeNoStatus;
365
+ if (request.isHistory)
366
+ body.isHistory = request.isHistory;
245
367
  if (request.pageNum != null)
246
368
  body.pageNum = request.pageNum;
247
369
  if (request.pageSize != null)
248
370
  body.pageSize = request.pageSize;
249
- return this.post(`${API_PREFIX}/order/list`, body, true);
371
+ return this.postJson(`${API_PREFIX}/order/list`, body, true);
250
372
  }
251
- async listAddressBook() {
252
- return this.get(`${API_PREFIX}/address-book/list`, {}, true);
373
+ async listAddressBook(request) {
374
+ const body = {};
375
+ if (request.addressType)
376
+ body.addressType = request.addressType;
377
+ if (request.keyword)
378
+ body.keyword = request.keyword;
379
+ if (request.pageNum != null)
380
+ body.pageNum = request.pageNum;
381
+ if (request.pageSize != null)
382
+ body.pageSize = request.pageSize;
383
+ return this.post(`${API_PREFIX}/address-book/list`, body, true);
253
384
  }
254
385
  async searchDestinationCountry(key, productCode) {
255
386
  const body = { key };
@@ -266,14 +397,20 @@ export class ApiClient {
266
397
  async editOrder(request) {
267
398
  return this.postJson(`${API_PREFIX}/order/edit`, request, true);
268
399
  }
269
- async forecastOrder(orderIds) {
270
- return this.post(`${API_PREFIX}/order/forecast`, { orderIds }, true);
400
+ /** 草稿转预报。传客户订单号,后端按单号反查主键。 */
401
+ async forecastOrder(orderNos) {
402
+ return this.post(`${API_PREFIX}/order/forecast`, { orderNos }, true);
403
+ }
404
+ /** 取消订单。传单号,后端按单号反查主键。 */
405
+ async cancelOrder(orderNos, cancelReason) {
406
+ return this.post(`${API_PREFIX}/order/cancel`, { orderNos, cancelReason }, true);
271
407
  }
272
- async cancelOrder(orderIds, cancelReason) {
273
- return this.post(`${API_PREFIX}/order/cancel`, { orderIds, cancelReason }, true);
408
+ /** 申请拦截。传单号,后端按单号反查主键。 */
409
+ async interceptOrder(orderNos) {
410
+ return this.post(`${API_PREFIX}/order/intercept`, { orderNos }, true);
274
411
  }
275
- async interceptOrder(orderIds) {
276
- return this.post(`${API_PREFIX}/order/intercept`, { orderIds }, true);
412
+ async uninterceptOrder(orderNos) {
413
+ return this.post(`${API_PREFIX}/order/unintercept`, { orderNos }, true);
277
414
  }
278
415
  async searchProduct(key, countryCode) {
279
416
  const body = { key };
@@ -294,7 +431,7 @@ export class ApiClient {
294
431
  body.isBattery = request.isBattery;
295
432
  if (request.declareValue != null)
296
433
  body.declareValue = request.declareValue;
297
- return this.post(`${API_PREFIX}/product-recommendation`, body, true);
434
+ return this.postJson(`${API_PREFIX}/product-recommendation`, body, true);
298
435
  }
299
436
  async listAvailableProducts(country, startCity) {
300
437
  const body = { country };
@@ -322,7 +459,7 @@ export class ApiClient {
322
459
  body.isBattery = request.isBattery;
323
460
  if (request.declareValue != null)
324
461
  body.declareValue = request.declareValue;
325
- return this.post(`${API_PREFIX}/shipping-fee/calculate`, body, true);
462
+ return this.postJson(`${API_PREFIX}/shipping-fee/calculate`, body, true);
326
463
  }
327
464
  async getEstimatedDeliveryTime(countryCode, productCode) {
328
465
  return this.get(`${API_PREFIX}/estimated-delivery-time`, { countryCode, productCode }, true);
@@ -342,7 +479,7 @@ export class ApiClient {
342
479
  body.pageNum = request.pageNum;
343
480
  if (request.pageSize != null)
344
481
  body.pageSize = request.pageSize;
345
- return this.post(`${API_PREFIX}/service/claim/order/list`, body, true);
482
+ return this.postJson(`${API_PREFIX}/service/claim/order/list`, body, true);
346
483
  }
347
484
  // ==================== Problem / Abnormal ====================
348
485
  async listProblemOrder(request) {
@@ -368,7 +505,7 @@ export class ApiClient {
368
505
  body.items = JSON.stringify(request.items);
369
506
  if (request.orderNoItems)
370
507
  body.orderNoItems = request.orderNoItems.join(',');
371
- return this.post(`${API_PREFIX}/problem/suggestions`, body, true);
508
+ return this.postJson(`${API_PREFIX}/problem/suggestions`, body, true);
372
509
  }
373
510
  async listProblemNotify(pageNum, pageSize) {
374
511
  const body = {};
@@ -402,6 +539,8 @@ export class ApiClient {
402
539
  body.customerOrderNo = request.customerOrderNo;
403
540
  if (request.fpxTrackNo)
404
541
  body.fpxTrackNo = request.fpxTrackNo;
542
+ if (request.queryDateType)
543
+ body.queryDateType = request.queryDateType;
405
544
  if (request.queryStartDate)
406
545
  body.queryStartDate = request.queryStartDate;
407
546
  if (request.queryEndDate)
@@ -410,7 +549,7 @@ export class ApiClient {
410
549
  body.pageNum = request.pageNum;
411
550
  if (request.pageSize != null)
412
551
  body.pageSize = request.pageSize;
413
- return this.post(`${API_PREFIX}/problem/intercepted/list`, body, true);
552
+ return this.postJson(`${API_PREFIX}/problem/intercepted/list`, body, true);
414
553
  }
415
554
  // ==================== Service Center ====================
416
555
  async listServiceOrderAftersale(request) {
@@ -431,7 +570,7 @@ export class ApiClient {
431
570
  body.pageNum = request.pageNum;
432
571
  if (request.pageSize != null)
433
572
  body.pageSize = request.pageSize;
434
- return this.post(`${API_PREFIX}/service-order/aftersale/list`, body, true);
573
+ return this.postJson(`${API_PREFIX}/service-order/aftersale/list`, body, true);
435
574
  }
436
575
  async listServiceOrderCheck(request) {
437
576
  const body = {};
@@ -449,7 +588,7 @@ export class ApiClient {
449
588
  body.pageNum = request.pageNum;
450
589
  if (request.pageSize != null)
451
590
  body.pageSize = request.pageSize;
452
- return this.post(`${API_PREFIX}/service-order/check/list`, body, true);
591
+ return this.postJson(`${API_PREFIX}/service-order/check/list`, body, true);
453
592
  }
454
593
  async listServiceOrderComplaint(request) {
455
594
  const body = {};
@@ -467,7 +606,7 @@ export class ApiClient {
467
606
  body.pageNum = request.pageNum;
468
607
  if (request.pageSize != null)
469
608
  body.pageSize = request.pageSize;
470
- return this.post(`${API_PREFIX}/service-order/complaint/list`, body, true);
609
+ return this.postJson(`${API_PREFIX}/service-order/complaint/list`, body, true);
471
610
  }
472
611
  async getServiceOrderCheckDetail(serviceNo) {
473
612
  const body = { serviceNo };
@@ -521,7 +660,7 @@ export class ApiClient {
521
660
  body.pageNum = pageNum;
522
661
  if (pageSize != null)
523
662
  body.pageSize = pageSize;
524
- return this.post(`${API_PREFIX}/finance/fee/daily/list`, body, true);
663
+ return this.postJson(`${API_PREFIX}/finance/fee/daily/list`, body, true);
525
664
  }
526
665
  async getUnbilledFeeDetail(businessNo, currencyCode) {
527
666
  const body = { businessNo, currencyCode };
@@ -551,7 +690,7 @@ export class ApiClient {
551
690
  body.pageNum = pageNum;
552
691
  if (pageSize != null)
553
692
  body.pageSize = pageSize;
554
- return this.post(`${API_PREFIX}/finance/recharge/list`, body, true);
693
+ return this.postJson(`${API_PREFIX}/finance/recharge/list`, body, true);
555
694
  }
556
695
  async listOfflineRechargeRecord(businessSystem, currency, tradeNo, status, startDate, endDate, pageNum, pageSize) {
557
696
  const body = {};
@@ -571,7 +710,7 @@ export class ApiClient {
571
710
  body.pageNum = pageNum;
572
711
  if (pageSize != null)
573
712
  body.pageSize = pageSize;
574
- return this.post(`${API_PREFIX}/finance/recharge/offline/list`, body, true);
713
+ return this.postJson(`${API_PREFIX}/finance/recharge/offline/list`, body, true);
575
714
  }
576
715
  async getBilledFeeDetail(businessNo) {
577
716
  const body = { businessNo };
@@ -753,18 +892,38 @@ export class ApiClient {
753
892
  body.pageSize = pageSize;
754
893
  return this.post(`${API_PREFIX}/platformOrder/syncRecord/list`, body, true);
755
894
  }
756
- async listPlatformOrders(status, keyword, pageNum, pageSize) {
895
+ async listPlatformOrders(status, keyword, filters, pageNum, pageSize) {
757
896
  const body = {};
758
897
  if (status != null)
759
898
  body.status = status;
760
899
  if (keyword)
761
900
  body.keyword = keyword;
901
+ if (filters) {
902
+ for (const [k, v] of Object.entries(filters)) {
903
+ if (v)
904
+ body[k] = v;
905
+ }
906
+ }
762
907
  if (pageNum != null)
763
908
  body.pageNum = pageNum;
764
909
  if (pageSize != null)
765
910
  body.pageSize = pageSize;
766
911
  return this.post(`${API_PREFIX}/platformOrder/order/list`, body, true);
767
912
  }
913
+ async updatePlatformOrders(ids, fields) {
914
+ const body = { ids };
915
+ if (fields) {
916
+ for (const [k, v] of Object.entries(fields)) {
917
+ if (v)
918
+ body[k] = v;
919
+ }
920
+ }
921
+ return this.post(`${API_PREFIX}/platformOrder/order/update`, body, true);
922
+ }
923
+ /**
924
+ * 推送平台订单。返回的是**失败明细数组**,空数组即全部成功。
925
+ * 已推送的单会被后端按状态拒绝并出现在返回里(防重复建物流单)。
926
+ */
768
927
  async pushPlatformOrders(ids) {
769
928
  return this.post(`${API_PREFIX}/platformOrder/order/push`, { ids }, true);
770
929
  }
@@ -784,7 +943,7 @@ export class ApiClient {
784
943
  body.bankCard = request.bankCard;
785
944
  if (request.isAgent != null)
786
945
  body.isAgent = request.isAgent;
787
- return this.post(`${API_PREFIX}/onboarding/indiv-auth`, body, true);
946
+ return this.postJson(`${API_PREFIX}/onboarding/indiv-auth`, body, true);
788
947
  }
789
948
  async checkAuthCode(request) {
790
949
  const body = {
@@ -795,18 +954,38 @@ export class ApiClient {
795
954
  body.authType = request.authType;
796
955
  if (request.isAgent != null)
797
956
  body.isAgent = request.isAgent;
798
- return this.post(`${API_PREFIX}/onboarding/check-auth-code`, body, true);
957
+ return this.postJson(`${API_PREFIX}/onboarding/check-auth-code`, body, true);
799
958
  }
959
+ /**
960
+ * 企业实名认证:服务端把企业证件、法人、认证方式与完整注册地址一并校验,
961
+ * 因此这里整体组装后再发出,缺字段时由命令层提前拦截而不是靠服务端报错。
962
+ */
800
963
  async startOrganRealNameAuth(request) {
801
964
  const body = {
802
965
  name: request.name,
803
966
  certNumber: request.certNumber,
967
+ certType: request.certType,
968
+ authType: request.authType,
969
+ agentAccountId: request.agentAccountId,
970
+ legalName: request.legalName,
971
+ countryCode: request.countryCode,
972
+ alpha2Code: request.alpha2Code,
973
+ country: request.country,
974
+ state: request.state,
975
+ city: request.city,
976
+ county: request.county,
977
+ address: request.address,
804
978
  };
805
- if (request.certType != null)
806
- body.certType = request.certType;
807
- if (request.agentAccountId)
808
- body.agentAccountId = request.agentAccountId;
809
- return this.post(`${API_PREFIX}/onboarding/organ-auth`, body, true);
979
+ // 服务端 certTypeEnum 与 certType 是同一含义的两种写法,由 certType 推导可
980
+ // 避免两者互相矛盾;超出枚举范围时留空,服务端允许 null。
981
+ const certTypeEnum = request.certTypeEnum ?? ORGAN_CERT_TYPE_ENUMS[request.certType];
982
+ if (certTypeEnum)
983
+ body.certTypeEnum = certTypeEnum;
984
+ if (request.legalCertNumber)
985
+ body.legalCertNumber = request.legalCertNumber;
986
+ if (request.legalCertType != null)
987
+ body.legalCertType = request.legalCertType;
988
+ return this.postJson(`${API_PREFIX}/onboarding/organ-auth`, body, true);
810
989
  }
811
990
  async openBrandAndApplyContract(request) {
812
991
  const body = {
@@ -828,7 +1007,14 @@ export class ApiClient {
828
1007
  body.county = request.county;
829
1008
  if (request.cLegalName)
830
1009
  body.cLegalName = request.cLegalName;
831
- return this.post(`${API_PREFIX}/onboarding/open-brand`, body, true);
1010
+ return this.postJson(`${API_PREFIX}/onboarding/open-brand`, body, true);
1011
+ }
1012
+ /**
1013
+ * 重复入驻场景下通知当前客户对应的销售(钉钉卡片)。
1014
+ * 客户编码由服务端从 API Key 上下文取,通知内容服务端写死,本接口无入参、无返回数据。
1015
+ */
1016
+ async notifyRepeatEnterSaler() {
1017
+ await this.postJson(`${API_PREFIX}/onboarding/repeat-enter/notify-saler`, {}, true);
832
1018
  }
833
1019
  async authSaveGAT(request) {
834
1020
  const body = {
@@ -865,11 +1051,7 @@ export class ApiClient {
865
1051
  body.countyCode = request.countyCode;
866
1052
  if (request.address)
867
1053
  body.address = request.address;
868
- return this.post(`${API_PREFIX}/onboarding/gat-auth`, body, true);
869
- }
870
- /** amount is in cents — the backend rejects yuan. */
871
- async checkRemitAmount(flowId, amount) {
872
- return this.post(`${API_PREFIX}/onboarding/check-remit`, { flowId, amount }, true);
1054
+ return this.postJson(`${API_PREFIX}/onboarding/gat-auth`, body, true);
873
1055
  }
874
1056
  async queryOnboardingProgress() {
875
1057
  return this.get(`${API_PREFIX}/onboarding/progress`, {}, true);
@@ -894,8 +1076,12 @@ export class ApiClient {
894
1076
  body.pageSize = pageSize;
895
1077
  return this.post(`${API_PREFIX}/onboarding/contracts`, body, true);
896
1078
  }
897
- async getContractSignUrl(contractCode) {
898
- return this.post(`${API_PREFIX}/onboarding/contract-sign-url`, { contractCode }, true);
1079
+ /**
1080
+ * `status` 必填,取自 `contract list`:服务端会重新查合同详情并以实际状态为准,
1081
+ * 详情未返回状态时用它兜底,所以状态码只能来自列表,不能猜。
1082
+ */
1083
+ async getContractSignUrl(contractCode, status) {
1084
+ return this.post(`${API_PREFIX}/onboarding/contract-sign-url`, { contractCode, status }, true);
899
1085
  }
900
1086
  }
901
1087
  //# sourceMappingURL=api-client.js.map