UNPKG

react-tap-payment

Version:

ReactJS library for implementing TAP payment gateway

430 lines (416 loc) 15.3 kB
'use strict'; var React = require('react'); /****************************************************************************** Copyright (c) Microsoft Corporation. Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted. THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ***************************************************************************** */ /* global Reflect, Promise, SuppressedError, Symbol, Iterator */ var __assign = function() { __assign = Object.assign || function __assign(t) { for (var s, i = 1, n = arguments.length; i < n; i++) { s = arguments[i]; for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p)) t[p] = s[p]; } return t; }; return __assign.apply(this, arguments); }; function __rest(s, e) { var t = {}; for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0) t[p] = s[p]; if (s != null && typeof Object.getOwnPropertySymbols === "function") for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) { if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i])) t[p[i]] = s[p[i]]; } return t; } typeof SuppressedError === "function" ? SuppressedError : function (error, suppressed, message) { var e = new Error(message); return e.name = "SuppressedError", e.error = error, e.suppressed = suppressed, e; }; 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 = false, this.isIframeOpen = false, this.transactionDefaults = t, this.checkoutLoaded = false, this.checkoutRemoved = false, 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); }, false ); } /** * 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 = true); } /** * 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 = false) { this.background.style.opacity = 0, this.iframe.style.display = "none", this.iframe.contentWindow.postMessage("close", "*"), this.isIframeOpen = false, 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 = false, this.messageHandler = null), this.iframe && (this.iframe.remove(), this.iframe = null), this.background && (this.background.remove(), this.background = null), this.iframeLoaded = false, this.isIframeOpen = false, this.checkoutRemoved = true; } } let o; const r = { isInitialized: false, initialize(e) { o = new u(e), this.isInitialized = true; }, 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 || false, 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 = false; } }; 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 true; } 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; } @keyframes spin { to { transform: rotate(360deg); } } </style> </head> <body> <div class="loader" id="app-loader"></div> </body> </html> `; } var callTAPPaymentPop = function (tapPaymentArgs) { var handler = r.setup(tapPaymentArgs); handler.openIframe(); }; function useTAPPayment(hookConfig) { function initializePayment(_a) { var config = _a.config, onSuccess = _a.onSuccess, onClose = _a.onClose; var args = __assign(__assign({}, hookConfig), config); var apiKey = args.apiKey, amount = args.amount, transID = args.transID, firstname = args.firstname, lastname = args.lastname, phone = args.phone, email = args.email, env = args.env, savePaymentDetails = args.savePaymentDetails, customerReference = args.customerReference, billerID = args.billerID, productID = args.productID, metadata = args.metadata, label = args.label, quantity = args.quantity, rest = __rest(args, ["apiKey", "amount", "transID", "firstname", "lastname", "phone", "email", "env", "savePaymentDetails", "customerReference", "billerID", "productID", "metadata", "label", "quantity"]); var tapPaymentArgs = { callback: onSuccess ? onSuccess : function () { return null; }, onClose: onClose ? onClose : function () { return null; }, apiKey: apiKey, transID: transID, email: email, amount: amount, env: env, phone: phone !== null && phone !== void 0 ? phone : undefined, savePaymentDetails: savePaymentDetails !== null && savePaymentDetails !== void 0 ? savePaymentDetails : undefined, customerReference: customerReference !== null && customerReference !== void 0 ? customerReference : undefined, customPayload: __assign(__assign(__assign(__assign(__assign(__assign(__assign(__assign(__assign(__assign({}, (firstname && { firstname: firstname })), (lastname && { lastname: lastname })), (email && { email: email })), (phone && { phone: phone })), (billerID && { billerID: billerID })), (productID && { productID: productID })), (metadata && { metadata: metadata })), (label && { label: label })), (quantity && { quantity: quantity })), (rest && __assign({}, rest))) }; callTAPPaymentPop(tapPaymentArgs); } return initializePayment; } var TAPPaymentButton = function (_a) { var text = _a.text, className = _a.className, children = _a.children, onSuccess = _a.onSuccess, onClose = _a.onClose, disabled = _a.disabled, config = __rest(_a, ["text", "className", "children", "onSuccess", "onClose", "disabled"]); var initializePayment = useTAPPayment(config); return (React.createElement("button", { className: className, onClick: function () { return initializePayment({ config: config, onSuccess: onSuccess, onClose: onClose }); }, disabled: disabled }, text || children)); }; exports.TAPPaymentButton = TAPPaymentButton; exports.useTAPPayment = useTAPPayment; //# sourceMappingURL=index.js.map