recur-tw 0.4.1 → 0.4.4

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/README.md CHANGED
@@ -85,7 +85,6 @@ function SubscriptionPage() {
85
85
  planId: plan.id,
86
86
  customerEmail: 'user@example.com',
87
87
  customerName: 'John Doe',
88
- customerPhone: '+886912345678',
89
88
  })}
90
89
  disabled={isCheckingOut}
91
90
  >
@@ -196,7 +195,6 @@ await checkout({
196
195
  planId: 'plan_xxx',
197
196
  customerEmail: 'user@example.com',
198
197
  customerName: 'John Doe',
199
- customerPhone: '+886912345678',
200
198
  // mode: 'embedded' is default when containerElementId is configured
201
199
  });
202
200
  ```
@@ -398,12 +396,11 @@ interface CheckoutOptions {
398
396
  // Required: Plan ID to subscribe to
399
397
  planId: string;
400
398
 
401
- // Customer information
402
- customerEmail?: string;
399
+ // Customer information (email is required)
400
+ customerEmail: string; // Required: primary customer identifier
403
401
  customerName?: string;
404
- customerPhone?: string;
405
402
 
406
- // External customer ID - link to your existing users
403
+ // External customer ID - link to your existing users (optional, immutable once set)
407
404
  externalCustomerId?: string;
408
405
 
409
406
  // Checkout mode
@@ -423,7 +420,12 @@ interface CheckoutOptions {
423
420
 
424
421
  ### Customer Identification
425
422
 
426
- The SDK supports multiple ways to identify customers across your system and Recur.
423
+ The SDK uses email as the primary customer identifier, with optional external ID support.
424
+
425
+ #### Required Fields
426
+
427
+ - `customerEmail` - **Required**. Customer's email address (primary identifier)
428
+ - `externalCustomerId` - Optional. Your system's user ID
427
429
 
428
430
  #### Using External Customer ID
429
431
 
@@ -433,15 +435,15 @@ The `externalCustomerId` parameter allows you to link Recur subscriptions to you
433
435
  // React
434
436
  await checkout({
435
437
  planId: 'plan_xxx',
436
- customerEmail: 'user@example.com',
438
+ customerEmail: 'user@example.com', // Required
437
439
  customerName: 'John Doe',
438
- externalCustomerId: 'user_12345', // Your system's user ID
440
+ externalCustomerId: 'user_12345', // Optional: Your system's user ID
439
441
  });
440
442
 
441
443
  // Vanilla JS
442
444
  await recur.checkout({
443
445
  planId: 'plan_xxx',
444
- customerEmail: 'user@example.com',
446
+ customerEmail: 'user@example.com', // Required
445
447
  externalCustomerId: 'cus_abc456',
446
448
  });
447
449
 
@@ -450,28 +452,31 @@ await recur.redirectToCheckout({
450
452
  productId: 'prod_xxx',
451
453
  successUrl: '/success',
452
454
  cancelUrl: '/cancel',
453
- customerEmail: 'user@example.com',
455
+ customerEmail: 'user@example.com', // Required
454
456
  externalCustomerId: 'user_12345',
455
457
  });
456
458
  ```
457
459
 
458
- #### Required Fields
459
-
460
- For customer identification, **at least one** of the following must be provided:
461
- - `customerEmail` - Customer's email address
462
- - `externalCustomerId` - Your system's user ID
460
+ #### Customer Resolution Rules
463
461
 
464
- The SDK will throw an error if neither is provided.
462
+ When processing a checkout:
465
463
 
466
- #### Customer Resolution Priority
464
+ 1. **externalCustomerId provided** - Looks up customer by external ID first
465
+ - If found, verifies email matches (throws error if mismatch)
466
+ - If not found, checks if email already exists
467
+ 2. **Email lookup** - If external ID not found or not provided
468
+ - If email exists and external ID was provided → Error (cannot add external ID to existing customer)
469
+ - If email exists without external ID → Returns existing customer
470
+ 3. **Create new** - Creates a new customer if neither found
467
471
 
468
- When processing a checkout, the system uses the following priority to identify customers:
472
+ #### Important: External ID is Immutable
469
473
 
470
- 1. **externalCustomerId** - If provided, looks up customer by external ID first
471
- 2. **customerEmail** - Falls back to email-based lookup
472
- 3. **Create new** - Creates a new customer if no match found
474
+ The `externalCustomerId` can only be set when **creating** a customer. Once set:
475
+ - It cannot be changed
476
+ - It cannot be added to an existing customer
477
+ - It cannot be transferred to another customer
473
478
 
474
- If an `externalCustomerId` is provided but the customer already exists by email, the external ID will be bound to that existing customer.
479
+ This design ensures data consistency and prevents accidental customer merges.
475
480
 
476
481
  #### Retrieving Customer by External ID
477
482
 
@@ -481,13 +486,12 @@ Use the API to retrieve customers by their external ID:
481
486
  GET /api/v1/subscribers/external/{externalCustomerId}
482
487
  ```
483
488
 
484
- This allows you to query subscription status and details using your own user identifiers.
485
-
486
489
  #### Best Practices
487
490
 
491
+ - **Always provide email**: Email is required for all checkout operations
492
+ - **Set external ID early**: Include `externalCustomerId` in the initial checkout request when creating customers
488
493
  - **Use consistent IDs**: Use your database primary key or UUID as the external ID
489
- - **Set early**: Include `externalCustomerId` in the initial checkout request
490
- - **Provide both when possible**: Although only one is required, providing both email and external ID ensures maximum flexibility
494
+ - **Plan ahead**: Decide whether to use external IDs before your first customer signup
491
495
 
492
496
  ---
493
497
 
package/dist/index.cjs CHANGED
@@ -1461,7 +1461,7 @@ var init_payment_form = __esm({
1461
1461
  section.className = "customer-info-section";
1462
1462
  const customerName = this.getAttribute("customer-name");
1463
1463
  const customerEmail = this.getAttribute("customer-email");
1464
- if (customerName && customerEmail) {
1464
+ if (customerEmail) {
1465
1465
  section.innerHTML = `
1466
1466
  <style>
