UNPKG

equal-angular-pfm-sdk

Version:

Equal PFM Angular SDK

228 lines (207 loc) 8.7 kB
/** * @typedef {Object} SDKCallbackData * @property {string} eventType - Type of event ('PFM_SDK_CALLBACK', 'EQUAL_SDK_CALLBACK', etc.) * @property {string} status - Status of the event ('ON_CLOSE', 'ERROR', etc.) * @property {string} [statusCode] - Status code for error events * @property {string} message - Message associated with the event * @property {string} [transaction_id] - Optional transaction ID * @property {string} [url] - Optional URL for navigation events */ /** * @typedef {function(SDKCallbackData): void} SDKCallback - Callback function for SDK events */ var equalCloseEvent; var equalErrorEvent; var win; var clientViewPort; var intervalID; const _PFM_APP_URL = { "prod": "https://pfm.equal.in", "uat": "https://uat.pfm.equal.in", } /** * Checks if the device is running iOS * @returns {boolean} True if the device is running iOS, false otherwise * @private */ const _isIOSMobile = () => { if (navigator.userAgent.match(/iPhone/i) || navigator.userAgent.match(/iPad/i) || navigator.userAgent.match(/iPod/i)) { return true; } else { return false; } }; /** * Checks if the device is a mobile device * @returns {boolean} True if the device is mobile, false otherwise * @private */ const _isMobileDevice = () => { if (navigator.userAgent.match(/Android/i) || navigator.userAgent.match(/webOS/i) || navigator.userAgent.match(/iPhone/i) || navigator.userAgent.match(/iPad/i) || navigator.userAgent.match(/iPod/i) || navigator.userAgent.match(/BlackBerry/i) || navigator.userAgent.match(/Windows Phone/i)) { return true; } else { return false; } }; /** * Personal Finance Management SDK * @constructor * @param {string} token - Authentication token * @param {string} env - Environment ('uat' or 'production') */ function PFMSDK(token, env) { let equalDomain = _PFM_APP_URL.uat; if (token && env) { if (env.startsWith("production")) { equalDomain = _PFM_APP_URL.prod; } } /** * Handles error messages and triggers callbacks * @param {SDKCallback} callBack - Callback for the error event * @param {string} statusCode - Error status code * @param {string} errorMessage - Error message */ this.onErrorMessage = (callBack, statusCode, errorMessage) => { if (callBack != null) { callBack({ 'eventType': 'PFM_SDK_CALLBACK', 'status': 'ERROR', 'statusCode': statusCode, 'message': errorMessage }); } if (equalErrorEvent != null) { equalErrorEvent({ 'eventType': 'PFM_SDK_CALLBACK', 'status': 'ERROR', 'statusCode': statusCode, 'message': errorMessage }); } } /** * Opens the PFM interface * @param {SDKCallback} onErrorEvent - Callback for error events * @param {SDKCallback} onCloseEvent - Callback for close events * @returns {Promise<void>} */ this.openPFM = async (onErrorEvent, onCloseEvent) => { if (_isMobileDevice()) { this.addMobileViewPort(); } equalErrorEvent = onErrorEvent; equalCloseEvent = onCloseEvent; this.openPFMSDK(null); } /** * Adds mobile viewport meta tag */ this.addMobileViewPort = () => { clientViewPort = document.querySelector("[name='viewport']"); if (clientViewPort != null) { document.querySelector("[name='viewport']").remove(); } var metaTag = document.createElement("meta"); metaTag.id = 'equal-viewport'; metaTag.name = "viewport"; metaTag.content = "width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=0"; document.getElementsByTagName("head")[0].appendChild(metaTag); } /** * Opens the PFM SDK iframe or popup * @param {SDKCallback} callBack - Callback for SDK events * @returns {Promise<void>} */ this.openPFMSDK = async (callBack) => { if (token == null) { let event = { 'eventType': 'PFM_SDK_CALLBACK', 'status': 'INVALID_SESSION_TOKEN', 'statusCode': "UNKNOWN", 'message': 'INVALID_SESSION_TOKEN' }; equalErrorEvent(event); window.postMessage(event); return; } const iframeUrl = equalDomain + "/pfm?access_token=" + token; this.equalRootView = document.createElement('div'); this.equalRootView.id = 'equal-modal'; this.equalRootView.setAttribute("style", "z-index:1500; display:block; padding-top:100px; position:fixed; left:0; top:0; width:100%; height:100%; overflow:auto; background-color:rgb(0,0,0); background-color:rgba(0,0,0,0.4)"); var div = document.createElement('div'); div.id = 'loading'; let width = '480px'; let height = '95%'; if (_isMobileDevice()) { height = '99%' width = '99%'; } else { width = '99%'; height = '99%' } if (_isIOSMobile()) { if ('visualViewport' in window) { const VIEWPORT_VS_CLIENT_HEIGHT_RATIO = 0.75; window.visualViewport.addEventListener('resize', function (event) { if ((event.target.height * event.target.scale) / window.screen.height < VIEWPORT_VS_CLIENT_HEIGHT_RATIO) { eIframe.contentWindow.postMessage({ 'eventType': 'EQUAL_KEYBOARD_EVENT', 'status': 'OPEN', 'height': (window.outerHeight - window.innerHeight) + 0 }, '*'); } else { eIframe.contentWindow.postMessage({ 'eventType': 'EQUAL_KEYBOARD_EVENT', 'status': 'CLOSED' }, '*'); } }); } } div.setAttribute("style", "position: fixed; left: 50%; top: 50%; transform: translate(-50%, -50%); height: " + height + "; width: " + width + "; background: #ffffff; overflow: hidden; border-radius: 8px; cursor: pointer; box-shadow: 0 0 8px 8px rgb(0 0 0 / 10%);"); var eIframe = document.createElement("iframe"); eIframe.id = "pfmIframe" eIframe.setAttribute("src", iframeUrl); eIframe.setAttribute("style", "height: 100%; width: 100%;"); eIframe.setAttribute("sandbox", "allow-same-origin allow-scripts allow-forms allow-popups"); eIframe.setAttribute("frameBorder", "0"); div.appendChild(eIframe); this.equalRootView.appendChild(div); document.body.appendChild(this.equalRootView); const messageHandler = (event) => { console.log(event); if (event.data.type === 'EXIT_SDK') { event.data.type = 'PFM_SDK_CALLBACK'; console.log('Iframe URL changed to:', event.data.url); } else return; const url = event.data.url; event.data.url = null; if (win != null) window.clearInterval(intervalID); const uri = new URL(url); const message = uri.searchParams.get('message'); const status_code = uri.searchParams.get('status_code'); const status = uri.searchParams.get('status'); event.data["message"] = message; event.data["status_code"] = status_code; event.data["status"] = status; if (event.data["status"] == "CLOSED") { if (equalCloseEvent != null) equalCloseEvent(event.data); window.postMessage(event.data); } else if (event.data["status"] == "ERROR") { if (equalErrorEvent != null) equalErrorEvent(event.data); window.postMessage(event.data); } if (this.equalRootView != null) { if (document.body.contains(this.equalRootView)) { document.body.removeChild(this.equalRootView); } if (document.querySelector("[id='equal-viewport']") != null) { document.querySelector("[id='equal-viewport']").remove(); } this.equalRootView = null; if (this.messageHandler) { window.removeEventListener('message', this.messageHandler); this.messageHandler = null; } } else if (win != null) { win.close(); } }; window.addEventListener('message', messageHandler); this.messageHandler = messageHandler; } } // Make PFMSDK available for module systems if (typeof module !== 'undefined' && typeof module.exports !== 'undefined') { module.exports = PFMSDK; } else { window.PFMSDK = PFMSDK; }