cyymall-cli 0.1.0 → 0.1.2

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.
@@ -1,327 +1,399 @@
1
- "use strict";
2
-
3
- const fs = require("fs");
4
- const crypto = require("crypto");
5
- const http = require("../http");
6
- const config = require("../config");
7
- const biz = require("../biz");
8
-
9
- function envelope(success, message, data, exitCode) {
10
- const traceId = `local-${crypto.randomBytes(8).toString("hex")}`;
11
- console.log(
12
- JSON.stringify(
13
- {
14
- success,
15
- code: success ? "OK" : "UPSTREAM_ERROR",
16
- message,
17
- data,
18
- traceId,
19
- },
20
- null,
21
- 2,
22
- ),
23
- );
24
- process.exit(exitCode ?? (success ? 0 : 2));
25
- }
26
-
27
- /**
28
- * @param {{ bodyFile?: string, bodyJson?: string }} opts
29
- */
30
- async function preSettle(opts) {
31
- const cfg = config.loadConfig();
32
- if (!cfg?.token) {
33
- console.error("cyy: not logged in.");
34
- process.exit(1);
35
- }
36
- let raw = opts.bodyJson;
37
- if (opts.bodyFile) raw = fs.readFileSync(opts.bodyFile, "utf8");
38
- if (!raw) {
39
- console.error("cyy: provide --body-file or --body-json");
40
- process.exit(1);
41
- }
42
- const url = http.moduleUrl("ORDER", "/app/order/preSettleOrder");
43
- const headers = /** @type {Record<string,string>} */ (http.buildAuthHeaders(cfg));
44
- const { ok, json } = await http.request(url, {
45
- method: "POST",
46
- headers,
47
- body: raw,
48
- });
49
- const success = ok && biz.isBizSuccess(json);
50
- envelope(success, success ? "success" : "pre-settle failed", { upstream: json }, success ? 0 : 2);
51
- }
52
-
53
- /**
54
- * @param {{ bodyFile?: string, bodyJson?: string }} opts
55
- */
56
- async function confirm(opts) {
57
- const cfg = config.loadConfig();
58
- if (!cfg?.token) {
59
- console.error("cyy: not logged in.");
60
- process.exit(1);
61
- }
62
- let raw = opts.bodyJson;
63
- if (opts.bodyFile) raw = fs.readFileSync(opts.bodyFile, "utf8");
64
- if (!raw) {
65
- console.error("cyy: provide --body-file or --body-json");
66
- process.exit(1);
67
- }
68
- const url = http.moduleUrl("ORDER", "/app/order/confirmOrder");
69
- const headers = /** @type {Record<string,string>} */ (http.buildAuthHeaders(cfg));
70
- const { ok, json } = await http.request(url, {
71
- method: "POST",
72
- headers,
73
- body: raw,
74
- });
75
- const success = ok && biz.isBizSuccess(json);
76
- envelope(success, success ? "success" : "confirm failed", { upstream: json }, success ? 0 : 2);
77
- }
78
-
79
- async function payUrl(opts) {
80
- const cfg = config.loadConfig();
81
- if (!cfg?.token) {
82
- console.error("cyy: not logged in.");
83
- process.exit(1);
84
- }
85
- const orderId = opts.orderId;
86
- if (!orderId) {
87
- console.error("cyy: --order-id required");
88
- process.exit(1);
89
- }
90
-
91
- const url = http.moduleUrl("DEFAULT", "/member/getInfo/V2");
92
- const headers = /** @type {Record<string,string>} */ (http.buildAuthHeaders(cfg));
93
- delete headers["Content-Type"];
94
-
95
- const { ok, json } = await http.request(url, { method: "GET", headers, body: null });
96
-
97
- let phone = String(cfg.phone || "");
98
- let nick = "";
99
- let img = "";
100
- if (ok && biz.isBizSuccess(json) && json && typeof json === "object") {
101
- const d = /** @type {{data?:Record<string,unknown>}} */ (json).data;
102
- if (d) {
103
- phone = String(d.memberPhone || phone);
104
- nick = String(d.memberNick || "");
105
- img = String(d.headerImg || "");
106
- }
107
- }
108
-
109
- const siteId = cfg.site_id;
110
- const shopId = cfg.shop_id;
111
- const enc = encodeURIComponent;
112
- const payUrlStr = `https://dhcmall.ifoodbuy.com/H5/#/replacePay?phone=${enc(phone)}&orderid=${enc(String(orderId))}&img=${enc(img)}&nick=${enc(nick)}&siteId=${siteId}&shopId=${shopId}&share=true`;
113
-
114
- envelope(true, "success", { payUrl: payUrlStr, orderId }, 0);
115
- }
116
-
117
- /**
118
- * @param {object} opts
119
- */
120
- async function quick(opts) {
121
- const cfg = config.loadConfig();
122
- if (!cfg?.token) {
123
- console.error("cyy: not logged in.");
124
- process.exit(1);
125
- }
126
-
127
- const keyword = opts.keyword;
128
- const quantity = Number(opts.quantity || 1);
129
- const unit = opts.unit || "袋";
130
- const shopId = Number(opts.shopId ?? cfg.shop_id);
131
- const siteId = Number(opts.siteId ?? cfg.site_id);
132
-
133
- const headers = /** @type {Record<string,string>} */ (http.buildAuthHeaders(cfg));
134
-
135
- // 1) Search
136
- const searchUrl = http.moduleUrl("PRODUCT", "/app/product/getSkuList");
137
- const searchBody = JSON.stringify({
138
- pageNum: 1,
139
- pageSize: 10,
140
- shopId,
141
- siteId,
142
- spuName: keyword,
143
- stockFlag: "0",
144
- });
145
- let r = await http.request(searchUrl, {
146
- method: "POST",
147
- headers,
148
- body: searchBody,
149
- });
150
- if (!r.ok || !biz.isBizSuccess(r.json)) {
151
- envelope(false, "search failed", { upstream: r.json }, 2);
152
- return;
153
- }
154
- const list =
155
- r.json &&
156
- typeof r.json === "object" &&
157
- r.json.data &&
158
- typeof r.json.data === "object"
159
- ? /** @type {{list?:unknown[]}} */ (r.json.data).list
160
- : [];
161
- const products = Array.isArray(list) ? list : [];
162
- if (!products.length) {
163
- envelope(false, "no products found", {}, 2);
164
- return;
165
- }
166
-
167
- const product = /** @type {Record<string,unknown>} */ (products[0]);
168
- const skuId = product.id;
169
- const skuCode = product.skuCode;
170
- const skuName = product.spuName;
171
- const stockQty = product.stockAllQuantity ?? 0;
172
- const promotionList = Array.isArray(product.promotionList) ? product.promotionList : [];
173
-
174
- let price = 0;
175
- let unitRate = 1;
176
- for (const p of promotionList) {
177
- const row = /** @type {Record<string,unknown>} */ (p);
178
- if (row.skuSaleUnitName === unit) {
179
- price = Number(row.salePrice || 0);
180
- unitRate = Number(row.unitRate ?? 1);
181
- break;
182
- }
183
- }
184
- if (!price) {
185
- envelope(
186
- false,
187
- `unit "${unit}" not found in promotionList`,
188
- { availableUnits: promotionList.map((x) => /** @type {{skuSaleUnitName?:string}} */ (x).skuSaleUnitName) },
189
- 2,
190
- );
191
- return;
192
- }
193
-
194
- // 2) Cart
195
- const cartBody = JSON.stringify({
196
- cartItemList: [
197
- {
198
- skuCode,
199
- skuName,
200
- skuQty: quantity,
201
- skuSaleUnit: unit,
202
- listPrice: price,
203
- salePrice: price,
204
- unitRate,
205
- selectFlag: true,
206
- },
207
- ],
208
- cartModel: "append",
209
- shopId,
210
- siteId,
211
- });
212
- const cartUrl = http.moduleUrl("ORDER", "/app/order/cart");
213
- r = await http.request(cartUrl, { method: "POST", headers, body: cartBody });
214
- if (!r.ok || !biz.isBizSuccess(r.json)) {
215
- envelope(false, "cart failed", { upstream: r.json }, 2);
216
- return;
217
- }
218
- const cartData =
219
- r.json && typeof r.json === "object" && "data" in r.json
220
- ? /** @type {{data?:{cartItemList?:{addTime?:string}[]}}} */ (r.json).data
221
- : undefined;
222
- const addTime = cartData?.cartItemList?.[0]?.addTime;
223
- if (!addTime) {
224
- envelope(false, "missing addTime from cart response", { upstream: r.json }, 2);
225
- return;
226
- }
227
-
228
- // 3) Pre-settle
229
- const preBody = JSON.stringify({
230
- headerVO: { shopId, siteId },
231
- itemVOList: [
232
- {
233
- skuId,
234
- skuCode,
235
- skuName,
236
- skuQty: quantity,
237
- skuSaleUnit: unit,
238
- salePrice: price,
239
- listPrice: price,
240
- unitRate,
241
- addTime,
242
- stockQty,
243
- minSaleUnit: unit,
244
- selectFlag: true,
245
- status: 0,
246
- canBuyFlag: true,
247
- },
248
- ],
249
- balanceFlag: false,
250
- userPointFlag: false,
251
- });
252
- const preUrl = http.moduleUrl("ORDER", "/app/order/preSettleOrder");
253
- r = await http.request(preUrl, { method: "POST", headers, body: preBody });
254
- if (!r.ok || !biz.isBizSuccess(r.json)) {
255
- envelope(false, "pre-settle failed", { upstream: r.json }, 2);
256
- return;
257
- }
258
- const pdata =
259
- r.json && typeof r.json === "object" && r.json.data && typeof r.json.data === "object"
260
- ? r.json.data
261
- : null;
262
- const preSettleId = pdata && /** @type {{preSettleId?:string}} */ (pdata).preSettleId;
263
- const headerVO = pdata && /** @type {{headerVO?:unknown}} */ (pdata).headerVO;
264
- const itemVOList = pdata && /** @type {{itemVOList?:unknown}} */ (pdata).itemVOList;
265
- if (!preSettleId) {
266
- envelope(false, "missing preSettleId", { upstream: r.json }, 2);
267
- return;
268
- }
269
-
270
- // 4) Confirm
271
- const confirmBody = JSON.stringify({
272
- preSettleId,
273
- headerVO,
274
- itemVOList,
275
- balanceFlag: false,
276
- userPointFlag: false,
277
- validateStockFlag: true,
278
- repeatFlag: false,
279
- });
280
- const confirmUrl = http.moduleUrl("ORDER", "/app/order/confirmOrder");
281
- r = await http.request(confirmUrl, { method: "POST", headers, body: confirmBody });
282
- if (!r.ok || !biz.isBizSuccess(r.json)) {
283
- envelope(false, "confirm failed", { upstream: r.json }, 2);
284
- return;
285
- }
286
- const orderData =
287
- r.json && typeof r.json === "object" && r.json.data && typeof r.json.data === "object"
288
- ? r.json.data
289
- : {};
290
- const orderId = /** @type {{orderId?:string,payAmt?:unknown}} */ (orderData).orderId;
291
- const payAmt = /** @type {{orderId?:string,payAmt?:unknown}} */ (orderData).payAmt;
292
-
293
- // 5) Pay URL
294
- const memberUrl = http.moduleUrl("DEFAULT", "/member/getInfo/V2");
295
- const h2 = /** @type {Record<string,string>} */ ({ ...headers });
296
- delete h2["Content-Type"];
297
- const uinfo = await http.request(memberUrl, { method: "GET", headers: h2, body: null });
298
- let phone = String(cfg.phone || "");
299
- let nick = "";
300
- let img = "";
301
- if (uinfo.ok && biz.isBizSuccess(uinfo.json) && uinfo.json && typeof uinfo.json === "object") {
302
- const d = /** @type {{data?:Record<string,unknown>}} */ (uinfo.json).data;
303
- if (d) {
304
- phone = String(d.memberPhone || phone);
305
- nick = String(d.memberNick || "");
306
- img = String(d.headerImg || "");
307
- }
308
- }
309
- const enc = encodeURIComponent;
310
- const payUrlStr = `https://dhcmall.ifoodbuy.com/H5/#/replacePay?phone=${enc(phone)}&orderid=${enc(String(orderId))}&img=${enc(img)}&nick=${enc(nick)}&siteId=${siteId}&shopId=${shopId}&share=true`;
311
-
312
- envelope(
313
- true,
314
- "order placed",
315
- {
316
- product: skuName,
317
- quantity,
318
- unit,
319
- orderId,
320
- payAmt,
321
- payUrl: payUrlStr,
322
- },
323
- 0,
324
- );
325
- }
326
-
327
- module.exports = { preSettle, confirm, payUrl, quick };
1
+ "use strict";
2
+
3
+ const fs = require("fs");
4
+ const crypto = require("crypto");
5
+ const http = require("../http");
6
+ const config = require("../config");
7
+ const biz = require("../biz");
8
+
9
+ function envelope(success, message, data, exitCode) {
10
+ const traceId = `local-${crypto.randomBytes(8).toString("hex")}`;
11
+ console.log(
12
+ JSON.stringify(
13
+ {
14
+ success,
15
+ code: success ? "OK" : "UPSTREAM_ERROR",
16
+ message,
17
+ data,
18
+ traceId,
19
+ },
20
+ null,
21
+ 2,
22
+ ),
23
+ );
24
+ process.exit(exitCode ?? (success ? 0 : 2));
25
+ }
26
+
27
+ /**
28
+ * @param {{ bodyFile?: string, bodyJson?: string }} opts
29
+ */
30
+ async function preSettle(opts) {
31
+ const cfg = config.loadConfig();
32
+ if (!cfg?.token) {
33
+ console.error("cyy: not logged in.");
34
+ process.exit(1);
35
+ }
36
+ let raw = opts.bodyJson;
37
+ if (opts.bodyFile) raw = fs.readFileSync(opts.bodyFile, "utf8");
38
+ if (!raw) {
39
+ console.error("cyy: provide --body-file or --body-json");
40
+ process.exit(1);
41
+ }
42
+ const url = http.moduleUrl("ORDER", "/app/order/preSettleOrder");
43
+ const headers = /** @type {Record<string,string>} */ (http.buildAuthHeaders(cfg));
44
+ const { ok, json } = await http.request(url, {
45
+ method: "POST",
46
+ headers,
47
+ body: raw,
48
+ });
49
+ const success = ok && biz.isBizSuccess(json);
50
+ envelope(success, success ? "success" : "pre-settle failed", { upstream: json }, success ? 0 : 2);
51
+ }
52
+
53
+ /**
54
+ * @param {{ bodyFile?: string, bodyJson?: string }} opts
55
+ */
56
+ async function confirm(opts) {
57
+ const cfg = config.loadConfig();
58
+ if (!cfg?.token) {
59
+ console.error("cyy: not logged in.");
60
+ process.exit(1);
61
+ }
62
+ let raw = opts.bodyJson;
63
+ if (opts.bodyFile) raw = fs.readFileSync(opts.bodyFile, "utf8");
64
+ if (!raw) {
65
+ console.error("cyy: provide --body-file or --body-json");
66
+ process.exit(1);
67
+ }
68
+ const url = http.moduleUrl("ORDER", "/app/order/confirmOrder");
69
+ const headers = /** @type {Record<string,string>} */ (http.buildAuthHeaders(cfg));
70
+ const { ok, json } = await http.request(url, {
71
+ method: "POST",
72
+ headers,
73
+ body: raw,
74
+ });
75
+ const success = ok && biz.isBizSuccess(json);
76
+ envelope(success, success ? "success" : "confirm failed", { upstream: json }, success ? 0 : 2);
77
+ }
78
+
79
+ async function payUrl(opts) {
80
+ const cfg = config.loadConfig();
81
+ if (!cfg?.token) {
82
+ console.error("cyy: not logged in.");
83
+ process.exit(1);
84
+ }
85
+ const orderId = opts.orderId;
86
+ if (!orderId) {
87
+ console.error("cyy: --order-id required");
88
+ process.exit(1);
89
+ }
90
+
91
+ const url = http.moduleUrl("DEFAULT", "/member/getInfo/V2");
92
+ const headers = /** @type {Record<string,string>} */ (http.buildAuthHeaders(cfg));
93
+ delete headers["Content-Type"];
94
+
95
+ const { ok, json } = await http.request(url, { method: "GET", headers, body: null });
96
+
97
+ let phone = String(cfg.phone || "");
98
+ let nick = "";
99
+ let img = "";
100
+ if (ok && biz.isBizSuccess(json) && json && typeof json === "object") {
101
+ const d = /** @type {{data?:Record<string,unknown>}} */ (json).data;
102
+ if (d) {
103
+ phone = String(d.memberPhone || phone);
104
+ nick = String(d.memberNick || "");
105
+ img = String(d.headerImg || "");
106
+ }
107
+ }
108
+
109
+ const siteId = cfg.site_id;
110
+ const shopId = cfg.shop_id;
111
+ const enc = encodeURIComponent;
112
+ const payUrlStr = `https://dhcmall.ifoodbuy.com/H5/#/replacePay?phone=${enc(phone)}&orderid=${enc(String(orderId))}&img=${enc(img)}&nick=${enc(nick)}&siteId=${siteId}&shopId=${shopId}&share=true`;
113
+
114
+ envelope(true, "success", { payUrl: payUrlStr, orderId }, 0);
115
+ }
116
+
117
+ /**
118
+ * @param {object} opts
119
+ */
120
+ async function quick(opts) {
121
+ const cfg = config.loadConfig();
122
+ if (!cfg?.token) {
123
+ console.error("cyy: not logged in.");
124
+ process.exit(1);
125
+ }
126
+
127
+ const keyword = opts.keyword;
128
+ const quantity = Number(opts.quantity || 1);
129
+ const unit = opts.unit || "袋";
130
+ const shopId = Number(opts.shopId ?? cfg.shop_id);
131
+ const siteId = Number(opts.siteId ?? cfg.site_id);
132
+
133
+ const headers = /** @type {Record<string,string>} */ (http.buildAuthHeaders(cfg));
134
+
135
+ // 1) Search
136
+ const searchUrl = http.moduleUrl("PRODUCT", "/app/product/getSkuList");
137
+ const searchBody = JSON.stringify({
138
+ pageNum: 1,
139
+ pageSize: 10,
140
+ shopId,
141
+ siteId,
142
+ spuName: keyword,
143
+ stockFlag: "0",
144
+ });
145
+ let r = await http.request(searchUrl, {
146
+ method: "POST",
147
+ headers,
148
+ body: searchBody,
149
+ });
150
+ if (!r.ok || !biz.isBizSuccess(r.json)) {
151
+ envelope(false, "search failed", { upstream: r.json }, 2);
152
+ return;
153
+ }
154
+ const list =
155
+ r.json &&
156
+ typeof r.json === "object" &&
157
+ r.json.data &&
158
+ typeof r.json.data === "object"
159
+ ? /** @type {{list?:unknown[]}} */ (r.json.data).list
160
+ : [];
161
+ const products = Array.isArray(list) ? list : [];
162
+ if (!products.length) {
163
+ envelope(false, "no products found", {}, 2);
164
+ return;
165
+ }
166
+
167
+ const product = /** @type {Record<string,unknown>} */ (products[0]);
168
+ const skuId = product.id;
169
+ const skuCode = product.skuCode;
170
+ const skuName = product.spuName;
171
+ const stockQty = product.stockAllQuantity ?? 0;
172
+ const promotionList = Array.isArray(product.promotionList) ? product.promotionList : [];
173
+
174
+ let price = 0;
175
+ let unitRate = 1;
176
+ for (const p of promotionList) {
177
+ const row = /** @type {Record<string,unknown>} */ (p);
178
+ if (row.skuSaleUnitName === unit) {
179
+ price = Number(row.salePrice || 0);
180
+ unitRate = Number(row.unitRate ?? 1);
181
+ break;
182
+ }
183
+ }
184
+ if (!price) {
185
+ envelope(
186
+ false,
187
+ `unit "${unit}" not found in promotionList`,
188
+ { availableUnits: promotionList.map((x) => /** @type {{skuSaleUnitName?:string}} */ (x).skuSaleUnitName) },
189
+ 2,
190
+ );
191
+ return;
192
+ }
193
+
194
+ // 2) Cart
195
+ const cartBody = JSON.stringify({
196
+ cartItemList: [
197
+ {
198
+ skuCode,
199
+ skuName,
200
+ skuQty: quantity,
201
+ skuSaleUnit: unit,
202
+ listPrice: price,
203
+ salePrice: price,
204
+ unitRate,
205
+ selectFlag: true,
206
+ },
207
+ ],
208
+ cartModel: "append",
209
+ shopId,
210
+ siteId,
211
+ });
212
+ const cartUrl = http.moduleUrl("ORDER", "/app/order/cart");
213
+ r = await http.request(cartUrl, { method: "POST", headers, body: cartBody });
214
+ if (!r.ok || !biz.isBizSuccess(r.json)) {
215
+ envelope(false, "cart failed", { upstream: r.json }, 2);
216
+ return;
217
+ }
218
+ const cartData =
219
+ r.json && typeof r.json === "object" && "data" in r.json
220
+ ? /** @type {{data?:{cartItemList?:{addTime?:string}[]}}} */ (r.json).data
221
+ : undefined;
222
+ const addTime = cartData?.cartItemList?.[0]?.addTime;
223
+ if (!addTime) {
224
+ envelope(false, "missing addTime from cart response", { upstream: r.json }, 2);
225
+ return;
226
+ }
227
+
228
+ // 3) Pre-settle
229
+ const preBody = JSON.stringify({
230
+ headerVO: { shopId, siteId },
231
+ itemVOList: [
232
+ {
233
+ skuId,
234
+ skuCode,
235
+ skuName,
236
+ skuQty: quantity,
237
+ skuSaleUnit: unit,
238
+ salePrice: price,
239
+ listPrice: price,
240
+ unitRate,
241
+ addTime,
242
+ stockQty,
243
+ minSaleUnit: unit,
244
+ selectFlag: true,
245
+ status: 0,
246
+ canBuyFlag: true,
247
+ },
248
+ ],
249
+ balanceFlag: false,
250
+ userPointFlag: false,
251
+ });
252
+ const preUrl = http.moduleUrl("ORDER", "/app/order/preSettleOrder");
253
+ r = await http.request(preUrl, { method: "POST", headers, body: preBody });
254
+ if (!r.ok || !biz.isBizSuccess(r.json)) {
255
+ envelope(false, "pre-settle failed", { upstream: r.json }, 2);
256
+ return;
257
+ }
258
+ const pdata =
259
+ r.json && typeof r.json === "object" && r.json.data && typeof r.json.data === "object"
260
+ ? r.json.data
261
+ : null;
262
+ const preSettleId = pdata && /** @type {{preSettleId?:string}} */ (pdata).preSettleId;
263
+ const headerVO = pdata && /** @type {{headerVO?:unknown}} */ (pdata).headerVO;
264
+ const itemVOList = pdata && /** @type {{itemVOList?:unknown}} */ (pdata).itemVOList;
265
+ if (!preSettleId) {
266
+ envelope(false, "missing preSettleId", { upstream: r.json }, 2);
267
+ return;
268
+ }
269
+
270
+ // 4) Confirm
271
+ const confirmBody = JSON.stringify({
272
+ preSettleId,
273
+ headerVO,
274
+ itemVOList,
275
+ balanceFlag: false,
276
+ userPointFlag: false,
277
+ validateStockFlag: true,
278
+ repeatFlag: false,
279
+ });
280
+ const confirmUrl = http.moduleUrl("ORDER", "/app/order/confirmOrder");
281
+ r = await http.request(confirmUrl, { method: "POST", headers, body: confirmBody });
282
+ if (!r.ok || !biz.isBizSuccess(r.json)) {
283
+ envelope(false, "confirm failed", { upstream: r.json }, 2);
284
+ return;
285
+ }
286
+ const orderData =
287
+ r.json && typeof r.json === "object" && r.json.data && typeof r.json.data === "object"
288
+ ? r.json.data
289
+ : {};
290
+ const orderId = /** @type {{orderId?:string,payAmt?:unknown}} */ (orderData).orderId;
291
+ const payAmt = /** @type {{orderId?:string,payAmt?:unknown}} */ (orderData).payAmt;
292
+
293
+ // 5) Pay URL
294
+ const memberUrl = http.moduleUrl("DEFAULT", "/member/getInfo/V2");
295
+ const h2 = /** @type {Record<string,string>} */ ({ ...headers });
296
+ delete h2["Content-Type"];
297
+ const uinfo = await http.request(memberUrl, { method: "GET", headers: h2, body: null });
298
+ let phone = String(cfg.phone || "");
299
+ let nick = "";
300
+ let img = "";
301
+ if (uinfo.ok && biz.isBizSuccess(uinfo.json) && uinfo.json && typeof uinfo.json === "object") {
302
+ const d = /** @type {{data?:Record<string,unknown>}} */ (uinfo.json).data;
303
+ if (d) {
304
+ phone = String(d.memberPhone || phone);
305
+ nick = String(d.memberNick || "");
306
+ img = String(d.headerImg || "");
307
+ }
308
+ }
309
+ const enc = encodeURIComponent;
310
+ const payUrlStr = `https://dhcmall.ifoodbuy.com/H5/#/replacePay?phone=${enc(phone)}&orderid=${enc(String(orderId))}&img=${enc(img)}&nick=${enc(nick)}&siteId=${siteId}&shopId=${shopId}&share=true`;
311
+
312
+ envelope(
313
+ true,
314
+ "order placed",
315
+ {
316
+ product: skuName,
317
+ quantity,
318
+ unit,
319
+ orderId,
320
+ payAmt,
321
+ payUrl: payUrlStr,
322
+ },
323
+ 0,
324
+ );
325
+ }
326
+
327
+ /**
328
+ * 订单分页列表(与 App `OrderQeq` / `NetConfig.QUERY_PAGE` 一致)。
329
+ * @param {{ page?: string, pageSize?: string, status?: string, shopId?: string, objectCode?: string, all?: boolean, shopKeyword?: string }} opts
330
+ */
331
+ async function list(opts) {
332
+ const cfg = config.loadConfig();
333
+ if (!cfg?.token) {
334
+ console.error("cyy: not logged in.");
335
+ process.exit(1);
336
+ }
337
+ const shopId = opts.shopId != null && opts.shopId !== "" ? Number(opts.shopId) : Number(cfg.shop_id);
338
+ if (!Number.isFinite(shopId)) {
339
+ console.error("cyy: shopId missing (set shop_id in config or pass --shop-id)");
340
+ process.exit(1);
341
+ }
342
+ const pageNum = Math.max(1, parseInt(String(opts.page ?? "1"), 10) || 1);
343
+ const pageSize = Math.max(1, Math.min(100, parseInt(String(opts.pageSize ?? "10"), 10) || 10));
344
+ const objectCode = parseInt(String(opts.objectCode ?? "1"), 10) || 1;
345
+ const status = opts.status != null ? String(opts.status) : "";
346
+ const queryAllFlag = Boolean(opts.all);
347
+ const shopKeyWord = opts.shopKeyword != null ? String(opts.shopKeyword) : "";
348
+
349
+ const bodyObj = {
350
+ pageNum,
351
+ pageSize,
352
+ shopId,
353
+ status,
354
+ queryAllFlag,
355
+ objectCode,
356
+ shopKeyWord,
357
+ };
358
+ const url = http.moduleUrl("DEFAULT", "/order/queryPage");
359
+ const headers = /** @type {Record<string,string>} */ (http.buildAuthHeaders(cfg));
360
+ const { ok, json } = await http.request(url, {
361
+ method: "POST",
362
+ headers,
363
+ body: JSON.stringify(bodyObj),
364
+ });
365
+ const success = ok && biz.isBizSuccess(json);
366
+ envelope(success, success ? "success" : "order list failed", { upstream: json }, success ? 0 : 2);
367
+ }
368
+
369
+ /**
370
+ * 取消订单(与 App `OrderReq` / `cancelOrder` 一致)。
371
+ * @param {{ orderId?: string, childId?: string }} opts
372
+ */
373
+ async function cancel(opts) {
374
+ const cfg = config.loadConfig();
375
+ if (!cfg?.token) {
376
+ console.error("cyy: not logged in.");
377
+ process.exit(1);
378
+ }
379
+ const orderId = opts.orderId;
380
+ if (!orderId) {
381
+ console.error("cyy: --order-id required");
382
+ process.exit(1);
383
+ }
384
+ const bodyObj = /** @type {Record<string, unknown>} */ ({ orderId: String(orderId) });
385
+ if (opts.childId != null && String(opts.childId) !== "") {
386
+ bodyObj.childId = String(opts.childId);
387
+ }
388
+ const url = http.moduleUrl("ORDER", "/app/order/cancelOrder");
389
+ const headers = /** @type {Record<string,string>} */ (http.buildAuthHeaders(cfg));
390
+ const { ok, json } = await http.request(url, {
391
+ method: "POST",
392
+ headers,
393
+ body: JSON.stringify(bodyObj),
394
+ });
395
+ const success = ok && biz.isBizSuccess(json);
396
+ envelope(success, success ? "success" : "cancel order failed", { upstream: json }, success ? 0 : 2);
397
+ }
398
+
399
+ module.exports = { preSettle, confirm, payUrl, quick, list, cancel };