@youidian/sdk 3.1.0 → 3.2.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
@@ -199,115 +199,6 @@ var HostedFrameModal = class {
199
199
  }
200
200
  };
201
201
 
202
- // src/client.ts
203
- var PaymentUI = class extends HostedFrameModal {
204
- /**
205
- * Opens the payment checkout page in an iframe modal.
206
- * @param urlOrParams - The checkout page URL or payment parameters
207
- * @param options - UI options
208
- */
209
- openPayment(urlOrParams, options) {
210
- if (typeof document === "undefined") return;
211
- if (this.modal) return;
212
- let checkoutUrl;
213
- if (typeof urlOrParams === "string") {
214
- checkoutUrl = urlOrParams;
215
- } else {
216
- const {
217
- appId,
218
- productId,
219
- priceId,
220
- productCode,
221
- userId,
222
- checkoutUrl: checkoutUrlParam,
223
- baseUrl = "https://pay.imgto.link"
224
- } = urlOrParams;
225
- const base = (checkoutUrlParam || baseUrl).replace(/\/$/, "");
226
- if (productCode) {
227
- checkoutUrl = `${base}/checkout/${appId}/code/${productCode}?userId=${encodeURIComponent(userId)}`;
228
- } else if (productId && priceId) {
229
- checkoutUrl = `${base}/checkout/${appId}/${productId}/${priceId}?userId=${encodeURIComponent(userId)}`;
230
- } else {
231
- throw new Error(
232
- "Either productCode or both productId and priceId are required"
233
- );
234
- }
235
- }
236
- const finalUrl = applyLocaleToUrl(checkoutUrl, options?.locale);
237
- this.openHostedFrame(finalUrl, {
238
- allowedOrigin: options?.allowedOrigin,
239
- onCloseButton: () => options?.onCancel?.(),
240
- onMessage: (data, container) => {
241
- switch (data.type) {
242
- case "PAYMENT_SUCCESS":
243
- options?.onSuccess?.(data.orderId);
244
- break;
245
- case "PAYMENT_CANCELLED":
246
- options?.onCancel?.(data.orderId);
247
- break;
248
- case "PAYMENT_RESIZE":
249
- if (data.height) {
250
- const maxHeight = window.innerHeight * 0.9;
251
- const newHeight = Math.min(data.height, maxHeight);
252
- container.style.height = `${newHeight}px`;
253
- }
254
- break;
255
- case "PAYMENT_CLOSE":
256
- this.close();
257
- options?.onClose?.();
258
- break;
259
- }
260
- }
261
- });
262
- }
263
- /**
264
- * Poll order status from integrator's API endpoint
265
- * @param statusUrl - The integrator's API endpoint to check order status
266
- * @param options - Polling options
267
- * @returns Promise that resolves when order is paid or rejects on timeout/failure
268
- */
269
- async pollOrderStatus(statusUrl, options) {
270
- const interval = options?.interval || 3e3;
271
- const timeout = options?.timeout || 3e5;
272
- const startTime = Date.now();
273
- return new Promise((resolve, reject) => {
274
- const poll = async () => {
275
- try {
276
- const response = await fetch(statusUrl);
277
- if (!response.ok) {
278
- throw new Error(`Status check failed: ${response.status}`);
279
- }
280
- const status = await response.json();
281
- options?.onStatusChange?.(status);
282
- if (status.status === "PAID") {
283
- resolve(status);
284
- return;
285
- }
286
- if (status.status === "CANCELLED" || status.status === "FAILED") {
287
- reject(new Error(`Order ${status.status.toLowerCase()}`));
288
- return;
289
- }
290
- if (Date.now() - startTime > timeout) {
291
- reject(new Error("Polling timeout"));
292
- return;
293
- }
294
- setTimeout(poll, interval);
295
- } catch (error) {
296
- if (Date.now() - startTime > timeout) {
297
- reject(error);
298
- return;
299
- }
300
- setTimeout(poll, interval);
301
- }
302
- };
303
- poll();
304
- });
305
- }
306
- };
307
- function createPaymentUI() {
308
- return new PaymentUI();
309
- }
310
-
311
202
  // src/login.ts
