@youidian/sdk 3.3.7 → 3.4.1

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/client.js CHANGED
@@ -204,6 +204,91 @@ var HostedFrameModal = class {
204
204
  }
205
205
  };
206
206
 
207
+ // src/environment.ts
208
+ function normalizeText(value) {
209
+ return value || "";
210
+ }
211
+ function getRuntimeInput() {
212
+ if (typeof navigator === "undefined") {
213
+ return {};
214
+ }
215
+ const nav = navigator;
216
+ const coarsePointer = typeof window !== "undefined" && typeof window.matchMedia === "function" ? window.matchMedia("(pointer: coarse)").matches : void 0;
217
+ return {
218
+ coarsePointer,
219
+ maxTouchPoints: nav.maxTouchPoints || 0,
220
+ platform: nav.platform || "",
221
+ standalone: nav.standalone,
222
+ userAgent: nav.userAgent || "",
223
+ userAgentDataMobile: nav.userAgentData?.mobile
224
+ };
225
+ }
226
+ function includesAny(value, patterns) {
227
+ return patterns.some((pattern) => pattern.test(value));
228
+ }
229
+ function detectLoginEnvironment(input = getRuntimeInput()) {
230
+ const userAgent = normalizeText(input.userAgent);
231
+ const platform = normalizeText(input.platform);
232
+ const rawMaxTouchPoints = input.maxTouchPoints ?? 0;
233
+ const maxTouchPoints = Number.isFinite(rawMaxTouchPoints) ? Math.max(0, rawMaxTouchPoints) : 0;
234
+ const isCoarsePointer = input.coarsePointer === true;
235
+ const isTouch = maxTouchPoints > 0 || isCoarsePointer;
236
+ const isWeChat = /micromessenger/i.test(userAgent);
237
+ const isAndroid = /\bandroid\b/i.test(userAgent);
238
+ const hasExplicitIOSDevice = /\b(iPad|iPhone|iPod)\b/i.test(userAgent);
239
+ const hasMacintoshUserAgent = /\bMacintosh\b/i.test(userAgent);
240
+ const hasMacPlatform = /^Mac/i.test(platform);
241
+ const isIPadOS = !hasExplicitIOSDevice && hasMacintoshUserAgent && hasMacPlatform && typeof input.standalone !== "undefined" && maxTouchPoints > 2;
242
+ const isIOS = hasExplicitIOSDevice || isIPadOS;
243
+ const isTabletByUa = includesAny(userAgent, [
244
+ /\biPad\b/i,
245
+ /\btablet\b/i,
246
+ /\bplaybook\b/i,
247
+ /\bsilk\b(?!.*\bmobile\b)/i,
248
+ /\bkindle\b/i,
249
+ /\bnexus 7\b/i,
250
+ /\bnexus 9\b/i,
251
+ /\bxoom\b/i,
252
+ /\bsm-t\d+/i,
253
+ /\bgt-p\d+/i,
254
+ /\bmi pad\b/i
255
+ ]);
256
+ const isMobileByUa = includesAny(userAgent, [
257
+ /\bMobile\b/i,
258
+ /\biPhone\b/i,
259
+ /\biPod\b/i,
260
+ /\bWindows Phone\b/i,
261
+ /\bIEMobile\b/i,
262
+ /\bBlackBerry\b/i,
263
+ /\bBB10\b/i,
264
+ /\bOpera Mini\b/i,
265
+ /\bOpera Mobi\b/i,
266
+ /\bwebOS\b/i
267
+ ]);
268
+ const isAndroidTablet = isAndroid && !/\bMobile\b/i.test(userAgent);
269
+ const isTablet = isIPadOS || isTabletByUa || isAndroidTablet;
270
+ const isMobile = input.userAgentDataMobile === true || isMobileByUa || isAndroid && !isTablet || isIOS && !isTablet;
271
+ const deviceType = isTablet ? "tablet" : isMobile ? "mobile" : userAgent || platform || isTouch ? "desktop" : "unknown";
272
+ const shouldUseRedirectLogin = deviceType === "mobile" || deviceType === "tablet" || isWeChat;
273
+ return {
274
+ deviceType,
275
+ isAndroid,
276
+ isCoarsePointer,
277
+ isDesktop: deviceType === "desktop",
278
+ isIOS,
279
+ isIPadOS,
280
+ isMobile,
281
+ isStandalone: input.standalone === true,
282
+ isTablet,
283
+ isTouch,
284
+ isWeChat,
285
+ maxTouchPoints,
286
+ platform,
287
+ shouldUseRedirectLogin,
288
+ userAgent
289
+ };
290
+ }
291
+
207
292
  // src/login.ts
