@youidian/sdk 3.2.1 → 3.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -301,9 +301,6 @@ function buildLoginUrl(params, options, launchPayload) {
301
301
  if (parentOrigin) {
302
302
  url.searchParams.set("origin", parentOrigin);
303
303
  }
304
- if (launchPayload.callbackUrl) {
305
- url.searchParams.set("callbackUrl", launchPayload.callbackUrl);
306
- }
307
304
  return appendLoginLaunchHash(url.toString(), launchPayload);
308
305
  } catch (_error) {
309
306
  const searchParams = new URLSearchParams();
@@ -316,9 +313,6 @@ function buildLoginUrl(params, options, launchPayload) {
316
313
  if (parentOrigin) {
317
314
  searchParams.set("origin", parentOrigin);
318
315
  }
319
- if (launchPayload.callbackUrl) {
320
- searchParams.set("callbackUrl", launchPayload.callbackUrl);
321
- }
322
316
  const query = searchParams.toString();
323
317
  if (!query) {
324
318
  return appendLoginLaunchHash(finalUrl, launchPayload);
@@ -339,6 +333,11 @@ function extractLoginResult(data) {
339
333
  legacyCasdoorId: data.legacyCasdoorId,
340
334
  loginToken: data.loginToken,
341
335
  name: data.name,
336
+ username: data.username,
337
+ phoneCountryCode: data.phoneCountryCode,
338
+ phoneNumber: data.phoneNumber,
339
+ phoneE164: data.phoneE164,
340
+ phoneVerifiedAt: data.phoneVerifiedAt,
342
341
  userId: data.userId,
343
342
  wechatOpenId: data.wechatOpenId,
344
343
  wechatUnionId: data.wechatUnionId
@@ -399,6 +398,23 @@ function publishLoginCallback(state, data) {
399
398
  } catch {
400
399
  }
401
400
  }
401
+ function safeIsPopupClosed(popup) {
402
+ if (!popup) return true;
403
+ try {
404
+ return popup.closed;
405
+ } catch {
406
+ logLoginDebug("Unable to read popup.closed; treating popup as open");
407
+ return false;
408
+ }
409
+ }
410
+ function safeClosePopup(popup) {
411
+ if (!popup) return;
412
+ try {
413
+ popup.close();
414
+ } catch {
415
+ logLoginDebug("Unable to close popup");
416
+ }
417
+ }
402
418
  function cleanLoginCallbackUrl(url) {
403
419
  url.searchParams.delete(LOGIN_CALLBACK_MARKER);
404
420
  url.searchParams.delete(LOGIN_CALLBACK_STATE_PARAM);
@@ -407,7 +423,7 @@ function cleanLoginCallbackUrl(url) {
407
423
  url.hash = returnHash ? `#${returnHash}` : "";
408
424
  return url.toString();
409
425
  }
410
- function handleLoginCallbackIfPresent() {
426
+ function handleLoginCallbackIfPresent(options) {
411
427
  if (typeof window === "undefined") {
412
428
  return false;
413
429
  }
@@ -433,12 +449,19 @@ function handleLoginCallbackIfPresent() {
433
449
  window.history.replaceState(null, "", cleanLoginCallbackUrl(url));
434
450
  } catch {
435
451
  }
436
- window.setTimeout(() => {
437
- try {
438
- window.close();
439
- } catch {
440
- }
441
- }, 30);
452
+ if (options?.autoClose === true) {
453
+ window.setTimeout(() => {
454
+ try {
455
+ window.close();
456
+ } catch {
457
+ }
458
+ }, 30);
459
+ return true;
460
+ }
461
+ try {
462
+ document.documentElement.style.visibility = "";
463
+ } catch {
464
+ }
442
465
  return true;
443
466
  }
444
467
  function logLoginDebug(message, details) {
@@ -453,12 +476,13 @@ function logLoginWarn(message, details) {
453
476
  if (typeof console === "undefined") return;
454
477
  console.warn(LOGIN_UI_LOG_PREFIX, message, details || {});
455
478
  }
456
- var LoginUI = class {
479
+ var LoginUI = class extends HostedFrameModal {
457
480
  constructor() {
481
+ super(...arguments);
458
482
  __publicField(this, "popup", null);
459
483
  __publicField(this, "callbackChannel", null);
460
484
  __publicField(this, "callbackStorageHandler", null);
461
- __publicField(this, "messageHandler", null);
485
+ __publicField(this, "popupMessageHandler", null);
462
486
  __publicField(this, "closeMonitor", null);
463
487
  __publicField(this, "completed", false);
464
488
  }
@@ -469,15 +493,15 @@ var LoginUI = class {
469
493
  if (typeof window !== "undefined" && this.callbackStorageHandler) {
470
494
  window.removeEventListener("storage", this.callbackStorageHandler);
471
495
  }
472
- if (typeof window !== "undefined" && this.messageHandler) {
473
- window.removeEventListener("message", this.messageHandler);
496
+ if (typeof window !== "undefined" && this.popupMessageHandler) {
497
+ window.removeEventListener("message", this.popupMessageHandler);
474
498
  }
475
499
  this.callbackChannel = null;
476
500
  this.callbackStorageHandler = null;
477
501
  if (typeof window !== "undefined" && this.closeMonitor) {
478
502
  window.clearInterval(this.closeMonitor);
479
503
  }
480
- this.messageHandler = null;
504
+ this.popupMessageHandler = null;
481
505
  this.closeMonitor = null;
482
506
  this.popup = null;
483
507
  this.completed = false;
@@ -520,12 +544,12 @@ var LoginUI = class {
520
544
  case "LOGIN_CLOSE":
521
545
  if (options?.autoClose === false) {
522
546
  logLoginInfo(
523
- "Login popup requested close; autoClose disabled, keeping popup open"
547
+ "Login surface requested close; autoClose disabled, keeping it open"
524
548
  );
525
549
  options?.onClose?.();
526
550
  break;
527
551
  }
528
- logLoginInfo("Login popup requested close; autoClose enabled");
552
+ logLoginInfo("Login surface requested close; autoClose enabled");
529
553
  this.close();
530
554
  options?.onClose?.();
531
555
  break;
@@ -559,17 +583,15 @@ var LoginUI = class {
559
583
  }
560
584
  close() {
561
585
  logLoginInfo("close() called", {
586
+ hasModal: Boolean(this.modal),
562
587
  hasPopup: Boolean(this.popup),
563
- popupClosed: this.popup?.closed ?? true
588
+ popupClosed: safeIsPopupClosed(this.popup)
564
589
  });
565
- if (this.popup && !this.popup.closed) {
566
- this.popup.close();
567
- }
590
+ safeClosePopup(this.popup);
591
+ super.close();
568
592
  this.cleanup();
569
593
  }
570
- openLogin(params, options) {
571
- if (typeof window === "undefined") return;
572
- if (this.popup && !this.popup.closed) return;
594
+ buildOpenContext(params, options) {
573
595
  const callbackState = createLoginCallbackState();
574
596
  const launchPayload = buildLoginLaunchPayload(
575
597
  params,
@@ -577,6 +599,54 @@ var LoginUI = class {
577
599
  callbackState
578
600
  );
579
601
  const finalUrl = buildLoginUrl(params, options, launchPayload);
602
+ return { callbackState, finalUrl, launchPayload };
603
+ }
604
+ openLoginModal(params, options) {
605
+ if (typeof document === "undefined") return;
606
+ if (this.modal) return;
607
+ const { callbackState, finalUrl, launchPayload } = this.buildOpenContext(
608
+ params,
609
+ options
610
+ );
611
+ const loginOrigin = getOrigin(finalUrl);
612
+ logLoginInfo("Opening hosted login iframe modal", {
613
+ appId: params.appId,
614
+ callbackState,
615
+ callbackUrl: launchPayload.callbackUrl || null,
616
+ hasCallbackUrl: Boolean(launchPayload.callbackUrl),
617
+ loginUrl: finalUrl,
618
+ allowedOrigin: options?.allowedOrigin || null,
619
+ autoClose: options?.autoClose ?? true,
620
+ displayMode: "modal",
621
+ pageUrl: typeof window !== "undefined" ? window.location.href : null,
622
+ parentOrigin: launchPayload.origin || null
623
+ });
624
+ this.completed = false;
625
+ this.listenForLoginCallback(callbackState, options);
626
+ this.openHostedFrame(finalUrl, {
627
+ allowedOrigin: options?.allowedOrigin || loginOrigin || void 0,
628
+ height: "min(760px, 94vh)",
629
+ onCloseButton: () => {
630
+ options?.onCancel?.();
631
+ options?.onClose?.();
632
+ },
633
+ onMessage: (data, container) => {
634
+ if (data.type === "LOGIN_RESIZE" && data.height) {
635
+ const maxHeight = window.innerHeight * 0.94;
636
+ container.style.height = `${Math.min(data.height, maxHeight)}px`;
637
+ }
638
+ this.handleLoginEvent(data, options);
639
+ },
640
+ width: "min(520px, 100%)"
641
+ });
642
+ }
643
+ openLoginPopup(params, options) {
644
+ if (typeof window === "undefined") return;
645
+ if (this.popup && !safeIsPopupClosed(this.popup)) return;
646
+ const { callbackState, finalUrl, launchPayload } = this.buildOpenContext(
647
+ params,
648
+ options
649
+ );
580
650
  logLoginInfo("Opening hosted login popup", {
581
651
  appId: params.appId,
582
652
  callbackState,
@@ -585,6 +655,7 @@ var LoginUI = class {
585
655
  loginUrl: finalUrl,
586
656
  allowedOrigin: options?.allowedOrigin || null,
587
657
  autoClose: options?.autoClose ?? true,
658
+ displayMode: "popup",
588
659
  pageUrl: typeof window !== "undefined" ? window.location.href : null,
589
660
  parentOrigin: launchPayload.origin || null
590
661
  });
@@ -619,7 +690,7 @@ var LoginUI = class {
619
690
  this.listenForLoginCallback(callbackState, options);
620
691
  const allowedOrigin = options?.allowedOrigin;
621
692
  const popupOrigin = getOrigin(finalUrl);
622
- this.messageHandler = (event) => {
693
+ this.popupMessageHandler = (event) => {
623
694
  if (allowedOrigin && allowedOrigin !== "*" && event.origin !== allowedOrigin) {
624
695
  logLoginWarn("Ignored message due to allowedOrigin mismatch", {
625
696
  allowedOrigin,
@@ -645,26 +716,37 @@ var LoginUI = class {
645
716
  });
646
717
  this.handleLoginEvent(data, options);
647
718
  };
648
- window.addEventListener("message", this.messageHandler);
649
- this.closeMonitor = window.setInterval(() => {
650
- if (!this.popup || this.popup.closed) {
651
- const shouldTreatAsCancel = !this.completed;
652
- logLoginInfo("Detected popup closed", {
653
- shouldTreatAsCancel
654
- });
655
- this.cleanup();
656
- if (shouldTreatAsCancel) {
657
- options?.onCancel?.();
719
+ window.addEventListener("message", this.popupMessageHandler);
720
+ if (options?.monitorPopupClosed === true) {
721
+ this.closeMonitor = window.setInterval(() => {
722
+ if (!this.popup || safeIsPopupClosed(this.popup)) {
723
+ const shouldTreatAsCancel = !this.completed;
724
+ logLoginInfo("Detected popup closed", {
725
+ shouldTreatAsCancel
726
+ });
727
+ this.cleanup();
728
+ if (shouldTreatAsCancel) {
729
+ options?.onCancel?.();
730
+ }
731
+ options?.onClose?.();
658
732
  }
659
- options?.onClose?.();
660
- }
661
- }, 500);
733
+ }, 500);
734
+ }
735
+ }
736
+ openLogin(params, options) {
737
+ if (typeof window === "undefined") return;
738
+ const displayMode = options?.displayMode ?? "modal";
739
+ if (displayMode === "popup") {
740
+ this.openLoginPopup(params, options);
741
+ return;
742
+ }
743
+ this.openLoginModal(params, options);
662
744
  }
663
745
  };
664
746
  function createLoginUI() {
665
747
  return new LoginUI();
666
748
  }
667
- handleLoginCallbackIfPresent();
749
+ handleLoginCallbackIfPresent({ autoClose: false });
668
750
 
669
751
  // src/client.ts
670
752
  var PaymentUI = class extends HostedFrameModal {
@@ -700,7 +782,10 @@ var PaymentUI = class extends HostedFrameModal {
700
782
  );
701
783
  }
702
784
  }
703
- const finalUrl = applyLocaleToUrl(checkoutUrl, options?.locale);
785
+ const finalUrl = applyLocaleToUrl(
786
+ checkoutUrl,
787
+ getAutoResolvedLocale(options?.locale)
788
+ );
704
789
  this.openHostedFrame(finalUrl, {
705
790
  allowedOrigin: options?.allowedOrigin,
706
791
  onCloseButton: () => options?.onCancel?.(),
@@ -857,7 +942,7 @@ var PaymentClient = class {
857
942
  let decrypted = decipher.update(encryptedData, "hex", "utf8");
858
943
  decrypted += decipher.final("utf8");
859
944
  return JSON.parse(decrypted);
860
- } catch (error) {
945
+ } catch {
861
946
  throw new Error(
862
947
  "Failed to decrypt payment callback: Invalid secret or tampered data."
863
948
  );
@@ -1024,6 +1109,43 @@ var PaymentClient = class {
1024
1109
  }
1025
1110
  return this.request("POST", "/login/tokens/verify", { token: token.trim() });
1026
1111
  }
1112
+ /**
1113
+ * Send a phone verification code for binding a phone number to a hosted login user.
1114
+ */
1115
+ async sendPhoneVerificationCode(params) {
1116
+ const userId = params.userId?.trim();
1117
+ const phoneNumber = params.phoneNumber?.trim();
1118
+ if (!userId) throw new Error("userId is required");
1119
+ if (!phoneNumber) throw new Error("phoneNumber is required");
1120
+ return this.request(
1121
+ "POST",
1122
+ `/login/users/${encodeURIComponent(userId)}/phone/code`,
1123
+ {
1124
+ phoneCountryCode: params.phoneCountryCode || params.countryCode,
1125
+ phoneNumber
1126
+ }
1127
+ );
1128
+ }
1129
+ /**
1130
+ * Bind a verified phone number to a hosted login user, merging existing accounts when needed.
1131
+ */
1132
+ async bindPhoneNumber(params) {
1133
+ const userId = params.userId?.trim();
1134
+ const phoneNumber = params.phoneNumber?.trim();
1135
+ const code = params.code?.trim();
1136
+ if (!userId) throw new Error("userId is required");
1137
+ if (!phoneNumber) throw new Error("phoneNumber is required");
1138
+ if (!code) throw new Error("code is required");
1139
+ return this.request(
1140
+ "POST",
1141
+ `/login/users/${encodeURIComponent(userId)}/phone/bind`,
1142
+ {
1143
+ code,
1144
+ phoneCountryCode: params.phoneCountryCode || params.countryCode,
1145
+ phoneNumber
1146
+ }
1147
+ );
1148
+ }
1027
1149
  };
1028
1150
  export {
1029
1151
  LoginUI,