1467
1467
  .recur-info-display {
@@ -1497,10 +1497,12 @@ var init_payment_form = __esm({
1497
1497
  </style>
1498
1498
 
1499
1499
  <div class="recur-info-display">
1500
- <div class="recur-info-row">
1501
- <span class="recur-info-label">\u5BA2\u6236\u59D3\u540D\uFF1A</span>
1502
- <span class="recur-info-value">${customerName}</span>
1503
- </div>
1500
+ ${customerName ? `
1501
+ <div class="recur-info-row">
1502
+ <span class="recur-info-label">\u5BA2\u6236\u59D3\u540D\uFF1A</span>
1503
+ <span class="recur-info-value">${customerName}</span>
1504
+ </div>
1505
+ ` : ""}
1504
1506
  <div class="recur-info-row">
1505
1507
  <span class="recur-info-label">\u96FB\u5B50\u90F5\u4EF6\uFF1A</span>
1506
1508
  <span class="recur-info-value">${customerEmail}</span>
@@ -1563,17 +1565,7 @@ var init_payment_form = __esm({
1563
1565
  id="${this.containerId}-name"
1564
1566
  class="recur-form-input"
1565
1567
  placeholder="\u738B\u5C0F\u660E"
1566
- required
1567
- />
1568
- </div>
1569
-
1570
- <div class="recur-form-group">
1571
- <label class="recur-form-label" for="${this.containerId}-phone">\u96FB\u8A71</label>
1572
- <input
1573
- type="tel"
1574
- id="${this.containerId}-phone"
1575
- class="recur-form-input"
1576
- placeholder="+886 912345678"
1568
+ value="${customerName || ""}"
1577
1569
  required
1578
1570
  />
1579
1571
  </div>
@@ -1850,14 +1842,11 @@ var init_payment_form = __esm({
1850
1842
  }
1851
1843
  let email;
1852
1844
  let name;
1853
- let phone;
1854
1845
  const emailInput = document.getElementById(`${this.containerId}-email`);
1855
1846
  const nameInput = document.getElementById(`${this.containerId}-name`);
1856
- const phoneInput = document.getElementById(`${this.containerId}-phone`);
1857
1847
  if (emailInput && nameInput) {
1858
1848
  email = emailInput.value;
1859
1849
  name = nameInput.value;
1860
- phone = phoneInput?.value;
1861
1850
  if (!email || !name) {
1862
1851
  this.showError("\u8ACB\u586B\u5BEB\u59D3\u540D\u548C\u96FB\u5B50\u90F5\u4EF6");
1863
1852
  return;
@@ -1876,7 +1865,6 @@ var init_payment_form = __esm({
1876
1865
  detail: {
1877
1866
  customerEmail: email,
1878
1867
  customerName: name,
1879
- customerPhone: phone,
1880
1868
  paymentSession: this._paymentSession
1881
1869
  },
1882
1870
  bubbles: true,
@@ -1961,8 +1949,7 @@ var init_payment_form = __esm({
1961
1949
  getFormData() {
1962
1950
  return {
1963
1951
  email: document.getElementById(`${this.containerId}-email`)?.value,
1964
- name: document.getElementById(`${this.containerId}-name`)?.value,
1965
- phone: document.getElementById(`${this.containerId}-phone`)?.value
1952
+ name: document.getElementById(`${this.containerId}-name`)?.value
1966
1953
  };
1967
1954
  }
1968
1955
  /**
@@ -1977,10 +1964,6 @@ var init_payment_form = __esm({
1977
1964
  const nameInput = document.getElementById(`${this.containerId}-name`);
1978
1965
  if (nameInput) nameInput.value = data.name;
1979
1966
  }
1980
- if (data.phone) {
1981
- const phoneInput = document.getElementById(`${this.containerId}-phone`);
1982
- if (phoneInput) phoneInput.value = data.phone;
1983
- }
1984
1967
  }
1985
1968
  };
1986
1969
  if (!customElements.get("recur-payment-form")) {
@@ -2358,8 +2341,8 @@ function RecurProvider({ children, config: initialConfig = {} }) {
2358
2341
  if (!options.customerName) {
2359
2342
  throw new Error("customerName is required");
2360
2343
  }
2361
- if (!options.customerEmail && !options.externalCustomerId) {
2362
- throw new Error("Either customerEmail or externalCustomerId is required for customer identification");
2344
+ if (!options.customerEmail) {
2345
+ throw new Error("customerEmail is required");
2363
2346
  }
2364
2347
  const baseUrl = config.baseUrl || "https://api.recur.tw";
2365
2348
  console.log("[Recur SDK] Base URL:", baseUrl);
@@ -2483,7 +2466,6 @@ function RecurProvider({ children, config: initialConfig = {} }) {
2483
2466
  productId: options.planId,
2484
2467
  customerName: options.customerName,
2485
2468
  customerEmail: options.customerEmail,
2486
- customerPhone: options.customerPhone,
2487
2469
  externalCustomerId: options.externalCustomerId
2488
2470
  })
2489
2471
  });
package/dist/index.d.cts CHANGED
@@ -212,11 +212,15 @@ interface CheckoutOptions {
212
212
  * Customer information
213
213
  */
214
214
  customerName?: string;
215
- customerEmail?: string;
216
- customerPhone?: string;
217
215
  /**
218
- * External customer ID from your system
219
- * Use this to link Recur subscriptions to your existing users
216
+ * Customer email address (required)
217
+ * Used as the primary identifier for the customer
218
+ */
219
+ customerEmail: string;
220
+ /**
221
+ * External customer ID from your system (optional)
222
+ * Use this to link Recur subscriptions to your existing users.
223
+ * Once set during customer creation, this cannot be changed.
220
224
  *
221
225
  * @example 'user_123', 'cus_abc456'
222
226
  */
@@ -458,7 +462,6 @@ declare class RecurPaymentForm extends HTMLElement {
458
462
  getFormData(): {
459
463
  email: string;
460
464
  name: string;
461
- phone: string;
462
465
  };
463
466
  /**
464
467
  * 設置表單數據
@@ -466,7 +469,6 @@ declare class RecurPaymentForm extends HTMLElement {
466
469
  setFormData(data: {
467
470
  email?: string;
468
471
  name?: string;
469
- phone?: string;
470
472
  }): void;
471
473
  }
472
474
  declare global {
package/dist/index.d.ts CHANGED
@@ -212,11 +212,15 @@ interface CheckoutOptions {
212
212
  * Customer information
213
213
  */
214
214
  customerName?: string;
215
- customerEmail?: string;
216
- customerPhone?: string;
217
215
  /**
218
- * External customer ID from your system
219
- * Use this to link Recur subscriptions to your existing users
216
+ * Customer email address (required)
217
+ * Used as the primary identifier for the customer
218
+ */
219
+ customerEmail: string;
220
+ /**
221
+ * External customer ID from your system (optional)
222
+ * Use this to link Recur subscriptions to your existing users.
223
+ * Once set during customer creation, this cannot be changed.
220
224
  *
221
225
  * @example 'user_123', 'cus_abc456'
222
226
  */
@@ -458,7 +462,6 @@ declare class RecurPaymentForm extends HTMLElement {
458
462
  getFormData(): {
459
463
  email: string;
460
464
  name: string;
461
- phone: string;
462
465
  };
463
466
  /**
464
467
  * 設置表單數據
@@ -466,7 +469,6 @@ declare class RecurPaymentForm extends HTMLElement {
466
469
  setFormData(data: {
467
470
  email?: string;
468
471
  name?: string;
469
- phone?: string;
470
472
  }): void;
471
473
  }
472
474
  declare global {
package/dist/index.js CHANGED
@@ -1455,7 +1455,7 @@ var init_payment_form = __esm({
1455
1455
  section.className = "customer-info-section";
1456
1456
  const customerName = this.getAttribute("customer-name");
1457
1457
  const customerEmail = this.getAttribute("customer-email");
1458
- if (customerName && customerEmail) {
1458
+ if (customerEmail) {
1459
1459
  section.innerHTML = `
1460
1460
  <style>
1461
1461
  .recur-info-display {
@@ -1491,10 +1491,12 @@ var init_payment_form = __esm({
1491
1491
  </style>
1492
1492
 
1493
1493
  <div class="recur-info-display">
1494
- <div class="recur-info-row">
1495
- <span class="recur-info-label">\u5BA2\u6236\u59D3\u540D\uFF1A</span>
1496
- <span class="recur-info-value">${customerName}</span>
1497
- </div>
1494
+ ${customerName ? `
1495
+ <div class="recur-info-row">
1496
+ <span class="recur-info-label">\u5BA2\u6236\u59D3\u540D\uFF1A</span>
1497
+ <span class="recur-info-value">${customerName}</span>
1498
+ </div>
1499
+ ` : ""}
1498
1500
  <div class="recur-info-row">
1499
1501
  <span class="recur-info-label">\u96FB\u5B50\u90F5\u4EF6\uFF1A</span>
1500
1502
  <span class="recur-info-value">${customerEmail}</span>
@@ -1557,17 +1559,7 @@ var init_payment_form = __esm({
1557
1559
  id="${this.containerId}-name"
1558
1560
  class="recur-form-input"
1559
1561
  placeholder="\u738B\u5C0F\u660E"
1560
- required
1561
- />
1562
- </div>
1563
-
1564
- <div class="recur-form-group">
1565
- <label class="recur-form-label" for="${this.containerId}-phone">\u96FB\u8A71</label>
1566
- <input
1567
- type="tel"
1568
- id="${this.containerId}-phone"
1569
- class="recur-form-input"
1570
- placeholder="+886 912345678"
1562
+ value="${customerName || ""}"
1571
1563
  required
1572
1564
  />
1573
1565
  </div>
@@ -1844,14 +1836,11 @@ var init_payment_form = __esm({
1844
1836
  }
1845
1837
  let email;
1846
1838
  let name;
1847
- let phone;
1848
1839
  const emailInput = document.getElementById(`${this.containerId}-email`);
1849
1840
  const nameInput = document.getElementById(`${this.containerId}-name`);
1850
- const phoneInput = document.getElementById(`${this.containerId}-phone`);
1851
1841
  if (emailInput && nameInput) {
1852
1842
  email = emailInput.value;
1853
1843
  name = nameInput.value;
1854
- phone = phoneInput?.value;
1855
1844
  if (!email || !name) {
1856
1845
  this.showError("\u8ACB\u586B\u5BEB\u59D3\u540D\u548C\u96FB\u5B50\u90F5\u4EF6");
1857
1846
  return;
@@ -1870,7 +1859,6 @@ var init_payment_form = __esm({
1870
1859
  detail: {
1871
1860
  customerEmail: email,
1872
1861
  customerName: name,
1873
- customerPhone: phone,
1874
1862
  paymentSession: this._paymentSession
1875
1863
  },
1876
1864
  bubbles: true,
@@ -1955,8 +1943,7 @@ var init_payment_form = __esm({
1955
1943
  getFormData() {
1956
1944
  return {
1957
1945
  email: document.getElementById(`${this.containerId}-email`)?.value,
1958
- name: document.getElementById(`${this.containerId}-name`)?.value,
1959
- phone: document.getElementById(`${this.containerId}-phone`)?.value
1946
+ name: document.getElementById(`${this.containerId}-name`)?.value
1960
1947
  };
1961
1948
  }
1962
1949
  /**
@@ -1971,10 +1958,6 @@ var init_payment_form = __esm({
1971
1958
  const nameInput = document.getElementById(`${this.containerId}-name`);
1972
1959
  if (nameInput) nameInput.value = data.name;
1973
1960
  }
1974
- if (data.phone) {
1975
- const phoneInput = document.getElementById(`${this.containerId}-phone`);
1976
- if (phoneInput) phoneInput.value = data.phone;
1977
- }
1978
1961
  }
1979
1962
  };
1980
1963
  if (!customElements.get("recur-payment-form")) {
@@ -2352,8 +2335,8 @@ function RecurProvider({ children, config: initialConfig = {} }) {
2352
2335
  if (!options.customerName) {
2353
2336
  throw new Error("customerName is required");
2354
2337
  }
2355
- if (!options.customerEmail && !options.externalCustomerId) {
2356
- throw new Error("Either customerEmail or externalCustomerId is required for customer identification");
2338
+ if (!options.customerEmail) {
2339
+ throw new Error("customerEmail is required");
2357
2340
  }
2358
2341
  const baseUrl = config.baseUrl || "https://api.recur.tw";
2359
2342
  console.log("[Recur SDK] Base URL:", baseUrl);
@@ -2477,7 +2460,6 @@ function RecurProvider({ children, config: initialConfig = {} }) {
2477
2460
  productId: options.planId,
2478
2461
  customerName: options.customerName,
2479
2462
  customerEmail: options.customerEmail,
2480
- customerPhone: options.customerPhone,
2481
2463
  externalCustomerId: options.externalCustomerId
2482
2464
  })
2483
2465
  });
package/dist/recur.umd.js CHANGED
@@ -1,4 +1,4 @@
1
- "use strict";var RecurCheckout=(()=>{var C=Object.defineProperty;var ce=Object.getOwnPropertyDescriptor;var le=Object.getOwnPropertyNames;var de=Object.prototype.hasOwnProperty;var ue=(c,e,t)=>e in c?C(c,e,{enumerable:!0,configurable:!0,writable:!0,value:t}):c[e]=t;var g=(c,e)=>()=>(c&&(e=c(c=0)),e);var h=(c,e)=>{for(var t in e)C(c,t,{get:e[t],enumerable:!0})},me=(c,e,t,r)=>{if(e&&typeof e=="object"||typeof e=="function")for(let i of le(e))!de.call(c,i)&&i!==t&&C(c,i,{get:()=>e[i],enumerable:!(r=ce(e,i))||r.enumerable});return c};var pe=c=>me(C({},"__esModule",{value:!0}),c);var a=(c,e,t)=>ue(c,typeof e!="symbol"?e+"":e,t);var B={};h(B,{RecurLoadingSpinner:()=>S});var S,N=g(()=>{"use strict";S=class extends HTMLElement{static get observedAttributes(){return["message","size"]}constructor(){super(),this.attachShadow({mode:"open"})}connectedCallback(){this.render()}attributeChangedCallback(e,t,r){t!==r&&this.render()}get message(){return this.getAttribute("message")||"\u6B63\u5728\u8655\u7406\u8A02\u95B1..."}get size(){let e=this.getAttribute("size");return e==="small"||e==="large"?e:"medium"}getSizeValue(){return{small:24,medium:40,large:56}[this.size]}render(){let e=this.getSizeValue();this.shadowRoot.innerHTML=`
1
+ "use strict";var RecurCheckout=(()=>{var C=Object.defineProperty;var ce=Object.getOwnPropertyDescriptor;var le=Object.getOwnPropertyNames;var de=Object.prototype.hasOwnProperty;var ue=(c,e,t)=>e in c?C(c,e,{enumerable:!0,configurable:!0,writable:!0,value:t}):c[e]=t;var g=(c,e)=>()=>(c&&(e=c(c=0)),e);var h=(c,e)=>{for(var t in e)C(c,t,{get:e[t],enumerable:!0})},me=(c,e,t,r)=>{if(e&&typeof e=="object"||typeof e=="function")for(let i of le(e))!de.call(c,i)&&i!==t&&C(c,i,{get:()=>e[i],enumerable:!(r=ce(e,i))||r.enumerable});return c};var pe=c=>me(C({},"__esModule",{value:!0}),c);var a=(c,e,t)=>ue(c,typeof e!="symbol"?e+"":e,t);var N={};h(N,{RecurLoadingSpinner:()=>S});var S,B=g(()=>{"use strict";S=class extends HTMLElement{static get observedAttributes(){return["message","size"]}constructor(){super(),this.attachShadow({mode:"open"})}connectedCallback(){this.render()}attributeChangedCallback(e,t,r){t!==r&&this.render()}get message(){return this.getAttribute("message")||"\u6B63\u5728\u8655\u7406\u8A02\u95B1..."}get size(){let e=this.getAttribute("size");return e==="small"||e==="large"?e:"medium"}getSizeValue(){return{small:24,medium:40,large:56}[this.size]}render(){let e=this.getSizeValue();this.shadowRoot.innerHTML=`
2
2
  <style>
3
3
  :host {
4
4
  display: block;
@@ -40,7 +40,7 @@
40
40
 
41
41
  <div class="recur-sdk__spinner"></div>
42
42
  ${this.message?`<p class="recur-sdk__loading-text">${this.message}</p>`:""}
43
- `}};typeof window<"u"&&!customElements.get("recur-loading-spinner")&&customElements.define("recur-loading-spinner",S)});var K={};h(K,{RecurSuccessMessage:()=>I});var I,O=g(()=>{"use strict";I=class extends HTMLElement{static get observedAttributes(){return["title","message","icon"]}constructor(){super(),this.attachShadow({mode:"open"})}connectedCallback(){this.render()}attributeChangedCallback(e,t,r){t!==r&&this.render()}get successTitle(){return this.getAttribute("title")||"Subscription Complete!"}get successMessage(){return this.getAttribute("message")||"Thank you for subscribing. Your payment has been processed successfully."}get showIcon(){return this.getAttribute("icon")!=="false"}render(){this.shadowRoot.innerHTML=`
43
+ `}};typeof window<"u"&&!customElements.get("recur-loading-spinner")&&customElements.define("recur-loading-spinner",S)});var K={};h(K,{RecurSuccessMessage:()=>T});var T,O=g(()=>{"use strict";T=class extends HTMLElement{static get observedAttributes(){return["title","message","icon"]}constructor(){super(),this.attachShadow({mode:"open"})}connectedCallback(){this.render()}attributeChangedCallback(e,t,r){t!==r&&this.render()}get successTitle(){return this.getAttribute("title")||"Subscription Complete!"}get successMessage(){return this.getAttribute("message")||"Thank you for subscribing. Your payment has been processed successfully."}get showIcon(){return this.getAttribute("icon")!=="false"}render(){this.shadowRoot.innerHTML=`
44
44
  <style>
45
45
  :host {
46
46
  display: block;
@@ -121,7 +121,7 @@
121
121
  <p class="recur-sdk__success-message">${this.successMessage}</p>
122
122
  <slot></slot>
123
123
  </div>
124
- `}};typeof window<"u"&&!customElements.get("recur-success-message")&&customElements.define("recur-success-message",I)});var F={};h(F,{RecurErrorDisplay:()=>T});var T,j=g(()=>{"use strict";T=class extends HTMLElement{static get observedAttributes(){return["error","dismissible"]}constructor(){super(),this.attachShadow({mode:"open"})}connectedCallback(){this.render()}attributeChangedCallback(e,t,r){t!==r&&this.render()}get error(){return this.getAttribute("error")||""}get isDismissible(){return this.getAttribute("dismissible")==="true"}handleDismiss(){this.dispatchEvent(new CustomEvent("dismiss",{bubbles:!0,composed:!0})),this.remove()}render(){if(!this.error){this.shadowRoot.innerHTML="";return}this.shadowRoot.innerHTML=`
124
+ `}};typeof window<"u"&&!customElements.get("recur-success-message")&&customElements.define("recur-success-message",T)});var F={};h(F,{RecurErrorDisplay:()=>I});var I,j=g(()=>{"use strict";I=class extends HTMLElement{static get observedAttributes(){return["error","dismissible"]}constructor(){super(),this.attachShadow({mode:"open"})}connectedCallback(){this.render()}attributeChangedCallback(e,t,r){t!==r&&this.render()}get error(){return this.getAttribute("error")||""}get isDismissible(){return this.getAttribute("dismissible")==="true"}handleDismiss(){this.dispatchEvent(new CustomEvent("dismiss",{bubbles:!0,composed:!0})),this.remove()}render(){if(!this.error){this.shadowRoot.innerHTML="";return}this.shadowRoot.innerHTML=`
125
125
  <style>
126
126
  :host {
127
127
  display: block;
@@ -211,7 +211,7 @@
211
211
  </button>
212
212
  `:""}
213
213
  </div>
214
- `,this.isDismissible&&this.shadowRoot.querySelector(".recur-sdk__error-dismiss")?.addEventListener("click",()=>this.handleDismiss())}};typeof window<"u"&&!customElements.get("recur-error-display")&&customElements.define("recur-error-display",T)});var Y={};h(Y,{RecurSkeletonLoader:()=>R});var R,q=g(()=>{"use strict";R=class extends HTMLElement{static get observedAttributes(){return["type"]}constructor(){super(),this.attachShadow({mode:"open"})}connectedCallback(){this.render()}attributeChangedCallback(e,t,r){t!==r&&this.render()}get type(){let e=this.getAttribute("type");return e==="list"||e==="card"?e:"payment-form"}renderPaymentFormSkeleton(){return`
214
+ `,this.isDismissible&&this.shadowRoot.querySelector(".recur-sdk__error-dismiss")?.addEventListener("click",()=>this.handleDismiss())}};typeof window<"u"&&!customElements.get("recur-error-display")&&customElements.define("recur-error-display",I)});var Y={};h(Y,{RecurSkeletonLoader:()=>R});var R,q=g(()=>{"use strict";R=class extends HTMLElement{static get observedAttributes(){return["type"]}constructor(){super(),this.attachShadow({mode:"open"})}connectedCallback(){this.render()}attributeChangedCallback(e,t,r){t!==r&&this.render()}get type(){let e=this.getAttribute("type");return e==="list"||e==="card"?e:"payment-form"}renderPaymentFormSkeleton(){return`
215
215
  <div class="skeleton-field">
216
216
  <div class="skeleton-label"></div>
217
217
  <div class="skeleton-input"></div>
@@ -377,7 +377,7 @@
377
377
  </style>
378
378
 
379
379
  ${e}
380
- `}};typeof window<"u"&&!customElements.get("recur-skeleton-loader")&&customElements.define("recur-skeleton-loader",R)});var V={};h(V,{RecurPaymentFormSkeleton:()=>P});var P,X=g(()=>{"use strict";P=class extends HTMLElement{constructor(){super(),this.attachShadow({mode:"open"})}connectedCallback(){this.render()}render(){this.shadowRoot.innerHTML=`
380
+ `}};typeof window<"u"&&!customElements.get("recur-skeleton-loader")&&customElements.define("recur-skeleton-loader",R)});var V={};h(V,{RecurPaymentFormSkeleton:()=>M});var M,X=g(()=>{"use strict";M=class extends HTMLElement{constructor(){super(),this.attachShadow({mode:"open"})}connectedCallback(){this.render()}render(){this.shadowRoot.innerHTML=`
381
381
  <style>
382
382
  :host {
383
383
  display: block;
@@ -644,7 +644,7 @@
644
644
  <p class="security-text">\u60A8\u7684\u4ED8\u6B3E\u8CC7\u8A0A\u7D93\u904E\u52A0\u5BC6\u4FDD\u8B77</p>
645
645
  </div>
646
646
  </div>
647
- `}};typeof window<"u"&&!customElements.get("recur-payment-form-skeleton")&&customElements.define("recur-payment-form-skeleton",P)});var W={};h(W,{RecurToast:()=>M,RecurToastContainer:()=>k});var M,f,k,J=g(()=>{"use strict";M=class extends HTMLElement{static get observedAttributes(){return["message","type","duration"]}constructor(){super(),this.attachShadow({mode:"open"})}connectedCallback(){this.render(),this.setupAutoDismiss()}get message(){return this.getAttribute("message")||"Notification"}get type(){let e=this.getAttribute("type");return e==="success"||e==="error"?e:"info"}get duration(){let e=this.getAttribute("duration");return e?parseInt(e,10):5e3}setupAutoDismiss(){let e=this.duration;e>0&&setTimeout(()=>this.dismiss(),e)}dismiss(){this.style.animation="recur-toast-slide-out 0.3s ease-in-out",setTimeout(()=>this.remove(),300)}getTypeIcon(){switch(this.type){case"success":return`<svg width="20" height="20" fill="none" stroke="currentColor" viewBox="0 0 24 24">
647
+ `}};typeof window<"u"&&!customElements.get("recur-payment-form-skeleton")&&customElements.define("recur-payment-form-skeleton",M)});var W={};h(W,{RecurToast:()=>P,RecurToastContainer:()=>k});var P,f,k,J=g(()=>{"use strict";P=class extends HTMLElement{static get observedAttributes(){return["message","type","duration"]}constructor(){super(),this.attachShadow({mode:"open"})}connectedCallback(){this.render(),this.setupAutoDismiss()}get message(){return this.getAttribute("message")||"Notification"}get type(){let e=this.getAttribute("type");return e==="success"||e==="error"?e:"info"}get duration(){let e=this.getAttribute("duration");return e?parseInt(e,10):5e3}setupAutoDismiss(){let e=this.duration;e>0&&setTimeout(()=>this.dismiss(),e)}dismiss(){this.style.animation="recur-toast-slide-out 0.3s ease-in-out",setTimeout(()=>this.remove(),300)}getTypeIcon(){switch(this.type){case"success":return`<svg width="20" height="20" fill="none" stroke="currentColor" viewBox="0 0 24 24">
648
648
  <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M5 13l4 4L19 7" />
649
649
  </svg>`;case"error":return`<svg width="20" height="20" fill="none" stroke="currentColor" viewBox="0 0 24 24">
650
650
  <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M6 18L18 6M6 6l12 12" />
@@ -791,7 +791,7 @@
791
791
  </style>
792
792
 
793
793
  <slot></slot>
794
- `}static getInstance(){return f.instance||(f.instance=document.querySelector("recur-toast-container"),f.instance||(f.instance=document.createElement("recur-toast-container"),document.body.appendChild(f.instance))),f.instance}};a(f,"instance",null);k=f;typeof window<"u"&&!customElements.get("recur-toast")&&customElements.define("recur-toast",M);typeof window<"u"&&!customElements.get("recur-toast-container")&&customElements.define("recur-toast-container",k)});var Z={};h(Z,{RecurPaymentForm:()=>L});var L,G=g(()=>{"use strict";L=class extends HTMLElement{constructor(){super();a(this,"containerId");a(this,"customStyles");a(this,"_isInitializing",!1);a(this,"_initializationAborted",!1);this.containerId=this.getAttribute("container-id")||`recur-${Date.now()}`,this.customStyles=this.getAttribute("custom-styles")||"",this.attachShadow({mode:"open"})}connectedCallback(){this.render()}disconnectedCallback(){console.log("[PaymentForm] Component disconnected, cleaning up..."),this._initializationAborted=!0,this._paymentSession=null;let t=document.getElementById(`${this.containerId}-submit-btn`);if(t){let r=t.cloneNode(!0);t.parentNode?.replaceChild(r,t)}}static get observedAttributes(){return["custom-styles","customer-name","customer-email","plan-name","amount","billing-period"]}attributeChangedCallback(t,r,i){t==="custom-styles"&&r!==i?(this.customStyles=i||"",this.updateCustomStyles()):r!==i&&this.updateCustomerInfoSection()}render(){this.shadowRoot.innerHTML=`
794
+ `}static getInstance(){return f.instance||(f.instance=document.querySelector("recur-toast-container"),f.instance||(f.instance=document.createElement("recur-toast-container"),document.body.appendChild(f.instance))),f.instance}};a(f,"instance",null);k=f;typeof window<"u"&&!customElements.get("recur-toast")&&customElements.define("recur-toast",P);typeof window<"u"&&!customElements.get("recur-toast-container")&&customElements.define("recur-toast-container",k)});var Z={};h(Z,{RecurPaymentForm:()=>L});var L,G=g(()=>{"use strict";L=class extends HTMLElement{constructor(){super();a(this,"containerId");a(this,"customStyles");a(this,"_isInitializing",!1);a(this,"_initializationAborted",!1);this.containerId=this.getAttribute("container-id")||`recur-${Date.now()}`,this.customStyles=this.getAttribute("custom-styles")||"",this.attachShadow({mode:"open"})}connectedCallback(){this.render()}disconnectedCallback(){console.log("[PaymentForm] Component disconnected, cleaning up..."),this._initializationAborted=!0,this._paymentSession=null;let t=document.getElementById(`${this.containerId}-submit-btn`);if(t){let r=t.cloneNode(!0);t.parentNode?.replaceChild(r,t)}}static get observedAttributes(){return["custom-styles","customer-name","customer-email","plan-name","amount","billing-period"]}attributeChangedCallback(t,r,i){t==="custom-styles"&&r!==i?(this.customStyles=i||"",this.updateCustomStyles()):r!==i&&this.updateCustomerInfoSection()}render(){this.shadowRoot.innerHTML=`
795
795
  <style>
796
796
  /* \u9019\u4E9B\u6A23\u5F0F\u88AB\u9694\u96E2\u5728 Shadow DOM \u5167\uFF0C\u4E0D\u6703\u5F71\u97FF\u5916\u90E8 */
797
797
  :host {
@@ -974,7 +974,7 @@
974
974
  <span class="order-summary-label">\u7E3D\u8A08</span>
975
975
  <span class="order-summary-total">NT$ ${Number(i).toLocaleString()}</span>
976
976
  </div>
977
- `,t}createCustomerInfoSection(){let t=document.createElement("div");t.className="customer-info-section";let r=this.getAttribute("customer-name"),i=this.getAttribute("customer-email");return r&&i?t.innerHTML=`
977
+ `,t}createCustomerInfoSection(){let t=document.createElement("div");t.className="customer-info-section";let r=this.getAttribute("customer-name"),i=this.getAttribute("customer-email");return i?t.innerHTML=`
978
978
  <style>
979
979
  .recur-info-display {
980
980
  background: #f7fafc;
@@ -1009,10 +1009,12 @@
1009
1009
  </style>
1010
1010
 
1011
1011
  <div class="recur-info-display">
1012
- <div class="recur-info-row">
1013
- <span class="recur-info-label">\u5BA2\u6236\u59D3\u540D\uFF1A</span>
1014
- <span class="recur-info-value">${r}</span>
1015
- </div>
1012
+ ${r?`
1013
+ <div class="recur-info-row">
1014
+ <span class="recur-info-label">\u5BA2\u6236\u59D3\u540D\uFF1A</span>
1015
+ <span class="recur-info-value">${r}</span>
1016
+ </div>
1017
+ `:""}
1016
1018
  <div class="recur-info-row">
1017
1019
  <span class="recur-info-label">\u96FB\u5B50\u90F5\u4EF6\uFF1A</span>
1018
1020
  <span class="recur-info-value">${i}</span>
@@ -1073,17 +1075,7 @@
1073
1075
  id="${this.containerId}-name"
1074
1076
  class="recur-form-input"
1075
1077
  placeholder="\u738B\u5C0F\u660E"
1076
- required
1077
- />
1078
- </div>
1079
-
1080
- <div class="recur-form-group">
1081
- <label class="recur-form-label" for="${this.containerId}-phone">\u96FB\u8A71</label>
1082
- <input
1083
- type="tel"
1084
- id="${this.containerId}-phone"
1085
- class="recur-form-input"
1086
- placeholder="+886 912345678"
1078
+ value="${r||""}"
1087
1079
  required
1088
1080
  />
1089
1081
  </div>
@@ -1225,10 +1217,10 @@
1225
1217
  >
1226
1218
  <span id="${this.containerId}-submit-text">\u78BA\u8A8D\u4ED8\u6B3E</span>
1227
1219
  </button>
1228
- `,t}async initializePayment(t,r){if(this._initializationAborted)return console.log("[PaymentForm] Initialization aborted before start"),null;if(this._isInitializing=!0,await this.updateComplete(),this._initializationAborted)return console.log("[PaymentForm] Initialization aborted after updateComplete"),this._isInitializing=!1,null;if(!window.UniPayment)throw this._isInitializing=!1,new Error("PAYUNi SDK not loaded");try{let i=document.getElementById(`${this.containerId}-card-no`),s=document.getElementById(`${this.containerId}-card-exp`),n=document.getElementById(`${this.containerId}-card-cvc`);if(!i||!s||!n)return console.log("[PaymentForm] DOM elements not found, likely disconnected"),this._isInitializing=!1,null;if(this._initializationAborted)return console.log("[PaymentForm] Initialization aborted before createSession"),this._isInitializing=!1,null;let o=window.UniPayment.createSession(t,{env:r==="SANDBOX"?"S":"P",elements:{CardNo:`${this.containerId}-card-no`,CardExp:`${this.containerId}-card-exp`,CardCvc:`${this.containerId}-card-cvc`}});if(this._initializationAborted)return console.log("[PaymentForm] Initialization aborted before paymentSession.start()"),this._isInitializing=!1,null;try{await o.start()}catch(l){if((l?.message?.includes("1008")||l?.message?.includes("timeout")||l?.code===1008)&&this._initializationAborted)return console.log("[PaymentForm] Caught 1008 timeout error after component disconnect - ignoring"),this._isInitializing=!1,null;throw l}return this._initializationAborted?(console.log("[PaymentForm] Initialization aborted after paymentSession.start()"),this._isInitializing=!1,null):(this.hideCardSkeletons(),o.onUpdate?.(l=>{if(this._initializationAborted){console.log("[PaymentForm] Ignoring onUpdate event - component disconnected");return}console.log("[PaymentForm] PAYUNi update:",l);let d=l.status&&l.status.CardNo===!0&&l.status.CardExp===!0&&l.status.CardCvc===!0,y=document.getElementById(`${this.containerId}-submit-btn`);y&&(y.disabled=!d,console.log("[PaymentForm] Submit button disabled:",!d))}),this._initializationAborted?(console.log("[PaymentForm] Initialization aborted before saving session"),this._isInitializing=!1,null):(this._paymentSession=o,this.setupFormSubmission(),this._isInitializing=!1,o))}catch(i){throw this._isInitializing=!1,console.error("[PaymentForm] Failed to initialize payment:",i),i}}setupFormSubmission(){let t=document.getElementById(`${this.containerId}-submit-btn`);t&&t.addEventListener("click",async r=>{if(r.preventDefault(),t.classList.contains("loading"))return;let i,s,n,o=document.getElementById(`${this.containerId}-email`),l=document.getElementById(`${this.containerId}-name`),d=document.getElementById(`${this.containerId}-phone`);if(o&&l){if(i=o.value,s=l.value,n=d?.value,!i||!s){this.showError("\u8ACB\u586B\u5BEB\u59D3\u540D\u548C\u96FB\u5B50\u90F5\u4EF6");return}}else if(i=this.getAttribute("customer-email")||void 0,s=this.getAttribute("customer-name")||void 0,!i||!s){this.showError("\u5BA2\u6236\u8CC7\u8A0A\u4E0D\u5B8C\u6574");return}this.clearError(),this.setButtonLoading(!0),this.dispatchEvent(new CustomEvent("submit",{detail:{customerEmail:i,customerName:s,customerPhone:n,paymentSession:this._paymentSession},bubbles:!0,composed:!0}))})}setButtonLoading(t){let r=document.getElementById(`${this.containerId}-submit-btn`);r&&(t?(r.classList.add("loading"),r.disabled=!0,r.innerHTML=`
1220
+ `,t}async initializePayment(t,r){if(this._initializationAborted)return console.log("[PaymentForm] Initialization aborted before start"),null;if(this._isInitializing=!0,await this.updateComplete(),this._initializationAborted)return console.log("[PaymentForm] Initialization aborted after updateComplete"),this._isInitializing=!1,null;if(!window.UniPayment)throw this._isInitializing=!1,new Error("PAYUNi SDK not loaded");try{let i=document.getElementById(`${this.containerId}-card-no`),s=document.getElementById(`${this.containerId}-card-exp`),n=document.getElementById(`${this.containerId}-card-cvc`);if(!i||!s||!n)return console.log("[PaymentForm] DOM elements not found, likely disconnected"),this._isInitializing=!1,null;if(this._initializationAborted)return console.log("[PaymentForm] Initialization aborted before createSession"),this._isInitializing=!1,null;let o=window.UniPayment.createSession(t,{env:r==="SANDBOX"?"S":"P",elements:{CardNo:`${this.containerId}-card-no`,CardExp:`${this.containerId}-card-exp`,CardCvc:`${this.containerId}-card-cvc`}});if(this._initializationAborted)return console.log("[PaymentForm] Initialization aborted before paymentSession.start()"),this._isInitializing=!1,null;try{await o.start()}catch(l){if((l?.message?.includes("1008")||l?.message?.includes("timeout")||l?.code===1008)&&this._initializationAborted)return console.log("[PaymentForm] Caught 1008 timeout error after component disconnect - ignoring"),this._isInitializing=!1,null;throw l}return this._initializationAborted?(console.log("[PaymentForm] Initialization aborted after paymentSession.start()"),this._isInitializing=!1,null):(this.hideCardSkeletons(),o.onUpdate?.(l=>{if(this._initializationAborted){console.log("[PaymentForm] Ignoring onUpdate event - component disconnected");return}console.log("[PaymentForm] PAYUNi update:",l);let d=l.status&&l.status.CardNo===!0&&l.status.CardExp===!0&&l.status.CardCvc===!0,v=document.getElementById(`${this.containerId}-submit-btn`);v&&(v.disabled=!d,console.log("[PaymentForm] Submit button disabled:",!d))}),this._initializationAborted?(console.log("[PaymentForm] Initialization aborted before saving session"),this._isInitializing=!1,null):(this._paymentSession=o,this.setupFormSubmission(),this._isInitializing=!1,o))}catch(i){throw this._isInitializing=!1,console.error("[PaymentForm] Failed to initialize payment:",i),i}}setupFormSubmission(){let t=document.getElementById(`${this.containerId}-submit-btn`);t&&t.addEventListener("click",async r=>{if(r.preventDefault(),t.classList.contains("loading"))return;let i,s,n=document.getElementById(`${this.containerId}-email`),o=document.getElementById(`${this.containerId}-name`);if(n&&o){if(i=n.value,s=o.value,!i||!s){this.showError("\u8ACB\u586B\u5BEB\u59D3\u540D\u548C\u96FB\u5B50\u90F5\u4EF6");return}}else if(i=this.getAttribute("customer-email")||void 0,s=this.getAttribute("customer-name")||void 0,!i||!s){this.showError("\u5BA2\u6236\u8CC7\u8A0A\u4E0D\u5B8C\u6574");return}this.clearError(),this.setButtonLoading(!0),this.dispatchEvent(new CustomEvent("submit",{detail:{customerEmail:i,customerName:s,paymentSession:this._paymentSession},bubbles:!0,composed:!0}))})}setButtonLoading(t){let r=document.getElementById(`${this.containerId}-submit-btn`);r&&(t?(r.classList.add("loading"),r.disabled=!0,r.innerHTML=`
1229
1221
  <span class="recur-loading-spinner"></span>
1230
1222
  <span>\u8655\u7406\u4E2D...</span>
1231
- `):(r.classList.remove("loading"),r.disabled=!1,r.innerHTML='<span id="'+this.containerId+'-submit-text">\u78BA\u8A8D\u4ED8\u6B3E</span>'))}resetButton(){this.setButtonLoading(!1)}showError(t){let r=this.querySelector(".recur-sdk__error-container");r||(r=document.createElement("div"),r.className="recur-sdk__error-container",r.style.cssText="margin-bottom: 16px;",this.insertBefore(r,this.firstChild));let i=document.createElement("recur-error-display");i.setAttribute("error",t),i.setAttribute("dismissible","true"),r.innerHTML="",r.appendChild(i),i.scrollIntoView({behavior:"smooth",block:"center"})}clearError(){let t=this.querySelector(".recur-sdk__error-container");t&&(t.innerHTML="")}updateComplete(){return new Promise(t=>{if(this.isConnected)setTimeout(t,0);else{let r=new MutationObserver(()=>{this.isConnected&&(r.disconnect(),setTimeout(t,0))});r.observe(document.body,{childList:!0,subtree:!0})}})}getFormData(){return{email:document.getElementById(`${this.containerId}-email`)?.value,name:document.getElementById(`${this.containerId}-name`)?.value,phone:document.getElementById(`${this.containerId}-phone`)?.value}}setFormData(t){if(t.email){let r=document.getElementById(`${this.containerId}-email`);r&&(r.value=t.email)}if(t.name){let r=document.getElementById(`${this.containerId}-name`);r&&(r.value=t.name)}if(t.phone){let r=document.getElementById(`${this.containerId}-phone`);r&&(r.value=t.phone)}}};customElements.get("recur-payment-form")||customElements.define("recur-payment-form",L)});var Q={};h(Q,{RecurCheckoutButton:()=>U});var U,ee=g(()=>{"use strict";U=class extends HTMLElement{constructor(){super();a(this,"_isLoading",!1);a(this,"handleClick",async t=>{if(t.preventDefault(),this._isLoading||this.hasAttribute("disabled"))return;let r=this.getAttribute("publishable-key"),i=this.getAttribute("product-id"),s=this.getAttribute("success-url"),n=this.getAttribute("cancel-url");if(!r){this.dispatchError("Missing required attribute: publishable-key");return}if(!i){this.dispatchError("Missing required attribute: product-id");return}if(!s){this.dispatchError("Missing required attribute: success-url");return}if(!n){this.dispatchError("Missing required attribute: cancel-url");return}this._isLoading=!0,this.render(),this.setupEventListeners();try{let o=await this.createCheckoutSession({publishableKey:r,productId:i,successUrl:this.resolveUrl(s),cancelUrl:this.resolveUrl(n),customerEmail:this.getAttribute("customer-email")||void 0,mode:this.getAttribute("mode")});this.dispatchEvent(new CustomEvent("checkout-started",{detail:{sessionId:o.id,url:o.url},bubbles:!0,composed:!0})),window.location.href=o.url}catch(o){this._isLoading=!1,this.render(),this.setupEventListeners(),this.dispatchError(o.message||"Failed to create checkout session")}});this.attachShadow({mode:"open"})}static get observedAttributes(){return["publishable-key","product-id","success-url","cancel-url","customer-email","mode","button-text","button-style","disabled"]}connectedCallback(){this.render(),this.setupEventListeners()}disconnectedCallback(){let t=this.shadowRoot?.querySelector("button");t&&t.removeEventListener("click",this.handleClick)}attributeChangedCallback(t,r,i){r!==i&&this.render()}render(){let t=this.getAttribute("button-text")||this.textContent?.trim()||"\u8A02\u95B1",r=this.getAttribute("button-style")||"primary",i=this.hasAttribute("disabled")||this._isLoading;this.shadowRoot.innerHTML=`
1223
+ `):(r.classList.remove("loading"),r.disabled=!1,r.innerHTML='<span id="'+this.containerId+'-submit-text">\u78BA\u8A8D\u4ED8\u6B3E</span>'))}resetButton(){this.setButtonLoading(!1)}showError(t){let r=this.querySelector(".recur-sdk__error-container");r||(r=document.createElement("div"),r.className="recur-sdk__error-container",r.style.cssText="margin-bottom: 16px;",this.insertBefore(r,this.firstChild));let i=document.createElement("recur-error-display");i.setAttribute("error",t),i.setAttribute("dismissible","true"),r.innerHTML="",r.appendChild(i),i.scrollIntoView({behavior:"smooth",block:"center"})}clearError(){let t=this.querySelector(".recur-sdk__error-container");t&&(t.innerHTML="")}updateComplete(){return new Promise(t=>{if(this.isConnected)setTimeout(t,0);else{let r=new MutationObserver(()=>{this.isConnected&&(r.disconnect(),setTimeout(t,0))});r.observe(document.body,{childList:!0,subtree:!0})}})}getFormData(){return{email:document.getElementById(`${this.containerId}-email`)?.value,name:document.getElementById(`${this.containerId}-name`)?.value}}setFormData(t){if(t.email){let r=document.getElementById(`${this.containerId}-email`);r&&(r.value=t.email)}if(t.name){let r=document.getElementById(`${this.containerId}-name`);r&&(r.value=t.name)}}};customElements.get("recur-payment-form")||customElements.define("recur-payment-form",L)});var Q={};h(Q,{RecurCheckoutButton:()=>U});var U,ee=g(()=>{"use strict";U=class extends HTMLElement{constructor(){super();a(this,"_isLoading",!1);a(this,"handleClick",async t=>{if(t.preventDefault(),this._isLoading||this.hasAttribute("disabled"))return;let r=this.getAttribute("publishable-key"),i=this.getAttribute("product-id"),s=this.getAttribute("success-url"),n=this.getAttribute("cancel-url");if(!r){this.dispatchError("Missing required attribute: publishable-key");return}if(!i){this.dispatchError("Missing required attribute: product-id");return}if(!s){this.dispatchError("Missing required attribute: success-url");return}if(!n){this.dispatchError("Missing required attribute: cancel-url");return}this._isLoading=!0,this.render(),this.setupEventListeners();try{let o=await this.createCheckoutSession({publishableKey:r,productId:i,successUrl:this.resolveUrl(s),cancelUrl:this.resolveUrl(n),customerEmail:this.getAttribute("customer-email")||void 0,mode:this.getAttribute("mode")});this.dispatchEvent(new CustomEvent("checkout-started",{detail:{sessionId:o.id,url:o.url},bubbles:!0,composed:!0})),window.location.href=o.url}catch(o){this._isLoading=!1,this.render(),this.setupEventListeners(),this.dispatchError(o.message||"Failed to create checkout session")}});this.attachShadow({mode:"open"})}static get observedAttributes(){return["publishable-key","product-id","success-url","cancel-url","customer-email","mode","button-text","button-style","disabled"]}connectedCallback(){this.render(),this.setupEventListeners()}disconnectedCallback(){let t=this.shadowRoot?.querySelector("button");t&&t.removeEventListener("click",this.handleClick)}attributeChangedCallback(t,r,i){r!==i&&this.render()}render(){let t=this.getAttribute("button-text")||this.textContent?.trim()||"\u8A02\u95B1",r=this.getAttribute("button-style")||"primary",i=this.hasAttribute("disabled")||this._isLoading;this.shadowRoot.innerHTML=`
1232
1224
  <style>
1233
1225
  :host {
1234
1226
  display: inline-block;
@@ -1327,7 +1319,7 @@
1327
1319
  ${this._isLoading?'<span class="spinner"></span>':""}
1328
1320
  <span>${this._isLoading?"\u8655\u7406\u4E2D...":t}</span>
1329
1321
  </button>
1330
- `}setupEventListeners(){let t=this.shadowRoot?.querySelector("button");t&&t.addEventListener("click",this.handleClick)}async createCheckoutSession(t){let r=this.getApiBaseUrl(),i={productId:t.productId,successUrl:t.successUrl,cancelUrl:t.cancelUrl};t.mode&&(i.mode=t.mode),t.customerEmail&&(i.customerEmail=t.customerEmail);let s=await fetch(`${r}/v1/checkout/sessions`,{method:"POST",headers:{"Content-Type":"application/json","X-Recur-Publishable-Key":t.publishableKey},body:JSON.stringify(i)});if(!s.ok){let n=await s.json().catch(()=>({}));throw new Error(n.error?.message||`HTTP ${s.status}: Failed to create checkout session`)}return s.json()}getApiBaseUrl(){let t=this.getAttribute("api-base-url");if(t)return t;if(typeof window<"u"){let r=window.location.hostname;if(r==="localhost"||r.includes(".test")||r.includes(".local")||r==="127.0.0.1")return`${window.location.protocol}//${window.location.host}/api`}return"https://api.recur.tw"}resolveUrl(t){return t.startsWith("/")?`${window.location.origin}${t}`:t}dispatchError(t){console.error("[recur-checkout]",t),this.dispatchEvent(new CustomEvent("checkout-error",{detail:{message:t},bubbles:!0,composed:!0}))}};typeof window<"u"&&!customElements.get("recur-checkout")&&customElements.define("recur-checkout",U)});var ye={};h(ye,{RecurCheckout:()=>w,RecurElements:()=>v,createElements:()=>$,default:()=>ge,init:()=>ie});async function he(){if(typeof window>"u"){console.warn("[Recur SDK] Cannot register Web Components: window is not defined");return}await Promise.all([Promise.resolve().then(()=>(N(),B)),Promise.resolve().then(()=>(O(),K)),Promise.resolve().then(()=>(j(),F)),Promise.resolve().then(()=>(q(),Y)),Promise.resolve().then(()=>(X(),V)),Promise.resolve().then(()=>(J(),W)),Promise.resolve().then(()=>(G(),Z)),Promise.resolve().then(()=>(ee(),Q))]);let e=["recur-loading-spinner","recur-success-message","recur-error-display","recur-skeleton-loader","recur-payment-form-skeleton","recur-toast","recur-toast-container","recur-payment-form","recur-checkout"].filter(t=>!customElements.get(t));e.length>0&&console.warn("[Recur SDK] The following components are not registered:",e)}typeof window<"u"&&he();var z=class{constructor(e){a(this,"config");if(!e.publishableKey)throw new Error("publishableKey is required");this.config={baseUrl:"https://api.recur.tw",...e}}async createSubscription(e){let{planId:t,customerName:r,customerEmail:i,customerPhone:s}=e;if(!t)throw new Error("planId is required");let n=await fetch(`${this.config.baseUrl}/v1/subscriptions`,{method:"POST",headers:{"Content-Type":"application/json","X-Recur-Publishable-Key":this.config.publishableKey},body:JSON.stringify({planId:t,customerName:r,customerEmail:i,customerPhone:s})});if(!n.ok){let o=await n.json().catch(()=>({}));throw{code:o.error||"CHECKOUT_FAILED",message:o.message||"Failed to initiate checkout",details:o}}return await n.json()}async fetchPlans(){let e=await fetch(`${this.config.baseUrl}/v1/plans`,{method:"GET",headers:{"Content-Type":"application/json","X-Recur-Publishable-Key":this.config.publishableKey}});if(!e.ok){let t=await e.json().catch(()=>({}));throw{code:t.error||"FETCH_PLANS_FAILED",message:t.message||"Failed to fetch plans",details:t}}return await e.json()}getConfig(){return{...this.config}}};var _=class{constructor(e,t){a(this,"config");a(this,"options");a(this,"container");a(this,"checkoutId",null);a(this,"sdkToken",null);a(this,"sdkEnv","S");a(this,"payuniSDK",null);a(this,"isFormValid",!1);if(this.config=e,this.options=t,typeof t.container=="string"){let r=document.querySelector(t.container);if(!r)throw new Error(`Container not found: ${t.container}`);this.container=r}else this.container=t.container}async render(){try{await this.initCheckout(),this.renderHTML(),await this.loadPayUniSDK(),await this.initPayUniSDK(),this.setupFormSubmit()}catch(e){this.handleError(e)}}getBaseUrl(){if(this.config.baseUrl)return this.config.baseUrl;if(typeof window<"u"){let e=window.location.hostname;if(e==="localhost"||e.includes(".test")||e.includes(".local")||e==="127.0.0.1")return`${window.location.protocol}//${window.location.host}/api`}return"https://api.recur.tw"}async initCheckout(){let e=this.getBaseUrl(),t=await fetch(`${e}/v1/checkouts`,{method:"POST",headers:{"Content-Type":"application/json","X-Recur-Publishable-Key":this.config.publishableKey},body:JSON.stringify({productId:this.options.planId,customerEmail:this.options.customerEmail,customerName:this.options.customerName,customerPhone:this.options.customerPhone})});if(!t.ok){let i=await t.json().catch(()=>({}));throw new Error(i.error||"Failed to initialize checkout")}let r=await t.json();this.checkoutId=r.checkout.id,this.sdkToken=r.sdkToken,this.sdkEnv=this.config.publishableKey.startsWith("pk_test_")?"S":"P"}renderHTML(){this.container.innerHTML=`
1322
+ `}setupEventListeners(){let t=this.shadowRoot?.querySelector("button");t&&t.addEventListener("click",this.handleClick)}async createCheckoutSession(t){let r=this.getApiBaseUrl(),i={productId:t.productId,successUrl:t.successUrl,cancelUrl:t.cancelUrl};t.mode&&(i.mode=t.mode),t.customerEmail&&(i.customerEmail=t.customerEmail);let s=await fetch(`${r}/v1/checkout/sessions`,{method:"POST",headers:{"Content-Type":"application/json","X-Recur-Publishable-Key":t.publishableKey},body:JSON.stringify(i)});if(!s.ok){let n=await s.json().catch(()=>({}));throw new Error(n.error?.message||`HTTP ${s.status}: Failed to create checkout session`)}return s.json()}getApiBaseUrl(){let t=this.getAttribute("api-base-url");if(t)return t;if(typeof window<"u"){let r=window.location.hostname;if(r==="localhost"||r.includes(".test")||r.includes(".local")||r==="127.0.0.1")return`${window.location.protocol}//${window.location.host}/api`}return"https://api.recur.tw"}resolveUrl(t){return t.startsWith("/")?`${window.location.origin}${t}`:t}dispatchError(t){console.error("[recur-checkout]",t),this.dispatchEvent(new CustomEvent("checkout-error",{detail:{message:t},bubbles:!0,composed:!0}))}};typeof window<"u"&&!customElements.get("recur-checkout")&&customElements.define("recur-checkout",U)});var ye={};h(ye,{RecurCheckout:()=>w,RecurElements:()=>y,createElements:()=>$,default:()=>ge,init:()=>ie});async function he(){if(typeof window>"u"){console.warn("[Recur SDK] Cannot register Web Components: window is not defined");return}await Promise.all([Promise.resolve().then(()=>(B(),N)),Promise.resolve().then(()=>(O(),K)),Promise.resolve().then(()=>(j(),F)),Promise.resolve().then(()=>(q(),Y)),Promise.resolve().then(()=>(X(),V)),Promise.resolve().then(()=>(J(),W)),Promise.resolve().then(()=>(G(),Z)),Promise.resolve().then(()=>(ee(),Q))]);let e=["recur-loading-spinner","recur-success-message","recur-error-display","recur-skeleton-loader","recur-payment-form-skeleton","recur-toast","recur-toast-container","recur-payment-form","recur-checkout"].filter(t=>!customElements.get(t));e.length>0&&console.warn("[Recur SDK] The following components are not registered:",e)}typeof window<"u"&&he();var _=class{constructor(e){a(this,"config");if(!e.publishableKey)throw new Error("publishableKey is required");this.config={baseUrl:"https://api.recur.tw",...e}}async createSubscription(e){let{planId:t,customerName:r,customerEmail:i}=e;if(!t)throw new Error("planId is required");let s=await fetch(`${this.config.baseUrl}/v1/subscriptions`,{method:"POST",headers:{"Content-Type":"application/json","X-Recur-Publishable-Key":this.config.publishableKey},body:JSON.stringify({planId:t,customerName:r,customerEmail:i})});if(!s.ok){let n=await s.json().catch(()=>({}));throw{code:n.error||"CHECKOUT_FAILED",message:n.message||"Failed to initiate checkout",details:n}}return await s.json()}async fetchPlans(){let e=await fetch(`${this.config.baseUrl}/v1/plans`,{method:"GET",headers:{"Content-Type":"application/json","X-Recur-Publishable-Key":this.config.publishableKey}});if(!e.ok){let t=await e.json().catch(()=>({}));throw{code:t.error||"FETCH_PLANS_FAILED",message:t.message||"Failed to fetch plans",details:t}}return await e.json()}getConfig(){return{...this.config}}};var z=class{constructor(e,t){a(this,"config");a(this,"options");a(this,"container");a(this,"checkoutId",null);a(this,"sdkToken",null);a(this,"sdkEnv","S");a(this,"payuniSDK",null);a(this,"isFormValid",!1);if(this.config=e,this.options=t,typeof t.container=="string"){let r=document.querySelector(t.container);if(!r)throw new Error(`Container not found: ${t.container}`);this.container=r}else this.container=t.container}async render(){try{await this.initCheckout(),this.renderHTML(),await this.loadPayUniSDK(),await this.initPayUniSDK(),this.setupFormSubmit()}catch(e){this.handleError(e)}}getBaseUrl(){if(this.config.baseUrl)return this.config.baseUrl;if(typeof window<"u"){let e=window.location.hostname;if(e==="localhost"||e.includes(".test")||e.includes(".local")||e==="127.0.0.1")return`${window.location.protocol}//${window.location.host}/api`}return"https://api.recur.tw"}async initCheckout(){let e=this.getBaseUrl(),t=await fetch(`${e}/v1/checkouts`,{method:"POST",headers:{"Content-Type":"application/json","X-Recur-Publishable-Key":this.config.publishableKey},body:JSON.stringify({productId:this.options.planId,customerEmail:this.options.customerEmail,customerName:this.options.customerName})});if(!t.ok){let i=await t.json().catch(()=>({}));throw new Error(i.error||"Failed to initialize checkout")}let r=await t.json();this.checkoutId=r.checkout.id,this.sdkToken=r.sdkToken,this.sdkEnv=this.config.publishableKey.startsWith("pk_test_")?"S":"P"}renderHTML(){this.container.innerHTML=`
1331
1323
  <div class="recur-embedded-checkout" style="max-width: 400px; margin: 0 auto; padding: 20px; font-family: system-ui, -apple-system, sans-serif;">
1332
1324
  <div class="recur-checkout-header" style="margin-bottom: 24px;">
1333
1325
  <h2 style="margin: 0 0 8px 0; font-size: 20px; font-weight: 600; color: #111;">Subscribe</h2>
@@ -1361,18 +1353,6 @@
1361
1353
  />
1362
1354
  </div>
1363
1355
 
1364
- <div class="recur-field">
1365
- <label style="display: block; margin-bottom: 6px; font-size: 14px; font-weight: 500; color: #374151;">Phone (Optional)</label>
1366
- <input
1367
- type="tel"
1368
- id="recur-phone"
1369
- value="${this.options.customerPhone||""}"
1370
- style="width: 100%; padding: 8px 12px; border: 1px solid #d1d5db; border-radius: 6px; font-size: 14px; outline: none; transition: border-color 0.2s;"
1371
- onfocus="this.style.borderColor='#3b82f6'"
1372
- onblur="this.style.borderColor='#d1d5db'"
1373
- />
1374
- </div>
1375
-
1376
1356
  <div class="recur-divider" style="height: 1px; background: #e5e7eb; margin: 8px 0;"></div>
1377
1357
 
1378
1358
  <div class="recur-field">
@@ -1409,21 +1389,21 @@
1409
1389
  </p>
1410
1390
  </form>
1411
1391
  </div>
1412
- `}async loadPayUniSDK(){return new Promise((e,t)=>{if(window.UniPayment){e();return}let r=document.createElement("script");r.src=this.sdkEnv==="P"?"https://vendor.payuni.com.tw/sdk/uni-payment.js":"https://sandbox-vendor.payuni.com.tw/sdk/uni-payment.js",r.async=!0,r.onload=()=>e(),r.onerror=()=>t(new Error("Failed to load PAYUNi SDK")),document.head.appendChild(r)})}async initPayUniSDK(){if(!this.sdkToken)throw new Error("SDK token not initialized");let e=window.UniPayment;if(!e)throw new Error("PAYUNi SDK not loaded");let t={env:this.sdkEnv,useInst:!1,elements:{CardNo:"recur-card-number",CardExp:"recur-card-exp",CardCvc:"recur-card-cvc"},style:{color:"#111827",errorColor:"#dc2626",fontSize:"14px",fontWeight:"400",lineHeight:"24px"}};this.payuniSDK=e.createSession(this.sdkToken,t),await this.payuniSDK.start(),this.payuniSDK.onUpdate(r=>{let i=r?.status;i&&(this.isFormValid=i.CardNo===!0&&i.CardExp===!0&&i.CardCvc===!0,this.updateSubmitButton())})}updateSubmitButton(){let e=document.getElementById("recur-submit-btn");e&&(e.disabled=!this.isFormValid,e.style.opacity=this.isFormValid?"1":"0.5",e.style.cursor=this.isFormValid?"pointer":"not-allowed")}setupFormSubmit(){let e=document.getElementById("recur-checkout-form");e&&e.addEventListener("submit",async t=>{t.preventDefault(),await this.handleSubmit()})}async handleSubmit(){try{this.showLoading(!0),this.hideError();let e=document.getElementById("recur-email").value,t=document.getElementById("recur-name").value,r=document.getElementById("recur-phone").value;if(!e||!t)throw new Error("Please fill in all required fields");if(!this.checkoutId)throw new Error("Checkout session not initialized");if(!this.payuniSDK)throw new Error("Payment system not initialized");let i=await this.payuniSDK.getTradeResult();if(i.Status!=="SUCCESS")throw new Error(i.Message||"Card validation failed");let s=i.EncryptInfo||i.creditToken;if(!s)throw console.error("[Recur SDK] Missing payment token. Available fields:",Object.keys(i)),new Error("Missing payment token");let n=this.getBaseUrl(),o=await fetch(`${n}/v1/checkouts/${this.checkoutId}/pay`,{method:"POST",headers:{"Content-Type":"application/json","X-Recur-Publishable-Key":this.config.publishableKey},body:JSON.stringify({creditToken:s,timestamp:i.HashTimestamp||i.timestamp})});if(!o.ok){let y=await o.json().catch(()=>({}));throw new Error(y.error||"Failed to process payment")}let l=await o.json(),d={subscription:{id:l.subscription?.id||l.charge?.id||"",status:l.success?"active":"failed",planId:this.options.planId,planName:"",amount:l.charge?.amount||0,billingPeriod:l.subscription?.billingPeriod||"MONTHLY",trialDays:null},subscriber:{id:"",email:document.getElementById("recur-email")?.value||"",name:document.getElementById("recur-name")?.value||""},nextSteps:{getSdkToken:"",completeSubscription:""}};this.options.onSuccess&&this.options.onSuccess(d),this.showSuccess()}catch(e){this.handleError(e)}finally{this.showLoading(!1)}}showLoading(e){let t=document.getElementById("recur-submit-btn");t&&(t.disabled=e,t.textContent=e?"Processing...":"Subscribe Now")}showError(e){let t=document.getElementById("recur-error");t&&(t.textContent=e,t.style.display="block")}hideError(){let e=document.getElementById("recur-error");e&&(e.style.display="none")}showSuccess(){this.container.innerHTML="";let e=document.createElement("recur-success-message");e.setAttribute("title","Subscription Complete!"),e.setAttribute("message","Thank you for subscribing. You will receive a confirmation email shortly."),this.container.appendChild(e)}handleError(e){let t=e?.message||"An error occurred";this.showError(t);let r={code:"CHECKOUT_ERROR",message:t};this.options.onError&&this.options.onError(r)}};var v=class{constructor(e){a(this,"publishableKey");a(this,"baseUrl");a(this,"embedUrl");a(this,"iframe",null);a(this,"container",null);a(this,"sessionId",null);a(this,"timestamp",null);a(this,"creditToken",null);a(this,"cardToken",null);a(this,"cardTimestamp",null);a(this,"eventHandlers",new Map);typeof e=="string"?(this.publishableKey=e,this.baseUrl=this.getDefaultBaseUrl(),this.embedUrl=this.getDefaultEmbedUrl()):(this.publishableKey=e.publishableKey,this.baseUrl=e.baseUrl||this.getDefaultBaseUrl(),this.embedUrl=e.embedUrl||this.getDefaultEmbedUrl()),window.addEventListener("message",this.handleMessage.bind(this))}async mount(e){let t=typeof e=="string"?document.querySelector(e):e;if(!t)throw new Error(`Container not found: ${e}`);return this.container=t,this.iframe=document.createElement("iframe"),this.iframe.src=`${this.embedUrl}/elements?key=${encodeURIComponent(this.publishableKey)}`,this.iframe.style.cssText=`
1392
+ `}async loadPayUniSDK(){return new Promise((e,t)=>{if(window.UniPayment){e();return}let r=document.createElement("script");r.src=this.sdkEnv==="P"?"https://vendor.payuni.com.tw/sdk/uni-payment.js":"https://sandbox-vendor.payuni.com.tw/sdk/uni-payment.js",r.async=!0,r.onload=()=>e(),r.onerror=()=>t(new Error("Failed to load PAYUNi SDK")),document.head.appendChild(r)})}async initPayUniSDK(){if(!this.sdkToken)throw new Error("SDK token not initialized");let e=window.UniPayment;if(!e)throw new Error("PAYUNi SDK not loaded");let t={env:this.sdkEnv,useInst:!1,elements:{CardNo:"recur-card-number",CardExp:"recur-card-exp",CardCvc:"recur-card-cvc"},style:{color:"#111827",errorColor:"#dc2626",fontSize:"14px",fontWeight:"400",lineHeight:"24px"}};this.payuniSDK=e.createSession(this.sdkToken,t),await this.payuniSDK.start(),this.payuniSDK.onUpdate(r=>{let i=r?.status;i&&(this.isFormValid=i.CardNo===!0&&i.CardExp===!0&&i.CardCvc===!0,this.updateSubmitButton())})}updateSubmitButton(){let e=document.getElementById("recur-submit-btn");e&&(e.disabled=!this.isFormValid,e.style.opacity=this.isFormValid?"1":"0.5",e.style.cursor=this.isFormValid?"pointer":"not-allowed")}setupFormSubmit(){let e=document.getElementById("recur-checkout-form");e&&e.addEventListener("submit",async t=>{t.preventDefault(),await this.handleSubmit()})}async handleSubmit(){try{this.showLoading(!0),this.hideError();let e=document.getElementById("recur-email").value,t=document.getElementById("recur-name").value;if(!e||!t)throw new Error("Please fill in all required fields");if(!this.checkoutId)throw new Error("Checkout session not initialized");if(!this.payuniSDK)throw new Error("Payment system not initialized");let r=await this.payuniSDK.getTradeResult();if(r.Status!=="SUCCESS")throw new Error(r.Message||"Card validation failed");let i=r.EncryptInfo||r.creditToken;if(!i)throw console.error("[Recur SDK] Missing payment token. Available fields:",Object.keys(r)),new Error("Missing payment token");let s=this.getBaseUrl(),n=await fetch(`${s}/v1/checkouts/${this.checkoutId}/pay`,{method:"POST",headers:{"Content-Type":"application/json","X-Recur-Publishable-Key":this.config.publishableKey},body:JSON.stringify({creditToken:i,timestamp:r.HashTimestamp||r.timestamp})});if(!n.ok){let d=await n.json().catch(()=>({}));throw new Error(d.error||"Failed to process payment")}let o=await n.json(),l={subscription:{id:o.subscription?.id||o.charge?.id||"",status:o.success?"active":"failed",planId:this.options.planId,planName:"",amount:o.charge?.amount||0,billingPeriod:o.subscription?.billingPeriod||"MONTHLY",trialDays:null},subscriber:{id:"",email:document.getElementById("recur-email")?.value||"",name:document.getElementById("recur-name")?.value||""},nextSteps:{getSdkToken:"",completeSubscription:""}};this.options.onSuccess&&this.options.onSuccess(l),this.showSuccess()}catch(e){this.handleError(e)}finally{this.showLoading(!1)}}showLoading(e){let t=document.getElementById("recur-submit-btn");t&&(t.disabled=e,t.textContent=e?"Processing...":"Subscribe Now")}showError(e){let t=document.getElementById("recur-error");t&&(t.textContent=e,t.style.display="block")}hideError(){let e=document.getElementById("recur-error");e&&(e.style.display="none")}showSuccess(){this.container.innerHTML="";let e=document.createElement("recur-success-message");e.setAttribute("title","Subscription Complete!"),e.setAttribute("message","Thank you for subscribing. You will receive a confirmation email shortly."),this.container.appendChild(e)}handleError(e){let t=e?.message||"An error occurred";this.showError(t);let r={code:"CHECKOUT_ERROR",message:t};this.options.onError&&this.options.onError(r)}};var y=class{constructor(e){a(this,"publishableKey");a(this,"baseUrl");a(this,"embedUrl");a(this,"iframe",null);a(this,"container",null);a(this,"sessionId",null);a(this,"timestamp",null);a(this,"creditToken",null);a(this,"cardToken",null);a(this,"cardTimestamp",null);a(this,"eventHandlers",new Map);typeof e=="string"?(this.publishableKey=e,this.baseUrl=this.getDefaultBaseUrl(),this.embedUrl=this.getDefaultEmbedUrl()):(this.publishableKey=e.publishableKey,this.baseUrl=e.baseUrl||this.getDefaultBaseUrl(),this.embedUrl=e.embedUrl||this.getDefaultEmbedUrl()),window.addEventListener("message",this.handleMessage.bind(this))}async mount(e){let t=typeof e=="string"?document.querySelector(e):e;if(!t)throw new Error(`Container not found: ${e}`);return this.container=t,this.iframe=document.createElement("iframe"),this.iframe.src=`${this.embedUrl}/elements?key=${encodeURIComponent(this.publishableKey)}`,this.iframe.style.cssText=`
1413
1393
  width: 100%;
1414
1394
  border: none;
1415
1395
  min-height: 200px;
1416
1396
  display: block;
1417
1397
  user-select: none;
1418
1398
  transition: height 0.35s ease, opacity 0.4s ease 0.1s;
1419
- `.replace(/\s+/g," ").trim(),this.iframe.allow="payment *",this.iframe.setAttribute("title","Secure payment input frame"),this.iframe.setAttribute("role","presentation"),this.iframe.setAttribute("scrolling","no"),this.iframe.setAttribute("frameBorder","0"),this.container.innerHTML="",this.container.appendChild(this.iframe),new Promise((r,i)=>{let s=setTimeout(()=>{i(new Error("Elements initialization timeout"))},3e4),n=()=>{clearTimeout(s),this.off("ready",n),r()},o=l=>{clearTimeout(s),this.off("error",o),i(new Error(l.message||"Elements initialization failed"))};this.on("ready",n),this.on("error",o)})}on(e,t){this.eventHandlers.has(e)||this.eventHandlers.set(e,new Set),this.eventHandlers.get(e).add(t)}off(e,t){let r=this.eventHandlers.get(e);r&&r.delete(t)}emit(e,t){let r=this.eventHandlers.get(e);r&&r.forEach(i=>i(t))}handleMessage(e){if(!this.isValidOrigin(e.origin))return;let{type:t,data:r}=e.data||{};switch(t){case"RECUR_ELEMENTS_READY":this.sessionId=r.sessionId,this.timestamp=r.timestamp,this.creditToken=r.creditToken,this.emit("ready",r);break;case"RECUR_CARD_VALID":this.emit("change",{valid:r.valid});break;case"RECUR_CARD_TOKENIZED":this.cardToken=r.cardToken,this.cardTimestamp=r.timestamp,this.emit("tokenized",r);break;case"RECUR_PAYMENT_ERROR":this.emit("error",r);break;case"RECUR_RESIZE":this.iframe&&r?.height&&(this.iframe.style.height=`${r.height}px`);break}}isValidOrigin(e){try{let t=new URL(this.embedUrl).origin;return e===t}catch{return!1}}async tokenize(){if(!this.iframe||!this.iframe.contentWindow)throw new Error("Elements not mounted");let e=new URL(this.embedUrl).origin;return this.iframe.contentWindow.postMessage({type:"RECUR_TOKENIZE"},e),new Promise((t,r)=>{let i=setTimeout(()=>{r(new Error("Tokenization timeout"))},6e4),s=o=>{clearTimeout(i),this.off("tokenized",s),t(o)},n=o=>{clearTimeout(i),this.off("error",n),r(new Error(o.message||"Tokenization failed"))};this.on("tokenized",s),this.on("error",n)})}async confirmPayment(e){if(!this.sessionId||!this.cardToken)throw new Error("Card not tokenized. Call tokenize() first.");let t=await fetch(`${this.baseUrl}/api/v1/elements/confirm`,{method:"POST",headers:{"Content-Type":"application/json","X-Recur-Publishable-Key":this.publishableKey},body:JSON.stringify({sessionId:this.sessionId,sdkToken:this.cardToken,timestamp:this.cardTimestamp,creditToken:this.creditToken,productId:e.productId,email:e.email,name:e.name,phone:e.phone,metadata:e.metadata})}),r=await t.json();return t.ok?r:{status:"failed",message:r.error||r.message||"Payment failed",canRetry:r.canRetry??!0}}getDefaultBaseUrl(){if(typeof window>"u")return"https://app.recur.tw";let e=window.location.hostname;return e==="localhost"||e.includes(".test")||e.includes(".local")||e==="127.0.0.1"?`${window.location.protocol}//${e}:3000`:"https://app.recur.tw"}getDefaultEmbedUrl(){if(typeof window>"u")return"https://embed.recur.tw";let e=window.location.hostname;return e==="localhost"||e.includes(".test")||e.includes(".local")||e==="127.0.0.1"?`${window.location.protocol}//${e}:3002`:"https://embed.recur.tw"}destroy(){this.iframe&&this.iframe.parentNode&&this.iframe.parentNode.removeChild(this.iframe),this.iframe=null,this.container=null,this.sessionId=null,this.timestamp=null,this.creditToken=null,this.cardToken=null,this.cardTimestamp=null,this.eventHandlers.clear(),window.removeEventListener("message",this.handleMessage.bind(this))}};function $(c){return new v(c)}var fe="https://vendor.payuni.com.tw/sdk/uni-payment.js",be="https://sandbox-vendor.payuni.com.tw/sdk/uni-payment.js",te=!1,D=!1,x=null;async function re(c=!1){return te&&window.UniPayment?Promise.resolve():(D&&x||(D=!0,x=new Promise((e,t)=>{let r=document.createElement("script");r.src=c?be:fe,r.async=!0,r.onload=()=>{te=!0,D=!1,e()},r.onerror=()=>{D=!1,x=null,t(new Error("Failed to load PAYUNi SDK"))},document.head.appendChild(r)})),x)}var w=class{constructor(e){a(this,"core");a(this,"currentModal",null);a(this,"currentIframe",null);a(this,"currentModalOverlay",null);this.core=new z(e)}async fetchPlans(){return await this.core.fetchPlans()}async createEmbeddedCheckout(e){let t=this.core.getConfig();await new _(t,e).render()}async redirectToCheckout(e){let t=this.core.getConfig(),r=()=>{if(typeof window<"u"){let l=window.location.hostname;if(l==="localhost"||l.includes(".test")||l.includes(".local")||l==="127.0.0.1")return`${window.location.protocol}//${window.location.host}/api`}return"https://api.recur.tw"},i=t.baseUrl||r(),s={productId:e.productId,successUrl:e.successUrl,cancelUrl:e.cancelUrl};e.mode&&(s.mode=e.mode),e.customerEmail&&(s.customerEmail=e.customerEmail),e.externalCustomerId&&(s.externalCustomerId=e.externalCustomerId);let n=await fetch(`${i}/v1/checkout/sessions`,{method:"POST",headers:{"Content-Type":"application/json","X-Recur-Publishable-Key":t.publishableKey},body:JSON.stringify(s)});if(!n.ok){let l=await n.json().catch(()=>({}));throw new Error(l.error?.message||"Failed to create checkout session")}let o=await n.json();window.location.href=o.url}async createCheckoutSession(e){let t=this.core.getConfig(),r=()=>{if(typeof window<"u"){let o=window.location.hostname;if(o==="localhost"||o.includes(".test")||o.includes(".local")||o==="127.0.0.1")return`${window.location.protocol}//${window.location.host}/api`}return"https://api.recur.tw"},i=t.baseUrl||r(),s={productId:e.productId,successUrl:e.successUrl,cancelUrl:e.cancelUrl};e.mode&&(s.mode=e.mode),e.customerEmail&&(s.customerEmail=e.customerEmail),e.externalCustomerId&&(s.externalCustomerId=e.externalCustomerId);let n=await fetch(`${i}/v1/checkout/sessions`,{method:"POST",headers:{"Content-Type":"application/json","X-Recur-Publishable-Key":t.publishableKey},body:JSON.stringify(s)});if(!n.ok){let o=await n.json().catch(()=>({}));throw new Error(o.error?.message||"Failed to create checkout session")}return n.json()}async checkout(e){let t=this.core.getConfig(),r=null;try{if(console.log("[Recur SDK] Starting checkout flow...",{planId:e.planId,mode:e.mode}),!e.planId)throw new Error("planId is required");if(!t.publishableKey)throw new Error("publishableKey is required");if(!e.customerName)throw new Error("customerName is required");if(!e.customerEmail&&!e.externalCustomerId)throw new Error("Either customerEmail or externalCustomerId is required for customer identification");let i=this.getBaseUrl();console.log("[Recur SDK] Base URL:",i);let s={"Content-Type":"application/json","X-Recur-Publishable-Key":t.publishableKey},n=e.mode||"modal",o=null;if(n==="modal"){let u=this.createModalWithSkeleton(e.onClose);r=u.overlay,o=u.container}else if(n==="iframe"){if(o=this.getEmbeddedContainer(e.container),!o)throw new Error("Container is required for iframe mode");o.innerHTML="";let u=document.createElement("recur-payment-form-skeleton");o.appendChild(u)}console.log("[Recur SDK] Step 1: Creating checkout session...");let l=await fetch(`${i}/v1/checkouts`,{method:"POST",headers:s,body:JSON.stringify({productId:e.planId,customerName:e.customerName,customerEmail:e.customerEmail,customerPhone:e.customerPhone,externalCustomerId:e.externalCustomerId})});if(!l.ok){let u=await l.json().catch(()=>({}));console.error("[Recur SDK] Failed to create checkout:",u);let A=u.details||u.error||"Failed to create checkout";throw new Error(A)}let d=await l.json();if(console.log("[Recur SDK] Checkout created successfully:",d),e.onSuccess?.(d),n==="redirect"){let u=`https://checkout.recur.tw/${d.checkout.id}`;console.log("[Recur SDK] Redirecting to hosted checkout:",u),window.location.href=u;return}if(console.log("[Recur SDK] Step 2: Extracting SDK token..."),!d.sdkToken)throw new Error("SDK token missing from checkout response");console.log("[Recur SDK] Step 3: Loading PAYUNi SDK...");let y=!0;if(await re(y),console.log("[Recur SDK] PAYUNi SDK loaded successfully"),!window.UniPayment)throw new Error("PAYUNi SDK failed to load");if(console.log("[Recur SDK] Step 4: Rendering payment form..."),!o)throw new Error("Payment container not available");o.innerHTML="";let m=document.createElement("recur-payment-form");if(m.setAttribute("container-id",o.id||"recur-payment-container"),e.customerName&&m.setAttribute("customer-name",e.customerName),e.customerEmail&&m.setAttribute("customer-email",e.customerEmail),d.plan?.name&&m.setAttribute("plan-name",d.plan.name),d.checkout?.amount&&m.setAttribute("amount",d.checkout.amount.toString()),d.plan?.billingPeriod&&m.setAttribute("billing-period",d.plan.billingPeriod),m.setAttribute("custom-styles",`
1399
+ `.replace(/\s+/g," ").trim(),this.iframe.allow="payment *",this.iframe.setAttribute("title","Secure payment input frame"),this.iframe.setAttribute("role","presentation"),this.iframe.setAttribute("scrolling","no"),this.iframe.setAttribute("frameBorder","0"),this.container.innerHTML="",this.container.appendChild(this.iframe),new Promise((r,i)=>{let s=setTimeout(()=>{i(new Error("Elements initialization timeout"))},3e4),n=()=>{clearTimeout(s),this.off("ready",n),r()},o=l=>{clearTimeout(s),this.off("error",o),i(new Error(l.message||"Elements initialization failed"))};this.on("ready",n),this.on("error",o)})}on(e,t){this.eventHandlers.has(e)||this.eventHandlers.set(e,new Set),this.eventHandlers.get(e).add(t)}off(e,t){let r=this.eventHandlers.get(e);r&&r.delete(t)}emit(e,t){let r=this.eventHandlers.get(e);r&&r.forEach(i=>i(t))}handleMessage(e){if(!this.isValidOrigin(e.origin))return;let{type:t,data:r}=e.data||{};switch(t){case"RECUR_ELEMENTS_READY":this.sessionId=r.sessionId,this.timestamp=r.timestamp,this.creditToken=r.creditToken,this.emit("ready",r);break;case"RECUR_CARD_VALID":this.emit("change",{valid:r.valid});break;case"RECUR_CARD_TOKENIZED":this.cardToken=r.cardToken,this.cardTimestamp=r.timestamp,this.emit("tokenized",r);break;case"RECUR_PAYMENT_ERROR":this.emit("error",r);break;case"RECUR_RESIZE":this.iframe&&r?.height&&(this.iframe.style.height=`${r.height}px`);break}}isValidOrigin(e){try{let t=new URL(this.embedUrl).origin;return e===t}catch{return!1}}async tokenize(){if(!this.iframe||!this.iframe.contentWindow)throw new Error("Elements not mounted");let e=new URL(this.embedUrl).origin;return this.iframe.contentWindow.postMessage({type:"RECUR_TOKENIZE"},e),new Promise((t,r)=>{let i=setTimeout(()=>{r(new Error("Tokenization timeout"))},6e4),s=o=>{clearTimeout(i),this.off("tokenized",s),t(o)},n=o=>{clearTimeout(i),this.off("error",n),r(new Error(o.message||"Tokenization failed"))};this.on("tokenized",s),this.on("error",n)})}async confirmPayment(e){if(!this.sessionId||!this.cardToken)throw new Error("Card not tokenized. Call tokenize() first.");let t=await fetch(`${this.baseUrl}/api/v1/elements/confirm`,{method:"POST",headers:{"Content-Type":"application/json","X-Recur-Publishable-Key":this.publishableKey},body:JSON.stringify({sessionId:this.sessionId,sdkToken:this.cardToken,timestamp:this.cardTimestamp,creditToken:this.creditToken,productId:e.productId,email:e.email,name:e.name,metadata:e.metadata})}),r=await t.json();return t.ok?r:{status:"failed",message:r.error||r.message||"Payment failed",canRetry:r.canRetry??!0}}getDefaultBaseUrl(){if(typeof window>"u")return"https://app.recur.tw";let e=window.location.hostname;return e==="localhost"||e.includes(".test")||e.includes(".local")||e==="127.0.0.1"?`${window.location.protocol}//${e}:3000`:"https://app.recur.tw"}getDefaultEmbedUrl(){if(typeof window>"u")return"https://embed.recur.tw";let e=window.location.hostname;return e==="localhost"||e.includes(".test")||e.includes(".local")||e==="127.0.0.1"?`${window.location.protocol}//${e}:3002`:"https://embed.recur.tw"}destroy(){this.iframe&&this.iframe.parentNode&&this.iframe.parentNode.removeChild(this.iframe),this.iframe=null,this.container=null,this.sessionId=null,this.timestamp=null,this.creditToken=null,this.cardToken=null,this.cardTimestamp=null,this.eventHandlers.clear(),window.removeEventListener("message",this.handleMessage.bind(this))}};function $(c){return new y(c)}var fe="https://vendor.payuni.com.tw/sdk/uni-payment.js",be="https://sandbox-vendor.payuni.com.tw/sdk/uni-payment.js",te=!1,D=!1,x=null;async function re(c=!1){return te&&window.UniPayment?Promise.resolve():(D&&x||(D=!0,x=new Promise((e,t)=>{let r=document.createElement("script");r.src=c?be:fe,r.async=!0,r.onload=()=>{te=!0,D=!1,e()},r.onerror=()=>{D=!1,x=null,t(new Error("Failed to load PAYUNi SDK"))},document.head.appendChild(r)})),x)}var w=class{constructor(e){a(this,"core");a(this,"currentModal",null);a(this,"currentIframe",null);a(this,"currentModalOverlay",null);this.core=new _(e)}async fetchPlans(){return await this.core.fetchPlans()}async createEmbeddedCheckout(e){let t=this.core.getConfig();await new z(t,e).render()}async redirectToCheckout(e){let t=this.core.getConfig(),r=()=>{if(typeof window<"u"){let l=window.location.hostname;if(l==="localhost"||l.includes(".test")||l.includes(".local")||l==="127.0.0.1")return`${window.location.protocol}//${window.location.host}/api`}return"https://api.recur.tw"},i=t.baseUrl||r(),s={productId:e.productId,successUrl:e.successUrl,cancelUrl:e.cancelUrl};e.mode&&(s.mode=e.mode),e.customerEmail&&(s.customerEmail=e.customerEmail),e.externalCustomerId&&(s.externalCustomerId=e.externalCustomerId);let n=await fetch(`${i}/v1/checkout/sessions`,{method:"POST",headers:{"Content-Type":"application/json","X-Recur-Publishable-Key":t.publishableKey},body:JSON.stringify(s)});if(!n.ok){let l=await n.json().catch(()=>({}));throw new Error(l.error?.message||"Failed to create checkout session")}let o=await n.json();window.location.href=o.url}async createCheckoutSession(e){let t=this.core.getConfig(),r=()=>{if(typeof window<"u"){let o=window.location.hostname;if(o==="localhost"||o.includes(".test")||o.includes(".local")||o==="127.0.0.1")return`${window.location.protocol}//${window.location.host}/api`}return"https://api.recur.tw"},i=t.baseUrl||r(),s={productId:e.productId,successUrl:e.successUrl,cancelUrl:e.cancelUrl};e.mode&&(s.mode=e.mode),e.customerEmail&&(s.customerEmail=e.customerEmail),e.externalCustomerId&&(s.externalCustomerId=e.externalCustomerId);let n=await fetch(`${i}/v1/checkout/sessions`,{method:"POST",headers:{"Content-Type":"application/json","X-Recur-Publishable-Key":t.publishableKey},body:JSON.stringify(s)});if(!n.ok){let o=await n.json().catch(()=>({}));throw new Error(o.error?.message||"Failed to create checkout session")}return n.json()}async checkout(e){let t=this.core.getConfig(),r=null;try{if(console.log("[Recur SDK] Starting checkout flow...",{planId:e.planId,mode:e.mode}),!e.planId)throw new Error("planId is required");if(!t.publishableKey)throw new Error("publishableKey is required");if(!e.customerName)throw new Error("customerName is required");if(!e.customerEmail)throw new Error("customerEmail is required");let i=this.getBaseUrl();console.log("[Recur SDK] Base URL:",i);let s={"Content-Type":"application/json","X-Recur-Publishable-Key":t.publishableKey},n=e.mode||"modal",o=null;if(n==="modal"){let u=this.createModalWithSkeleton(e.onClose);r=u.overlay,o=u.container}else if(n==="iframe"){if(o=this.getEmbeddedContainer(e.container),!o)throw new Error("Container is required for iframe mode");o.innerHTML="";let u=document.createElement("recur-payment-form-skeleton");o.appendChild(u)}console.log("[Recur SDK] Step 1: Creating checkout session...");let l=await fetch(`${i}/v1/checkouts`,{method:"POST",headers:s,body:JSON.stringify({productId:e.planId,customerName:e.customerName,customerEmail:e.customerEmail,externalCustomerId:e.externalCustomerId})});if(!l.ok){let u=await l.json().catch(()=>({}));console.error("[Recur SDK] Failed to create checkout:",u);let A=u.details||u.error||"Failed to create checkout";throw new Error(A)}let d=await l.json();if(console.log("[Recur SDK] Checkout created successfully:",d),e.onSuccess?.(d),n==="redirect"){let u=`https://checkout.recur.tw/${d.checkout.id}`;console.log("[Recur SDK] Redirecting to hosted checkout:",u),window.location.href=u;return}if(console.log("[Recur SDK] Step 2: Extracting SDK token..."),!d.sdkToken)throw new Error("SDK token missing from checkout response");console.log("[Recur SDK] Step 3: Loading PAYUNi SDK...");let v=!0;if(await re(v),console.log("[Recur SDK] PAYUNi SDK loaded successfully"),!window.UniPayment)throw new Error("PAYUNi SDK failed to load");if(console.log("[Recur SDK] Step 4: Rendering payment form..."),!o)throw new Error("Payment container not available");o.innerHTML="";let m=document.createElement("recur-payment-form");if(m.setAttribute("container-id",o.id||"recur-payment-container"),e.customerName&&m.setAttribute("customer-name",e.customerName),e.customerEmail&&m.setAttribute("customer-email",e.customerEmail),d.plan?.name&&m.setAttribute("plan-name",d.plan.name),d.checkout?.amount&&m.setAttribute("amount",d.checkout.amount.toString()),d.plan?.billingPeriod&&m.setAttribute("billing-period",d.plan.billingPeriod),m.setAttribute("custom-styles",`
1420
1400
  .form-input-focus {
1421
1401
  border-color: var(--ring, hsl(215 16% 47%)) !important;
1422
1402
  outline: 0 !important;
1423
1403
  box-shadow: 0 0 0 3px color-mix(in oklch, var(--ring, hsl(215 16% 47%)) 50%, transparent) !important;
1424
1404
  transition: border-color 0.15s ease-in-out, box-shadow 0.15s ease-in-out !important;
1425
1405
  }
1426
- `),o.appendChild(m),await new Promise(u=>setTimeout(u,100)),console.log("[Recur SDK] Step 5: Initializing PAYUNi SDK..."),await m.initializePayment(d.sdkToken,y?"SANDBOX":"PRODUCTION")===null){console.log("[Recur SDK] Initialization aborted");return}console.log("[Recur SDK] PAYUNi SDK initialized successfully"),console.log("[Recur SDK] Step 6: Setting up submit handler..."),m.addEventListener("submit",(async u=>{console.log("[Recur SDK] Form submitted");let A=u,{paymentSession:se}=A.detail;try{let b=await se.getTradeResult();console.log("[Recur SDK] Trade result received"),console.log("[Recur SDK] Executing payment...");let E=b.EncryptInfo||b.creditToken,oe=b.HashTimestamp||b.timestamp;if(!E)throw new Error("Missing payment token from PAYUNi SDK");let ne=d.checkout.productType==="SUBSCRIPTION"?{creditToken:E,timestamp:oe}:{},H=await fetch(`${i}/v1/checkouts/${d.checkout.id}/pay`,{method:"POST",headers:s,body:JSON.stringify(ne)});if(!H.ok){let ae=await H.json().catch(()=>({}));throw new Error(ae.error||"Failed to execute payment")}let p=await H.json();if(console.log("[Recur SDK] Payment executed:",p),p.requires3D&&p.redirectUrl){console.log("[Recur SDK] 3D verification required"),window.location.href=p.redirectUrl;return}e.onPaymentComplete&&(p.subscription?e.onPaymentComplete({id:p.subscription.id,status:p.subscription.status,planId:d.checkout.productId,amount:d.checkout.amount,billingPeriod:p.subscription.billingPeriod,currentPeriodStart:p.subscription.currentPeriodStart,currentPeriodEnd:p.subscription.currentPeriodEnd}):e.onPaymentComplete({id:p.checkout.id,status:p.checkout.status,planId:d.checkout.productId,amount:d.checkout.amount,billingPeriod:d.checkout.productType})),console.log("[Recur SDK] Checkout flow completed successfully!"),m.resetButton?.(),r&&r.remove()}catch(b){console.error("[Recur SDK] Payment error:",b);let E={code:"PAYMENT_FAILED",message:b instanceof Error?b.message:"Payment failed"};e.onError?.(E),m.resetButton?.()}})),console.log("[Recur SDK] Checkout flow initialized, waiting for user input...")}catch(i){console.error("[Recur SDK] Checkout error:",i),r&&r.remove();let s={code:"CHECKOUT_ERROR",message:i instanceof Error?i.message:"An unknown error occurred"};throw e.onError?.(s),i}}getBaseUrl(){let e=this.core.getConfig();if(e.baseUrl)return e.baseUrl;if(typeof window<"u"){let t=window.location.hostname;if(t==="localhost"||t.includes(".test")||t.includes(".local")||t==="127.0.0.1")return`${window.location.protocol}//${window.location.host}/api`}return"https://api.recur.tw"}createModalWithSkeleton(e){this.closeModal();let t=document.createElement("div");t.id="recur-modal-overlay",t.style.cssText=`
1406
+ `),o.appendChild(m),await new Promise(u=>setTimeout(u,100)),console.log("[Recur SDK] Step 5: Initializing PAYUNi SDK..."),await m.initializePayment(d.sdkToken,v?"SANDBOX":"PRODUCTION")===null){console.log("[Recur SDK] Initialization aborted");return}console.log("[Recur SDK] PAYUNi SDK initialized successfully"),console.log("[Recur SDK] Step 6: Setting up submit handler..."),m.addEventListener("submit",(async u=>{console.log("[Recur SDK] Form submitted");let A=u,{paymentSession:se}=A.detail;try{let b=await se.getTradeResult();console.log("[Recur SDK] Trade result received"),console.log("[Recur SDK] Executing payment...");let E=b.EncryptInfo||b.creditToken,oe=b.HashTimestamp||b.timestamp;if(!E)throw new Error("Missing payment token from PAYUNi SDK");let ne=d.checkout.productType==="SUBSCRIPTION"?{creditToken:E,timestamp:oe}:{},H=await fetch(`${i}/v1/checkouts/${d.checkout.id}/pay`,{method:"POST",headers:s,body:JSON.stringify(ne)});if(!H.ok){let ae=await H.json().catch(()=>({}));throw new Error(ae.error||"Failed to execute payment")}let p=await H.json();if(console.log("[Recur SDK] Payment executed:",p),p.requires3D&&p.redirectUrl){console.log("[Recur SDK] 3D verification required"),window.location.href=p.redirectUrl;return}e.onPaymentComplete&&(p.subscription?e.onPaymentComplete({id:p.subscription.id,status:p.subscription.status,planId:d.checkout.productId,amount:d.checkout.amount,billingPeriod:p.subscription.billingPeriod,currentPeriodStart:p.subscription.currentPeriodStart,currentPeriodEnd:p.subscription.currentPeriodEnd}):e.onPaymentComplete({id:p.checkout.id,status:p.checkout.status,planId:d.checkout.productId,amount:d.checkout.amount,billingPeriod:d.checkout.productType})),console.log("[Recur SDK] Checkout flow completed successfully!"),m.resetButton?.(),r&&r.remove()}catch(b){console.error("[Recur SDK] Payment error:",b);let E={code:"PAYMENT_FAILED",message:b instanceof Error?b.message:"Payment failed"};e.onError?.(E),m.resetButton?.()}})),console.log("[Recur SDK] Checkout flow initialized, waiting for user input...")}catch(i){console.error("[Recur SDK] Checkout error:",i),r&&r.remove();let s={code:"CHECKOUT_ERROR",message:i instanceof Error?i.message:"An unknown error occurred"};throw e.onError?.(s),i}}getBaseUrl(){let e=this.core.getConfig();if(e.baseUrl)return e.baseUrl;if(typeof window<"u"){let t=window.location.hostname;if(t==="localhost"||t.includes(".test")||t.includes(".local")||t==="127.0.0.1")return`${window.location.protocol}//${window.location.host}/api`}return"https://api.recur.tw"}createModalWithSkeleton(e){this.closeModal();let t=document.createElement("div");t.id="recur-modal-overlay",t.style.cssText=`
1427
1407
  position: fixed;
1428
1408
  top: 0;
1429
1409
  left: 0;
@@ -1462,7 +1442,7 @@
1462
1442
  background: white;
1463
1443
  border-radius: 12px;
1464
1444
  box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
1465
- `;let n=document.createElement("recur-payment-form-skeleton");return s.appendChild(n),r.appendChild(i),r.appendChild(s),t.appendChild(r),document.body.appendChild(t),this.currentModalOverlay=t,{overlay:t,container:s}}getEmbeddedContainer(e){return e?typeof e=="string"?document.getElementById(e)||document.querySelector(e):e:null}closeModal(){this.currentModal&&(this.currentModal.close(),this.currentModal=null),this.currentModalOverlay&&(this.currentModalOverlay.remove(),this.currentModalOverlay=null)}removeIframe(){this.currentIframe&&(this.currentIframe.remove(),this.currentIframe=null)}close(){this.closeModal(),this.removeIframe()}};function ie(c){return new w(c)}var ge={init:ie,RecurCheckout:w,RecurElements:v,createElements:$};return pe(ye);})();
1445
+ `;let n=document.createElement("recur-payment-form-skeleton");return s.appendChild(n),r.appendChild(i),r.appendChild(s),t.appendChild(r),document.body.appendChild(t),this.currentModalOverlay=t,{overlay:t,container:s}}getEmbeddedContainer(e){return e?typeof e=="string"?document.getElementById(e)||document.querySelector(e):e:null}closeModal(){this.currentModal&&(this.currentModal.close(),this.currentModal=null),this.currentModalOverlay&&(this.currentModalOverlay.remove(),this.currentModalOverlay=null)}removeIframe(){this.currentIframe&&(this.currentIframe.remove(),this.currentIframe=null)}close(){this.closeModal(),this.removeIframe()}};function ie(c){return new w(c)}var ge={init:ie,RecurCheckout:w,RecurElements:y,createElements:$};return pe(ye);})();
1466
1446
  if (typeof window !== "undefined") {
1467
1447
  window.RecurCheckout = RecurCheckout.default;
1468
1448
  window.RecurElements = RecurCheckout.RecurElements;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "recur-tw",
3
- "version": "0.4.1",
3
+ "version": "0.4.4",
4
4
  "description": "React & Vanilla JS SDK for embedding subscription checkout flows (Taiwan / PAYUNi)",
5
5
  "type": "module",
6
6
  "private": false,