@youidian/sdk 3.3.6 → 3.3.10

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/dist/index.js CHANGED
@@ -355,7 +355,7 @@ var LOGIN_CALLBACK_RETURN_HASH_PARAM = "yd_login_return_hash";
355
355
  var LOGIN_CALLBACK_STATE_PARAM = "yd_login_state";
356
356
  var LOGIN_CALLBACK_STORAGE_PREFIX = "yd-login-callback:";
357
357
  var LOGIN_CALLBACK_CURRENT_PAGE_STORAGE_KEY = "yd-login-current-page-callback";
358
- var DEFAULT_IFRAME_LOAD_TIMEOUT_MS = 1500;
358
+ var DEFAULT_IFRAME_LOAD_TIMEOUT_MS = 6e3;
359
359
  function decodeCallbackPayload(value) {
360
360
  try {
361
361
  const padded = value.padEnd(
@@ -760,7 +760,7 @@ var LoginUI = class extends HostedFrameModal {
760
760
  this.iframeLoadingPanel.parentNode.removeChild(this.iframeLoadingPanel);
761
761
  }
762
762
  this.iframeLoadingPanel = null;
763
- if (loginOptions?.fallbackRedirectMode !== "manual") {
763
+ if (loginOptions?.fallbackRedirectMode === "auto") {
764
764
  const panel2 = createLoginRedirectingPanel({
765
765
  description: loginOptions?.fallbackDescription || "The embedded login page is taking longer than expected. Redirecting you to the login page now.",
766
766
  title: loginOptions?.fallbackTitle || "Redirecting to login page"
@@ -1064,6 +1064,43 @@ handleLoginCallbackIfPresent({ autoClose: false });
1064
1064
 
1065
1065
  // src/client.ts
1066
1066
  var PaymentUI = class extends HostedFrameModal {
1067
+ constructor() {
1068
+ super(...arguments);
1069
+ __publicField(this, "activeCheckoutAppId", null);
1070
+ __publicField(this, "activeCheckoutBaseUrl", null);
1071
+ __publicField(this, "activeOrderId", null);
1072
+ __publicField(this, "paymentCompleted", false);
1073
+ __publicField(this, "cancelRequestedOrderId", null);
1074
+ }
1075
+ cancelHostedOrder(reason = "user_cancel", orderId) {
1076
+ const targetOrderId = orderId || this.activeOrderId;
1077
+ if (!targetOrderId || !this.activeCheckoutAppId || !this.activeCheckoutBaseUrl || this.paymentCompleted || this.cancelRequestedOrderId === targetOrderId) {
1078
+ return;
1079
+ }
1080
+ this.cancelRequestedOrderId = targetOrderId;
1081
+ const url = `${this.activeCheckoutBaseUrl}/api/internal/checkout/cancel-order`;
1082
+ const payload = JSON.stringify({
1083
+ appId: this.activeCheckoutAppId,
1084
+ orderId: targetOrderId,
1085
+ reason
1086
+ });
1087
+ if (typeof navigator !== "undefined" && navigator.sendBeacon) {
1088
+ const sent = navigator.sendBeacon(
1089
+ url,
1090
+ new Blob([payload], { type: "application/json" })
1091
+ );
1092
+ if (sent) return;
1093
+ }
1094
+ void fetch(url, {
1095
+ method: "POST",
1096
+ body: payload,
1097
+ headers: { "Content-Type": "text/plain;charset=UTF-8" },
1098
+ keepalive: true,
1099
+ mode: "no-cors"
1100
+ }).catch(() => {
1101
+ this.cancelRequestedOrderId = null;
1102
+ });
1103
+ }
1067
1104
  /**
1068
1105
  * Opens the payment checkout page in an iframe modal.
1069
1106
  * @param urlOrParams - The checkout page URL or payment parameters
@@ -1073,11 +1110,25 @@ var PaymentUI = class extends HostedFrameModal {
1073
1110
  if (typeof document === "undefined") return;
1074
1111
  if (this.modal) return;
1075
1112
  let checkoutUrl;
1113
+ this.activeOrderId = null;
1114
+ this.paymentCompleted = false;
1115
+ this.cancelRequestedOrderId = null;
1076
1116
  if (typeof urlOrParams === "string") {
1077
1117
  checkoutUrl = urlOrParams;
1118
+ try {
1119
+ const parsedUrl = new URL(checkoutUrl);
1120
+ this.activeCheckoutBaseUrl = parsedUrl.origin;
1121
+ const parts = parsedUrl.pathname.split("/").filter(Boolean);
1122
+ const checkoutIndex = parts.indexOf("checkout");
1123
+ this.activeCheckoutAppId = checkoutIndex >= 0 ? parts[checkoutIndex + 1] || null : null;
1124
+ } catch {
1125
+ this.activeCheckoutAppId = null;
1126
+ this.activeCheckoutBaseUrl = null;
1127
+ }
1078
1128
  } else {
1079
1129
  const {
1080
1130
  appId,
1131
+ orderId,
1081
1132
  productId,
1082
1133
  priceId,
1083
1134
  productCode,
@@ -1087,9 +1138,10 @@ var PaymentUI = class extends HostedFrameModal {
1087
1138
  baseUrl = "https://pay.imgto.link"
1088
1139
  } = urlOrParams;
1089
1140
  const base = (checkoutUrlParam || baseUrl).replace(/\/$/, "");
1090
- const query = new URLSearchParams({
1091
- userId
1092
- });
1141
+ this.activeCheckoutAppId = appId;
1142
+ this.activeCheckoutBaseUrl = base;
1143
+ const query = new URLSearchParams();
1144
+ if (userId) query.set("userId", userId);
1093
1145
  if (customAmount) {
1094
1146
  const amount = Number(customAmount.amount);
1095
1147
  const currency = customAmount.currency.trim().toUpperCase();
@@ -1106,13 +1158,22 @@ var PaymentUI = class extends HostedFrameModal {
1106
1158
  query.set("customAmount", String(amount));
1107
1159
  query.set("customCurrency", currency);
1108
1160
  }
1109
- if (productCode) {
1161
+ if (orderId) {
1162
+ const cleanOrderId = orderId.trim();
1163
+ if (!cleanOrderId) {
1164
+ throw new Error("orderId is required");
1165
+ }
1166
+ this.activeOrderId = cleanOrderId;
1167
+ checkoutUrl = `${base}/checkout/${appId}/orders/${cleanOrderId}`;
1168
+ const queryString = query.toString();
1169
+ if (queryString) checkoutUrl += `?${queryString}`;
1170
+ } else if (productCode) {
1110
1171
  checkoutUrl = `${base}/checkout/${appId}/code/${productCode}?${query.toString()}`;
1111
1172
  } else if (productId && priceId) {
1112
1173
  checkoutUrl = `${base}/checkout/${appId}/${productId}/${priceId}?${query.toString()}`;
1113
1174
  } else {
1114
1175
  throw new Error(
1115
- "Either productCode or both productId and priceId are required"
1176
+ "Either orderId, productCode, or both productId and priceId are required"
1116
1177
  );
1117
1178
  }
1118
1179
  }
@@ -1122,13 +1183,23 @@ var PaymentUI = class extends HostedFrameModal {
1122
1183
  );
1123
1184
  this.openHostedFrame(finalUrl, {
1124
1185
  allowedOrigin: options?.allowedOrigin,
1125
- onCloseButton: () => options?.onCancel?.(),
1186
+ onCloseButton: () => {
1187
+ this.cancelHostedOrder("modal_close");
1188
+ options?.onCancel?.(this.activeOrderId || void 0);
1189
+ },
1126
1190
  onMessage: (data, container) => {
1127
1191
  switch (data.type) {
1192
+ case "PAYMENT_STARTED":
1193
+ if (data.orderId) {
1194
+ this.activeOrderId = data.orderId;
1195
+ }
1196
+ break;
1128
1197
  case "PAYMENT_SUCCESS":
1198
+ this.paymentCompleted = true;
1129
1199
  options?.onSuccess?.(data.orderId);
1130
1200
  break;
1131
1201
  case "PAYMENT_CANCELLED":
1202
+ this.cancelHostedOrder("payment_cancelled", data.orderId);
1132
1203
  options?.onCancel?.(data.orderId);
1133
1204
  break;
1134
1205
  case "PAYMENT_RESIZE":
@@ -1139,6 +1210,7 @@ var PaymentUI = class extends HostedFrameModal {
1139
1210
  }
1140
1211
  break;
1141
1212
  case "PAYMENT_CLOSE":
1213
+ this.cancelHostedOrder("payment_close", data.orderId);
1142
1214
  this.close();
1143
1215
  options?.onClose?.();
1144
1216
  break;
@@ -1355,6 +1427,48 @@ var PaymentClient = class {
1355
1427
  const path = params.toString() ? `/products?${params.toString()}` : "/products";
1356
1428
  return this.request("GET", path);
1357
1429
  }
1430
+ /**
1431
+ * Fetch the realtime stock snapshot for a single product.
1432
+ */
1433
+ async getProductStock(productIdOrCode, options) {
1434
+ const value = productIdOrCode?.trim();
1435
+ if (!value) {
1436
+ throw new Error("productIdOrCode is required");
1437
+ }
1438
+ const params = new URLSearchParams();
1439
+ params.set("productIdOrCode", value);
1440
+ if (options?.lookupBy) params.set("lookupBy", options.lookupBy);
1441
+ if (options?.locale) params.set("locale", options.locale);
1442
+ if (options?.currency) params.set("currency", options.currency);
1443
+ return this.request(
1444
+ "GET",
1445
+ `/products/${encodeURIComponent(value)}/stock?${params.toString()}`
1446
+ );
1447
+ }
1448
+ async getProductStocks(params, options) {
1449
+ const productIds = [
1450
+ ...new Set(
1451
+ (params.productIds || []).map((item) => item.trim()).filter(Boolean)
1452
+ )
1453
+ ];
1454
+ const productCodes = [
1455
+ ...new Set(
1456
+ (params.productCodes || []).map((item) => item.trim()).filter(Boolean)
1457
+ )
1458
+ ];
1459
+ if (productIds.length === 0 && productCodes.length === 0) {
1460
+ throw new Error("productIds or productCodes is required");
1461
+ }
1462
+ const queryOptions = options || params;
1463
+ const query = new URLSearchParams();
1464
+ if (productIds.length > 0) query.set("productIds", productIds.join(","));
1465
+ if (productCodes.length > 0)
1466
+ query.set("productCodes", productCodes.join(","));
1467
+ if (queryOptions.lookupBy) query.set("lookupBy", queryOptions.lookupBy);
1468
+ if (queryOptions.locale) query.set("locale", queryOptions.locale);
1469
+ if (queryOptions.currency) query.set("currency", queryOptions.currency);
1470
+ return this.request("GET", `/products/stocks?${query.toString()}`);
1471
+ }
1358
1472
  /**
1359
1473
  * Create a new order
1360
1474
  * @param params - Order creation parameters
@@ -1363,6 +1477,17 @@ var PaymentClient = class {
1363
1477
  async createOrder(params) {
1364
1478
  return this.request("POST", "/orders", params);
1365
1479
  }
1480
+ /**
1481
+ * Create a paid manual bank transfer order.
1482
+ * @param params - Order creation parameters without channel
1483
+ * @returns Paid order details
1484
+ */
1485
+ async createBankTransferOrder(params) {
1486
+ return this.request("POST", "/orders", {
1487
+ ...params,
1488
+ channel: "BANK_TRANSFER"
1489
+ });
1490
+ }
1366
1491
  /**
1367
1492
  * Create a WeChat Mini Program order (channel fixed to WECHAT_MINI)
1368
1493
  * @param params - Mini program order parameters
@@ -1385,6 +1510,36 @@ var PaymentClient = class {
1385
1510
  async payOrder(orderId, params) {
1386
1511
  return this.request("POST", `/orders/${orderId}/pay`, params);
1387
1512
  }
1513
+ /**
1514
+ * Cancel a pending order and release its inventory reservation.
1515
+ * Paid/refunded/failed orders are returned unchanged by the gateway.
1516
+ */
1517
+ async cancelOrder(orderId, params) {
1518
+ const value = orderId?.trim();
1519
+ if (!value) {
1520
+ throw new Error("orderId is required");
1521
+ }
1522
+ return this.request(
1523
+ "POST",
1524
+ `/orders/${encodeURIComponent(value)}/cancel`,
1525
+ params || {}
1526
+ );
1527
+ }
1528
+ /**
1529
+ * Complete a zero-amount FREE order.
1530
+ * This marks the pending order as paid and triggers normal paid-order side effects.
1531
+ */
1532
+ async completeFreeOrder(orderId) {
1533
+ const value = orderId?.trim();
1534
+ if (!value) {
1535
+ throw new Error("orderId is required");
1536
+ }
1537
+ return this.request(
1538
+ "POST",
1539
+ `/orders/${encodeURIComponent(value)}/free/complete`,
1540
+ {}
1541
+ );
1542
+ }
1388
1543
  /**
1389
1544
  * Query order status
1390
1545
  * @param orderId - The order ID to query