@youidian/sdk 3.3.10 → 3.4.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/client.cjs +1123 -41
- package/dist/client.cjs.map +1 -1
- package/dist/client.d.cts +74 -4
- package/dist/client.d.ts +74 -4
- package/dist/client.js +1120 -41
- package/dist/client.js.map +1 -1
- package/dist/feedback.cjs +682 -0
- package/dist/feedback.cjs.map +1 -0
- package/dist/feedback.d.cts +38 -0
- package/dist/feedback.d.ts +38 -0
- package/dist/feedback.js +656 -0
- package/dist/feedback.js.map +1 -0
- package/dist/index.cjs +1866 -41
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +4 -3
- package/dist/index.d.ts +4 -3
- package/dist/index.js +1861 -41
- package/dist/index.js.map +1 -1
- package/dist/{login-DerOcXcH.d.cts → login-Dqemys65.d.cts} +8 -4
- package/dist/{login-DerOcXcH.d.ts → login-Dqemys65.d.ts} +8 -4
- package/dist/login.cjs +334 -33
- 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 +334 -33
- package/dist/login.js.map +1 -1
- package/dist/server.cjs +87 -0
- package/dist/server.cjs.map +1 -1
- package/dist/server.d.cts +146 -1
- package/dist/server.d.ts +146 -1
- package/dist/server.js +87 -0
- package/dist/server.js.map +1 -1
- package/package.json +6 -1
package/dist/client.cjs
CHANGED
|
@@ -23,13 +23,231 @@ var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "sy
|
|
|
23
23
|
var client_exports = {};
|
|
24
24
|
__export(client_exports, {
|
|
25
25
|
LoginUI: () => LoginUI,
|
|
26
|
+
MessageUI: () => MessageUI,
|
|
26
27
|
PaymentUI: () => PaymentUI,
|
|
27
28
|
createLoginUI: () => createLoginUI,
|
|
29
|
+
createMessageUI: () => createMessageUI,
|
|
28
30
|
createPaymentUI: () => createPaymentUI,
|
|
31
|
+
detectLoginEnvironment: () => detectLoginEnvironment,
|
|
29
32
|
handleLoginCallbackIfPresent: () => handleLoginCallbackIfPresent
|
|
30
33
|
});
|
|
31
34
|
module.exports = __toCommonJS(client_exports);
|
|
32
35
|
|
|
36
|
+
// src/brand-logo.ts
|
|
37
|
+
function ensureSdkBrandLogoStyles() {
|
|
38
|
+
if (document.getElementById?.("youidian-sdk-brand-logo-style")) {
|
|
39
|
+
return;
|
|
40
|
+
}
|
|
41
|
+
const style = document.createElement("style");
|
|
42
|
+
style.id = "youidian-sdk-brand-logo-style";
|
|
43
|
+
style.textContent = `
|
|
44
|
+
.youidian-sdk-brand-logo__ring,
|
|
45
|
+
.youidian-sdk-brand-logo__dot,
|
|
46
|
+
.youidian-sdk-brand-logo__copy,
|
|
47
|
+
.youidian-sdk-brand-logo__tagline {
|
|
48
|
+
transform-box: fill-box;
|
|
49
|
+
transform-origin: center;
|
|
50
|
+
will-change: opacity, transform;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
.youidian-sdk-brand-logo[data-animated="true"] .youidian-sdk-brand-logo__ring {
|
|
54
|
+
animation: youidian-sdk-brand-logo-ring 1400ms cubic-bezier(0.4, 0, 0.2, 1) infinite;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
.youidian-sdk-brand-logo[data-animated="true"] .youidian-sdk-brand-logo__dot {
|
|
58
|
+
animation: youidian-sdk-brand-logo-dot 1400ms cubic-bezier(0.4, 0, 0.2, 1) infinite;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
.youidian-sdk-brand-logo[data-animated="true"] .youidian-sdk-brand-logo__copy {
|
|
62
|
+
animation: youidian-sdk-brand-logo-copy 1600ms cubic-bezier(0.4, 0, 0.2, 1) infinite;
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
.youidian-sdk-brand-logo[data-animated="true"] .youidian-sdk-brand-logo__tagline {
|
|
66
|
+
animation: youidian-sdk-brand-logo-tagline 1600ms cubic-bezier(0.4, 0, 0.2, 1) infinite;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
@keyframes youidian-sdk-brand-logo-ring {
|
|
70
|
+
0%,
|
|
71
|
+
100% {
|
|
72
|
+
opacity: 0.72;
|
|
73
|
+
transform: rotate(0deg) scale(0.98);
|
|
74
|
+
}
|
|
75
|
+
50% {
|
|
76
|
+
opacity: 1;
|
|
77
|
+
transform: rotate(8deg) scale(1.02);
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
@keyframes youidian-sdk-brand-logo-dot {
|
|
82
|
+
0%,
|
|
83
|
+
100% {
|
|
84
|
+
opacity: 0.58;
|
|
85
|
+
transform: scale(0.9);
|
|
86
|
+
}
|
|
87
|
+
50% {
|
|
88
|
+
opacity: 1;
|
|
89
|
+
transform: scale(1.08);
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
@keyframes youidian-sdk-brand-logo-copy {
|
|
94
|
+
0%,
|
|
95
|
+
100% {
|
|
96
|
+
opacity: 0.86;
|
|
97
|
+
transform: translateY(0);
|
|
98
|
+
}
|
|
99
|
+
50% {
|
|
100
|
+
opacity: 1;
|
|
101
|
+
transform: translateY(-1px);
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
@keyframes youidian-sdk-brand-logo-tagline {
|
|
106
|
+
0%,
|
|
107
|
+
100% {
|
|
108
|
+
opacity: 0.64;
|
|
109
|
+
}
|
|
110
|
+
50% {
|
|
111
|
+
opacity: 0.92;
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
@media (prefers-reduced-motion: reduce) {
|
|
116
|
+
.youidian-sdk-brand-logo__ring,
|
|
117
|
+
.youidian-sdk-brand-logo__dot,
|
|
118
|
+
.youidian-sdk-brand-logo__copy,
|
|
119
|
+
.youidian-sdk-brand-logo__tagline {
|
|
120
|
+
animation: none;
|
|
121
|
+
opacity: 1;
|
|
122
|
+
transform: none;
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
`;
|
|
126
|
+
document.head?.appendChild(style);
|
|
127
|
+
}
|
|
128
|
+
function createSdkBrandLogoMark({
|
|
129
|
+
animated,
|
|
130
|
+
inverted,
|
|
131
|
+
size,
|
|
132
|
+
theme,
|
|
133
|
+
variant = "brand"
|
|
134
|
+
}) {
|
|
135
|
+
ensureSdkBrandLogoStyles();
|
|
136
|
+
const mark = document.createElementNS("http://www.w3.org/2000/svg", "svg");
|
|
137
|
+
mark.setAttribute("viewBox", "0 0 512 512");
|
|
138
|
+
mark.setAttribute("fill", "none");
|
|
139
|
+
mark.setAttribute("aria-hidden", "true");
|
|
140
|
+
Object.assign(mark.style, {
|
|
141
|
+
width: `${size}px`,
|
|
142
|
+
height: `${size}px`,
|
|
143
|
+
color: inverted ? "#ffffff" : theme.primary,
|
|
144
|
+
display: "block",
|
|
145
|
+
flex: "0 0 auto",
|
|
146
|
+
overflow: "visible"
|
|
147
|
+
});
|
|
148
|
+
const logoGroup = document.createElementNS("http://www.w3.org/2000/svg", "g");
|
|
149
|
+
logoGroup.setAttribute(
|
|
150
|
+
"transform",
|
|
151
|
+
variant === "mark" ? "matrix(0.74 0 0 0.74 -124 -114)" : "matrix(0.58 0 0 0.58 -40 -31)"
|
|
152
|
+
);
|
|
153
|
+
const ring = document.createElementNS("http://www.w3.org/2000/svg", "path");
|
|
154
|
+
ring.setAttribute("class", animated ? "youidian-sdk-brand-logo__ring" : "");
|
|
155
|
+
ring.setAttribute("fill", inverted ? "currentColor" : theme.primary);
|
|
156
|
+
ring.setAttribute(
|
|
157
|
+
"d",
|
|
158
|
+
"M704.298 679.54A264 264 0 1 1 704.298 309.46A49 49 0 0 1 634.4 378.149A166 166 0 1 0 634.4 610.851A49 49 0 0 1 704.298 679.54Z"
|
|
159
|
+
);
|
|
160
|
+
const dot = document.createElementNS("http://www.w3.org/2000/svg", "circle");
|
|
161
|
+
dot.setAttribute("class", animated ? "youidian-sdk-brand-logo__dot" : "");
|
|
162
|
+
dot.setAttribute("fill", inverted ? "currentColor" : theme.secondary);
|
|
163
|
+
dot.setAttribute("cx", "714.5");
|
|
164
|
+
dot.setAttribute("cy", "490.5");
|
|
165
|
+
dot.setAttribute("r", "68");
|
|
166
|
+
dot.setAttribute("opacity", inverted ? "0.78" : "1");
|
|
167
|
+
logoGroup.appendChild(ring);
|
|
168
|
+
logoGroup.appendChild(dot);
|
|
169
|
+
mark.appendChild(logoGroup);
|
|
170
|
+
return mark;
|
|
171
|
+
}
|
|
172
|
+
function createSdkBrandLogo({
|
|
173
|
+
animated,
|
|
174
|
+
brand,
|
|
175
|
+
brandWidth,
|
|
176
|
+
copyWidth,
|
|
177
|
+
gap = 10,
|
|
178
|
+
markMarginRight,
|
|
179
|
+
markSize,
|
|
180
|
+
nameSize,
|
|
181
|
+
subtitleMarginTop = 6,
|
|
182
|
+
subtitleSize,
|
|
183
|
+
subtitleWeight = "800",
|
|
184
|
+
theme,
|
|
185
|
+
variant = "brand"
|
|
186
|
+
}) {
|
|
187
|
+
ensureSdkBrandLogoStyles();
|
|
188
|
+
const wrapper = document.createElement("div");
|
|
189
|
+
wrapper.className = "youidian-sdk-brand-logo";
|
|
190
|
+
wrapper.setAttribute("data-animated", animated ? "true" : "false");
|
|
191
|
+
Object.assign(wrapper.style, {
|
|
192
|
+
display: "inline-flex",
|
|
193
|
+
alignItems: "center",
|
|
194
|
+
justifyContent: "center",
|
|
195
|
+
gap: `${gap}px`,
|
|
196
|
+
width: brandWidth ? `${brandWidth}px` : void 0
|
|
197
|
+
});
|
|
198
|
+
const copy = document.createElement("div");
|
|
199
|
+
copy.className = "youidian-sdk-brand-logo__copy";
|
|
200
|
+
copy.setAttribute("data-brand-locale", brand.language);
|
|
201
|
+
Object.assign(copy.style, {
|
|
202
|
+
display: "flex",
|
|
203
|
+
flexDirection: "column",
|
|
204
|
+
alignItems: "flex-start",
|
|
205
|
+
justifyContent: "center",
|
|
206
|
+
lineHeight: "1",
|
|
207
|
+
width: copyWidth ? `${copyWidth}px` : void 0
|
|
208
|
+
});
|
|
209
|
+
const name = document.createElement("div");
|
|
210
|
+
name.className = "youidian-sdk-brand-logo__name";
|
|
211
|
+
name.textContent = brand.name;
|
|
212
|
+
Object.assign(name.style, {
|
|
213
|
+
color: theme.foreground,
|
|
214
|
+
fontFamily: brand.language === "zh" ? '"Noto Sans TC", "Inter", -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif' : '"Unbounded", "Space Grotesk", "Inter", -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif',
|
|
215
|
+
fontSize: `${nameSize}px`,
|
|
216
|
+
fontWeight: brand.language === "zh" ? "900" : "800",
|
|
217
|
+
letterSpacing: brand.language === "zh" ? "0.08em" : "0.01em",
|
|
218
|
+
lineHeight: "1",
|
|
219
|
+
whiteSpace: "nowrap"
|
|
220
|
+
});
|
|
221
|
+
const subtitle = document.createElement("div");
|
|
222
|
+
subtitle.className = "youidian-sdk-brand-logo__tagline";
|
|
223
|
+
subtitle.textContent = brand.subtitle;
|
|
224
|
+
Object.assign(subtitle.style, {
|
|
225
|
+
color: theme.muted,
|
|
226
|
+
fontFamily: brand.language === "zh" ? '"Noto Sans TC", "Inter", -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif' : '"Space Grotesk", "Inter", -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif',
|
|
227
|
+
fontSize: `${subtitleSize}px`,
|
|
228
|
+
fontWeight: subtitleWeight,
|
|
229
|
+
letterSpacing: brand.language === "zh" ? "0.24em" : "0.07em",
|
|
230
|
+
lineHeight: "1",
|
|
231
|
+
marginTop: `${subtitleMarginTop}px`,
|
|
232
|
+
textTransform: brand.language === "zh" ? "none" : "uppercase",
|
|
233
|
+
whiteSpace: "nowrap"
|
|
234
|
+
});
|
|
235
|
+
copy.appendChild(name);
|
|
236
|
+
copy.appendChild(subtitle);
|
|
237
|
+
const mark = createSdkBrandLogoMark({
|
|
238
|
+
animated,
|
|
239
|
+
size: markSize,
|
|
240
|
+
theme,
|
|
241
|
+
variant
|
|
242
|
+
});
|
|
243
|
+
if (typeof markMarginRight === "number") {
|
|
244
|
+
mark.style.marginRight = `${markMarginRight}px`;
|
|
245
|
+
}
|
|
246
|
+
wrapper.appendChild(mark);
|
|
247
|
+
wrapper.appendChild(copy);
|
|
248
|
+
return wrapper;
|
|
249
|
+
}
|
|
250
|
+
|
|
33
251
|
// src/hosted-modal.ts
|
|
34
252
|
var SDK_SUPPORTED_LOCALES = [
|
|
35
253
|
"en",
|
|
@@ -153,7 +371,7 @@ var HostedFrameModal = class {
|
|
|
153
371
|
const container = document.createElement("div");
|
|
154
372
|
Object.assign(container.style, {
|
|
155
373
|
width: options.width || "450px",
|
|
156
|
-
height: options.height || "min(
|
|
374
|
+
height: options.height || "min(760px, calc(100vh - 32px))",
|
|
157
375
|
backgroundColor: "transparent",
|
|
158
376
|
borderRadius: "28px",
|
|
159
377
|
overflow: "visible",
|
|
@@ -161,8 +379,7 @@ var HostedFrameModal = class {
|
|
|
161
379
|
boxShadow: "none",
|
|
162
380
|
maxWidth: "calc(100vw - 32px)",
|
|
163
381
|
maxHeight: "calc(100vh - 32px)",
|
|
164
|
-
transition: "
|
|
165
|
-
willChange: "height"
|
|
382
|
+
transition: "none"
|
|
166
383
|
});
|
|
167
384
|
const closeBtn = document.createElement("button");
|
|
168
385
|
closeBtn.innerHTML = "\xD7";
|
|
@@ -232,6 +449,91 @@ var HostedFrameModal = class {
|
|
|
232
449
|
}
|
|
233
450
|
};
|
|
234
451
|
|
|
452
|
+
// src/environment.ts
|
|
453
|
+
function normalizeText(value) {
|
|
454
|
+
return value || "";
|
|
455
|
+
}
|
|
456
|
+
function getRuntimeInput() {
|
|
457
|
+
if (typeof navigator === "undefined") {
|
|
458
|
+
return {};
|
|
459
|
+
}
|
|
460
|
+
const nav = navigator;
|
|
461
|
+
const coarsePointer = typeof window !== "undefined" && typeof window.matchMedia === "function" ? window.matchMedia("(pointer: coarse)").matches : void 0;
|
|
462
|
+
return {
|
|
463
|
+
coarsePointer,
|
|
464
|
+
maxTouchPoints: nav.maxTouchPoints || 0,
|
|
465
|
+
platform: nav.platform || "",
|
|
466
|
+
standalone: nav.standalone,
|
|
467
|
+
userAgent: nav.userAgent || "",
|
|
468
|
+
userAgentDataMobile: nav.userAgentData?.mobile
|
|
469
|
+
};
|
|
470
|
+
}
|
|
471
|
+
function includesAny(value, patterns) {
|
|
472
|
+
return patterns.some((pattern) => pattern.test(value));
|
|
473
|
+
}
|
|
474
|
+
function detectLoginEnvironment(input = getRuntimeInput()) {
|
|
475
|
+
const userAgent = normalizeText(input.userAgent);
|
|
476
|
+
const platform = normalizeText(input.platform);
|
|
477
|
+
const rawMaxTouchPoints = input.maxTouchPoints ?? 0;
|
|
478
|
+
const maxTouchPoints = Number.isFinite(rawMaxTouchPoints) ? Math.max(0, rawMaxTouchPoints) : 0;
|
|
479
|
+
const isCoarsePointer = input.coarsePointer === true;
|
|
480
|
+
const isTouch = maxTouchPoints > 0 || isCoarsePointer;
|
|
481
|
+
const isWeChat = /micromessenger/i.test(userAgent);
|
|
482
|
+
const isAndroid = /\bandroid\b/i.test(userAgent);
|
|
483
|
+
const hasExplicitIOSDevice = /\b(iPad|iPhone|iPod)\b/i.test(userAgent);
|
|
484
|
+
const hasMacintoshUserAgent = /\bMacintosh\b/i.test(userAgent);
|
|
485
|
+
const hasMacPlatform = /^Mac/i.test(platform);
|
|
486
|
+
const isIPadOS = !hasExplicitIOSDevice && hasMacintoshUserAgent && hasMacPlatform && typeof input.standalone !== "undefined" && maxTouchPoints > 2;
|
|
487
|
+
const isIOS = hasExplicitIOSDevice || isIPadOS;
|
|
488
|
+
const isTabletByUa = includesAny(userAgent, [
|
|
489
|
+
/\biPad\b/i,
|
|
490
|
+
/\btablet\b/i,
|
|
491
|
+
/\bplaybook\b/i,
|
|
492
|
+
/\bsilk\b(?!.*\bmobile\b)/i,
|
|
493
|
+
/\bkindle\b/i,
|
|
494
|
+
/\bnexus 7\b/i,
|
|
495
|
+
/\bnexus 9\b/i,
|
|
496
|
+
/\bxoom\b/i,
|
|
497
|
+
/\bsm-t\d+/i,
|
|
498
|
+
/\bgt-p\d+/i,
|
|
499
|
+
/\bmi pad\b/i
|
|
500
|
+
]);
|
|
501
|
+
const isMobileByUa = includesAny(userAgent, [
|
|
502
|
+
/\bMobile\b/i,
|
|
503
|
+
/\biPhone\b/i,
|
|
504
|
+
/\biPod\b/i,
|
|
505
|
+
/\bWindows Phone\b/i,
|
|
506
|
+
/\bIEMobile\b/i,
|
|
507
|
+
/\bBlackBerry\b/i,
|
|
508
|
+
/\bBB10\b/i,
|
|
509
|
+
/\bOpera Mini\b/i,
|
|
510
|
+
/\bOpera Mobi\b/i,
|
|
511
|
+
/\bwebOS\b/i
|
|
512
|
+
]);
|
|
513
|
+
const isAndroidTablet = isAndroid && !/\bMobile\b/i.test(userAgent);
|
|
514
|
+
const isTablet = isIPadOS || isTabletByUa || isAndroidTablet;
|
|
515
|
+
const isMobile = input.userAgentDataMobile === true || isMobileByUa || isAndroid && !isTablet || isIOS && !isTablet;
|
|
516
|
+
const deviceType = isTablet ? "tablet" : isMobile ? "mobile" : userAgent || platform || isTouch ? "desktop" : "unknown";
|
|
517
|
+
const shouldUseRedirectLogin = deviceType === "mobile" || deviceType === "tablet" || isWeChat;
|
|
518
|
+
return {
|
|
519
|
+
deviceType,
|
|
520
|
+
isAndroid,
|
|
521
|
+
isCoarsePointer,
|
|
522
|
+
isDesktop: deviceType === "desktop",
|
|
523
|
+
isIOS,
|
|
524
|
+
isIPadOS,
|
|
525
|
+
isMobile,
|
|
526
|
+
isStandalone: input.standalone === true,
|
|
527
|
+
isTablet,
|
|
528
|
+
isTouch,
|
|
529
|
+
isWeChat,
|
|
530
|
+
maxTouchPoints,
|
|
531
|
+
platform,
|
|
532
|
+
shouldUseRedirectLogin,
|
|
533
|
+
userAgent
|
|
534
|
+
};
|
|
535
|
+
}
|
|
536
|
+
|
|
235
537
|
// src/login.ts
|
|
236
538
|
function getOrigin(value) {
|
|
237
539
|
if (!value) return null;
|
|
@@ -241,6 +543,15 @@ function getOrigin(value) {
|
|
|
241
543
|
return null;
|
|
242
544
|
}
|
|
243
545
|
}
|
|
546
|
+
function isValidLoginRedirectUrl(value) {
|
|
547
|
+
if (!value) return false;
|
|
548
|
+
try {
|
|
549
|
+
const url = new URL(value);
|
|
550
|
+
return url.protocol === "https:" || url.protocol === "http:";
|
|
551
|
+
} catch {
|
|
552
|
+
return false;
|
|
553
|
+
}
|
|
554
|
+
}
|
|
244
555
|
function createLoginCallbackState() {
|
|
245
556
|
if (typeof crypto !== "undefined" && crypto.randomUUID) {
|
|
246
557
|
return crypto.randomUUID().replace(/-/g, "");
|
|
@@ -587,6 +898,24 @@ function applyLoginPanelStyle(panel) {
|
|
|
587
898
|
backdropFilter: "blur(16px)"
|
|
588
899
|
});
|
|
589
900
|
}
|
|
901
|
+
function applyLoginLoadingPanelStyle(panel) {
|
|
902
|
+
Object.assign(panel.style, {
|
|
903
|
+
position: "absolute",
|
|
904
|
+
inset: "0",
|
|
905
|
+
display: "flex",
|
|
906
|
+
alignItems: "center",
|
|
907
|
+
justifyContent: "center",
|
|
908
|
+
border: "0",
|
|
909
|
+
borderRadius: "28px",
|
|
910
|
+
background: "rgba(255,255,255,0.94)",
|
|
911
|
+
color: "#0f172a",
|
|
912
|
+
padding: "24px",
|
|
913
|
+
textAlign: "center",
|
|
914
|
+
zIndex: "1",
|
|
915
|
+
boxShadow: "none",
|
|
916
|
+
backdropFilter: "blur(16px)"
|
|
917
|
+
});
|
|
918
|
+
}
|
|
590
919
|
function createLoginPanelContent() {
|
|
591
920
|
const content = document.createElement("div");
|
|
592
921
|
Object.assign(content.style, {
|
|
@@ -611,6 +940,71 @@ function createLoginPanelContent() {
|
|
|
611
940
|
content.appendChild(badge);
|
|
612
941
|
return content;
|
|
613
942
|
}
|
|
943
|
+
function createBrandLoadingMark() {
|
|
944
|
+
const logo = document.createElementNS("http://www.w3.org/2000/svg", "svg");
|
|
945
|
+
logo.setAttribute("viewBox", "0 0 1024 1024");
|
|
946
|
+
logo.setAttribute("fill", "none");
|
|
947
|
+
logo.setAttribute("aria-hidden", "true");
|
|
948
|
+
Object.assign(logo.style, {
|
|
949
|
+
width: "112px",
|
|
950
|
+
height: "112px",
|
|
951
|
+
color: "#22c55e",
|
|
952
|
+
display: "block",
|
|
953
|
+
overflow: "visible"
|
|
954
|
+
});
|
|
955
|
+
const group = document.createElementNS("http://www.w3.org/2000/svg", "g");
|
|
956
|
+
group.setAttribute("fill", "currentColor");
|
|
957
|
+
const ring = document.createElementNS("http://www.w3.org/2000/svg", "path");
|
|
958
|
+
ring.setAttribute(
|
|
959
|
+
"d",
|
|
960
|
+
"M704.298 679.54A264 264 0 1 1 704.298 309.46A49 49 0 0 1 634.4 378.149A166 166 0 1 0 634.4 610.851A49 49 0 0 1 704.298 679.54Z"
|
|
961
|
+
);
|
|
962
|
+
ring.setAttribute("class", "youidian-sdk-brand-loading__ring");
|
|
963
|
+
const dot = document.createElementNS("http://www.w3.org/2000/svg", "circle");
|
|
964
|
+
dot.setAttribute("class", "youidian-sdk-brand-loading__dot");
|
|
965
|
+
dot.setAttribute("cx", "714.5");
|
|
966
|
+
dot.setAttribute("cy", "490.5");
|
|
967
|
+
dot.setAttribute("r", "68");
|
|
968
|
+
group.appendChild(ring);
|
|
969
|
+
group.appendChild(dot);
|
|
970
|
+
logo.appendChild(group);
|
|
971
|
+
return logo;
|
|
972
|
+
}
|
|
973
|
+
function createBrandLoadingCopy() {
|
|
974
|
+
const brand = document.createElement("div");
|
|
975
|
+
brand.className = "youidian-sdk-brand-loading__copy";
|
|
976
|
+
Object.assign(brand.style, {
|
|
977
|
+
display: "flex",
|
|
978
|
+
flexDirection: "column",
|
|
979
|
+
alignItems: "flex-start",
|
|
980
|
+
justifyContent: "center",
|
|
981
|
+
lineHeight: "1"
|
|
982
|
+
});
|
|
983
|
+
const name = document.createElement("div");
|
|
984
|
+
name.className = "youidian-sdk-brand-loading__name";
|
|
985
|
+
name.textContent = "\u4F18\u6613\u70B9";
|
|
986
|
+
Object.assign(name.style, {
|
|
987
|
+
color: "#0f172a",
|
|
988
|
+
fontSize: "34px",
|
|
989
|
+
fontWeight: "900",
|
|
990
|
+
letterSpacing: "0",
|
|
991
|
+
lineHeight: "1"
|
|
992
|
+
});
|
|
993
|
+
const tagline = document.createElement("div");
|
|
994
|
+
tagline.className = "youidian-sdk-brand-loading__tagline";
|
|
995
|
+
tagline.textContent = "\u5F00\u53D1\u8005\u670D\u52A1\u4E2D\u53F0";
|
|
996
|
+
Object.assign(tagline.style, {
|
|
997
|
+
color: "#64748b",
|
|
998
|
+
fontSize: "16px",
|
|
999
|
+
fontWeight: "700",
|
|
1000
|
+
letterSpacing: "0.24em",
|
|
1001
|
+
lineHeight: "1",
|
|
1002
|
+
marginTop: "6px"
|
|
1003
|
+
});
|
|
1004
|
+
brand.appendChild(name);
|
|
1005
|
+
brand.appendChild(tagline);
|
|
1006
|
+
return brand;
|
|
1007
|
+
}
|
|
614
1008
|
function createLoginPanelTitle(value) {
|
|
615
1009
|
const title = document.createElement("div");
|
|
616
1010
|
title.textContent = value;
|
|
@@ -640,32 +1034,111 @@ function ensureLoginLoadingStyles() {
|
|
|
640
1034
|
}
|
|
641
1035
|
const style = document.createElement("style");
|
|
642
1036
|
style.id = "youidian-login-loading-style";
|
|
643
|
-
style.textContent =
|
|
1037
|
+
style.textContent = `
|
|
1038
|
+
.youidian-sdk-brand-loading__ring,
|
|
1039
|
+
.youidian-sdk-brand-loading__dot {
|
|
1040
|
+
transform-box: fill-box;
|
|
1041
|
+
transform-origin: center;
|
|
1042
|
+
will-change: opacity, transform;
|
|
1043
|
+
}
|
|
1044
|
+
|
|
1045
|
+
.youidian-sdk-brand-loading__ring {
|
|
1046
|
+
animation: youidian-sdk-brand-loading-ring 1400ms cubic-bezier(0.4, 0, 0.2, 1) infinite;
|
|
1047
|
+
}
|
|
1048
|
+
|
|
1049
|
+
.youidian-sdk-brand-loading__dot {
|
|
1050
|
+
animation: youidian-sdk-brand-loading-dot 1400ms cubic-bezier(0.4, 0, 0.2, 1) infinite;
|
|
1051
|
+
}
|
|
1052
|
+
|
|
1053
|
+
.youidian-sdk-brand-loading__copy {
|
|
1054
|
+
will-change: opacity, transform;
|
|
1055
|
+
animation: youidian-sdk-brand-loading-copy 1600ms cubic-bezier(0.4, 0, 0.2, 1) infinite;
|
|
1056
|
+
}
|
|
1057
|
+
|
|
1058
|
+
.youidian-sdk-brand-loading__tagline {
|
|
1059
|
+
will-change: opacity;
|
|
1060
|
+
animation: youidian-sdk-brand-loading-tagline 1600ms cubic-bezier(0.4, 0, 0.2, 1) infinite;
|
|
1061
|
+
}
|
|
1062
|
+
|
|
1063
|
+
@keyframes youidian-sdk-brand-loading-ring {
|
|
1064
|
+
0%,
|
|
1065
|
+
100% {
|
|
1066
|
+
opacity: 0.72;
|
|
1067
|
+
transform: rotate(0deg) scale(0.98);
|
|
1068
|
+
}
|
|
1069
|
+
50% {
|
|
1070
|
+
opacity: 1;
|
|
1071
|
+
transform: rotate(8deg) scale(1.02);
|
|
1072
|
+
}
|
|
1073
|
+
}
|
|
1074
|
+
|
|
1075
|
+
@keyframes youidian-sdk-brand-loading-dot {
|
|
1076
|
+
0%,
|
|
1077
|
+
100% {
|
|
1078
|
+
opacity: 0.55;
|
|
1079
|
+
transform: scale(0.9);
|
|
1080
|
+
}
|
|
1081
|
+
50% {
|
|
1082
|
+
opacity: 1;
|
|
1083
|
+
transform: scale(1.08);
|
|
1084
|
+
}
|
|
1085
|
+
}
|
|
1086
|
+
|
|
1087
|
+
@keyframes youidian-sdk-brand-loading-copy {
|
|
1088
|
+
0%,
|
|
1089
|
+
100% {
|
|
1090
|
+
opacity: 0.86;
|
|
1091
|
+
transform: translateY(0);
|
|
1092
|
+
}
|
|
1093
|
+
50% {
|
|
1094
|
+
opacity: 1;
|
|
1095
|
+
transform: translateY(-1px);
|
|
1096
|
+
}
|
|
1097
|
+
}
|
|
1098
|
+
|
|
1099
|
+
@keyframes youidian-sdk-brand-loading-tagline {
|
|
1100
|
+
0%,
|
|
1101
|
+
100% {
|
|
1102
|
+
opacity: 0.64;
|
|
1103
|
+
}
|
|
1104
|
+
50% {
|
|
1105
|
+
opacity: 0.92;
|
|
1106
|
+
}
|
|
1107
|
+
}
|
|
1108
|
+
|
|
1109
|
+
@media (prefers-reduced-motion: reduce) {
|
|
1110
|
+
.youidian-sdk-brand-loading__ring,
|
|
1111
|
+
.youidian-sdk-brand-loading__dot,
|
|
1112
|
+
.youidian-sdk-brand-loading__copy,
|
|
1113
|
+
.youidian-sdk-brand-loading__tagline {
|
|
1114
|
+
animation: none;
|
|
1115
|
+
opacity: 1;
|
|
1116
|
+
transform: none;
|
|
1117
|
+
}
|
|
1118
|
+
}
|
|
1119
|
+
`;
|
|
644
1120
|
document.head.appendChild(style);
|
|
645
1121
|
}
|
|
646
|
-
function createLoginLoadingPanel(
|
|
1122
|
+
function createLoginLoadingPanel() {
|
|
647
1123
|
ensureLoginLoadingStyles();
|
|
648
1124
|
const panel = document.createElement("div");
|
|
649
|
-
|
|
650
|
-
|
|
651
|
-
|
|
652
|
-
|
|
653
|
-
|
|
654
|
-
|
|
655
|
-
|
|
656
|
-
|
|
657
|
-
|
|
658
|
-
margin: "0 auto 18px",
|
|
659
|
-
animation: "youidian-login-spin 780ms linear infinite"
|
|
1125
|
+
applyLoginLoadingPanelStyle(panel);
|
|
1126
|
+
panel.setAttribute("role", "status");
|
|
1127
|
+
panel.setAttribute("aria-label", "\u4F18\u6613\u70B9\u5F00\u53D1\u8005\u670D\u52A1\u4E2D\u53F0");
|
|
1128
|
+
const content = document.createElement("div");
|
|
1129
|
+
Object.assign(content.style, {
|
|
1130
|
+
display: "flex",
|
|
1131
|
+
alignItems: "center",
|
|
1132
|
+
justifyContent: "center",
|
|
1133
|
+
gap: "12px"
|
|
660
1134
|
});
|
|
661
|
-
content.appendChild(
|
|
662
|
-
content.appendChild(
|
|
663
|
-
content.appendChild(createLoginPanelDescription(options.description));
|
|
1135
|
+
content.appendChild(createBrandLoadingMark());
|
|
1136
|
+
content.appendChild(createBrandLoadingCopy());
|
|
664
1137
|
panel.appendChild(content);
|
|
665
1138
|
return panel;
|
|
666
1139
|
}
|
|
667
|
-
function createLoginRedirectingPanel(
|
|
668
|
-
return createLoginLoadingPanel(
|
|
1140
|
+
function createLoginRedirectingPanel(_options) {
|
|
1141
|
+
return createLoginLoadingPanel();
|
|
669
1142
|
}
|
|
670
1143
|
function createLoginFallbackPanel(options) {
|
|
671
1144
|
const panel = document.createElement("div");
|
|
@@ -747,6 +1220,7 @@ var LoginUI = class extends HostedFrameModal {
|
|
|
747
1220
|
this.completed = false;
|
|
748
1221
|
}
|
|
749
1222
|
markIframeReady() {
|
|
1223
|
+
if (this.iframeReady) return;
|
|
750
1224
|
this.iframeReady = true;
|
|
751
1225
|
if (typeof window !== "undefined" && this.iframeLoadTimer) {
|
|
752
1226
|
window.clearTimeout(this.iframeLoadTimer);
|
|
@@ -765,14 +1239,11 @@ var LoginUI = class extends HostedFrameModal {
|
|
|
765
1239
|
this.iframeFallbackPanel = null;
|
|
766
1240
|
this.iframeLoadingPanel = null;
|
|
767
1241
|
}
|
|
768
|
-
showIframeLoading(container
|
|
1242
|
+
showIframeLoading(container) {
|
|
769
1243
|
if (this.iframeLoadingPanel || this.iframeReady) {
|
|
770
1244
|
return;
|
|
771
1245
|
}
|
|
772
|
-
const panel = createLoginLoadingPanel(
|
|
773
|
-
description: options?.loadingDescription || "Please wait while the secure login page opens.",
|
|
774
|
-
title: options?.loadingTitle || "Opening login page"
|
|
775
|
-
});
|
|
1246
|
+
const panel = createLoginLoadingPanel();
|
|
776
1247
|
this.iframeLoadingPanel = panel;
|
|
777
1248
|
container.appendChild(panel);
|
|
778
1249
|
}
|
|
@@ -860,6 +1331,20 @@ var LoginUI = class extends HostedFrameModal {
|
|
|
860
1331
|
break;
|
|
861
1332
|
case "LOGIN_RESIZE":
|
|
862
1333
|
break;
|
|
1334
|
+
case "LOGIN_REDIRECT_REQUIRED":
|
|
1335
|
+
if (!isValidLoginRedirectUrl(data.authUrl)) {
|
|
1336
|
+
logLoginWarn("Login redirect requested with invalid authUrl");
|
|
1337
|
+
options?.onError?.("Login redirect URL is invalid", data);
|
|
1338
|
+
break;
|
|
1339
|
+
}
|
|
1340
|
+
logLoginInfo("Login redirect requested by hosted page", {
|
|
1341
|
+
attemptId: data.attemptId || null,
|
|
1342
|
+
channel: data.channel || null,
|
|
1343
|
+
authUrl: data.authUrl
|
|
1344
|
+
});
|
|
1345
|
+
this.close();
|
|
1346
|
+
window.location.assign(data.authUrl);
|
|
1347
|
+
break;
|
|
863
1348
|
case "LOGIN_ERROR":
|
|
864
1349
|
if (this.completed) {
|
|
865
1350
|
break;
|
|
@@ -883,6 +1368,25 @@ var LoginUI = class extends HostedFrameModal {
|
|
|
883
1368
|
break;
|
|
884
1369
|
}
|
|
885
1370
|
}
|
|
1371
|
+
openLoginRedirect(params, options) {
|
|
1372
|
+
if (typeof window === "undefined") return;
|
|
1373
|
+
const { callbackState, finalUrl, launchPayload } = this.buildOpenContext(
|
|
1374
|
+
params,
|
|
1375
|
+
options
|
|
1376
|
+
);
|
|
1377
|
+
logLoginInfo("Redirecting to hosted login page", {
|
|
1378
|
+
appId: params.appId,
|
|
1379
|
+
callbackState,
|
|
1380
|
+
callbackUrl: launchPayload.callbackUrl || null,
|
|
1381
|
+
hasCallbackUrl: Boolean(launchPayload.callbackUrl),
|
|
1382
|
+
loginUrl: finalUrl,
|
|
1383
|
+
autoClose: options?.autoClose ?? true,
|
|
1384
|
+
displayMode: "redirect",
|
|
1385
|
+
pageUrl: window.location.href,
|
|
1386
|
+
parentOrigin: launchPayload.origin || null
|
|
1387
|
+
});
|
|
1388
|
+
window.location.assign(finalUrl);
|
|
1389
|
+
}
|
|
886
1390
|
listenForLoginCallback(callbackState, options) {
|
|
887
1391
|
try {
|
|
888
1392
|
this.callbackChannel = new BroadcastChannel(
|
|
@@ -959,21 +1463,28 @@ var LoginUI = class extends HostedFrameModal {
|
|
|
959
1463
|
options?.onCancel?.();
|
|
960
1464
|
options?.onClose?.();
|
|
961
1465
|
},
|
|
962
|
-
onMessage: (data,
|
|
1466
|
+
onMessage: (data, _container, event) => {
|
|
963
1467
|
const isIframeEvent = event.source === this.iframe?.contentWindow;
|
|
1468
|
+
if (!isIframeEvent && (data.type === "LOGIN_READY" || data.type === "LOGIN_RESIZE")) {
|
|
1469
|
+
logLoginWarn(
|
|
1470
|
+
"Login lifecycle event ignored: event.source does not match iframe contentWindow",
|
|
1471
|
+
{
|
|
1472
|
+
type: data.type,
|
|
1473
|
+
eventOrigin: event.origin,
|
|
1474
|
+
hasIframe: Boolean(this.iframe),
|
|
1475
|
+
hasIframeContentWindow: Boolean(this.iframe?.contentWindow)
|
|
1476
|
+
}
|
|
1477
|
+
);
|
|
1478
|
+
}
|
|
964
1479
|
if (isIframeEvent && (data.type === "LOGIN_READY" || data.type === "LOGIN_RESIZE") || data.type === "LOGIN_SUCCESS" || data.type === "LOGIN_ERROR") {
|
|
965
1480
|
this.markIframeReady();
|
|
966
1481
|
}
|
|
967
|
-
if (data.type === "LOGIN_RESIZE" && data.height) {
|
|
968
|
-
const maxHeight = window.innerHeight * 0.94;
|
|
969
|
-
container.style.height = `${Math.min(data.height, maxHeight)}px`;
|
|
970
|
-
}
|
|
971
1482
|
this.handleLoginEvent(data, options);
|
|
972
1483
|
},
|
|
973
1484
|
width: "min(520px, 100%)"
|
|
974
1485
|
});
|
|
975
1486
|
if (hostedFrame) {
|
|
976
|
-
this.showIframeLoading(hostedFrame.container
|
|
1487
|
+
this.showIframeLoading(hostedFrame.container);
|
|
977
1488
|
this.startIframeWatchdog({
|
|
978
1489
|
container: hostedFrame.container,
|
|
979
1490
|
finalUrl,
|
|
@@ -1077,11 +1588,19 @@ var LoginUI = class extends HostedFrameModal {
|
|
|
1077
1588
|
}
|
|
1078
1589
|
openLogin(params, options) {
|
|
1079
1590
|
if (typeof window === "undefined") return;
|
|
1080
|
-
const displayMode = options?.displayMode ?? "
|
|
1591
|
+
const displayMode = options?.displayMode ?? "auto";
|
|
1592
|
+
if (displayMode === "redirect") {
|
|
1593
|
+
this.openLoginRedirect(params, options);
|
|
1594
|
+
return;
|
|
1595
|
+
}
|
|
1081
1596
|
if (displayMode === "popup") {
|
|
1082
1597
|
this.openLoginPopup(params, options);
|
|
1083
1598
|
return;
|
|
1084
1599
|
}
|
|
1600
|
+
if (displayMode === "auto" && detectLoginEnvironment().shouldUseRedirectLogin) {
|
|
1601
|
+
this.openLoginRedirect(params, options);
|
|
1602
|
+
return;
|
|
1603
|
+
}
|
|
1085
1604
|
this.openLoginModal(params, options);
|
|
1086
1605
|
}
|
|
1087
1606
|
};
|
|
@@ -1091,6 +1610,406 @@ function createLoginUI() {
|
|
|
1091
1610
|
handleLoginCallbackIfPresent({ autoClose: false });
|
|
1092
1611
|
|
|
1093
1612
|
// src/client.ts
|
|
1613
|
+
var DEFAULT_PAYMENT_IFRAME_LOAD_TIMEOUT_MS = 8e3;
|
|
1614
|
+
var PAYMENT_UI_LOG_PREFIX = "[Youidian PaymentUI]";
|
|
1615
|
+
function hexToRgb(value) {
|
|
1616
|
+
const normalized = value.trim().replace(/^#/, "");
|
|
1617
|
+
if (!/^[0-9a-f]{3}([0-9a-f]{3})?$/i.test(normalized)) return null;
|
|
1618
|
+
const hex = normalized.length === 3 ? normalized.split("").map((char) => `${char}${char}`).join("") : normalized;
|
|
1619
|
+
const number = Number.parseInt(hex, 16);
|
|
1620
|
+
return {
|
|
1621
|
+
b: number & 255,
|
|
1622
|
+
g: number >> 8 & 255,
|
|
1623
|
+
r: number >> 16 & 255
|
|
1624
|
+
};
|
|
1625
|
+
}
|
|
1626
|
+
function alphaColor(value, alpha) {
|
|
1627
|
+
const rgb = hexToRgb(value);
|
|
1628
|
+
if (!rgb)
|
|
1629
|
+
return `color-mix(in srgb, ${value} ${Math.round(alpha * 100)}%, transparent)`;
|
|
1630
|
+
return `rgba(${rgb.r},${rgb.g},${rgb.b},${alpha})`;
|
|
1631
|
+
}
|
|
1632
|
+
function resolvePaymentTheme(options) {
|
|
1633
|
+
const primary = options?.theme?.primary || "#16a34a";
|
|
1634
|
+
const secondary = options?.theme?.secondary || "color-mix(in srgb, #16a34a 78%, white)";
|
|
1635
|
+
const foreground = options?.theme?.foreground || "#0f172a";
|
|
1636
|
+
const muted = options?.theme?.muted || "#64748b";
|
|
1637
|
+
const surface = options?.theme?.surface || "#ffffff";
|
|
1638
|
+
return {
|
|
1639
|
+
foreground,
|
|
1640
|
+
muted,
|
|
1641
|
+
primary,
|
|
1642
|
+
primary10: alphaColor(primary, 0.1),
|
|
1643
|
+
primary14: alphaColor(primary, 0.14),
|
|
1644
|
+
primary20: alphaColor(primary, 0.2),
|
|
1645
|
+
primary28: alphaColor(primary, 0.28),
|
|
1646
|
+
primary36: alphaColor(primary, 0.36),
|
|
1647
|
+
primary64: alphaColor(primary, 0.64),
|
|
1648
|
+
secondary,
|
|
1649
|
+
surface
|
|
1650
|
+
};
|
|
1651
|
+
}
|
|
1652
|
+
function logPaymentInfo(message, details) {
|
|
1653
|
+
if (typeof console === "undefined") return;
|
|
1654
|
+
console.info(PAYMENT_UI_LOG_PREFIX, message, details || {});
|
|
1655
|
+
}
|
|
1656
|
+
function logPaymentWarn(message, details) {
|
|
1657
|
+
if (typeof console === "undefined") return;
|
|
1658
|
+
console.warn(PAYMENT_UI_LOG_PREFIX, message, details || {});
|
|
1659
|
+
}
|
|
1660
|
+
function getPaymentIframeLoadTimeoutMs(options) {
|
|
1661
|
+
const timeout = options?.iframeLoadTimeoutMs;
|
|
1662
|
+
if (typeof timeout !== "number" || !Number.isFinite(timeout)) {
|
|
1663
|
+
return DEFAULT_PAYMENT_IFRAME_LOAD_TIMEOUT_MS;
|
|
1664
|
+
}
|
|
1665
|
+
return Math.max(0, timeout);
|
|
1666
|
+
}
|
|
1667
|
+
function isChinesePaymentLocale(locale) {
|
|
1668
|
+
return locale?.toLowerCase().startsWith("zh") || false;
|
|
1669
|
+
}
|
|
1670
|
+
function getPaymentFallbackText(options) {
|
|
1671
|
+
const isChinese = isChinesePaymentLocale(options?.locale);
|
|
1672
|
+
return {
|
|
1673
|
+
buttonText: options?.fallbackButtonText || (isChinese ? "\u5728\u65B0\u9875\u9762\u4E2D\u6253\u5F00" : "Open in new page"),
|
|
1674
|
+
description: isChinese ? "\u5F53\u524D\u7F51\u7EDC\u53EF\u80FD\u8F83\u6162\uFF0C\u5EFA\u8BAE\u91CD\u65B0\u5C1D\u8BD5\u6216\u5728\u65B0\u9875\u9762\u4E2D\u6253\u5F00\uFF0C\u4EE5\u83B7\u5F97\u66F4\u6D41\u7545\u7684\u652F\u4ED8\u4F53\u9A8C\u3002" : "Your network may be slow. Try again or open the payment page in a new page to continue.",
|
|
1675
|
+
retryText: options?.fallbackRetryText || (isChinese ? "\u91CD\u65B0\u5C1D\u8BD5" : "Try again"),
|
|
1676
|
+
title: isChinese ? "\u652F\u4ED8\u9875\u9762\u6253\u5F00\u8F83\u6162" : "Payment page is taking longer"
|
|
1677
|
+
};
|
|
1678
|
+
}
|
|
1679
|
+
function getPaymentBrandText(options) {
|
|
1680
|
+
const isChinese = isChinesePaymentLocale(options?.locale);
|
|
1681
|
+
return {
|
|
1682
|
+
language: isChinese ? "zh" : "en",
|
|
1683
|
+
name: isChinese ? "\u4F18\u6613\u70B9" : "Youidian",
|
|
1684
|
+
subtitle: isChinese ? "\u5F00\u53D1\u8005\u670D\u52A1\u5E73\u53F0" : "Developer Service Platform"
|
|
1685
|
+
};
|
|
1686
|
+
}
|
|
1687
|
+
function getPaymentBrandLoadingText(options) {
|
|
1688
|
+
const isChinese = isChinesePaymentLocale(options?.locale);
|
|
1689
|
+
return {
|
|
1690
|
+
language: isChinese ? "zh" : "en",
|
|
1691
|
+
name: isChinese ? "\u4F18\u6613\u70B9" : "Youidian",
|
|
1692
|
+
subtitle: isChinese ? "\u5F00\u53D1\u8005\u670D\u52A1\u4E2D\u53F0" : "Developer Service"
|
|
1693
|
+
};
|
|
1694
|
+
}
|
|
1695
|
+
function getPaymentLoadingText(options) {
|
|
1696
|
+
const isChinese = isChinesePaymentLocale(options?.locale);
|
|
1697
|
+
return options?.loadingTitle || options?.loadingDescription || (isChinese ? "\u52A0\u8F7D\u4E2D..." : "Loading...");
|
|
1698
|
+
}
|
|
1699
|
+
function applyPaymentPanelStyle(panel, theme) {
|
|
1700
|
+
Object.assign(panel.style, {
|
|
1701
|
+
position: "absolute",
|
|
1702
|
+
inset: "0",
|
|
1703
|
+
display: "flex",
|
|
1704
|
+
alignItems: "center",
|
|
1705
|
+
justifyContent: "center",
|
|
1706
|
+
borderRadius: "28px",
|
|
1707
|
+
background: `linear-gradient(180deg, ${theme.surface} 0%, rgba(248,250,252,0.98) 100%)`,
|
|
1708
|
+
color: theme.foreground,
|
|
1709
|
+
padding: "28px 24px",
|
|
1710
|
+
textAlign: "center",
|
|
1711
|
+
zIndex: "1",
|
|
1712
|
+
boxShadow: "none",
|
|
1713
|
+
backdropFilter: "blur(16px)"
|
|
1714
|
+
});
|
|
1715
|
+
}
|
|
1716
|
+
function createPaymentIcon(type) {
|
|
1717
|
+
const svg = document.createElementNS("http://www.w3.org/2000/svg", "svg");
|
|
1718
|
+
svg.setAttribute("viewBox", "0 0 24 24");
|
|
1719
|
+
svg.setAttribute("fill", "none");
|
|
1720
|
+
svg.setAttribute("aria-hidden", "true");
|
|
1721
|
+
Object.assign(svg.style, {
|
|
1722
|
+
display: "block",
|
|
1723
|
+
flex: "0 0 auto"
|
|
1724
|
+
});
|
|
1725
|
+
const paths = type === "external" ? [
|
|
1726
|
+
"M7 17L17 7",
|
|
1727
|
+
"M10 7H17V14",
|
|
1728
|
+
"M6.5 6.5H5.5A2.5 2.5 0 0 0 3 9V18.5A2.5 2.5 0 0 0 5.5 21H15A2.5 2.5 0 0 0 17.5 18.5V17.5"
|
|
1729
|
+
] : type === "refresh" ? [
|
|
1730
|
+
"M20 6V11H15",
|
|
1731
|
+
"M4 18V13H9",
|
|
1732
|
+
"M18.2 9A7 7 0 0 0 6.2 6.6L4 9",
|
|
1733
|
+
"M5.8 15A7 7 0 0 0 17.8 17.4L20 15"
|
|
1734
|
+
] : ["M12 7V12L15 14", "M21 12A9 9 0 1 1 3 12A9 9 0 0 1 21 12"];
|
|
1735
|
+
for (const value of paths) {
|
|
1736
|
+
const path = document.createElementNS("http://www.w3.org/2000/svg", "path");
|
|
1737
|
+
path.setAttribute("d", value);
|
|
1738
|
+
path.setAttribute("stroke", "currentColor");
|
|
1739
|
+
path.setAttribute("stroke-width", "2");
|
|
1740
|
+
path.setAttribute("stroke-linecap", "round");
|
|
1741
|
+
path.setAttribute("stroke-linejoin", "round");
|
|
1742
|
+
svg.appendChild(path);
|
|
1743
|
+
}
|
|
1744
|
+
return svg;
|
|
1745
|
+
}
|
|
1746
|
+
function createPaymentFallbackArtwork(theme) {
|
|
1747
|
+
const artwork = document.createElement("div");
|
|
1748
|
+
Object.assign(artwork.style, {
|
|
1749
|
+
height: "164px",
|
|
1750
|
+
margin: "0 auto 34px",
|
|
1751
|
+
position: "relative",
|
|
1752
|
+
width: "184px"
|
|
1753
|
+
});
|
|
1754
|
+
const wash = document.createElement("div");
|
|
1755
|
+
Object.assign(wash.style, {
|
|
1756
|
+
position: "absolute",
|
|
1757
|
+
left: "16px",
|
|
1758
|
+
top: "20px",
|
|
1759
|
+
width: "152px",
|
|
1760
|
+
height: "126px",
|
|
1761
|
+
borderRadius: "48% 52% 43% 57% / 54% 42% 58% 46%",
|
|
1762
|
+
background: `radial-gradient(circle at 48% 42%, ${theme.primary20}, ${theme.primary10} 52%, transparent 76%)`,
|
|
1763
|
+
filter: "blur(1px)",
|
|
1764
|
+
transform: "rotate(-10deg)"
|
|
1765
|
+
});
|
|
1766
|
+
const blob = document.createElement("div");
|
|
1767
|
+
Object.assign(blob.style, {
|
|
1768
|
+
position: "absolute",
|
|
1769
|
+
left: "26px",
|
|
1770
|
+
top: "28px",
|
|
1771
|
+
width: "132px",
|
|
1772
|
+
height: "116px",
|
|
1773
|
+
borderRadius: "42% 58% 53% 47% / 45% 39% 61% 55%",
|
|
1774
|
+
background: `linear-gradient(150deg, ${theme.primary14}, ${theme.primary10})`,
|
|
1775
|
+
boxShadow: `0 30px 64px ${theme.primary14}`,
|
|
1776
|
+
transform: "rotate(8deg)"
|
|
1777
|
+
});
|
|
1778
|
+
const tile = document.createElement("div");
|
|
1779
|
+
Object.assign(tile.style, {
|
|
1780
|
+
position: "absolute",
|
|
1781
|
+
left: "50%",
|
|
1782
|
+
top: "50%",
|
|
1783
|
+
transform: "translate(-50%, -50%) rotate(-4deg)",
|
|
1784
|
+
width: "112px",
|
|
1785
|
+
height: "106px",
|
|
1786
|
+
borderRadius: "38% 62% 50% 50% / 44% 43% 57% 56%",
|
|
1787
|
+
background: `linear-gradient(145deg, ${theme.primary}, ${theme.secondary})`,
|
|
1788
|
+
border: `1px solid ${theme.primary36}`,
|
|
1789
|
+
color: "#ffffff",
|
|
1790
|
+
display: "inline-flex",
|
|
1791
|
+
alignItems: "center",
|
|
1792
|
+
justifyContent: "center",
|
|
1793
|
+
boxShadow: `0 26px 54px ${theme.primary28}`
|
|
1794
|
+
});
|
|
1795
|
+
const icon = createPaymentIcon("slow");
|
|
1796
|
+
Object.assign(icon.style, {
|
|
1797
|
+
width: "52px",
|
|
1798
|
+
height: "52px",
|
|
1799
|
+
transform: "rotate(4deg)"
|
|
1800
|
+
});
|
|
1801
|
+
tile.appendChild(icon);
|
|
1802
|
+
artwork.appendChild(wash);
|
|
1803
|
+
artwork.appendChild(blob);
|
|
1804
|
+
artwork.appendChild(tile);
|
|
1805
|
+
return artwork;
|
|
1806
|
+
}
|
|
1807
|
+
function createPaymentBrandLoading(options, theme) {
|
|
1808
|
+
const brand = getPaymentBrandLoadingText(options);
|
|
1809
|
+
const wrapper = document.createElement("div");
|
|
1810
|
+
Object.assign(wrapper.style, {
|
|
1811
|
+
display: "flex",
|
|
1812
|
+
flexDirection: "column",
|
|
1813
|
+
alignItems: "center",
|
|
1814
|
+
justifyContent: "center",
|
|
1815
|
+
margin: "0 auto 16px"
|
|
1816
|
+
});
|
|
1817
|
+
wrapper.appendChild(
|
|
1818
|
+
createSdkBrandLogo({
|
|
1819
|
+
animated: true,
|
|
1820
|
+
brand,
|
|
1821
|
+
brandWidth: 292,
|
|
1822
|
+
copyWidth: 176,
|
|
1823
|
+
gap: 6,
|
|
1824
|
+
markMarginRight: -10,
|
|
1825
|
+
markSize: 112,
|
|
1826
|
+
nameSize: 39,
|
|
1827
|
+
subtitleMarginTop: 8,
|
|
1828
|
+
subtitleSize: 14,
|
|
1829
|
+
subtitleWeight: "700",
|
|
1830
|
+
theme,
|
|
1831
|
+
variant: "brand"
|
|
1832
|
+
})
|
|
1833
|
+
);
|
|
1834
|
+
return wrapper;
|
|
1835
|
+
}
|
|
1836
|
+
function createPaymentPlatformLogo(options, theme) {
|
|
1837
|
+
const brand = getPaymentBrandText(options);
|
|
1838
|
+
const wrapper = document.createElement("div");
|
|
1839
|
+
Object.assign(wrapper.style, {
|
|
1840
|
+
display: "flex",
|
|
1841
|
+
alignItems: "center",
|
|
1842
|
+
justifyContent: "center",
|
|
1843
|
+
margin: "0 auto 10px"
|
|
1844
|
+
});
|
|
1845
|
+
wrapper.appendChild(
|
|
1846
|
+
createSdkBrandLogo({
|
|
1847
|
+
brand,
|
|
1848
|
+
markSize: 48,
|
|
1849
|
+
nameSize: brand.language === "zh" ? 22 : 22,
|
|
1850
|
+
subtitleSize: brand.language === "zh" ? 9 : 9,
|
|
1851
|
+
theme
|
|
1852
|
+
})
|
|
1853
|
+
);
|
|
1854
|
+
return wrapper;
|
|
1855
|
+
}
|
|
1856
|
+
function createPaymentPanelContent() {
|
|
1857
|
+
const content = document.createElement("div");
|
|
1858
|
+
Object.assign(content.style, {
|
|
1859
|
+
display: "flex",
|
|
1860
|
+
flexDirection: "column",
|
|
1861
|
+
justifyContent: "center",
|
|
1862
|
+
maxWidth: "364px",
|
|
1863
|
+
minHeight: "100%",
|
|
1864
|
+
width: "100%"
|
|
1865
|
+
});
|
|
1866
|
+
return content;
|
|
1867
|
+
}
|
|
1868
|
+
function createPaymentPanelTitle(value, theme) {
|
|
1869
|
+
const title = document.createElement("div");
|
|
1870
|
+
title.textContent = value;
|
|
1871
|
+
Object.assign(title.style, {
|
|
1872
|
+
color: theme?.foreground || "#0f172a",
|
|
1873
|
+
fontSize: "24px",
|
|
1874
|
+
fontWeight: "900",
|
|
1875
|
+
lineHeight: "1.22",
|
|
1876
|
+
marginBottom: "16px"
|
|
1877
|
+
});
|
|
1878
|
+
return title;
|
|
1879
|
+
}
|
|
1880
|
+
function createPaymentPanelDescription(value, theme) {
|
|
1881
|
+
const description = document.createElement("div");
|
|
1882
|
+
description.textContent = value;
|
|
1883
|
+
Object.assign(description.style, {
|
|
1884
|
+
color: theme?.muted || "#64748b",
|
|
1885
|
+
fontSize: "14px",
|
|
1886
|
+
fontWeight: "600",
|
|
1887
|
+
lineHeight: "1.62",
|
|
1888
|
+
margin: "0 auto",
|
|
1889
|
+
maxWidth: "320px"
|
|
1890
|
+
});
|
|
1891
|
+
return description;
|
|
1892
|
+
}
|
|
1893
|
+
function createPaymentLoadingDescription(value, theme) {
|
|
1894
|
+
const description = document.createElement("div");
|
|
1895
|
+
description.textContent = value;
|
|
1896
|
+
Object.assign(description.style, {
|
|
1897
|
+
color: theme?.muted || "#64748b",
|
|
1898
|
+
fontSize: "14px",
|
|
1899
|
+
fontWeight: "500",
|
|
1900
|
+
lineHeight: "1.25",
|
|
1901
|
+
margin: "12px auto 0",
|
|
1902
|
+
maxWidth: "320px"
|
|
1903
|
+
});
|
|
1904
|
+
return description;
|
|
1905
|
+
}
|
|
1906
|
+
function createPaymentFallbackMessage(options) {
|
|
1907
|
+
const message = document.createElement("div");
|
|
1908
|
+
Object.assign(message.style, {
|
|
1909
|
+
margin: "0 auto",
|
|
1910
|
+
textAlign: "center"
|
|
1911
|
+
});
|
|
1912
|
+
message.appendChild(createPaymentFallbackArtwork(options.theme));
|
|
1913
|
+
message.appendChild(createPaymentPanelTitle(options.title, options.theme));
|
|
1914
|
+
message.appendChild(
|
|
1915
|
+
createPaymentPanelDescription(options.description, options.theme)
|
|
1916
|
+
);
|
|
1917
|
+
return message;
|
|
1918
|
+
}
|
|
1919
|
+
function createPaymentLoadingPanel(options) {
|
|
1920
|
+
const panel = document.createElement("div");
|
|
1921
|
+
const theme = resolvePaymentTheme(options);
|
|
1922
|
+
applyPaymentPanelStyle(panel, theme);
|
|
1923
|
+
const content = createPaymentPanelContent();
|
|
1924
|
+
content.appendChild(createPaymentBrandLoading(options, theme));
|
|
1925
|
+
content.appendChild(
|
|
1926
|
+
createPaymentLoadingDescription(getPaymentLoadingText(options), theme)
|
|
1927
|
+
);
|
|
1928
|
+
panel.appendChild(content);
|
|
1929
|
+
return panel;
|
|
1930
|
+
}
|
|
1931
|
+
function createPaymentButton(value, options) {
|
|
1932
|
+
const primary = options?.primary || false;
|
|
1933
|
+
const theme = options?.theme || resolvePaymentTheme();
|
|
1934
|
+
const button = document.createElement("button");
|
|
1935
|
+
button.type = "button";
|
|
1936
|
+
Object.assign(button.style, {
|
|
1937
|
+
width: "100%",
|
|
1938
|
+
height: "50px",
|
|
1939
|
+
borderRadius: "14px",
|
|
1940
|
+
border: primary ? `1px solid ${theme.primary}` : `1px solid ${theme.primary64}`,
|
|
1941
|
+
background: primary ? `linear-gradient(135deg, ${theme.primary}, ${theme.secondary})` : "#ffffff",
|
|
1942
|
+
color: primary ? "#ffffff" : theme.primary,
|
|
1943
|
+
cursor: "pointer",
|
|
1944
|
+
display: "inline-flex",
|
|
1945
|
+
alignItems: "center",
|
|
1946
|
+
justifyContent: "center",
|
|
1947
|
+
gap: "10px",
|
|
1948
|
+
fontSize: "15px",
|
|
1949
|
+
fontWeight: "800",
|
|
1950
|
+
marginTop: primary ? "12px" : "0",
|
|
1951
|
+
boxShadow: primary ? `0 14px 28px ${theme.primary20}` : "none"
|
|
1952
|
+
});
|
|
1953
|
+
if (options?.icon) {
|
|
1954
|
+
const icon = createPaymentIcon(options.icon);
|
|
1955
|
+
Object.assign(icon.style, {
|
|
1956
|
+
width: "17px",
|
|
1957
|
+
height: "17px"
|
|
1958
|
+
});
|
|
1959
|
+
button.appendChild(icon);
|
|
1960
|
+
}
|
|
1961
|
+
const label = document.createElement("span");
|
|
1962
|
+
label.textContent = value;
|
|
1963
|
+
button.appendChild(label);
|
|
1964
|
+
return button;
|
|
1965
|
+
}
|
|
1966
|
+
function createPaymentFallbackPanel(options) {
|
|
1967
|
+
const panel = document.createElement("div");
|
|
1968
|
+
const theme = resolvePaymentTheme(options.paymentOptions);
|
|
1969
|
+
applyPaymentPanelStyle(panel, theme);
|
|
1970
|
+
const content = createPaymentPanelContent();
|
|
1971
|
+
Object.assign(content.style, {
|
|
1972
|
+
justifyContent: "space-between"
|
|
1973
|
+
});
|
|
1974
|
+
const main = document.createElement("div");
|
|
1975
|
+
Object.assign(main.style, {
|
|
1976
|
+
display: "flex",
|
|
1977
|
+
flexDirection: "column",
|
|
1978
|
+
alignItems: "center",
|
|
1979
|
+
marginTop: "38px",
|
|
1980
|
+
width: "100%"
|
|
1981
|
+
});
|
|
1982
|
+
main.appendChild(
|
|
1983
|
+
createPaymentFallbackMessage({
|
|
1984
|
+
description: options.description,
|
|
1985
|
+
theme,
|
|
1986
|
+
title: options.title
|
|
1987
|
+
})
|
|
1988
|
+
);
|
|
1989
|
+
const actions = document.createElement("div");
|
|
1990
|
+
Object.assign(actions.style, {
|
|
1991
|
+
marginTop: "46px",
|
|
1992
|
+
width: "100%"
|
|
1993
|
+
});
|
|
1994
|
+
const retryButton = createPaymentButton(options.retryText, {
|
|
1995
|
+
icon: "refresh",
|
|
1996
|
+
theme
|
|
1997
|
+
});
|
|
1998
|
+
retryButton.onclick = options.onRetry;
|
|
1999
|
+
actions.appendChild(retryButton);
|
|
2000
|
+
const openButton = createPaymentButton(options.buttonText, {
|
|
2001
|
+
icon: "external",
|
|
2002
|
+
primary: true,
|
|
2003
|
+
theme
|
|
2004
|
+
});
|
|
2005
|
+
openButton.onclick = options.onOpen;
|
|
2006
|
+
actions.appendChild(openButton);
|
|
2007
|
+
main.appendChild(actions);
|
|
2008
|
+
content.appendChild(main);
|
|
2009
|
+
content.appendChild(createPaymentPlatformLogo(options.paymentOptions, theme));
|
|
2010
|
+
panel.appendChild(content);
|
|
2011
|
+
return panel;
|
|
2012
|
+
}
|
|
1094
2013
|
var PaymentUI = class extends HostedFrameModal {
|
|
1095
2014
|
constructor() {
|
|
1096
2015
|
super(...arguments);
|
|
@@ -1099,6 +2018,127 @@ var PaymentUI = class extends HostedFrameModal {
|
|
|
1099
2018
|
__publicField(this, "activeOrderId", null);
|
|
1100
2019
|
__publicField(this, "paymentCompleted", false);
|
|
1101
2020
|
__publicField(this, "cancelRequestedOrderId", null);
|
|
2021
|
+
__publicField(this, "iframeFallbackPanel", null);
|
|
2022
|
+
__publicField(this, "iframeLoadingPanel", null);
|
|
2023
|
+
__publicField(this, "iframeLoadTimer", null);
|
|
2024
|
+
__publicField(this, "iframeReady", false);
|
|
2025
|
+
}
|
|
2026
|
+
cleanupPaymentFrameState() {
|
|
2027
|
+
if (typeof window !== "undefined" && this.iframeLoadTimer) {
|
|
2028
|
+
window.clearTimeout(this.iframeLoadTimer);
|
|
2029
|
+
}
|
|
2030
|
+
if (this.iframeFallbackPanel?.parentNode) {
|
|
2031
|
+
this.iframeFallbackPanel.parentNode.removeChild(this.iframeFallbackPanel);
|
|
2032
|
+
}
|
|
2033
|
+
if (this.iframeLoadingPanel?.parentNode) {
|
|
2034
|
+
this.iframeLoadingPanel.parentNode.removeChild(this.iframeLoadingPanel);
|
|
2035
|
+
}
|
|
2036
|
+
this.iframeFallbackPanel = null;
|
|
2037
|
+
this.iframeLoadingPanel = null;
|
|
2038
|
+
this.iframeLoadTimer = null;
|
|
2039
|
+
this.iframeReady = false;
|
|
2040
|
+
}
|
|
2041
|
+
markPaymentIframeReady() {
|
|
2042
|
+
if (this.iframeReady) return;
|
|
2043
|
+
this.iframeReady = true;
|
|
2044
|
+
if (typeof window !== "undefined" && this.iframeLoadTimer) {
|
|
2045
|
+
window.clearTimeout(this.iframeLoadTimer);
|
|
2046
|
+
this.iframeLoadTimer = null;
|
|
2047
|
+
}
|
|
2048
|
+
if (this.iframeFallbackPanel?.parentNode) {
|
|
2049
|
+
this.iframeFallbackPanel.parentNode.removeChild(this.iframeFallbackPanel);
|
|
2050
|
+
}
|
|
2051
|
+
if (this.iframeLoadingPanel?.parentNode) {
|
|
2052
|
+
this.iframeLoadingPanel.parentNode.removeChild(this.iframeLoadingPanel);
|
|
2053
|
+
}
|
|
2054
|
+
this.iframeFallbackPanel = null;
|
|
2055
|
+
this.iframeLoadingPanel = null;
|
|
2056
|
+
}
|
|
2057
|
+
showPaymentIframeLoading(container, options) {
|
|
2058
|
+
if (this.iframeLoadingPanel || this.iframeReady) return;
|
|
2059
|
+
const panel = createPaymentLoadingPanel(options);
|
|
2060
|
+
this.iframeLoadingPanel = panel;
|
|
2061
|
+
container.appendChild(panel);
|
|
2062
|
+
}
|
|
2063
|
+
openFallbackPaymentPage(finalUrl, options) {
|
|
2064
|
+
if (typeof window === "undefined") return;
|
|
2065
|
+
const popup = window.open(
|
|
2066
|
+
finalUrl,
|
|
2067
|
+
"youidian-payment-checkout",
|
|
2068
|
+
"popup=yes,width=480,height=760,resizable=yes,scrollbars=yes"
|
|
2069
|
+
);
|
|
2070
|
+
if (popup) {
|
|
2071
|
+
logPaymentInfo("Opened hosted checkout fallback page", {
|
|
2072
|
+
checkoutUrl: finalUrl
|
|
2073
|
+
});
|
|
2074
|
+
options?.onFallbackOpen?.(finalUrl);
|
|
2075
|
+
try {
|
|
2076
|
+
popup.focus();
|
|
2077
|
+
} catch {
|
|
2078
|
+
}
|
|
2079
|
+
return;
|
|
2080
|
+
}
|
|
2081
|
+
logPaymentWarn("Hosted checkout fallback popup was blocked", {
|
|
2082
|
+
checkoutUrl: finalUrl
|
|
2083
|
+
});
|
|
2084
|
+
options?.onFallbackBlocked?.(finalUrl);
|
|
2085
|
+
window.location.assign(finalUrl);
|
|
2086
|
+
}
|
|
2087
|
+
showPaymentIframeFallback(options) {
|
|
2088
|
+
if (this.iframeReady || this.iframeFallbackPanel) return;
|
|
2089
|
+
const { container, finalUrl, paymentOptions } = options;
|
|
2090
|
+
logPaymentWarn("Hosted checkout iframe did not report ready in time", {
|
|
2091
|
+
checkoutUrl: finalUrl
|
|
2092
|
+
});
|
|
2093
|
+
if (this.iframeLoadingPanel?.parentNode) {
|
|
2094
|
+
this.iframeLoadingPanel.parentNode.removeChild(this.iframeLoadingPanel);
|
|
2095
|
+
}
|
|
2096
|
+
this.iframeLoadingPanel = null;
|
|
2097
|
+
const fallbackText = getPaymentFallbackText(paymentOptions);
|
|
2098
|
+
const panel = createPaymentFallbackPanel({
|
|
2099
|
+
buttonText: fallbackText.buttonText,
|
|
2100
|
+
description: fallbackText.description,
|
|
2101
|
+
onOpen: () => {
|
|
2102
|
+
this.openFallbackPaymentPage(finalUrl, paymentOptions);
|
|
2103
|
+
},
|
|
2104
|
+
onRetry: () => {
|
|
2105
|
+
this.iframeFallbackPanel = null;
|
|
2106
|
+
if (panel.parentNode) {
|
|
2107
|
+
panel.parentNode.removeChild(panel);
|
|
2108
|
+
}
|
|
2109
|
+
this.iframeReady = false;
|
|
2110
|
+
this.showPaymentIframeLoading(container, paymentOptions);
|
|
2111
|
+
if (this.iframe) {
|
|
2112
|
+
this.iframe.src = finalUrl;
|
|
2113
|
+
}
|
|
2114
|
+
this.startPaymentIframeWatchdog({
|
|
2115
|
+
container,
|
|
2116
|
+
finalUrl,
|
|
2117
|
+
paymentOptions
|
|
2118
|
+
});
|
|
2119
|
+
},
|
|
2120
|
+
paymentOptions,
|
|
2121
|
+
retryText: fallbackText.retryText,
|
|
2122
|
+
title: fallbackText.title
|
|
2123
|
+
});
|
|
2124
|
+
this.iframeFallbackPanel = panel;
|
|
2125
|
+
container.appendChild(panel);
|
|
2126
|
+
paymentOptions?.onFallbackVisible?.();
|
|
2127
|
+
}
|
|
2128
|
+
startPaymentIframeWatchdog(options) {
|
|
2129
|
+
if (typeof window === "undefined") return;
|
|
2130
|
+
if (this.iframeLoadTimer) {
|
|
2131
|
+
window.clearTimeout(this.iframeLoadTimer);
|
|
2132
|
+
}
|
|
2133
|
+
const timeoutMs = getPaymentIframeLoadTimeoutMs(options.paymentOptions);
|
|
2134
|
+
if (timeoutMs === 0) {
|
|
2135
|
+
this.showPaymentIframeFallback(options);
|
|
2136
|
+
return;
|
|
2137
|
+
}
|
|
2138
|
+
this.iframeLoadTimer = window.setTimeout(() => {
|
|
2139
|
+
this.iframeLoadTimer = null;
|
|
2140
|
+
this.showPaymentIframeFallback(options);
|
|
2141
|
+
}, timeoutMs);
|
|
1102
2142
|
}
|
|
1103
2143
|
cancelHostedOrder(reason = "user_cancel", orderId) {
|
|
1104
2144
|
const targetOrderId = orderId || this.activeOrderId;
|
|
@@ -1141,6 +2181,7 @@ var PaymentUI = class extends HostedFrameModal {
|
|
|
1141
2181
|
this.activeOrderId = null;
|
|
1142
2182
|
this.paymentCompleted = false;
|
|
1143
2183
|
this.cancelRequestedOrderId = null;
|
|
2184
|
+
this.cleanupPaymentFrameState();
|
|
1144
2185
|
if (typeof urlOrParams === "string") {
|
|
1145
2186
|
checkoutUrl = urlOrParams;
|
|
1146
2187
|
try {
|
|
@@ -1209,14 +2250,21 @@ var PaymentUI = class extends HostedFrameModal {
|
|
|
1209
2250
|
checkoutUrl,
|
|
1210
2251
|
getAutoResolvedLocale(options?.locale)
|
|
1211
2252
|
);
|
|
1212
|
-
this.openHostedFrame(finalUrl, {
|
|
2253
|
+
const hostedFrame = this.openHostedFrame(finalUrl, {
|
|
1213
2254
|
allowedOrigin: options?.allowedOrigin,
|
|
2255
|
+
height: "min(760px, calc(100vh - 32px))",
|
|
1214
2256
|
onCloseButton: () => {
|
|
1215
2257
|
this.cancelHostedOrder("modal_close");
|
|
1216
2258
|
options?.onCancel?.(this.activeOrderId || void 0);
|
|
1217
2259
|
},
|
|
1218
|
-
onMessage: (data, container) => {
|
|
2260
|
+
onMessage: (data, container, event) => {
|
|
2261
|
+
const isIframeMessage = event.source === this.iframe?.contentWindow;
|
|
2262
|
+
if (isIframeMessage && (data.type === "PAYMENT_READY" || data.type === "PAYMENT_RESIZE" || data.type === "PAYMENT_STARTED")) {
|
|
2263
|
+
this.markPaymentIframeReady();
|
|
2264
|
+
}
|
|
1219
2265
|
switch (data.type) {
|
|
2266
|
+
case "PAYMENT_READY":
|
|
2267
|
+
break;
|
|
1220
2268
|
case "PAYMENT_STARTED":
|
|
1221
2269
|
if (data.orderId) {
|
|
1222
2270
|
this.activeOrderId = data.orderId;
|
|
@@ -1231,11 +2279,6 @@ var PaymentUI = class extends HostedFrameModal {
|
|
|
1231
2279
|
options?.onCancel?.(data.orderId);
|
|
1232
2280
|
break;
|
|
1233
2281
|
case "PAYMENT_RESIZE":
|
|
1234
|
-
if (data.height) {
|
|
1235
|
-
const maxHeight = window.innerHeight * 0.9;
|
|
1236
|
-
const newHeight = Math.min(data.height, maxHeight);
|
|
1237
|
-
container.style.height = `${newHeight}px`;
|
|
1238
|
-
}
|
|
1239
2282
|
break;
|
|
1240
2283
|
case "PAYMENT_CLOSE":
|
|
1241
2284
|
this.cancelHostedOrder("payment_close", data.orderId);
|
|
@@ -1243,8 +2286,21 @@ var PaymentUI = class extends HostedFrameModal {
|
|
|
1243
2286
|
options?.onClose?.();
|
|
1244
2287
|
break;
|
|
1245
2288
|
}
|
|
1246
|
-
}
|
|
2289
|
+
},
|
|
2290
|
+
width: "min(450px, 100%)"
|
|
1247
2291
|
});
|
|
2292
|
+
if (hostedFrame) {
|
|
2293
|
+
this.showPaymentIframeLoading(hostedFrame.container, options);
|
|
2294
|
+
this.startPaymentIframeWatchdog({
|
|
2295
|
+
container: hostedFrame.container,
|
|
2296
|
+
finalUrl,
|
|
2297
|
+
paymentOptions: options
|
|
2298
|
+
});
|
|
2299
|
+
}
|
|
2300
|
+
}
|
|
2301
|
+
close() {
|
|
2302
|
+
super.close();
|
|
2303
|
+
this.cleanupPaymentFrameState();
|
|
1248
2304
|
}
|
|
1249
2305
|
/**
|
|
1250
2306
|
* Poll order status from integrator's API endpoint
|
|
@@ -1290,15 +2346,41 @@ var PaymentUI = class extends HostedFrameModal {
|
|
|
1290
2346
|
});
|
|
1291
2347
|
}
|
|
1292
2348
|
};
|
|
2349
|
+
var MessageUI = class {
|
|
2350
|
+
openWechatBinding(options) {
|
|
2351
|
+
const bindingUrl = options.bindingUrl?.trim();
|
|
2352
|
+
if (!bindingUrl) {
|
|
2353
|
+
throw new Error("bindingUrl is required");
|
|
2354
|
+
}
|
|
2355
|
+
if (options.displayMode === "popup") {
|
|
2356
|
+
const popup = window.open(
|
|
2357
|
+
bindingUrl,
|
|
2358
|
+
options.popupName || "youidian-wechat-message-binding",
|
|
2359
|
+
"width=480,height=720,noopener,noreferrer"
|
|
2360
|
+
);
|
|
2361
|
+
if (!popup) {
|
|
2362
|
+
window.location.href = bindingUrl;
|
|
2363
|
+
}
|
|
2364
|
+
return;
|
|
2365
|
+
}
|
|
2366
|
+
window.location.href = bindingUrl;
|
|
2367
|
+
}
|
|
2368
|
+
};
|
|
2369
|
+
function createMessageUI() {
|
|
2370
|
+
return new MessageUI();
|
|
2371
|
+
}
|
|
1293
2372
|
function createPaymentUI() {
|
|
1294
2373
|
return new PaymentUI();
|
|
1295
2374
|
}
|
|
1296
2375
|
// Annotate the CommonJS export names for ESM import in node:
|
|
1297
2376
|
0 && (module.exports = {
|
|
1298
2377
|
LoginUI,
|
|
2378
|
+
MessageUI,
|
|
1299
2379
|
PaymentUI,
|
|
1300
2380
|
createLoginUI,
|
|
2381
|
+
createMessageUI,
|
|
1301
2382
|
createPaymentUI,
|
|
2383
|
+
detectLoginEnvironment,
|
|
1302
2384
|
handleLoginCallbackIfPresent
|
|
1303
2385
|
});
|
|
1304
2386
|
//# sourceMappingURL=client.cjs.map
|