tap-payment-popupjs
Version:
library for loading TAP's payment checkout gateway.
347 lines (346 loc) • 10.5 kB
JavaScript
const l = {
// checkoutURL: "https://tap-checkout.netlify.app/",
checkoutURL: "https://checkout.touchandpay.me/"
// checkoutURL: "http://localhost:3050/",
};
class u {
constructor(t) {
this.iframe = null, this.background = null, this.iframeLoaded = !1, this.isIframeOpen = !1, this.transactionDefaults = t, this.checkoutLoaded = !1, this.checkoutRemoved = !1, this.fallback = h(), this.initializeCheckout(), this.listenForEvents();
}
/**
* Set new transaction parameters and update the iframe
*/
setTransaction(t) {
this.transactionDefaults && this.resetCheckout(), this.transactionDefaults = t, this.updateIframe();
}
/**
* Initializes the checkout iframe and background
*/
initializeCheckout() {
this.createPopupBackground();
}
/**
* Fetch transaction parameters, excluding unwanted fields
*/
getTransactionParameters() {
if (!this.transactionDefaults)
return null;
this.transactionDefaults.metadata.referrer = v();
const t = [
"customButton",
"onClose",
"callback",
"tlsFallback"
], i = f(this.transactionDefaults, t);
return i.mode = "popup", i.hasTLSFallback = !!this.transactionDefaults.tlsFallback, i.metadata && typeof i.metadata != "string" && (i.metadata = JSON.stringify(i.metadata)), i.split && typeof i.split != "string" && Object.keys(i.split).length > 0 && (i.split = JSON.stringify(i.split)), i;
}
/**
* Updates the iframe content with new transaction details
*/
updateIframe() {
const t = this.getTransactionParameters(), i = t ? "newTransaction" : "popup";
setTimeout(() => {
this.iframe.contentWindow.postMessage(
{
type: "inline:url",
path: i,
params: t
},
"*"
);
}, 3e3);
}
/**
* Listen for events from the iframe
*/
listenForEvents() {
const t = this;
window.addEventListener(
"message",
(i) => {
!t.isEmbed && !t.checkoutRemoved && t.handleCheckoutEvents(i);
},
!1
);
}
/**
* Open the iframe for a new checkout
*/
openIframe() {
this.showCheckout();
}
/**
* Creates the background and iframe for the popup
*/
createPopupBackground() {
const t = document.createElement("iframe");
t.setAttribute("frameBorder", "0"), t.setAttribute("allowtransparency", "true"), t.id = d(), t.name = "checkout-background-" + t.id, t.style.cssText = `
z-index: 999999999999999;
background: rgba(0, 0, 0, 0.75);
border: none;
overflow-x: hidden;
overflow-y: hidden;
position: fixed;
left: 0;
top: 0;
width: 100%;
height: 100%;
visibility: hidden;
display: none;
transition: opacity 0.3s;
`, this.background = t, document.body.appendChild(t);
const i = this.background.contentWindow.document;
i.open(), i.write(P()), i.close();
const n = document.createElement("iframe");
n.setAttribute("frameBorder", "0"), n.setAttribute("allowtransparency", "true"), n.setAttribute("allowpaymentrequest", "true"), n.id = d(), n.name = "checkout-" + n.id, n.style.cssText = `
z-index: 999999999999999;
background: transparent;
border: none;
overflow-x: hidden;
overflow-y: hidden;
position: fixed;
left: 0;
top: 0;
width: 100%;
height: 100%;
visibility: hidden;
display: none;
`, n.src = l.checkoutURL + "popup", this.iframe = n, document.body.appendChild(n);
}
/**
* Opens the checkout iframe and displays the background
*/
showCheckout() {
!this.iframe || this.isIframeOpen || (this.background.style.display = "", this.background.style.visibility = "visible", this.iframe.style.display = "", this.iframe.contentWindow.postMessage("render", "*"), this.isIframeOpen = !0);
}
/**
* Remove the loader once the transaction is loaded
*/
removeLoader() {
this.iframe.style.visibility = "visible";
const t = this.background.contentWindow.document.getElementById("app-loader");
t && (t.style.display = "none");
}
/**
* Handles events received from the iframe, such as success or closing the iframe
*/
handleCheckoutEvents(t) {
if (t.origin + "/" === l.checkoutURL && this.iframe.contentWindow === t.source) {
const i = t.data || t.message;
try {
i && i.response.success.status === 1 && (this.closeCheckout(!0), this.handleSuccess(i));
} catch {
}
switch (i) {
case "loaded:transaction":
this.removeLoader();
break;
case "close":
this.closeCheckout(), this.transactionDefaults.onClose && this.transactionDefaults.onClose.call(this);
break;
}
}
}
/**
* Closes the checkout iframe
*/
closeCheckout(t = !1) {
this.background.style.opacity = 0, this.iframe.style.display = "none", this.iframe.contentWindow.postMessage("close", "*"), this.isIframeOpen = !1, setTimeout(() => {
this.resetBackground();
}, 300);
}
/**
* Resets the iframe and background to initial state
*/
resetCheckout() {
this.resetIframe(), this.resetBackground();
}
/**
* Resets the visibility of the main iframe
*/
resetIframe() {
this.iframe.style.visibility = "hidden", this.transactionDefaults = null, this.updateIframe();
}
/**
* Resets the background and loader
*/
resetBackground() {
this.background.style.display = "none", this.background.style.opacity = 1, this.background.contentWindow.document.getElementById(
"app-loader"
).style.display = "block";
}
/**
* Handles successful transactions
*/
handleSuccess(t) {
this.transactionDefaults.callback && this.transactionDefaults.callback.call(this, t);
}
/**
* Clean up resources
*/
destroy() {
this.messageHandler && this.eventListenerAdded && (window.removeEventListener("message", this.messageHandler), this.eventListenerAdded = !1, this.messageHandler = null), this.iframe && (this.iframe.remove(), this.iframe = null), this.background && (this.background.remove(), this.background = null), this.iframeLoaded = !1, this.isIframeOpen = !1, this.checkoutRemoved = !0;
}
}
let o;
const r = {
isInitialized: !1,
initialize(e) {
o = new u(e), this.isInitialized = !0;
},
setup(e, t) {
const i = {
apiKey: e.apiKey || "",
// required
transID: e.transID || "",
// required
amount: e.amount || "",
// required
email: e.email || "",
// required
env: e.env || "",
phone: e.phone || "",
savePaymentDetails: e.savePaymentDetails || !1,
customerReference: e.customerReference || "",
metadata: e.metadata || {},
onClose: e.onClose || "",
callback: e.callback || "",
tlsFallback: e.tlsFallback || "",
customPayload: {
email: e.email,
...e.customPayload || {}
// Ensure customPayload is an object
}
};
if (m(i) && (this.isInitialized ? o.setTransaction(i) : this.initialize(i), !t))
return o;
},
destroy() {
o && (o.destroy(), o = null), this.isInitialized = !1;
}
};
function c() {
return typeof window < "u" ? window : {};
}
if (typeof c() < "u") {
const e = c();
e.TAPPaymentPop = r, e.onload = () => {
r.isInitialized || r.initialize();
};
}
function d() {
let e = "";
const t = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
for (let i = 0; i < 5; i++)
e += t.charAt(Math.floor(Math.random() * t.length));
return e;
}
function h() {
const e = "onload" in document.createElement("iframe");
return e || console.warn(
"This browser does not support iframes. Please redirect to standard"
), !e;
}
function f(e, t) {
const i = JSON.parse(JSON.stringify(e));
return t.forEach((n) => {
delete i[n];
}), Object.keys(i).forEach((n) => {
(i[n] === null || i[n] === void 0 || i[n].length === 0) && delete i[n];
}), i;
}
function m(e) {
if (p(e), e.apiKey === null)
throw new Error("Please provide your public key via the key attribute");
if (e.amount === null)
throw new Error("Please provide transaction amount via the amount");
if (e.email === null)
throw new Error(
"Please provide customer email via the email or customerCode attribute"
);
if (e.savePaymentDetails) {
if (!e.customerReference)
throw new Error(
"Please provide customerReference when savePaymentDetails is true."
);
if (!e.phone)
throw new Error("Please provide phone when savePaymentDetails is true.");
}
return !0;
}
function p(e) {
const t = {
email: "email",
amount: "integer",
onClose: "function",
callback: "function"
};
for (const s in e)
e.hasOwnProperty(s) && i(s, e[s]);
function i(s, a) {
if (t[s] && a)
switch (t[s]) {
case "email":
y(a) || n(s);
break;
case "integer":
b(a) || n(s);
break;
case "function":
g(a) || n(s);
break;
case "object":
k(a) || n(s);
break;
case "array":
w(a) || n(s);
}
}
function n(s) {
const a = t[s];
throw alert(`Attribute ${s} must be a valid ${a}`), new Error(`Attribute ${s} must be a valid ${a}`);
}
}
function y(e) {
return /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(e);
}
function b(e) {
return /^\d+$/.test(e);
}
function g(e) {
return typeof e == "function";
}
function k(e) {
return e !== null && typeof e == "object";
}
function w(e) {
return Array.isArray(e);
}
function v() {
return window.location.href;
}
function P() {
return `
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Loading...</title>
<style>
* { margin: 0; padding: 0; box-sizing: border-box; }
body { display: flex; justify-content: center; align-items: center; height: 100vh; background: rgba(0, 0, 0, 0.50); }
.loader { width: 50px; height: 50px; border: 5px solid white; border-top-color: transparent; border-radius: 50%; animation: spin 1s linear infinite; }
spin { to { transform: rotate(360deg); } }
</style>
</head>
<body>
<div class="loader" id="app-loader"></div>
</body>
</html>
`;
}
export {
r as TAPPaymentPop
};
//# sourceMappingURL=index.js.map