cyymall-cli 0.1.5 → 0.1.6

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "cyymall-cli",
3
- "version": "0.1.5",
3
+ "version": "0.1.6",
4
4
  "description": "CyyMall / 菜洋洋商城 API CLI (per app-api-cli-spec)",
5
5
  "bin": {
6
6
  "cyy": "bin/cyy.js"
@@ -1,4 +1,4 @@
1
- "use strict";
1
+ "use strict";
2
2
 
3
3
  const crypto = require("crypto");
4
4
  const readline = require("readline/promises");
@@ -9,15 +9,15 @@ const biz = require("../biz");
9
9
  const encrypt = require("../encrypt");
10
10
 
11
11
  /**
12
- * `/app/auth/ua/*` responses (e.g. sendCodeV2, registerMember/v2): raw wire -> decryptResponse ->
13
- * JSON.parse -> optional parsedJsonAfterHybridEnvelopeDecrypt, same order as App.
12
+ * `/app/auth/ua/sendCodeV2` responses may still be returned as a hybrid envelope.
13
+ * Decrypt the raw wire body first, then parse JSON, matching the App pipeline.
14
14
  *
15
15
  * @param {string} [rawWireText]
16
16
  * @param {unknown} jsonAfterParse
17
- * @param {string} clientPkForDecrypt
18
17
  * @returns {unknown}
19
18
  */
20
- function plainBizJsonFromSendCodeWire(rawWireText, jsonAfterParse, clientPkForDecrypt) {
19
+ function plainBizJsonFromSendCodeWire(rawWireText, jsonAfterParse) {
20
+ const { clientPrivateKey } = encrypt.resolveEncryptKeys();
21
21
  let wire =
22
22
  typeof rawWireText === "string" && rawWireText.trim()
23
23
  ? rawWireText.trim()
@@ -44,26 +44,26 @@ function plainBizJsonFromSendCodeWire(rawWireText, jsonAfterParse, clientPkForDe
44
44
  }
45
45
  }
46
46
 
47
- if (wire) {
48
- const decryptedText = encrypt.decryptResponse(wire, clientPkForDecrypt);
47
+ if (wire && clientPrivateKey) {
48
+ const decryptedText = encrypt.decryptResponse(wire, clientPrivateKey);
49
49
  try {
50
50
  const obj = decryptedText ? JSON.parse(decryptedText) : null;
51
51
  if (obj != null && typeof obj === "object" && !Array.isArray(obj)) {
52
52
  const out = encrypt.looksLikeHybridEnvelope(obj)
53
- ? encrypt.parsedJsonAfterHybridEnvelopeDecrypt(obj, clientPkForDecrypt)
53
+ ? encrypt.parsedJsonAfterHybridEnvelopeDecrypt(obj, clientPrivateKey)
54
54
  : obj;
55
55
  if (!encrypt.looksLikeHybridEnvelope(out)) {
56
56
  return out;
57
57
  }
58
58
  }
59
59
  } catch {
60
- // fall through to parsed-json fallback
60
+ // fall through to parsed fallback
61
61
  }
62
62
  }
63
63
 
64
64
  if (jsonAfterParse != null && typeof jsonAfterParse === "object" && !Array.isArray(jsonAfterParse)) {
65
- return encrypt.looksLikeHybridEnvelope(jsonAfterParse)
66
- ? encrypt.parsedJsonAfterHybridEnvelopeDecrypt(jsonAfterParse, clientPkForDecrypt)
65
+ return clientPrivateKey && encrypt.looksLikeHybridEnvelope(jsonAfterParse)
66
+ ? encrypt.parsedJsonAfterHybridEnvelopeDecrypt(jsonAfterParse, clientPrivateKey)
67
67
  : jsonAfterParse;
68
68
  }
69
69
 
@@ -91,31 +91,24 @@ function extractBizMessage(json, fallback) {
91
91
  : fallback;
92
92
  }
93
93
 
94
- function buildHybridAuthBody(plainBody, headers) {
94
+ function buildEncryptedSendCodeBody(phone) {
95
+ const headers = /** @type {Record<string,string>} */ (http.buildDefaultHeaders());
96
+ const plainBody = JSON.stringify({ phone, objectCode: "3" });
95
97
  if (!encrypt.encryptEnvConfigured()) {
96
- return plainBody;
98
+ return { headers, body: plainBody };
97
99
  }
98
100
  headers.encrypte = "true";
99
101
  const { serverPublicKey } = encrypt.resolveEncryptKeys();
100
102
  const hy = encrypt.hybridEncrypt(plainBody, serverPublicKey);
101
- return encrypt.hybridEncryptResultToJson(hy);
102
- }
103
-
104
- function decryptAuthBizJson(rawWireText, jsonAfterParse) {
105
- const { clientPrivateKey } = encrypt.resolveEncryptKeys();
106
- if (!clientPrivateKey) return jsonAfterParse;
107
- return plainBizJsonFromSendCodeWire(
108
- typeof rawWireText === "string" ? rawWireText : "",
109
- jsonAfterParse,
110
- clientPrivateKey,
111
- );
103
+ return {
104
+ headers,
105
+ body: encrypt.hybridEncryptResultToJson(hy),
106
+ };
112
107
  }
113
108
 
114
109
  async function requestSmsCode(phone) {
115
110
  const url = http.moduleUrl("DEFAULT", "/app/auth/ua/sendCodeV2");
116
- const headers = /** @type {Record<string,string>} */ (http.buildDefaultHeaders());
117
- const plainBody = JSON.stringify({ phone, objectCode: "3" });
118
- const body = buildHybridAuthBody(plainBody, headers);
111
+ const { headers, body } = buildEncryptedSendCodeBody(phone);
119
112
 
120
113
  const { ok, status, json: jsonAfterParse, rawWireText } = await http.request(url, {
121
114
  method: "POST",
@@ -125,7 +118,7 @@ async function requestSmsCode(phone) {
125
118
  includeRawWireText: true,
126
119
  });
127
120
 
128
- const json = decryptAuthBizJson(rawWireText, jsonAfterParse);
121
+ const json = plainBizJsonFromSendCodeWire(rawWireText, jsonAfterParse);
129
122
 
130
123
  if (!ok) {
131
124
  const msg = extractBizMessage(json, `send login code failed (HTTP ${status})`);
@@ -134,26 +127,24 @@ async function requestSmsCode(phone) {
134
127
  process.exit(2);
135
128
  }
136
129
 
137
- // User-requested behavior: once the send-code request itself succeeds over HTTP,
138
- // treat SMS dispatch as successful even if the encrypted response body cannot be
139
- // decrypted into upstream business JSON.
140
- return { status, json, acceptedByGateway: true };
130
+ // Only sendCodeV2 is encrypted. Once transport succeeds, treat the SMS request as accepted.
131
+ return { status, json, gatewayAccepted: true };
141
132
  }
142
133
 
143
134
  async function sendCode(phone) {
144
- const { status, json, acceptedByGateway } = await requestSmsCode(phone);
135
+ const { status, json, gatewayAccepted } = await requestSmsCode(phone);
145
136
  const traceId = buildTraceId();
146
137
  console.log(
147
138
  JSON.stringify(
148
139
  {
149
140
  success: true,
150
141
  code: "OK",
151
- message: acceptedByGateway ? "code sent" : "code send accepted",
142
+ message: "code sent",
152
143
  data: {
153
144
  phone,
154
145
  objectCode: "3",
155
146
  httpStatus: status,
156
- gatewayAccepted: acceptedByGateway,
147
+ gatewayAccepted,
157
148
  upstream: json,
158
149
  },
159
150
  traceId,
@@ -168,7 +159,7 @@ async function sendCode(phone) {
168
159
  async function loginWithCode(phone, code) {
169
160
  const url = http.moduleUrl("DEFAULT", "/app/auth/ua/registerMember/v2");
170
161
  const headers = /** @type {Record<string,string>} */ (http.buildDefaultHeaders());
171
- const plainBody = JSON.stringify({
162
+ const body = JSON.stringify({
172
163
  phone,
173
164
  objectCode: "3",
174
165
  password: "",
@@ -177,18 +168,13 @@ async function loginWithCode(phone, code) {
177
168
  smsCode: code,
178
169
  wxOpenid: "",
179
170
  });
180
- const body = buildHybridAuthBody(plainBody, headers);
181
171
 
182
- const { ok, json: jsonAfterParse, rawWireText } = await http.request(url, {
172
+ const { ok, json } = await http.request(url, {
183
173
  method: "POST",
184
174
  headers,
185
175
  body,
186
- decryptHybridResponse: false,
187
- includeRawWireText: true,
188
176
  });
189
177
 
190
- const json = decryptAuthBizJson(rawWireText, jsonAfterParse);
191
-
192
178
  if (!ok || !biz.isBizSuccess(json)) {
193
179
  const msg = extractBizMessage(json, "login failed");
194
180
  console.error(`cyy: ${msg}`);
@@ -202,8 +188,8 @@ async function loginWithCode(phone, code) {
202
188
 
203
189
  const loginId = String(data.loginId || "");
204
190
  const memberId = loginId.includes("_") ? loginId.split("_")[0] : loginId;
205
-
206
191
  const token = pickLoginToken(data);
192
+
207
193
  if (!token) {
208
194
  console.error(
209
195
  "cyy: login reported success but data has no token (expected token, appToken, or accessToken)",
@@ -305,4 +291,4 @@ async function whoami() {
305
291
  process.exit(success ? 0 : 2);
306
292
  }
307
293
 
308
- module.exports = { login, loginWithCode, sendCode, whoami };
294
+ module.exports = { login, loginWithCode, sendCode, whoami };