312
203
  function getOrigin(value) {
313
204
  if (!value) return null;
@@ -317,10 +208,70 @@ function getOrigin(value) {
317
208
  return null;
318
209
  }
319
210
  }
320
- function buildLoginUrl(params) {
211
+ function createLoginCallbackState() {
212
+ if (typeof crypto !== "undefined" && crypto.randomUUID) {
213
+ return crypto.randomUUID().replace(/-/g, "");
214
+ }
215
+ return `${Date.now().toString(36)}${Math.random().toString(36).slice(2)}`;
216
+ }
217
+ function buildLoginCallbackUrl(callbackState, callbackUrl) {
218
+ const baseUrl = callbackUrl || window.location.href;
219
+ const url = new URL(baseUrl, window.location.href);
220
+ const returnHash = url.hash.replace(/^#/, "");
221
+ url.hash = "";
222
+ url.searchParams.set(LOGIN_CALLBACK_MARKER, "1");
223
+ url.searchParams.set(LOGIN_CALLBACK_STATE_PARAM, callbackState);
224
+ if (returnHash) {
225
+ url.searchParams.set(LOGIN_CALLBACK_RETURN_HASH_PARAM, returnHash);
226
+ } else {
227
+ url.searchParams.delete(LOGIN_CALLBACK_RETURN_HASH_PARAM);
228
+ }
229
+ return url.toString();
230
+ }
231
+ function buildLoginLaunchPayload(params, options, callbackState) {
232
+ const parentOrigin = typeof window !== "undefined" ? window.location.origin : void 0;
233
+ const callbackUrl = typeof window !== "undefined" && callbackState ? buildLoginCallbackUrl(callbackState, options?.callbackUrl) : void 0;
234
+ return {
235
+ autoClose: options?.autoClose ?? true,
236
+ callbackUrl,
237
+ callbackState,
238
+ origin: parentOrigin,
239
+ preferredChannel: params.preferredChannel
240
+ };
241
+ }
242
+ function appendLoginLaunchHash(urlValue, payload) {
243
+ const hashParams = new URLSearchParams();
244
+ if (payload.autoClose === false) {
245
+ hashParams.set("ydAutoClose", "false");
246
+ }
247
+ if (payload.origin) {
248
+ hashParams.set("ydOrigin", payload.origin);
249
+ }
250
+ if (payload.callbackUrl) {
251
+ hashParams.set("ydCallbackUrl", payload.callbackUrl);
252
+ }
253
+ if (payload.preferredChannel) {
254
+ hashParams.set("ydPreferredChannel", payload.preferredChannel);
255
+ }
256
+ const hash = hashParams.toString();
257
+ if (!hash) {
258
+ return urlValue;
259
+ }
260
+ try {
261
+ const url = new URL(urlValue);
262
+ url.hash = hash;
263
+ return url.toString();
264
+ } catch (_error) {
265
+ return `${urlValue}#${hash}`;
266
+ }
267
+ }
268
+ function buildLoginPopupName(payload) {
269
+ return `youidian-login:${JSON.stringify(payload)}`;
270
+ }
271
+ function buildLoginUrl(params, options, launchPayload) {
321
272
  const { appId, baseUrl = "https://pay.imgto.link", loginUrl } = params;
322
273
  const rawBase = (loginUrl || baseUrl).replace(/\/$/, "");
323
- const parentOrigin = typeof window !== "undefined" ? window.location.origin : void 0;
274
+ const parentOrigin = launchPayload.origin;
324
275
  let finalUrl;
325
276
  try {
326
277
  const url = new URL(rawBase);
@@ -344,24 +295,39 @@ function buildLoginUrl(params) {
344
295
  if (params.preferredChannel) {
345
296
  url.searchParams.set("preferredChannel", params.preferredChannel);
346
297
  }
298
+ if (options?.autoClose === false) {
299
+ url.searchParams.set("autoClose", "false");
300
+ }
347
301
  if (parentOrigin) {
348
302
  url.searchParams.set("origin", parentOrigin);
349
303
  }
350
- return url.toString();
304
+ if (launchPayload.callbackUrl) {
305
+ url.searchParams.set("callbackUrl", launchPayload.callbackUrl);
306
+ }
307
+ return appendLoginLaunchHash(url.toString(), launchPayload);
351
308
  } catch (_error) {
352
309
  const searchParams = new URLSearchParams();
353
310
  if (params.preferredChannel) {
354
311
  searchParams.set("preferredChannel", params.preferredChannel);
355
312
  }
313
+ if (options?.autoClose === false) {
314
+ searchParams.set("autoClose", "false");
315
+ }
356
316
  if (parentOrigin) {
357
317
  searchParams.set("origin", parentOrigin);
358
318
  }
319
+ if (launchPayload.callbackUrl) {
320
+ searchParams.set("callbackUrl", launchPayload.callbackUrl);
321
+ }
359
322
  const query = searchParams.toString();
360
323
  if (!query) {
361
- return finalUrl;
324
+ return appendLoginLaunchHash(finalUrl, launchPayload);
362
325
  }
363
326
  const separator = finalUrl.includes("?") ? "&" : "?";
364
- return `${finalUrl}${separator}${query}`;
327
+ return appendLoginLaunchHash(
328
+ `${finalUrl}${separator}${query}`,
329
+ launchPayload
330
+ );
365
331
  }
366
332
  }
367
333
  function extractLoginResult(data) {
@@ -379,6 +345,102 @@ function extractLoginResult(data) {
379
345
  };
380
346
  }
381
347
  var LOGIN_UI_LOG_PREFIX = "[Youidian LoginUI]";
348
+ var LOGIN_CALLBACK_MARKER = "yd_login_callback";
349
+ var LOGIN_CALLBACK_RESULT_PARAM = "yd_login_result";
350
+ var LOGIN_CALLBACK_RETURN_HASH_PARAM = "yd_login_return_hash";
351
+ var LOGIN_CALLBACK_STATE_PARAM = "yd_login_state";
352
+ var LOGIN_CALLBACK_STORAGE_PREFIX = "yd-login-callback:";
353
+ function decodeCallbackPayload(value) {
354
+ try {
355
+ const padded = value.padEnd(
356
+ value.length + (4 - value.length % 4) % 4,
357
+ "="
358
+ );
359
+ const base64 = padded.replaceAll("-", "+").replaceAll("_", "/");
360
+ const binary = atob(base64);
361
+ const json = decodeURIComponent(
362
+ Array.from(
363
+ binary,
364
+ (char) => `%${char.charCodeAt(0).toString(16).padStart(2, "0")}`
365
+ ).join("")
366
+ );
367
+ const parsed = JSON.parse(json);
368
+ return parsed && typeof parsed === "object" && parsed.type ? parsed : null;
369
+ } catch {
370
+ return null;
371
+ }
372
+ }
373
+ function getLoginCallbackChannelName(state) {
374
+ return `youidian-login:${state}`;
375
+ }
376
+ function getLoginCallbackStorageKey(state) {
377
+ return `${LOGIN_CALLBACK_STORAGE_PREFIX}${state}`;
378
+ }
379
+ function publishLoginCallback(state, data) {
380
+ try {
381
+ const channel = new BroadcastChannel(getLoginCallbackChannelName(state));
382
+ channel.postMessage(data);
383
+ channel.close();
384
+ } catch {
385
+ }
386
+ try {
387
+ const storageKey = getLoginCallbackStorageKey(state);
388
+ window.localStorage.setItem(storageKey, JSON.stringify(data));
389
+ window.setTimeout(() => {
390
+ try {
391
+ window.localStorage.removeItem(storageKey);
392
+ } catch {
393
+ }
394
+ }, 800);
395
+ } catch {
396
+ }
397
+ try {
398
+ window.opener?.postMessage(data, window.location.origin);
399
+ } catch {
400
+ }
401
+ }
402
+ function cleanLoginCallbackUrl(url) {
403
+ url.searchParams.delete(LOGIN_CALLBACK_MARKER);
404
+ url.searchParams.delete(LOGIN_CALLBACK_STATE_PARAM);
405
+ const returnHash = url.searchParams.get(LOGIN_CALLBACK_RETURN_HASH_PARAM);
406
+ url.searchParams.delete(LOGIN_CALLBACK_RETURN_HASH_PARAM);
407
+ url.hash = returnHash ? `#${returnHash}` : "";
408
+ return url.toString();
409
+ }
410
+ function handleLoginCallbackIfPresent() {
411
+ if (typeof window === "undefined") {
412
+ return false;
413
+ }
414
+ const url = new URL(window.location.href);
415
+ if (url.searchParams.get(LOGIN_CALLBACK_MARKER) !== "1") {
416
+ return false;
417
+ }
418
+ const state = url.searchParams.get(LOGIN_CALLBACK_STATE_PARAM) || "";
419
+ const hashParams = new URLSearchParams(url.hash.replace(/^#/, ""));
420
+ const rawResult = hashParams.get(LOGIN_CALLBACK_RESULT_PARAM);
421
+ const data = rawResult && state ? decodeCallbackPayload(rawResult) : {
422
+ type: "LOGIN_ERROR",
423
+ message: "Missing login callback result"
424
+ };
425
+ try {
426
+ document.documentElement.style.visibility = "hidden";
427
+ } catch {
428
+ }
429
+ if (state && data) {
430
+ publishLoginCallback(state, data);
431
+ }
432
+ try {
433
+ window.history.replaceState(null, "", cleanLoginCallbackUrl(url));
434
+ } catch {
435
+ }
436
+ window.setTimeout(() => {
437
+ try {
438
+ window.close();
439
+ } catch {
440
+ }
441
+ }, 30);
442
+ return true;
443
+ }
382
444
  function logLoginDebug(message, details) {
383
445
  if (typeof console === "undefined") return;
384
446
  console.debug(LOGIN_UI_LOG_PREFIX, message, details || {});
@@ -394,14 +456,24 @@ function logLoginWarn(message, details) {
394
456
  var LoginUI = class {
395
457
  constructor() {
396
458
  __publicField(this, "popup", null);
459
+ __publicField(this, "callbackChannel", null);
460
+ __publicField(this, "callbackStorageHandler", null);
397
461
  __publicField(this, "messageHandler", null);
398
462
  __publicField(this, "closeMonitor", null);
399
463
  __publicField(this, "completed", false);
400
464
  }
401
465
  cleanup() {
466
+ if (this.callbackChannel) {
467
+ this.callbackChannel.close();
468
+ }
469
+ if (typeof window !== "undefined" && this.callbackStorageHandler) {
470
+ window.removeEventListener("storage", this.callbackStorageHandler);
471
+ }
402
472
  if (typeof window !== "undefined" && this.messageHandler) {
403
473
  window.removeEventListener("message", this.messageHandler);
404
474
  }
475
+ this.callbackChannel = null;
476
+ this.callbackStorageHandler = null;
405
477
  if (typeof window !== "undefined" && this.closeMonitor) {
406
478
  window.clearInterval(this.closeMonitor);
407
479
  }
@@ -410,6 +482,81 @@ var LoginUI = class {
410
482
  this.popup = null;
411
483
  this.completed = false;
412
484
  }
485
+ handleLoginEvent(data, options) {
486
+ if (!data || typeof data !== "object" || !data.type) {
487
+ logLoginDebug("Ignored non-login event payload");
488
+ return;
489
+ }
490
+ logLoginInfo("Received login event", {
491
+ type: data.type
492
+ });
493
+ switch (data.type) {
494
+ case "LOGIN_SUCCESS":
495
+ if (this.completed) {
496
+ break;
497
+ }
498
+ this.completed = true;
499
+ logLoginInfo("Login succeeded", {
500
+ channel: data.channel || null,
501
+ userId: data.userId || null
502
+ });
503
+ options?.onSuccess?.(extractLoginResult(data));
504
+ break;
505
+ case "LOGIN_CANCELLED":
506
+ logLoginInfo("Login cancelled");
507
+ options?.onCancel?.();
508
+ break;
509
+ case "LOGIN_RESIZE":
510
+ break;
511
+ case "LOGIN_ERROR":
512
+ if (this.completed) {
513
+ break;
514
+ }
515
+ logLoginWarn("Login flow reported an error", {
516
+ message: data.message || data.error || null
517
+ });
518
+ options?.onError?.(data.message || data.error, data);
519
+ break;
520
+ case "LOGIN_CLOSE":
521
+ if (options?.autoClose === false) {
522
+ logLoginInfo(
523
+ "Login popup requested close; autoClose disabled, keeping popup open"
524
+ );
525
+ options?.onClose?.();
526
+ break;
527
+ }
528
+ logLoginInfo("Login popup requested close; autoClose enabled");
529
+ this.close();
530
+ options?.onClose?.();
531
+ break;
532
+ }
533
+ }
534
+ listenForLoginCallback(callbackState, options) {
535
+ try {
536
+ this.callbackChannel = new BroadcastChannel(
537
+ getLoginCallbackChannelName(callbackState)
538
+ );
539
+ this.callbackChannel.onmessage = (event) => {
540
+ this.handleLoginEvent(event.data, options);
541
+ this.handleLoginEvent({ type: "LOGIN_CLOSE" }, options);
542
+ };
543
+ } catch {
544
+ logLoginDebug("BroadcastChannel is unavailable for login callback");
545
+ }
546
+ this.callbackStorageHandler = (event) => {
547
+ if (event.key !== getLoginCallbackStorageKey(callbackState) || !event.newValue) {
548
+ return;
549
+ }
550
+ try {
551
+ const data = JSON.parse(event.newValue);
552
+ this.handleLoginEvent(data, options);
553
+ this.handleLoginEvent({ type: "LOGIN_CLOSE" }, options);
554
+ } catch {
555
+ logLoginWarn("Failed to parse login callback storage payload");
556
+ }
557
+ };
558
+ window.addEventListener("storage", this.callbackStorageHandler);
559
+ }
413
560
  close() {
414
561
  logLoginInfo("close() called", {
415
562
  hasPopup: Boolean(this.popup),
@@ -423,7 +570,13 @@ var LoginUI = class {
423
570
  openLogin(params, options) {
424
571
  if (typeof window === "undefined") return;
425
572
  if (this.popup && !this.popup.closed) return;
426
- const finalUrl = buildLoginUrl(params);
573
+ const callbackState = createLoginCallbackState();
574
+ const launchPayload = buildLoginLaunchPayload(
575
+ params,
576
+ options,
577
+ callbackState
578
+ );
579
+ const finalUrl = buildLoginUrl(params, options, launchPayload);
427
580
  logLoginInfo("Opening hosted login popup", {
428
581
  appId: params.appId,
429
582
  loginUrl: finalUrl,
@@ -449,7 +602,8 @@ var LoginUI = class {
449
602
  "resizable=yes",
450
603
  "scrollbars=yes"
451
604
  ].join(",");
452
- const popup = window.open(finalUrl, "youidian-login", features);
605
+ const popupName = buildLoginPopupName(launchPayload);
606
+ const popup = window.open(finalUrl, popupName, features);
453
607
  if (!popup) {
454
608
  logLoginWarn("Popup blocked by the browser");
455
609
  options?.onError?.("Login popup was blocked");
@@ -457,6 +611,7 @@ var LoginUI = class {
457
611
  }
458
612
  this.popup = popup;
459
613
  this.completed = false;
614
+ this.listenForLoginCallback(callbackState, options);
460
615
  const allowedOrigin = options?.allowedOrigin;
461
616
  const popupOrigin = getOrigin(finalUrl);
462
617
  this.messageHandler = (event) => {
@@ -483,38 +638,7 @@ var LoginUI = class {
483
638
  type: data.type,
484
639
  eventOrigin: event.origin
485
640
  });
486
- switch (data.type) {
487
- case "LOGIN_SUCCESS":
488
- this.completed = true;
489
- logLoginInfo("Login succeeded", {
490
- channel: data.channel || null,
491
- userId: data.userId || null
492
- });
493
- options?.onSuccess?.(extractLoginResult(data));
494
- break;
495
- case "LOGIN_CANCELLED":
496
- logLoginInfo("Login cancelled");
497
- options?.onCancel?.();
498
- break;
499
- case "LOGIN_RESIZE":
500
- break;
501
- case "LOGIN_ERROR":
502
- logLoginWarn("Login flow reported an error", {
503
- message: data.message || data.error || null
504
- });
505
- options?.onError?.(data.message || data.error, data);
506
- break;
507
- case "LOGIN_CLOSE":
508
- if (options?.autoClose === false) {
509
- logLoginInfo("Login popup requested close; autoClose disabled, keeping popup open");
510
- options?.onClose?.();
511
- break;
512
- }
513
- logLoginInfo("Login popup requested close; autoClose enabled");
514
- this.close();
515
- options?.onClose?.();
516
- break;
517
- }
641
+ this.handleLoginEvent(data, options);
518
642
  };
519
643
  window.addEventListener("message", this.messageHandler);
520
644
  this.closeMonitor = window.setInterval(() => {
@@ -535,9 +659,119 @@ var LoginUI = class {
535
659
  function createLoginUI() {
536
660
  return new LoginUI();
537
661
  }
662
+ handleLoginCallbackIfPresent();
663
+
664
+ // src/client.ts
665
+ var PaymentUI = class extends HostedFrameModal {
666
+ /**
667
+ * Opens the payment checkout page in an iframe modal.
668
+ * @param urlOrParams - The checkout page URL or payment parameters
669
+ * @param options - UI options
670
+ */
671
+ openPayment(urlOrParams, options) {
672
+ if (typeof document === "undefined") return;
673
+ if (this.modal) return;
674
+ let checkoutUrl;
675
+ if (typeof urlOrParams === "string") {
676
+ checkoutUrl = urlOrParams;
677
+ } else {
678
+ const {
679
+ appId,
680
+ productId,
681
+ priceId,
682
+ productCode,
683
+ userId,
684
+ checkoutUrl: checkoutUrlParam,
685
+ baseUrl = "https://pay.imgto.link"
686
+ } = urlOrParams;
687
+ const base = (checkoutUrlParam || baseUrl).replace(/\/$/, "");
688
+ if (productCode) {
689
+ checkoutUrl = `${base}/checkout/${appId}/code/${productCode}?userId=${encodeURIComponent(userId)}`;
690
+ } else if (productId && priceId) {
691
+ checkoutUrl = `${base}/checkout/${appId}/${productId}/${priceId}?userId=${encodeURIComponent(userId)}`;
692
+ } else {
693
+ throw new Error(
694
+ "Either productCode or both productId and priceId are required"
695
+ );
696
+ }
697
+ }
698
+ const finalUrl = applyLocaleToUrl(checkoutUrl, options?.locale);
699
+ this.openHostedFrame(finalUrl, {
700
+ allowedOrigin: options?.allowedOrigin,
701
+ onCloseButton: () => options?.onCancel?.(),
702
+ onMessage: (data, container) => {
703
+ switch (data.type) {
704
+ case "PAYMENT_SUCCESS":
705
+ options?.onSuccess?.(data.orderId);
706
+ break;
707
+ case "PAYMENT_CANCELLED":
708
+ options?.onCancel?.(data.orderId);
709
+ break;
710
+ case "PAYMENT_RESIZE":
711
+ if (data.height) {
712
+ const maxHeight = window.innerHeight * 0.9;
713
+ const newHeight = Math.min(data.height, maxHeight);
714
+ container.style.height = `${newHeight}px`;
715
+ }
716
+ break;
717
+ case "PAYMENT_CLOSE":
718
+ this.close();
719
+ options?.onClose?.();
720
+ break;
721
+ }
722
+ }
723
+ });
724
+ }
725
+ /**
726
+ * Poll order status from integrator's API endpoint
727
+ * @param statusUrl - The integrator's API endpoint to check order status
728
+ * @param options - Polling options
729
+ * @returns Promise that resolves when order is paid or rejects on timeout/failure
730
+ */
731
+ async pollOrderStatus(statusUrl, options) {
732
+ const interval = options?.interval || 3e3;
733
+ const timeout = options?.timeout || 3e5;
734
+ const startTime = Date.now();
735
+ return new Promise((resolve, reject) => {
736
+ const poll = async () => {
737
+ try {
738
+ const response = await fetch(statusUrl);
739
+ if (!response.ok) {
740
+ throw new Error(`Status check failed: ${response.status}`);
741
+ }
742
+ const status = await response.json();
743
+ options?.onStatusChange?.(status);
744
+ if (status.status === "PAID") {
745
+ resolve(status);
746
+ return;
747
+ }
748
+ if (status.status === "CANCELLED" || status.status === "FAILED") {
749
+ reject(new Error(`Order ${status.status.toLowerCase()}`));
750
+ return;
751
+ }
752
+ if (Date.now() - startTime > timeout) {
753
+ reject(new Error("Polling timeout"));
754
+ return;
755
+ }
756
+ setTimeout(poll, interval);
757
+ } catch (error) {
758
+ if (Date.now() - startTime > timeout) {
759
+ reject(error);
760
+ return;
761
+ }
762
+ setTimeout(poll, interval);
763
+ }
764
+ };
765
+ poll();
766
+ });
767
+ }
768
+ };
769
+ function createPaymentUI() {
770
+ return new PaymentUI();
771
+ }
538
772
 
539
773
  // src/server.ts
540
- import crypto from "crypto";
774
+ import crypto2 from "crypto";
541
775
  var PaymentClient = class {
542
776
  // 用于生成 checkout URL
543
777
  constructor(options) {
@@ -561,7 +795,7 @@ var PaymentClient = class {
561
795
  */
562
796
  generateSignature(timestamp) {
563
797
  const str = `${this.appId}${this.appSecret}${timestamp}`;
564
- return crypto.createHash("sha256").update(str).digest("hex");
798
+ return crypto2.createHash("sha256").update(str).digest("hex");
565
799
  }
566
800
  /**
567
801
  * Internal request helper for Gateway API
@@ -608,8 +842,8 @@ var PaymentClient = class {
608
842
  decryptCallback(notification) {
609
843
  try {
610
844
  const { iv, encryptedData, authTag } = notification;
611
- const key = crypto.createHash("sha256").update(this.appSecret).digest();
612
- const decipher = crypto.createDecipheriv(
845
+ const key = crypto2.createHash("sha256").update(this.appSecret).digest();
846
+ const decipher = crypto2.createDecipheriv(
613
847
  "aes-256-gcm",
614
848
  key,
615
849
  Buffer.from(iv, "hex")
@@ -791,6 +1025,7 @@ export {
791
1025
  PaymentClient,
792
1026
  PaymentUI,
793
1027
  createLoginUI,
794
- createPaymentUI
1028
+ createPaymentUI,
1029
+ handleLoginCallbackIfPresent
795
1030
  };
796
1031
  //# sourceMappingURL=index.js.map