From ba0db5b2cb2d54c2406ca2315c827f68bd4b917a Mon Sep 17 00:00:00 2001 From: Yaroslav Lapushkin Date: Tue, 21 Nov 2023 11:12:17 +0400 Subject: [PATCH] [XP-3462] Changes for npm publishing --- .gitignore | 2 + js/dist/connect.es.js | 188 +++++++ js/dist/connect.js | 193 +++++++ js/dist/connect.min.js | 1 + js/dist/widget.es.js | 923 +++++++++++++++++++++++++++++++++ js/dist/widget.js | 928 ++++++++++++++++++++++++++++++++++ js/dist/widget.min.js | 1 + js/package-lock.json | 650 ++++++++++++++++++++++++ js/package.json | 28 + js/rollup.config.js | 53 ++ js/{ => src}/connect.js | 4 +- js/{ => src}/widget.js | 4 +- lib/XPaymentsCloud/Client.php | 2 +- 13 files changed, 2974 insertions(+), 3 deletions(-) create mode 100644 .gitignore create mode 100644 js/dist/connect.es.js create mode 100644 js/dist/connect.js create mode 100644 js/dist/connect.min.js create mode 100644 js/dist/widget.es.js create mode 100644 js/dist/widget.js create mode 100644 js/dist/widget.min.js create mode 100644 js/package-lock.json create mode 100644 js/package.json create mode 100644 js/rollup.config.js rename js/{ => src}/connect.js (99%) rename js/{ => src}/widget.js (99%) diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..d484654 --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +/js/node_modules/ +.idea/ diff --git a/js/dist/connect.es.js b/js/dist/connect.es.js new file mode 100644 index 0000000..4758fb7 --- /dev/null +++ b/js/dist/connect.es.js @@ -0,0 +1,188 @@ +/* + * X-Payments Cloud SDK - Connect Widget + */ + +function XPaymentsConnect(elmSelector, quickAccessKey, handlers) { + this.jsApiVersion = '2.0'; + this.serverDomain = 'xpayments.com'; + this.messageNamespace = 'xpayments.connect.'; + + this.previousHeight = -1; + + this.config = { + debug: false, + account: '', + container: '', + topElement: '', + referrerUrl: document.location.href, + applePayOnly: false, + quickAccessKey: '' + }; + + this.handlers = {}; + + this.bindedListener = false; + +} + +XPaymentsConnect.prototype.init = function(settings) +{ + for (var key in settings) { + if ('undefined' !== typeof this.config[key]) { + this.config[key] = settings[key]; + } + } + + // Set default handlers + this.on('alert', function(params) { + window.alert(params.message); + }).on('config', function() { + console.error('X-Payments Widget is not configured properly!'); + }); + + this.bindedListener = this.messageListener.bind(this); + window.addEventListener('message', this.bindedListener); + + return this; +}; + +XPaymentsConnect.prototype.getContainerElm = function() +{ + return this.safeQuerySelector(this.config.container); +}; + +XPaymentsConnect.prototype.getIframeId = function() +{ + return 'xpayments-connect'; +}; + +XPaymentsConnect.prototype.getIframeElm = function() +{ + return document.getElementById(this.getIframeId()); +}; + +XPaymentsConnect.prototype.safeQuerySelector = function(selector) +{ + var elm = false; + if (selector) { + elm = document.querySelector(selector); + } + return elm; +}; + +XPaymentsConnect.prototype.resize = function(height) +{ + var elm = this.getIframeElm(); + if (elm) { + this.previousHeight = elm.style.height; + elm.style.height = height + 'px'; + } +}; + +XPaymentsConnect.prototype.load = function() +{ + var containerElm = this.getContainerElm(); + if (!containerElm) { + return this; + } + + var elm = document.createElement('iframe'); + elm.id = this.getIframeId(); + elm.style.width = '100%'; + elm.style.height = '0'; + elm.style.overflow = 'hidden'; + elm.setAttribute('scrolling', 'no'); + containerElm.appendChild(elm); + + elm.src = this.getRedirectUrl(); + +}; + +XPaymentsConnect.prototype.getRedirectUrl = function() +{ + return 'https://' + this.getServerHost() + '/' + + '?ref=' + encodeURIComponent(this.config.referrerUrl) + + '&account=' + encodeURIComponent(this.config.account) + + '&api_version=' + encodeURIComponent(this.jsApiVersion) + + '&quickaccess=' + encodeURIComponent(this.config.quickAccessKey); +}; + +XPaymentsConnect.prototype.on = function(event, handler) +{ + this.handlers[event] = handler.bind(this); + return this; +}; + +XPaymentsConnect.prototype.trigger = function(event, params) +{ + if ('function' === typeof this.handlers[event]) { + this.handlers[event](params); + } + return this; +}; + +XPaymentsConnect.prototype.getServerHost = function() +{ + return 'connect.' + this.serverDomain; +}; + +XPaymentsConnect.prototype.messageListener = function(event) +{ + if (window.JSON) { + var msg = false; + + try { + msg = window.JSON.parse(event.data); + } catch (e) { + // Skip invalid messages + } + + if (msg && msg.event && 0 === msg.event.indexOf(this.messageNamespace)) { + this.log('X-Payments Event: ' + msg.event + "\n" + window.JSON.stringify(msg.params)); + + var eventType = msg.event.substr(this.messageNamespace.length); + + if ('loaded' === eventType) { + if (-1 !== this.previousHeight) { + var topElm = (this.config.topElement) + ? this.safeQuerySelector(this.config.topElement) + : this.getContainerElm(); + if (topElm) { + topElm.scrollIntoView(true); + } + } + this.resize(msg.params.height); + } else if ('resize' === eventType) { + this.resize(msg.params.height); + } else if ('alert' === eventType) { + msg.params.message = msg.params.message.replace(/<\/?[^>]+>/gi, ''); + } + + this.trigger(eventType, msg.params); + } + } +}; + +XPaymentsConnect.prototype.postMessage = function(message) +{ + var elm = this.getIframeElm(); + if ( + window.postMessage + && window.JSON + && elm + && elm.contentWindow + ) { + this.log('Sent to X-Payments: ' + message.event + "\n" + window.JSON.stringify(message.params)); + elm.contentWindow.postMessage(window.JSON.stringify(message), '*'); + } else { + this.log('Error sending message - iframe wasn\'t initialized!'); + } +}; + +XPaymentsConnect.prototype.log = function(msg) { + if (this.config.debug) { + console.log(msg); + } +}; + +export { XPaymentsConnect as default }; diff --git a/js/dist/connect.js b/js/dist/connect.js new file mode 100644 index 0000000..6d48da5 --- /dev/null +++ b/js/dist/connect.js @@ -0,0 +1,193 @@ +(function () { + 'use strict'; + + /* + * X-Payments Cloud SDK - Connect Widget + */ + + function XPaymentsConnect(elmSelector, quickAccessKey, handlers) { + this.jsApiVersion = '2.0'; + this.serverDomain = 'xpayments.com'; + this.messageNamespace = 'xpayments.connect.'; + + this.previousHeight = -1; + + this.config = { + debug: false, + account: '', + container: '', + topElement: '', + referrerUrl: document.location.href, + applePayOnly: false, + quickAccessKey: '' + }; + + this.handlers = {}; + + this.bindedListener = false; + + } + + XPaymentsConnect.prototype.init = function(settings) + { + for (var key in settings) { + if ('undefined' !== typeof this.config[key]) { + this.config[key] = settings[key]; + } + } + + // Set default handlers + this.on('alert', function(params) { + window.alert(params.message); + }).on('config', function() { + console.error('X-Payments Widget is not configured properly!'); + }); + + this.bindedListener = this.messageListener.bind(this); + window.addEventListener('message', this.bindedListener); + + return this; + }; + + XPaymentsConnect.prototype.getContainerElm = function() + { + return this.safeQuerySelector(this.config.container); + }; + + XPaymentsConnect.prototype.getIframeId = function() + { + return 'xpayments-connect'; + }; + + XPaymentsConnect.prototype.getIframeElm = function() + { + return document.getElementById(this.getIframeId()); + }; + + XPaymentsConnect.prototype.safeQuerySelector = function(selector) + { + var elm = false; + if (selector) { + elm = document.querySelector(selector); + } + return elm; + }; + + XPaymentsConnect.prototype.resize = function(height) + { + var elm = this.getIframeElm(); + if (elm) { + this.previousHeight = elm.style.height; + elm.style.height = height + 'px'; + } + }; + + XPaymentsConnect.prototype.load = function() + { + var containerElm = this.getContainerElm(); + if (!containerElm) { + return this; + } + + var elm = document.createElement('iframe'); + elm.id = this.getIframeId(); + elm.style.width = '100%'; + elm.style.height = '0'; + elm.style.overflow = 'hidden'; + elm.setAttribute('scrolling', 'no'); + containerElm.appendChild(elm); + + elm.src = this.getRedirectUrl(); + + }; + + XPaymentsConnect.prototype.getRedirectUrl = function() + { + return 'https://' + this.getServerHost() + '/' + + '?ref=' + encodeURIComponent(this.config.referrerUrl) + + '&account=' + encodeURIComponent(this.config.account) + + '&api_version=' + encodeURIComponent(this.jsApiVersion) + + '&quickaccess=' + encodeURIComponent(this.config.quickAccessKey); + }; + + XPaymentsConnect.prototype.on = function(event, handler) + { + this.handlers[event] = handler.bind(this); + return this; + }; + + XPaymentsConnect.prototype.trigger = function(event, params) + { + if ('function' === typeof this.handlers[event]) { + this.handlers[event](params); + } + return this; + }; + + XPaymentsConnect.prototype.getServerHost = function() + { + return 'connect.' + this.serverDomain; + }; + + XPaymentsConnect.prototype.messageListener = function(event) + { + if (window.JSON) { + var msg = false; + + try { + msg = window.JSON.parse(event.data); + } catch (e) { + // Skip invalid messages + } + + if (msg && msg.event && 0 === msg.event.indexOf(this.messageNamespace)) { + this.log('X-Payments Event: ' + msg.event + "\n" + window.JSON.stringify(msg.params)); + + var eventType = msg.event.substr(this.messageNamespace.length); + + if ('loaded' === eventType) { + if (-1 !== this.previousHeight) { + var topElm = (this.config.topElement) + ? this.safeQuerySelector(this.config.topElement) + : this.getContainerElm(); + if (topElm) { + topElm.scrollIntoView(true); + } + } + this.resize(msg.params.height); + } else if ('resize' === eventType) { + this.resize(msg.params.height); + } else if ('alert' === eventType) { + msg.params.message = msg.params.message.replace(/<\/?[^>]+>/gi, ''); + } + + this.trigger(eventType, msg.params); + } + } + }; + + XPaymentsConnect.prototype.postMessage = function(message) + { + var elm = this.getIframeElm(); + if ( + window.postMessage + && window.JSON + && elm + && elm.contentWindow + ) { + this.log('Sent to X-Payments: ' + message.event + "\n" + window.JSON.stringify(message.params)); + elm.contentWindow.postMessage(window.JSON.stringify(message), '*'); + } else { + this.log('Error sending message - iframe wasn\'t initialized!'); + } + }; + + XPaymentsConnect.prototype.log = function(msg) { + if (this.config.debug) { + console.log(msg); + } + }; + + return XPaymentsConnect; + +})(); diff --git a/js/dist/connect.min.js b/js/dist/connect.min.js new file mode 100644 index 0000000..6c74204 --- /dev/null +++ b/js/dist/connect.min.js @@ -0,0 +1 @@ +!function(){"use strict";function e(e,t,n){this.jsApiVersion="2.0",this.serverDomain="xpayments.com",this.messageNamespace="xpayments.connect.",this.previousHeight=-1,this.config={debug:!1,account:"",container:"",topElement:"",referrerUrl:document.location.href,applePayOnly:!1,quickAccessKey:""},this.handlers={},this.bindedListener=!1}e.prototype.init=function(e){for(var t in e)void 0!==this.config[t]&&(this.config[t]=e[t]);return this.on("alert",(function(e){window.alert(e.message)})).on("config",(function(){console.error("X-Payments Widget is not configured properly!")})),this.bindedListener=this.messageListener.bind(this),window.addEventListener("message",this.bindedListener),this},e.prototype.getContainerElm=function(){return this.safeQuerySelector(this.config.container)},e.prototype.getIframeId=function(){return"xpayments-connect"},e.prototype.getIframeElm=function(){return document.getElementById(this.getIframeId())},e.prototype.safeQuerySelector=function(e){var t=!1;return e&&(t=document.querySelector(e)),t},e.prototype.resize=function(e){var t=this.getIframeElm();t&&(this.previousHeight=t.style.height,t.style.height=e+"px")},e.prototype.load=function(){var e=this.getContainerElm();if(!e)return this;var t=document.createElement("iframe");t.id=this.getIframeId(),t.style.width="100%",t.style.height="0",t.style.overflow="hidden",t.setAttribute("scrolling","no"),e.appendChild(t),t.src=this.getRedirectUrl()},e.prototype.getRedirectUrl=function(){return"https://"+this.getServerHost()+"/?ref="+encodeURIComponent(this.config.referrerUrl)+"&account="+encodeURIComponent(this.config.account)+"&api_version="+encodeURIComponent(this.jsApiVersion)+"&quickaccess="+encodeURIComponent(this.config.quickAccessKey)},e.prototype.on=function(e,t){return this.handlers[e]=t.bind(this),this},e.prototype.trigger=function(e,t){return"function"==typeof this.handlers[e]&&this.handlers[e](t),this},e.prototype.getServerHost=function(){return"connect."+this.serverDomain},e.prototype.messageListener=function(e){if(window.JSON){var t=!1;try{t=window.JSON.parse(e.data)}catch(e){}if(t&&t.event&&0===t.event.indexOf(this.messageNamespace)){this.log("X-Payments Event: "+t.event+"\n"+window.JSON.stringify(t.params));var n=t.event.substr(this.messageNamespace.length);if("loaded"===n){if(-1!==this.previousHeight){var i=this.config.topElement?this.safeQuerySelector(this.config.topElement):this.getContainerElm();i&&i.scrollIntoView(!0)}this.resize(t.params.height)}else"resize"===n?this.resize(t.params.height):"alert"===n&&(t.params.message=t.params.message.replace(/<\/?[^>]+>/gi,""));this.trigger(n,t.params)}}},e.prototype.postMessage=function(e){var t=this.getIframeElm();window.postMessage&&window.JSON&&t&&t.contentWindow?(this.log("Sent to X-Payments: "+e.event+"\n"+window.JSON.stringify(e.params)),t.contentWindow.postMessage(window.JSON.stringify(e),"*")):this.log("Error sending message - iframe wasn't initialized!")},e.prototype.log=function(e){this.config.debug&&console.log(e)}}(); diff --git a/js/dist/widget.es.js b/js/dist/widget.es.js new file mode 100644 index 0000000..fc969e2 --- /dev/null +++ b/js/dist/widget.es.js @@ -0,0 +1,923 @@ +/* + * X-Payments Cloud SDK - Payment Widget + */ + +const XPaymentsWidget = function() +{ + this.jsApiVersion = '2.0'; + this.serverDomain = 'xpayments.com'; + this.messageNamespace = 'xpayments.widget.'; + this.receiverNamespace = 'xpayments.checkout.'; + this.widgetId = this.generateId(); + this.previousHeight = -1; + this.applePayData = { + session: null, + supportedNetworks: [], + merchantCapabilities: [], + merchantId: '', + }; + this.googlePayData = { + client: null, + libUrl: 'https://pay.google.com/gp/p/js/pay.js', + libLoaded: false, + paymentMethods: {}, + merchantInfo: {}, + tokenizationSpecification: {}, + }; + this.paymentMethod = null; + + this.config = { + debug: false, + account: '', + widgetKey: '', + container: '', + form: '', + language: '', + customerId: '', + tokenName: 'xpaymentsToken', + showSaveCard: true, + enableWallets: true, + applePay: { + enabled: false, + shippingMethods: [], + requiredShippingFields: [], + requiredBillingFields: [], + }, + googlePay: { + enabled: false, + shippingMethods: [], + requiredShippingFields: [], + requiredBillingFields: [], + }, + walletMode: '', + company: { + name: '', + domain: document.location.hostname, + countryCode: '', + }, + order: { + tokenizeCard: false, + total: -1, + currency: '' + } + }; + + this.handlers = {}; + + this.bindedListener = false; + this.bindedSubmit = false; + +}; + +XPaymentsWidget.prototype.on = function(event, handler, context) +{ + if ('undefined' === typeof context) { + context = this; + } + + if ('formSubmit' !== event) { + + this.handlers[event] = handler.bind(context); + + } else { + var formElm = this.getFormElm(); + + if (formElm) { + if (this.bindedSubmit) { + formElm.removeEventListener('submit', this.bindedSubmit); + } + this.bindedSubmit = handler.bind(context); + formElm.addEventListener('submit', this.bindedSubmit); + } + } + + return this; +}; + +XPaymentsWidget.prototype.trigger = function(event, params) +{ + var result = null; + + if ('function' === typeof this.handlers[event]) { + result = this.handlers[event](params); + } + + this._log('X-Payments widget triggered: ' + event, params); + + return result; +}; + +XPaymentsWidget.prototype.init = function(settings) +{ + for (var key in settings) { + if ('undefined' !== typeof this.config[key]) { + if ('object' === typeof this.config[key]) { + for (var subkey in settings[key]) { + if ('undefined' !== typeof this.config[key][subkey]) { + this.config[key][subkey] = settings[key][subkey]; + } + } + } else { + this.config[key] = settings[key]; + } + } + } + + if (this.config.order.tokenizeCard) { + this.config.showSaveCard = false; + } + + // Set default handlers + this.on('formSubmit', function (domEvent) { + // "this" here is the widget + if (this.isValid()) { + this.submit(); + domEvent.preventDefault(); + } + }) + .on('success', this._defaultSuccessHandler) + .on('applepay.paymentauthorized', this._applePayAuthorized) + .on('applepay.buttonclick', function() { + this.isValid() && this.submit(); + }) + .on('googlepay.paymentauthorized', this._googlePayAuthorized) + .on('googlepay.buttonclick', function() { + this.isValid() && this.submit(); + }) + .on('alert', function(params) { + window.alert(params.message); + }); + + this.bindedListener = this.messageListener.bind(this); + window.addEventListener('message', this.bindedListener); + + if ( + 'undefined' !== typeof settings.autoload + && settings.autoload + ) { + this.load(); + } + + return this; +}; + +XPaymentsWidget.prototype.generateId = function() +{ + return Math.random().toString(36).substring(2, 15) + Math.random().toString(36).substring(2, 15); +}; + +XPaymentsWidget.prototype.getIframeId = function() +{ + return 'xpayments-' + this.widgetId; +}; + +XPaymentsWidget.prototype.getIframeElm = function() +{ + return document.getElementById(this.getIframeId()); +}; + +XPaymentsWidget.prototype.getContainerElm = function() +{ + return this.safeQuerySelector(this.config.container); +}; + +XPaymentsWidget.prototype.getFormElm = function() +{ + return this.safeQuerySelector(this.config.form); +}; + +XPaymentsWidget.prototype.isValid = function() +{ + return this.getIframeElm() && this.getFormElm(); +}; + +XPaymentsWidget.prototype.safeQuerySelector = function(selector) +{ + var elm = false; + if (selector) { + elm = document.querySelector(selector); + } + return elm; +}; + +XPaymentsWidget.prototype.loadAsyncJS = function(url, callback) +{ + var script = document.createElement('script'); + script.type = 'text/javascript'; + script.async = true; + script.onload = callback; + script.src = url; + document.getElementsByTagName('head')[0].appendChild(script); +}; + +XPaymentsWidget.prototype.load = function() +{ + var containerElm = this.getContainerElm(); + if (!containerElm) { + return this; + } + + var elm = this.getIframeElm(); + if (!elm) { + elm = document.createElement('iframe'); + elm.id = this.getIframeId(); + elm.style.width = '100%'; + elm.style.height = '0'; + elm.style.overflow = 'hidden'; + elm.style.border = 'none'; + if (this.config.walletMode) { + elm.style.display = 'none'; + } + elm.setAttribute('scrolling', 'no'); + containerElm.appendChild(elm); + } + + var url = + this.getServerUrl() + '/payment.php' + + '?widget_key=' + encodeURIComponent(this.config.widgetKey) + + '&widget_id=' + encodeURIComponent(this.widgetId) + + '&shop=' + encodeURIComponent(this.config.company.domain) + + '&api_version=' + encodeURIComponent(this.jsApiVersion); + + if (this.config.customerId) { + url += '&customer_id=' + encodeURIComponent(this.config.customerId); + } + if (this.config.language) { + url += '&language=' + encodeURIComponent(this.config.language); + } + if (this.config.walletMode) { + url += '&target=wallet&mode=' + encodeURIComponent(this.config.walletMode); + } + elm.src = url; + + if (this._isGooglePayEnabled()) { + this.loadAsyncJS(this.googlePayData.libUrl, (function() { + this.googlePayData.libLoaded = true; + }).bind(this)); + } + + return this; +}; + +XPaymentsWidget.prototype.getServerHost = function() +{ + return this.config.account + '.' + this.serverDomain; +}; + +XPaymentsWidget.prototype.getServerUrl = function() +{ + return 'https://' + this.getServerHost(); +}; + +XPaymentsWidget.prototype.submit = function() +{ + if (!this.config.walletMode) { + this._sendEvent('submit'); + } else { + switch (this.getPaymentMethod()) { + case 'applePay': + this.trigger('applepay.start'); + this._applePayStart(); + break; + case 'googlePay': + this.trigger('googlepay.start'); + this._googlePayStart(); + break; + } + } +}; + +XPaymentsWidget.prototype.beginCheckoutWithWallet = function() +{ + this.submit(); +}; + +XPaymentsWidget.prototype._afterLoad = function(params) +{ + this.showSaveCard(); + if (this._isApplePayAvailable()) { + this._sendEvent('applepay.enable'); + } + if (this._isGooglePayEnabled()) { + // Actual GPay availability can be checked only after loading + this._sendGooglePayLoaded(); + } + this.setOrder(); + this.resize(params.height); +}; + +XPaymentsWidget.prototype._defaultSuccessHandler = function(params) { + var formElm = this.getFormElm(); + if (formElm) { + var input = document.getElementById(this.config.tokenName); + if (!input) { + input = document.createElement('input'); + input.type = 'hidden'; + input.name = input.id = this.config.tokenName; + formElm.appendChild(input); + } + input.value = params.token; + formElm.submit(); + } +}; + +XPaymentsWidget.prototype.getPaymentMethod = function() +{ + return this.config.walletMode || this.paymentMethod; +}; + +XPaymentsWidget.prototype._paymentMethodChange = function(params) +{ + this.paymentMethod = params.newId; +}; + +XPaymentsWidget.prototype._applePayValidated = function(params) +{ + try { + this.applePayData.session.completeMerchantValidation(params.data); + } catch (e) { + } +}; + +XPaymentsWidget.prototype._applePayAuthorized = function(params) +{ + this.succeedApplePayPayment(params); +}; + +XPaymentsWidget.prototype._applePayCompleted = function(params) +{ + this.completeApplePayPayment({ status: ApplePaySession.STATUS_SUCCESS, errors: [] }); +}; + +XPaymentsWidget.prototype._applePayError = function(params) +{ + try { + this.applePayData.session.abort(); + } catch (e) { + // Skip errors if any + } +}; + +XPaymentsWidget.prototype._applePayStart = function() +{ + if (!this.applePayData.merchantCapabilities.length) { + this._sendEvent('applepay.cancel', { alert: true }); + return; + } + + var request = { + countryCode: this.config.company.countryCode, + currencyCode: this.config.order.currency, + supportedNetworks: this.applePayData.supportedNetworks, + merchantCapabilities: this.applePayData.merchantCapabilities, + total: { + label: this.config.company.name, + amount: this.config.order.total + }, + }; + + this.applePayCustomerAddress = null; + if (this.config.walletMode) { + if (this.config.applePay.shippingMethods.length) { + request.shippingMethods = this.config.applePay.shippingMethods; + } + if (this.config.applePay.requiredShippingFields.length) { + request.requiredShippingContactFields = this.config.applePay.requiredShippingFields; + } + if (this.config.applePay.requiredBillingFields.length) { + request.requiredBillingContactFields = this.config.applePay.requiredBillingFields; + } + } + + this.applePayData.session = new ApplePaySession(3, request); + + this.applePayData.session.onvalidatemerchant = (function(event) { + this._sendEvent('applepay.validatemerchant', { + validationURL: event.validationURL, + displayName: this.config.company.name, + context: this.config.company.domain, + }); + }).bind(this); + + this.applePayData.session.onpaymentauthorized = (function(event) { + this.trigger('applepay.paymentauthorized', event.payment); + }).bind(this); + + this.applePayData.session.oncancel = (function(event) { + var params = {}; + if ('undefined' !== typeof event.sessionError) { + params.error = event.sessionError; + } + this._sendEvent('applepay.cancel', params); + this.trigger('applepay.cancel', params); + }).bind(this); + + if (this.config.walletMode) { + this.applePayData.session.onshippingcontactselected = (function(event) { + this.trigger('applepay.shippingcontactselected', event.shippingContact); + }).bind(this); + this.applePayData.session.onshippingmethodselected = (function(event) { + this.trigger('applepay.shippingmethodselected', event.shippingMethod); + }).bind(this); + } + + this.applePayData.session.begin(); + +}; + +XPaymentsWidget.prototype._parseApplePayNewTotal = function(updateData) +{ + this.setOrder(updateData.newTotal.amount); + if ('undefined' != typeof updateData.newTotal && 'undefined' == typeof updateData.newTotal.label) { + updateData.newTotal.label = this.config.company.name; + } + return updateData; +}; + +XPaymentsWidget.prototype.completeApplePayShippingContactSelection = function(updateData) { + this.applePayData.session.completeShippingContactSelection(this._parseApplePayNewTotal(updateData)); +}; + +XPaymentsWidget.prototype.completeApplePayShippingMethodSelection = function(updateData) { + this.applePayData.session.completeShippingMethodSelection(this._parseApplePayNewTotal(updateData)); +}; + +XPaymentsWidget.prototype.completeApplePayPayment = function(updateData) { + this.applePayData.session.completePayment(updateData); +}; + +XPaymentsWidget.prototype.succeedApplePayPayment = function(payment) { + this._sendEvent('applepay.paymentauthorized', { payment: payment }); +}; + +XPaymentsWidget.prototype.isApplePaySupportedByDevice = function() { + return (window.ApplePaySession && ApplePaySession.canMakePayments()); +}; + +XPaymentsWidget.prototype._isApplePayAvailable = function() { + return this.isApplePaySupportedByDevice() + && ( + this.config.enableWallets && this.config.applePay.enabled + || 'applePay' === this.config.walletMode + ); +}; + +XPaymentsWidget.prototype._checkApplePayActiveCard = function() +{ + var promise = ApplePaySession.canMakePaymentsWithActiveCard(this.applePayData.merchantId); + promise.then((function (canMakePayments) { + if (canMakePayments) { + this.trigger('applepay.forceselect'); + this._sendEvent('applepay.select'); + } + }).bind(this)); +}; + +XPaymentsWidget.prototype._applePayInit = function(params) +{ + this.applePayData.supportedNetworks = params.supportedNetworks; + this.applePayData.merchantCapabilities = params.merchantCapabilities; + this.applePayData.merchantId = params.merchantId; + if (!this.config.walletMode) { + this._checkApplePayActiveCard(); + } +}; + +XPaymentsWidget.prototype._isGooglePayEnabled = function() { + return ( + this.config.enableWallets && this.config.googlePay.enabled + || 'googlePay' === this.config.walletMode + ); +}; + +XPaymentsWidget.prototype._sendGooglePayLoaded = function() +{ + var promise = new Promise((function(resolve, reject) { + var counter = 0; + var checkReady = (function() { + counter++; + if (this.googlePayData.libLoaded) { + resolve(); + } else if (counter < 300) { + setTimeout(checkReady, 100); + } else { + this._log('Error! Failed to load Google Pay library.'); + } + }).bind(this); + checkReady(); + }).bind(this)); + + promise.then( + (function() { + this._sendEvent('googlepay.loaded', { origin: this.config.company.domain }); + }).bind(this) + ); +}; + +XPaymentsWidget.prototype._googlePayPrepareBaseRequest = function() +{ + var baseRequest = { + apiVersion: 2, + apiVersionMinor: 0, + allowedPaymentMethods: this.googlePayData.paymentMethods, + }; + + return baseRequest; +}; + +XPaymentsWidget.prototype._googlePayPrepareReadyToPay = function(existingRequired) +{ + var request = {}; + if ('undefined' !== typeof existingRequired && existingRequired) { + request.existingPaymentMethodRequired = existingRequired; + } + + return Object.assign({}, this._googlePayPrepareBaseRequest(), request); +}; + +XPaymentsWidget.prototype._googlePayPrepareLoadPayment = function(request) +{ + var baseRequest = this._googlePayPrepareBaseRequest(); + + for (var key in baseRequest.allowedPaymentMethods) { + baseRequest.allowedPaymentMethods[key].tokenizationSpecification = this.googlePayData.tokenizationSpecification; + if (this.config.walletMode && this.config.googlePay.requiredBillingFields.length) { + baseRequest.allowedPaymentMethods[key].parameters.billingAddressRequired = true; + baseRequest.allowedPaymentMethods[key].parameters.billingAddressParameters = { + format: (-1 !== this.config.googlePay.requiredBillingFields.indexOf('full')) ? 'FULL' : 'MIN', + phoneNumberRequired: (-1 !== this.config.googlePay.requiredBillingFields.indexOf('phone')), + }; + } + + } + + return Object.assign({}, baseRequest, request); +}; + +XPaymentsWidget.prototype._googlePayInit = function(params) +{ + this.googlePayData.merchantInfo = { + merchantName: this.config.company.name, + merchantOrigin: this.config.company.domain, + merchantId: params.businessId, + }; + if (params.authJwt) { + this.googlePayData.merchantInfo.authJwt = params.authJwt; + } + + this.googlePayData.tokenizationSpecification = { + type: 'PAYMENT_GATEWAY', + parameters: { + gateway: params.gatewayId, + gatewayMerchantId: params.merchantId, + } + }; + + var options = { + environment: params.environment, + merchantInfo: this.googlePayData.merchantInfo, + paymentDataCallbacks: { + onPaymentAuthorized: (function(paymentData) { + return this.trigger('googlepay.paymentauthorized', paymentData, true); + }).bind(this), + } + }; + + if (this.config.walletMode && this.config.googlePay.requiredShippingFields.length) { + options.paymentDataCallbacks.onPaymentDataChanged = (function(intermediatePaymentData) { + return this.trigger('googlepay.paymentdatachanged', intermediatePaymentData); + }).bind(this); + } + + this.googlePayData.client = new google.payments.api.PaymentsClient(options); + + this.googlePayData.paymentMethods = []; + for (var key in params.paymentMethods) { + this.googlePayData.paymentMethods.push({ + type: params.paymentMethods[key], + parameters: { + allowedAuthMethods: params.authMethods, + allowedCardNetworks: params.supportedNetworks + } + }); + } + + var request = this._googlePayPrepareReadyToPay(); + + this.googlePayData.client.isReadyToPay(request) + .then((function(response) { + if (response.result) { + this._sendEvent('googlepay.enable'); + this.trigger('googlepay.ready'); + } else { + this.trigger('googlepay.nonready'); + } + }).bind(this)) + .catch((function(err) { + this._log(err); + }).bind(this)); +}; + +XPaymentsWidget.prototype._googlePayStart = function(params) +{ + if (!this.googlePayData.client) { + this._sendEvent('googlepay.cancel', { alert: true }); + return; + } + + var request = { + merchantInfo: this.googlePayData.merchantInfo, + transactionInfo: { + totalPriceStatus: 'FINAL', + totalPrice: this.config.order.total.toString(), + currencyCode: this.config.order.currency, + countryCode: this.config.company.countryCode, + }, + callbackIntents: [ + 'PAYMENT_AUTHORIZATION', + ], + }; + + if (this.config.walletMode && this.config.googlePay.requiredShippingFields.length) { + // We need to add displayItems because them won't show after finalization otherwise + request.transactionInfo.displayItems = [ + { + label: 'Subtotal', + type: 'SUBTOTAL', + price: this.config.order.total.toString(), + } + ]; + request.transactionInfo.totalPriceStatus = 'ESTIMATED'; + request.transactionInfo.totalPriceLabel = 'Total'; + + request.callbackIntents.push('SHIPPING_ADDRESS'); + request.shippingAddressRequired = true; + request.shippingAddressParameters = { + phoneNumberRequired: (-1 !== this.config.googlePay.requiredShippingFields.indexOf('phone')) + }; + request.emailRequired = (-1 !== this.config.googlePay.requiredShippingFields.indexOf('email')); + + if (this.config.googlePay.shippingMethods.length) { + request.callbackIntents.push('SHIPPING_OPTION'); + request.shippingOptionRequired = true; + } + } + + request = this._googlePayPrepareLoadPayment(request); + + this.googlePayData.client.loadPaymentData(request) + .then((function(paymentData) { + // Successful response parsed in googlepay.paymentauthorized + }).bind(this)) + .catch((function(err) { + this._sendEvent('googlepay.cancel', { error: err }); + this.trigger('googlepay.cancel'); + }).bind(this)); +}; + +XPaymentsWidget.prototype._googlePayAuthorized = function(paymentData) +{ + return new Promise((function(resolve, reject) { + resolve(this.succeedGooglePayPayment(paymentData)); + }).bind(this)); +}; + +XPaymentsWidget.prototype._googlePayError = function(params) +{ + // Do nothing +}; + +XPaymentsWidget.prototype.succeedGooglePayPayment = function(paymentData) { + this._sendEvent('googlepay.paymentauthorized', { payment: paymentData.paymentMethodData }); + return { transactionState: 'SUCCESS' }; +}; + +XPaymentsWidget.prototype.isGooglePayInitialized = function(options) +{ + return (null !== this.googlePayData.client); +}; + +XPaymentsWidget.prototype.createApplePayButton = function(options) +{ + if (!this.isApplePaySupportedByDevice()) { + console.error('Apple Pay is not supported by the device'); + return null; + } + + var buttonOptions = { + onClick: (function() { + this.trigger('applepay.buttonclick'); + }).bind(this), + wrapperClass: 'apple-pay-button-wrapper', + buttonClass: 'apple-pay-button', + buttonContent: '', + }; + + if ('undefined' !== typeof options) { + buttonOptions = Object.assign({}, buttonOptions, options); + } + + var wrapper = document.createElement('div'); + wrapper.className = buttonOptions.wrapperClass; + + var button = document.createElement('button'); + button.className = buttonOptions.buttonClass; + button.type = 'button'; + button.innerHTML = buttonOptions.buttonContent; + button.addEventListener('click', buttonOptions.onClick); + + wrapper.appendChild(button); + + return wrapper; +}; + + +XPaymentsWidget.prototype.createGooglePayButton = function(options) +{ + if (!this.isGooglePayInitialized()) { + console.error('Google Pay not initalized'); + return null; + } + + var buttonOptions = { + onClick: (function() { + this.trigger('googlepay.buttonclick'); + }).bind(this) + }; + + if ('undefined' !== typeof options) { + buttonOptions = Object.assign({}, buttonOptions, options); + } + + return this.googlePayData.client.createButton(buttonOptions); +}; + +XPaymentsWidget.prototype.setWalletMode = function(walletId) +{ + this.config.walletMode = walletId; +}; + +XPaymentsWidget.prototype.showSaveCard = function(value) +{ + if ('undefined' === typeof value) { + value = this.config.showSaveCard; + } else { + this.config.showSaveCard = (true === value); + } + this._sendEvent('savecard', { show: value }); +}; + + +XPaymentsWidget.prototype.refresh = function() +{ + this._sendEvent('refresh'); +}; + +XPaymentsWidget.prototype.resize = function(height) +{ + var elm = this.getIframeElm(); + if (elm) { + this.previousHeight = elm.style.height; + elm.style.height = height + 'px'; + } +}; + +XPaymentsWidget.prototype.setOrder = function(total, currency) +{ + if ('undefined' !== typeof total) { + this.config.order.total = total; + } + if ('undefined' !== typeof currency) { + this.config.order.currency = currency; + } + + this._sendEvent('details', { + tokenizeCard: this.config.order.tokenizeCard, + total: this.config.order.total, + currency: this.config.order.currency + }); +}; + +XPaymentsWidget.prototype.destroy = function() +{ + if (this.bindedListener) { + window.removeEventListener('message', this.bindedListener); + } + + var formElm = this.getFormElm(); + if (this.bindedSubmit && formElm) { + formElm.removeEventListener('submit', this.bindedSubmit); + } + + var containerElm = this.getContainerElm(); + if (containerElm) { + var elm = this.getIframeElm(); + if (elm && containerElm.contains(elm)) { + containerElm.removeChild(elm); + } + } +}; + +XPaymentsWidget.prototype.messageListener = function(event) +{ + if (window.JSON) { + var msg = false; + if (-1 !== this.getServerUrl().toLowerCase().indexOf(event.origin.toLowerCase())) { + try { + msg = window.JSON.parse(event.data); + } catch (e) { + // Skip invalid messages + } + } + + if ( + msg && + msg.event && + 0 === msg.event.indexOf(this.messageNamespace) && + (!msg.widgetId || msg.widgetId === this.widgetId) + ) { + this._log('Received from X-Payments: ' + msg.event, msg.params); + + var eventType = msg.event.substr(this.messageNamespace.length); + + if ('loaded' === eventType) { + this._afterLoad(msg.params); + } else if ('applepay.start' === eventType) { + this._applePayStart(msg.params); + } else if ('applepay.init' === eventType) { + this._applePayInit(msg.params); + } else if ('applepay.merchantvalidated' === eventType) { + this._applePayValidated(msg.params); + } else if ('applepay.completed' === eventType) { + this._applePayCompleted(msg.params); + } else if ('applepay.error' === eventType) { + this._applePayError(msg.params); + } else if ('googlepay.init' === eventType) { + this._googlePayInit(msg.params); + } else if ('googlepay.start' === eventType) { + this._googlePayStart(msg.params); + } else if ('googlepay.error' === eventType) { + this._googlePayError(msg.params); + } else if ('paymentmethod.change' === eventType) { + this._paymentMethodChange(msg.params); + } else if ('resize' === eventType) { + this.resize(msg.params.height); + } else if ('alert' === eventType) { + msg.params.message = + ('string' === typeof msg.params.message) + ? msg.params.message.replace(/<\/?[^>]+>/gi, '') + : ''; + } + + this.trigger(eventType, msg.params); + } + + } +}; + +XPaymentsWidget.prototype._isDebugMode = function() +{ + return this.config.debug; +}; + +XPaymentsWidget.prototype._log = function(msg, params) +{ + if (this._isDebugMode()) { + console.groupCollapsed(msg); + if ('undefined' !== typeof params) { + console.log(JSON.stringify(params)); + } + console.trace(); + console.groupEnd(); + } +}; + +XPaymentsWidget.prototype._sendEvent = function(eventName, eventParams) +{ + if ('undefined' === typeof eventParams) { + eventParams = {}; + } + + this._postMessage({ + event: this.receiverNamespace + eventName, + params: eventParams + }); +}; + +XPaymentsWidget.prototype._postMessage = function(message) +{ + var elm = this.getIframeElm(); + if ( + window.postMessage + && window.JSON + && elm + && elm.contentWindow + ) { + this._log('Sent to X-Payments: ' + message.event, message.params); + elm.contentWindow.postMessage(window.JSON.stringify(message), '*'); + } else { + this._log('Error sending message - iframe wasn\'t initialized!'); + } +}; + +export { XPaymentsWidget as default }; diff --git a/js/dist/widget.js b/js/dist/widget.js new file mode 100644 index 0000000..bea1a63 --- /dev/null +++ b/js/dist/widget.js @@ -0,0 +1,928 @@ +(function () { + 'use strict'; + + /* + * X-Payments Cloud SDK - Payment Widget + */ + + const XPaymentsWidget = function() + { + this.jsApiVersion = '2.0'; + this.serverDomain = 'xpayments.com'; + this.messageNamespace = 'xpayments.widget.'; + this.receiverNamespace = 'xpayments.checkout.'; + this.widgetId = this.generateId(); + this.previousHeight = -1; + this.applePayData = { + session: null, + supportedNetworks: [], + merchantCapabilities: [], + merchantId: '', + }; + this.googlePayData = { + client: null, + libUrl: 'https://pay.google.com/gp/p/js/pay.js', + libLoaded: false, + paymentMethods: {}, + merchantInfo: {}, + tokenizationSpecification: {}, + }; + this.paymentMethod = null; + + this.config = { + debug: false, + account: '', + widgetKey: '', + container: '', + form: '', + language: '', + customerId: '', + tokenName: 'xpaymentsToken', + showSaveCard: true, + enableWallets: true, + applePay: { + enabled: false, + shippingMethods: [], + requiredShippingFields: [], + requiredBillingFields: [], + }, + googlePay: { + enabled: false, + shippingMethods: [], + requiredShippingFields: [], + requiredBillingFields: [], + }, + walletMode: '', + company: { + name: '', + domain: document.location.hostname, + countryCode: '', + }, + order: { + tokenizeCard: false, + total: -1, + currency: '' + } + }; + + this.handlers = {}; + + this.bindedListener = false; + this.bindedSubmit = false; + + }; + + XPaymentsWidget.prototype.on = function(event, handler, context) + { + if ('undefined' === typeof context) { + context = this; + } + + if ('formSubmit' !== event) { + + this.handlers[event] = handler.bind(context); + + } else { + var formElm = this.getFormElm(); + + if (formElm) { + if (this.bindedSubmit) { + formElm.removeEventListener('submit', this.bindedSubmit); + } + this.bindedSubmit = handler.bind(context); + formElm.addEventListener('submit', this.bindedSubmit); + } + } + + return this; + }; + + XPaymentsWidget.prototype.trigger = function(event, params) + { + var result = null; + + if ('function' === typeof this.handlers[event]) { + result = this.handlers[event](params); + } + + this._log('X-Payments widget triggered: ' + event, params); + + return result; + }; + + XPaymentsWidget.prototype.init = function(settings) + { + for (var key in settings) { + if ('undefined' !== typeof this.config[key]) { + if ('object' === typeof this.config[key]) { + for (var subkey in settings[key]) { + if ('undefined' !== typeof this.config[key][subkey]) { + this.config[key][subkey] = settings[key][subkey]; + } + } + } else { + this.config[key] = settings[key]; + } + } + } + + if (this.config.order.tokenizeCard) { + this.config.showSaveCard = false; + } + + // Set default handlers + this.on('formSubmit', function (domEvent) { + // "this" here is the widget + if (this.isValid()) { + this.submit(); + domEvent.preventDefault(); + } + }) + .on('success', this._defaultSuccessHandler) + .on('applepay.paymentauthorized', this._applePayAuthorized) + .on('applepay.buttonclick', function() { + this.isValid() && this.submit(); + }) + .on('googlepay.paymentauthorized', this._googlePayAuthorized) + .on('googlepay.buttonclick', function() { + this.isValid() && this.submit(); + }) + .on('alert', function(params) { + window.alert(params.message); + }); + + this.bindedListener = this.messageListener.bind(this); + window.addEventListener('message', this.bindedListener); + + if ( + 'undefined' !== typeof settings.autoload + && settings.autoload + ) { + this.load(); + } + + return this; + }; + + XPaymentsWidget.prototype.generateId = function() + { + return Math.random().toString(36).substring(2, 15) + Math.random().toString(36).substring(2, 15); + }; + + XPaymentsWidget.prototype.getIframeId = function() + { + return 'xpayments-' + this.widgetId; + }; + + XPaymentsWidget.prototype.getIframeElm = function() + { + return document.getElementById(this.getIframeId()); + }; + + XPaymentsWidget.prototype.getContainerElm = function() + { + return this.safeQuerySelector(this.config.container); + }; + + XPaymentsWidget.prototype.getFormElm = function() + { + return this.safeQuerySelector(this.config.form); + }; + + XPaymentsWidget.prototype.isValid = function() + { + return this.getIframeElm() && this.getFormElm(); + }; + + XPaymentsWidget.prototype.safeQuerySelector = function(selector) + { + var elm = false; + if (selector) { + elm = document.querySelector(selector); + } + return elm; + }; + + XPaymentsWidget.prototype.loadAsyncJS = function(url, callback) + { + var script = document.createElement('script'); + script.type = 'text/javascript'; + script.async = true; + script.onload = callback; + script.src = url; + document.getElementsByTagName('head')[0].appendChild(script); + }; + + XPaymentsWidget.prototype.load = function() + { + var containerElm = this.getContainerElm(); + if (!containerElm) { + return this; + } + + var elm = this.getIframeElm(); + if (!elm) { + elm = document.createElement('iframe'); + elm.id = this.getIframeId(); + elm.style.width = '100%'; + elm.style.height = '0'; + elm.style.overflow = 'hidden'; + elm.style.border = 'none'; + if (this.config.walletMode) { + elm.style.display = 'none'; + } + elm.setAttribute('scrolling', 'no'); + containerElm.appendChild(elm); + } + + var url = + this.getServerUrl() + '/payment.php' + + '?widget_key=' + encodeURIComponent(this.config.widgetKey) + + '&widget_id=' + encodeURIComponent(this.widgetId) + + '&shop=' + encodeURIComponent(this.config.company.domain) + + '&api_version=' + encodeURIComponent(this.jsApiVersion); + + if (this.config.customerId) { + url += '&customer_id=' + encodeURIComponent(this.config.customerId); + } + if (this.config.language) { + url += '&language=' + encodeURIComponent(this.config.language); + } + if (this.config.walletMode) { + url += '&target=wallet&mode=' + encodeURIComponent(this.config.walletMode); + } + elm.src = url; + + if (this._isGooglePayEnabled()) { + this.loadAsyncJS(this.googlePayData.libUrl, (function() { + this.googlePayData.libLoaded = true; + }).bind(this)); + } + + return this; + }; + + XPaymentsWidget.prototype.getServerHost = function() + { + return this.config.account + '.' + this.serverDomain; + }; + + XPaymentsWidget.prototype.getServerUrl = function() + { + return 'https://' + this.getServerHost(); + }; + + XPaymentsWidget.prototype.submit = function() + { + if (!this.config.walletMode) { + this._sendEvent('submit'); + } else { + switch (this.getPaymentMethod()) { + case 'applePay': + this.trigger('applepay.start'); + this._applePayStart(); + break; + case 'googlePay': + this.trigger('googlepay.start'); + this._googlePayStart(); + break; + } + } + }; + + XPaymentsWidget.prototype.beginCheckoutWithWallet = function() + { + this.submit(); + }; + + XPaymentsWidget.prototype._afterLoad = function(params) + { + this.showSaveCard(); + if (this._isApplePayAvailable()) { + this._sendEvent('applepay.enable'); + } + if (this._isGooglePayEnabled()) { + // Actual GPay availability can be checked only after loading + this._sendGooglePayLoaded(); + } + this.setOrder(); + this.resize(params.height); + }; + + XPaymentsWidget.prototype._defaultSuccessHandler = function(params) { + var formElm = this.getFormElm(); + if (formElm) { + var input = document.getElementById(this.config.tokenName); + if (!input) { + input = document.createElement('input'); + input.type = 'hidden'; + input.name = input.id = this.config.tokenName; + formElm.appendChild(input); + } + input.value = params.token; + formElm.submit(); + } + }; + + XPaymentsWidget.prototype.getPaymentMethod = function() + { + return this.config.walletMode || this.paymentMethod; + }; + + XPaymentsWidget.prototype._paymentMethodChange = function(params) + { + this.paymentMethod = params.newId; + }; + + XPaymentsWidget.prototype._applePayValidated = function(params) + { + try { + this.applePayData.session.completeMerchantValidation(params.data); + } catch (e) { + } + }; + + XPaymentsWidget.prototype._applePayAuthorized = function(params) + { + this.succeedApplePayPayment(params); + }; + + XPaymentsWidget.prototype._applePayCompleted = function(params) + { + this.completeApplePayPayment({ status: ApplePaySession.STATUS_SUCCESS, errors: [] }); + }; + + XPaymentsWidget.prototype._applePayError = function(params) + { + try { + this.applePayData.session.abort(); + } catch (e) { + // Skip errors if any + } + }; + + XPaymentsWidget.prototype._applePayStart = function() + { + if (!this.applePayData.merchantCapabilities.length) { + this._sendEvent('applepay.cancel', { alert: true }); + return; + } + + var request = { + countryCode: this.config.company.countryCode, + currencyCode: this.config.order.currency, + supportedNetworks: this.applePayData.supportedNetworks, + merchantCapabilities: this.applePayData.merchantCapabilities, + total: { + label: this.config.company.name, + amount: this.config.order.total + }, + }; + + this.applePayCustomerAddress = null; + if (this.config.walletMode) { + if (this.config.applePay.shippingMethods.length) { + request.shippingMethods = this.config.applePay.shippingMethods; + } + if (this.config.applePay.requiredShippingFields.length) { + request.requiredShippingContactFields = this.config.applePay.requiredShippingFields; + } + if (this.config.applePay.requiredBillingFields.length) { + request.requiredBillingContactFields = this.config.applePay.requiredBillingFields; + } + } + + this.applePayData.session = new ApplePaySession(3, request); + + this.applePayData.session.onvalidatemerchant = (function(event) { + this._sendEvent('applepay.validatemerchant', { + validationURL: event.validationURL, + displayName: this.config.company.name, + context: this.config.company.domain, + }); + }).bind(this); + + this.applePayData.session.onpaymentauthorized = (function(event) { + this.trigger('applepay.paymentauthorized', event.payment); + }).bind(this); + + this.applePayData.session.oncancel = (function(event) { + var params = {}; + if ('undefined' !== typeof event.sessionError) { + params.error = event.sessionError; + } + this._sendEvent('applepay.cancel', params); + this.trigger('applepay.cancel', params); + }).bind(this); + + if (this.config.walletMode) { + this.applePayData.session.onshippingcontactselected = (function(event) { + this.trigger('applepay.shippingcontactselected', event.shippingContact); + }).bind(this); + this.applePayData.session.onshippingmethodselected = (function(event) { + this.trigger('applepay.shippingmethodselected', event.shippingMethod); + }).bind(this); + } + + this.applePayData.session.begin(); + + }; + + XPaymentsWidget.prototype._parseApplePayNewTotal = function(updateData) + { + this.setOrder(updateData.newTotal.amount); + if ('undefined' != typeof updateData.newTotal && 'undefined' == typeof updateData.newTotal.label) { + updateData.newTotal.label = this.config.company.name; + } + return updateData; + }; + + XPaymentsWidget.prototype.completeApplePayShippingContactSelection = function(updateData) { + this.applePayData.session.completeShippingContactSelection(this._parseApplePayNewTotal(updateData)); + }; + + XPaymentsWidget.prototype.completeApplePayShippingMethodSelection = function(updateData) { + this.applePayData.session.completeShippingMethodSelection(this._parseApplePayNewTotal(updateData)); + }; + + XPaymentsWidget.prototype.completeApplePayPayment = function(updateData) { + this.applePayData.session.completePayment(updateData); + }; + + XPaymentsWidget.prototype.succeedApplePayPayment = function(payment) { + this._sendEvent('applepay.paymentauthorized', { payment: payment }); + }; + + XPaymentsWidget.prototype.isApplePaySupportedByDevice = function() { + return (window.ApplePaySession && ApplePaySession.canMakePayments()); + }; + + XPaymentsWidget.prototype._isApplePayAvailable = function() { + return this.isApplePaySupportedByDevice() + && ( + this.config.enableWallets && this.config.applePay.enabled + || 'applePay' === this.config.walletMode + ); + }; + + XPaymentsWidget.prototype._checkApplePayActiveCard = function() + { + var promise = ApplePaySession.canMakePaymentsWithActiveCard(this.applePayData.merchantId); + promise.then((function (canMakePayments) { + if (canMakePayments) { + this.trigger('applepay.forceselect'); + this._sendEvent('applepay.select'); + } + }).bind(this)); + }; + + XPaymentsWidget.prototype._applePayInit = function(params) + { + this.applePayData.supportedNetworks = params.supportedNetworks; + this.applePayData.merchantCapabilities = params.merchantCapabilities; + this.applePayData.merchantId = params.merchantId; + if (!this.config.walletMode) { + this._checkApplePayActiveCard(); + } + }; + + XPaymentsWidget.prototype._isGooglePayEnabled = function() { + return ( + this.config.enableWallets && this.config.googlePay.enabled + || 'googlePay' === this.config.walletMode + ); + }; + + XPaymentsWidget.prototype._sendGooglePayLoaded = function() + { + var promise = new Promise((function(resolve, reject) { + var counter = 0; + var checkReady = (function() { + counter++; + if (this.googlePayData.libLoaded) { + resolve(); + } else if (counter < 300) { + setTimeout(checkReady, 100); + } else { + this._log('Error! Failed to load Google Pay library.'); + } + }).bind(this); + checkReady(); + }).bind(this)); + + promise.then( + (function() { + this._sendEvent('googlepay.loaded', { origin: this.config.company.domain }); + }).bind(this) + ); + }; + + XPaymentsWidget.prototype._googlePayPrepareBaseRequest = function() + { + var baseRequest = { + apiVersion: 2, + apiVersionMinor: 0, + allowedPaymentMethods: this.googlePayData.paymentMethods, + }; + + return baseRequest; + }; + + XPaymentsWidget.prototype._googlePayPrepareReadyToPay = function(existingRequired) + { + var request = {}; + if ('undefined' !== typeof existingRequired && existingRequired) { + request.existingPaymentMethodRequired = existingRequired; + } + + return Object.assign({}, this._googlePayPrepareBaseRequest(), request); + }; + + XPaymentsWidget.prototype._googlePayPrepareLoadPayment = function(request) + { + var baseRequest = this._googlePayPrepareBaseRequest(); + + for (var key in baseRequest.allowedPaymentMethods) { + baseRequest.allowedPaymentMethods[key].tokenizationSpecification = this.googlePayData.tokenizationSpecification; + if (this.config.walletMode && this.config.googlePay.requiredBillingFields.length) { + baseRequest.allowedPaymentMethods[key].parameters.billingAddressRequired = true; + baseRequest.allowedPaymentMethods[key].parameters.billingAddressParameters = { + format: (-1 !== this.config.googlePay.requiredBillingFields.indexOf('full')) ? 'FULL' : 'MIN', + phoneNumberRequired: (-1 !== this.config.googlePay.requiredBillingFields.indexOf('phone')), + }; + } + + } + + return Object.assign({}, baseRequest, request); + }; + + XPaymentsWidget.prototype._googlePayInit = function(params) + { + this.googlePayData.merchantInfo = { + merchantName: this.config.company.name, + merchantOrigin: this.config.company.domain, + merchantId: params.businessId, + }; + if (params.authJwt) { + this.googlePayData.merchantInfo.authJwt = params.authJwt; + } + + this.googlePayData.tokenizationSpecification = { + type: 'PAYMENT_GATEWAY', + parameters: { + gateway: params.gatewayId, + gatewayMerchantId: params.merchantId, + } + }; + + var options = { + environment: params.environment, + merchantInfo: this.googlePayData.merchantInfo, + paymentDataCallbacks: { + onPaymentAuthorized: (function(paymentData) { + return this.trigger('googlepay.paymentauthorized', paymentData, true); + }).bind(this), + } + }; + + if (this.config.walletMode && this.config.googlePay.requiredShippingFields.length) { + options.paymentDataCallbacks.onPaymentDataChanged = (function(intermediatePaymentData) { + return this.trigger('googlepay.paymentdatachanged', intermediatePaymentData); + }).bind(this); + } + + this.googlePayData.client = new google.payments.api.PaymentsClient(options); + + this.googlePayData.paymentMethods = []; + for (var key in params.paymentMethods) { + this.googlePayData.paymentMethods.push({ + type: params.paymentMethods[key], + parameters: { + allowedAuthMethods: params.authMethods, + allowedCardNetworks: params.supportedNetworks + } + }); + } + + var request = this._googlePayPrepareReadyToPay(); + + this.googlePayData.client.isReadyToPay(request) + .then((function(response) { + if (response.result) { + this._sendEvent('googlepay.enable'); + this.trigger('googlepay.ready'); + } else { + this.trigger('googlepay.nonready'); + } + }).bind(this)) + .catch((function(err) { + this._log(err); + }).bind(this)); + }; + + XPaymentsWidget.prototype._googlePayStart = function(params) + { + if (!this.googlePayData.client) { + this._sendEvent('googlepay.cancel', { alert: true }); + return; + } + + var request = { + merchantInfo: this.googlePayData.merchantInfo, + transactionInfo: { + totalPriceStatus: 'FINAL', + totalPrice: this.config.order.total.toString(), + currencyCode: this.config.order.currency, + countryCode: this.config.company.countryCode, + }, + callbackIntents: [ + 'PAYMENT_AUTHORIZATION', + ], + }; + + if (this.config.walletMode && this.config.googlePay.requiredShippingFields.length) { + // We need to add displayItems because them won't show after finalization otherwise + request.transactionInfo.displayItems = [ + { + label: 'Subtotal', + type: 'SUBTOTAL', + price: this.config.order.total.toString(), + } + ]; + request.transactionInfo.totalPriceStatus = 'ESTIMATED'; + request.transactionInfo.totalPriceLabel = 'Total'; + + request.callbackIntents.push('SHIPPING_ADDRESS'); + request.shippingAddressRequired = true; + request.shippingAddressParameters = { + phoneNumberRequired: (-1 !== this.config.googlePay.requiredShippingFields.indexOf('phone')) + }; + request.emailRequired = (-1 !== this.config.googlePay.requiredShippingFields.indexOf('email')); + + if (this.config.googlePay.shippingMethods.length) { + request.callbackIntents.push('SHIPPING_OPTION'); + request.shippingOptionRequired = true; + } + } + + request = this._googlePayPrepareLoadPayment(request); + + this.googlePayData.client.loadPaymentData(request) + .then((function(paymentData) { + // Successful response parsed in googlepay.paymentauthorized + }).bind(this)) + .catch((function(err) { + this._sendEvent('googlepay.cancel', { error: err }); + this.trigger('googlepay.cancel'); + }).bind(this)); + }; + + XPaymentsWidget.prototype._googlePayAuthorized = function(paymentData) + { + return new Promise((function(resolve, reject) { + resolve(this.succeedGooglePayPayment(paymentData)); + }).bind(this)); + }; + + XPaymentsWidget.prototype._googlePayError = function(params) + { + // Do nothing + }; + + XPaymentsWidget.prototype.succeedGooglePayPayment = function(paymentData) { + this._sendEvent('googlepay.paymentauthorized', { payment: paymentData.paymentMethodData }); + return { transactionState: 'SUCCESS' }; + }; + + XPaymentsWidget.prototype.isGooglePayInitialized = function(options) + { + return (null !== this.googlePayData.client); + }; + + XPaymentsWidget.prototype.createApplePayButton = function(options) + { + if (!this.isApplePaySupportedByDevice()) { + console.error('Apple Pay is not supported by the device'); + return null; + } + + var buttonOptions = { + onClick: (function() { + this.trigger('applepay.buttonclick'); + }).bind(this), + wrapperClass: 'apple-pay-button-wrapper', + buttonClass: 'apple-pay-button', + buttonContent: '', + }; + + if ('undefined' !== typeof options) { + buttonOptions = Object.assign({}, buttonOptions, options); + } + + var wrapper = document.createElement('div'); + wrapper.className = buttonOptions.wrapperClass; + + var button = document.createElement('button'); + button.className = buttonOptions.buttonClass; + button.type = 'button'; + button.innerHTML = buttonOptions.buttonContent; + button.addEventListener('click', buttonOptions.onClick); + + wrapper.appendChild(button); + + return wrapper; + }; + + + XPaymentsWidget.prototype.createGooglePayButton = function(options) + { + if (!this.isGooglePayInitialized()) { + console.error('Google Pay not initalized'); + return null; + } + + var buttonOptions = { + onClick: (function() { + this.trigger('googlepay.buttonclick'); + }).bind(this) + }; + + if ('undefined' !== typeof options) { + buttonOptions = Object.assign({}, buttonOptions, options); + } + + return this.googlePayData.client.createButton(buttonOptions); + }; + + XPaymentsWidget.prototype.setWalletMode = function(walletId) + { + this.config.walletMode = walletId; + }; + + XPaymentsWidget.prototype.showSaveCard = function(value) + { + if ('undefined' === typeof value) { + value = this.config.showSaveCard; + } else { + this.config.showSaveCard = (true === value); + } + this._sendEvent('savecard', { show: value }); + }; + + + XPaymentsWidget.prototype.refresh = function() + { + this._sendEvent('refresh'); + }; + + XPaymentsWidget.prototype.resize = function(height) + { + var elm = this.getIframeElm(); + if (elm) { + this.previousHeight = elm.style.height; + elm.style.height = height + 'px'; + } + }; + + XPaymentsWidget.prototype.setOrder = function(total, currency) + { + if ('undefined' !== typeof total) { + this.config.order.total = total; + } + if ('undefined' !== typeof currency) { + this.config.order.currency = currency; + } + + this._sendEvent('details', { + tokenizeCard: this.config.order.tokenizeCard, + total: this.config.order.total, + currency: this.config.order.currency + }); + }; + + XPaymentsWidget.prototype.destroy = function() + { + if (this.bindedListener) { + window.removeEventListener('message', this.bindedListener); + } + + var formElm = this.getFormElm(); + if (this.bindedSubmit && formElm) { + formElm.removeEventListener('submit', this.bindedSubmit); + } + + var containerElm = this.getContainerElm(); + if (containerElm) { + var elm = this.getIframeElm(); + if (elm && containerElm.contains(elm)) { + containerElm.removeChild(elm); + } + } + }; + + XPaymentsWidget.prototype.messageListener = function(event) + { + if (window.JSON) { + var msg = false; + if (-1 !== this.getServerUrl().toLowerCase().indexOf(event.origin.toLowerCase())) { + try { + msg = window.JSON.parse(event.data); + } catch (e) { + // Skip invalid messages + } + } + + if ( + msg && + msg.event && + 0 === msg.event.indexOf(this.messageNamespace) && + (!msg.widgetId || msg.widgetId === this.widgetId) + ) { + this._log('Received from X-Payments: ' + msg.event, msg.params); + + var eventType = msg.event.substr(this.messageNamespace.length); + + if ('loaded' === eventType) { + this._afterLoad(msg.params); + } else if ('applepay.start' === eventType) { + this._applePayStart(msg.params); + } else if ('applepay.init' === eventType) { + this._applePayInit(msg.params); + } else if ('applepay.merchantvalidated' === eventType) { + this._applePayValidated(msg.params); + } else if ('applepay.completed' === eventType) { + this._applePayCompleted(msg.params); + } else if ('applepay.error' === eventType) { + this._applePayError(msg.params); + } else if ('googlepay.init' === eventType) { + this._googlePayInit(msg.params); + } else if ('googlepay.start' === eventType) { + this._googlePayStart(msg.params); + } else if ('googlepay.error' === eventType) { + this._googlePayError(msg.params); + } else if ('paymentmethod.change' === eventType) { + this._paymentMethodChange(msg.params); + } else if ('resize' === eventType) { + this.resize(msg.params.height); + } else if ('alert' === eventType) { + msg.params.message = + ('string' === typeof msg.params.message) + ? msg.params.message.replace(/<\/?[^>]+>/gi, '') + : ''; + } + + this.trigger(eventType, msg.params); + } + + } + }; + + XPaymentsWidget.prototype._isDebugMode = function() + { + return this.config.debug; + }; + + XPaymentsWidget.prototype._log = function(msg, params) + { + if (this._isDebugMode()) { + console.groupCollapsed(msg); + if ('undefined' !== typeof params) { + console.log(JSON.stringify(params)); + } + console.trace(); + console.groupEnd(); + } + }; + + XPaymentsWidget.prototype._sendEvent = function(eventName, eventParams) + { + if ('undefined' === typeof eventParams) { + eventParams = {}; + } + + this._postMessage({ + event: this.receiverNamespace + eventName, + params: eventParams + }); + }; + + XPaymentsWidget.prototype._postMessage = function(message) + { + var elm = this.getIframeElm(); + if ( + window.postMessage + && window.JSON + && elm + && elm.contentWindow + ) { + this._log('Sent to X-Payments: ' + message.event, message.params); + elm.contentWindow.postMessage(window.JSON.stringify(message), '*'); + } else { + this._log('Error sending message - iframe wasn\'t initialized!'); + } + }; + + return XPaymentsWidget; + +})(); diff --git a/js/dist/widget.min.js b/js/dist/widget.min.js new file mode 100644 index 0000000..ad77e50 --- /dev/null +++ b/js/dist/widget.min.js @@ -0,0 +1 @@ +!function(){"use strict";const e=function(){this.jsApiVersion="2.0",this.serverDomain="xpayments.com",this.messageNamespace="xpayments.widget.",this.receiverNamespace="xpayments.checkout.",this.widgetId=this.generateId(),this.previousHeight=-1,this.applePayData={session:null,supportedNetworks:[],merchantCapabilities:[],merchantId:""},this.googlePayData={client:null,libUrl:"https://pay.google.com/gp/p/js/pay.js",libLoaded:!1,paymentMethods:{},merchantInfo:{},tokenizationSpecification:{}},this.paymentMethod=null,this.config={debug:!1,account:"",widgetKey:"",container:"",form:"",language:"",customerId:"",tokenName:"xpaymentsToken",showSaveCard:!0,enableWallets:!0,applePay:{enabled:!1,shippingMethods:[],requiredShippingFields:[],requiredBillingFields:[]},googlePay:{enabled:!1,shippingMethods:[],requiredShippingFields:[],requiredBillingFields:[]},walletMode:"",company:{name:"",domain:document.location.hostname,countryCode:""},order:{tokenizeCard:!1,total:-1,currency:""}},this.handlers={},this.bindedListener=!1,this.bindedSubmit=!1};e.prototype.on=function(e,t,i){if(void 0===i&&(i=this),"formSubmit"!==e)this.handlers[e]=t.bind(i);else{var o=this.getFormElm();o&&(this.bindedSubmit&&o.removeEventListener("submit",this.bindedSubmit),this.bindedSubmit=t.bind(i),o.addEventListener("submit",this.bindedSubmit))}return this},e.prototype.trigger=function(e,t){var i=null;return"function"==typeof this.handlers[e]&&(i=this.handlers[e](t)),this._log("X-Payments widget triggered: "+e,t),i},e.prototype.init=function(e){for(var t in e)if(void 0!==this.config[t])if("object"==typeof this.config[t])for(var i in e[t])void 0!==this.config[t][i]&&(this.config[t][i]=e[t][i]);else this.config[t]=e[t];return this.config.order.tokenizeCard&&(this.config.showSaveCard=!1),this.on("formSubmit",(function(e){this.isValid()&&(this.submit(),e.preventDefault())})).on("success",this._defaultSuccessHandler).on("applepay.paymentauthorized",this._applePayAuthorized).on("applepay.buttonclick",(function(){this.isValid()&&this.submit()})).on("googlepay.paymentauthorized",this._googlePayAuthorized).on("googlepay.buttonclick",(function(){this.isValid()&&this.submit()})).on("alert",(function(e){window.alert(e.message)})),this.bindedListener=this.messageListener.bind(this),window.addEventListener("message",this.bindedListener),void 0!==e.autoload&&e.autoload&&this.load(),this},e.prototype.generateId=function(){return Math.random().toString(36).substring(2,15)+Math.random().toString(36).substring(2,15)},e.prototype.getIframeId=function(){return"xpayments-"+this.widgetId},e.prototype.getIframeElm=function(){return document.getElementById(this.getIframeId())},e.prototype.getContainerElm=function(){return this.safeQuerySelector(this.config.container)},e.prototype.getFormElm=function(){return this.safeQuerySelector(this.config.form)},e.prototype.isValid=function(){return this.getIframeElm()&&this.getFormElm()},e.prototype.safeQuerySelector=function(e){var t=!1;return e&&(t=document.querySelector(e)),t},e.prototype.loadAsyncJS=function(e,t){var i=document.createElement("script");i.type="text/javascript",i.async=!0,i.onload=t,i.src=e,document.getElementsByTagName("head")[0].appendChild(i)},e.prototype.load=function(){var e=this.getContainerElm();if(!e)return this;var t=this.getIframeElm();t||((t=document.createElement("iframe")).id=this.getIframeId(),t.style.width="100%",t.style.height="0",t.style.overflow="hidden",t.style.border="none",this.config.walletMode&&(t.style.display="none"),t.setAttribute("scrolling","no"),e.appendChild(t));var i=this.getServerUrl()+"/payment.php?widget_key="+encodeURIComponent(this.config.widgetKey)+"&widget_id="+encodeURIComponent(this.widgetId)+"&shop="+encodeURIComponent(this.config.company.domain)+"&api_version="+encodeURIComponent(this.jsApiVersion);return this.config.customerId&&(i+="&customer_id="+encodeURIComponent(this.config.customerId)),this.config.language&&(i+="&language="+encodeURIComponent(this.config.language)),this.config.walletMode&&(i+="&target=wallet&mode="+encodeURIComponent(this.config.walletMode)),t.src=i,this._isGooglePayEnabled()&&this.loadAsyncJS(this.googlePayData.libUrl,function(){this.googlePayData.libLoaded=!0}.bind(this)),this},e.prototype.getServerHost=function(){return this.config.account+"."+this.serverDomain},e.prototype.getServerUrl=function(){return"https://"+this.getServerHost()},e.prototype.submit=function(){if(this.config.walletMode)switch(this.getPaymentMethod()){case"applePay":this.trigger("applepay.start"),this._applePayStart();break;case"googlePay":this.trigger("googlepay.start"),this._googlePayStart()}else this._sendEvent("submit")},e.prototype.beginCheckoutWithWallet=function(){this.submit()},e.prototype._afterLoad=function(e){this.showSaveCard(),this._isApplePayAvailable()&&this._sendEvent("applepay.enable"),this._isGooglePayEnabled()&&this._sendGooglePayLoaded(),this.setOrder(),this.resize(e.height)},e.prototype._defaultSuccessHandler=function(e){var t=this.getFormElm();if(t){var i=document.getElementById(this.config.tokenName);i||((i=document.createElement("input")).type="hidden",i.name=i.id=this.config.tokenName,t.appendChild(i)),i.value=e.token,t.submit()}},e.prototype.getPaymentMethod=function(){return this.config.walletMode||this.paymentMethod},e.prototype._paymentMethodChange=function(e){this.paymentMethod=e.newId},e.prototype._applePayValidated=function(e){try{this.applePayData.session.completeMerchantValidation(e.data)}catch(e){}},e.prototype._applePayAuthorized=function(e){this.succeedApplePayPayment(e)},e.prototype._applePayCompleted=function(e){this.completeApplePayPayment({status:ApplePaySession.STATUS_SUCCESS,errors:[]})},e.prototype._applePayError=function(e){try{this.applePayData.session.abort()}catch(e){}},e.prototype._applePayStart=function(){if(this.applePayData.merchantCapabilities.length){var e={countryCode:this.config.company.countryCode,currencyCode:this.config.order.currency,supportedNetworks:this.applePayData.supportedNetworks,merchantCapabilities:this.applePayData.merchantCapabilities,total:{label:this.config.company.name,amount:this.config.order.total}};this.applePayCustomerAddress=null,this.config.walletMode&&(this.config.applePay.shippingMethods.length&&(e.shippingMethods=this.config.applePay.shippingMethods),this.config.applePay.requiredShippingFields.length&&(e.requiredShippingContactFields=this.config.applePay.requiredShippingFields),this.config.applePay.requiredBillingFields.length&&(e.requiredBillingContactFields=this.config.applePay.requiredBillingFields)),this.applePayData.session=new ApplePaySession(3,e),this.applePayData.session.onvalidatemerchant=function(e){this._sendEvent("applepay.validatemerchant",{validationURL:e.validationURL,displayName:this.config.company.name,context:this.config.company.domain})}.bind(this),this.applePayData.session.onpaymentauthorized=function(e){this.trigger("applepay.paymentauthorized",e.payment)}.bind(this),this.applePayData.session.oncancel=function(e){var t={};void 0!==e.sessionError&&(t.error=e.sessionError),this._sendEvent("applepay.cancel",t),this.trigger("applepay.cancel",t)}.bind(this),this.config.walletMode&&(this.applePayData.session.onshippingcontactselected=function(e){this.trigger("applepay.shippingcontactselected",e.shippingContact)}.bind(this),this.applePayData.session.onshippingmethodselected=function(e){this.trigger("applepay.shippingmethodselected",e.shippingMethod)}.bind(this)),this.applePayData.session.begin()}else this._sendEvent("applepay.cancel",{alert:!0})},e.prototype._parseApplePayNewTotal=function(e){return this.setOrder(e.newTotal.amount),void 0!==e.newTotal&&void 0===e.newTotal.label&&(e.newTotal.label=this.config.company.name),e},e.prototype.completeApplePayShippingContactSelection=function(e){this.applePayData.session.completeShippingContactSelection(this._parseApplePayNewTotal(e))},e.prototype.completeApplePayShippingMethodSelection=function(e){this.applePayData.session.completeShippingMethodSelection(this._parseApplePayNewTotal(e))},e.prototype.completeApplePayPayment=function(e){this.applePayData.session.completePayment(e)},e.prototype.succeedApplePayPayment=function(e){this._sendEvent("applepay.paymentauthorized",{payment:e})},e.prototype.isApplePaySupportedByDevice=function(){return window.ApplePaySession&&ApplePaySession.canMakePayments()},e.prototype._isApplePayAvailable=function(){return this.isApplePaySupportedByDevice()&&(this.config.enableWallets&&this.config.applePay.enabled||"applePay"===this.config.walletMode)},e.prototype._checkApplePayActiveCard=function(){ApplePaySession.canMakePaymentsWithActiveCard(this.applePayData.merchantId).then(function(e){e&&(this.trigger("applepay.forceselect"),this._sendEvent("applepay.select"))}.bind(this))},e.prototype._applePayInit=function(e){this.applePayData.supportedNetworks=e.supportedNetworks,this.applePayData.merchantCapabilities=e.merchantCapabilities,this.applePayData.merchantId=e.merchantId,this.config.walletMode||this._checkApplePayActiveCard()},e.prototype._isGooglePayEnabled=function(){return this.config.enableWallets&&this.config.googlePay.enabled||"googlePay"===this.config.walletMode},e.prototype._sendGooglePayLoaded=function(){new Promise(function(e,t){var i=0,o=function(){i++,this.googlePayData.libLoaded?e():i<300?setTimeout(o,100):this._log("Error! Failed to load Google Pay library.")}.bind(this);o()}.bind(this)).then(function(){this._sendEvent("googlepay.loaded",{origin:this.config.company.domain})}.bind(this))},e.prototype._googlePayPrepareBaseRequest=function(){return{apiVersion:2,apiVersionMinor:0,allowedPaymentMethods:this.googlePayData.paymentMethods}},e.prototype._googlePayPrepareReadyToPay=function(e){var t={};return void 0!==e&&e&&(t.existingPaymentMethodRequired=e),Object.assign({},this._googlePayPrepareBaseRequest(),t)},e.prototype._googlePayPrepareLoadPayment=function(e){var t=this._googlePayPrepareBaseRequest();for(var i in t.allowedPaymentMethods)t.allowedPaymentMethods[i].tokenizationSpecification=this.googlePayData.tokenizationSpecification,this.config.walletMode&&this.config.googlePay.requiredBillingFields.length&&(t.allowedPaymentMethods[i].parameters.billingAddressRequired=!0,t.allowedPaymentMethods[i].parameters.billingAddressParameters={format:-1!==this.config.googlePay.requiredBillingFields.indexOf("full")?"FULL":"MIN",phoneNumberRequired:-1!==this.config.googlePay.requiredBillingFields.indexOf("phone")});return Object.assign({},t,e)},e.prototype._googlePayInit=function(e){this.googlePayData.merchantInfo={merchantName:this.config.company.name,merchantOrigin:this.config.company.domain,merchantId:e.businessId},e.authJwt&&(this.googlePayData.merchantInfo.authJwt=e.authJwt),this.googlePayData.tokenizationSpecification={type:"PAYMENT_GATEWAY",parameters:{gateway:e.gatewayId,gatewayMerchantId:e.merchantId}};var t={environment:e.environment,merchantInfo:this.googlePayData.merchantInfo,paymentDataCallbacks:{onPaymentAuthorized:function(e){return this.trigger("googlepay.paymentauthorized",e,!0)}.bind(this)}};for(var i in this.config.walletMode&&this.config.googlePay.requiredShippingFields.length&&(t.paymentDataCallbacks.onPaymentDataChanged=function(e){return this.trigger("googlepay.paymentdatachanged",e)}.bind(this)),this.googlePayData.client=new google.payments.api.PaymentsClient(t),this.googlePayData.paymentMethods=[],e.paymentMethods)this.googlePayData.paymentMethods.push({type:e.paymentMethods[i],parameters:{allowedAuthMethods:e.authMethods,allowedCardNetworks:e.supportedNetworks}});var o=this._googlePayPrepareReadyToPay();this.googlePayData.client.isReadyToPay(o).then(function(e){e.result?(this._sendEvent("googlepay.enable"),this.trigger("googlepay.ready")):this.trigger("googlepay.nonready")}.bind(this)).catch(function(e){this._log(e)}.bind(this))},e.prototype._googlePayStart=function(e){if(this.googlePayData.client){var t={merchantInfo:this.googlePayData.merchantInfo,transactionInfo:{totalPriceStatus:"FINAL",totalPrice:this.config.order.total.toString(),currencyCode:this.config.order.currency,countryCode:this.config.company.countryCode},callbackIntents:["PAYMENT_AUTHORIZATION"]};this.config.walletMode&&this.config.googlePay.requiredShippingFields.length&&(t.transactionInfo.displayItems=[{label:"Subtotal",type:"SUBTOTAL",price:this.config.order.total.toString()}],t.transactionInfo.totalPriceStatus="ESTIMATED",t.transactionInfo.totalPriceLabel="Total",t.callbackIntents.push("SHIPPING_ADDRESS"),t.shippingAddressRequired=!0,t.shippingAddressParameters={phoneNumberRequired:-1!==this.config.googlePay.requiredShippingFields.indexOf("phone")},t.emailRequired=-1!==this.config.googlePay.requiredShippingFields.indexOf("email"),this.config.googlePay.shippingMethods.length&&(t.callbackIntents.push("SHIPPING_OPTION"),t.shippingOptionRequired=!0)),t=this._googlePayPrepareLoadPayment(t),this.googlePayData.client.loadPaymentData(t).then(function(e){}.bind(this)).catch(function(e){this._sendEvent("googlepay.cancel",{error:e}),this.trigger("googlepay.cancel")}.bind(this))}else this._sendEvent("googlepay.cancel",{alert:!0})},e.prototype._googlePayAuthorized=function(e){return new Promise(function(t,i){t(this.succeedGooglePayPayment(e))}.bind(this))},e.prototype._googlePayError=function(e){},e.prototype.succeedGooglePayPayment=function(e){return this._sendEvent("googlepay.paymentauthorized",{payment:e.paymentMethodData}),{transactionState:"SUCCESS"}},e.prototype.isGooglePayInitialized=function(e){return null!==this.googlePayData.client},e.prototype.createApplePayButton=function(e){if(!this.isApplePaySupportedByDevice())return console.error("Apple Pay is not supported by the device"),null;var t={onClick:function(){this.trigger("applepay.buttonclick")}.bind(this),wrapperClass:"apple-pay-button-wrapper",buttonClass:"apple-pay-button",buttonContent:""};void 0!==e&&(t=Object.assign({},t,e));var i=document.createElement("div");i.className=t.wrapperClass;var o=document.createElement("button");return o.className=t.buttonClass,o.type="button",o.innerHTML=t.buttonContent,o.addEventListener("click",t.onClick),i.appendChild(o),i},e.prototype.createGooglePayButton=function(e){if(!this.isGooglePayInitialized())return console.error("Google Pay not initalized"),null;var t={onClick:function(){this.trigger("googlepay.buttonclick")}.bind(this)};return void 0!==e&&(t=Object.assign({},t,e)),this.googlePayData.client.createButton(t)},e.prototype.setWalletMode=function(e){this.config.walletMode=e},e.prototype.showSaveCard=function(e){void 0===e?e=this.config.showSaveCard:this.config.showSaveCard=!0===e,this._sendEvent("savecard",{show:e})},e.prototype.refresh=function(){this._sendEvent("refresh")},e.prototype.resize=function(e){var t=this.getIframeElm();t&&(this.previousHeight=t.style.height,t.style.height=e+"px")},e.prototype.setOrder=function(e,t){void 0!==e&&(this.config.order.total=e),void 0!==t&&(this.config.order.currency=t),this._sendEvent("details",{tokenizeCard:this.config.order.tokenizeCard,total:this.config.order.total,currency:this.config.order.currency})},e.prototype.destroy=function(){this.bindedListener&&window.removeEventListener("message",this.bindedListener);var e=this.getFormElm();this.bindedSubmit&&e&&e.removeEventListener("submit",this.bindedSubmit);var t=this.getContainerElm();if(t){var i=this.getIframeElm();i&&t.contains(i)&&t.removeChild(i)}},e.prototype.messageListener=function(e){if(window.JSON){var t=!1;if(-1!==this.getServerUrl().toLowerCase().indexOf(e.origin.toLowerCase()))try{t=window.JSON.parse(e.data)}catch(e){}if(t&&t.event&&0===t.event.indexOf(this.messageNamespace)&&(!t.widgetId||t.widgetId===this.widgetId)){this._log("Received from X-Payments: "+t.event,t.params);var i=t.event.substr(this.messageNamespace.length);"loaded"===i?this._afterLoad(t.params):"applepay.start"===i?this._applePayStart(t.params):"applepay.init"===i?this._applePayInit(t.params):"applepay.merchantvalidated"===i?this._applePayValidated(t.params):"applepay.completed"===i?this._applePayCompleted(t.params):"applepay.error"===i?this._applePayError(t.params):"googlepay.init"===i?this._googlePayInit(t.params):"googlepay.start"===i?this._googlePayStart(t.params):"googlepay.error"===i?this._googlePayError(t.params):"paymentmethod.change"===i?this._paymentMethodChange(t.params):"resize"===i?this.resize(t.params.height):"alert"===i&&(t.params.message="string"==typeof t.params.message?t.params.message.replace(/<\/?[^>]+>/gi,""):""),this.trigger(i,t.params)}}},e.prototype._isDebugMode=function(){return this.config.debug},e.prototype._log=function(e,t){this._isDebugMode()&&(console.groupCollapsed(e),void 0!==t&&console.log(JSON.stringify(t)),console.trace(),console.groupEnd())},e.prototype._sendEvent=function(e,t){void 0===t&&(t={}),this._postMessage({event:this.receiverNamespace+e,params:t})},e.prototype._postMessage=function(e){var t=this.getIframeElm();window.postMessage&&window.JSON&&t&&t.contentWindow?(this._log("Sent to X-Payments: "+e.event,e.params),t.contentWindow.postMessage(window.JSON.stringify(e),"*")):this._log("Error sending message - iframe wasn't initialized!")}}(); diff --git a/js/package-lock.json b/js/package-lock.json new file mode 100644 index 0000000..3a2e639 --- /dev/null +++ b/js/package-lock.json @@ -0,0 +1,650 @@ +{ + "name": "cloud-sdk-js", + "version": "0.3.0", + "lockfileVersion": 2, + "requires": true, + "packages": { + "": { + "name": "cloud-sdk-js", + "version": "0.3.0", + "license": "ISC", + "devDependencies": { + "@rollup/plugin-terser": "^0.4.4", + "rollup": "^4.5.0" + } + }, + "node_modules/@jridgewell/gen-mapping": { + "version": "0.3.3", + "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.3.tgz", + "integrity": "sha512-HLhSWOLRi875zjjMG/r+Nv0oCW8umGb0BgEhyX3dDX3egwZtB8PqLnjz3yedt8R5StBrzcg4aBpnh8UA9D1BoQ==", + "dev": true, + "dependencies": { + "@jridgewell/set-array": "^1.0.1", + "@jridgewell/sourcemap-codec": "^1.4.10", + "@jridgewell/trace-mapping": "^0.3.9" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/resolve-uri": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.1.tgz", + "integrity": "sha512-dSYZh7HhCDtCKm4QakX0xFpsRDqjjtZf/kjI/v3T3Nwt5r8/qz/M19F9ySyOqU94SXBmeG9ttTul+YnR4LOxFA==", + "dev": true, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/set-array": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.1.2.tgz", + "integrity": "sha512-xnkseuNADM0gt2bs+BvhO0p78Mk762YnZdsuzFV018NoG1Sj1SCQvpSqa7XUaTam5vAGasABV9qXASMKnFMwMw==", + "dev": true, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/source-map": { + "version": "0.3.5", + "resolved": "https://registry.npmjs.org/@jridgewell/source-map/-/source-map-0.3.5.tgz", + "integrity": "sha512-UTYAUj/wviwdsMfzoSJspJxbkH5o1snzwX0//0ENX1u/55kkZZkcTZP6u9bwKGkv+dkk9at4m1Cpt0uY80kcpQ==", + "dev": true, + "dependencies": { + "@jridgewell/gen-mapping": "^0.3.0", + "@jridgewell/trace-mapping": "^0.3.9" + } + }, + "node_modules/@jridgewell/sourcemap-codec": { + "version": "1.4.15", + "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.15.tgz", + "integrity": "sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg==", + "dev": true + }, + "node_modules/@jridgewell/trace-mapping": { + "version": "0.3.20", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.20.tgz", + "integrity": "sha512-R8LcPeWZol2zR8mmH3JeKQ6QRCFb7XgUhV9ZlGhHLGyg4wpPiPZNQOOWhFZhxKw8u//yTbNGI42Bx/3paXEQ+Q==", + "dev": true, + "dependencies": { + "@jridgewell/resolve-uri": "^3.1.0", + "@jridgewell/sourcemap-codec": "^1.4.14" + } + }, + "node_modules/@rollup/plugin-terser": { + "version": "0.4.4", + "resolved": "https://registry.npmjs.org/@rollup/plugin-terser/-/plugin-terser-0.4.4.tgz", + "integrity": "sha512-XHeJC5Bgvs8LfukDwWZp7yeqin6ns8RTl2B9avbejt6tZqsqvVoWI7ZTQrcNsfKEDWBTnTxM8nMDkO2IFFbd0A==", + "dev": true, + "dependencies": { + "serialize-javascript": "^6.0.1", + "smob": "^1.0.0", + "terser": "^5.17.4" + }, + "engines": { + "node": ">=14.0.0" + }, + "peerDependencies": { + "rollup": "^2.0.0||^3.0.0||^4.0.0" + }, + "peerDependenciesMeta": { + "rollup": { + "optional": true + } + } + }, + "node_modules/@rollup/rollup-android-arm-eabi": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.5.0.tgz", + "integrity": "sha512-OINaBGY+Wc++U0rdr7BLuFClxcoWaVW3vQYqmQq6B3bqQ/2olkaoz+K8+af/Mmka/C2yN5j+L9scBkv4BtKsDA==", + "cpu": [ + "arm" + ], + "dev": true, + "optional": true, + "os": [ + "android" + ] + }, + "node_modules/@rollup/rollup-android-arm64": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.5.0.tgz", + "integrity": "sha512-UdMf1pOQc4ZmUA/NTmKhgJTBimbSKnhPS2zJqucqFyBRFPnPDtwA8MzrGNTjDeQbIAWfpJVAlxejw+/lQyBK/w==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "android" + ] + }, + "node_modules/@rollup/rollup-darwin-arm64": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.5.0.tgz", + "integrity": "sha512-L0/CA5p/idVKI+c9PcAPGorH6CwXn6+J0Ys7Gg1axCbTPgI8MeMlhA6fLM9fK+ssFhqogMHFC8HDvZuetOii7w==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/@rollup/rollup-darwin-x64": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.5.0.tgz", + "integrity": "sha512-QZCbVqU26mNlLn8zi/XDDquNmvcr4ON5FYAHQQsyhrHx8q+sQi/6xduoznYXwk/KmKIXG5dLfR0CvY+NAWpFYQ==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/@rollup/rollup-linux-arm-gnueabihf": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.5.0.tgz", + "integrity": "sha512-VpSQ+xm93AeV33QbYslgf44wc5eJGYfYitlQzAi3OObu9iwrGXEnmu5S3ilkqE3Pr/FkgOiJKV/2p0ewf4Hrtg==", + "cpu": [ + "arm" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-arm64-gnu": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.5.0.tgz", + "integrity": "sha512-OrEyIfpxSsMal44JpEVx9AEcGpdBQG1ZuWISAanaQTSMeStBW+oHWwOkoqR54bw3x8heP8gBOyoJiGg+fLY8qQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-arm64-musl": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.5.0.tgz", + "integrity": "sha512-1H7wBbQuE6igQdxMSTjtFfD+DGAudcYWhp106z/9zBA8OQhsJRnemO4XGavdzHpGhRtRxbgmUGdO3YQgrWf2RA==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-x64-gnu": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.5.0.tgz", + "integrity": "sha512-FVyFI13tXw5aE65sZdBpNjPVIi4Q5mARnL/39UIkxvSgRAIqCo5sCpCELk0JtXHGee2owZz5aNLbWNfBHzr71Q==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-x64-musl": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.5.0.tgz", + "integrity": "sha512-eBPYl2sLpH/o8qbSz6vPwWlDyThnQjJfcDOGFbNjmjb44XKC1F5dQfakOsADRVrXCNzM6ZsSIPDG5dc6HHLNFg==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-win32-arm64-msvc": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.5.0.tgz", + "integrity": "sha512-xaOHIfLOZypoQ5U2I6rEaugS4IYtTgP030xzvrBf5js7p9WI9wik07iHmsKaej8Z83ZDxN5GyypfoyKV5O5TJA==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@rollup/rollup-win32-ia32-msvc": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.5.0.tgz", + "integrity": "sha512-Al6quztQUrHwcOoU2TuFblUQ5L+/AmPBXFR6dUvyo4nRj2yQRK0WIUaGMF/uwKulvRcXkpHe3k9A8Vf93VDktA==", + "cpu": [ + "ia32" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@rollup/rollup-win32-x64-msvc": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.5.0.tgz", + "integrity": "sha512-8kdW+brNhI/NzJ4fxDufuJUjepzINqJKLGHuxyAtpPG9bMbn8P5mtaCcbOm0EzLJ+atg+kF9dwg8jpclkVqx5w==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/acorn": { + "version": "8.11.2", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.11.2.tgz", + "integrity": "sha512-nc0Axzp/0FILLEVsm4fNwLCwMttvhEI263QtVPQcbpfZZ3ts0hLsZGOpE6czNlid7CJ9MlyH8reXkpsf3YUY4w==", + "dev": true, + "bin": { + "acorn": "bin/acorn" + }, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/buffer-from": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", + "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==", + "dev": true + }, + "node_modules/commander": { + "version": "2.20.3", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", + "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==", + "dev": true + }, + "node_modules/fsevents": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", + "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", + "dev": true, + "hasInstallScript": true, + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^8.16.0 || ^10.6.0 || >=11.0.0" + } + }, + "node_modules/randombytes": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz", + "integrity": "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==", + "dev": true, + "dependencies": { + "safe-buffer": "^5.1.0" + } + }, + "node_modules/rollup": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.5.0.tgz", + "integrity": "sha512-41xsWhzxqjMDASCxH5ibw1mXk+3c4TNI2UjKbLxe6iEzrSQnqOzmmK8/3mufCPbzHNJ2e04Fc1ddI35hHy+8zg==", + "dev": true, + "bin": { + "rollup": "dist/bin/rollup" + }, + "engines": { + "node": ">=18.0.0", + "npm": ">=8.0.0" + }, + "optionalDependencies": { + "@rollup/rollup-android-arm-eabi": "4.5.0", + "@rollup/rollup-android-arm64": "4.5.0", + "@rollup/rollup-darwin-arm64": "4.5.0", + "@rollup/rollup-darwin-x64": "4.5.0", + "@rollup/rollup-linux-arm-gnueabihf": "4.5.0", + "@rollup/rollup-linux-arm64-gnu": "4.5.0", + "@rollup/rollup-linux-arm64-musl": "4.5.0", + "@rollup/rollup-linux-x64-gnu": "4.5.0", + "@rollup/rollup-linux-x64-musl": "4.5.0", + "@rollup/rollup-win32-arm64-msvc": "4.5.0", + "@rollup/rollup-win32-ia32-msvc": "4.5.0", + "@rollup/rollup-win32-x64-msvc": "4.5.0", + "fsevents": "~2.3.2" + } + }, + "node_modules/safe-buffer": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, + "node_modules/serialize-javascript": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-6.0.1.tgz", + "integrity": "sha512-owoXEFjWRllis8/M1Q+Cw5k8ZH40e3zhp/ovX+Xr/vi1qj6QesbyXXViFbpNvWvPNAD62SutwEXavefrLJWj7w==", + "dev": true, + "dependencies": { + "randombytes": "^2.1.0" + } + }, + "node_modules/smob": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/smob/-/smob-1.4.1.tgz", + "integrity": "sha512-9LK+E7Hv5R9u4g4C3p+jjLstaLe11MDsL21UpYaCNmapvMkYhqCV4A/f/3gyH8QjMyh6l68q9xC85vihY9ahMQ==", + "dev": true + }, + "node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/source-map-support": { + "version": "0.5.21", + "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.21.tgz", + "integrity": "sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==", + "dev": true, + "dependencies": { + "buffer-from": "^1.0.0", + "source-map": "^0.6.0" + } + }, + "node_modules/terser": { + "version": "5.24.0", + "resolved": "https://registry.npmjs.org/terser/-/terser-5.24.0.tgz", + "integrity": "sha512-ZpGR4Hy3+wBEzVEnHvstMvqpD/nABNelQn/z2r0fjVWGQsN3bpOLzQlqDxmb4CDZnXq5lpjnQ+mHQLAOpfM5iw==", + "dev": true, + "dependencies": { + "@jridgewell/source-map": "^0.3.3", + "acorn": "^8.8.2", + "commander": "^2.20.0", + "source-map-support": "~0.5.20" + }, + "bin": { + "terser": "bin/terser" + }, + "engines": { + "node": ">=10" + } + } + }, + "dependencies": { + "@jridgewell/gen-mapping": { + "version": "0.3.3", + "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.3.tgz", + "integrity": "sha512-HLhSWOLRi875zjjMG/r+Nv0oCW8umGb0BgEhyX3dDX3egwZtB8PqLnjz3yedt8R5StBrzcg4aBpnh8UA9D1BoQ==", + "dev": true, + "requires": { + "@jridgewell/set-array": "^1.0.1", + "@jridgewell/sourcemap-codec": "^1.4.10", + "@jridgewell/trace-mapping": "^0.3.9" + } + }, + "@jridgewell/resolve-uri": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.1.tgz", + "integrity": "sha512-dSYZh7HhCDtCKm4QakX0xFpsRDqjjtZf/kjI/v3T3Nwt5r8/qz/M19F9ySyOqU94SXBmeG9ttTul+YnR4LOxFA==", + "dev": true + }, + "@jridgewell/set-array": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.1.2.tgz", + "integrity": "sha512-xnkseuNADM0gt2bs+BvhO0p78Mk762YnZdsuzFV018NoG1Sj1SCQvpSqa7XUaTam5vAGasABV9qXASMKnFMwMw==", + "dev": true + }, + "@jridgewell/source-map": { + "version": "0.3.5", + "resolved": "https://registry.npmjs.org/@jridgewell/source-map/-/source-map-0.3.5.tgz", + "integrity": "sha512-UTYAUj/wviwdsMfzoSJspJxbkH5o1snzwX0//0ENX1u/55kkZZkcTZP6u9bwKGkv+dkk9at4m1Cpt0uY80kcpQ==", + "dev": true, + "requires": { + "@jridgewell/gen-mapping": "^0.3.0", + "@jridgewell/trace-mapping": "^0.3.9" + } + }, + "@jridgewell/sourcemap-codec": { + "version": "1.4.15", + "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.15.tgz", + "integrity": "sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg==", + "dev": true + }, + "@jridgewell/trace-mapping": { + "version": "0.3.20", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.20.tgz", + "integrity": "sha512-R8LcPeWZol2zR8mmH3JeKQ6QRCFb7XgUhV9ZlGhHLGyg4wpPiPZNQOOWhFZhxKw8u//yTbNGI42Bx/3paXEQ+Q==", + "dev": true, + "requires": { + "@jridgewell/resolve-uri": "^3.1.0", + "@jridgewell/sourcemap-codec": "^1.4.14" + } + }, + "@rollup/plugin-terser": { + "version": "0.4.4", + "resolved": "https://registry.npmjs.org/@rollup/plugin-terser/-/plugin-terser-0.4.4.tgz", + "integrity": "sha512-XHeJC5Bgvs8LfukDwWZp7yeqin6ns8RTl2B9avbejt6tZqsqvVoWI7ZTQrcNsfKEDWBTnTxM8nMDkO2IFFbd0A==", + "dev": true, + "requires": { + "serialize-javascript": "^6.0.1", + "smob": "^1.0.0", + "terser": "^5.17.4" + } + }, + "@rollup/rollup-android-arm-eabi": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.5.0.tgz", + "integrity": "sha512-OINaBGY+Wc++U0rdr7BLuFClxcoWaVW3vQYqmQq6B3bqQ/2olkaoz+K8+af/Mmka/C2yN5j+L9scBkv4BtKsDA==", + "dev": true, + "optional": true + }, + "@rollup/rollup-android-arm64": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.5.0.tgz", + "integrity": "sha512-UdMf1pOQc4ZmUA/NTmKhgJTBimbSKnhPS2zJqucqFyBRFPnPDtwA8MzrGNTjDeQbIAWfpJVAlxejw+/lQyBK/w==", + "dev": true, + "optional": true + }, + "@rollup/rollup-darwin-arm64": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.5.0.tgz", + "integrity": "sha512-L0/CA5p/idVKI+c9PcAPGorH6CwXn6+J0Ys7Gg1axCbTPgI8MeMlhA6fLM9fK+ssFhqogMHFC8HDvZuetOii7w==", + "dev": true, + "optional": true + }, + "@rollup/rollup-darwin-x64": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.5.0.tgz", + "integrity": "sha512-QZCbVqU26mNlLn8zi/XDDquNmvcr4ON5FYAHQQsyhrHx8q+sQi/6xduoznYXwk/KmKIXG5dLfR0CvY+NAWpFYQ==", + "dev": true, + "optional": true + }, + "@rollup/rollup-linux-arm-gnueabihf": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.5.0.tgz", + "integrity": "sha512-VpSQ+xm93AeV33QbYslgf44wc5eJGYfYitlQzAi3OObu9iwrGXEnmu5S3ilkqE3Pr/FkgOiJKV/2p0ewf4Hrtg==", + "dev": true, + "optional": true + }, + "@rollup/rollup-linux-arm64-gnu": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.5.0.tgz", + "integrity": "sha512-OrEyIfpxSsMal44JpEVx9AEcGpdBQG1ZuWISAanaQTSMeStBW+oHWwOkoqR54bw3x8heP8gBOyoJiGg+fLY8qQ==", + "dev": true, + "optional": true + }, + "@rollup/rollup-linux-arm64-musl": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.5.0.tgz", + "integrity": "sha512-1H7wBbQuE6igQdxMSTjtFfD+DGAudcYWhp106z/9zBA8OQhsJRnemO4XGavdzHpGhRtRxbgmUGdO3YQgrWf2RA==", + "dev": true, + "optional": true + }, + "@rollup/rollup-linux-x64-gnu": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.5.0.tgz", + "integrity": "sha512-FVyFI13tXw5aE65sZdBpNjPVIi4Q5mARnL/39UIkxvSgRAIqCo5sCpCELk0JtXHGee2owZz5aNLbWNfBHzr71Q==", + "dev": true, + "optional": true + }, + "@rollup/rollup-linux-x64-musl": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.5.0.tgz", + "integrity": "sha512-eBPYl2sLpH/o8qbSz6vPwWlDyThnQjJfcDOGFbNjmjb44XKC1F5dQfakOsADRVrXCNzM6ZsSIPDG5dc6HHLNFg==", + "dev": true, + "optional": true + }, + "@rollup/rollup-win32-arm64-msvc": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.5.0.tgz", + "integrity": "sha512-xaOHIfLOZypoQ5U2I6rEaugS4IYtTgP030xzvrBf5js7p9WI9wik07iHmsKaej8Z83ZDxN5GyypfoyKV5O5TJA==", + "dev": true, + "optional": true + }, + "@rollup/rollup-win32-ia32-msvc": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.5.0.tgz", + "integrity": "sha512-Al6quztQUrHwcOoU2TuFblUQ5L+/AmPBXFR6dUvyo4nRj2yQRK0WIUaGMF/uwKulvRcXkpHe3k9A8Vf93VDktA==", + "dev": true, + "optional": true + }, + "@rollup/rollup-win32-x64-msvc": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.5.0.tgz", + "integrity": "sha512-8kdW+brNhI/NzJ4fxDufuJUjepzINqJKLGHuxyAtpPG9bMbn8P5mtaCcbOm0EzLJ+atg+kF9dwg8jpclkVqx5w==", + "dev": true, + "optional": true + }, + "acorn": { + "version": "8.11.2", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.11.2.tgz", + "integrity": "sha512-nc0Axzp/0FILLEVsm4fNwLCwMttvhEI263QtVPQcbpfZZ3ts0hLsZGOpE6czNlid7CJ9MlyH8reXkpsf3YUY4w==", + "dev": true + }, + "buffer-from": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", + "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==", + "dev": true + }, + "commander": { + "version": "2.20.3", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", + "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==", + "dev": true + }, + "fsevents": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", + "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", + "dev": true, + "optional": true + }, + "randombytes": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz", + "integrity": "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==", + "dev": true, + "requires": { + "safe-buffer": "^5.1.0" + } + }, + "rollup": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.5.0.tgz", + "integrity": "sha512-41xsWhzxqjMDASCxH5ibw1mXk+3c4TNI2UjKbLxe6iEzrSQnqOzmmK8/3mufCPbzHNJ2e04Fc1ddI35hHy+8zg==", + "dev": true, + "requires": { + "@rollup/rollup-android-arm-eabi": "4.5.0", + "@rollup/rollup-android-arm64": "4.5.0", + "@rollup/rollup-darwin-arm64": "4.5.0", + "@rollup/rollup-darwin-x64": "4.5.0", + "@rollup/rollup-linux-arm-gnueabihf": "4.5.0", + "@rollup/rollup-linux-arm64-gnu": "4.5.0", + "@rollup/rollup-linux-arm64-musl": "4.5.0", + "@rollup/rollup-linux-x64-gnu": "4.5.0", + "@rollup/rollup-linux-x64-musl": "4.5.0", + "@rollup/rollup-win32-arm64-msvc": "4.5.0", + "@rollup/rollup-win32-ia32-msvc": "4.5.0", + "@rollup/rollup-win32-x64-msvc": "4.5.0", + "fsevents": "~2.3.2" + } + }, + "safe-buffer": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", + "dev": true + }, + "serialize-javascript": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-6.0.1.tgz", + "integrity": "sha512-owoXEFjWRllis8/M1Q+Cw5k8ZH40e3zhp/ovX+Xr/vi1qj6QesbyXXViFbpNvWvPNAD62SutwEXavefrLJWj7w==", + "dev": true, + "requires": { + "randombytes": "^2.1.0" + } + }, + "smob": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/smob/-/smob-1.4.1.tgz", + "integrity": "sha512-9LK+E7Hv5R9u4g4C3p+jjLstaLe11MDsL21UpYaCNmapvMkYhqCV4A/f/3gyH8QjMyh6l68q9xC85vihY9ahMQ==", + "dev": true + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + }, + "source-map-support": { + "version": "0.5.21", + "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.21.tgz", + "integrity": "sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==", + "dev": true, + "requires": { + "buffer-from": "^1.0.0", + "source-map": "^0.6.0" + } + }, + "terser": { + "version": "5.24.0", + "resolved": "https://registry.npmjs.org/terser/-/terser-5.24.0.tgz", + "integrity": "sha512-ZpGR4Hy3+wBEzVEnHvstMvqpD/nABNelQn/z2r0fjVWGQsN3bpOLzQlqDxmb4CDZnXq5lpjnQ+mHQLAOpfM5iw==", + "dev": true, + "requires": { + "@jridgewell/source-map": "^0.3.3", + "acorn": "^8.8.2", + "commander": "^2.20.0", + "source-map-support": "~0.5.20" + } + } + } +} diff --git a/js/package.json b/js/package.json new file mode 100644 index 0000000..382bc9c --- /dev/null +++ b/js/package.json @@ -0,0 +1,28 @@ +{ + "name": "cloud-sdk-js", + "version": "0.3.0", + "description": "X-PAYMENTS CLOUD API", + "type": "module", + "scripts": { + "build": "rollup -c", + "test": "echo \"Error: no test specified\" && exit 1" + }, + "repository": { + "type": "git", + "url": "git+https://github.com/xpayments/cloud-sdk-php.git" + }, + "keywords": [ + "xpayments", + "xcart" + ], + "author": "xpayments", + "license": "ISC", + "bugs": { + "url": "https://github.com/xpayments/cloud-sdk-php/issues" + }, + "homepage": "https://github.com/xpayments/cloud-sdk-php#readme", + "devDependencies": { + "@rollup/plugin-terser": "^0.4.4", + "rollup": "^4.5.0" + } +} diff --git a/js/rollup.config.js b/js/rollup.config.js new file mode 100644 index 0000000..159e5ce --- /dev/null +++ b/js/rollup.config.js @@ -0,0 +1,53 @@ +import terser from '@rollup/plugin-terser'; + +export default [ + { + input: 'src/connect.js', + output: [ + { + file: 'dist/connect.es.js', + format: 'es', + }, + { + file: 'dist/connect.js', + format: 'iife', + } + ], + plugins: [] + }, + { + input: 'src/widget.js', + output: [ + { + file: 'dist/widget.es.js', + format: 'es', + }, + { + file: 'dist/widget.js', + format: 'iife', + } + ], + plugins: [] + }, + { + input: 'src/connect.js', + output: [ + { + file: 'dist/connect.min.js', + format: 'iife', + } + ], + plugins: [terser()] + }, + { + input: 'src/widget.js', + output: [ + { + file: 'dist/widget.min.js', + format: 'iife', + } + ], + plugins: [terser()] + } +]; + diff --git a/js/connect.js b/js/src/connect.js similarity index 99% rename from js/connect.js rename to js/src/connect.js index 4929cca..8a631a6 100644 --- a/js/connect.js +++ b/js/src/connect.js @@ -183,4 +183,6 @@ XPaymentsConnect.prototype.log = function(msg) { if (this.config.debug) { console.log(msg); } -} \ No newline at end of file +} + +export default XPaymentsConnect \ No newline at end of file diff --git a/js/widget.js b/js/src/widget.js similarity index 99% rename from js/widget.js rename to js/src/widget.js index 57fdb9b..b9f2010 100644 --- a/js/widget.js +++ b/js/src/widget.js @@ -2,7 +2,7 @@ * X-Payments Cloud SDK - Payment Widget */ -window.XPaymentsWidget = function() +const XPaymentsWidget = function() { this.jsApiVersion = '2.0'; this.serverDomain = 'xpayments.com'; @@ -919,3 +919,5 @@ XPaymentsWidget.prototype._postMessage = function(message) this._log('Error sending message - iframe wasn\'t initialized!'); } } + +export default XPaymentsWidget diff --git a/lib/XPaymentsCloud/Client.php b/lib/XPaymentsCloud/Client.php index 5a9cf20..62c24d5 100644 --- a/lib/XPaymentsCloud/Client.php +++ b/lib/XPaymentsCloud/Client.php @@ -19,7 +19,7 @@ class Client { - const SDK_VERSION = '0.2.14'; + const SDK_VERSION = '0.3.0'; private $account; private $secretKey;