recur-tw 0.7.6 → 0.8.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (2) hide show
  1. package/dist/recur.umd.js +13 -13
  2. package/package.json +1 -1
package/dist/recur.umd.js CHANGED
@@ -1,4 +1,4 @@
1
- "use strict";var RecurCheckout=(()=>{var I=Object.defineProperty;var be=Object.getOwnPropertyDescriptor;var ge=Object.getOwnPropertyNames;var ye=Object.prototype.hasOwnProperty;var ve=(n,e,t)=>e in n?I(n,e,{enumerable:!0,configurable:!0,writable:!0,value:t}):n[e]=t;var g=(n,e)=>()=>(n&&(e=n(n=0)),e);var f=(n,e)=>{for(var t in e)I(n,t,{get:e[t],enumerable:!0})},ke=(n,e,t,r)=>{if(e&&typeof e=="object"||typeof e=="function")for(let i of ge(e))!ye.call(n,i)&&i!==t&&I(n,i,{get:()=>e[i],enumerable:!(r=be(e,i))||r.enumerable});return n};var we=n=>ke(I({},"__esModule",{value:!0}),n);var c=(n,e,t)=>ve(n,typeof e!="symbol"?e+"":e,t);var V={};f(V,{RecurLoadingSpinner:()=>R});var R,X=g(()=>{"use strict";R=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 I=Object.defineProperty;var be=Object.getOwnPropertyDescriptor;var ge=Object.getOwnPropertyNames;var ye=Object.prototype.hasOwnProperty;var ve=(o,e,t)=>e in o?I(o,e,{enumerable:!0,configurable:!0,writable:!0,value:t}):o[e]=t;var g=(o,e)=>()=>(o&&(e=o(o=0)),e);var f=(o,e)=>{for(var t in e)I(o,t,{get:e[t],enumerable:!0})},ke=(o,e,t,r)=>{if(e&&typeof e=="object"||typeof e=="function")for(let i of ge(e))!ye.call(o,i)&&i!==t&&I(o,i,{get:()=>e[i],enumerable:!(r=be(e,i))||r.enumerable});return o};var xe=o=>ke(I({},"__esModule",{value:!0}),o);var c=(o,e,t)=>ve(o,typeof e!="symbol"?e+"":e,t);var V={};f(V,{RecurLoadingSpinner:()=>R});var R,X=g(()=>{"use strict";R=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;
@@ -899,7 +899,7 @@
899
899
  height: 36px !important;
900
900
  }
901
901
  `;t.textContent=this.customStyles+`
902
- `+r,this.appendChild(t);let i=this.createOrderSummarySection();i.slot="order-summary",this.appendChild(i);let s=this.createCustomerInfoSection();s.slot="customer-info",this.appendChild(s);let o=this.createCardFieldsSection();o.slot="card-fields",this.appendChild(o);let a=this.createActionsSection();a.slot="actions",this.appendChild(a)}updateCustomerInfoSection(){let t=this.querySelector('[slot="customer-info"]');if(t){let r=this.createCustomerInfoSection();r.slot="customer-info",t.replaceWith(r)}}updateCustomStyles(){let t=this.querySelector(`#${this.containerId}-custom-styles`);if(t){let r=`
902
+ `+r,this.appendChild(t);let i=this.createOrderSummarySection();i.slot="order-summary",this.appendChild(i);let s=this.createCustomerInfoSection();s.slot="customer-info",this.appendChild(s);let a=this.createCardFieldsSection();a.slot="card-fields",this.appendChild(a);let n=this.createActionsSection();n.slot="actions",this.appendChild(n)}updateCustomerInfoSection(){let t=this.querySelector('[slot="customer-info"]');if(t){let r=this.createCustomerInfoSection();r.slot="customer-info",t.replaceWith(r)}}updateCustomStyles(){let t=this.querySelector(`#${this.containerId}-custom-styles`);if(t){let r=`
903
903
  /* PAYUNi iframe \u5BB9\u5668\u9AD8\u5EA6\uFF08\u4F7F\u7528\u5BE6\u969B\u7684 container ID\uFF09 */
904
904
  #${this.containerId}-card-no,
905
905
  #${this.containerId}-card-exp,
@@ -907,7 +907,7 @@
907
907
  height: 36px !important;
908
908
  }
909
909
  `;t.textContent=this.customStyles+`
910
- `+r}}createOrderSummarySection(){let t=document.createElement("div");t.className="order-summary-section";let r=this.getAttribute("plan-name"),i=this.getAttribute("amount"),s=this.getAttribute("billing-period");if(!r||!i)return t;let a=s?{MONTHLY:"\u6708",QUARTERLY:"\u5B63",YEARLY:"\u5E74",WEEKLY:"\u9031"}[s]||s:"";return t.innerHTML=`
910
+ `+r}}createOrderSummarySection(){let t=document.createElement("div");t.className="order-summary-section";let r=this.getAttribute("plan-name"),i=this.getAttribute("amount"),s=this.getAttribute("billing-period");if(!r||!i)return t;let n=s?{MONTHLY:"\u6708",QUARTERLY:"\u5B63",YEARLY:"\u5E74",WEEKLY:"\u9031"}[s]||s:"";return t.innerHTML=`
911
911
  <style>
912
912
  .order-summary-section {
913
913
  background: #f7fafc;
@@ -962,10 +962,10 @@
962
962
  <span class="order-summary-label">\u8A02\u95B1\u65B9\u6848</span>
963
963
  <span class="order-summary-value">${r}</span>
964
964
  </div>
965
- ${a?`
965
+ ${n?`
966
966
  <div class="order-summary-item">
967
967
  <span class="order-summary-label">\u8A08\u8CBB\u9031\u671F</span>
968
- <span class="order-summary-value">\u6BCF${a}</span>
968
+ <span class="order-summary-value">\u6BCF${n}</span>
969
969
  </div>
970
970
  `:""}
971
971
  <div class="order-summary-item">
@@ -1220,10 +1220,10 @@
1220
1220
  >
1221
1221
  <span id="${this.containerId}-submit-text">\u78BA\u8A8D\u4ED8\u6B3E</span>
1222
1222
  </button>
1223
- `,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`),o=document.getElementById(`${this.containerId}-card-cvc`);if(!i||!s||!o)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 a=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 a.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(),a.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=a,this.setupFormSubmission(),this._isInitializing=!1,a))}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,o=document.getElementById(`${this.containerId}-email`),a=document.getElementById(`${this.containerId}-name`);if(o&&a){if(i=o.value,s=a.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=`
1223
+ `,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`),a=document.getElementById(`${this.containerId}-card-cvc`);if(!i||!s||!a)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 n=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 n.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(),n.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=n,this.setupFormSubmission(),this._isInitializing=!1,n))}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,a=document.getElementById(`${this.containerId}-email`),n=document.getElementById(`${this.containerId}-name`);if(a&&n){if(i=a.value,s=n.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=`
1224
1224
  <span class="recur-loading-spinner"></span>
1225
1225
  <span>\u8655\u7406\u4E2D...</span>
1226
- `):(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",A)});var ae={};f(ae,{RecurCheckoutButton:()=>D});var D,ce=g(()=>{"use strict";D=class extends HTMLElement{constructor(){super();c(this,"_isLoading",!1);c(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"),o=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(!o){this.dispatchError("Missing required attribute: cancel-url");return}this._isLoading=!0,this.render(),this.setupEventListeners();try{let a=await this.createCheckoutSession({publishableKey:r,productId:i,successUrl:this.resolveUrl(s),cancelUrl:this.resolveUrl(o),customerEmail:this.getAttribute("customer-email")||void 0,mode:this.getAttribute("mode")});this.dispatchEvent(new CustomEvent("checkout-started",{detail:{sessionId:a.id,url:a.url},bubbles:!0,composed:!0})),window.location.href=a.url}catch(a){this._isLoading=!1,this.render(),this.setupEventListeners(),this.dispatchError(a.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=`
1226
+ `):(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",A)});var ae={};f(ae,{RecurCheckoutButton:()=>D});var D,ce=g(()=>{"use strict";D=class extends HTMLElement{constructor(){super();c(this,"_isLoading",!1);c(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"),a=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(!a){this.dispatchError("Missing required attribute: cancel-url");return}this._isLoading=!0,this.render(),this.setupEventListeners();try{let n=await this.createCheckoutSession({publishableKey:r,productId:i,successUrl:this.resolveUrl(s),cancelUrl:this.resolveUrl(a),customerEmail:this.getAttribute("customer-email")||void 0,mode:this.getAttribute("mode")});this.dispatchEvent(new CustomEvent("checkout-started",{detail:{sessionId:n.id,url:n.url},bubbles:!0,composed:!0})),window.location.href=n.url}catch(n){this._isLoading=!1,this.render(),this.setupEventListeners(),this.dispatchError(n.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=`
1227
1227
  <style>
1228
1228
  :host {
1229
1229
  display: inline-block;
@@ -1322,7 +1322,7 @@
1322
1322
  ${this._isLoading?'<span class="spinner"></span>':""}
1323
1323
  <span>${this._isLoading?"\u8655\u7406\u4E2D...":t}</span>
1324
1324
  </button>
1325
- `}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 o=await s.json().catch(()=>({}));throw new Error(o.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",D)});var le={};f(le,{RecurPortalButton:()=>z});var z,de=g(()=>{"use strict";z=class extends HTMLElement{constructor(){super();c(this,"_isLoading",!1);c(this,"handleClick",async t=>{if(t.preventDefault(),this._isLoading||this.hasAttribute("disabled"))return;let r=this.getAttribute("portal-url"),i=this.getAttribute("api-endpoint");if(r){this.redirectToPortal(r);return}if(i){await this.fetchAndRedirect(i);return}this.dispatchError("Missing required attribute: either portal-url or api-endpoint must be provided")});this.attachShadow({mode:"open"})}static get observedAttributes(){return["portal-url","api-endpoint","customer-id","return-url","button-text","button-style","disabled","target"]}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()||"\u7BA1\u7406\u8A02\u95B1",r=this.getAttribute("button-style")||"primary",i=this.hasAttribute("disabled")||this._isLoading;this.shadowRoot.innerHTML=`
1325
+ `}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 a=await s.json().catch(()=>({}));throw new Error(a.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",D)});var le={};f(le,{RecurPortalButton:()=>z});var z,de=g(()=>{"use strict";z=class extends HTMLElement{constructor(){super();c(this,"_isLoading",!1);c(this,"handleClick",async t=>{if(t.preventDefault(),this._isLoading||this.hasAttribute("disabled"))return;let r=this.getAttribute("portal-url"),i=this.getAttribute("api-endpoint");if(r){this.redirectToPortal(r);return}if(i){await this.fetchAndRedirect(i);return}this.dispatchError("Missing required attribute: either portal-url or api-endpoint must be provided")});this.attachShadow({mode:"open"})}static get observedAttributes(){return["portal-url","api-endpoint","customer-id","return-url","button-text","button-style","disabled","target"]}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()||"\u7BA1\u7406\u8A02\u95B1",r=this.getAttribute("button-style")||"primary",i=this.hasAttribute("disabled")||this._isLoading;this.shadowRoot.innerHTML=`
1326
1326
  <style>
1327
1327
  :host {
1328
1328
  display: inline-block;
@@ -1449,7 +1449,7 @@
1449
1449
  <path d="M19 21v-2a4 4 0 0 0-4-4H9a4 4 0 0 0-4 4v2"/>
1450
1450
  <circle cx="12" cy="7" r="4"/>
1451
1451
  </svg>
1452
- `}setupEventListeners(){let t=this.shadowRoot?.querySelector("button");t&&t.addEventListener("click",this.handleClick)}redirectToPortal(t){let r=this.getAttribute("target");this.dispatchEvent(new CustomEvent("portal-redirect",{detail:{url:t},bubbles:!0,composed:!0})),r==="_blank"?window.open(t,"_blank","noopener,noreferrer"):window.location.href=t}async fetchAndRedirect(t){let r=this.getAttribute("customer-id"),i=this.getAttribute("return-url");this._isLoading=!0,this.render(),this.setupEventListeners();try{let s={};r&&(s.customerId=r),i&&(s.returnUrl=i);let o=await fetch(t,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(s)});if(!o.ok){let d=await o.json().catch(()=>({}));throw new Error(d.error?.message||d.message||`HTTP ${o.status}: Failed to create portal session`)}let a=await o.json(),l=a.url||a.portalUrl;if(!l)throw new Error("Portal URL not found in response");this._isLoading=!1,this.render(),this.setupEventListeners(),this.redirectToPortal(l)}catch(s){this._isLoading=!1,this.render(),this.setupEventListeners(),this.dispatchError(s.message||"Failed to create portal session")}}dispatchError(t){console.error("[recur-portal]",t),this.dispatchEvent(new CustomEvent("portal-error",{detail:{message:t},bubbles:!0,composed:!0}))}};typeof window<"u"&&!customElements.get("recur-portal")&&customElements.define("recur-portal",z)});var Ie={};f(Ie,{RecurCheckout:()=>S,RecurElements:()=>x,createElements:()=>j,default:()=>Te,init:()=>pe});async function xe(){if(typeof window>"u"){console.warn("[Recur SDK] Cannot register Web Components: window is not defined");return}await Promise.all([Promise.resolve().then(()=>(X(),V)),Promise.resolve().then(()=>(W(),J)),Promise.resolve().then(()=>(Z(),G)),Promise.resolve().then(()=>(ee(),Q)),Promise.resolve().then(()=>(re(),te)),Promise.resolve().then(()=>(se(),ie)),Promise.resolve().then(()=>(ne(),oe)),Promise.resolve().then(()=>(ce(),ae)),Promise.resolve().then(()=>(de(),le))]);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","recur-portal"].filter(t=>!customElements.get(t));e.length>0&&console.warn("[Recur SDK] The following components are not registered:",e)}typeof window<"u"&&xe();function Ee(n){return n.replace(/_([a-z])/g,(e,t)=>t.toUpperCase())}function b(n){if(n==null)return n;if(Array.isArray(n))return n.map(e=>b(e));if(n instanceof Date)return n;if(typeof n=="object"){let e={};for(let[t,r]of Object.entries(n)){let i=Ee(t);e[i]=b(r)}return e}return n}var H=class{constructor(e){c(this,"config");if(!e.publishableKey)throw new Error("publishableKey is required");this.config={baseUrl:"https://api.recur.tw",...e}}async createSubscription(e){let{customerName:t,customerEmail:r}=e,i=e.productId||e.planId,s=e.productSlug;if(!i&&!s)throw new Error("Either productId or productSlug is required");let o={customerName:t,customerEmail:r};i&&(o.productId=i),s&&(o.productSlug=s);let a=await fetch(`${this.config.baseUrl}/v1/subscriptions`,{method:"POST",headers:{"Content-Type":"application/json","X-Recur-Publishable-Key":this.config.publishableKey},body:JSON.stringify(o)});if(!a.ok){let d=await a.json().catch(()=>({}));throw{code:d.error||"CHECKOUT_FAILED",message:d.message||"Failed to initiate checkout",details:d}}let l=await a.json();return b(l)}async fetchProducts(e){let t=new URL(`${this.config.baseUrl}/v1/products`);e?.type&&t.searchParams.set("type",e.type);let r=await fetch(t.toString(),{method:"GET",headers:{"Content-Type":"application/json","X-Recur-Publishable-Key":this.config.publishableKey}});if(!r.ok){let s=await r.json().catch(()=>({}));throw{code:s.error||"FETCH_PRODUCTS_FAILED",message:s.message||"Failed to fetch products",details:s}}let i=await r.json();return b(i)}async fetchPlans(){return{plans:(await this.fetchProducts({type:"SUBSCRIPTION"})).products}}getConfig(){return{...this.config}}};var $=class{constructor(e,t){c(this,"config");c(this,"options");c(this,"container");c(this,"checkoutId",null);c(this,"sdkToken",null);c(this,"sdkEnv","S");c(this,"payuniSDK",null);c(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 s=await t.json().catch(()=>({}));throw new Error(s.error||"Failed to initialize checkout")}let r=await t.json(),i=b(r);this.checkoutId=i.checkout.id,this.sdkToken=i.sdkToken,this.sdkEnv=this.config.publishableKey.startsWith("pk_test_")?"S":"P"}renderHTML(){this.container.innerHTML=`
1452
+ `}setupEventListeners(){let t=this.shadowRoot?.querySelector("button");t&&t.addEventListener("click",this.handleClick)}redirectToPortal(t){let r=this.getAttribute("target");this.dispatchEvent(new CustomEvent("portal-redirect",{detail:{url:t},bubbles:!0,composed:!0})),r==="_blank"?window.open(t,"_blank","noopener,noreferrer"):window.location.href=t}async fetchAndRedirect(t){let r=this.getAttribute("customer-id"),i=this.getAttribute("return-url");this._isLoading=!0,this.render(),this.setupEventListeners();try{let s={};r&&(s.customerId=r),i&&(s.returnUrl=i);let a=await fetch(t,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(s)});if(!a.ok){let d=await a.json().catch(()=>({}));throw new Error(d.error?.message||d.message||`HTTP ${a.status}: Failed to create portal session`)}let n=await a.json(),l=n.url||n.portalUrl;if(!l)throw new Error("Portal URL not found in response");this._isLoading=!1,this.render(),this.setupEventListeners(),this.redirectToPortal(l)}catch(s){this._isLoading=!1,this.render(),this.setupEventListeners(),this.dispatchError(s.message||"Failed to create portal session")}}dispatchError(t){console.error("[recur-portal]",t),this.dispatchEvent(new CustomEvent("portal-error",{detail:{message:t},bubbles:!0,composed:!0}))}};typeof window<"u"&&!customElements.get("recur-portal")&&customElements.define("recur-portal",z)});var Ie={};f(Ie,{RecurCheckout:()=>S,RecurElements:()=>w,createElements:()=>j,default:()=>Te,init:()=>pe});async function we(){if(typeof window>"u"){console.warn("[Recur SDK] Cannot register Web Components: window is not defined");return}await Promise.all([Promise.resolve().then(()=>(X(),V)),Promise.resolve().then(()=>(W(),J)),Promise.resolve().then(()=>(Z(),G)),Promise.resolve().then(()=>(ee(),Q)),Promise.resolve().then(()=>(re(),te)),Promise.resolve().then(()=>(se(),ie)),Promise.resolve().then(()=>(ne(),oe)),Promise.resolve().then(()=>(ce(),ae)),Promise.resolve().then(()=>(de(),le))]);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","recur-portal"].filter(t=>!customElements.get(t));e.length>0&&console.warn("[Recur SDK] The following components are not registered:",e)}typeof window<"u"&&we();function Ee(o){return o.replace(/_([a-z])/g,(e,t)=>t.toUpperCase())}function b(o){if(o==null)return o;if(Array.isArray(o))return o.map(e=>b(e));if(o instanceof Date)return o;if(typeof o=="object"){let e={};for(let[t,r]of Object.entries(o)){let i=Ee(t);e[i]=b(r)}return e}return o}var H=class{constructor(e){c(this,"config");if(!e.publishableKey)throw new Error("publishableKey is required");this.config={baseUrl:"https://api.recur.tw",...e}}async createSubscription(e){let{customerName:t,customerEmail:r}=e,i=e.productId||e.planId,s=e.productSlug;if(!i&&!s)throw new Error("Either productId or productSlug is required");let a={customerName:t,customerEmail:r};i&&(a.productId=i),s&&(a.productSlug=s);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(a)});if(!n.ok){let d=await n.json().catch(()=>({}));throw{code:d.error||"CHECKOUT_FAILED",message:d.message||"Failed to initiate checkout",details:d}}let l=await n.json();return b(l)}async fetchProducts(e){let t=new URL(`${this.config.baseUrl}/v1/products`);e?.type&&t.searchParams.set("type",e.type);let r=await fetch(t.toString(),{method:"GET",headers:{"Content-Type":"application/json","X-Recur-Publishable-Key":this.config.publishableKey}});if(!r.ok){let s=await r.json().catch(()=>({}));throw{code:s.error||"FETCH_PRODUCTS_FAILED",message:s.message||"Failed to fetch products",details:s}}let i=await r.json();return b(i)}async fetchPlans(){return{plans:(await this.fetchProducts({type:"SUBSCRIPTION"})).products}}getConfig(){return{...this.config}}};var $=class{constructor(e,t){c(this,"config");c(this,"options");c(this,"container");c(this,"checkoutId",null);c(this,"sdkToken",null);c(this,"sdkEnv","S");c(this,"payuniSDK",null);c(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 s=await t.json().catch(()=>({}));throw new Error(s.error||"Failed to initialize checkout")}let r=await t.json(),i=b(r);this.checkoutId=i.checkout.id,this.sdkToken=i.sdkToken,this.sdkEnv=this.config.publishableKey.startsWith("pk_test_")?"S":"P"}renderHTML(){this.container.innerHTML=`
1453
1453
  <div class="recur-embedded-checkout" style="max-width: 400px; margin: 0 auto; padding: 20px; font-family: system-ui, -apple-system, sans-serif;">
1454
1454
  <div class="recur-checkout-header" style="margin-bottom: 24px;">
1455
1455
  <h2 style="margin: 0 0 8px 0; font-size: 20px; font-weight: 600; color: #111;">Subscribe</h2>
@@ -1519,21 +1519,21 @@
1519
1519
  </p>
1520
1520
  </form>
1521
1521
  </div>
1522
- `}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(),o=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(!o.ok){let d=await o.json().catch(()=>({}));throw new Error(d.error||"Failed to process payment")}let a=await o.json(),l={subscription:{id:a.subscription?.id||a.charge?.id||"",status:a.success?"active":"failed",planId:this.options.planId,planName:"",amount:a.charge?.amount||0,billingPeriod:a.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 x=class{constructor(e){c(this,"publishableKey");c(this,"baseUrl");c(this,"embedUrl");c(this,"iframe",null);c(this,"container",null);c(this,"sessionId",null);c(this,"timestamp",null);c(this,"creditToken",null);c(this,"sdkToken",null);c(this,"cardToken",null);c(this,"cardTimestamp",null);c(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=`
1522
+ `}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(),a=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(!a.ok){let d=await a.json().catch(()=>({}));throw new Error(d.error||"Failed to process payment")}let n=await a.json(),l={subscription:{id:n.subscription?.id||n.charge?.id||"",status:n.success?"active":"failed",planId:this.options.planId,planName:"",amount:n.charge?.amount||0,billingPeriod:n.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 w=class{constructor(e){c(this,"publishableKey");c(this,"baseUrl");c(this,"embedUrl");c(this,"iframe",null);c(this,"container",null);c(this,"sessionId",null);c(this,"timestamp",null);c(this,"creditToken",null);c(this,"sdkToken",null);c(this,"cardToken",null);c(this,"cardTimestamp",null);c(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=`
1523
1523
  width: 100%;
1524
1524
  border: none;
1525
1525
  min-height: 200px;
1526
1526
  display: block;
1527
1527
  user-select: none;
1528
1528
  transition: height 0.35s ease, opacity 0.4s ease 0.1s;
1529
- `.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),o=()=>{clearTimeout(s),this.off("ready",o),r()},a=l=>{clearTimeout(s),this.off("error",a),i(new Error(l.message||"Elements initialization failed"))};this.on("ready",o),this.on("error",a)})}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.sdkToken=r.sdkToken,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=a=>{clearTimeout(i),this.off("tokenized",s),t(a)},o=a=>{clearTimeout(i),this.off("error",o),r(new Error(a.message||"Tokenization failed"))};this.on("tokenized",s),this.on("error",o)})}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,productId:e.productId,email:e.email,name:e.name,phone:e.phone,externalCustomerId:e.externalCustomerId,metadata:e.metadata,successUrl:e.successUrl,cancelUrl:e.cancelUrl})}),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.sdkToken=null,this.cardToken=null,this.cardTimestamp=null,this.eventHandlers.clear(),window.removeEventListener("message",this.handleMessage.bind(this))}};function j(n){return new x(n)}var Ce="https://vendor.payuni.com.tw/sdk/uni-payment.js",Se="https://sandbox-vendor.payuni.com.tw/sdk/uni-payment.js",ue=!1,N=!1,C=null;async function me(n=!1){return ue&&window.UniPayment?Promise.resolve():(N&&C||(N=!0,C=new Promise((e,t)=>{let r=document.createElement("script");r.src=n?Se:Ce,r.async=!0,r.onload=()=>{ue=!0,N=!1,e()},r.onerror=()=>{N=!1,C=null,t(new Error("Failed to load PAYUNi SDK"))},document.head.appendChild(r)})),C)}var S=class{constructor(e){c(this,"core");c(this,"currentModal",null);c(this,"currentIframe",null);c(this,"currentModalOverlay",null);this.core=new H(e)}async fetchProducts(e){return await this.core.fetchProducts(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();if(!e.productId&&!e.productSlug)throw new Error("Either productId or productSlug is required");let s={successUrl:e.successUrl,cancelUrl:e.cancelUrl};e.productId&&(s.productId=e.productId),e.productSlug&&(s.productSlug=e.productSlug),e.mode&&(s.mode=e.mode),e.customerEmail&&(s.customerEmail=e.customerEmail),e.customerName&&(s.customerName=e.customerName),e.externalCustomerId&&(s.externalCustomerId=e.externalCustomerId);let o=await fetch(`${i}/v1/checkout/sessions`,{method:"POST",headers:{"Content-Type":"application/json","X-Recur-Publishable-Key":t.publishableKey},body:JSON.stringify(s)});if(!o.ok){let l=await o.json().catch(()=>({}));throw new Error(l.error?.message||"Failed to create checkout session")}let a=await o.json();window.location.href=a.url}async createCheckoutSession(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();if(!e.productId&&!e.productSlug)throw new Error("Either productId or productSlug is required");let s={successUrl:e.successUrl,cancelUrl:e.cancelUrl};e.productId&&(s.productId=e.productId),e.productSlug&&(s.productSlug=e.productSlug),e.mode&&(s.mode=e.mode),e.customerEmail&&(s.customerEmail=e.customerEmail),e.customerName&&(s.customerName=e.customerName),e.externalCustomerId&&(s.externalCustomerId=e.externalCustomerId);let o=await fetch(`${i}/v1/checkout/sessions`,{method:"POST",headers:{"Content-Type":"application/json","X-Recur-Publishable-Key":t.publishableKey},body:JSON.stringify(s)});if(!o.ok){let l=await o.json().catch(()=>({}));throw new Error(l.error?.message||"Failed to create checkout session")}let a=await o.json();return b(a)}async checkout(e){let t=this.core.getConfig(),r=null,i=e.productId||e.planId,s=e.productSlug;try{if(console.log("[Recur SDK] Starting checkout flow...",{productId:i,productSlug:s,mode:e.mode}),!i&&!s)throw new Error("Either productId or productSlug 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 o=this.getBaseUrl();console.log("[Recur SDK] Base URL:",o);let a={"Content-Type":"application/json","X-Recur-Publishable-Key":t.publishableKey},l=e.mode||"modal",d=null;if(l==="modal"){let m=this.createModalWithSkeleton(e.onClose);r=m.overlay,d=m.container}else if(l==="iframe"){if(d=this.getEmbeddedContainer(e.container),!d)throw new Error("Container is required for iframe mode");d.innerHTML="";let m=document.createElement("recur-payment-form-skeleton");d.appendChild(m)}console.log("[Recur SDK] Step 1: Creating checkout session...");let v={customerName:e.customerName,customerEmail:e.customerEmail};i&&(v.productId=i),s&&(v.productSlug=s),e.externalCustomerId&&(v.externalCustomerId=e.externalCustomerId);let B=await fetch(`${o}/v1/checkouts`,{method:"POST",headers:a,body:JSON.stringify(v)});if(!B.ok){let m=await B.json().catch(()=>({}));console.error("[Recur SDK] Failed to create checkout:",m);let O=m.details||m.error||"Failed to create checkout";throw new Error(O)}let he=await B.json(),u=b(he);if(console.log("[Recur SDK] Checkout created successfully:",u),e.onSuccess?.(u),l==="redirect"){let m=`https://checkout.recur.tw/${u.checkout.id}`;console.log("[Recur SDK] Redirecting to hosted checkout:",m),window.location.href=m;return}if(console.log("[Recur SDK] Step 2: Extracting SDK token..."),!u.sdkToken)throw new Error("SDK token missing from checkout response");console.log("[Recur SDK] Step 3: Loading PAYUNi SDK...");let q=!0;if(await me(q),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..."),!d)throw new Error("Payment container not available");d.innerHTML="";let h=document.createElement("recur-payment-form");if(h.setAttribute("container-id",d.id||"recur-payment-container"),e.customerName&&h.setAttribute("customer-name",e.customerName),e.customerEmail&&h.setAttribute("customer-email",e.customerEmail),u.plan?.name&&h.setAttribute("plan-name",u.plan.name),u.checkout?.amount&&h.setAttribute("amount",u.checkout.amount.toString()),u.plan?.billingPeriod&&h.setAttribute("billing-period",u.plan.billingPeriod),h.setAttribute("custom-styles",`
1529
+ `.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),a=()=>{clearTimeout(s),this.off("ready",a),r()},n=l=>{clearTimeout(s),this.off("error",n),i(new Error(l.message||"Elements initialization failed"))};this.on("ready",a),this.on("error",n)})}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.sdkToken=r.sdkToken,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=n=>{clearTimeout(i),this.off("tokenized",s),t(n)},a=n=>{clearTimeout(i),this.off("error",a),r(new Error(n.message||"Tokenization failed"))};this.on("tokenized",s),this.on("error",a)})}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,productId:e.productId,email:e.email,name:e.name,phone:e.phone,externalCustomerId:e.externalCustomerId,metadata:e.metadata,successUrl:e.successUrl,cancelUrl:e.cancelUrl})}),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.sdkToken=null,this.cardToken=null,this.cardTimestamp=null,this.eventHandlers.clear(),window.removeEventListener("message",this.handleMessage.bind(this))}};function j(o){return new w(o)}var Ce="https://vendor.payuni.com.tw/sdk/uni-payment.js",Se="https://sandbox-vendor.payuni.com.tw/sdk/uni-payment.js",ue=!1,N=!1,C=null;async function me(o=!1){return ue&&window.UniPayment?Promise.resolve():(N&&C||(N=!0,C=new Promise((e,t)=>{let r=document.createElement("script");r.src=o?Se:Ce,r.async=!0,r.onload=()=>{ue=!0,N=!1,e()},r.onerror=()=>{N=!1,C=null,t(new Error("Failed to load PAYUNi SDK"))},document.head.appendChild(r)})),C)}var S=class{constructor(e){c(this,"core");c(this,"currentModal",null);c(this,"currentIframe",null);c(this,"currentModalOverlay",null);this.core=new H(e)}async fetchProducts(e){return await this.core.fetchProducts(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=await this.createCheckoutSession(e);window.location.href=t.url}async createCheckoutSession(e){let t=this.getBaseUrl();if(!e.productId&&!e.productSlug)throw new Error("Either productId or productSlug is required");let r={};e.productId&&(r.productId=e.productId),e.productSlug&&(r.productSlug=e.productSlug),e.customerEmail&&(r.customerEmail=e.customerEmail),e.customerName&&(r.customerName=e.customerName),e.externalCustomerId&&(r.externalCustomerId=e.externalCustomerId),e.successUrl&&(r.successUrl=e.successUrl),e.cancelUrl&&(r.cancelUrl=e.cancelUrl);let i=this.core.getConfig(),s=await fetch(`${t}/v1/checkouts`,{method:"POST",headers:{"Content-Type":"application/json","X-Recur-Publishable-Key":i.publishableKey},body:JSON.stringify(r)});if(!s.ok){let l=await s.json().catch(()=>({}));throw new Error(l.error?.message||l.error||"Failed to create checkout session")}let a=await s.json(),n=b(a);return{id:n.checkout.id,url:n.url,expiresAt:n.checkout.expiresAt}}async checkout(e){let t=this.core.getConfig(),r=null,i=e.productId||e.planId,s=e.productSlug;try{if(console.log("[Recur SDK] Starting checkout flow...",{productId:i,productSlug:s,mode:e.mode}),!i&&!s)throw new Error("Either productId or productSlug 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 a=this.getBaseUrl();console.log("[Recur SDK] Base URL:",a);let n={"Content-Type":"application/json","X-Recur-Publishable-Key":t.publishableKey},l=e.mode||"modal",d=null;if(l==="modal"){let m=this.createModalWithSkeleton(e.onClose);r=m.overlay,d=m.container}else if(l==="iframe"){if(d=this.getEmbeddedContainer(e.container),!d)throw new Error("Container is required for iframe mode");d.innerHTML="";let m=document.createElement("recur-payment-form-skeleton");d.appendChild(m)}console.log("[Recur SDK] Step 1: Creating checkout session...");let v={customerName:e.customerName,customerEmail:e.customerEmail};i&&(v.productId=i),s&&(v.productSlug=s),e.externalCustomerId&&(v.externalCustomerId=e.externalCustomerId);let B=await fetch(`${a}/v1/checkouts`,{method:"POST",headers:n,body:JSON.stringify(v)});if(!B.ok){let m=await B.json().catch(()=>({}));console.error("[Recur SDK] Failed to create checkout:",m);let O=m.details||m.error||"Failed to create checkout";throw new Error(O)}let he=await B.json(),u=b(he);if(console.log("[Recur SDK] Checkout created successfully:",u),e.onSuccess?.(u),l==="redirect"){let m=`https://checkout.recur.tw/${u.checkout.id}`;console.log("[Recur SDK] Redirecting to hosted checkout:",m),window.location.href=m;return}if(console.log("[Recur SDK] Step 2: Extracting SDK token..."),!u.sdkToken)throw new Error("SDK token missing from checkout response");console.log("[Recur SDK] Step 3: Loading PAYUNi SDK...");let q=!0;if(await me(q),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..."),!d)throw new Error("Payment container not available");d.innerHTML="";let h=document.createElement("recur-payment-form");if(h.setAttribute("container-id",d.id||"recur-payment-container"),e.customerName&&h.setAttribute("customer-name",e.customerName),e.customerEmail&&h.setAttribute("customer-email",e.customerEmail),u.plan?.name&&h.setAttribute("plan-name",u.plan.name),u.checkout?.amount&&h.setAttribute("amount",u.checkout.amount.toString()),u.plan?.billingPeriod&&h.setAttribute("billing-period",u.plan.billingPeriod),h.setAttribute("custom-styles",`
1530
1530
  .form-input-focus {
1531
1531
  border-color: var(--ring, hsl(215 16% 47%)) !important;
1532
1532
  outline: 0 !important;
1533
1533
  box-shadow: 0 0 0 3px color-mix(in oklch, var(--ring, hsl(215 16% 47%)) 50%, transparent) !important;
1534
1534
  transition: border-color 0.15s ease-in-out, box-shadow 0.15s ease-in-out !important;
1535
1535
  }
1536
- `),d.appendChild(h),await new Promise(m=>setTimeout(m,100)),console.log("[Recur SDK] Step 5: Initializing PAYUNi SDK..."),await h.initializePayment(u.sdkToken,q?"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..."),h.addEventListener("submit",(async m=>{console.log("[Recur SDK] Form submitted");let O=m,{paymentSession:fe}=O.detail;try{let w=await fe.getTradeResult();console.log("[Recur SDK] Trade result received"),console.log("[Recur SDK] Executing payment...");let K=w.HashTimestamp||w.timestamp,Y={};if(u.checkout.productType==="SUBSCRIPTION"){let k=u.creditToken,T=u.sdkTimestamp;if(!k)throw console.error("[Recur SDK] Missing creditToken from checkout for subscription"),new Error("Missing creditToken for subscription payment");Y={creditToken:k,timestamp:T||K},console.log("[Recur SDK] Using creditToken from checkout:",k.substring(0,30)+"..."),console.log("[Recur SDK] Using timestamp:",T?"from checkout (sdkTimestamp)":"from tradeResult")}let F=await fetch(`${o}/v1/checkouts/${u.checkout.id}/pay`,{method:"POST",headers:a,body:JSON.stringify(Y)});if(!F.ok){let k=await F.json().catch(()=>({}));throw new Error(k.error||"Failed to execute payment")}let p=await F.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}if(e.onPaymentComplete)if(p.subscription)e.onPaymentComplete({id:p.subscription.id,status:p.subscription.status,planId:u.checkout.productId,amount:u.checkout.amount,billingPeriod:p.subscription.billingPeriod,currentPeriodStart:p.subscription.currentPeriodStart,currentPeriodEnd:p.subscription.currentPeriodEnd});else{let k=p.charge?.id||p.paymentIntent?.id,T=p.charge?.status||"SUCCEEDED";e.onPaymentComplete({id:k,status:T,planId:u.checkout.productId,amount:u.checkout.amount,billingPeriod:u.checkout.productType})}console.log("[Recur SDK] Checkout flow completed successfully!"),h.resetButton?.(),r&&r.remove()}catch(w){console.error("[Recur SDK] Payment error:",w);let K={code:"PAYMENT_FAILED",message:w instanceof Error?w.message:"Payment failed"};e.onError?.(K),h.resetButton?.()}})),console.log("[Recur SDK] Checkout flow initialized, waiting for user input...")}catch(o){console.error("[Recur SDK] Checkout error:",o),r&&r.remove();let a={code:"CHECKOUT_ERROR",message:o instanceof Error?o.message:"An unknown error occurred"};throw e.onError?.(a),o}}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=`
1536
+ `),d.appendChild(h),await new Promise(m=>setTimeout(m,100)),console.log("[Recur SDK] Step 5: Initializing PAYUNi SDK..."),await h.initializePayment(u.sdkToken,q?"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..."),h.addEventListener("submit",(async m=>{console.log("[Recur SDK] Form submitted");let O=m,{paymentSession:fe}=O.detail;try{let x=await fe.getTradeResult();console.log("[Recur SDK] Trade result received"),console.log("[Recur SDK] Executing payment...");let K=x.HashTimestamp||x.timestamp,Y={};if(u.checkout.productType==="SUBSCRIPTION"){let k=u.creditToken,T=u.sdkTimestamp;if(!k)throw console.error("[Recur SDK] Missing creditToken from checkout for subscription"),new Error("Missing creditToken for subscription payment");Y={creditToken:k,timestamp:T||K},console.log("[Recur SDK] Using creditToken from checkout:",k.substring(0,30)+"..."),console.log("[Recur SDK] Using timestamp:",T?"from checkout (sdkTimestamp)":"from tradeResult")}let F=await fetch(`${a}/v1/checkouts/${u.checkout.id}/pay`,{method:"POST",headers:n,body:JSON.stringify(Y)});if(!F.ok){let k=await F.json().catch(()=>({}));throw new Error(k.error||"Failed to execute payment")}let p=await F.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}if(e.onPaymentComplete)if(p.subscription)e.onPaymentComplete({id:p.subscription.id,status:p.subscription.status,planId:u.checkout.productId,amount:u.checkout.amount,billingPeriod:p.subscription.billingPeriod,currentPeriodStart:p.subscription.currentPeriodStart,currentPeriodEnd:p.subscription.currentPeriodEnd});else{let k=p.charge?.id||p.paymentIntent?.id,T=p.charge?.status||"SUCCEEDED";e.onPaymentComplete({id:k,status:T,planId:u.checkout.productId,amount:u.checkout.amount,billingPeriod:u.checkout.productType})}console.log("[Recur SDK] Checkout flow completed successfully!"),h.resetButton?.(),r&&r.remove()}catch(x){console.error("[Recur SDK] Payment error:",x);let K={code:"PAYMENT_FAILED",message:x instanceof Error?x.message:"Payment failed"};e.onError?.(K),h.resetButton?.()}})),console.log("[Recur SDK] Checkout flow initialized, waiting for user input...")}catch(a){console.error("[Recur SDK] Checkout error:",a),r&&r.remove();let n={code:"CHECKOUT_ERROR",message:a instanceof Error?a.message:"An unknown error occurred"};throw e.onError?.(n),a}}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=`
1537
1537
  position: fixed;
1538
1538
  top: 0;
1539
1539
  left: 0;
@@ -1572,7 +1572,7 @@
1572
1572
  border-radius: 50%;
1573
1573
  z-index: 10;
1574
1574
  transition: background 0.2s;
1575
- `,i.onmouseover=()=>{i.style.background="rgba(0, 0, 0, 0.1)"},i.onmouseout=()=>{i.style.background="rgba(0, 0, 0, 0.05)"},i.onclick=()=>{t.remove(),e?.()};let s=document.createElement("div");s.id="recur-modal-payment-container";let o=document.createElement("recur-payment-form-skeleton");return s.appendChild(o),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()}async createPortalSession(e,t){let r=await fetch(e,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({customerId:t.customerId,returnUrl:t.returnUrl})});if(!r.ok){let s=await r.json().catch(()=>({}));throw new Error(s.error?.message||s.message||"Failed to create portal session")}let i=await r.json();return{id:i.id,url:i.url||i.portalUrl,expiresAt:i.expiresAt}}async redirectToPortal(e,t){let r=await this.createPortalSession(e,t);window.location.href=r.url}};function pe(n){return new S(n)}var Te={init:pe,RecurCheckout:S,RecurElements:x,createElements:j};return we(Ie);})();
1575
+ `,i.onmouseover=()=>{i.style.background="rgba(0, 0, 0, 0.1)"},i.onmouseout=()=>{i.style.background="rgba(0, 0, 0, 0.05)"},i.onclick=()=>{t.remove(),e?.()};let s=document.createElement("div");s.id="recur-modal-payment-container";let a=document.createElement("recur-payment-form-skeleton");return s.appendChild(a),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()}async createPortalSession(e,t){let r=await fetch(e,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({customerId:t.customerId,returnUrl:t.returnUrl})});if(!r.ok){let s=await r.json().catch(()=>({}));throw new Error(s.error?.message||s.message||"Failed to create portal session")}let i=await r.json();return{id:i.id,url:i.url||i.portalUrl,expiresAt:i.expiresAt}}async redirectToPortal(e,t){let r=await this.createPortalSession(e,t);window.location.href=r.url}};function pe(o){return new S(o)}var Te={init:pe,RecurCheckout:S,RecurElements:w,createElements:j};return xe(Ie);})();
1576
1576
  if (typeof window !== "undefined") {
1577
1577
  window.RecurCheckout = RecurCheckout.default;
1578
1578
  window.RecurElements = RecurCheckout.RecurElements;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "recur-tw",
3
- "version": "0.7.6",
3
+ "version": "0.8.0",
4
4
  "description": "React & Vanilla JS SDK for embedding subscription checkout flows (Taiwan / PAYUNi)",
5
5
  "type": "module",
6
6
  "private": false,