208
293
  function getOrigin(value) {
209
294
  if (!value) return null;
@@ -213,6 +298,15 @@ function getOrigin(value) {
213
298
  return null;
214
299
  }
215
300
  }
301
+ function isValidLoginRedirectUrl(value) {
302
+ if (!value) return false;
303
+ try {
304
+ const url = new URL(value);
305
+ return url.protocol === "https:" || url.protocol === "http:";
306
+ } catch {
307
+ return false;
308
+ }
309
+ }
216
310
  function createLoginCallbackState() {
217
311
  if (typeof crypto !== "undefined" && crypto.randomUUID) {
218
312
  return crypto.randomUUID().replace(/-/g, "");
@@ -559,6 +653,24 @@ function applyLoginPanelStyle(panel) {
559
653
  backdropFilter: "blur(16px)"
560
654
  });
561
655
  }
656
+ function applyLoginLoadingPanelStyle(panel) {
657
+ Object.assign(panel.style, {
658
+ position: "absolute",
659
+ inset: "0",
660
+ display: "flex",
661
+ alignItems: "center",
662
+ justifyContent: "center",
663
+ border: "0",
664
+ borderRadius: "28px",
665
+ background: "rgba(255,255,255,0.94)",
666
+ color: "#0f172a",
667
+ padding: "24px",
668
+ textAlign: "center",
669
+ zIndex: "1",
670
+ boxShadow: "none",
671
+ backdropFilter: "blur(16px)"
672
+ });
673
+ }
562
674
  function createLoginPanelContent() {
563
675
  const content = document.createElement("div");
564
676
  Object.assign(content.style, {
@@ -583,6 +695,71 @@ function createLoginPanelContent() {
583
695
  content.appendChild(badge);
584
696
  return content;
585
697
  }
698
+ function createBrandLoadingMark() {
699
+ const logo = document.createElementNS("http://www.w3.org/2000/svg", "svg");
700
+ logo.setAttribute("viewBox", "0 0 1024 1024");
701
+ logo.setAttribute("fill", "none");
702
+ logo.setAttribute("aria-hidden", "true");
703
+ Object.assign(logo.style, {
704
+ width: "112px",
705
+ height: "112px",
706
+ color: "#22c55e",
707
+ display: "block",
708
+ overflow: "visible"
709
+ });
710
+ const group = document.createElementNS("http://www.w3.org/2000/svg", "g");
711
+ group.setAttribute("fill", "currentColor");
712
+ const ring = document.createElementNS("http://www.w3.org/2000/svg", "path");
713
+ ring.setAttribute(
714
+ "d",
715
+ "M704.298 679.54A264 264 0 1 1 704.298 309.46A49 49 0 0 1 634.4 378.149A166 166 0 1 0 634.4 610.851A49 49 0 0 1 704.298 679.54Z"
716
+ );
717
+ ring.setAttribute("class", "youidian-sdk-brand-loading__ring");
718
+ const dot = document.createElementNS("http://www.w3.org/2000/svg", "circle");
719
+ dot.setAttribute("class", "youidian-sdk-brand-loading__dot");
720
+ dot.setAttribute("cx", "714.5");
721
+ dot.setAttribute("cy", "490.5");
722
+ dot.setAttribute("r", "68");
723
+ group.appendChild(ring);
724
+ group.appendChild(dot);
725
+ logo.appendChild(group);
726
+ return logo;
727
+ }
728
+ function createBrandLoadingCopy() {
729
+ const brand = document.createElement("div");
730
+ brand.className = "youidian-sdk-brand-loading__copy";
731
+ Object.assign(brand.style, {
732
+ display: "flex",
733
+ flexDirection: "column",
734
+ alignItems: "flex-start",
735
+ justifyContent: "center",
736
+ lineHeight: "1"
737
+ });
738
+ const name = document.createElement("div");
739
+ name.className = "youidian-sdk-brand-loading__name";
740
+ name.textContent = "\u4F18\u6613\u70B9";
741
+ Object.assign(name.style, {
742
+ color: "#0f172a",
743
+ fontSize: "34px",
744
+ fontWeight: "900",
745
+ letterSpacing: "0",
746
+ lineHeight: "1"
747
+ });
748
+ const tagline = document.createElement("div");
749
+ tagline.className = "youidian-sdk-brand-loading__tagline";
750
+ tagline.textContent = "\u5F00\u53D1\u8005\u670D\u52A1\u4E2D\u53F0";
751
+ Object.assign(tagline.style, {
752
+ color: "#64748b",
753
+ fontSize: "16px",
754
+ fontWeight: "700",
755
+ letterSpacing: "0.24em",
756
+ lineHeight: "1",
757
+ marginTop: "6px"
758
+ });
759
+ brand.appendChild(name);
760
+ brand.appendChild(tagline);
761
+ return brand;
762
+ }
586
763
  function createLoginPanelTitle(value) {
587
764
  const title = document.createElement("div");
588
765
  title.textContent = value;
@@ -612,32 +789,111 @@ function ensureLoginLoadingStyles() {
612
789
  }
613
790
  const style = document.createElement("style");
614
791
  style.id = "youidian-login-loading-style";
615
- style.textContent = "@keyframes youidian-login-spin{to{transform:rotate(360deg)}}";
792
+ style.textContent = `
793
+ .youidian-sdk-brand-loading__ring,
794
+ .youidian-sdk-brand-loading__dot {
795
+ transform-box: fill-box;
796
+ transform-origin: center;
797
+ will-change: opacity, transform;
798
+ }
799
+
800
+ .youidian-sdk-brand-loading__ring {
801
+ animation: youidian-sdk-brand-loading-ring 1400ms cubic-bezier(0.4, 0, 0.2, 1) infinite;
802
+ }
803
+
804
+ .youidian-sdk-brand-loading__dot {
805
+ animation: youidian-sdk-brand-loading-dot 1400ms cubic-bezier(0.4, 0, 0.2, 1) infinite;
806
+ }
807
+
808
+ .youidian-sdk-brand-loading__copy {
809
+ will-change: opacity, transform;
810
+ animation: youidian-sdk-brand-loading-copy 1600ms cubic-bezier(0.4, 0, 0.2, 1) infinite;
811
+ }
812
+
813
+ .youidian-sdk-brand-loading__tagline {
814
+ will-change: opacity;
815
+ animation: youidian-sdk-brand-loading-tagline 1600ms cubic-bezier(0.4, 0, 0.2, 1) infinite;
816
+ }
817
+
818
+ @keyframes youidian-sdk-brand-loading-ring {
819
+ 0%,
820
+ 100% {
821
+ opacity: 0.72;
822
+ transform: rotate(0deg) scale(0.98);
823
+ }
824
+ 50% {
825
+ opacity: 1;
826
+ transform: rotate(8deg) scale(1.02);
827
+ }
828
+ }
829
+
830
+ @keyframes youidian-sdk-brand-loading-dot {
831
+ 0%,
832
+ 100% {
833
+ opacity: 0.55;
834
+ transform: scale(0.9);
835
+ }
836
+ 50% {
837
+ opacity: 1;
838
+ transform: scale(1.08);
839
+ }
840
+ }
841
+
842
+ @keyframes youidian-sdk-brand-loading-copy {
843
+ 0%,
844
+ 100% {
845
+ opacity: 0.86;
846
+ transform: translateY(0);
847
+ }
848
+ 50% {
849
+ opacity: 1;
850
+ transform: translateY(-1px);
851
+ }
852
+ }
853
+
854
+ @keyframes youidian-sdk-brand-loading-tagline {
855
+ 0%,
856
+ 100% {
857
+ opacity: 0.64;
858
+ }
859
+ 50% {
860
+ opacity: 0.92;
861
+ }
862
+ }
863
+
864
+ @media (prefers-reduced-motion: reduce) {
865
+ .youidian-sdk-brand-loading__ring,
866
+ .youidian-sdk-brand-loading__dot,
867
+ .youidian-sdk-brand-loading__copy,
868
+ .youidian-sdk-brand-loading__tagline {
869
+ animation: none;
870
+ opacity: 1;
871
+ transform: none;
872
+ }
873
+ }
874
+ `;
616
875
  document.head.appendChild(style);
617
876
  }
618
- function createLoginLoadingPanel(options) {
877
+ function createLoginLoadingPanel() {
619
878
  ensureLoginLoadingStyles();
620
879
  const panel = document.createElement("div");
621
- applyLoginPanelStyle(panel);
622
- const content = createLoginPanelContent();
623
- const spinner = document.createElement("div");
624
- Object.assign(spinner.style, {
625
- width: "22px",
626
- height: "22px",
627
- borderRadius: "9999px",
628
- border: "2px solid rgba(23,23,23,0.16)",
629
- borderTopColor: "#171717",
630
- margin: "0 auto 18px",
631
- animation: "youidian-login-spin 780ms linear infinite"
880
+ applyLoginLoadingPanelStyle(panel);
881
+ panel.setAttribute("role", "status");
882
+ panel.setAttribute("aria-label", "\u4F18\u6613\u70B9\u5F00\u53D1\u8005\u670D\u52A1\u4E2D\u53F0");
883
+ const content = document.createElement("div");
884
+ Object.assign(content.style, {
885
+ display: "flex",
886
+ alignItems: "center",
887
+ justifyContent: "center",
888
+ gap: "12px"
632
889
  });
633
- content.appendChild(spinner);
634
- content.appendChild(createLoginPanelTitle(options.title));
635
- content.appendChild(createLoginPanelDescription(options.description));
890
+ content.appendChild(createBrandLoadingMark());
891
+ content.appendChild(createBrandLoadingCopy());
636
892
  panel.appendChild(content);
637
893
  return panel;
638
894
  }
639
- function createLoginRedirectingPanel(options) {
640
- return createLoginLoadingPanel(options);
895
+ function createLoginRedirectingPanel(_options) {
896
+ return createLoginLoadingPanel();
641
897
  }
642
898
  function createLoginFallbackPanel(options) {
643
899
  const panel = document.createElement("div");
@@ -737,14 +993,11 @@ var LoginUI = class extends HostedFrameModal {
737
993
  this.iframeFallbackPanel = null;
738
994
  this.iframeLoadingPanel = null;
739
995
  }
740
- showIframeLoading(container, options) {
996
+ showIframeLoading(container) {
741
997
  if (this.iframeLoadingPanel || this.iframeReady) {
742
998
  return;
743
999
  }
744
- const panel = createLoginLoadingPanel({
745
- description: options?.loadingDescription || "Please wait while the secure login page opens.",
746
- title: options?.loadingTitle || "Opening login page"
747
- });
1000
+ const panel = createLoginLoadingPanel();
748
1001
  this.iframeLoadingPanel = panel;
749
1002
  container.appendChild(panel);
750
1003
  }
@@ -832,6 +1085,20 @@ var LoginUI = class extends HostedFrameModal {
832
1085
  break;
833
1086
  case "LOGIN_RESIZE":
834
1087
  break;
1088
+ case "LOGIN_REDIRECT_REQUIRED":
1089
+ if (!isValidLoginRedirectUrl(data.authUrl)) {
1090
+ logLoginWarn("Login redirect requested with invalid authUrl");
1091
+ options?.onError?.("Login redirect URL is invalid", data);
1092
+ break;
1093
+ }
1094
+ logLoginInfo("Login redirect requested by hosted page", {
1095
+ attemptId: data.attemptId || null,
1096
+ channel: data.channel || null,
1097
+ authUrl: data.authUrl
1098
+ });
1099
+ this.close();
1100
+ window.location.assign(data.authUrl);
1101
+ break;
835
1102
  case "LOGIN_ERROR":
836
1103
  if (this.completed) {
837
1104
  break;
@@ -855,6 +1122,25 @@ var LoginUI = class extends HostedFrameModal {
855
1122
  break;
856
1123
  }
857
1124
  }
1125
+ openLoginRedirect(params, options) {
1126
+ if (typeof window === "undefined") return;
1127
+ const { callbackState, finalUrl, launchPayload } = this.buildOpenContext(
1128
+ params,
1129
+ options
1130
+ );
1131
+ logLoginInfo("Redirecting to hosted login page", {
1132
+ appId: params.appId,
1133
+ callbackState,
1134
+ callbackUrl: launchPayload.callbackUrl || null,
1135
+ hasCallbackUrl: Boolean(launchPayload.callbackUrl),
1136
+ loginUrl: finalUrl,
1137
+ autoClose: options?.autoClose ?? true,
1138
+ displayMode: "redirect",
1139
+ pageUrl: window.location.href,
1140
+ parentOrigin: launchPayload.origin || null
1141
+ });
1142
+ window.location.assign(finalUrl);
1143
+ }
858
1144
  listenForLoginCallback(callbackState, options) {
859
1145
  try {
860
1146
  this.callbackChannel = new BroadcastChannel(
@@ -931,21 +1217,17 @@ var LoginUI = class extends HostedFrameModal {
931
1217
  options?.onCancel?.();
932
1218
  options?.onClose?.();
933
1219
  },
934
- onMessage: (data, container, event) => {
1220
+ onMessage: (data, _container, event) => {
935
1221
  const isIframeEvent = event.source === this.iframe?.contentWindow;
936
1222
  if (isIframeEvent && (data.type === "LOGIN_READY" || data.type === "LOGIN_RESIZE") || data.type === "LOGIN_SUCCESS" || data.type === "LOGIN_ERROR") {
937
1223
  this.markIframeReady();
938
1224
  }
939
- if (data.type === "LOGIN_RESIZE" && data.height) {
940
- const maxHeight = window.innerHeight * 0.94;
941
- container.style.height = `${Math.min(data.height, maxHeight)}px`;
942
- }
943
1225
  this.handleLoginEvent(data, options);
944
1226
  },
945
1227
  width: "min(520px, 100%)"
946
1228
  });
947
1229
  if (hostedFrame) {
948
- this.showIframeLoading(hostedFrame.container, options);
1230
+ this.showIframeLoading(hostedFrame.container);
949
1231
  this.startIframeWatchdog({
950
1232
  container: hostedFrame.container,
951
1233
  finalUrl,
@@ -1049,11 +1331,19 @@ var LoginUI = class extends HostedFrameModal {
1049
1331
  }
1050
1332
  openLogin(params, options) {
1051
1333
  if (typeof window === "undefined") return;
1052
- const displayMode = options?.displayMode ?? "modal";
1334
+ const displayMode = options?.displayMode ?? "auto";
1335
+ if (displayMode === "redirect") {
1336
+ this.openLoginRedirect(params, options);
1337
+ return;
1338
+ }
1053
1339
  if (displayMode === "popup") {
1054
1340
  this.openLoginPopup(params, options);
1055
1341
  return;
1056
1342
  }
1343
+ if (displayMode === "auto" && detectLoginEnvironment().shouldUseRedirectLogin) {
1344
+ this.openLoginRedirect(params, options);
1345
+ return;
1346
+ }
1057
1347
  this.openLoginModal(params, options);
1058
1348
  }
1059
1349
  };
@@ -1064,6 +1354,43 @@ handleLoginCallbackIfPresent({ autoClose: false });
1064
1354
 
1065
1355
  // src/client.ts
1066
1356
  var PaymentUI = class extends HostedFrameModal {
1357
+ constructor() {
1358
+ super(...arguments);
1359
+ __publicField(this, "activeCheckoutAppId", null);
1360
+ __publicField(this, "activeCheckoutBaseUrl", null);
1361
+ __publicField(this, "activeOrderId", null);
1362
+ __publicField(this, "paymentCompleted", false);
1363
+ __publicField(this, "cancelRequestedOrderId", null);
1364
+ }
1365
+ cancelHostedOrder(reason = "user_cancel", orderId) {
1366
+ const targetOrderId = orderId || this.activeOrderId;
1367
+ if (!targetOrderId || !this.activeCheckoutAppId || !this.activeCheckoutBaseUrl || this.paymentCompleted || this.cancelRequestedOrderId === targetOrderId) {
1368
+ return;
1369
+ }
1370
+ this.cancelRequestedOrderId = targetOrderId;
1371
+ const url = `${this.activeCheckoutBaseUrl}/api/internal/checkout/cancel-order`;
1372
+ const payload = JSON.stringify({
1373
+ appId: this.activeCheckoutAppId,
1374
+ orderId: targetOrderId,
1375
+ reason
1376
+ });
1377
+ if (typeof navigator !== "undefined" && navigator.sendBeacon) {
1378
+ const sent = navigator.sendBeacon(
1379
+ url,
1380
+ new Blob([payload], { type: "application/json" })
1381
+ );
1382
+ if (sent) return;
1383
+ }
1384
+ void fetch(url, {
1385
+ method: "POST",
1386
+ body: payload,
1387
+ headers: { "Content-Type": "text/plain;charset=UTF-8" },
1388
+ keepalive: true,
1389
+ mode: "no-cors"
1390
+ }).catch(() => {
1391
+ this.cancelRequestedOrderId = null;
1392
+ });
1393
+ }
1067
1394
  /**
1068
1395
  * Opens the payment checkout page in an iframe modal.
1069
1396
  * @param urlOrParams - The checkout page URL or payment parameters
@@ -1073,11 +1400,25 @@ var PaymentUI = class extends HostedFrameModal {
1073
1400
  if (typeof document === "undefined") return;
1074
1401
  if (this.modal) return;
1075
1402
  let checkoutUrl;
1403
+ this.activeOrderId = null;
1404
+ this.paymentCompleted = false;
1405
+ this.cancelRequestedOrderId = null;
1076
1406
  if (typeof urlOrParams === "string") {
1077
1407
  checkoutUrl = urlOrParams;
1408
+ try {
1409
+ const parsedUrl = new URL(checkoutUrl);
1410
+ this.activeCheckoutBaseUrl = parsedUrl.origin;
1411
+ const parts = parsedUrl.pathname.split("/").filter(Boolean);
1412
+ const checkoutIndex = parts.indexOf("checkout");
1413
+ this.activeCheckoutAppId = checkoutIndex >= 0 ? parts[checkoutIndex + 1] || null : null;
1414
+ } catch {
1415
+ this.activeCheckoutAppId = null;
1416
+ this.activeCheckoutBaseUrl = null;
1417
+ }
1078
1418
  } else {
1079
1419
  const {
1080
1420
  appId,
1421
+ orderId,
1081
1422
  productId,
1082
1423
  priceId,
1083
1424
  productCode,
@@ -1087,9 +1428,10 @@ var PaymentUI = class extends HostedFrameModal {
1087
1428
  baseUrl = "https://pay.imgto.link"
1088
1429
  } = urlOrParams;
1089
1430
  const base = (checkoutUrlParam || baseUrl).replace(/\/$/, "");
1090
- const query = new URLSearchParams({
1091
- userId
1092
- });
1431
+ this.activeCheckoutAppId = appId;
1432
+ this.activeCheckoutBaseUrl = base;
1433
+ const query = new URLSearchParams();
1434
+ if (userId) query.set("userId", userId);
1093
1435
  if (customAmount) {
1094
1436
  const amount = Number(customAmount.amount);
1095
1437
  const currency = customAmount.currency.trim().toUpperCase();
@@ -1106,13 +1448,22 @@ var PaymentUI = class extends HostedFrameModal {
1106
1448
  query.set("customAmount", String(amount));
1107
1449
  query.set("customCurrency", currency);
1108
1450
  }
1109
- if (productCode) {
1451
+ if (orderId) {
1452
+ const cleanOrderId = orderId.trim();
1453
+ if (!cleanOrderId) {
1454
+ throw new Error("orderId is required");
1455
+ }
1456
+ this.activeOrderId = cleanOrderId;
1457
+ checkoutUrl = `${base}/checkout/${appId}/orders/${cleanOrderId}`;
1458
+ const queryString = query.toString();
1459
+ if (queryString) checkoutUrl += `?${queryString}`;
1460
+ } else if (productCode) {
1110
1461
  checkoutUrl = `${base}/checkout/${appId}/code/${productCode}?${query.toString()}`;
1111
1462
  } else if (productId && priceId) {
1112
1463
  checkoutUrl = `${base}/checkout/${appId}/${productId}/${priceId}?${query.toString()}`;
1113
1464
  } else {
1114
1465
  throw new Error(
1115
- "Either productCode or both productId and priceId are required"
1466
+ "Either orderId, productCode, or both productId and priceId are required"
1116
1467
  );
1117
1468
  }
1118
1469
  }
@@ -1122,13 +1473,23 @@ var PaymentUI = class extends HostedFrameModal {
1122
1473
  );
1123
1474
  this.openHostedFrame(finalUrl, {
1124
1475
  allowedOrigin: options?.allowedOrigin,
1125
- onCloseButton: () => options?.onCancel?.(),
1476
+ onCloseButton: () => {
1477
+ this.cancelHostedOrder("modal_close");
1478
+ options?.onCancel?.(this.activeOrderId || void 0);
1479
+ },
1126
1480
  onMessage: (data, container) => {
1127
1481
  switch (data.type) {
1482
+ case "PAYMENT_STARTED":
1483
+ if (data.orderId) {
1484
+ this.activeOrderId = data.orderId;
1485
+ }
1486
+ break;
1128
1487
  case "PAYMENT_SUCCESS":
1488
+ this.paymentCompleted = true;
1129
1489
  options?.onSuccess?.(data.orderId);
1130
1490
  break;
1131
1491
  case "PAYMENT_CANCELLED":
1492
+ this.cancelHostedOrder("payment_cancelled", data.orderId);
1132
1493
  options?.onCancel?.(data.orderId);
1133
1494
  break;
1134
1495
  case "PAYMENT_RESIZE":
@@ -1139,6 +1500,7 @@ var PaymentUI = class extends HostedFrameModal {
1139
1500
  }
1140
1501
  break;
1141
1502
  case "PAYMENT_CLOSE":
1503
+ this.cancelHostedOrder("payment_close", data.orderId);
1142
1504
  this.close();
1143
1505
  options?.onClose?.();
1144
1506
  break;
@@ -1198,6 +1560,7 @@ export {
1198
1560
  PaymentUI,
1199
1561
  createLoginUI,
1200
1562
  createPaymentUI,
1563
+ detectLoginEnvironment,
1201
1564
  handleLoginCallbackIfPresent
1202
1565
  };
1203
1566
  //# sourceMappingURL=client.js.map