@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/client.cjs +80 -8
- package/dist/client.cjs.map +1 -1
- package/dist/client.d.cts +12 -4
- package/dist/client.d.ts +12 -4
- package/dist/client.js +80 -8
- package/dist/client.js.map +1 -1
- package/dist/index.cjs +163 -8
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +2 -2
- package/dist/index.d.ts +2 -2
- package/dist/index.js +163 -8
- package/dist/index.js.map +1 -1
- package/dist/{login-C-fF3Bw1.d.cts → login-DerOcXcH.d.cts} +3 -2
- package/dist/{login-C-fF3Bw1.d.ts → login-DerOcXcH.d.ts} +3 -2
- package/dist/login.cjs +2 -2
- package/dist/login.cjs.map +1 -1
- package/dist/login.d.cts +1 -1
- package/dist/login.d.ts +1 -1
- package/dist/login.js +2 -2
- package/dist/login.js.map +1 -1
- package/dist/server.cjs +83 -0
- package/dist/server.cjs.map +1 -1
- package/dist/server.d.cts +97 -1
- package/dist/server.d.ts +97 -1
- package/dist/server.js +83 -0
- package/dist/server.js.map +1 -1
- package/package.json +1 -1
package/dist/client.cjs
CHANGED
|
@@ -383,7 +383,7 @@ var LOGIN_CALLBACK_RETURN_HASH_PARAM = "yd_login_return_hash";
|
|
|
383
383
|
var LOGIN_CALLBACK_STATE_PARAM = "yd_login_state";
|
|
384
384
|
var LOGIN_CALLBACK_STORAGE_PREFIX = "yd-login-callback:";
|
|
385
385
|
var LOGIN_CALLBACK_CURRENT_PAGE_STORAGE_KEY = "yd-login-current-page-callback";
|
|
386
|
-
var DEFAULT_IFRAME_LOAD_TIMEOUT_MS =
|
|
386
|
+
var DEFAULT_IFRAME_LOAD_TIMEOUT_MS = 6e3;
|
|
387
387
|
function decodeCallbackPayload(value) {
|
|
388
388
|
try {
|
|
389
389
|
const padded = value.padEnd(
|
|
@@ -788,7 +788,7 @@ var LoginUI = class extends HostedFrameModal {
|
|
|
788
788
|
this.iframeLoadingPanel.parentNode.removeChild(this.iframeLoadingPanel);
|
|
789
789
|
}
|
|
790
790
|
this.iframeLoadingPanel = null;
|
|
791
|
-
if (loginOptions?.fallbackRedirectMode
|
|
791
|
+
if (loginOptions?.fallbackRedirectMode === "auto") {
|
|
792
792
|
const panel2 = createLoginRedirectingPanel({
|
|
793
793
|
description: loginOptions?.fallbackDescription || "The embedded login page is taking longer than expected. Redirecting you to the login page now.",
|
|
794
794
|
title: loginOptions?.fallbackTitle || "Redirecting to login page"
|
|
@@ -1092,6 +1092,43 @@ handleLoginCallbackIfPresent({ autoClose: false });
|
|
|
1092
1092
|
|
|
1093
1093
|
// src/client.ts
|
|
1094
1094
|
var PaymentUI = class extends HostedFrameModal {
|
|
1095
|
+
constructor() {
|
|
1096
|
+
super(...arguments);
|
|
1097
|
+
__publicField(this, "activeCheckoutAppId", null);
|
|
1098
|
+
__publicField(this, "activeCheckoutBaseUrl", null);
|
|
1099
|
+
__publicField(this, "activeOrderId", null);
|
|
1100
|
+
__publicField(this, "paymentCompleted", false);
|
|
1101
|
+
__publicField(this, "cancelRequestedOrderId", null);
|
|
1102
|
+
}
|
|
1103
|
+
cancelHostedOrder(reason = "user_cancel", orderId) {
|
|
1104
|
+
const targetOrderId = orderId || this.activeOrderId;
|
|
1105
|
+
if (!targetOrderId || !this.activeCheckoutAppId || !this.activeCheckoutBaseUrl || this.paymentCompleted || this.cancelRequestedOrderId === targetOrderId) {
|
|
1106
|
+
return;
|
|
1107
|
+
}
|
|
1108
|
+
this.cancelRequestedOrderId = targetOrderId;
|
|
1109
|
+
const url = `${this.activeCheckoutBaseUrl}/api/internal/checkout/cancel-order`;
|
|
1110
|
+
const payload = JSON.stringify({
|
|
1111
|
+
appId: this.activeCheckoutAppId,
|
|
1112
|
+
orderId: targetOrderId,
|
|
1113
|
+
reason
|
|
1114
|
+
});
|
|
1115
|
+
if (typeof navigator !== "undefined" && navigator.sendBeacon) {
|
|
1116
|
+
const sent = navigator.sendBeacon(
|
|
1117
|
+
url,
|
|
1118
|
+
new Blob([payload], { type: "application/json" })
|
|
1119
|
+
);
|
|
1120
|
+
if (sent) return;
|
|
1121
|
+
}
|
|
1122
|
+
void fetch(url, {
|
|
1123
|
+
method: "POST",
|
|
1124
|
+
body: payload,
|
|
1125
|
+
headers: { "Content-Type": "text/plain;charset=UTF-8" },
|
|
1126
|
+
keepalive: true,
|
|
1127
|
+
mode: "no-cors"
|
|
1128
|
+
}).catch(() => {
|
|
1129
|
+
this.cancelRequestedOrderId = null;
|
|
1130
|
+
});
|
|
1131
|
+
}
|
|
1095
1132
|
/**
|
|
1096
1133
|
* Opens the payment checkout page in an iframe modal.
|
|
1097
1134
|
* @param urlOrParams - The checkout page URL or payment parameters
|
|
@@ -1101,11 +1138,25 @@ var PaymentUI = class extends HostedFrameModal {
|
|
|
1101
1138
|
if (typeof document === "undefined") return;
|
|
1102
1139
|
if (this.modal) return;
|
|
1103
1140
|
let checkoutUrl;
|
|
1141
|
+
this.activeOrderId = null;
|
|
1142
|
+
this.paymentCompleted = false;
|
|
1143
|
+
this.cancelRequestedOrderId = null;
|
|
1104
1144
|
if (typeof urlOrParams === "string") {
|
|
1105
1145
|
checkoutUrl = urlOrParams;
|
|
1146
|
+
try {
|
|
1147
|
+
const parsedUrl = new URL(checkoutUrl);
|
|
1148
|
+
this.activeCheckoutBaseUrl = parsedUrl.origin;
|
|
1149
|
+
const parts = parsedUrl.pathname.split("/").filter(Boolean);
|
|
1150
|
+
const checkoutIndex = parts.indexOf("checkout");
|
|
1151
|
+
this.activeCheckoutAppId = checkoutIndex >= 0 ? parts[checkoutIndex + 1] || null : null;
|
|
1152
|
+
} catch {
|
|
1153
|
+
this.activeCheckoutAppId = null;
|
|
1154
|
+
this.activeCheckoutBaseUrl = null;
|
|
1155
|
+
}
|
|
1106
1156
|
} else {
|
|
1107
1157
|
const {
|
|
1108
1158
|
appId,
|
|
1159
|
+
orderId,
|
|
1109
1160
|
productId,
|
|
1110
1161
|
priceId,
|
|
1111
1162
|
productCode,
|
|
@@ -1115,9 +1166,10 @@ var PaymentUI = class extends HostedFrameModal {
|
|
|
1115
1166
|
baseUrl = "https://pay.imgto.link"
|
|
1116
1167
|
} = urlOrParams;
|
|
1117
1168
|
const base = (checkoutUrlParam || baseUrl).replace(/\/$/, "");
|
|
1118
|
-
|
|
1119
|
-
|
|
1120
|
-
|
|
1169
|
+
this.activeCheckoutAppId = appId;
|
|
1170
|
+
this.activeCheckoutBaseUrl = base;
|
|
1171
|
+
const query = new URLSearchParams();
|
|
1172
|
+
if (userId) query.set("userId", userId);
|
|
1121
1173
|
if (customAmount) {
|
|
1122
1174
|
const amount = Number(customAmount.amount);
|
|
1123
1175
|
const currency = customAmount.currency.trim().toUpperCase();
|
|
@@ -1134,13 +1186,22 @@ var PaymentUI = class extends HostedFrameModal {
|
|
|
1134
1186
|
query.set("customAmount", String(amount));
|
|
1135
1187
|
query.set("customCurrency", currency);
|
|
1136
1188
|
}
|
|
1137
|
-
if (
|
|
1189
|
+
if (orderId) {
|
|
1190
|
+
const cleanOrderId = orderId.trim();
|
|
1191
|
+
if (!cleanOrderId) {
|
|
1192
|
+
throw new Error("orderId is required");
|
|
1193
|
+
}
|
|
1194
|
+
this.activeOrderId = cleanOrderId;
|
|
1195
|
+
checkoutUrl = `${base}/checkout/${appId}/orders/${cleanOrderId}`;
|
|
1196
|
+
const queryString = query.toString();
|
|
1197
|
+
if (queryString) checkoutUrl += `?${queryString}`;
|
|
1198
|
+
} else if (productCode) {
|
|
1138
1199
|
checkoutUrl = `${base}/checkout/${appId}/code/${productCode}?${query.toString()}`;
|
|
1139
1200
|
} else if (productId && priceId) {
|
|
1140
1201
|
checkoutUrl = `${base}/checkout/${appId}/${productId}/${priceId}?${query.toString()}`;
|
|
1141
1202
|
} else {
|
|
1142
1203
|
throw new Error(
|
|
1143
|
-
"Either productCode or both productId and priceId are required"
|
|
1204
|
+
"Either orderId, productCode, or both productId and priceId are required"
|
|
1144
1205
|
);
|
|
1145
1206
|
}
|
|
1146
1207
|
}
|
|
@@ -1150,13 +1211,23 @@ var PaymentUI = class extends HostedFrameModal {
|
|
|
1150
1211
|
);
|
|
1151
1212
|
this.openHostedFrame(finalUrl, {
|
|
1152
1213
|
allowedOrigin: options?.allowedOrigin,
|
|
1153
|
-
onCloseButton: () =>
|
|
1214
|
+
onCloseButton: () => {
|
|
1215
|
+
this.cancelHostedOrder("modal_close");
|
|
1216
|
+
options?.onCancel?.(this.activeOrderId || void 0);
|
|
1217
|
+
},
|
|
1154
1218
|
onMessage: (data, container) => {
|
|
1155
1219
|
switch (data.type) {
|
|
1220
|
+
case "PAYMENT_STARTED":
|
|
1221
|
+
if (data.orderId) {
|
|
1222
|
+
this.activeOrderId = data.orderId;
|
|
1223
|
+
}
|
|
1224
|
+
break;
|
|
1156
1225
|
case "PAYMENT_SUCCESS":
|
|
1226
|
+
this.paymentCompleted = true;
|
|
1157
1227
|
options?.onSuccess?.(data.orderId);
|
|
1158
1228
|
break;
|
|
1159
1229
|
case "PAYMENT_CANCELLED":
|
|
1230
|
+
this.cancelHostedOrder("payment_cancelled", data.orderId);
|
|
1160
1231
|
options?.onCancel?.(data.orderId);
|
|
1161
1232
|
break;
|
|
1162
1233
|
case "PAYMENT_RESIZE":
|
|
@@ -1167,6 +1238,7 @@ var PaymentUI = class extends HostedFrameModal {
|
|
|
1167
1238
|
}
|
|
1168
1239
|
break;
|
|
1169
1240
|
case "PAYMENT_CLOSE":
|
|
1241
|
+
this.cancelHostedOrder("payment_close", data.orderId);
|
|
1170
1242
|
this.close();
|
|
1171
1243
|
options?.onClose?.();
|
|
1172
1244
|
break;
|
package/dist/client.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/client.ts","../src/hosted-modal.ts","../src/login.ts"],"sourcesContent":["/**\n * Youidian Payment SDK - Client Module\n * 用于浏览器端集成,包含支付弹窗、状态轮询等功能\n * 不依赖 Node.js crypto 模块\n */\n\nimport {\n\tapplyLocaleToUrl,\n\tgetAutoResolvedLocale,\n\tHostedFrameModal,\n} from \"./hosted-modal\"\n\n/**\n * Payment event types from checkout pages\n */\nexport type PaymentEventType =\n\t| \"PAYMENT_SUCCESS\"\n\t| \"PAYMENT_CANCELLED\"\n\t| \"PAYMENT_CLOSE\"\n\t| \"PAYMENT_RESIZE\"\n\n/**\n * Payment event data from postMessage\n */\nexport interface PaymentEventData {\n\ttype: PaymentEventType\n\torderId?: string\n\theight?: number\n}\n\n/**\n * Order status response\n */\nexport interface OrderStatus {\n\torderId: string\n\tstatus: \"PENDING\" | \"PAID\" | \"CANCELLED\" | \"REFUNDED\" | \"FAILED\"\n\tpaidAt?: string\n\tchannelTransactionId?: string\n}\n\n/**\n * Payment UI Options\n */\nexport interface PaymentUIOptions {\n\tlocale?: string\n\tonSuccess?: (orderId?: string) => void\n\tonCancel?: (orderId?: string) => void\n\tonClose?: () => void\n\t/** Origin to validate postMessage (defaults to '*', set for security) */\n\tallowedOrigin?: string\n}\n\n/**\n * Poll Options\n */\nexport interface PollOptions {\n\t/** Polling interval in ms (default: 3000) */\n\tinterval?: number\n\t/** Timeout in ms (default: 300000 = 5 minutes) */\n\ttimeout?: number\n\t/** Callback on each status check */\n\tonStatusChange?: (status: OrderStatus) => void\n}\n\n/**\n * Client-side Payment UI Helper\n * 浏览器端支付 UI 辅助类,用于弹出支付窗口和轮询订单状态\n */\n/**\n * Params for opening payment directly without manual URL construction\n */\nexport interface PaymentParams {\n\tappId: string\n\tuserId: string\n\t/** Product ID - use with priceId for direct ID-based payment */\n\tproductId?: string\n\t/** Price ID - use with productId for direct ID-based payment */\n\tpriceId?: string\n\t/** Product code - use with locale for code-based payment (alternative to productId/priceId) */\n\tproductCode?: string\n\t/** Optional custom recharge amount in the smallest currency unit */\n\tcustomAmount?: {\n\t\tamount: number\n\t\tcurrency: string\n\t}\n\n\t/**\n\t * @deprecated Use checkoutUrl instead\n\t * Defaults to https://pay.imgto.link\n\t */\n\tbaseUrl?: string\n\n\t/**\n\t * Checkout page URL (e.g. https://pay.youidian.com)\n\t * Defaults to https://pay.imgto.link\n\t */\n\tcheckoutUrl?: string\n}\n\n/**\n * Client-side Payment UI Helper\n * 浏览器端支付 UI 辅助类,用于弹出支付窗口和轮询订单状态\n */\nexport class PaymentUI extends HostedFrameModal<PaymentEventData> {\n\t/**\n\t * Opens the payment checkout page in an iframe modal.\n\t * @param urlOrParams - The checkout page URL or payment parameters\n\t * @param options - UI options\n\t */\n\topenPayment(urlOrParams: string | PaymentParams, options?: PaymentUIOptions) {\n\t\tif (typeof document === \"undefined\") return // Server-side guard\n\t\tif (this.modal) return // Prevent multiple modals\n\n\t\tlet checkoutUrl: string\n\t\tif (typeof urlOrParams === \"string\") {\n\t\t\tcheckoutUrl = urlOrParams\n\t\t} else {\n\t\t\tconst {\n\t\t\t\tappId,\n\t\t\t\tproductId,\n\t\t\t\tpriceId,\n\t\t\t\tproductCode,\n\t\t\t\tuserId,\n\t\t\t\tcustomAmount,\n\t\t\t\tcheckoutUrl: checkoutUrlParam,\n\t\t\t\tbaseUrl = \"https://pay.imgto.link\",\n\t\t\t} = urlOrParams\n\n\t\t\t// 优先使用 checkoutUrl,其次 baseUrl,默认 https://pay.imgto.link\n\t\t\tconst base = (checkoutUrlParam || baseUrl).replace(/\\/$/, \"\")\n\n\t\t\tconst query = new URLSearchParams({\n\t\t\t\tuserId,\n\t\t\t})\n\t\t\tif (customAmount) {\n\t\t\t\tconst amount = Number(customAmount.amount)\n\t\t\t\tconst currency = customAmount.currency.trim().toUpperCase()\n\t\t\t\tif (!Number.isInteger(amount) || amount <= 0) {\n\t\t\t\t\tthrow new Error(\n\t\t\t\t\t\t\"customAmount.amount must be a positive integer in the smallest currency unit\",\n\t\t\t\t\t)\n\t\t\t\t}\n\t\t\t\tif (!/^[A-Z]{3}$/.test(currency)) {\n\t\t\t\t\tthrow new Error(\n\t\t\t\t\t\t\"customAmount.currency must be a 3-letter currency code\",\n\t\t\t\t\t)\n\t\t\t\t}\n\t\t\t\tquery.set(\"customAmount\", String(amount))\n\t\t\t\tquery.set(\"customCurrency\", currency)\n\t\t\t}\n\n\t\t\tif (productCode) {\n\t\t\t\t// Use product code route\n\t\t\t\tcheckoutUrl = `${base}/checkout/${appId}/code/${productCode}?${query.toString()}`\n\t\t\t} else if (productId && priceId) {\n\t\t\t\t// Use ID-based route\n\t\t\t\tcheckoutUrl = `${base}/checkout/${appId}/${productId}/${priceId}?${query.toString()}`\n\t\t\t} else {\n\t\t\t\tthrow new Error(\n\t\t\t\t\t\"Either productCode or both productId and priceId are required\",\n\t\t\t\t)\n\t\t\t}\n\t\t}\n\n\t\tconst finalUrl = applyLocaleToUrl(\n\t\t\tcheckoutUrl,\n\t\t\tgetAutoResolvedLocale(options?.locale),\n\t\t)\n\n\t\tthis.openHostedFrame(finalUrl, {\n\t\t\tallowedOrigin: options?.allowedOrigin,\n\t\t\tonCloseButton: () => options?.onCancel?.(),\n\t\t\tonMessage: (data, container) => {\n\t\t\t\tswitch (data.type) {\n\t\t\t\t\tcase \"PAYMENT_SUCCESS\":\n\t\t\t\t\t\toptions?.onSuccess?.(data.orderId)\n\t\t\t\t\t\tbreak\n\t\t\t\t\tcase \"PAYMENT_CANCELLED\":\n\t\t\t\t\t\toptions?.onCancel?.(data.orderId)\n\t\t\t\t\t\tbreak\n\t\t\t\t\tcase \"PAYMENT_RESIZE\":\n\t\t\t\t\t\tif (data.height) {\n\t\t\t\t\t\t\tconst maxHeight = window.innerHeight * 0.9\n\t\t\t\t\t\t\tconst newHeight = Math.min(data.height, maxHeight)\n\t\t\t\t\t\t\tcontainer.style.height = `${newHeight}px`\n\t\t\t\t\t\t}\n\t\t\t\t\t\tbreak\n\t\t\t\t\tcase \"PAYMENT_CLOSE\":\n\t\t\t\t\t\tthis.close()\n\t\t\t\t\t\toptions?.onClose?.()\n\t\t\t\t\t\tbreak\n\t\t\t\t}\n\t\t\t},\n\t\t})\n\t}\n\n\t/**\n\t * Poll order status from integrator's API endpoint\n\t * @param statusUrl - The integrator's API endpoint to check order status\n\t * @param options - Polling options\n\t * @returns Promise that resolves when order is paid or rejects on timeout/failure\n\t */\n\tasync pollOrderStatus(\n\t\tstatusUrl: string,\n\t\toptions?: PollOptions,\n\t): Promise<OrderStatus> {\n\t\tconst interval = options?.interval || 3000\n\t\tconst timeout = options?.timeout || 300000\n\t\tconst startTime = Date.now()\n\n\t\treturn new Promise((resolve, reject) => {\n\t\t\tconst poll = async () => {\n\t\t\t\ttry {\n\t\t\t\t\tconst response = await fetch(statusUrl)\n\t\t\t\t\tif (!response.ok) {\n\t\t\t\t\t\tthrow new Error(`Status check failed: ${response.status}`)\n\t\t\t\t\t}\n\n\t\t\t\t\tconst status: OrderStatus = await response.json()\n\t\t\t\t\toptions?.onStatusChange?.(status)\n\n\t\t\t\t\tif (status.status === \"PAID\") {\n\t\t\t\t\t\tresolve(status)\n\t\t\t\t\t\treturn\n\t\t\t\t\t}\n\n\t\t\t\t\tif (status.status === \"CANCELLED\" || status.status === \"FAILED\") {\n\t\t\t\t\t\treject(new Error(`Order ${status.status.toLowerCase()}`))\n\t\t\t\t\t\treturn\n\t\t\t\t\t}\n\n\t\t\t\t\t// Check timeout\n\t\t\t\t\tif (Date.now() - startTime > timeout) {\n\t\t\t\t\t\treject(new Error(\"Polling timeout\"))\n\t\t\t\t\t\treturn\n\t\t\t\t\t}\n\n\t\t\t\t\t// Continue polling\n\t\t\t\t\tsetTimeout(poll, interval)\n\t\t\t\t} catch (error) {\n\t\t\t\t\t// On network error, continue polling unless timeout\n\t\t\t\t\tif (Date.now() - startTime > timeout) {\n\t\t\t\t\t\treject(error)\n\t\t\t\t\t\treturn\n\t\t\t\t\t}\n\t\t\t\t\tsetTimeout(poll, interval)\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tpoll()\n\t\t})\n\t}\n}\n\n/**\n * Convenience function to create a PaymentUI instance\n */\nexport function createPaymentUI(): PaymentUI {\n\treturn new PaymentUI()\n}\n\nexport type {\n\tLoginCallbackOptions,\n\tLoginDisplayMode,\n\tLoginEventData,\n\tLoginEventType,\n\tLoginParams,\n\tLoginResult,\n\tLoginUIOptions,\n} from \"./login\"\nexport { createLoginUI, handleLoginCallbackIfPresent, LoginUI } from \"./login\"\n","export interface HostedFrameMessage {\n\ttype: string\n\theight?: number\n}\n\ntype HostedFrameOptions<TData extends HostedFrameMessage> = {\n\tallowedOrigin?: string\n\theight?: string\n\tonCloseButton?: () => void\n\tonMessage: (\n\t\tdata: TData,\n\t\tcontainer: HTMLDivElement,\n\t\tevent: MessageEvent,\n\t) => void\n\twidth?: string\n}\n\ntype HostedFrameInstance = {\n\tcontainer: HTMLDivElement\n\tiframe: HTMLIFrameElement\n}\n\nconst SDK_SUPPORTED_LOCALES = [\n\t\"en\",\n\t\"zh-CN\",\n\t\"zh-Hant\",\n\t\"fr\",\n\t\"de\",\n\t\"ja\",\n\t\"es\",\n\t\"ko\",\n\t\"nl\",\n\t\"it\",\n\t\"pt\",\n] as const\n\nconst SDK_DEFAULT_LOCALE = \"zh-CN\"\n\nconst SDK_LOCALE_ALIASES: Record<string, string> = {\n\ten: \"en\",\n\t\"en-us\": \"en\",\n\t\"en-gb\": \"en\",\n\tzh: \"zh-CN\",\n\t\"zh-cn\": \"zh-CN\",\n\t\"zh-tw\": \"zh-Hant\",\n\t\"zh-hk\": \"zh-Hant\",\n\t\"zh-hant\": \"zh-Hant\",\n\t\"zh-hans\": \"zh-CN\",\n\tfr: \"fr\",\n\tde: \"de\",\n\tja: \"ja\",\n\tes: \"es\",\n\tko: \"ko\",\n\tnl: \"nl\",\n\tit: \"it\",\n\tpt: \"pt\",\n}\n\nfunction matchSupportedBaseLocale(locale: string): string | undefined {\n\tconst base = locale.toLowerCase().split(\"-\")[0]\n\treturn SDK_SUPPORTED_LOCALES.find((item) => item.toLowerCase() === base)\n}\n\nexport function normalizeSdkLocale(locale?: string): string | undefined {\n\tif (!locale) return\n\n\tconst sanitized = locale.trim().replace(/_/g, \"-\")\n\tif (!sanitized) return\n\n\tconst lower = sanitized.toLowerCase()\n\tif (SDK_LOCALE_ALIASES[lower]) {\n\t\treturn SDK_LOCALE_ALIASES[lower]\n\t}\n\n\tlet canonical: string | undefined\n\ttry {\n\t\tcanonical = Intl.getCanonicalLocales(sanitized)[0]\n\t} catch {\n\t\tcanonical = undefined\n\t}\n\n\tconst candidates = [canonical, sanitized].filter(Boolean) as string[]\n\n\tfor (const candidate of candidates) {\n\t\tconst candidateLower = candidate.toLowerCase()\n\n\t\tif (SDK_LOCALE_ALIASES[candidateLower]) {\n\t\t\treturn SDK_LOCALE_ALIASES[candidateLower]\n\t\t}\n\t\tif ((SDK_SUPPORTED_LOCALES as readonly string[]).includes(candidate)) {\n\t\t\treturn candidate\n\t\t}\n\n\t\tconst baseMatch = matchSupportedBaseLocale(candidate)\n\t\tif (baseMatch) {\n\t\t\treturn baseMatch\n\t\t}\n\t}\n}\n\nexport function getBrowserLocale(): string | undefined {\n\tif (typeof navigator === \"undefined\") return\n\n\tfor (const candidate of navigator.languages || []) {\n\t\tconst normalized = normalizeSdkLocale(candidate)\n\t\tif (normalized) return normalized\n\t}\n\n\treturn normalizeSdkLocale(navigator.language)\n}\n\nexport function getAutoResolvedLocale(locale?: string): string {\n\treturn normalizeSdkLocale(locale) || getBrowserLocale() || SDK_DEFAULT_LOCALE\n}\n\nexport function applyLocaleToUrl(urlValue: string, locale?: string): string {\n\tif (!locale) return urlValue\n\n\ttry {\n\t\tconst url = new URL(urlValue)\n\t\tconst localePrefix = `/${locale}`\n\t\tif (\n\t\t\t!url.pathname.startsWith(`${localePrefix}/`) &&\n\t\t\turl.pathname !== localePrefix\n\t\t) {\n\t\t\turl.pathname = `${localePrefix}${url.pathname}`\n\t\t}\n\t\treturn url.toString()\n\t} catch (_error) {\n\t\tconst localePrefix = `/${locale}`\n\t\tif (!urlValue.startsWith(`${localePrefix}/`) && urlValue !== localePrefix) {\n\t\t\treturn `${localePrefix}${urlValue.startsWith(\"/\") ? \"\" : \"/\"}${urlValue}`\n\t\t}\n\t\treturn urlValue\n\t}\n}\n\nexport class HostedFrameModal<TData extends HostedFrameMessage> {\n\tprotected iframe: HTMLIFrameElement | null = null\n\tprotected modal: HTMLDivElement | null = null\n\tprotected messageHandler: ((event: MessageEvent) => void) | null = null\n\n\tprotected openHostedFrame(\n\t\turl: string,\n\t\toptions: HostedFrameOptions<TData>,\n\t): HostedFrameInstance | null {\n\t\tif (typeof document === \"undefined\") return null\n\t\tif (this.modal) return null\n\n\t\tthis.modal = document.createElement(\"div\")\n\t\tObject.assign(this.modal.style, {\n\t\t\tposition: \"fixed\",\n\t\t\ttop: \"0\",\n\t\t\tleft: \"0\",\n\t\t\twidth: \"100%\",\n\t\t\theight: \"100%\",\n\t\t\tbackgroundColor: \"rgba(15,23,42,0.52)\",\n\t\t\tdisplay: \"flex\",\n\t\t\talignItems: \"center\",\n\t\t\tjustifyContent: \"center\",\n\t\t\tzIndex: \"9999\",\n\t\t\ttransition: \"opacity 0.3s ease\",\n\t\t\tbackdropFilter: \"blur(14px)\",\n\t\t\tpadding: \"16px\",\n\t\t})\n\n\t\tconst container = document.createElement(\"div\")\n\t\tObject.assign(container.style, {\n\t\t\twidth: options.width || \"450px\",\n\t\t\theight: options.height || \"min(600px, 90vh)\",\n\t\t\tbackgroundColor: \"transparent\",\n\t\t\tborderRadius: \"28px\",\n\t\t\toverflow: \"visible\",\n\t\t\tposition: \"relative\",\n\t\t\tboxShadow: \"none\",\n\t\t\tmaxWidth: \"calc(100vw - 32px)\",\n\t\t\tmaxHeight: \"calc(100vh - 32px)\",\n\t\t\ttransition: \"height 180ms ease\",\n\t\t\twillChange: \"height\",\n\t\t})\n\n\t\tconst closeBtn = document.createElement(\"button\")\n\t\tcloseBtn.innerHTML = \"×\"\n\t\tObject.assign(closeBtn.style, {\n\t\t\tposition: \"absolute\",\n\t\t\tright: \"-14px\",\n\t\t\ttop: \"-14px\",\n\t\t\tfontSize: \"20px\",\n\t\t\twidth: \"36px\",\n\t\t\theight: \"36px\",\n\t\t\tborderRadius: \"9999px\",\n\t\t\tborder: \"1px solid rgba(255,255,255,0.5)\",\n\t\t\tbackground: \"rgba(255,255,255,0.9)\",\n\t\t\tcursor: \"pointer\",\n\t\t\tcolor: \"#475569\",\n\t\t\tzIndex: \"2\",\n\t\t\tboxShadow: \"0 10px 30px rgba(15,23,42,0.16)\",\n\t\t})\n\t\tcloseBtn.onclick = () => {\n\t\t\tthis.close()\n\t\t\toptions.onCloseButton?.()\n\t\t}\n\n\t\tthis.iframe = document.createElement(\"iframe\")\n\t\tthis.iframe.src = url\n\t\tthis.iframe.allow = \"local-network-access\"\n\t\tObject.assign(this.iframe.style, {\n\t\t\twidth: \"100%\",\n\t\t\theight: \"100%\",\n\t\t\tborder: \"none\",\n\t\t\tborderRadius: \"28px\",\n\t\t\tbackground: \"transparent\",\n\t\t\tdisplay: \"block\",\n\t\t})\n\n\t\tcontainer.appendChild(closeBtn)\n\t\tcontainer.appendChild(this.iframe)\n\t\tthis.modal.appendChild(container)\n\t\tdocument.body.appendChild(this.modal)\n\n\t\tthis.messageHandler = (event: MessageEvent) => {\n\t\t\tif (options.allowedOrigin && options.allowedOrigin !== \"*\") {\n\t\t\t\tif (event.origin !== options.allowedOrigin) {\n\t\t\t\t\treturn\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tconst data = event.data as TData\n\t\t\tif (!data || typeof data !== \"object\" || !data.type) {\n\t\t\t\treturn\n\t\t\t}\n\n\t\t\toptions.onMessage(data, container, event)\n\t\t}\n\n\t\twindow.addEventListener(\"message\", this.messageHandler)\n\n\t\treturn {\n\t\t\tcontainer,\n\t\t\tiframe: this.iframe,\n\t\t}\n\t}\n\n\tclose() {\n\t\tif (typeof window === \"undefined\") return\n\n\t\tif (this.messageHandler) {\n\t\t\twindow.removeEventListener(\"message\", this.messageHandler)\n\t\t\tthis.messageHandler = null\n\t\t}\n\n\t\tif (this.modal?.parentNode) {\n\t\t\tthis.modal.parentNode.removeChild(this.modal)\n\t\t}\n\n\t\tthis.modal = null\n\t\tthis.iframe = null\n\t}\n}\n","import {\n\tapplyLocaleToUrl,\n\tgetAutoResolvedLocale,\n\ttype HostedFrameMessage,\n\tHostedFrameModal,\n} from \"./hosted-modal\"\n\nexport type LoginEventType =\n\t| \"LOGIN_READY\"\n\t| \"LOGIN_SUCCESS\"\n\t| \"LOGIN_CANCELLED\"\n\t| \"LOGIN_CLOSE\"\n\t| \"LOGIN_RESIZE\"\n\t| \"LOGIN_ERROR\"\n\nexport type LoginDisplayMode = \"modal\" | \"popup\"\nexport type LoginFallbackRedirectMode = \"auto\" | \"manual\"\n\nexport interface LoginResult {\n\tavatar?: string | null\n\tchannel?: string\n\temail?: string | null\n\texpiresAt?: string\n\tlegacyCasdoorId?: string\n\tloginToken?: string\n\tname?: string | null\n\tusername?: string | null\n\tphoneCountryCode?: string | null\n\tphoneNumber?: string | null\n\tphoneE164?: string | null\n\tphoneVerifiedAt?: string | null\n\tuserId?: string\n\twechatOpenId?: string | null\n\twechatUnionId?: string | null\n}\n\nexport interface LoginEventData extends HostedFrameMessage, LoginResult {\n\ttype: LoginEventType\n\terror?: string\n\tmessage?: string\n}\n\nexport interface LoginUIOptions {\n\t/** Origin to validate postMessage (defaults to '*', set for security) */\n\tallowedOrigin?: string\n\t/** Whether the SDK should close the login surface after receiving LOGIN_CLOSE. Defaults to true. */\n\tautoClose?: boolean\n\t/** Optional same-origin URL used as the no-API OAuth callback landing page. */\n\tcallbackUrl?: string\n\t/**\n\t * How to open the hosted login page. Defaults to \"modal\", which embeds the\n\t * login page in an iframe modal. Use \"popup\" to keep the legacy popup flow.\n\t */\n\tdisplayMode?: LoginDisplayMode\n\t/** Text for the fallback button shown when the iframe does not report readiness. */\n\tfallbackButtonText?: string\n\t/** Description for the fallback panel shown when the iframe does not report readiness. */\n\tfallbackDescription?: string\n\t/**\n\t * Whether the SDK should redirect automatically when iframe loading times out.\n\t * Defaults to \"auto\". Use \"manual\" to show a button instead.\n\t */\n\tfallbackRedirectMode?: LoginFallbackRedirectMode\n\t/** Title for the fallback panel shown when the iframe does not report readiness. */\n\tfallbackTitle?: string\n\t/**\n\t * How long the SDK waits for LOGIN_READY or LOGIN_RESIZE before showing the\n\t * fallback redirect button. Only used when displayMode is \"modal\".\n\t * Defaults to 1500ms.\n\t */\n\tiframeLoadTimeoutMs?: number\n\t/** Description shown while the hosted login iframe is loading. */\n\tloadingDescription?: string\n\t/** Title shown while the hosted login iframe is loading. */\n\tloadingTitle?: string\n\t/**\n\t * Whether to poll popup.closed to detect manual popup closure.\n\t * Only used when displayMode is \"popup\". Defaults to false because COOP can\n\t * make popup.closed unreliable.\n\t */\n\tmonitorPopupClosed?: boolean\n\tonCancel?: () => void\n\tonClose?: () => void\n\tonError?: (message?: string, data?: LoginEventData) => void\n\tonFallbackVisible?: () => void\n\tonSuccess?: (result: LoginResult) => void\n}\n\nexport interface LoginCallbackOptions {\n\t/**\n\t * Whether the callback helper should close the current window after\n\t * publishing the login result. Defaults to false; LoginUI closes the popup\n\t * it opened after receiving the callback event.\n\t */\n\tautoClose?: boolean\n\tonError?: (message?: string, data?: LoginEventData) => void\n\tonResult?: (data: LoginEventData) => void\n\tonSuccess?: (result: LoginResult) => void\n}\n\nexport interface LoginParams {\n\tappId: string\n\n\t/**\n\t * @deprecated Use loginUrl instead\n\t * Defaults to https://pay.imgto.link\n\t */\n\tbaseUrl?: string\n\n\t/**\n\t * Hosted login page base URL (e.g. https://pay.youidian.com)\n\t * Defaults to https://pay.imgto.link\n\t */\n\tloginUrl?: string\n\n\t/**\n\t * Optional locale prefix to prepend to the hosted login path.\n\t * If omitted, the SDK automatically resolves the locale from the browser language.\n\t */\n\tlocale?: string\n\n\t/** Preferred provider/channel code */\n\tpreferredChannel?: string\n}\n\nfunction getOrigin(value?: string): string | null {\n\tif (!value) return null\n\ttry {\n\t\treturn new URL(value).origin\n\t} catch {\n\t\treturn null\n\t}\n}\n\nfunction createLoginCallbackState() {\n\tif (typeof crypto !== \"undefined\" && crypto.randomUUID) {\n\t\treturn crypto.randomUUID().replace(/-/g, \"\")\n\t}\n\treturn `${Date.now().toString(36)}${Math.random().toString(36).slice(2)}`\n}\n\nfunction buildLoginCallbackUrl(callbackState: string, callbackUrl?: string) {\n\tconst baseUrl = callbackUrl || window.location.href\n\tconst url = new URL(baseUrl, window.location.href)\n\tconst returnHash = url.hash.replace(/^#/, \"\")\n\n\turl.hash = \"\"\n\turl.searchParams.set(LOGIN_CALLBACK_MARKER, \"1\")\n\turl.searchParams.set(LOGIN_CALLBACK_STATE_PARAM, callbackState)\n\tif (returnHash) {\n\t\turl.searchParams.set(LOGIN_CALLBACK_RETURN_HASH_PARAM, returnHash)\n\t} else {\n\t\turl.searchParams.delete(LOGIN_CALLBACK_RETURN_HASH_PARAM)\n\t}\n\n\treturn url.toString()\n}\n\nfunction buildLoginLaunchPayload(\n\tparams: LoginParams,\n\toptions?: LoginUIOptions,\n\tcallbackState?: string,\n) {\n\tconst parentOrigin =\n\t\ttypeof window !== \"undefined\" ? window.location.origin : undefined\n\tconst callbackUrl =\n\t\ttypeof window !== \"undefined\" && callbackState\n\t\t\t? buildLoginCallbackUrl(callbackState, options?.callbackUrl)\n\t\t\t: undefined\n\n\treturn {\n\t\tautoClose: options?.autoClose ?? true,\n\t\tcallbackUrl,\n\t\tcallbackState,\n\t\torigin: parentOrigin,\n\t\tpreferredChannel: params.preferredChannel,\n\t}\n}\n\nfunction appendLoginLaunchHash(\n\turlValue: string,\n\tpayload: ReturnType<typeof buildLoginLaunchPayload>,\n) {\n\tconst hashParams = new URLSearchParams()\n\tif (payload.autoClose === false) {\n\t\thashParams.set(\"ydAutoClose\", \"false\")\n\t}\n\tif (payload.origin) {\n\t\thashParams.set(\"ydOrigin\", payload.origin)\n\t}\n\tif (payload.callbackUrl) {\n\t\thashParams.set(\"ydCallbackUrl\", payload.callbackUrl)\n\t}\n\tif (payload.preferredChannel) {\n\t\thashParams.set(\"ydPreferredChannel\", payload.preferredChannel)\n\t}\n\tconst hash = hashParams.toString()\n\tif (!hash) {\n\t\treturn urlValue\n\t}\n\n\ttry {\n\t\tconst url = new URL(urlValue)\n\t\turl.hash = hash\n\t\treturn url.toString()\n\t} catch (_error) {\n\t\treturn `${urlValue}#${hash}`\n\t}\n}\n\nfunction buildLoginPopupName(payload: LoginLaunchPayload) {\n\treturn `youidian-login:${JSON.stringify(payload)}`\n}\n\nfunction buildLoginUrl(\n\tparams: LoginParams,\n\toptions: LoginUIOptions | undefined,\n\tlaunchPayload: LoginLaunchPayload,\n): string {\n\tconst { appId, baseUrl = \"https://pay.imgto.link\", loginUrl } = params\n\tconst rawBase = (loginUrl || baseUrl).replace(/\\/$/, \"\")\n\tconst parentOrigin = launchPayload.origin\n\n\tlet finalUrl: string\n\ttry {\n\t\tconst url = new URL(rawBase)\n\t\tif (!/\\/auth\\/connect\\/[^/]+$/.test(url.pathname)) {\n\t\t\turl.pathname =\n\t\t\t\t`${url.pathname.replace(/\\/$/, \"\")}/auth/connect/${appId}`.replace(\n\t\t\t\t\t/\\/{2,}/g,\n\t\t\t\t\t\"/\",\n\t\t\t\t)\n\t\t}\n\t\tfinalUrl = url.toString()\n\t} catch (_error) {\n\t\tif (/\\/auth\\/connect\\/[^/]+$/.test(rawBase)) {\n\t\t\tfinalUrl = rawBase\n\t\t} else {\n\t\t\tfinalUrl = `${rawBase}/auth/connect/${appId}`.replace(/\\/{2,}/g, \"/\")\n\t\t}\n\t}\n\n\tfinalUrl = applyLocaleToUrl(finalUrl, getAutoResolvedLocale(params.locale))\n\n\ttry {\n\t\tconst url = new URL(finalUrl)\n\t\tif (params.preferredChannel) {\n\t\t\turl.searchParams.set(\"preferredChannel\", params.preferredChannel)\n\t\t}\n\t\tif (options?.autoClose === false) {\n\t\t\turl.searchParams.set(\"autoClose\", \"false\")\n\t\t}\n\t\tif (parentOrigin) {\n\t\t\turl.searchParams.set(\"origin\", parentOrigin)\n\t\t}\n\t\treturn appendLoginLaunchHash(url.toString(), launchPayload)\n\t} catch (_error) {\n\t\tconst searchParams = new URLSearchParams()\n\t\tif (params.preferredChannel) {\n\t\t\tsearchParams.set(\"preferredChannel\", params.preferredChannel)\n\t\t}\n\t\tif (options?.autoClose === false) {\n\t\t\tsearchParams.set(\"autoClose\", \"false\")\n\t\t}\n\t\tif (parentOrigin) {\n\t\t\tsearchParams.set(\"origin\", parentOrigin)\n\t\t}\n\t\tconst query = searchParams.toString()\n\t\tif (!query) {\n\t\t\treturn appendLoginLaunchHash(finalUrl, launchPayload)\n\t\t}\n\t\tconst separator = finalUrl.includes(\"?\") ? \"&\" : \"?\"\n\t\treturn appendLoginLaunchHash(\n\t\t\t`${finalUrl}${separator}${query}`,\n\t\t\tlaunchPayload,\n\t\t)\n\t}\n}\n\nfunction extractLoginResult(data: LoginEventData): LoginResult {\n\treturn {\n\t\tavatar: data.avatar,\n\t\tchannel: data.channel,\n\t\temail: data.email,\n\t\texpiresAt: data.expiresAt,\n\t\tlegacyCasdoorId: data.legacyCasdoorId,\n\t\tloginToken: data.loginToken,\n\t\tname: data.name,\n\t\tusername: data.username,\n\t\tphoneCountryCode: data.phoneCountryCode,\n\t\tphoneNumber: data.phoneNumber,\n\t\tphoneE164: data.phoneE164,\n\t\tphoneVerifiedAt: data.phoneVerifiedAt,\n\t\tuserId: data.userId,\n\t\twechatOpenId: data.wechatOpenId,\n\t\twechatUnionId: data.wechatUnionId,\n\t}\n}\n\nconst LOGIN_UI_LOG_PREFIX = \"[Youidian LoginUI]\"\nconst LOGIN_CALLBACK_MARKER = \"yd_login_callback\"\nconst LOGIN_CALLBACK_RESULT_PARAM = \"yd_login_result\"\nconst LOGIN_CALLBACK_RETURN_HASH_PARAM = \"yd_login_return_hash\"\nconst LOGIN_CALLBACK_STATE_PARAM = \"yd_login_state\"\nconst LOGIN_CALLBACK_STORAGE_PREFIX = \"yd-login-callback:\"\nconst LOGIN_CALLBACK_CURRENT_PAGE_STORAGE_KEY =\n\t\"yd-login-current-page-callback\"\nconst DEFAULT_IFRAME_LOAD_TIMEOUT_MS = 1500\n\ntype LoginLaunchPayload = ReturnType<typeof buildLoginLaunchPayload>\n\nfunction decodeCallbackPayload(value: string): LoginEventData | null {\n\ttry {\n\t\tconst padded = value.padEnd(\n\t\t\tvalue.length + ((4 - (value.length % 4)) % 4),\n\t\t\t\"=\",\n\t\t)\n\t\tconst base64 = padded.replaceAll(\"-\", \"+\").replaceAll(\"_\", \"/\")\n\t\tconst binary = atob(base64)\n\t\tconst json = decodeURIComponent(\n\t\t\tArray.from(\n\t\t\t\tbinary,\n\t\t\t\t(char) => `%${char.charCodeAt(0).toString(16).padStart(2, \"0\")}`,\n\t\t\t).join(\"\"),\n\t\t)\n\t\tconst parsed = JSON.parse(json) as LoginEventData\n\t\treturn parsed && typeof parsed === \"object\" && parsed.type ? parsed : null\n\t} catch {\n\t\treturn null\n\t}\n}\n\nfunction getLoginCallbackChannelName(state: string) {\n\treturn `youidian-login:${state}`\n}\n\nfunction getLoginCallbackStorageKey(state: string) {\n\treturn `${LOGIN_CALLBACK_STORAGE_PREFIX}${state}`\n}\n\nfunction publishLoginCallback(state: string, data: LoginEventData) {\n\ttry {\n\t\tconst channel = new BroadcastChannel(getLoginCallbackChannelName(state))\n\t\tchannel.postMessage(data)\n\t\tchannel.close()\n\t} catch {\n\t\t// BroadcastChannel is not available in every embedded browser.\n\t}\n\n\ttry {\n\t\tconst storageKey = getLoginCallbackStorageKey(state)\n\t\twindow.localStorage.setItem(storageKey, JSON.stringify(data))\n\t\twindow.setTimeout(() => {\n\t\t\ttry {\n\t\t\t\twindow.localStorage.removeItem(storageKey)\n\t\t\t} catch {\n\t\t\t\t// Ignore cleanup failures.\n\t\t\t}\n\t\t}, 800)\n\t} catch {\n\t\t// localStorage may be disabled; postMessage remains available below.\n\t}\n\n\ttry {\n\t\twindow.opener?.postMessage(data, window.location.origin)\n\t} catch {\n\t\t// opener is only an opportunistic fast path.\n\t}\n}\n\nfunction safeIsPopupClosed(popup: Window | null) {\n\tif (!popup) return true\n\ttry {\n\t\treturn popup.closed\n\t} catch {\n\t\tlogLoginDebug(\"Unable to read popup.closed; treating popup as open\")\n\t\treturn false\n\t}\n}\n\nfunction safeClosePopup(popup: Window | null) {\n\tif (!popup) return\n\ttry {\n\t\tpopup.close()\n\t} catch {\n\t\tlogLoginDebug(\"Unable to close popup\")\n\t}\n}\n\nfunction cleanLoginCallbackUrl(url: URL) {\n\turl.searchParams.delete(LOGIN_CALLBACK_MARKER)\n\turl.searchParams.delete(LOGIN_CALLBACK_STATE_PARAM)\n\tconst returnHash = url.searchParams.get(LOGIN_CALLBACK_RETURN_HASH_PARAM)\n\turl.searchParams.delete(LOGIN_CALLBACK_RETURN_HASH_PARAM)\n\turl.hash = returnHash ? `#${returnHash}` : \"\"\n\treturn url.toString()\n}\n\nfunction saveCurrentPageLoginCallback(data: LoginEventData) {\n\ttry {\n\t\twindow.sessionStorage.setItem(\n\t\t\tLOGIN_CALLBACK_CURRENT_PAGE_STORAGE_KEY,\n\t\t\tJSON.stringify({\n\t\t\t\tcreatedAt: Date.now(),\n\t\t\t\tdata,\n\t\t\t}),\n\t\t)\n\t} catch {\n\t\t// sessionStorage may be disabled in some embedded browsers.\n\t}\n}\n\nfunction readCurrentPageLoginCallback() {\n\ttry {\n\t\tconst raw = window.sessionStorage.getItem(\n\t\t\tLOGIN_CALLBACK_CURRENT_PAGE_STORAGE_KEY,\n\t\t)\n\t\tif (!raw) return null\n\t\twindow.sessionStorage.removeItem(LOGIN_CALLBACK_CURRENT_PAGE_STORAGE_KEY)\n\t\tconst parsed = JSON.parse(raw) as {\n\t\t\tcreatedAt?: number\n\t\t\tdata?: LoginEventData\n\t\t} | null\n\t\tconst data = parsed?.data\n\t\treturn data && typeof data === \"object\" && data.type ? data : null\n\t} catch {\n\t\treturn null\n\t}\n}\n\nfunction deliverLoginCallbackData(\n\tdata: LoginEventData,\n\toptions?: LoginCallbackOptions,\n) {\n\toptions?.onResult?.(data)\n\tswitch (data.type) {\n\t\tcase \"LOGIN_SUCCESS\":\n\t\t\toptions?.onSuccess?.(extractLoginResult(data))\n\t\t\tbreak\n\t\tcase \"LOGIN_ERROR\":\n\t\t\toptions?.onError?.(data.message || data.error, data)\n\t\t\tbreak\n\t\tdefault:\n\t\t\tbreak\n\t}\n}\n\nexport function handleLoginCallbackIfPresent(options?: LoginCallbackOptions) {\n\tif (typeof window === \"undefined\") {\n\t\treturn false\n\t}\n\n\tconst url = new URL(window.location.href)\n\tif (url.searchParams.get(LOGIN_CALLBACK_MARKER) !== \"1\") {\n\t\tif (options?.onResult || options?.onSuccess || options?.onError) {\n\t\t\tconst pendingData = readCurrentPageLoginCallback()\n\t\t\tif (pendingData) {\n\t\t\t\tdeliverLoginCallbackData(pendingData, options)\n\t\t\t\treturn true\n\t\t\t}\n\t\t}\n\t\treturn false\n\t}\n\n\tconst state = url.searchParams.get(LOGIN_CALLBACK_STATE_PARAM) || \"\"\n\tconst hashParams = new URLSearchParams(url.hash.replace(/^#/, \"\"))\n\tconst rawResult = hashParams.get(LOGIN_CALLBACK_RESULT_PARAM)\n\tconst data: LoginEventData | null =\n\t\trawResult && state\n\t\t\t? decodeCallbackPayload(rawResult)\n\t\t\t: {\n\t\t\t\t\ttype: \"LOGIN_ERROR\",\n\t\t\t\t\tmessage: \"Missing login callback result\",\n\t\t\t\t}\n\n\ttry {\n\t\tdocument.documentElement.style.visibility = \"hidden\"\n\t} catch {\n\t\t// This is best-effort to avoid a visible callback-page flash.\n\t}\n\n\tif (state && data) {\n\t\tpublishLoginCallback(state, data)\n\t}\n\tif (data && (options?.onResult || options?.onSuccess || options?.onError)) {\n\t\tdeliverLoginCallbackData(data, options)\n\t} else if (data) {\n\t\tsaveCurrentPageLoginCallback(data)\n\t}\n\n\ttry {\n\t\twindow.history.replaceState(null, \"\", cleanLoginCallbackUrl(url))\n\t} catch {\n\t\t// Ignore history cleanup failures.\n\t}\n\n\tif (options?.autoClose === true) {\n\t\twindow.setTimeout(() => {\n\t\t\ttry {\n\t\t\t\twindow.close()\n\t\t\t} catch {\n\t\t\t\t// Some browsers disallow script-closing the current window.\n\t\t\t}\n\t\t}, 30)\n\t\treturn true\n\t}\n\n\ttry {\n\t\tdocument.documentElement.style.visibility = \"\"\n\t} catch {\n\t\t// Ignore visibility restoration failures.\n\t}\n\n\treturn true\n}\n\nfunction logLoginDebug(message: string, details?: Record<string, unknown>) {\n\tif (typeof console === \"undefined\") return\n\tconsole.debug(LOGIN_UI_LOG_PREFIX, message, details || {})\n}\n\nfunction logLoginInfo(message: string, details?: Record<string, unknown>) {\n\tif (typeof console === \"undefined\") return\n\tconsole.info(LOGIN_UI_LOG_PREFIX, message, details || {})\n}\n\nfunction logLoginWarn(message: string, details?: Record<string, unknown>) {\n\tif (typeof console === \"undefined\") return\n\tconsole.warn(LOGIN_UI_LOG_PREFIX, message, details || {})\n}\n\nfunction getIframeLoadTimeoutMs(options?: LoginUIOptions) {\n\tconst timeout = options?.iframeLoadTimeoutMs\n\tif (typeof timeout !== \"number\" || !Number.isFinite(timeout)) {\n\t\treturn DEFAULT_IFRAME_LOAD_TIMEOUT_MS\n\t}\n\treturn Math.max(0, timeout)\n}\n\nfunction applyLoginPanelStyle(panel: HTMLDivElement) {\n\tObject.assign(panel.style, {\n\t\tposition: \"absolute\",\n\t\tinset: \"0\",\n\t\tdisplay: \"flex\",\n\t\talignItems: \"center\",\n\t\tjustifyContent: \"center\",\n\t\tborder: \"1px solid rgba(229,229,229,0.92)\",\n\t\tborderRadius: \"28px\",\n\t\tbackground: \"rgba(255,255,255,0.94)\",\n\t\tcolor: \"#0f172a\",\n\t\tpadding: \"24px\",\n\t\ttextAlign: \"center\",\n\t\tzIndex: \"1\",\n\t\tboxShadow: \"0 18px 50px rgba(15,15,15,0.06)\",\n\t\tbackdropFilter: \"blur(16px)\",\n\t})\n}\n\nfunction createLoginPanelContent() {\n\tconst content = document.createElement(\"div\")\n\tObject.assign(content.style, {\n\t\tmaxWidth: \"360px\",\n\t})\n\n\tconst badge = document.createElement(\"div\")\n\tbadge.textContent = \"YOUiDIAN\"\n\tObject.assign(badge.style, {\n\t\tdisplay: \"inline-flex\",\n\t\talignItems: \"center\",\n\t\tborder: \"1px solid rgba(229,229,229,0.92)\",\n\t\tborderRadius: \"9999px\",\n\t\tbackground: \"#fafafa\",\n\t\tcolor: \"#171717\",\n\t\tfontSize: \"11px\",\n\t\tfontWeight: \"700\",\n\t\tletterSpacing: \"0.22em\",\n\t\tlineHeight: \"1\",\n\t\tmarginBottom: \"18px\",\n\t\tpadding: \"8px 12px\",\n\t})\n\n\tcontent.appendChild(badge)\n\n\treturn content\n}\n\nfunction createLoginPanelTitle(value: string) {\n\tconst title = document.createElement(\"div\")\n\ttitle.textContent = value\n\tObject.assign(title.style, {\n\t\tcolor: \"#171717\",\n\t\tfontSize: \"18px\",\n\t\tfontWeight: \"700\",\n\t\tlineHeight: \"1.35\",\n\t\tmarginBottom: \"10px\",\n\t})\n\treturn title\n}\n\nfunction createLoginPanelDescription(value: string) {\n\tconst description = document.createElement(\"div\")\n\tdescription.textContent = value\n\tObject.assign(description.style, {\n\t\tcolor: \"#525252\",\n\t\tfontSize: \"14px\",\n\t\tlineHeight: \"1.6\",\n\t\tmarginBottom: \"20px\",\n\t})\n\treturn description\n}\n\nfunction ensureLoginLoadingStyles() {\n\tif (document.getElementById(\"youidian-login-loading-style\")) {\n\t\treturn\n\t}\n\tconst style = document.createElement(\"style\")\n\tstyle.id = \"youidian-login-loading-style\"\n\tstyle.textContent =\n\t\t\"@keyframes youidian-login-spin{to{transform:rotate(360deg)}}\"\n\tdocument.head.appendChild(style)\n}\n\nfunction createLoginLoadingPanel(options: {\n\tdescription: string\n\ttitle: string\n}) {\n\tensureLoginLoadingStyles()\n\tconst panel = document.createElement(\"div\")\n\tapplyLoginPanelStyle(panel)\n\n\tconst content = createLoginPanelContent()\n\tconst spinner = document.createElement(\"div\")\n\tObject.assign(spinner.style, {\n\t\twidth: \"22px\",\n\t\theight: \"22px\",\n\t\tborderRadius: \"9999px\",\n\t\tborder: \"2px solid rgba(23,23,23,0.16)\",\n\t\tborderTopColor: \"#171717\",\n\t\tmargin: \"0 auto 18px\",\n\t\tanimation: \"youidian-login-spin 780ms linear infinite\",\n\t})\n\n\tcontent.appendChild(spinner)\n\tcontent.appendChild(createLoginPanelTitle(options.title))\n\tcontent.appendChild(createLoginPanelDescription(options.description))\n\tpanel.appendChild(content)\n\n\treturn panel\n}\n\nfunction createLoginRedirectingPanel(options: {\n\tdescription: string\n\ttitle: string\n}) {\n\treturn createLoginLoadingPanel(options)\n}\n\nfunction createLoginFallbackPanel(options: {\n\tbuttonText: string\n\tdescription: string\n\tonRedirect: () => void\n\ttitle: string\n}) {\n\tconst panel = document.createElement(\"div\")\n\tapplyLoginPanelStyle(panel)\n\n\tconst content = createLoginPanelContent()\n\n\tconst button = document.createElement(\"button\")\n\tbutton.type = \"button\"\n\tbutton.textContent = options.buttonText\n\tObject.assign(button.style, {\n\t\twidth: \"100%\",\n\t\tborder: \"0\",\n\t\tborderRadius: \"12px\",\n\t\tbackground: \"#0a0a0a\",\n\t\tcolor: \"#ffffff\",\n\t\tcursor: \"pointer\",\n\t\tfontSize: \"14px\",\n\t\tfontWeight: \"700\",\n\t\tminHeight: \"44px\",\n\t\tpadding: \"12px 16px\",\n\t\tboxShadow: \"0 12px 28px rgba(17,17,17,0.14)\",\n\t})\n\tbutton.onclick = options.onRedirect\n\n\tcontent.appendChild(createLoginPanelTitle(options.title))\n\tcontent.appendChild(createLoginPanelDescription(options.description))\n\tcontent.appendChild(button)\n\tpanel.appendChild(content)\n\n\treturn panel\n}\n\nexport class LoginUI extends HostedFrameModal<LoginEventData> {\n\tprivate popup: Window | null = null\n\tprivate callbackChannel: BroadcastChannel | null = null\n\tprivate callbackStorageHandler: ((event: StorageEvent) => void) | null = null\n\tprivate popupMessageHandler: ((event: MessageEvent) => void) | null = null\n\tprivate closeMonitor: number | null = null\n\tprivate iframeFallbackPanel: HTMLDivElement | null = null\n\tprivate iframeLoadingPanel: HTMLDivElement | null = null\n\tprivate iframeLoadTimer: number | null = null\n\tprivate iframeRedirectTimer: number | null = null\n\tprivate iframeReady = false\n\tprivate completed = false\n\n\tprivate cleanup() {\n\t\tif (this.callbackChannel) {\n\t\t\tthis.callbackChannel.close()\n\t\t}\n\t\tif (typeof window !== \"undefined\" && this.callbackStorageHandler) {\n\t\t\twindow.removeEventListener(\"storage\", this.callbackStorageHandler)\n\t\t}\n\t\tif (typeof window !== \"undefined\" && this.popupMessageHandler) {\n\t\t\twindow.removeEventListener(\"message\", this.popupMessageHandler)\n\t\t}\n\t\tthis.callbackChannel = null\n\t\tthis.callbackStorageHandler = null\n\t\tif (typeof window !== \"undefined\" && this.closeMonitor) {\n\t\t\twindow.clearInterval(this.closeMonitor)\n\t\t}\n\t\tif (typeof window !== \"undefined\" && this.iframeLoadTimer) {\n\t\t\twindow.clearTimeout(this.iframeLoadTimer)\n\t\t}\n\t\tif (typeof window !== \"undefined\" && this.iframeRedirectTimer) {\n\t\t\twindow.clearTimeout(this.iframeRedirectTimer)\n\t\t}\n\t\tif (this.iframeFallbackPanel?.parentNode) {\n\t\t\tthis.iframeFallbackPanel.parentNode.removeChild(this.iframeFallbackPanel)\n\t\t}\n\t\tif (this.iframeLoadingPanel?.parentNode) {\n\t\t\tthis.iframeLoadingPanel.parentNode.removeChild(this.iframeLoadingPanel)\n\t\t}\n\t\tthis.popupMessageHandler = null\n\t\tthis.closeMonitor = null\n\t\tthis.iframeFallbackPanel = null\n\t\tthis.iframeLoadingPanel = null\n\t\tthis.iframeLoadTimer = null\n\t\tthis.iframeRedirectTimer = null\n\t\tthis.iframeReady = false\n\t\tthis.popup = null\n\t\tthis.completed = false\n\t}\n\n\tprivate markIframeReady() {\n\t\tthis.iframeReady = true\n\t\tif (typeof window !== \"undefined\" && this.iframeLoadTimer) {\n\t\t\twindow.clearTimeout(this.iframeLoadTimer)\n\t\t\tthis.iframeLoadTimer = null\n\t\t}\n\t\tif (typeof window !== \"undefined\" && this.iframeRedirectTimer) {\n\t\t\twindow.clearTimeout(this.iframeRedirectTimer)\n\t\t\tthis.iframeRedirectTimer = null\n\t\t}\n\t\tif (this.iframeFallbackPanel?.parentNode) {\n\t\t\tthis.iframeFallbackPanel.parentNode.removeChild(this.iframeFallbackPanel)\n\t\t}\n\t\tif (this.iframeLoadingPanel?.parentNode) {\n\t\t\tthis.iframeLoadingPanel.parentNode.removeChild(this.iframeLoadingPanel)\n\t\t}\n\t\tthis.iframeFallbackPanel = null\n\t\tthis.iframeLoadingPanel = null\n\t}\n\n\tprivate showIframeLoading(\n\t\tcontainer: HTMLDivElement,\n\t\toptions?: LoginUIOptions,\n\t) {\n\t\tif (this.iframeLoadingPanel || this.iframeReady) {\n\t\t\treturn\n\t\t}\n\n\t\tconst panel = createLoginLoadingPanel({\n\t\t\tdescription:\n\t\t\t\toptions?.loadingDescription ||\n\t\t\t\t\"Please wait while the secure login page opens.\",\n\t\t\ttitle: options?.loadingTitle || \"Opening login page\",\n\t\t})\n\t\tthis.iframeLoadingPanel = panel\n\t\tcontainer.appendChild(panel)\n\t}\n\n\tprivate showIframeFallback(options: {\n\t\tcontainer: HTMLDivElement\n\t\tfinalUrl: string\n\t\tlaunchPayload: LoginLaunchPayload\n\t\tloginOptions?: LoginUIOptions\n\t}) {\n\t\tif (this.iframeReady || this.iframeFallbackPanel) {\n\t\t\treturn\n\t\t}\n\n\t\tconst { container, finalUrl, loginOptions } = options\n\t\tlogLoginWarn(\"Hosted login iframe did not report ready in time\", {\n\t\t\tloginUrl: finalUrl,\n\t\t})\n\t\tif (this.iframeLoadingPanel?.parentNode) {\n\t\t\tthis.iframeLoadingPanel.parentNode.removeChild(this.iframeLoadingPanel)\n\t\t}\n\t\tthis.iframeLoadingPanel = null\n\n\t\tif (loginOptions?.fallbackRedirectMode !== \"manual\") {\n\t\t\tconst panel = createLoginRedirectingPanel({\n\t\t\t\tdescription:\n\t\t\t\t\tloginOptions?.fallbackDescription ||\n\t\t\t\t\t\"The embedded login page is taking longer than expected. Redirecting you to the login page now.\",\n\t\t\t\ttitle: loginOptions?.fallbackTitle || \"Redirecting to login page\",\n\t\t\t})\n\t\t\tthis.iframeFallbackPanel = panel\n\t\t\tcontainer.appendChild(panel)\n\t\t\tloginOptions?.onFallbackVisible?.()\n\t\t\tthis.iframeRedirectTimer = window.setTimeout(() => {\n\t\t\t\tthis.iframeRedirectTimer = null\n\t\t\t\tlogLoginInfo(\"Redirecting to hosted login fallback page\", {\n\t\t\t\t\tloginUrl: finalUrl,\n\t\t\t\t})\n\t\t\t\twindow.location.assign(finalUrl)\n\t\t\t}, 350)\n\t\t\treturn\n\t\t}\n\n\t\tconst panel = createLoginFallbackPanel({\n\t\t\tbuttonText: loginOptions?.fallbackButtonText || \"Continue to login\",\n\t\t\tdescription:\n\t\t\t\tloginOptions?.fallbackDescription ||\n\t\t\t\t\"The embedded login page is taking longer than expected. Continue on the login page to finish signing in.\",\n\t\t\ttitle: loginOptions?.fallbackTitle || \"Login page is still loading\",\n\t\t\tonRedirect: () => {\n\t\t\t\tlogLoginInfo(\"Redirecting to hosted login fallback page\", {\n\t\t\t\t\tloginUrl: finalUrl,\n\t\t\t\t})\n\t\t\t\twindow.location.assign(finalUrl)\n\t\t\t},\n\t\t})\n\n\t\tthis.iframeFallbackPanel = panel\n\t\tcontainer.appendChild(panel)\n\t\tloginOptions?.onFallbackVisible?.()\n\t}\n\n\tprivate startIframeWatchdog(options: {\n\t\tcontainer: HTMLDivElement\n\t\tfinalUrl: string\n\t\tlaunchPayload: LoginLaunchPayload\n\t\tloginOptions?: LoginUIOptions\n\t}) {\n\t\tif (typeof window === \"undefined\") return\n\n\t\tconst timeoutMs = getIframeLoadTimeoutMs(options.loginOptions)\n\t\tif (timeoutMs === 0) {\n\t\t\tthis.showIframeFallback(options)\n\t\t\treturn\n\t\t}\n\n\t\tthis.iframeLoadTimer = window.setTimeout(() => {\n\t\t\tthis.iframeLoadTimer = null\n\t\t\tthis.showIframeFallback(options)\n\t\t}, timeoutMs)\n\t}\n\n\tprivate handleLoginEvent(data: LoginEventData, options?: LoginUIOptions) {\n\t\tif (!data || typeof data !== \"object\" || !data.type) {\n\t\t\tlogLoginDebug(\"Ignored non-login event payload\")\n\t\t\treturn\n\t\t}\n\n\t\tlogLoginInfo(\"Received login event\", {\n\t\t\ttype: data.type,\n\t\t})\n\n\t\tswitch (data.type) {\n\t\t\tcase \"LOGIN_READY\":\n\t\t\t\tbreak\n\t\t\tcase \"LOGIN_SUCCESS\":\n\t\t\t\tif (this.completed) {\n\t\t\t\t\tbreak\n\t\t\t\t}\n\t\t\t\tthis.completed = true\n\t\t\t\tlogLoginInfo(\"Login succeeded\", {\n\t\t\t\t\tchannel: data.channel || null,\n\t\t\t\t\tuserId: data.userId || null,\n\t\t\t\t})\n\t\t\t\toptions?.onSuccess?.(extractLoginResult(data))\n\t\t\t\tbreak\n\t\t\tcase \"LOGIN_CANCELLED\":\n\t\t\t\tlogLoginInfo(\"Login cancelled\")\n\t\t\t\toptions?.onCancel?.()\n\t\t\t\tbreak\n\t\t\tcase \"LOGIN_RESIZE\":\n\t\t\t\tbreak\n\t\t\tcase \"LOGIN_ERROR\":\n\t\t\t\tif (this.completed) {\n\t\t\t\t\tbreak\n\t\t\t\t}\n\t\t\t\tlogLoginWarn(\"Login flow reported an error\", {\n\t\t\t\t\tmessage: data.message || data.error || null,\n\t\t\t\t})\n\t\t\t\toptions?.onError?.(data.message || data.error, data)\n\t\t\t\tbreak\n\t\t\tcase \"LOGIN_CLOSE\":\n\t\t\t\tif (options?.autoClose === false) {\n\t\t\t\t\tlogLoginInfo(\n\t\t\t\t\t\t\"Login surface requested close; autoClose disabled, keeping it open\",\n\t\t\t\t\t)\n\t\t\t\t\toptions?.onClose?.()\n\t\t\t\t\tbreak\n\t\t\t\t}\n\t\t\t\tlogLoginInfo(\"Login surface requested close; autoClose enabled\")\n\t\t\t\tthis.close()\n\t\t\t\toptions?.onClose?.()\n\t\t\t\tbreak\n\t\t}\n\t}\n\n\tprivate listenForLoginCallback(\n\t\tcallbackState: string,\n\t\toptions?: LoginUIOptions,\n\t) {\n\t\ttry {\n\t\t\tthis.callbackChannel = new BroadcastChannel(\n\t\t\t\tgetLoginCallbackChannelName(callbackState),\n\t\t\t)\n\t\t\tthis.callbackChannel.onmessage = (event) => {\n\t\t\t\tthis.handleLoginEvent(event.data as LoginEventData, options)\n\t\t\t\tthis.handleLoginEvent({ type: \"LOGIN_CLOSE\" }, options)\n\t\t\t}\n\t\t} catch {\n\t\t\tlogLoginDebug(\"BroadcastChannel is unavailable for login callback\")\n\t\t}\n\n\t\tthis.callbackStorageHandler = (event: StorageEvent) => {\n\t\t\tif (\n\t\t\t\tevent.key !== getLoginCallbackStorageKey(callbackState) ||\n\t\t\t\t!event.newValue\n\t\t\t) {\n\t\t\t\treturn\n\t\t\t}\n\t\t\ttry {\n\t\t\t\tconst data = JSON.parse(event.newValue) as LoginEventData\n\t\t\t\tthis.handleLoginEvent(data, options)\n\t\t\t\tthis.handleLoginEvent({ type: \"LOGIN_CLOSE\" }, options)\n\t\t\t} catch {\n\t\t\t\tlogLoginWarn(\"Failed to parse login callback storage payload\")\n\t\t\t}\n\t\t}\n\t\twindow.addEventListener(\"storage\", this.callbackStorageHandler)\n\t}\n\n\tclose() {\n\t\tlogLoginInfo(\"close() called\", {\n\t\t\thasModal: Boolean(this.modal),\n\t\t\thasPopup: Boolean(this.popup),\n\t\t\tpopupClosed: safeIsPopupClosed(this.popup),\n\t\t})\n\t\tsafeClosePopup(this.popup)\n\t\tsuper.close()\n\t\tthis.cleanup()\n\t}\n\n\tprivate buildOpenContext(params: LoginParams, options?: LoginUIOptions) {\n\t\tconst callbackState = createLoginCallbackState()\n\t\tconst launchPayload = buildLoginLaunchPayload(\n\t\t\tparams,\n\t\t\toptions,\n\t\t\tcallbackState,\n\t\t)\n\t\tconst finalUrl = buildLoginUrl(params, options, launchPayload)\n\t\treturn { callbackState, finalUrl, launchPayload }\n\t}\n\n\tprivate openLoginModal(params: LoginParams, options?: LoginUIOptions) {\n\t\tif (typeof document === \"undefined\") return\n\t\tif (this.modal) return\n\n\t\tconst { callbackState, finalUrl, launchPayload } = this.buildOpenContext(\n\t\t\tparams,\n\t\t\toptions,\n\t\t)\n\t\tconst loginOrigin = getOrigin(finalUrl)\n\t\tlogLoginInfo(\"Opening hosted login iframe modal\", {\n\t\t\tappId: params.appId,\n\t\t\tcallbackState,\n\t\t\tcallbackUrl: launchPayload.callbackUrl || null,\n\t\t\thasCallbackUrl: Boolean(launchPayload.callbackUrl),\n\t\t\tloginUrl: finalUrl,\n\t\t\tallowedOrigin: options?.allowedOrigin || null,\n\t\t\tautoClose: options?.autoClose ?? true,\n\t\t\tdisplayMode: \"modal\",\n\t\t\tpageUrl: typeof window !== \"undefined\" ? window.location.href : null,\n\t\t\tparentOrigin: launchPayload.origin || null,\n\t\t})\n\n\t\tthis.completed = false\n\t\tthis.iframeReady = false\n\t\tthis.listenForLoginCallback(callbackState, options)\n\t\tconst hostedFrame = this.openHostedFrame(finalUrl, {\n\t\t\tallowedOrigin: options?.allowedOrigin || loginOrigin || undefined,\n\t\t\theight: \"min(760px, 94vh)\",\n\t\t\tonCloseButton: () => {\n\t\t\t\toptions?.onCancel?.()\n\t\t\t\toptions?.onClose?.()\n\t\t\t},\n\t\t\tonMessage: (data, container, event) => {\n\t\t\t\tconst isIframeEvent = event.source === this.iframe?.contentWindow\n\t\t\t\tif (\n\t\t\t\t\t(isIframeEvent &&\n\t\t\t\t\t\t(data.type === \"LOGIN_READY\" || data.type === \"LOGIN_RESIZE\")) ||\n\t\t\t\t\tdata.type === \"LOGIN_SUCCESS\" ||\n\t\t\t\t\tdata.type === \"LOGIN_ERROR\"\n\t\t\t\t) {\n\t\t\t\t\tthis.markIframeReady()\n\t\t\t\t}\n\t\t\t\tif (data.type === \"LOGIN_RESIZE\" && data.height) {\n\t\t\t\t\tconst maxHeight = window.innerHeight * 0.94\n\t\t\t\t\tcontainer.style.height = `${Math.min(data.height, maxHeight)}px`\n\t\t\t\t}\n\t\t\t\tthis.handleLoginEvent(data, options)\n\t\t\t},\n\t\t\twidth: \"min(520px, 100%)\",\n\t\t})\n\n\t\tif (hostedFrame) {\n\t\t\tthis.showIframeLoading(hostedFrame.container, options)\n\t\t\tthis.startIframeWatchdog({\n\t\t\t\tcontainer: hostedFrame.container,\n\t\t\t\tfinalUrl,\n\t\t\t\tlaunchPayload,\n\t\t\t\tloginOptions: options,\n\t\t\t})\n\t\t}\n\t}\n\n\tprivate openLoginPopup(params: LoginParams, options?: LoginUIOptions) {\n\t\tif (typeof window === \"undefined\") return\n\t\tif (this.popup && !safeIsPopupClosed(this.popup)) return\n\n\t\tconst { callbackState, finalUrl, launchPayload } = this.buildOpenContext(\n\t\t\tparams,\n\t\t\toptions,\n\t\t)\n\t\tlogLoginInfo(\"Opening hosted login popup\", {\n\t\t\tappId: params.appId,\n\t\t\tcallbackState,\n\t\t\tcallbackUrl: launchPayload.callbackUrl || null,\n\t\t\thasCallbackUrl: Boolean(launchPayload.callbackUrl),\n\t\t\tloginUrl: finalUrl,\n\t\t\tallowedOrigin: options?.allowedOrigin || null,\n\t\t\tautoClose: options?.autoClose ?? true,\n\t\t\tdisplayMode: \"popup\",\n\t\t\tpageUrl: typeof window !== \"undefined\" ? window.location.href : null,\n\t\t\tparentOrigin: launchPayload.origin || null,\n\t\t})\n\t\tconst popupWidth = 520\n\t\tconst popupHeight = 720\n\t\tconst left = Math.max(\n\t\t\t0,\n\t\t\tMath.round(window.screenX + (window.outerWidth - popupWidth) / 2),\n\t\t)\n\t\tconst top = Math.max(\n\t\t\t0,\n\t\t\tMath.round(window.screenY + (window.outerHeight - popupHeight) / 2),\n\t\t)\n\t\tconst features = [\n\t\t\t\"popup=yes\",\n\t\t\t`width=${popupWidth}`,\n\t\t\t`height=${popupHeight}`,\n\t\t\t`left=${left}`,\n\t\t\t`top=${top}`,\n\t\t\t\"resizable=yes\",\n\t\t\t\"scrollbars=yes\",\n\t\t].join(\",\")\n\n\t\tconst popupName = buildLoginPopupName(launchPayload)\n\t\tconst popup = window.open(finalUrl, popupName, features)\n\t\tif (!popup) {\n\t\t\tlogLoginWarn(\"Popup blocked by the browser\")\n\t\t\toptions?.onError?.(\"Login popup was blocked\")\n\t\t\treturn\n\t\t}\n\n\t\tthis.popup = popup\n\t\tthis.completed = false\n\t\tthis.listenForLoginCallback(callbackState, options)\n\n\t\tconst allowedOrigin = options?.allowedOrigin\n\t\tconst popupOrigin = getOrigin(finalUrl)\n\n\t\tthis.popupMessageHandler = (event: MessageEvent) => {\n\t\t\tif (\n\t\t\t\tallowedOrigin &&\n\t\t\t\tallowedOrigin !== \"*\" &&\n\t\t\t\tevent.origin !== allowedOrigin\n\t\t\t) {\n\t\t\t\tlogLoginWarn(\"Ignored message due to allowedOrigin mismatch\", {\n\t\t\t\t\tallowedOrigin,\n\t\t\t\t\teventOrigin: event.origin,\n\t\t\t\t})\n\t\t\t\treturn\n\t\t\t}\n\t\t\tif (!allowedOrigin && popupOrigin && event.origin !== popupOrigin) {\n\t\t\t\tlogLoginWarn(\"Ignored message due to popup origin mismatch\", {\n\t\t\t\t\texpectedOrigin: popupOrigin,\n\t\t\t\t\teventOrigin: event.origin,\n\t\t\t\t})\n\t\t\t\treturn\n\t\t\t}\n\n\t\t\tconst data = event.data as LoginEventData\n\t\t\tif (!data || typeof data !== \"object\" || !data.type) {\n\t\t\t\tlogLoginDebug(\"Ignored non-login postMessage payload\")\n\t\t\t\treturn\n\t\t\t}\n\n\t\t\tlogLoginInfo(\"Received login event\", {\n\t\t\t\ttype: data.type,\n\t\t\t\teventOrigin: event.origin,\n\t\t\t})\n\n\t\t\tthis.handleLoginEvent(data, options)\n\t\t}\n\n\t\twindow.addEventListener(\"message\", this.popupMessageHandler)\n\n\t\tif (options?.monitorPopupClosed === true) {\n\t\t\tthis.closeMonitor = window.setInterval(() => {\n\t\t\t\tif (!this.popup || safeIsPopupClosed(this.popup)) {\n\t\t\t\t\tconst shouldTreatAsCancel = !this.completed\n\t\t\t\t\tlogLoginInfo(\"Detected popup closed\", {\n\t\t\t\t\t\tshouldTreatAsCancel,\n\t\t\t\t\t})\n\t\t\t\t\tthis.cleanup()\n\t\t\t\t\tif (shouldTreatAsCancel) {\n\t\t\t\t\t\toptions?.onCancel?.()\n\t\t\t\t\t}\n\t\t\t\t\toptions?.onClose?.()\n\t\t\t\t}\n\t\t\t}, 500)\n\t\t}\n\t}\n\n\topenLogin(params: LoginParams, options?: LoginUIOptions) {\n\t\tif (typeof window === \"undefined\") return\n\n\t\tconst displayMode = options?.displayMode ?? \"modal\"\n\t\tif (displayMode === \"popup\") {\n\t\t\tthis.openLoginPopup(params, options)\n\t\t\treturn\n\t\t}\n\t\tthis.openLoginModal(params, options)\n\t}\n}\n\nexport function createLoginUI(): LoginUI {\n\treturn new LoginUI()\n}\n\nhandleLoginCallbackIfPresent({ autoClose: false })\n"],"mappings":"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","names":["panel"]}
|
|
1
|
+
{"version":3,"sources":["../src/client.ts","../src/hosted-modal.ts","../src/login.ts"],"sourcesContent":["/**\n * Youidian Payment SDK - Client Module\n * 用于浏览器端集成,包含支付弹窗、状态轮询等功能\n * 不依赖 Node.js crypto 模块\n */\n\nimport {\n\tapplyLocaleToUrl,\n\tgetAutoResolvedLocale,\n\tHostedFrameModal,\n} from \"./hosted-modal\"\n\n/**\n * Payment event types from checkout pages\n */\nexport type PaymentEventType =\n\t| \"PAYMENT_SUCCESS\"\n\t| \"PAYMENT_CANCELLED\"\n\t| \"PAYMENT_CLOSE\"\n\t| \"PAYMENT_RESIZE\"\n\t| \"PAYMENT_STARTED\"\n\n/**\n * Payment event data from postMessage\n */\nexport interface PaymentEventData {\n\ttype: PaymentEventType\n\torderId?: string\n\theight?: number\n}\n\n/**\n * Order status response\n */\nexport interface OrderStatus {\n\torderId: string\n\tstatus: \"PENDING\" | \"PAID\" | \"CANCELLED\" | \"REFUNDED\" | \"FAILED\"\n\tpaidAt?: string\n\tchannelTransactionId?: string\n}\n\n/**\n * Payment UI Options\n */\nexport interface PaymentUIOptions {\n\tlocale?: string\n\tonSuccess?: (orderId?: string) => void\n\tonCancel?: (orderId?: string) => void\n\tonClose?: () => void\n\t/** Origin to validate postMessage (defaults to '*', set for security) */\n\tallowedOrigin?: string\n}\n\n/**\n * Poll Options\n */\nexport interface PollOptions {\n\t/** Polling interval in ms (default: 3000) */\n\tinterval?: number\n\t/** Timeout in ms (default: 300000 = 5 minutes) */\n\ttimeout?: number\n\t/** Callback on each status check */\n\tonStatusChange?: (status: OrderStatus) => void\n}\n\n/**\n * Client-side Payment UI Helper\n * 浏览器端支付 UI 辅助类,用于弹出支付窗口和轮询订单状态\n */\n/**\n * Params for opening payment directly without manual URL construction\n */\nexport interface PaymentParams {\n\tappId: string\n\tuserId?: string\n\t/** Existing Youidian order ID - opens checkout for an already-created order */\n\torderId?: string\n\t/** Product ID - use with priceId for direct ID-based payment */\n\tproductId?: string\n\t/** Price ID - use with productId for direct ID-based payment */\n\tpriceId?: string\n\t/** Product code - use with locale for code-based payment (alternative to productId/priceId) */\n\tproductCode?: string\n\t/** Optional custom recharge amount in the smallest currency unit */\n\tcustomAmount?: {\n\t\tamount: number\n\t\tcurrency: string\n\t}\n\n\t/**\n\t * @deprecated Use checkoutUrl instead\n\t * Defaults to https://pay.imgto.link\n\t */\n\tbaseUrl?: string\n\n\t/**\n\t * Checkout page URL (e.g. https://pay.youidian.com)\n\t * Defaults to https://pay.imgto.link\n\t */\n\tcheckoutUrl?: string\n}\n\n/**\n * Client-side Payment UI Helper\n * 浏览器端支付 UI 辅助类,用于弹出支付窗口和轮询订单状态\n */\nexport class PaymentUI extends HostedFrameModal<PaymentEventData> {\n\tprivate activeCheckoutAppId: string | null = null\n\tprivate activeCheckoutBaseUrl: string | null = null\n\tprivate activeOrderId: string | null = null\n\tprivate paymentCompleted = false\n\tprivate cancelRequestedOrderId: string | null = null\n\n\tprivate cancelHostedOrder(reason = \"user_cancel\", orderId?: string) {\n\t\tconst targetOrderId = orderId || this.activeOrderId\n\t\tif (\n\t\t\t!targetOrderId ||\n\t\t\t!this.activeCheckoutAppId ||\n\t\t\t!this.activeCheckoutBaseUrl ||\n\t\t\tthis.paymentCompleted ||\n\t\t\tthis.cancelRequestedOrderId === targetOrderId\n\t\t) {\n\t\t\treturn\n\t\t}\n\n\t\tthis.cancelRequestedOrderId = targetOrderId\n\t\tconst url = `${this.activeCheckoutBaseUrl}/api/internal/checkout/cancel-order`\n\t\tconst payload = JSON.stringify({\n\t\t\tappId: this.activeCheckoutAppId,\n\t\t\torderId: targetOrderId,\n\t\t\treason,\n\t\t})\n\n\t\tif (typeof navigator !== \"undefined\" && navigator.sendBeacon) {\n\t\t\tconst sent = navigator.sendBeacon(\n\t\t\t\turl,\n\t\t\t\tnew Blob([payload], { type: \"application/json\" }),\n\t\t\t)\n\t\t\tif (sent) return\n\t\t}\n\n\t\tvoid fetch(url, {\n\t\t\tmethod: \"POST\",\n\t\t\tbody: payload,\n\t\t\theaders: { \"Content-Type\": \"text/plain;charset=UTF-8\" },\n\t\t\tkeepalive: true,\n\t\t\tmode: \"no-cors\",\n\t\t}).catch(() => {\n\t\t\tthis.cancelRequestedOrderId = null\n\t\t})\n\t}\n\n\t/**\n\t * Opens the payment checkout page in an iframe modal.\n\t * @param urlOrParams - The checkout page URL or payment parameters\n\t * @param options - UI options\n\t */\n\topenPayment(urlOrParams: string | PaymentParams, options?: PaymentUIOptions) {\n\t\tif (typeof document === \"undefined\") return // Server-side guard\n\t\tif (this.modal) return // Prevent multiple modals\n\n\t\tlet checkoutUrl: string\n\t\tthis.activeOrderId = null\n\t\tthis.paymentCompleted = false\n\t\tthis.cancelRequestedOrderId = null\n\t\tif (typeof urlOrParams === \"string\") {\n\t\t\tcheckoutUrl = urlOrParams\n\t\t\ttry {\n\t\t\t\tconst parsedUrl = new URL(checkoutUrl)\n\t\t\t\tthis.activeCheckoutBaseUrl = parsedUrl.origin\n\t\t\t\tconst parts = parsedUrl.pathname.split(\"/\").filter(Boolean)\n\t\t\t\tconst checkoutIndex = parts.indexOf(\"checkout\")\n\t\t\t\tthis.activeCheckoutAppId =\n\t\t\t\t\tcheckoutIndex >= 0 ? parts[checkoutIndex + 1] || null : null\n\t\t\t} catch {\n\t\t\t\tthis.activeCheckoutAppId = null\n\t\t\t\tthis.activeCheckoutBaseUrl = null\n\t\t\t}\n\t\t} else {\n\t\t\tconst {\n\t\t\t\tappId,\n\t\t\t\torderId,\n\t\t\t\tproductId,\n\t\t\t\tpriceId,\n\t\t\t\tproductCode,\n\t\t\t\tuserId,\n\t\t\t\tcustomAmount,\n\t\t\t\tcheckoutUrl: checkoutUrlParam,\n\t\t\t\tbaseUrl = \"https://pay.imgto.link\",\n\t\t\t} = urlOrParams\n\n\t\t\t// 优先使用 checkoutUrl,其次 baseUrl,默认 https://pay.imgto.link\n\t\t\tconst base = (checkoutUrlParam || baseUrl).replace(/\\/$/, \"\")\n\t\t\tthis.activeCheckoutAppId = appId\n\t\t\tthis.activeCheckoutBaseUrl = base\n\n\t\t\tconst query = new URLSearchParams()\n\t\t\tif (userId) query.set(\"userId\", userId)\n\t\t\tif (customAmount) {\n\t\t\t\tconst amount = Number(customAmount.amount)\n\t\t\t\tconst currency = customAmount.currency.trim().toUpperCase()\n\t\t\t\tif (!Number.isInteger(amount) || amount <= 0) {\n\t\t\t\t\tthrow new Error(\n\t\t\t\t\t\t\"customAmount.amount must be a positive integer in the smallest currency unit\",\n\t\t\t\t\t)\n\t\t\t\t}\n\t\t\t\tif (!/^[A-Z]{3}$/.test(currency)) {\n\t\t\t\t\tthrow new Error(\n\t\t\t\t\t\t\"customAmount.currency must be a 3-letter currency code\",\n\t\t\t\t\t)\n\t\t\t\t}\n\t\t\t\tquery.set(\"customAmount\", String(amount))\n\t\t\t\tquery.set(\"customCurrency\", currency)\n\t\t\t}\n\n\t\t\tif (orderId) {\n\t\t\t\tconst cleanOrderId = orderId.trim()\n\t\t\t\tif (!cleanOrderId) {\n\t\t\t\t\tthrow new Error(\"orderId is required\")\n\t\t\t\t}\n\t\t\t\tthis.activeOrderId = cleanOrderId\n\t\t\t\tcheckoutUrl = `${base}/checkout/${appId}/orders/${cleanOrderId}`\n\t\t\t\tconst queryString = query.toString()\n\t\t\t\tif (queryString) checkoutUrl += `?${queryString}`\n\t\t\t} else if (productCode) {\n\t\t\t\t// Use product code route\n\t\t\t\tcheckoutUrl = `${base}/checkout/${appId}/code/${productCode}?${query.toString()}`\n\t\t\t} else if (productId && priceId) {\n\t\t\t\t// Use ID-based route\n\t\t\t\tcheckoutUrl = `${base}/checkout/${appId}/${productId}/${priceId}?${query.toString()}`\n\t\t\t} else {\n\t\t\t\tthrow new Error(\n\t\t\t\t\t\"Either orderId, productCode, or both productId and priceId are required\",\n\t\t\t\t)\n\t\t\t}\n\t\t}\n\n\t\tconst finalUrl = applyLocaleToUrl(\n\t\t\tcheckoutUrl,\n\t\t\tgetAutoResolvedLocale(options?.locale),\n\t\t)\n\n\t\tthis.openHostedFrame(finalUrl, {\n\t\t\tallowedOrigin: options?.allowedOrigin,\n\t\t\tonCloseButton: () => {\n\t\t\t\tthis.cancelHostedOrder(\"modal_close\")\n\t\t\t\toptions?.onCancel?.(this.activeOrderId || undefined)\n\t\t\t},\n\t\t\tonMessage: (data, container) => {\n\t\t\t\tswitch (data.type) {\n\t\t\t\t\tcase \"PAYMENT_STARTED\":\n\t\t\t\t\t\tif (data.orderId) {\n\t\t\t\t\t\t\tthis.activeOrderId = data.orderId\n\t\t\t\t\t\t}\n\t\t\t\t\t\tbreak\n\t\t\t\t\tcase \"PAYMENT_SUCCESS\":\n\t\t\t\t\t\tthis.paymentCompleted = true\n\t\t\t\t\t\toptions?.onSuccess?.(data.orderId)\n\t\t\t\t\t\tbreak\n\t\t\t\t\tcase \"PAYMENT_CANCELLED\":\n\t\t\t\t\t\tthis.cancelHostedOrder(\"payment_cancelled\", data.orderId)\n\t\t\t\t\t\toptions?.onCancel?.(data.orderId)\n\t\t\t\t\t\tbreak\n\t\t\t\t\tcase \"PAYMENT_RESIZE\":\n\t\t\t\t\t\tif (data.height) {\n\t\t\t\t\t\t\tconst maxHeight = window.innerHeight * 0.9\n\t\t\t\t\t\t\tconst newHeight = Math.min(data.height, maxHeight)\n\t\t\t\t\t\t\tcontainer.style.height = `${newHeight}px`\n\t\t\t\t\t\t}\n\t\t\t\t\t\tbreak\n\t\t\t\t\tcase \"PAYMENT_CLOSE\":\n\t\t\t\t\t\tthis.cancelHostedOrder(\"payment_close\", data.orderId)\n\t\t\t\t\t\tthis.close()\n\t\t\t\t\t\toptions?.onClose?.()\n\t\t\t\t\t\tbreak\n\t\t\t\t}\n\t\t\t},\n\t\t})\n\t}\n\n\t/**\n\t * Poll order status from integrator's API endpoint\n\t * @param statusUrl - The integrator's API endpoint to check order status\n\t * @param options - Polling options\n\t * @returns Promise that resolves when order is paid or rejects on timeout/failure\n\t */\n\tasync pollOrderStatus(\n\t\tstatusUrl: string,\n\t\toptions?: PollOptions,\n\t): Promise<OrderStatus> {\n\t\tconst interval = options?.interval || 3000\n\t\tconst timeout = options?.timeout || 300000\n\t\tconst startTime = Date.now()\n\n\t\treturn new Promise((resolve, reject) => {\n\t\t\tconst poll = async () => {\n\t\t\t\ttry {\n\t\t\t\t\tconst response = await fetch(statusUrl)\n\t\t\t\t\tif (!response.ok) {\n\t\t\t\t\t\tthrow new Error(`Status check failed: ${response.status}`)\n\t\t\t\t\t}\n\n\t\t\t\t\tconst status: OrderStatus = await response.json()\n\t\t\t\t\toptions?.onStatusChange?.(status)\n\n\t\t\t\t\tif (status.status === \"PAID\") {\n\t\t\t\t\t\tresolve(status)\n\t\t\t\t\t\treturn\n\t\t\t\t\t}\n\n\t\t\t\t\tif (status.status === \"CANCELLED\" || status.status === \"FAILED\") {\n\t\t\t\t\t\treject(new Error(`Order ${status.status.toLowerCase()}`))\n\t\t\t\t\t\treturn\n\t\t\t\t\t}\n\n\t\t\t\t\t// Check timeout\n\t\t\t\t\tif (Date.now() - startTime > timeout) {\n\t\t\t\t\t\treject(new Error(\"Polling timeout\"))\n\t\t\t\t\t\treturn\n\t\t\t\t\t}\n\n\t\t\t\t\t// Continue polling\n\t\t\t\t\tsetTimeout(poll, interval)\n\t\t\t\t} catch (error) {\n\t\t\t\t\t// On network error, continue polling unless timeout\n\t\t\t\t\tif (Date.now() - startTime > timeout) {\n\t\t\t\t\t\treject(error)\n\t\t\t\t\t\treturn\n\t\t\t\t\t}\n\t\t\t\t\tsetTimeout(poll, interval)\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tpoll()\n\t\t})\n\t}\n}\n\n/**\n * Convenience function to create a PaymentUI instance\n */\nexport function createPaymentUI(): PaymentUI {\n\treturn new PaymentUI()\n}\n\nexport type {\n\tLoginCallbackOptions,\n\tLoginDisplayMode,\n\tLoginEventData,\n\tLoginEventType,\n\tLoginParams,\n\tLoginResult,\n\tLoginUIOptions,\n} from \"./login\"\nexport { createLoginUI, handleLoginCallbackIfPresent, LoginUI } from \"./login\"\n","export interface HostedFrameMessage {\n\ttype: string\n\theight?: number\n}\n\ntype HostedFrameOptions<TData extends HostedFrameMessage> = {\n\tallowedOrigin?: string\n\theight?: string\n\tonCloseButton?: () => void\n\tonMessage: (\n\t\tdata: TData,\n\t\tcontainer: HTMLDivElement,\n\t\tevent: MessageEvent,\n\t) => void\n\twidth?: string\n}\n\ntype HostedFrameInstance = {\n\tcontainer: HTMLDivElement\n\tiframe: HTMLIFrameElement\n}\n\nconst SDK_SUPPORTED_LOCALES = [\n\t\"en\",\n\t\"zh-CN\",\n\t\"zh-Hant\",\n\t\"fr\",\n\t\"de\",\n\t\"ja\",\n\t\"es\",\n\t\"ko\",\n\t\"nl\",\n\t\"it\",\n\t\"pt\",\n] as const\n\nconst SDK_DEFAULT_LOCALE = \"zh-CN\"\n\nconst SDK_LOCALE_ALIASES: Record<string, string> = {\n\ten: \"en\",\n\t\"en-us\": \"en\",\n\t\"en-gb\": \"en\",\n\tzh: \"zh-CN\",\n\t\"zh-cn\": \"zh-CN\",\n\t\"zh-tw\": \"zh-Hant\",\n\t\"zh-hk\": \"zh-Hant\",\n\t\"zh-hant\": \"zh-Hant\",\n\t\"zh-hans\": \"zh-CN\",\n\tfr: \"fr\",\n\tde: \"de\",\n\tja: \"ja\",\n\tes: \"es\",\n\tko: \"ko\",\n\tnl: \"nl\",\n\tit: \"it\",\n\tpt: \"pt\",\n}\n\nfunction matchSupportedBaseLocale(locale: string): string | undefined {\n\tconst base = locale.toLowerCase().split(\"-\")[0]\n\treturn SDK_SUPPORTED_LOCALES.find((item) => item.toLowerCase() === base)\n}\n\nexport function normalizeSdkLocale(locale?: string): string | undefined {\n\tif (!locale) return\n\n\tconst sanitized = locale.trim().replace(/_/g, \"-\")\n\tif (!sanitized) return\n\n\tconst lower = sanitized.toLowerCase()\n\tif (SDK_LOCALE_ALIASES[lower]) {\n\t\treturn SDK_LOCALE_ALIASES[lower]\n\t}\n\n\tlet canonical: string | undefined\n\ttry {\n\t\tcanonical = Intl.getCanonicalLocales(sanitized)[0]\n\t} catch {\n\t\tcanonical = undefined\n\t}\n\n\tconst candidates = [canonical, sanitized].filter(Boolean) as string[]\n\n\tfor (const candidate of candidates) {\n\t\tconst candidateLower = candidate.toLowerCase()\n\n\t\tif (SDK_LOCALE_ALIASES[candidateLower]) {\n\t\t\treturn SDK_LOCALE_ALIASES[candidateLower]\n\t\t}\n\t\tif ((SDK_SUPPORTED_LOCALES as readonly string[]).includes(candidate)) {\n\t\t\treturn candidate\n\t\t}\n\n\t\tconst baseMatch = matchSupportedBaseLocale(candidate)\n\t\tif (baseMatch) {\n\t\t\treturn baseMatch\n\t\t}\n\t}\n}\n\nexport function getBrowserLocale(): string | undefined {\n\tif (typeof navigator === \"undefined\") return\n\n\tfor (const candidate of navigator.languages || []) {\n\t\tconst normalized = normalizeSdkLocale(candidate)\n\t\tif (normalized) return normalized\n\t}\n\n\treturn normalizeSdkLocale(navigator.language)\n}\n\nexport function getAutoResolvedLocale(locale?: string): string {\n\treturn normalizeSdkLocale(locale) || getBrowserLocale() || SDK_DEFAULT_LOCALE\n}\n\nexport function applyLocaleToUrl(urlValue: string, locale?: string): string {\n\tif (!locale) return urlValue\n\n\ttry {\n\t\tconst url = new URL(urlValue)\n\t\tconst localePrefix = `/${locale}`\n\t\tif (\n\t\t\t!url.pathname.startsWith(`${localePrefix}/`) &&\n\t\t\turl.pathname !== localePrefix\n\t\t) {\n\t\t\turl.pathname = `${localePrefix}${url.pathname}`\n\t\t}\n\t\treturn url.toString()\n\t} catch (_error) {\n\t\tconst localePrefix = `/${locale}`\n\t\tif (!urlValue.startsWith(`${localePrefix}/`) && urlValue !== localePrefix) {\n\t\t\treturn `${localePrefix}${urlValue.startsWith(\"/\") ? \"\" : \"/\"}${urlValue}`\n\t\t}\n\t\treturn urlValue\n\t}\n}\n\nexport class HostedFrameModal<TData extends HostedFrameMessage> {\n\tprotected iframe: HTMLIFrameElement | null = null\n\tprotected modal: HTMLDivElement | null = null\n\tprotected messageHandler: ((event: MessageEvent) => void) | null = null\n\n\tprotected openHostedFrame(\n\t\turl: string,\n\t\toptions: HostedFrameOptions<TData>,\n\t): HostedFrameInstance | null {\n\t\tif (typeof document === \"undefined\") return null\n\t\tif (this.modal) return null\n\n\t\tthis.modal = document.createElement(\"div\")\n\t\tObject.assign(this.modal.style, {\n\t\t\tposition: \"fixed\",\n\t\t\ttop: \"0\",\n\t\t\tleft: \"0\",\n\t\t\twidth: \"100%\",\n\t\t\theight: \"100%\",\n\t\t\tbackgroundColor: \"rgba(15,23,42,0.52)\",\n\t\t\tdisplay: \"flex\",\n\t\t\talignItems: \"center\",\n\t\t\tjustifyContent: \"center\",\n\t\t\tzIndex: \"9999\",\n\t\t\ttransition: \"opacity 0.3s ease\",\n\t\t\tbackdropFilter: \"blur(14px)\",\n\t\t\tpadding: \"16px\",\n\t\t})\n\n\t\tconst container = document.createElement(\"div\")\n\t\tObject.assign(container.style, {\n\t\t\twidth: options.width || \"450px\",\n\t\t\theight: options.height || \"min(600px, 90vh)\",\n\t\t\tbackgroundColor: \"transparent\",\n\t\t\tborderRadius: \"28px\",\n\t\t\toverflow: \"visible\",\n\t\t\tposition: \"relative\",\n\t\t\tboxShadow: \"none\",\n\t\t\tmaxWidth: \"calc(100vw - 32px)\",\n\t\t\tmaxHeight: \"calc(100vh - 32px)\",\n\t\t\ttransition: \"height 180ms ease\",\n\t\t\twillChange: \"height\",\n\t\t})\n\n\t\tconst closeBtn = document.createElement(\"button\")\n\t\tcloseBtn.innerHTML = \"×\"\n\t\tObject.assign(closeBtn.style, {\n\t\t\tposition: \"absolute\",\n\t\t\tright: \"-14px\",\n\t\t\ttop: \"-14px\",\n\t\t\tfontSize: \"20px\",\n\t\t\twidth: \"36px\",\n\t\t\theight: \"36px\",\n\t\t\tborderRadius: \"9999px\",\n\t\t\tborder: \"1px solid rgba(255,255,255,0.5)\",\n\t\t\tbackground: \"rgba(255,255,255,0.9)\",\n\t\t\tcursor: \"pointer\",\n\t\t\tcolor: \"#475569\",\n\t\t\tzIndex: \"2\",\n\t\t\tboxShadow: \"0 10px 30px rgba(15,23,42,0.16)\",\n\t\t})\n\t\tcloseBtn.onclick = () => {\n\t\t\tthis.close()\n\t\t\toptions.onCloseButton?.()\n\t\t}\n\n\t\tthis.iframe = document.createElement(\"iframe\")\n\t\tthis.iframe.src = url\n\t\tthis.iframe.allow = \"local-network-access\"\n\t\tObject.assign(this.iframe.style, {\n\t\t\twidth: \"100%\",\n\t\t\theight: \"100%\",\n\t\t\tborder: \"none\",\n\t\t\tborderRadius: \"28px\",\n\t\t\tbackground: \"transparent\",\n\t\t\tdisplay: \"block\",\n\t\t})\n\n\t\tcontainer.appendChild(closeBtn)\n\t\tcontainer.appendChild(this.iframe)\n\t\tthis.modal.appendChild(container)\n\t\tdocument.body.appendChild(this.modal)\n\n\t\tthis.messageHandler = (event: MessageEvent) => {\n\t\t\tif (options.allowedOrigin && options.allowedOrigin !== \"*\") {\n\t\t\t\tif (event.origin !== options.allowedOrigin) {\n\t\t\t\t\treturn\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tconst data = event.data as TData\n\t\t\tif (!data || typeof data !== \"object\" || !data.type) {\n\t\t\t\treturn\n\t\t\t}\n\n\t\t\toptions.onMessage(data, container, event)\n\t\t}\n\n\t\twindow.addEventListener(\"message\", this.messageHandler)\n\n\t\treturn {\n\t\t\tcontainer,\n\t\t\tiframe: this.iframe,\n\t\t}\n\t}\n\n\tclose() {\n\t\tif (typeof window === \"undefined\") return\n\n\t\tif (this.messageHandler) {\n\t\t\twindow.removeEventListener(\"message\", this.messageHandler)\n\t\t\tthis.messageHandler = null\n\t\t}\n\n\t\tif (this.modal?.parentNode) {\n\t\t\tthis.modal.parentNode.removeChild(this.modal)\n\t\t}\n\n\t\tthis.modal = null\n\t\tthis.iframe = null\n\t}\n}\n","import {\n\tapplyLocaleToUrl,\n\tgetAutoResolvedLocale,\n\ttype HostedFrameMessage,\n\tHostedFrameModal,\n} from \"./hosted-modal\"\n\nexport type LoginEventType =\n\t| \"LOGIN_READY\"\n\t| \"LOGIN_SUCCESS\"\n\t| \"LOGIN_CANCELLED\"\n\t| \"LOGIN_CLOSE\"\n\t| \"LOGIN_RESIZE\"\n\t| \"LOGIN_ERROR\"\n\nexport type LoginDisplayMode = \"modal\" | \"popup\"\nexport type LoginFallbackRedirectMode = \"auto\" | \"manual\"\n\nexport interface LoginResult {\n\tavatar?: string | null\n\tchannel?: string\n\temail?: string | null\n\texpiresAt?: string\n\tlegacyCasdoorId?: string\n\tloginToken?: string\n\tname?: string | null\n\tusername?: string | null\n\tphoneCountryCode?: string | null\n\tphoneNumber?: string | null\n\tphoneE164?: string | null\n\tphoneVerifiedAt?: string | null\n\tuserId?: string\n\twechatOpenId?: string | null\n\twechatUnionId?: string | null\n}\n\nexport interface LoginEventData extends HostedFrameMessage, LoginResult {\n\ttype: LoginEventType\n\terror?: string\n\tmessage?: string\n}\n\nexport interface LoginUIOptions {\n\t/** Origin to validate postMessage (defaults to '*', set for security) */\n\tallowedOrigin?: string\n\t/** Whether the SDK should close the login surface after receiving LOGIN_CLOSE. Defaults to true. */\n\tautoClose?: boolean\n\t/** Optional same-origin URL used as the no-API OAuth callback landing page. */\n\tcallbackUrl?: string\n\t/**\n\t * How to open the hosted login page. Defaults to \"modal\", which embeds the\n\t * login page in an iframe modal. Use \"popup\" to keep the legacy popup flow.\n\t */\n\tdisplayMode?: LoginDisplayMode\n\t/** Text for the fallback button shown when the iframe does not report readiness. */\n\tfallbackButtonText?: string\n\t/** Description for the fallback panel shown when the iframe does not report readiness. */\n\tfallbackDescription?: string\n\t/**\n\t * Whether the SDK should redirect automatically when iframe loading times out.\n\t * Defaults to \"manual\" to avoid taking over the integrator page when the\n\t * hosted page is only slow to report readiness.\n\t */\n\tfallbackRedirectMode?: LoginFallbackRedirectMode\n\t/** Title for the fallback panel shown when the iframe does not report readiness. */\n\tfallbackTitle?: string\n\t/**\n\t * How long the SDK waits for LOGIN_READY or LOGIN_RESIZE before showing the\n\t * fallback redirect button. Only used when displayMode is \"modal\".\n\t * Defaults to 6000ms.\n\t */\n\tiframeLoadTimeoutMs?: number\n\t/** Description shown while the hosted login iframe is loading. */\n\tloadingDescription?: string\n\t/** Title shown while the hosted login iframe is loading. */\n\tloadingTitle?: string\n\t/**\n\t * Whether to poll popup.closed to detect manual popup closure.\n\t * Only used when displayMode is \"popup\". Defaults to false because COOP can\n\t * make popup.closed unreliable.\n\t */\n\tmonitorPopupClosed?: boolean\n\tonCancel?: () => void\n\tonClose?: () => void\n\tonError?: (message?: string, data?: LoginEventData) => void\n\tonFallbackVisible?: () => void\n\tonSuccess?: (result: LoginResult) => void\n}\n\nexport interface LoginCallbackOptions {\n\t/**\n\t * Whether the callback helper should close the current window after\n\t * publishing the login result. Defaults to false; LoginUI closes the popup\n\t * it opened after receiving the callback event.\n\t */\n\tautoClose?: boolean\n\tonError?: (message?: string, data?: LoginEventData) => void\n\tonResult?: (data: LoginEventData) => void\n\tonSuccess?: (result: LoginResult) => void\n}\n\nexport interface LoginParams {\n\tappId: string\n\n\t/**\n\t * @deprecated Use loginUrl instead\n\t * Defaults to https://pay.imgto.link\n\t */\n\tbaseUrl?: string\n\n\t/**\n\t * Hosted login page base URL (e.g. https://pay.youidian.com)\n\t * Defaults to https://pay.imgto.link\n\t */\n\tloginUrl?: string\n\n\t/**\n\t * Optional locale prefix to prepend to the hosted login path.\n\t * If omitted, the SDK automatically resolves the locale from the browser language.\n\t */\n\tlocale?: string\n\n\t/** Preferred provider/channel code */\n\tpreferredChannel?: string\n}\n\nfunction getOrigin(value?: string): string | null {\n\tif (!value) return null\n\ttry {\n\t\treturn new URL(value).origin\n\t} catch {\n\t\treturn null\n\t}\n}\n\nfunction createLoginCallbackState() {\n\tif (typeof crypto !== \"undefined\" && crypto.randomUUID) {\n\t\treturn crypto.randomUUID().replace(/-/g, \"\")\n\t}\n\treturn `${Date.now().toString(36)}${Math.random().toString(36).slice(2)}`\n}\n\nfunction buildLoginCallbackUrl(callbackState: string, callbackUrl?: string) {\n\tconst baseUrl = callbackUrl || window.location.href\n\tconst url = new URL(baseUrl, window.location.href)\n\tconst returnHash = url.hash.replace(/^#/, \"\")\n\n\turl.hash = \"\"\n\turl.searchParams.set(LOGIN_CALLBACK_MARKER, \"1\")\n\turl.searchParams.set(LOGIN_CALLBACK_STATE_PARAM, callbackState)\n\tif (returnHash) {\n\t\turl.searchParams.set(LOGIN_CALLBACK_RETURN_HASH_PARAM, returnHash)\n\t} else {\n\t\turl.searchParams.delete(LOGIN_CALLBACK_RETURN_HASH_PARAM)\n\t}\n\n\treturn url.toString()\n}\n\nfunction buildLoginLaunchPayload(\n\tparams: LoginParams,\n\toptions?: LoginUIOptions,\n\tcallbackState?: string,\n) {\n\tconst parentOrigin =\n\t\ttypeof window !== \"undefined\" ? window.location.origin : undefined\n\tconst callbackUrl =\n\t\ttypeof window !== \"undefined\" && callbackState\n\t\t\t? buildLoginCallbackUrl(callbackState, options?.callbackUrl)\n\t\t\t: undefined\n\n\treturn {\n\t\tautoClose: options?.autoClose ?? true,\n\t\tcallbackUrl,\n\t\tcallbackState,\n\t\torigin: parentOrigin,\n\t\tpreferredChannel: params.preferredChannel,\n\t}\n}\n\nfunction appendLoginLaunchHash(\n\turlValue: string,\n\tpayload: ReturnType<typeof buildLoginLaunchPayload>,\n) {\n\tconst hashParams = new URLSearchParams()\n\tif (payload.autoClose === false) {\n\t\thashParams.set(\"ydAutoClose\", \"false\")\n\t}\n\tif (payload.origin) {\n\t\thashParams.set(\"ydOrigin\", payload.origin)\n\t}\n\tif (payload.callbackUrl) {\n\t\thashParams.set(\"ydCallbackUrl\", payload.callbackUrl)\n\t}\n\tif (payload.preferredChannel) {\n\t\thashParams.set(\"ydPreferredChannel\", payload.preferredChannel)\n\t}\n\tconst hash = hashParams.toString()\n\tif (!hash) {\n\t\treturn urlValue\n\t}\n\n\ttry {\n\t\tconst url = new URL(urlValue)\n\t\turl.hash = hash\n\t\treturn url.toString()\n\t} catch (_error) {\n\t\treturn `${urlValue}#${hash}`\n\t}\n}\n\nfunction buildLoginPopupName(payload: LoginLaunchPayload) {\n\treturn `youidian-login:${JSON.stringify(payload)}`\n}\n\nfunction buildLoginUrl(\n\tparams: LoginParams,\n\toptions: LoginUIOptions | undefined,\n\tlaunchPayload: LoginLaunchPayload,\n): string {\n\tconst { appId, baseUrl = \"https://pay.imgto.link\", loginUrl } = params\n\tconst rawBase = (loginUrl || baseUrl).replace(/\\/$/, \"\")\n\tconst parentOrigin = launchPayload.origin\n\n\tlet finalUrl: string\n\ttry {\n\t\tconst url = new URL(rawBase)\n\t\tif (!/\\/auth\\/connect\\/[^/]+$/.test(url.pathname)) {\n\t\t\turl.pathname =\n\t\t\t\t`${url.pathname.replace(/\\/$/, \"\")}/auth/connect/${appId}`.replace(\n\t\t\t\t\t/\\/{2,}/g,\n\t\t\t\t\t\"/\",\n\t\t\t\t)\n\t\t}\n\t\tfinalUrl = url.toString()\n\t} catch (_error) {\n\t\tif (/\\/auth\\/connect\\/[^/]+$/.test(rawBase)) {\n\t\t\tfinalUrl = rawBase\n\t\t} else {\n\t\t\tfinalUrl = `${rawBase}/auth/connect/${appId}`.replace(/\\/{2,}/g, \"/\")\n\t\t}\n\t}\n\n\tfinalUrl = applyLocaleToUrl(finalUrl, getAutoResolvedLocale(params.locale))\n\n\ttry {\n\t\tconst url = new URL(finalUrl)\n\t\tif (params.preferredChannel) {\n\t\t\turl.searchParams.set(\"preferredChannel\", params.preferredChannel)\n\t\t}\n\t\tif (options?.autoClose === false) {\n\t\t\turl.searchParams.set(\"autoClose\", \"false\")\n\t\t}\n\t\tif (parentOrigin) {\n\t\t\turl.searchParams.set(\"origin\", parentOrigin)\n\t\t}\n\t\treturn appendLoginLaunchHash(url.toString(), launchPayload)\n\t} catch (_error) {\n\t\tconst searchParams = new URLSearchParams()\n\t\tif (params.preferredChannel) {\n\t\t\tsearchParams.set(\"preferredChannel\", params.preferredChannel)\n\t\t}\n\t\tif (options?.autoClose === false) {\n\t\t\tsearchParams.set(\"autoClose\", \"false\")\n\t\t}\n\t\tif (parentOrigin) {\n\t\t\tsearchParams.set(\"origin\", parentOrigin)\n\t\t}\n\t\tconst query = searchParams.toString()\n\t\tif (!query) {\n\t\t\treturn appendLoginLaunchHash(finalUrl, launchPayload)\n\t\t}\n\t\tconst separator = finalUrl.includes(\"?\") ? \"&\" : \"?\"\n\t\treturn appendLoginLaunchHash(\n\t\t\t`${finalUrl}${separator}${query}`,\n\t\t\tlaunchPayload,\n\t\t)\n\t}\n}\n\nfunction extractLoginResult(data: LoginEventData): LoginResult {\n\treturn {\n\t\tavatar: data.avatar,\n\t\tchannel: data.channel,\n\t\temail: data.email,\n\t\texpiresAt: data.expiresAt,\n\t\tlegacyCasdoorId: data.legacyCasdoorId,\n\t\tloginToken: data.loginToken,\n\t\tname: data.name,\n\t\tusername: data.username,\n\t\tphoneCountryCode: data.phoneCountryCode,\n\t\tphoneNumber: data.phoneNumber,\n\t\tphoneE164: data.phoneE164,\n\t\tphoneVerifiedAt: data.phoneVerifiedAt,\n\t\tuserId: data.userId,\n\t\twechatOpenId: data.wechatOpenId,\n\t\twechatUnionId: data.wechatUnionId,\n\t}\n}\n\nconst LOGIN_UI_LOG_PREFIX = \"[Youidian LoginUI]\"\nconst LOGIN_CALLBACK_MARKER = \"yd_login_callback\"\nconst LOGIN_CALLBACK_RESULT_PARAM = \"yd_login_result\"\nconst LOGIN_CALLBACK_RETURN_HASH_PARAM = \"yd_login_return_hash\"\nconst LOGIN_CALLBACK_STATE_PARAM = \"yd_login_state\"\nconst LOGIN_CALLBACK_STORAGE_PREFIX = \"yd-login-callback:\"\nconst LOGIN_CALLBACK_CURRENT_PAGE_STORAGE_KEY =\n\t\"yd-login-current-page-callback\"\nconst DEFAULT_IFRAME_LOAD_TIMEOUT_MS = 6000\n\ntype LoginLaunchPayload = ReturnType<typeof buildLoginLaunchPayload>\n\nfunction decodeCallbackPayload(value: string): LoginEventData | null {\n\ttry {\n\t\tconst padded = value.padEnd(\n\t\t\tvalue.length + ((4 - (value.length % 4)) % 4),\n\t\t\t\"=\",\n\t\t)\n\t\tconst base64 = padded.replaceAll(\"-\", \"+\").replaceAll(\"_\", \"/\")\n\t\tconst binary = atob(base64)\n\t\tconst json = decodeURIComponent(\n\t\t\tArray.from(\n\t\t\t\tbinary,\n\t\t\t\t(char) => `%${char.charCodeAt(0).toString(16).padStart(2, \"0\")}`,\n\t\t\t).join(\"\"),\n\t\t)\n\t\tconst parsed = JSON.parse(json) as LoginEventData\n\t\treturn parsed && typeof parsed === \"object\" && parsed.type ? parsed : null\n\t} catch {\n\t\treturn null\n\t}\n}\n\nfunction getLoginCallbackChannelName(state: string) {\n\treturn `youidian-login:${state}`\n}\n\nfunction getLoginCallbackStorageKey(state: string) {\n\treturn `${LOGIN_CALLBACK_STORAGE_PREFIX}${state}`\n}\n\nfunction publishLoginCallback(state: string, data: LoginEventData) {\n\ttry {\n\t\tconst channel = new BroadcastChannel(getLoginCallbackChannelName(state))\n\t\tchannel.postMessage(data)\n\t\tchannel.close()\n\t} catch {\n\t\t// BroadcastChannel is not available in every embedded browser.\n\t}\n\n\ttry {\n\t\tconst storageKey = getLoginCallbackStorageKey(state)\n\t\twindow.localStorage.setItem(storageKey, JSON.stringify(data))\n\t\twindow.setTimeout(() => {\n\t\t\ttry {\n\t\t\t\twindow.localStorage.removeItem(storageKey)\n\t\t\t} catch {\n\t\t\t\t// Ignore cleanup failures.\n\t\t\t}\n\t\t}, 800)\n\t} catch {\n\t\t// localStorage may be disabled; postMessage remains available below.\n\t}\n\n\ttry {\n\t\twindow.opener?.postMessage(data, window.location.origin)\n\t} catch {\n\t\t// opener is only an opportunistic fast path.\n\t}\n}\n\nfunction safeIsPopupClosed(popup: Window | null) {\n\tif (!popup) return true\n\ttry {\n\t\treturn popup.closed\n\t} catch {\n\t\tlogLoginDebug(\"Unable to read popup.closed; treating popup as open\")\n\t\treturn false\n\t}\n}\n\nfunction safeClosePopup(popup: Window | null) {\n\tif (!popup) return\n\ttry {\n\t\tpopup.close()\n\t} catch {\n\t\tlogLoginDebug(\"Unable to close popup\")\n\t}\n}\n\nfunction cleanLoginCallbackUrl(url: URL) {\n\turl.searchParams.delete(LOGIN_CALLBACK_MARKER)\n\turl.searchParams.delete(LOGIN_CALLBACK_STATE_PARAM)\n\tconst returnHash = url.searchParams.get(LOGIN_CALLBACK_RETURN_HASH_PARAM)\n\turl.searchParams.delete(LOGIN_CALLBACK_RETURN_HASH_PARAM)\n\turl.hash = returnHash ? `#${returnHash}` : \"\"\n\treturn url.toString()\n}\n\nfunction saveCurrentPageLoginCallback(data: LoginEventData) {\n\ttry {\n\t\twindow.sessionStorage.setItem(\n\t\t\tLOGIN_CALLBACK_CURRENT_PAGE_STORAGE_KEY,\n\t\t\tJSON.stringify({\n\t\t\t\tcreatedAt: Date.now(),\n\t\t\t\tdata,\n\t\t\t}),\n\t\t)\n\t} catch {\n\t\t// sessionStorage may be disabled in some embedded browsers.\n\t}\n}\n\nfunction readCurrentPageLoginCallback() {\n\ttry {\n\t\tconst raw = window.sessionStorage.getItem(\n\t\t\tLOGIN_CALLBACK_CURRENT_PAGE_STORAGE_KEY,\n\t\t)\n\t\tif (!raw) return null\n\t\twindow.sessionStorage.removeItem(LOGIN_CALLBACK_CURRENT_PAGE_STORAGE_KEY)\n\t\tconst parsed = JSON.parse(raw) as {\n\t\t\tcreatedAt?: number\n\t\t\tdata?: LoginEventData\n\t\t} | null\n\t\tconst data = parsed?.data\n\t\treturn data && typeof data === \"object\" && data.type ? data : null\n\t} catch {\n\t\treturn null\n\t}\n}\n\nfunction deliverLoginCallbackData(\n\tdata: LoginEventData,\n\toptions?: LoginCallbackOptions,\n) {\n\toptions?.onResult?.(data)\n\tswitch (data.type) {\n\t\tcase \"LOGIN_SUCCESS\":\n\t\t\toptions?.onSuccess?.(extractLoginResult(data))\n\t\t\tbreak\n\t\tcase \"LOGIN_ERROR\":\n\t\t\toptions?.onError?.(data.message || data.error, data)\n\t\t\tbreak\n\t\tdefault:\n\t\t\tbreak\n\t}\n}\n\nexport function handleLoginCallbackIfPresent(options?: LoginCallbackOptions) {\n\tif (typeof window === \"undefined\") {\n\t\treturn false\n\t}\n\n\tconst url = new URL(window.location.href)\n\tif (url.searchParams.get(LOGIN_CALLBACK_MARKER) !== \"1\") {\n\t\tif (options?.onResult || options?.onSuccess || options?.onError) {\n\t\t\tconst pendingData = readCurrentPageLoginCallback()\n\t\t\tif (pendingData) {\n\t\t\t\tdeliverLoginCallbackData(pendingData, options)\n\t\t\t\treturn true\n\t\t\t}\n\t\t}\n\t\treturn false\n\t}\n\n\tconst state = url.searchParams.get(LOGIN_CALLBACK_STATE_PARAM) || \"\"\n\tconst hashParams = new URLSearchParams(url.hash.replace(/^#/, \"\"))\n\tconst rawResult = hashParams.get(LOGIN_CALLBACK_RESULT_PARAM)\n\tconst data: LoginEventData | null =\n\t\trawResult && state\n\t\t\t? decodeCallbackPayload(rawResult)\n\t\t\t: {\n\t\t\t\t\ttype: \"LOGIN_ERROR\",\n\t\t\t\t\tmessage: \"Missing login callback result\",\n\t\t\t\t}\n\n\ttry {\n\t\tdocument.documentElement.style.visibility = \"hidden\"\n\t} catch {\n\t\t// This is best-effort to avoid a visible callback-page flash.\n\t}\n\n\tif (state && data) {\n\t\tpublishLoginCallback(state, data)\n\t}\n\tif (data && (options?.onResult || options?.onSuccess || options?.onError)) {\n\t\tdeliverLoginCallbackData(data, options)\n\t} else if (data) {\n\t\tsaveCurrentPageLoginCallback(data)\n\t}\n\n\ttry {\n\t\twindow.history.replaceState(null, \"\", cleanLoginCallbackUrl(url))\n\t} catch {\n\t\t// Ignore history cleanup failures.\n\t}\n\n\tif (options?.autoClose === true) {\n\t\twindow.setTimeout(() => {\n\t\t\ttry {\n\t\t\t\twindow.close()\n\t\t\t} catch {\n\t\t\t\t// Some browsers disallow script-closing the current window.\n\t\t\t}\n\t\t}, 30)\n\t\treturn true\n\t}\n\n\ttry {\n\t\tdocument.documentElement.style.visibility = \"\"\n\t} catch {\n\t\t// Ignore visibility restoration failures.\n\t}\n\n\treturn true\n}\n\nfunction logLoginDebug(message: string, details?: Record<string, unknown>) {\n\tif (typeof console === \"undefined\") return\n\tconsole.debug(LOGIN_UI_LOG_PREFIX, message, details || {})\n}\n\nfunction logLoginInfo(message: string, details?: Record<string, unknown>) {\n\tif (typeof console === \"undefined\") return\n\tconsole.info(LOGIN_UI_LOG_PREFIX, message, details || {})\n}\n\nfunction logLoginWarn(message: string, details?: Record<string, unknown>) {\n\tif (typeof console === \"undefined\") return\n\tconsole.warn(LOGIN_UI_LOG_PREFIX, message, details || {})\n}\n\nfunction getIframeLoadTimeoutMs(options?: LoginUIOptions) {\n\tconst timeout = options?.iframeLoadTimeoutMs\n\tif (typeof timeout !== \"number\" || !Number.isFinite(timeout)) {\n\t\treturn DEFAULT_IFRAME_LOAD_TIMEOUT_MS\n\t}\n\treturn Math.max(0, timeout)\n}\n\nfunction applyLoginPanelStyle(panel: HTMLDivElement) {\n\tObject.assign(panel.style, {\n\t\tposition: \"absolute\",\n\t\tinset: \"0\",\n\t\tdisplay: \"flex\",\n\t\talignItems: \"center\",\n\t\tjustifyContent: \"center\",\n\t\tborder: \"1px solid rgba(229,229,229,0.92)\",\n\t\tborderRadius: \"28px\",\n\t\tbackground: \"rgba(255,255,255,0.94)\",\n\t\tcolor: \"#0f172a\",\n\t\tpadding: \"24px\",\n\t\ttextAlign: \"center\",\n\t\tzIndex: \"1\",\n\t\tboxShadow: \"0 18px 50px rgba(15,15,15,0.06)\",\n\t\tbackdropFilter: \"blur(16px)\",\n\t})\n}\n\nfunction createLoginPanelContent() {\n\tconst content = document.createElement(\"div\")\n\tObject.assign(content.style, {\n\t\tmaxWidth: \"360px\",\n\t})\n\n\tconst badge = document.createElement(\"div\")\n\tbadge.textContent = \"YOUiDIAN\"\n\tObject.assign(badge.style, {\n\t\tdisplay: \"inline-flex\",\n\t\talignItems: \"center\",\n\t\tborder: \"1px solid rgba(229,229,229,0.92)\",\n\t\tborderRadius: \"9999px\",\n\t\tbackground: \"#fafafa\",\n\t\tcolor: \"#171717\",\n\t\tfontSize: \"11px\",\n\t\tfontWeight: \"700\",\n\t\tletterSpacing: \"0.22em\",\n\t\tlineHeight: \"1\",\n\t\tmarginBottom: \"18px\",\n\t\tpadding: \"8px 12px\",\n\t})\n\n\tcontent.appendChild(badge)\n\n\treturn content\n}\n\nfunction createLoginPanelTitle(value: string) {\n\tconst title = document.createElement(\"div\")\n\ttitle.textContent = value\n\tObject.assign(title.style, {\n\t\tcolor: \"#171717\",\n\t\tfontSize: \"18px\",\n\t\tfontWeight: \"700\",\n\t\tlineHeight: \"1.35\",\n\t\tmarginBottom: \"10px\",\n\t})\n\treturn title\n}\n\nfunction createLoginPanelDescription(value: string) {\n\tconst description = document.createElement(\"div\")\n\tdescription.textContent = value\n\tObject.assign(description.style, {\n\t\tcolor: \"#525252\",\n\t\tfontSize: \"14px\",\n\t\tlineHeight: \"1.6\",\n\t\tmarginBottom: \"20px\",\n\t})\n\treturn description\n}\n\nfunction ensureLoginLoadingStyles() {\n\tif (document.getElementById(\"youidian-login-loading-style\")) {\n\t\treturn\n\t}\n\tconst style = document.createElement(\"style\")\n\tstyle.id = \"youidian-login-loading-style\"\n\tstyle.textContent =\n\t\t\"@keyframes youidian-login-spin{to{transform:rotate(360deg)}}\"\n\tdocument.head.appendChild(style)\n}\n\nfunction createLoginLoadingPanel(options: {\n\tdescription: string\n\ttitle: string\n}) {\n\tensureLoginLoadingStyles()\n\tconst panel = document.createElement(\"div\")\n\tapplyLoginPanelStyle(panel)\n\n\tconst content = createLoginPanelContent()\n\tconst spinner = document.createElement(\"div\")\n\tObject.assign(spinner.style, {\n\t\twidth: \"22px\",\n\t\theight: \"22px\",\n\t\tborderRadius: \"9999px\",\n\t\tborder: \"2px solid rgba(23,23,23,0.16)\",\n\t\tborderTopColor: \"#171717\",\n\t\tmargin: \"0 auto 18px\",\n\t\tanimation: \"youidian-login-spin 780ms linear infinite\",\n\t})\n\n\tcontent.appendChild(spinner)\n\tcontent.appendChild(createLoginPanelTitle(options.title))\n\tcontent.appendChild(createLoginPanelDescription(options.description))\n\tpanel.appendChild(content)\n\n\treturn panel\n}\n\nfunction createLoginRedirectingPanel(options: {\n\tdescription: string\n\ttitle: string\n}) {\n\treturn createLoginLoadingPanel(options)\n}\n\nfunction createLoginFallbackPanel(options: {\n\tbuttonText: string\n\tdescription: string\n\tonRedirect: () => void\n\ttitle: string\n}) {\n\tconst panel = document.createElement(\"div\")\n\tapplyLoginPanelStyle(panel)\n\n\tconst content = createLoginPanelContent()\n\n\tconst button = document.createElement(\"button\")\n\tbutton.type = \"button\"\n\tbutton.textContent = options.buttonText\n\tObject.assign(button.style, {\n\t\twidth: \"100%\",\n\t\tborder: \"0\",\n\t\tborderRadius: \"12px\",\n\t\tbackground: \"#0a0a0a\",\n\t\tcolor: \"#ffffff\",\n\t\tcursor: \"pointer\",\n\t\tfontSize: \"14px\",\n\t\tfontWeight: \"700\",\n\t\tminHeight: \"44px\",\n\t\tpadding: \"12px 16px\",\n\t\tboxShadow: \"0 12px 28px rgba(17,17,17,0.14)\",\n\t})\n\tbutton.onclick = options.onRedirect\n\n\tcontent.appendChild(createLoginPanelTitle(options.title))\n\tcontent.appendChild(createLoginPanelDescription(options.description))\n\tcontent.appendChild(button)\n\tpanel.appendChild(content)\n\n\treturn panel\n}\n\nexport class LoginUI extends HostedFrameModal<LoginEventData> {\n\tprivate popup: Window | null = null\n\tprivate callbackChannel: BroadcastChannel | null = null\n\tprivate callbackStorageHandler: ((event: StorageEvent) => void) | null = null\n\tprivate popupMessageHandler: ((event: MessageEvent) => void) | null = null\n\tprivate closeMonitor: number | null = null\n\tprivate iframeFallbackPanel: HTMLDivElement | null = null\n\tprivate iframeLoadingPanel: HTMLDivElement | null = null\n\tprivate iframeLoadTimer: number | null = null\n\tprivate iframeRedirectTimer: number | null = null\n\tprivate iframeReady = false\n\tprivate completed = false\n\n\tprivate cleanup() {\n\t\tif (this.callbackChannel) {\n\t\t\tthis.callbackChannel.close()\n\t\t}\n\t\tif (typeof window !== \"undefined\" && this.callbackStorageHandler) {\n\t\t\twindow.removeEventListener(\"storage\", this.callbackStorageHandler)\n\t\t}\n\t\tif (typeof window !== \"undefined\" && this.popupMessageHandler) {\n\t\t\twindow.removeEventListener(\"message\", this.popupMessageHandler)\n\t\t}\n\t\tthis.callbackChannel = null\n\t\tthis.callbackStorageHandler = null\n\t\tif (typeof window !== \"undefined\" && this.closeMonitor) {\n\t\t\twindow.clearInterval(this.closeMonitor)\n\t\t}\n\t\tif (typeof window !== \"undefined\" && this.iframeLoadTimer) {\n\t\t\twindow.clearTimeout(this.iframeLoadTimer)\n\t\t}\n\t\tif (typeof window !== \"undefined\" && this.iframeRedirectTimer) {\n\t\t\twindow.clearTimeout(this.iframeRedirectTimer)\n\t\t}\n\t\tif (this.iframeFallbackPanel?.parentNode) {\n\t\t\tthis.iframeFallbackPanel.parentNode.removeChild(this.iframeFallbackPanel)\n\t\t}\n\t\tif (this.iframeLoadingPanel?.parentNode) {\n\t\t\tthis.iframeLoadingPanel.parentNode.removeChild(this.iframeLoadingPanel)\n\t\t}\n\t\tthis.popupMessageHandler = null\n\t\tthis.closeMonitor = null\n\t\tthis.iframeFallbackPanel = null\n\t\tthis.iframeLoadingPanel = null\n\t\tthis.iframeLoadTimer = null\n\t\tthis.iframeRedirectTimer = null\n\t\tthis.iframeReady = false\n\t\tthis.popup = null\n\t\tthis.completed = false\n\t}\n\n\tprivate markIframeReady() {\n\t\tthis.iframeReady = true\n\t\tif (typeof window !== \"undefined\" && this.iframeLoadTimer) {\n\t\t\twindow.clearTimeout(this.iframeLoadTimer)\n\t\t\tthis.iframeLoadTimer = null\n\t\t}\n\t\tif (typeof window !== \"undefined\" && this.iframeRedirectTimer) {\n\t\t\twindow.clearTimeout(this.iframeRedirectTimer)\n\t\t\tthis.iframeRedirectTimer = null\n\t\t}\n\t\tif (this.iframeFallbackPanel?.parentNode) {\n\t\t\tthis.iframeFallbackPanel.parentNode.removeChild(this.iframeFallbackPanel)\n\t\t}\n\t\tif (this.iframeLoadingPanel?.parentNode) {\n\t\t\tthis.iframeLoadingPanel.parentNode.removeChild(this.iframeLoadingPanel)\n\t\t}\n\t\tthis.iframeFallbackPanel = null\n\t\tthis.iframeLoadingPanel = null\n\t}\n\n\tprivate showIframeLoading(\n\t\tcontainer: HTMLDivElement,\n\t\toptions?: LoginUIOptions,\n\t) {\n\t\tif (this.iframeLoadingPanel || this.iframeReady) {\n\t\t\treturn\n\t\t}\n\n\t\tconst panel = createLoginLoadingPanel({\n\t\t\tdescription:\n\t\t\t\toptions?.loadingDescription ||\n\t\t\t\t\"Please wait while the secure login page opens.\",\n\t\t\ttitle: options?.loadingTitle || \"Opening login page\",\n\t\t})\n\t\tthis.iframeLoadingPanel = panel\n\t\tcontainer.appendChild(panel)\n\t}\n\n\tprivate showIframeFallback(options: {\n\t\tcontainer: HTMLDivElement\n\t\tfinalUrl: string\n\t\tlaunchPayload: LoginLaunchPayload\n\t\tloginOptions?: LoginUIOptions\n\t}) {\n\t\tif (this.iframeReady || this.iframeFallbackPanel) {\n\t\t\treturn\n\t\t}\n\n\t\tconst { container, finalUrl, loginOptions } = options\n\t\tlogLoginWarn(\"Hosted login iframe did not report ready in time\", {\n\t\t\tloginUrl: finalUrl,\n\t\t})\n\t\tif (this.iframeLoadingPanel?.parentNode) {\n\t\t\tthis.iframeLoadingPanel.parentNode.removeChild(this.iframeLoadingPanel)\n\t\t}\n\t\tthis.iframeLoadingPanel = null\n\n\t\tif (loginOptions?.fallbackRedirectMode === \"auto\") {\n\t\t\tconst panel = createLoginRedirectingPanel({\n\t\t\t\tdescription:\n\t\t\t\t\tloginOptions?.fallbackDescription ||\n\t\t\t\t\t\"The embedded login page is taking longer than expected. Redirecting you to the login page now.\",\n\t\t\t\ttitle: loginOptions?.fallbackTitle || \"Redirecting to login page\",\n\t\t\t})\n\t\t\tthis.iframeFallbackPanel = panel\n\t\t\tcontainer.appendChild(panel)\n\t\t\tloginOptions?.onFallbackVisible?.()\n\t\t\tthis.iframeRedirectTimer = window.setTimeout(() => {\n\t\t\t\tthis.iframeRedirectTimer = null\n\t\t\t\tlogLoginInfo(\"Redirecting to hosted login fallback page\", {\n\t\t\t\t\tloginUrl: finalUrl,\n\t\t\t\t})\n\t\t\t\twindow.location.assign(finalUrl)\n\t\t\t}, 350)\n\t\t\treturn\n\t\t}\n\n\t\tconst panel = createLoginFallbackPanel({\n\t\t\tbuttonText: loginOptions?.fallbackButtonText || \"Continue to login\",\n\t\t\tdescription:\n\t\t\t\tloginOptions?.fallbackDescription ||\n\t\t\t\t\"The embedded login page is taking longer than expected. Continue on the login page to finish signing in.\",\n\t\t\ttitle: loginOptions?.fallbackTitle || \"Login page is still loading\",\n\t\t\tonRedirect: () => {\n\t\t\t\tlogLoginInfo(\"Redirecting to hosted login fallback page\", {\n\t\t\t\t\tloginUrl: finalUrl,\n\t\t\t\t})\n\t\t\t\twindow.location.assign(finalUrl)\n\t\t\t},\n\t\t})\n\n\t\tthis.iframeFallbackPanel = panel\n\t\tcontainer.appendChild(panel)\n\t\tloginOptions?.onFallbackVisible?.()\n\t}\n\n\tprivate startIframeWatchdog(options: {\n\t\tcontainer: HTMLDivElement\n\t\tfinalUrl: string\n\t\tlaunchPayload: LoginLaunchPayload\n\t\tloginOptions?: LoginUIOptions\n\t}) {\n\t\tif (typeof window === \"undefined\") return\n\n\t\tconst timeoutMs = getIframeLoadTimeoutMs(options.loginOptions)\n\t\tif (timeoutMs === 0) {\n\t\t\tthis.showIframeFallback(options)\n\t\t\treturn\n\t\t}\n\n\t\tthis.iframeLoadTimer = window.setTimeout(() => {\n\t\t\tthis.iframeLoadTimer = null\n\t\t\tthis.showIframeFallback(options)\n\t\t}, timeoutMs)\n\t}\n\n\tprivate handleLoginEvent(data: LoginEventData, options?: LoginUIOptions) {\n\t\tif (!data || typeof data !== \"object\" || !data.type) {\n\t\t\tlogLoginDebug(\"Ignored non-login event payload\")\n\t\t\treturn\n\t\t}\n\n\t\tlogLoginInfo(\"Received login event\", {\n\t\t\ttype: data.type,\n\t\t})\n\n\t\tswitch (data.type) {\n\t\t\tcase \"LOGIN_READY\":\n\t\t\t\tbreak\n\t\t\tcase \"LOGIN_SUCCESS\":\n\t\t\t\tif (this.completed) {\n\t\t\t\t\tbreak\n\t\t\t\t}\n\t\t\t\tthis.completed = true\n\t\t\t\tlogLoginInfo(\"Login succeeded\", {\n\t\t\t\t\tchannel: data.channel || null,\n\t\t\t\t\tuserId: data.userId || null,\n\t\t\t\t})\n\t\t\t\toptions?.onSuccess?.(extractLoginResult(data))\n\t\t\t\tbreak\n\t\t\tcase \"LOGIN_CANCELLED\":\n\t\t\t\tlogLoginInfo(\"Login cancelled\")\n\t\t\t\toptions?.onCancel?.()\n\t\t\t\tbreak\n\t\t\tcase \"LOGIN_RESIZE\":\n\t\t\t\tbreak\n\t\t\tcase \"LOGIN_ERROR\":\n\t\t\t\tif (this.completed) {\n\t\t\t\t\tbreak\n\t\t\t\t}\n\t\t\t\tlogLoginWarn(\"Login flow reported an error\", {\n\t\t\t\t\tmessage: data.message || data.error || null,\n\t\t\t\t})\n\t\t\t\toptions?.onError?.(data.message || data.error, data)\n\t\t\t\tbreak\n\t\t\tcase \"LOGIN_CLOSE\":\n\t\t\t\tif (options?.autoClose === false) {\n\t\t\t\t\tlogLoginInfo(\n\t\t\t\t\t\t\"Login surface requested close; autoClose disabled, keeping it open\",\n\t\t\t\t\t)\n\t\t\t\t\toptions?.onClose?.()\n\t\t\t\t\tbreak\n\t\t\t\t}\n\t\t\t\tlogLoginInfo(\"Login surface requested close; autoClose enabled\")\n\t\t\t\tthis.close()\n\t\t\t\toptions?.onClose?.()\n\t\t\t\tbreak\n\t\t}\n\t}\n\n\tprivate listenForLoginCallback(\n\t\tcallbackState: string,\n\t\toptions?: LoginUIOptions,\n\t) {\n\t\ttry {\n\t\t\tthis.callbackChannel = new BroadcastChannel(\n\t\t\t\tgetLoginCallbackChannelName(callbackState),\n\t\t\t)\n\t\t\tthis.callbackChannel.onmessage = (event) => {\n\t\t\t\tthis.handleLoginEvent(event.data as LoginEventData, options)\n\t\t\t\tthis.handleLoginEvent({ type: \"LOGIN_CLOSE\" }, options)\n\t\t\t}\n\t\t} catch {\n\t\t\tlogLoginDebug(\"BroadcastChannel is unavailable for login callback\")\n\t\t}\n\n\t\tthis.callbackStorageHandler = (event: StorageEvent) => {\n\t\t\tif (\n\t\t\t\tevent.key !== getLoginCallbackStorageKey(callbackState) ||\n\t\t\t\t!event.newValue\n\t\t\t) {\n\t\t\t\treturn\n\t\t\t}\n\t\t\ttry {\n\t\t\t\tconst data = JSON.parse(event.newValue) as LoginEventData\n\t\t\t\tthis.handleLoginEvent(data, options)\n\t\t\t\tthis.handleLoginEvent({ type: \"LOGIN_CLOSE\" }, options)\n\t\t\t} catch {\n\t\t\t\tlogLoginWarn(\"Failed to parse login callback storage payload\")\n\t\t\t}\n\t\t}\n\t\twindow.addEventListener(\"storage\", this.callbackStorageHandler)\n\t}\n\n\tclose() {\n\t\tlogLoginInfo(\"close() called\", {\n\t\t\thasModal: Boolean(this.modal),\n\t\t\thasPopup: Boolean(this.popup),\n\t\t\tpopupClosed: safeIsPopupClosed(this.popup),\n\t\t})\n\t\tsafeClosePopup(this.popup)\n\t\tsuper.close()\n\t\tthis.cleanup()\n\t}\n\n\tprivate buildOpenContext(params: LoginParams, options?: LoginUIOptions) {\n\t\tconst callbackState = createLoginCallbackState()\n\t\tconst launchPayload = buildLoginLaunchPayload(\n\t\t\tparams,\n\t\t\toptions,\n\t\t\tcallbackState,\n\t\t)\n\t\tconst finalUrl = buildLoginUrl(params, options, launchPayload)\n\t\treturn { callbackState, finalUrl, launchPayload }\n\t}\n\n\tprivate openLoginModal(params: LoginParams, options?: LoginUIOptions) {\n\t\tif (typeof document === \"undefined\") return\n\t\tif (this.modal) return\n\n\t\tconst { callbackState, finalUrl, launchPayload } = this.buildOpenContext(\n\t\t\tparams,\n\t\t\toptions,\n\t\t)\n\t\tconst loginOrigin = getOrigin(finalUrl)\n\t\tlogLoginInfo(\"Opening hosted login iframe modal\", {\n\t\t\tappId: params.appId,\n\t\t\tcallbackState,\n\t\t\tcallbackUrl: launchPayload.callbackUrl || null,\n\t\t\thasCallbackUrl: Boolean(launchPayload.callbackUrl),\n\t\t\tloginUrl: finalUrl,\n\t\t\tallowedOrigin: options?.allowedOrigin || null,\n\t\t\tautoClose: options?.autoClose ?? true,\n\t\t\tdisplayMode: \"modal\",\n\t\t\tpageUrl: typeof window !== \"undefined\" ? window.location.href : null,\n\t\t\tparentOrigin: launchPayload.origin || null,\n\t\t})\n\n\t\tthis.completed = false\n\t\tthis.iframeReady = false\n\t\tthis.listenForLoginCallback(callbackState, options)\n\t\tconst hostedFrame = this.openHostedFrame(finalUrl, {\n\t\t\tallowedOrigin: options?.allowedOrigin || loginOrigin || undefined,\n\t\t\theight: \"min(760px, 94vh)\",\n\t\t\tonCloseButton: () => {\n\t\t\t\toptions?.onCancel?.()\n\t\t\t\toptions?.onClose?.()\n\t\t\t},\n\t\t\tonMessage: (data, container, event) => {\n\t\t\t\tconst isIframeEvent = event.source === this.iframe?.contentWindow\n\t\t\t\tif (\n\t\t\t\t\t(isIframeEvent &&\n\t\t\t\t\t\t(data.type === \"LOGIN_READY\" || data.type === \"LOGIN_RESIZE\")) ||\n\t\t\t\t\tdata.type === \"LOGIN_SUCCESS\" ||\n\t\t\t\t\tdata.type === \"LOGIN_ERROR\"\n\t\t\t\t) {\n\t\t\t\t\tthis.markIframeReady()\n\t\t\t\t}\n\t\t\t\tif (data.type === \"LOGIN_RESIZE\" && data.height) {\n\t\t\t\t\tconst maxHeight = window.innerHeight * 0.94\n\t\t\t\t\tcontainer.style.height = `${Math.min(data.height, maxHeight)}px`\n\t\t\t\t}\n\t\t\t\tthis.handleLoginEvent(data, options)\n\t\t\t},\n\t\t\twidth: \"min(520px, 100%)\",\n\t\t})\n\n\t\tif (hostedFrame) {\n\t\t\tthis.showIframeLoading(hostedFrame.container, options)\n\t\t\tthis.startIframeWatchdog({\n\t\t\t\tcontainer: hostedFrame.container,\n\t\t\t\tfinalUrl,\n\t\t\t\tlaunchPayload,\n\t\t\t\tloginOptions: options,\n\t\t\t})\n\t\t}\n\t}\n\n\tprivate openLoginPopup(params: LoginParams, options?: LoginUIOptions) {\n\t\tif (typeof window === \"undefined\") return\n\t\tif (this.popup && !safeIsPopupClosed(this.popup)) return\n\n\t\tconst { callbackState, finalUrl, launchPayload } = this.buildOpenContext(\n\t\t\tparams,\n\t\t\toptions,\n\t\t)\n\t\tlogLoginInfo(\"Opening hosted login popup\", {\n\t\t\tappId: params.appId,\n\t\t\tcallbackState,\n\t\t\tcallbackUrl: launchPayload.callbackUrl || null,\n\t\t\thasCallbackUrl: Boolean(launchPayload.callbackUrl),\n\t\t\tloginUrl: finalUrl,\n\t\t\tallowedOrigin: options?.allowedOrigin || null,\n\t\t\tautoClose: options?.autoClose ?? true,\n\t\t\tdisplayMode: \"popup\",\n\t\t\tpageUrl: typeof window !== \"undefined\" ? window.location.href : null,\n\t\t\tparentOrigin: launchPayload.origin || null,\n\t\t})\n\t\tconst popupWidth = 520\n\t\tconst popupHeight = 720\n\t\tconst left = Math.max(\n\t\t\t0,\n\t\t\tMath.round(window.screenX + (window.outerWidth - popupWidth) / 2),\n\t\t)\n\t\tconst top = Math.max(\n\t\t\t0,\n\t\t\tMath.round(window.screenY + (window.outerHeight - popupHeight) / 2),\n\t\t)\n\t\tconst features = [\n\t\t\t\"popup=yes\",\n\t\t\t`width=${popupWidth}`,\n\t\t\t`height=${popupHeight}`,\n\t\t\t`left=${left}`,\n\t\t\t`top=${top}`,\n\t\t\t\"resizable=yes\",\n\t\t\t\"scrollbars=yes\",\n\t\t].join(\",\")\n\n\t\tconst popupName = buildLoginPopupName(launchPayload)\n\t\tconst popup = window.open(finalUrl, popupName, features)\n\t\tif (!popup) {\n\t\t\tlogLoginWarn(\"Popup blocked by the browser\")\n\t\t\toptions?.onError?.(\"Login popup was blocked\")\n\t\t\treturn\n\t\t}\n\n\t\tthis.popup = popup\n\t\tthis.completed = false\n\t\tthis.listenForLoginCallback(callbackState, options)\n\n\t\tconst allowedOrigin = options?.allowedOrigin\n\t\tconst popupOrigin = getOrigin(finalUrl)\n\n\t\tthis.popupMessageHandler = (event: MessageEvent) => {\n\t\t\tif (\n\t\t\t\tallowedOrigin &&\n\t\t\t\tallowedOrigin !== \"*\" &&\n\t\t\t\tevent.origin !== allowedOrigin\n\t\t\t) {\n\t\t\t\tlogLoginWarn(\"Ignored message due to allowedOrigin mismatch\", {\n\t\t\t\t\tallowedOrigin,\n\t\t\t\t\teventOrigin: event.origin,\n\t\t\t\t})\n\t\t\t\treturn\n\t\t\t}\n\t\t\tif (!allowedOrigin && popupOrigin && event.origin !== popupOrigin) {\n\t\t\t\tlogLoginWarn(\"Ignored message due to popup origin mismatch\", {\n\t\t\t\t\texpectedOrigin: popupOrigin,\n\t\t\t\t\teventOrigin: event.origin,\n\t\t\t\t})\n\t\t\t\treturn\n\t\t\t}\n\n\t\t\tconst data = event.data as LoginEventData\n\t\t\tif (!data || typeof data !== \"object\" || !data.type) {\n\t\t\t\tlogLoginDebug(\"Ignored non-login postMessage payload\")\n\t\t\t\treturn\n\t\t\t}\n\n\t\t\tlogLoginInfo(\"Received login event\", {\n\t\t\t\ttype: data.type,\n\t\t\t\teventOrigin: event.origin,\n\t\t\t})\n\n\t\t\tthis.handleLoginEvent(data, options)\n\t\t}\n\n\t\twindow.addEventListener(\"message\", this.popupMessageHandler)\n\n\t\tif (options?.monitorPopupClosed === true) {\n\t\t\tthis.closeMonitor = window.setInterval(() => {\n\t\t\t\tif (!this.popup || safeIsPopupClosed(this.popup)) {\n\t\t\t\t\tconst shouldTreatAsCancel = !this.completed\n\t\t\t\t\tlogLoginInfo(\"Detected popup closed\", {\n\t\t\t\t\t\tshouldTreatAsCancel,\n\t\t\t\t\t})\n\t\t\t\t\tthis.cleanup()\n\t\t\t\t\tif (shouldTreatAsCancel) {\n\t\t\t\t\t\toptions?.onCancel?.()\n\t\t\t\t\t}\n\t\t\t\t\toptions?.onClose?.()\n\t\t\t\t}\n\t\t\t}, 500)\n\t\t}\n\t}\n\n\topenLogin(params: LoginParams, options?: LoginUIOptions) {\n\t\tif (typeof window === \"undefined\") return\n\n\t\tconst displayMode = options?.displayMode ?? \"modal\"\n\t\tif (displayMode === \"popup\") {\n\t\t\tthis.openLoginPopup(params, options)\n\t\t\treturn\n\t\t}\n\t\tthis.openLoginModal(params, options)\n\t}\n}\n\nexport function createLoginUI(): LoginUI {\n\treturn new LoginUI()\n}\n\nhandleLoginCallbackIfPresent({ autoClose: false })\n"],"mappings":"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","names":["panel"]}
|
package/dist/client.d.cts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { H as HostedFrameModal } from './login-
|
|
2
|
-
export { L as LoginCallbackOptions, a as LoginDisplayMode, b as LoginEventData, c as LoginEventType, e as LoginParams, f as LoginResult, g as LoginUI, h as LoginUIOptions, i as createLoginUI, j as handleLoginCallbackIfPresent } from './login-
|
|
1
|
+
import { H as HostedFrameModal } from './login-DerOcXcH.cjs';
|
|
2
|
+
export { L as LoginCallbackOptions, a as LoginDisplayMode, b as LoginEventData, c as LoginEventType, e as LoginParams, f as LoginResult, g as LoginUI, h as LoginUIOptions, i as createLoginUI, j as handleLoginCallbackIfPresent } from './login-DerOcXcH.cjs';
|
|
3
3
|
|
|
4
4
|
/**
|
|
5
5
|
* Youidian Payment SDK - Client Module
|
|
@@ -10,7 +10,7 @@ export { L as LoginCallbackOptions, a as LoginDisplayMode, b as LoginEventData,
|
|
|
10
10
|
/**
|
|
11
11
|
* Payment event types from checkout pages
|
|
12
12
|
*/
|
|
13
|
-
type PaymentEventType = "PAYMENT_SUCCESS" | "PAYMENT_CANCELLED" | "PAYMENT_CLOSE" | "PAYMENT_RESIZE";
|
|
13
|
+
type PaymentEventType = "PAYMENT_SUCCESS" | "PAYMENT_CANCELLED" | "PAYMENT_CLOSE" | "PAYMENT_RESIZE" | "PAYMENT_STARTED";
|
|
14
14
|
/**
|
|
15
15
|
* Payment event data from postMessage
|
|
16
16
|
*/
|
|
@@ -59,7 +59,9 @@ interface PollOptions {
|
|
|
59
59
|
*/
|
|
60
60
|
interface PaymentParams {
|
|
61
61
|
appId: string;
|
|
62
|
-
userId
|
|
62
|
+
userId?: string;
|
|
63
|
+
/** Existing Youidian order ID - opens checkout for an already-created order */
|
|
64
|
+
orderId?: string;
|
|
63
65
|
/** Product ID - use with priceId for direct ID-based payment */
|
|
64
66
|
productId?: string;
|
|
65
67
|
/** Price ID - use with productId for direct ID-based payment */
|
|
@@ -87,6 +89,12 @@ interface PaymentParams {
|
|
|
87
89
|
* 浏览器端支付 UI 辅助类,用于弹出支付窗口和轮询订单状态
|
|
88
90
|
*/
|
|
89
91
|
declare class PaymentUI extends HostedFrameModal<PaymentEventData> {
|
|
92
|
+
private activeCheckoutAppId;
|
|
93
|
+
private activeCheckoutBaseUrl;
|
|
94
|
+
private activeOrderId;
|
|
95
|
+
private paymentCompleted;
|
|
96
|
+
private cancelRequestedOrderId;
|
|
97
|
+
private cancelHostedOrder;
|
|
90
98
|
/**
|
|
91
99
|
* Opens the payment checkout page in an iframe modal.
|
|
92
100
|
* @param urlOrParams - The checkout page URL or payment parameters
|
package/dist/client.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { H as HostedFrameModal } from './login-
|
|
2
|
-
export { L as LoginCallbackOptions, a as LoginDisplayMode, b as LoginEventData, c as LoginEventType, e as LoginParams, f as LoginResult, g as LoginUI, h as LoginUIOptions, i as createLoginUI, j as handleLoginCallbackIfPresent } from './login-
|
|
1
|
+
import { H as HostedFrameModal } from './login-DerOcXcH.js';
|
|
2
|
+
export { L as LoginCallbackOptions, a as LoginDisplayMode, b as LoginEventData, c as LoginEventType, e as LoginParams, f as LoginResult, g as LoginUI, h as LoginUIOptions, i as createLoginUI, j as handleLoginCallbackIfPresent } from './login-DerOcXcH.js';
|
|
3
3
|
|
|
4
4
|
/**
|
|
5
5
|
* Youidian Payment SDK - Client Module
|
|
@@ -10,7 +10,7 @@ export { L as LoginCallbackOptions, a as LoginDisplayMode, b as LoginEventData,
|
|
|
10
10
|
/**
|
|
11
11
|
* Payment event types from checkout pages
|
|
12
12
|
*/
|
|
13
|
-
type PaymentEventType = "PAYMENT_SUCCESS" | "PAYMENT_CANCELLED" | "PAYMENT_CLOSE" | "PAYMENT_RESIZE";
|
|
13
|
+
type PaymentEventType = "PAYMENT_SUCCESS" | "PAYMENT_CANCELLED" | "PAYMENT_CLOSE" | "PAYMENT_RESIZE" | "PAYMENT_STARTED";
|
|
14
14
|
/**
|
|
15
15
|
* Payment event data from postMessage
|
|
16
16
|
*/
|
|
@@ -59,7 +59,9 @@ interface PollOptions {
|
|
|
59
59
|
*/
|
|
60
60
|
interface PaymentParams {
|
|
61
61
|
appId: string;
|
|
62
|
-
userId
|
|
62
|
+
userId?: string;
|
|
63
|
+
/** Existing Youidian order ID - opens checkout for an already-created order */
|
|
64
|
+
orderId?: string;
|
|
63
65
|
/** Product ID - use with priceId for direct ID-based payment */
|
|
64
66
|
productId?: string;
|
|
65
67
|
/** Price ID - use with productId for direct ID-based payment */
|
|
@@ -87,6 +89,12 @@ interface PaymentParams {
|
|
|
87
89
|
* 浏览器端支付 UI 辅助类,用于弹出支付窗口和轮询订单状态
|
|
88
90
|
*/
|
|
89
91
|
declare class PaymentUI extends HostedFrameModal<PaymentEventData> {
|
|
92
|
+
private activeCheckoutAppId;
|
|
93
|
+
private activeCheckoutBaseUrl;
|
|
94
|
+
private activeOrderId;
|
|
95
|
+
private paymentCompleted;
|
|
96
|
+
private cancelRequestedOrderId;
|
|
97
|
+
private cancelHostedOrder;
|
|
90
98
|
/**
|
|
91
99
|
* Opens the payment checkout page in an iframe modal.
|
|
92
100
|
* @param urlOrParams - The checkout page URL or payment parameters
|