@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.cjs CHANGED
@@ -340,9 +340,6 @@ function buildLoginUrl(params, options, launchPayload) {
340
340
  if (parentOrigin) {
341
341
  url.searchParams.set("origin", parentOrigin);
342
342
  }
343
- if (launchPayload.callbackUrl) {
344
- url.searchParams.set("callbackUrl", launchPayload.callbackUrl);
345
- }
346
343
  return appendLoginLaunchHash(url.toString(), launchPayload);
347
344
  } catch (_error) {
348
345
  const searchParams = new URLSearchParams();
@@ -355,9 +352,6 @@ function buildLoginUrl(params, options, launchPayload) {
355
352
  if (parentOrigin) {
356
353
  searchParams.set("origin", parentOrigin);
357
354
  }
358
- if (launchPayload.callbackUrl) {
359
- searchParams.set("callbackUrl", launchPayload.callbackUrl);
360
- }
361
355
  const query = searchParams.toString();
362
356
  if (!query) {
363
357
  return appendLoginLaunchHash(finalUrl, launchPayload);
@@ -378,6 +372,11 @@ function extractLoginResult(data) {
378
372
  legacyCasdoorId: data.legacyCasdoorId,
379
373
  loginToken: data.loginToken,
380
374
  name: data.name,
375
+ username: data.username,
376
+ phoneCountryCode: data.phoneCountryCode,
377
+ phoneNumber: data.phoneNumber,
378
+ phoneE164: data.phoneE164,
379
+ phoneVerifiedAt: data.phoneVerifiedAt,
381
380
  userId: data.userId,
382
381
  wechatOpenId: data.wechatOpenId,
383
382
  wechatUnionId: data.wechatUnionId
@@ -438,6 +437,23 @@ function publishLoginCallback(state, data) {
438
437
  } catch {
439
438
  }
440
439
  }
440
+ function safeIsPopupClosed(popup) {
441
+ if (!popup) return true;
442
+ try {
443
+ return popup.closed;
444
+ } catch {
445
+ logLoginDebug("Unable to read popup.closed; treating popup as open");
446
+ return false;
447
+ }
448
+ }
449
+ function safeClosePopup(popup) {
450
+ if (!popup) return;
451
+ try {
452
+ popup.close();
453
+ } catch {
454
+ logLoginDebug("Unable to close popup");
455
+ }
456
+ }
441
457
  function cleanLoginCallbackUrl(url) {
442
458
  url.searchParams.delete(LOGIN_CALLBACK_MARKER);
443
459
  url.searchParams.delete(LOGIN_CALLBACK_STATE_PARAM);
@@ -446,7 +462,7 @@ function cleanLoginCallbackUrl(url) {
446
462
  url.hash = returnHash ? `#${returnHash}` : "";
447
463
  return url.toString();
448
464
  }
449
- function handleLoginCallbackIfPresent() {
465
+ function handleLoginCallbackIfPresent(options) {
450
466
  if (typeof window === "undefined") {
451
467
  return false;
452
468
  }
@@ -472,12 +488,19 @@ function handleLoginCallbackIfPresent() {
472
488
  window.history.replaceState(null, "", cleanLoginCallbackUrl(url));
473
489
  } catch {
474
490
  }
475
- window.setTimeout(() => {
476
- try {
477
- window.close();
478
- } catch {
479
- }
480
- }, 30);
491
+ if (options?.autoClose === true) {
492
+ window.setTimeout(() => {
493
+ try {
494
+ window.close();
495
+ } catch {
496
+ }
497
+ }, 30);
498
+ return true;
499
+ }
500
+ try {
501
+ document.documentElement.style.visibility = "";
502
+ } catch {
503
+ }
481
504
  return true;
482
505
  }
483
506
  function logLoginDebug(message, details) {
@@ -492,12 +515,13 @@ function logLoginWarn(message, details) {
492
515
  if (typeof console === "undefined") return;
493
516
  console.warn(LOGIN_UI_LOG_PREFIX, message, details || {});
494
517
  }
495
- var LoginUI = class {
518
+ var LoginUI = class extends HostedFrameModal {
496
519
  constructor() {
520
+ super(...arguments);
497
521
  __publicField(this, "popup", null);
498
522
  __publicField(this, "callbackChannel", null);
499
523
  __publicField(this, "callbackStorageHandler", null);
500
- __publicField(this, "messageHandler", null);
524
+ __publicField(this, "popupMessageHandler", null);
501
525
  __publicField(this, "closeMonitor", null);
502
526
  __publicField(this, "completed", false);
503
527
  }
@@ -508,15 +532,15 @@ var LoginUI = class {
508
532
  if (typeof window !== "undefined" && this.callbackStorageHandler) {
509
533
  window.removeEventListener("storage", this.callbackStorageHandler);
510
534
  }
511
- if (typeof window !== "undefined" && this.messageHandler) {
512
- window.removeEventListener("message", this.messageHandler);
535
+ if (typeof window !== "undefined" && this.popupMessageHandler) {
536
+ window.removeEventListener("message", this.popupMessageHandler);
513
537
  }
514
538
  this.callbackChannel = null;
515
539
  this.callbackStorageHandler = null;
516
540
  if (typeof window !== "undefined" && this.closeMonitor) {
517
541
  window.clearInterval(this.closeMonitor);
518
542
  }
519
- this.messageHandler = null;
543
+ this.popupMessageHandler = null;
520
544
  this.closeMonitor = null;
521
545
  this.popup = null;
522
546
  this.completed = false;
@@ -559,12 +583,12 @@ var LoginUI = class {
559
583
  case "LOGIN_CLOSE":
560
584
  if (options?.autoClose === false) {
561
585
  logLoginInfo(
562
- "Login popup requested close; autoClose disabled, keeping popup open"
586
+ "Login surface requested close; autoClose disabled, keeping it open"
563
587
  );
564
588
  options?.onClose?.();
565
589
  break;
566
590
  }
567
- logLoginInfo("Login popup requested close; autoClose enabled");
591
+ logLoginInfo("Login surface requested close; autoClose enabled");
568
592
  this.close();
569
593
  options?.onClose?.();
570
594
  break;
@@ -598,17 +622,15 @@ var LoginUI = class {
598
622
  }
599
623
  close() {
600
624
  logLoginInfo("close() called", {
625
+ hasModal: Boolean(this.modal),
601
626
  hasPopup: Boolean(this.popup),
602
- popupClosed: this.popup?.closed ?? true
627
+ popupClosed: safeIsPopupClosed(this.popup)
603
628
  });
604
- if (this.popup && !this.popup.closed) {
605
- this.popup.close();
606
- }
629
+ safeClosePopup(this.popup);
630
+ super.close();
607
631
  this.cleanup();
608
632
  }
609
- openLogin(params, options) {
610
- if (typeof window === "undefined") return;
611
- if (this.popup && !this.popup.closed) return;
633
+ buildOpenContext(params, options) {
612
634
  const callbackState = createLoginCallbackState();
613
635
  const launchPayload = buildLoginLaunchPayload(
614
636
  params,
@@ -616,6 +638,54 @@ var LoginUI = class {
616
638
  callbackState
617
639
  );
618
640
  const finalUrl = buildLoginUrl(params, options, launchPayload);
641
+ return { callbackState, finalUrl, launchPayload };
642
+ }
643
+ openLoginModal(params, options) {
644
+ if (typeof document === "undefined") return;
645
+ if (this.modal) return;
646
+ const { callbackState, finalUrl, launchPayload } = this.buildOpenContext(
647
+ params,
648
+ options
649
+ );
650
+ const loginOrigin = getOrigin(finalUrl);
651
+ logLoginInfo("Opening hosted login iframe modal", {
652
+ appId: params.appId,
653
+ callbackState,
654
+ callbackUrl: launchPayload.callbackUrl || null,
655
+ hasCallbackUrl: Boolean(launchPayload.callbackUrl),
656
+ loginUrl: finalUrl,
657
+ allowedOrigin: options?.allowedOrigin || null,
658
+ autoClose: options?.autoClose ?? true,
659
+ displayMode: "modal",
660
+ pageUrl: typeof window !== "undefined" ? window.location.href : null,
661
+ parentOrigin: launchPayload.origin || null
662
+ });
663
+ this.completed = false;
664
+ this.listenForLoginCallback(callbackState, options);
665
+ this.openHostedFrame(finalUrl, {
666
+ allowedOrigin: options?.allowedOrigin || loginOrigin || void 0,
667
+ height: "min(760px, 94vh)",
668
+ onCloseButton: () => {
669
+ options?.onCancel?.();
670
+ options?.onClose?.();
671
+ },
672
+ onMessage: (data, container) => {
673
+ if (data.type === "LOGIN_RESIZE" && data.height) {
674
+ const maxHeight = window.innerHeight * 0.94;
675
+ container.style.height = `${Math.min(data.height, maxHeight)}px`;
676
+ }
677
+ this.handleLoginEvent(data, options);
678
+ },
679
+ width: "min(520px, 100%)"
680
+ });
681
+ }
682
+ openLoginPopup(params, options) {
683
+ if (typeof window === "undefined") return;
684
+ if (this.popup && !safeIsPopupClosed(this.popup)) return;
685
+ const { callbackState, finalUrl, launchPayload } = this.buildOpenContext(
686
+ params,
687
+ options
688
+ );
619
689
  logLoginInfo("Opening hosted login popup", {
620
690
  appId: params.appId,
621
691
  callbackState,
@@ -624,6 +694,7 @@ var LoginUI = class {
624
694
  loginUrl: finalUrl,
625
695
  allowedOrigin: options?.allowedOrigin || null,
626
696
  autoClose: options?.autoClose ?? true,
697
+ displayMode: "popup",
627
698
  pageUrl: typeof window !== "undefined" ? window.location.href : null,
628
699
  parentOrigin: launchPayload.origin || null
629
700
  });
@@ -658,7 +729,7 @@ var LoginUI = class {
658
729
  this.listenForLoginCallback(callbackState, options);
659
730
  const allowedOrigin = options?.allowedOrigin;
660
731
  const popupOrigin = getOrigin(finalUrl);
661
- this.messageHandler = (event) => {
732
+ this.popupMessageHandler = (event) => {
662
733
  if (allowedOrigin && allowedOrigin !== "*" && event.origin !== allowedOrigin) {
663
734
  logLoginWarn("Ignored message due to allowedOrigin mismatch", {
664
735
  allowedOrigin,
@@ -684,26 +755,37 @@ var LoginUI = class {
684
755
  });
685
756
  this.handleLoginEvent(data, options);
686
757
  };
687
- window.addEventListener("message", this.messageHandler);
688
- this.closeMonitor = window.setInterval(() => {
689
- if (!this.popup || this.popup.closed) {
690
- const shouldTreatAsCancel = !this.completed;
691
- logLoginInfo("Detected popup closed", {
692
- shouldTreatAsCancel
693
- });
694
- this.cleanup();
695
- if (shouldTreatAsCancel) {
696
- options?.onCancel?.();
758
+ window.addEventListener("message", this.popupMessageHandler);
759
+ if (options?.monitorPopupClosed === true) {
760
+ this.closeMonitor = window.setInterval(() => {
761
+ if (!this.popup || safeIsPopupClosed(this.popup)) {
762
+ const shouldTreatAsCancel = !this.completed;
763
+ logLoginInfo("Detected popup closed", {
764
+ shouldTreatAsCancel
765
+ });
766
+ this.cleanup();
767
+ if (shouldTreatAsCancel) {
768
+ options?.onCancel?.();
769
+ }
770
+ options?.onClose?.();
697
771
  }
698
- options?.onClose?.();
699
- }
700
- }, 500);
772
+ }, 500);
773
+ }
774
+ }
775
+ openLogin(params, options) {
776
+ if (typeof window === "undefined") return;
777
+ const displayMode = options?.displayMode ?? "modal";
778
+ if (displayMode === "popup") {
779
+ this.openLoginPopup(params, options);
780
+ return;
781
+ }
782
+ this.openLoginModal(params, options);
701
783
  }
702
784
  };
703
785
  function createLoginUI() {
704
786
  return new LoginUI();
705
787
  }
706
- handleLoginCallbackIfPresent();
788
+ handleLoginCallbackIfPresent({ autoClose: false });
707
789
 
708
790
  // src/client.ts
709
791
  var PaymentUI = class extends HostedFrameModal {
@@ -739,7 +821,10 @@ var PaymentUI = class extends HostedFrameModal {
739
821
  );
740
822
  }
741
823
  }
742
- const finalUrl = applyLocaleToUrl(checkoutUrl, options?.locale);
824
+ const finalUrl = applyLocaleToUrl(
825
+ checkoutUrl,
826
+ getAutoResolvedLocale(options?.locale)
827
+ );
743
828
  this.openHostedFrame(finalUrl, {
744
829
  allowedOrigin: options?.allowedOrigin,
745
830
  onCloseButton: () => options?.onCancel?.(),
@@ -896,7 +981,7 @@ var PaymentClient = class {
896
981
  let decrypted = decipher.update(encryptedData, "hex", "utf8");
897
982
  decrypted += decipher.final("utf8");
898
983
  return JSON.parse(decrypted);
899
- } catch (error) {
984
+ } catch {
900
985
  throw new Error(
901
986
  "Failed to decrypt payment callback: Invalid secret or tampered data."
902
987
  );
@@ -1063,6 +1148,43 @@ var PaymentClient = class {
1063
1148
  }
1064
1149
  return this.request("POST", "/login/tokens/verify", { token: token.trim() });
1065
1150
  }
1151
+ /**
1152
+ * Send a phone verification code for binding a phone number to a hosted login user.
1153
+ */
1154
+ async sendPhoneVerificationCode(params) {
1155
+ const userId = params.userId?.trim();
1156
+ const phoneNumber = params.phoneNumber?.trim();
1157
+ if (!userId) throw new Error("userId is required");
1158
+ if (!phoneNumber) throw new Error("phoneNumber is required");
1159
+ return this.request(
1160
+ "POST",
1161
+ `/login/users/${encodeURIComponent(userId)}/phone/code`,
1162
+ {
1163
+ phoneCountryCode: params.phoneCountryCode || params.countryCode,
1164
+ phoneNumber
1165
+ }
1166
+ );
1167
+ }
1168
+ /**
1169
+ * Bind a verified phone number to a hosted login user, merging existing accounts when needed.
1170
+ */
1171
+ async bindPhoneNumber(params) {
1172
+ const userId = params.userId?.trim();
1173
+ const phoneNumber = params.phoneNumber?.trim();
1174
+ const code = params.code?.trim();
1175
+ if (!userId) throw new Error("userId is required");
1176
+ if (!phoneNumber) throw new Error("phoneNumber is required");
1177
+ if (!code) throw new Error("code is required");
1178
+ return this.request(
1179
+ "POST",
1180
+ `/login/users/${encodeURIComponent(userId)}/phone/bind`,
1181
+ {
1182
+ code,
1183
+ phoneCountryCode: params.phoneCountryCode || params.countryCode,
1184
+ phoneNumber
1185
+ }
1186
+ );
1187
+ }
1066
1188
  };
1067
1189
  // Annotate the CommonJS export names for ESM import in node:
1068
1190
  0 && (module.exports = {