@payinto/checkout-sdk 1.1.0 → 1.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -32,6 +32,7 @@ const handlePayment = () => {
32
32
  email: 'customer@example.com',
33
33
  name: 'John Doe'
34
34
  },
35
+ settlement_account_id: '01964316-57cb-7284-8651-c53d3fcee694',
35
36
  onSuccess: (response) => {
36
37
  console.log('Payment successful:', response);
37
38
  },
@@ -66,6 +67,7 @@ window.PayintoCheckout.open({
66
67
  | `customer` | `object` | Yes | Customer details (`email` is required). |
67
68
  | `merchant_reference` | `string` | No | Unique merchant transaction reference. |
68
69
  | `metadata` | `object` | No | Additional data for the transaction. |
70
+ | `settlement_account_id` | `string` | No | The ID of the settlement account to receive funds for this checkout. If omitted, your Payinto Main account is used. |
69
71
  | `redirect_url`| `string` | No | URL to redirect to after successful payment. |
70
72
  | `onSuccess` | `function`| No | Callback on successful payment. |
71
73
  | `onClose` | `function`| No | Callback when the checkout is closed. |
@@ -1 +1 @@
1
- const e="undefined"!=typeof window,t=e?"https://checkout.payinto.co":"",o="/v1".replace(/\/+$/,""),n=`${t}${o}/popup`,i="https://checkout.payinto.co,https://go.payinto.co".split(",").map(e=>e.trim()).filter(Boolean),r=e?new URL(n).origin:"",c=/* @__PURE__ */new Set([r,...i]),s=e=>{try{const t=new URL(e.checkout_url),o=e.checkout_version||(e=>{try{const t=new URL(e).pathname.split("/").filter(Boolean)[0];return/^v[0-9]+$/i.test(t||"")?t:void 0}catch{return}})(e.checkout_url);return o?`${t.origin}/${o}/popup`:`${t.origin}/popup`}catch{return n}};const a=new class{container=null;iframe=null;messageListener=null;callbacks={};initRetryTimer=null;open(e){const t=(e=>{if("token"===e.mode)return e;if("public_key"===e.mode)return e;throw new Error('Payinto Checkout: invalid options. Provide a valid mode ("token" or "public_key").')})(e);this.container&&this.close(),this.callbacks={onClose:t.onClose,onSuccess:t.onSuccess,onError:t.onError,callback:t.callback},this.mountOverlay();(async()=>{try{const e="token"===t.mode?this.validateTokenMode(t):await this.initializePublicKeyMode(t);this.bindMessageListener(),this.initializeIframe(e)}catch(e){const t=e instanceof Error?e.message:"Unable to initialize checkout.";this.handleError({type:"checkout.error",code:"initialization_failed",message:t})}})()}pay(e){this.open(e)}close=()=>{this.clearInitRetry(),this.messageListener&&(window.removeEventListener("message",this.messageListener),this.messageListener=null),this.container&&document.body.contains(this.container)&&document.body.removeChild(this.container),this.container=null,this.iframe=null,document.body.classList.remove("payinto-checkout-open")};clearInitRetry(){null!==this.initRetryTimer&&(window.clearInterval(this.initRetryTimer),this.initRetryTimer=null)}mountOverlay(){const e=document.createElement("div");e.id="payinto-checkout-container",e.style.position="fixed",e.style.top="0",e.style.left="0",e.style.right="0",e.style.bottom="0",e.style.width="100%",e.style.minHeight="100vh",e.style.height="100%",e.style.backgroundColor="rgba(0, 0, 0, 0.85)",e.style.zIndex="9999",e.style.display="flex",e.style.alignItems="flex-start",e.style.justifyContent="center",e.style.overflowY="auto",e.style.paddingTop="6rem",e.style.paddingBottom="2rem",e.style.boxSizing="border-box";const t=document.createElement("div");t.className="payinto-preloader",t.style.display="flex",t.style.flexDirection="column",t.style.alignItems="center",t.style.justifyContent="center",t.style.position="absolute",t.style.top="6rem",t.style.left="50%",t.style.transform="translateX(-50%)",t.style.width="100%",t.style.maxWidth="650px",t.style.padding="4rem 0",t.style.zIndex="10",t.style.fontFamily="system-ui, -apple-system, sans-serif";const o=document.createElement("div");o.style.width="40px",o.style.height="40px",o.style.borderRadius="50%",o.style.border="2px solid transparent",o.style.borderBottom="2px solid #ffffff",o.style.marginBottom="16px",o.style.animation="spin 1s linear infinite";const i=document.createElement("p");i.id="payinto-checkout-subtitle",i.innerText="Initializing Secure Checkout...",i.style.fontSize="12px",i.style.color="#e5e7eb",i.style.margin="0",t.appendChild(o),t.appendChild(i),e.appendChild(t);const r=document.createElement("iframe");if(r.src=n,r.style.width="100%",r.style.maxWidth="650px",r.style.height="auto",r.style.border="none",r.style.backgroundColor="transparent",r.style.opacity="0",r.style.transition="opacity 0.25s ease",r.allow="payment; clipboard-read; clipboard-write",e.appendChild(r),!document.getElementById("payinto-checkout-styles")){const e=document.createElement("style");e.id="payinto-checkout-styles",e.innerHTML="\n @keyframes spin { 0% { transform: rotate(0deg); } 100% { transform: rotate(360deg); } }\n body.payinto-checkout-open { overflow: hidden !important; }\n @media (max-width: 767px) {\n #payinto-checkout-container {\n position: fixed !important;\n top: 0 !important;\n left: 0 !important;\n right: 0 !important;\n bottom: 0 !important;\n height: 100% !important;\n min-height: 100vh !important;\n overflow-y: auto !important;\n padding-top: 0 !important;\n padding-bottom: 0 !important;\n }\n .payinto-preloader { top: 2rem !important; }\n }\n ",document.head.appendChild(e)}document.body.appendChild(e),document.body.classList.add("payinto-checkout-open"),this.container=e,this.iframe=r}validateTokenMode(e){if(!e.token||"string"!=typeof e.token)throw new Error('Payinto Checkout: token is required for mode="token".');if(!e.checkout_url||"string"!=typeof e.checkout_url)throw new Error('Payinto Checkout: checkout_url is required for mode="token".');if(!new URL(e.checkout_url).origin)throw new Error("Payinto Checkout: invalid checkout_url.");return{token:e.token,checkout_url:e.checkout_url,merchant_reference:e.merchant_reference,checkout_version:e.checkout_version}}async initializePublicKeyMode(e){if(!e.public_key)throw new Error('Payinto Checkout: public_key is required for mode="public_key".');if(!e.customer?.email)throw new Error('Payinto Checkout: customer.email is required for mode="public_key".');if(!e.amount||e.amount<=0)throw new Error('Payinto Checkout: amount must be greater than zero for mode="public_key".');const t={merchant_reference:e.merchant_reference,amount:e.amount,currency:e.currency,customer:e.customer,redirect_url:e.redirect_url,metadata:e.metadata,checkout_version:e.checkout_version},o=await fetch("https://api.payinto.co/api/v1/checkout/initialize",{method:"POST",headers:{"Content-Type":"application/json",Accept:"application/json",Authorization:`Bearer ${e.public_key}`},body:JSON.stringify(t)});if(!o.ok){const e=(e=>{try{return JSON.parse(e)}catch{return null}})(await o.text());throw new Error(e?.message||"Failed to initialize transaction.")}const n=await o.json(),i=n.data||(n.token&&n.checkout_url?{token:n.token,checkout_url:n.checkout_url,merchant_reference:n.merchant_reference,checkout_version:n.checkout_version}:void 0);if(!i?.token||!i?.checkout_url)throw new Error("Payinto Checkout: invalid initialize response.");return{token:i.token,checkout_url:i.checkout_url,merchant_reference:i.merchant_reference,checkout_version:i.checkout_version}}initializeIframe(e){if(!this.iframe||!this.container)return;const t=this.container.querySelector("#payinto-checkout-subtitle"),o=this.container.querySelector(".payinto-preloader"),n=s(e),i=new URL(n).origin,r=new URL(e.checkout_url).origin,a=Array.from(/* @__PURE__ */new Set([i,r]));if(!c.has(i)&&i!==new URL(e.checkout_url).origin)throw new Error("Payinto Checkout: target origin is not in allowlist.");this.iframe.src=`${n}?updated=${Date.now()}`,this.iframe.onload=()=>{o&&(o.style.display="none"),this.iframe&&(this.iframe.style.opacity="1");const t=()=>{const t={type:"checkout.init",token:e.token,merchant_reference:e.merchant_reference,checkout_url:e.checkout_url};for(const e of a)this.iframe?.contentWindow?.postMessage(t,e)};t(),this.clearInitRetry();let n=0;this.initRetryTimer=window.setInterval(()=>{n+=1,n>=8?this.clearInitRetry():t()},500)},t&&(t.innerText="Loading checkout...")}bindMessageListener(){const e=e=>{if(!c.has(e.origin))return;this.clearInitRetry();const t=e.data;if("object"==typeof t&&"checkout.resize"===t?.type&&this.iframe)this.iframe.style.height=`${Math.max(300,t.height||0)}px`;else{if("object"==typeof t&&"checkout.close"===t?.type)return this.callbacks.onClose?.(),void this.close();if("object"==typeof t&&"checkout.success"===t?.type||"checkout.success"===t){const e="object"==typeof t?t:{type:"checkout.success",status:"success"};return this.callbacks.onSuccess?.(e),this.callbacks.callback?.(e),void this.close()}"object"==typeof t&&"checkout.error"===t?.type&&this.handleError(t)}};this.messageListener=e,window.addEventListener("message",e)}handleError(e){if(this.callbacks.onError?.(e),this.container){const t=this.container.querySelector(".payinto-preloader"),o=this.container.querySelector("#payinto-checkout-subtitle");t&&(t.style.display="flex"),o&&(o.innerText=e.message,o.style.color="#ff4444")}setTimeout(()=>{this.close()},1800)}},l={open:e=>a.open(e),pay:e=>a.pay(e),close:()=>a.close()},h=e=>{a.open(e)};h.open=e=>a.open(e),h.pay=e=>a.pay(e),h.close=()=>a.close(),e&&(window.PayintoCheckout=h);export{l as PayintoCheckoutApi,l as default};
1
+ const e="undefined"!=typeof window,t=e?"https://checkout.payinto.co":"",o="/v1".replace(/\/+$/,""),n=`${t}${o}/popup`,i="https://checkout.payinto.co,https://go.payinto.co".split(",").map(e=>e.trim()).filter(Boolean),r=e?new URL(n).origin:"",c=/* @__PURE__ */new Set([r,...i]),s=e=>{try{const t=new URL(e.checkout_url),o=e.checkout_version||(e=>{try{const t=new URL(e).pathname.split("/").filter(Boolean)[0];return/^v[0-9]+$/i.test(t||"")?t:void 0}catch{return}})(e.checkout_url);return o?`${t.origin}/${o}/popup`:`${t.origin}/popup`}catch{return n}};const a=new class{container=null;iframe=null;messageListener=null;callbacks={};initRetryTimer=null;open(e){const t=(e=>{if("token"===e.mode)return e;if("public_key"===e.mode)return e;throw new Error('Payinto Checkout: invalid options. Provide a valid mode ("token" or "public_key").')})(e);this.container&&this.close(),this.callbacks={onClose:t.onClose,onSuccess:t.onSuccess,onError:t.onError,callback:t.callback},this.mountOverlay();(async()=>{try{const e="token"===t.mode?this.validateTokenMode(t):await this.initializePublicKeyMode(t);this.bindMessageListener(),this.initializeIframe(e)}catch(e){const t=e instanceof Error?e.message:"Unable to initialize checkout.";this.handleError({type:"checkout.error",code:"initialization_failed",message:t})}})()}pay(e){this.open(e)}close=()=>{this.clearInitRetry(),this.messageListener&&(window.removeEventListener("message",this.messageListener),this.messageListener=null),this.container&&document.body.contains(this.container)&&document.body.removeChild(this.container),this.container=null,this.iframe=null,document.body.classList.remove("payinto-checkout-open")};clearInitRetry(){null!==this.initRetryTimer&&(window.clearInterval(this.initRetryTimer),this.initRetryTimer=null)}mountOverlay(){const e=document.createElement("div");e.id="payinto-checkout-container",e.style.position="fixed",e.style.top="0",e.style.left="0",e.style.right="0",e.style.bottom="0",e.style.width="100%",e.style.minHeight="100vh",e.style.height="100%",e.style.backgroundColor="rgba(0, 0, 0, 0.85)",e.style.zIndex="9999",e.style.display="flex",e.style.alignItems="flex-start",e.style.justifyContent="center",e.style.overflowY="auto",e.style.paddingTop="6rem",e.style.paddingBottom="2rem",e.style.boxSizing="border-box";const t=document.createElement("div");t.className="payinto-preloader",t.style.display="flex",t.style.flexDirection="column",t.style.alignItems="center",t.style.justifyContent="center",t.style.position="absolute",t.style.top="6rem",t.style.left="50%",t.style.transform="translateX(-50%)",t.style.width="100%",t.style.maxWidth="720px",t.style.padding="4rem 0",t.style.zIndex="10",t.style.fontFamily="system-ui, -apple-system, sans-serif";const o=document.createElement("div");o.style.width="40px",o.style.height="40px",o.style.borderRadius="50%",o.style.border="2px solid transparent",o.style.borderBottom="2px solid #ffffff",o.style.marginBottom="16px",o.style.animation="spin 1s linear infinite";const i=document.createElement("p");i.id="payinto-checkout-subtitle",i.innerText="Initializing Secure Checkout...",i.style.fontSize="12px",i.style.color="#e5e7eb",i.style.margin="0",t.appendChild(o),t.appendChild(i),e.appendChild(t);const r=document.createElement("iframe");if(r.src=n,r.style.width="100%",r.style.maxWidth="720px",r.style.height="auto",r.style.border="none",r.style.backgroundColor="transparent",r.style.opacity="0",r.style.transition="opacity 0.25s ease",r.allow="payment; clipboard-read; clipboard-write",e.appendChild(r),!document.getElementById("payinto-checkout-styles")){const e=document.createElement("style");e.id="payinto-checkout-styles",e.innerHTML="\n @keyframes spin { 0% { transform: rotate(0deg); } 100% { transform: rotate(360deg); } }\n body.payinto-checkout-open { overflow: hidden !important; }\n @media (max-width: 767px) {\n #payinto-checkout-container {\n position: fixed !important;\n top: 0 !important;\n left: 0 !important;\n right: 0 !important;\n bottom: 0 !important;\n height: 100% !important;\n min-height: 100vh !important;\n overflow-y: auto !important;\n padding-top: 0 !important;\n padding-bottom: 0 !important;\n }\n .payinto-preloader { top: 2rem !important; }\n }\n ",document.head.appendChild(e)}document.body.appendChild(e),document.body.classList.add("payinto-checkout-open"),this.container=e,this.iframe=r}validateTokenMode(e){if(!e.token||"string"!=typeof e.token)throw new Error('Payinto Checkout: token is required for mode="token".');if(!e.checkout_url||"string"!=typeof e.checkout_url)throw new Error('Payinto Checkout: checkout_url is required for mode="token".');if(!new URL(e.checkout_url).origin)throw new Error("Payinto Checkout: invalid checkout_url.");return{token:e.token,checkout_url:e.checkout_url,merchant_reference:e.merchant_reference,checkout_version:e.checkout_version}}async initializePublicKeyMode(e){if(!e.public_key)throw new Error('Payinto Checkout: public_key is required for mode="public_key".');if(!e.customer?.email)throw new Error('Payinto Checkout: customer.email is required for mode="public_key".');if(!e.amount||e.amount<=0)throw new Error('Payinto Checkout: amount must be greater than zero for mode="public_key".');const t={merchant_reference:e.merchant_reference,amount:e.amount,currency:e.currency,customer:e.customer,redirect_url:e.redirect_url,metadata:e.metadata,settlement_account_id:e.settlement_account_id,checkout_version:e.checkout_version},o=await fetch("https://api.payinto.co/api/v1/checkout/initialize",{method:"POST",headers:{"Content-Type":"application/json",Accept:"application/json",Authorization:`Bearer ${e.public_key}`},body:JSON.stringify(t)});if(!o.ok){const e=(e=>{try{return JSON.parse(e)}catch{return null}})(await o.text());throw new Error(e?.message||"Failed to initialize transaction.")}const n=await o.json(),i=n.data||(n.token&&n.checkout_url?{token:n.token,checkout_url:n.checkout_url,merchant_reference:n.merchant_reference,checkout_version:n.checkout_version}:void 0);if(!i?.token||!i?.checkout_url)throw new Error("Payinto Checkout: invalid initialize response.");return{token:i.token,checkout_url:i.checkout_url,merchant_reference:i.merchant_reference,checkout_version:i.checkout_version}}initializeIframe(e){if(!this.iframe||!this.container)return;const t=this.container.querySelector("#payinto-checkout-subtitle"),o=this.container.querySelector(".payinto-preloader"),n=s(e),i=new URL(n).origin,r=new URL(e.checkout_url).origin,a=Array.from(/* @__PURE__ */new Set([i,r]));if(!c.has(i)&&i!==new URL(e.checkout_url).origin)throw new Error("Payinto Checkout: target origin is not in allowlist.");this.iframe.src=`${n}?updated=${Date.now()}`,this.iframe.onload=()=>{o&&(o.style.display="none"),this.iframe&&(this.iframe.style.opacity="1");const t=()=>{const t={type:"checkout.init",token:e.token,merchant_reference:e.merchant_reference,checkout_url:e.checkout_url};for(const e of a)this.iframe?.contentWindow?.postMessage(t,e)};t(),this.clearInitRetry();let n=0;this.initRetryTimer=window.setInterval(()=>{n+=1,n>=8?this.clearInitRetry():t()},500)},t&&(t.innerText="Loading checkout...")}bindMessageListener(){const e=e=>{if(!c.has(e.origin))return;this.clearInitRetry();const t=e.data;if("object"==typeof t&&"checkout.resize"===t?.type&&this.iframe)this.iframe.style.height=`${Math.max(300,t.height||0)}px`;else{if("object"==typeof t&&"checkout.close"===t?.type)return this.callbacks.onClose?.(),void this.close();if("object"==typeof t&&"checkout.success"===t?.type||"checkout.success"===t){const e="object"==typeof t?t:{type:"checkout.success",status:"success"};return this.callbacks.onSuccess?.(e),this.callbacks.callback?.(e),void this.close()}"object"==typeof t&&"checkout.error"===t?.type&&this.handleError(t)}};this.messageListener=e,window.addEventListener("message",e)}handleError(e){if(this.callbacks.onError?.(e),this.container){const t=this.container.querySelector(".payinto-preloader"),o=this.container.querySelector("#payinto-checkout-subtitle");t&&(t.style.display="flex"),o&&(o.innerText=e.message,o.style.color="#ff4444")}setTimeout(()=>{this.close()},1800)}},l={open:e=>a.open(e),pay:e=>a.pay(e),close:()=>a.close()},h=e=>{a.open(e)};h.open=e=>a.open(e),h.pay=e=>a.pay(e),h.close=()=>a.close(),e&&(window.PayintoCheckout=h);export{l as PayintoCheckoutApi,l as default};
@@ -1 +1 @@
1
- var PayintoCheckout=function(e){"use strict";const t="undefined"!=typeof window,o=t?"https://checkout.payinto.co":"",n="/v1".replace(/\/+$/,""),i=`${o}${n}/popup`,r="https://checkout.payinto.co,https://go.payinto.co".split(",").map(e=>e.trim()).filter(Boolean),c=t?new URL(i).origin:"",s=new Set([c,...r]),a=e=>{try{const t=new URL(e.checkout_url),o=e.checkout_version||(e=>{try{const t=new URL(e).pathname.split("/").filter(Boolean)[0];return/^v[0-9]+$/i.test(t||"")?t:void 0}catch{return}})(e.checkout_url);return o?`${t.origin}/${o}/popup`:`${t.origin}/popup`}catch{return i}};const l=new class{container=null;iframe=null;messageListener=null;callbacks={};initRetryTimer=null;open(e){const t=(e=>{if("token"===e.mode)return e;if("public_key"===e.mode)return e;throw new Error('Payinto Checkout: invalid options. Provide a valid mode ("token" or "public_key").')})(e);this.container&&this.close(),this.callbacks={onClose:t.onClose,onSuccess:t.onSuccess,onError:t.onError,callback:t.callback},this.mountOverlay();(async()=>{try{const e="token"===t.mode?this.validateTokenMode(t):await this.initializePublicKeyMode(t);this.bindMessageListener(),this.initializeIframe(e)}catch(e){const t=e instanceof Error?e.message:"Unable to initialize checkout.";this.handleError({type:"checkout.error",code:"initialization_failed",message:t})}})()}pay(e){this.open(e)}close=()=>{this.clearInitRetry(),this.messageListener&&(window.removeEventListener("message",this.messageListener),this.messageListener=null),this.container&&document.body.contains(this.container)&&document.body.removeChild(this.container),this.container=null,this.iframe=null,document.body.classList.remove("payinto-checkout-open")};clearInitRetry(){null!==this.initRetryTimer&&(window.clearInterval(this.initRetryTimer),this.initRetryTimer=null)}mountOverlay(){const e=document.createElement("div");e.id="payinto-checkout-container",e.style.position="fixed",e.style.top="0",e.style.left="0",e.style.right="0",e.style.bottom="0",e.style.width="100%",e.style.minHeight="100vh",e.style.height="100%",e.style.backgroundColor="rgba(0, 0, 0, 0.85)",e.style.zIndex="9999",e.style.display="flex",e.style.alignItems="flex-start",e.style.justifyContent="center",e.style.overflowY="auto",e.style.paddingTop="6rem",e.style.paddingBottom="2rem",e.style.boxSizing="border-box";const t=document.createElement("div");t.className="payinto-preloader",t.style.display="flex",t.style.flexDirection="column",t.style.alignItems="center",t.style.justifyContent="center",t.style.position="absolute",t.style.top="6rem",t.style.left="50%",t.style.transform="translateX(-50%)",t.style.width="100%",t.style.maxWidth="650px",t.style.padding="4rem 0",t.style.zIndex="10",t.style.fontFamily="system-ui, -apple-system, sans-serif";const o=document.createElement("div");o.style.width="40px",o.style.height="40px",o.style.borderRadius="50%",o.style.border="2px solid transparent",o.style.borderBottom="2px solid #ffffff",o.style.marginBottom="16px",o.style.animation="spin 1s linear infinite";const n=document.createElement("p");n.id="payinto-checkout-subtitle",n.innerText="Initializing Secure Checkout...",n.style.fontSize="12px",n.style.color="#e5e7eb",n.style.margin="0",t.appendChild(o),t.appendChild(n),e.appendChild(t);const r=document.createElement("iframe");if(r.src=i,r.style.width="100%",r.style.maxWidth="650px",r.style.height="auto",r.style.border="none",r.style.backgroundColor="transparent",r.style.opacity="0",r.style.transition="opacity 0.25s ease",r.allow="payment; clipboard-read; clipboard-write",e.appendChild(r),!document.getElementById("payinto-checkout-styles")){const e=document.createElement("style");e.id="payinto-checkout-styles",e.innerHTML="\n @keyframes spin { 0% { transform: rotate(0deg); } 100% { transform: rotate(360deg); } }\n body.payinto-checkout-open { overflow: hidden !important; }\n @media (max-width: 767px) {\n #payinto-checkout-container {\n position: fixed !important;\n top: 0 !important;\n left: 0 !important;\n right: 0 !important;\n bottom: 0 !important;\n height: 100% !important;\n min-height: 100vh !important;\n overflow-y: auto !important;\n padding-top: 0 !important;\n padding-bottom: 0 !important;\n }\n .payinto-preloader { top: 2rem !important; }\n }\n ",document.head.appendChild(e)}document.body.appendChild(e),document.body.classList.add("payinto-checkout-open"),this.container=e,this.iframe=r}validateTokenMode(e){if(!e.token||"string"!=typeof e.token)throw new Error('Payinto Checkout: token is required for mode="token".');if(!e.checkout_url||"string"!=typeof e.checkout_url)throw new Error('Payinto Checkout: checkout_url is required for mode="token".');if(!new URL(e.checkout_url).origin)throw new Error("Payinto Checkout: invalid checkout_url.");return{token:e.token,checkout_url:e.checkout_url,merchant_reference:e.merchant_reference,checkout_version:e.checkout_version}}async initializePublicKeyMode(e){if(!e.public_key)throw new Error('Payinto Checkout: public_key is required for mode="public_key".');if(!e.customer?.email)throw new Error('Payinto Checkout: customer.email is required for mode="public_key".');if(!e.amount||e.amount<=0)throw new Error('Payinto Checkout: amount must be greater than zero for mode="public_key".');const t={merchant_reference:e.merchant_reference,amount:e.amount,currency:e.currency,customer:e.customer,redirect_url:e.redirect_url,metadata:e.metadata,checkout_version:e.checkout_version},o=await fetch("https://api.payinto.co/api/v1/checkout/initialize",{method:"POST",headers:{"Content-Type":"application/json",Accept:"application/json",Authorization:`Bearer ${e.public_key}`},body:JSON.stringify(t)});if(!o.ok){const e=(e=>{try{return JSON.parse(e)}catch{return null}})(await o.text());throw new Error(e?.message||"Failed to initialize transaction.")}const n=await o.json(),i=n.data||(n.token&&n.checkout_url?{token:n.token,checkout_url:n.checkout_url,merchant_reference:n.merchant_reference,checkout_version:n.checkout_version}:void 0);if(!i?.token||!i?.checkout_url)throw new Error("Payinto Checkout: invalid initialize response.");return{token:i.token,checkout_url:i.checkout_url,merchant_reference:i.merchant_reference,checkout_version:i.checkout_version}}initializeIframe(e){if(!this.iframe||!this.container)return;const t=this.container.querySelector("#payinto-checkout-subtitle"),o=this.container.querySelector(".payinto-preloader"),n=a(e),i=new URL(n).origin,r=new URL(e.checkout_url).origin,c=Array.from(new Set([i,r]));if(!s.has(i)&&i!==new URL(e.checkout_url).origin)throw new Error("Payinto Checkout: target origin is not in allowlist.");this.iframe.src=`${n}?updated=${Date.now()}`,this.iframe.onload=()=>{o&&(o.style.display="none"),this.iframe&&(this.iframe.style.opacity="1");const t=()=>{const t={type:"checkout.init",token:e.token,merchant_reference:e.merchant_reference,checkout_url:e.checkout_url};for(const e of c)this.iframe?.contentWindow?.postMessage(t,e)};t(),this.clearInitRetry();let n=0;this.initRetryTimer=window.setInterval(()=>{n+=1,n>=8?this.clearInitRetry():t()},500)},t&&(t.innerText="Loading checkout...")}bindMessageListener(){const e=e=>{if(!s.has(e.origin))return;this.clearInitRetry();const t=e.data;if("object"==typeof t&&"checkout.resize"===t?.type&&this.iframe)this.iframe.style.height=`${Math.max(300,t.height||0)}px`;else{if("object"==typeof t&&"checkout.close"===t?.type)return this.callbacks.onClose?.(),void this.close();if("object"==typeof t&&"checkout.success"===t?.type||"checkout.success"===t){const e="object"==typeof t?t:{type:"checkout.success",status:"success"};return this.callbacks.onSuccess?.(e),this.callbacks.callback?.(e),void this.close()}"object"==typeof t&&"checkout.error"===t?.type&&this.handleError(t)}};this.messageListener=e,window.addEventListener("message",e)}handleError(e){if(this.callbacks.onError?.(e),this.container){const t=this.container.querySelector(".payinto-preloader"),o=this.container.querySelector("#payinto-checkout-subtitle");t&&(t.style.display="flex"),o&&(o.innerText=e.message,o.style.color="#ff4444")}setTimeout(()=>{this.close()},1800)}},u={open:e=>l.open(e),pay:e=>l.pay(e),close:()=>l.close()},h=e=>{l.open(e)};return h.open=e=>l.open(e),h.pay=e=>l.pay(e),h.close=()=>l.close(),t&&(window.PayintoCheckout=h),e.PayintoCheckoutApi=u,e.default=u,Object.defineProperties(e,{__esModule:{value:!0},[Symbol.toStringTag]:{value:"Module"}}),e}({});
1
+ var PayintoCheckoutBundle=function(e){"use strict";const t="undefined"!=typeof window,o=t?"https://checkout.payinto.co":"",n="/v1".replace(/\/+$/,""),i=`${o}${n}/popup`,r="https://checkout.payinto.co,https://go.payinto.co".split(",").map(e=>e.trim()).filter(Boolean),c=t?new URL(i).origin:"",s=new Set([c,...r]),a=e=>{try{const t=new URL(e.checkout_url),o=e.checkout_version||(e=>{try{const t=new URL(e).pathname.split("/").filter(Boolean)[0];return/^v[0-9]+$/i.test(t||"")?t:void 0}catch{return}})(e.checkout_url);return o?`${t.origin}/${o}/popup`:`${t.origin}/popup`}catch{return i}};const l=new class{container=null;iframe=null;messageListener=null;callbacks={};initRetryTimer=null;open(e){const t=(e=>{if("token"===e.mode)return e;if("public_key"===e.mode)return e;throw new Error('Payinto Checkout: invalid options. Provide a valid mode ("token" or "public_key").')})(e);this.container&&this.close(),this.callbacks={onClose:t.onClose,onSuccess:t.onSuccess,onError:t.onError,callback:t.callback},this.mountOverlay();(async()=>{try{const e="token"===t.mode?this.validateTokenMode(t):await this.initializePublicKeyMode(t);this.bindMessageListener(),this.initializeIframe(e)}catch(e){const t=e instanceof Error?e.message:"Unable to initialize checkout.";this.handleError({type:"checkout.error",code:"initialization_failed",message:t})}})()}pay(e){this.open(e)}close=()=>{this.clearInitRetry(),this.messageListener&&(window.removeEventListener("message",this.messageListener),this.messageListener=null),this.container&&document.body.contains(this.container)&&document.body.removeChild(this.container),this.container=null,this.iframe=null,document.body.classList.remove("payinto-checkout-open")};clearInitRetry(){null!==this.initRetryTimer&&(window.clearInterval(this.initRetryTimer),this.initRetryTimer=null)}mountOverlay(){const e=document.createElement("div");e.id="payinto-checkout-container",e.style.position="fixed",e.style.top="0",e.style.left="0",e.style.right="0",e.style.bottom="0",e.style.width="100%",e.style.minHeight="100vh",e.style.height="100%",e.style.backgroundColor="rgba(0, 0, 0, 0.85)",e.style.zIndex="9999",e.style.display="flex",e.style.alignItems="flex-start",e.style.justifyContent="center",e.style.overflowY="auto",e.style.paddingTop="6rem",e.style.paddingBottom="2rem",e.style.boxSizing="border-box";const t=document.createElement("div");t.className="payinto-preloader",t.style.display="flex",t.style.flexDirection="column",t.style.alignItems="center",t.style.justifyContent="center",t.style.position="absolute",t.style.top="6rem",t.style.left="50%",t.style.transform="translateX(-50%)",t.style.width="100%",t.style.maxWidth="720px",t.style.padding="4rem 0",t.style.zIndex="10",t.style.fontFamily="system-ui, -apple-system, sans-serif";const o=document.createElement("div");o.style.width="40px",o.style.height="40px",o.style.borderRadius="50%",o.style.border="2px solid transparent",o.style.borderBottom="2px solid #ffffff",o.style.marginBottom="16px",o.style.animation="spin 1s linear infinite";const n=document.createElement("p");n.id="payinto-checkout-subtitle",n.innerText="Initializing Secure Checkout...",n.style.fontSize="12px",n.style.color="#e5e7eb",n.style.margin="0",t.appendChild(o),t.appendChild(n),e.appendChild(t);const r=document.createElement("iframe");if(r.src=i,r.style.width="100%",r.style.maxWidth="720px",r.style.height="auto",r.style.border="none",r.style.backgroundColor="transparent",r.style.opacity="0",r.style.transition="opacity 0.25s ease",r.allow="payment; clipboard-read; clipboard-write",e.appendChild(r),!document.getElementById("payinto-checkout-styles")){const e=document.createElement("style");e.id="payinto-checkout-styles",e.innerHTML="\n @keyframes spin { 0% { transform: rotate(0deg); } 100% { transform: rotate(360deg); } }\n body.payinto-checkout-open { overflow: hidden !important; }\n @media (max-width: 767px) {\n #payinto-checkout-container {\n position: fixed !important;\n top: 0 !important;\n left: 0 !important;\n right: 0 !important;\n bottom: 0 !important;\n height: 100% !important;\n min-height: 100vh !important;\n overflow-y: auto !important;\n padding-top: 0 !important;\n padding-bottom: 0 !important;\n }\n .payinto-preloader { top: 2rem !important; }\n }\n ",document.head.appendChild(e)}document.body.appendChild(e),document.body.classList.add("payinto-checkout-open"),this.container=e,this.iframe=r}validateTokenMode(e){if(!e.token||"string"!=typeof e.token)throw new Error('Payinto Checkout: token is required for mode="token".');if(!e.checkout_url||"string"!=typeof e.checkout_url)throw new Error('Payinto Checkout: checkout_url is required for mode="token".');if(!new URL(e.checkout_url).origin)throw new Error("Payinto Checkout: invalid checkout_url.");return{token:e.token,checkout_url:e.checkout_url,merchant_reference:e.merchant_reference,checkout_version:e.checkout_version}}async initializePublicKeyMode(e){if(!e.public_key)throw new Error('Payinto Checkout: public_key is required for mode="public_key".');if(!e.customer?.email)throw new Error('Payinto Checkout: customer.email is required for mode="public_key".');if(!e.amount||e.amount<=0)throw new Error('Payinto Checkout: amount must be greater than zero for mode="public_key".');const t={merchant_reference:e.merchant_reference,amount:e.amount,currency:e.currency,customer:e.customer,redirect_url:e.redirect_url,metadata:e.metadata,settlement_account_id:e.settlement_account_id,checkout_version:e.checkout_version},o=await fetch("https://api.payinto.co/api/v1/checkout/initialize",{method:"POST",headers:{"Content-Type":"application/json",Accept:"application/json",Authorization:`Bearer ${e.public_key}`},body:JSON.stringify(t)});if(!o.ok){const e=(e=>{try{return JSON.parse(e)}catch{return null}})(await o.text());throw new Error(e?.message||"Failed to initialize transaction.")}const n=await o.json(),i=n.data||(n.token&&n.checkout_url?{token:n.token,checkout_url:n.checkout_url,merchant_reference:n.merchant_reference,checkout_version:n.checkout_version}:void 0);if(!i?.token||!i?.checkout_url)throw new Error("Payinto Checkout: invalid initialize response.");return{token:i.token,checkout_url:i.checkout_url,merchant_reference:i.merchant_reference,checkout_version:i.checkout_version}}initializeIframe(e){if(!this.iframe||!this.container)return;const t=this.container.querySelector("#payinto-checkout-subtitle"),o=this.container.querySelector(".payinto-preloader"),n=a(e),i=new URL(n).origin,r=new URL(e.checkout_url).origin,c=Array.from(new Set([i,r]));if(!s.has(i)&&i!==new URL(e.checkout_url).origin)throw new Error("Payinto Checkout: target origin is not in allowlist.");this.iframe.src=`${n}?updated=${Date.now()}`,this.iframe.onload=()=>{o&&(o.style.display="none"),this.iframe&&(this.iframe.style.opacity="1");const t=()=>{const t={type:"checkout.init",token:e.token,merchant_reference:e.merchant_reference,checkout_url:e.checkout_url};for(const e of c)this.iframe?.contentWindow?.postMessage(t,e)};t(),this.clearInitRetry();let n=0;this.initRetryTimer=window.setInterval(()=>{n+=1,n>=8?this.clearInitRetry():t()},500)},t&&(t.innerText="Loading checkout...")}bindMessageListener(){const e=e=>{if(!s.has(e.origin))return;this.clearInitRetry();const t=e.data;if("object"==typeof t&&"checkout.resize"===t?.type&&this.iframe)this.iframe.style.height=`${Math.max(300,t.height||0)}px`;else{if("object"==typeof t&&"checkout.close"===t?.type)return this.callbacks.onClose?.(),void this.close();if("object"==typeof t&&"checkout.success"===t?.type||"checkout.success"===t){const e="object"==typeof t?t:{type:"checkout.success",status:"success"};return this.callbacks.onSuccess?.(e),this.callbacks.callback?.(e),void this.close()}"object"==typeof t&&"checkout.error"===t?.type&&this.handleError(t)}};this.messageListener=e,window.addEventListener("message",e)}handleError(e){if(this.callbacks.onError?.(e),this.container){const t=this.container.querySelector(".payinto-preloader"),o=this.container.querySelector("#payinto-checkout-subtitle");t&&(t.style.display="flex"),o&&(o.innerText=e.message,o.style.color="#ff4444")}setTimeout(()=>{this.close()},1800)}},u={open:e=>l.open(e),pay:e=>l.pay(e),close:()=>l.close()},h=e=>{l.open(e)};return h.open=e=>l.open(e),h.pay=e=>l.pay(e),h.close=()=>l.close(),t&&(window.PayintoCheckout=h),e.PayintoCheckoutApi=u,e.default=u,Object.defineProperties(e,{__esModule:{value:!0},[Symbol.toStringTag]:{value:"Module"}}),e}({});
package/dist/v1/demo.html CHANGED
@@ -44,12 +44,51 @@
44
44
  font-size: 14px;
45
45
  }
46
46
 
47
- .button-group {
48
- display: flex;
49
- flex-direction: column;
47
+ form {
48
+ display: grid;
49
+ gap: 16px;
50
+ }
51
+
52
+ .field-grid {
53
+ display: grid;
54
+ grid-template-columns: 1fr 1fr;
50
55
  gap: 12px;
51
56
  }
52
57
 
58
+ label {
59
+ display: grid;
60
+ gap: 6px;
61
+ color: #4a5568;
62
+ font-size: 12px;
63
+ font-weight: 700;
64
+ }
65
+
66
+ input,
67
+ select,
68
+ textarea {
69
+ width: 100%;
70
+ border: 1px solid #cbd5e0;
71
+ border-radius: 8px;
72
+ padding: 12px;
73
+ color: #1a202c;
74
+ font: inherit;
75
+ font-size: 14px;
76
+ outline: none;
77
+ transition: border-color 0.2s, box-shadow 0.2s;
78
+ }
79
+
80
+ input:focus,
81
+ select:focus,
82
+ textarea:focus {
83
+ border-color: #1a202c;
84
+ box-shadow: 0 0 0 3px rgba(26, 32, 44, 0.12);
85
+ }
86
+
87
+ textarea {
88
+ min-height: 82px;
89
+ resize: vertical;
90
+ }
91
+
53
92
  button {
54
93
  background: #1a202c;
55
94
  color: white;
@@ -72,6 +111,16 @@
72
111
  transform: translateY(0);
73
112
  }
74
113
 
114
+ .form-error {
115
+ display: none;
116
+ padding: 10px 12px;
117
+ border-radius: 8px;
118
+ background: #fff5f5;
119
+ color: #c53030;
120
+ font-size: 13px;
121
+ font-weight: 600;
122
+ }
123
+
75
124
  .code-block {
76
125
  background: #f7fafc;
77
126
  border: 1px solid #e2e8f0;
@@ -101,6 +150,16 @@
101
150
  text-transform: uppercase;
102
151
  margin-bottom: 16px;
103
152
  }
153
+
154
+ @media (max-width: 560px) {
155
+ .demo-container {
156
+ padding: 24px;
157
+ }
158
+
159
+ .field-grid {
160
+ grid-template-columns: 1fr;
161
+ }
162
+ }
104
163
  </style>
105
164
  </head>
106
165
 
@@ -108,40 +167,78 @@
108
167
  <div class="demo-container">
109
168
  <span class="badge">Demo</span>
110
169
  <h1>Payinto Checkout</h1>
111
- <p>Click the button below to test the payment checkout integration.</p>
170
+ <p>Enter checkout details and launch the local popup integration.</p>
171
+
172
+ <form id="checkout-form">
173
+ <label>
174
+ Public Key
175
+ <input id="public-key" name="public_key" value="pk_live_784683f25db04c05838ee730ce489e27e46e" required>
176
+ </label>
177
+
178
+ <div class="field-grid">
179
+ <label>
180
+ Amount
181
+ <input id="amount" name="amount" type="number" min="1" step="1" value="100000" required>
182
+ </label>
183
+
184
+ <label>
185
+ Currency
186
+ <select id="currency" name="currency">
187
+ <option value="NGN" selected>NGN</option>
188
+ <option value="USD">USD</option>
189
+ <option value="GBP">GBP</option>
190
+ </select>
191
+ </label>
192
+ </div>
193
+
194
+ <label>
195
+ Merchant Reference
196
+ <input id="merchant-reference" name="merchant_reference" value="TRANS_123456" required>
197
+ </label>
112
198
 
113
- <div class="button-group">
114
- <button onclick="openCheckout()">
115
- Pay NGN 10,000
199
+ <label>
200
+ Settlement Account ID
201
+ <input id="settlement-account-id" name="settlement_account_id" placeholder="Optional local accounts.id">
202
+ </label>
203
+
204
+ <div class="field-grid">
205
+ <label>
206
+ Customer Name
207
+ <input id="customer-name" name="customer_name" value="John Doe">
208
+ </label>
209
+
210
+ <label>
211
+ Customer Email
212
+ <input id="customer-email" name="customer_email" type="email" value="john.doe@example.com" required>
213
+ </label>
214
+ </div>
215
+
216
+ <div class="field-grid">
217
+ <label>
218
+ Phone Number
219
+ <input id="phone-number" name="phone_number" value="08123456789">
220
+ </label>
221
+
222
+ <label>
223
+ Redirect URL
224
+ <input id="redirect-url" name="redirect_url" type="url" value="https://example.com/redirect">
225
+ </label>
226
+ </div>
227
+
228
+ <label>
229
+ Metadata JSON
230
+ <textarea id="metadata" name="metadata">{"custom_field":"custom_value"}</textarea>
231
+ </label>
232
+
233
+ <div id="form-error" class="form-error"></div>
234
+
235
+ <button type="submit">
236
+ Open Checkout
116
237
  </button>
117
- </div>
238
+ </form>
118
239
 
119
240
  <div class="code-block">
120
- <pre>PayintoCheckout({
121
- mode: 'public_key',
122
- public_key: 'pk_test_123456789',
123
- merchant_reference: 'TRANS_123456',
124
- amount: 100000,
125
- currency: 'NGN',
126
- customer: {
127
- email: 'customer@example.com',
128
- name: 'John Doe',
129
- phone_number: '08123456789'
130
- },
131
- metadata: {
132
- custom_field: 'custom_value'
133
- },
134
- // With Redirect URL to redirect to after payment
135
- redirect_url: 'https://example.com/redirect', // URL
136
- // OR Alternatively, you can specify a callback function to handle payment response
137
- onClose: function () {
138
- console.log('Checkout closed');
139
- },
140
- callback: function (response) {
141
- console.log('Payment successful:', response);
142
- }
143
-
144
- });</pre>
241
+ <pre id="payload-preview"></pre>
145
242
  </div>
146
243
  </div>
147
244
 
@@ -149,31 +246,95 @@
149
246
  <script src="/checkout.js"></script>
150
247
 
151
248
  <script>
152
- function openCheckout() {
153
- PayintoCheckout({
249
+ const form = document.getElementById('checkout-form');
250
+ const errorBox = document.getElementById('form-error');
251
+ const payloadPreview = document.getElementById('payload-preview');
252
+
253
+ function setError(message) {
254
+ errorBox.textContent = message;
255
+ errorBox.style.display = message ? 'block' : 'none';
256
+ }
257
+
258
+ function getMetadata() {
259
+ const value = document.getElementById('metadata').value.trim();
260
+ if (!value) return {};
261
+
262
+ try {
263
+ return JSON.parse(value);
264
+ } catch {
265
+ throw new Error('Metadata must be valid JSON.');
266
+ }
267
+ }
268
+
269
+ function getCheckoutPayload() {
270
+ const settlementAccountId = document.getElementById('settlement-account-id').value.trim();
271
+ const payload = {
154
272
  mode: 'public_key',
155
- public_key: 'pk_live_784683f25db04c05838ee730ce489e27e46e', // Example public key
156
- merchant_reference: 'TRANS_123456',
157
- amount: 100000,
158
- currency: 'NGN',
273
+ public_key: document.getElementById('public-key').value.trim(),
274
+ merchant_reference: document.getElementById('merchant-reference').value.trim(),
275
+ amount: Number(document.getElementById('amount').value),
276
+ currency: document.getElementById('currency').value,
159
277
  customer: {
160
- name: 'John Doe',
161
- email: 'john.doe@example.com',
162
- phone_number: '08123456789'
163
- },
164
- redirect_url: 'https://example.com/redirect',
165
- metadata: {
166
- custom_field: 'custom_value'
278
+ name: document.getElementById('customer-name').value.trim(),
279
+ email: document.getElementById('customer-email').value.trim(),
280
+ phone_number: document.getElementById('phone-number').value.trim()
167
281
  },
282
+ redirect_url: document.getElementById('redirect-url').value.trim(),
283
+ metadata: getMetadata()
284
+ };
285
+ if (settlementAccountId) {
286
+ payload.settlement_account_id = settlementAccountId;
287
+ }
288
+ return payload;
289
+ }
290
+
291
+ function updatePayloadPreview() {
292
+ try {
293
+ const payload = getCheckoutPayload();
294
+ payloadPreview.textContent = `PayintoCheckout(${JSON.stringify(payload, null, 4).replace(/\n/g, '\n ')});
295
+
296
+ // callbacks are attached by the demo:
297
+ // onClose, onError, callback`;
298
+ } catch {
299
+ payloadPreview.textContent = 'Metadata must be valid JSON to preview the payload.';
300
+ }
301
+ }
302
+
303
+ form.addEventListener('input', updatePayloadPreview);
304
+ updatePayloadPreview();
305
+
306
+ form.addEventListener('submit', function (event) {
307
+ event.preventDefault();
308
+ setError('');
309
+
310
+ let payload;
311
+ try {
312
+ payload = getCheckoutPayload();
313
+ } catch (error) {
314
+ setError(error.message);
315
+ return;
316
+ }
317
+
318
+ if (!Number.isFinite(payload.amount) || payload.amount <= 0) {
319
+ setError('Amount must be greater than zero.');
320
+ return;
321
+ }
322
+
323
+ PayintoCheckout({
324
+ ...payload,
168
325
  onClose: function () {
169
326
  console.log('Checkout closed');
170
327
  },
328
+ onError: function (error) {
329
+ console.error('Checkout error:', error);
330
+ setError(error.message || 'Checkout failed to initialize.');
331
+ },
171
332
  callback: function (response) {
172
333
  console.log('Payment successful:', response);
173
334
  // alert('Payment successful! ' + JSON.stringify(response));
174
335
  }
175
336
  });
176
- }
337
+ });
177
338
  </script>
178
339
  </body>
179
340
 
@@ -36,6 +36,7 @@ type PublicKeyModeOptions = CheckoutCallbacks & {
36
36
  };
37
37
  redirect_url?: string;
38
38
  metadata?: Record<string, unknown>;
39
+ settlement_account_id?: string;
39
40
  checkout_version?: string;
40
41
  };
41
42
  export type CheckoutOpenOptions = TokenModeOptions | PublicKeyModeOptions;
package/package.json CHANGED
@@ -1,8 +1,8 @@
1
1
  {
2
2
  "name": "@payinto/checkout-sdk",
3
- "version": "1.1.0",
3
+ "version": "1.3.0",
4
4
  "type": "module",
5
- "description": "Payinto Checkout SDK for popup payments (token and public_key modes)",
5
+ "description": "Payinto Checkout SDK for popup payments",
6
6
  "main": "./dist/v1/checkout.es.js",
7
7
  "module": "./dist/v1/checkout.es.js",
8
8
  "types": "./dist/v1/types/checkout-sdk.d.ts",