diff --git a/.github/workflows/pr.yml b/.github/workflows/pr.yml index e389eb07..f868de2a 100644 --- a/.github/workflows/pr.yml +++ b/.github/workflows/pr.yml @@ -95,7 +95,7 @@ jobs: with: args: > -Dsonar.php.coverage.reportPaths=coverage/clover.xml - -Dsonar.coverage.exclusions=tests/**,assets/**,templates/**,woo-pagarme-payments.php + -Dsonar.coverage.exclusions=tests/**,assets/**,src/Controller/**,templates/**,woo-pagarme-payments.php -Dsonar.tests=tests/ -Dsonar.sources=src,assets,templates,woo-pagarme-payments.php diff --git a/assets/images/barcode.svg b/assets/images/barcode.svg index 886d25eb..cbe82881 100644 --- a/assets/images/barcode.svg +++ b/assets/images/barcode.svg @@ -1,185 +1,133 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + barcode-svg + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/assets/javascripts/admin/pagarme_notices.js b/assets/javascripts/admin/pagarme_notices.js index 0747304f..e39d1fcd 100644 --- a/assets/javascripts/admin/pagarme_notices.js +++ b/assets/javascripts/admin/pagarme_notices.js @@ -1,10 +1,10 @@ -const { __ } = wp.i18n; +/* jshint esversion: 6 */ jQuery(function ($) { $('.pagarme-get-hub-account-info').on('click', function (e) { try { - swal({ - title: ' ', - text: __('Processing', 'woo-pagarme-payments'), + swal.fire({ + title: 'Processando', + icon: 'warning', allowOutsideClick: false }); swal.showLoading(); @@ -16,30 +16,29 @@ jQuery(function ($) { command: 'get' }), success: function (response) { - swal( - __('Success!', 'woo-pagarme-payments'), - __('Dash configuration was retrieved successfully. The page is reloading. Please, wait a moment.', - 'woo-pagarme-payments' - ), - 'success' - ) + swal.fire({ + title: 'Sucesso!', + text: 'As configurações da Dash foram recuperadas com sucesso. A página está recarregando.' + + ' Por favor, aguarde um momento.', + icon: 'success' + }); document.location.reload(true); }, fail: function (response) { - swal( - __('Fail!', 'woo-pagarme-payments'), - __('Dash configuration was not retrieved. Please, try again.', 'woo-pagarme-payments'), - 'error' - ) + swal.fire({ + title: 'Falha!', + text: 'As configurações da Dash não foram recuperadas. Por favor, tente novamente.', + icon: 'error' + }); } }); - } catch (e) { - swal( - __('Fail!', 'woo-pagarme-payments'), - __('Dash configuration was not retrieved. Please, try again.', 'woo-pagarme-payments'), - 'error' - ) + } catch (error) { + swal.fire({ + title: 'Falha!', + text: 'As configurações da Dash não foram recuperadas. Por favor, tente novamente.', + icon: 'error' + }); } }); }); diff --git a/assets/javascripts/admin/pagarme_settings.js b/assets/javascripts/admin/pagarme_settings.js index ce9e240a..62f2d523 100644 --- a/assets/javascripts/admin/pagarme_settings.js +++ b/assets/javascripts/admin/pagarme_settings.js @@ -64,20 +64,19 @@ const element = $(this); const value = element.val(); if (value === 'yes') { - swal({ + swal.fire({ type: 'warning', title: allow_no_address_swal.title, text: allow_no_address_swal.text, showConfirmButton: true, - showCancelButton: true, - cancelButtonText: allow_no_address_swal.cancelButtonText, + showDenyButton: true, + denyButtonText: allow_no_address_swal.cancelButtonText, allowOutsideClick: false, - }).then( - function (confirm) {}, - function (cancel) { + }).then((result) => { + if (!result.isConfirmed) { element.val('no'); } - ); + }); } } ); diff --git a/assets/javascripts/admin/sales/order/view/cancel-capture.js b/assets/javascripts/admin/sales/order/view/cancel-capture.js index 294436bf..0c410767 100644 --- a/assets/javascripts/admin/sales/order/view/cancel-capture.js +++ b/assets/javascripts/admin/sales/order/view/cancel-capture.js @@ -1,3 +1,4 @@ +/* jshint esversion: 6 */ $ = jQuery; const actionsTarget = '[data-ref]:enabled'; const modalTarget = '.modal'; @@ -101,9 +102,9 @@ let pagarmeCancelCapture = { }, requestInProgress: function () { - swal({ - title: ' ', - text: 'Processando...', + swal.fire({ + title: 'Processando', + icon: 'warning', allowOutsideClick: false }); swal.showLoading(); @@ -113,14 +114,14 @@ let pagarmeCancelCapture = { this.lock = false; $( modalTarget ).iziModal('close'); swal.close(); - swal({ - type: 'success', + swal.fire({ + icon: 'success', title: ' ', html: response.data.message, showConfirmButton: false, - timer: 2000 + timer: 2000, + timerProgressBar: true }).then( - function () { }, function (dismiss) { window.location.reload(); } @@ -135,12 +136,13 @@ let pagarmeCancelCapture = { this.lock = false; swal.close(); let data = JSON.parse(xhr.responseText); - swal({ - type: 'error', + swal.fire({ + icon: 'error', title: ' ', html: data.message, showConfirmButton: false, - timer: 2000 + timer: 2000, + timerProgressBar: true }); }, diff --git a/assets/javascripts/front/checkout/model/payment.js b/assets/javascripts/front/checkout/model/payment.js deleted file mode 100644 index 003dc525..00000000 --- a/assets/javascripts/front/checkout/model/payment.js +++ /dev/null @@ -1,34 +0,0 @@ -/* globals wc_pagarme_checkout */ - -jQuery(function ($) { - if (typeof wc_pagarme_checkout !== 'undefined') { - globalThis.wc_pagarme_checkout = wc_pagarme_checkout; - $.jMaskGlobals.watchDataMask = true; - wc_pagarme_checkout.validate = function () { - const checkedPayment = $('form .payment_methods input[name="payment_method"]:checked')?.val(); - if (!checkedPayment) { - return true; - } - const requiredFields = $('#shipping_number:visible, input[data-required=true]:visible,' + - 'select[data-required=true]:visible,' + - `.wc_payment_method.payment_method_${checkedPayment} [data-pagarmecheckout-element="brand-input"]`); - let isValid = true; - requiredFields.each(function (index, item) { - const field = $(item); - const wrapper = field.closest( '.form-row' ); - if (field.val() == 0 || !$.trim(field.val())) { - field.addClass('invalid').val(''); - if (isValid) { - field.focus(); - } - wrapper.addClass('woocommerce-invalid' ); // error - isValid = false; - } - }); - if (!isValid) { - swal('Preencha os campos obrigatórios'); - } - return isValid; - } - } -}); diff --git a/assets/javascripts/front/checkout/model/payment/card.js b/assets/javascripts/front/checkout/model/payment/card.js index 3abe978e..41713c53 100644 --- a/assets/javascripts/front/checkout/model/payment/card.js +++ b/assets/javascripts/front/checkout/model/payment/card.js @@ -1,15 +1,18 @@ /* globals wc_pagarme_checkout */ -/*jshint esversion: 8 */ +/* jshint esversion: 11 */ let pagarmeCard = { limitTokenize: 10, tokenExpirationAttribute: 'data-pagarmecheckout-expiration', cardNumberTarget: 'input[data-element="pagarme-card-number"]', - brandTarget: 'input[data-pagarmecheckout-element="brand-input"]', - valueTarget: 'input[data-pagarmecheckout-element="order-value"]', + cardHolderNameTarget: 'input[data-element="card-holder-name"]', + cardExpiryTarget: 'input[data-element="card-expiry"]', + cardCvvTarget: 'input[data-element="card-cvv"]', + brandTarget: 'input[data-pagarme-element="brand-input"]', + valueTarget: 'input[data-pagarme-element="order-value"]', installmentsTarget: '[data-pagarme-component="installments"]', installmentsInfoTarget: '[data-pagarme-component="installments-info"]', mundiCdn: 'https://cdn.mundipagg.com/assets/images/logos/brands/png/', - tokenElement: '[data-pagarmecheckout-element="token"]', + tokenElement: '[data-pagarme-element="token"]', fieldsetCardElements: 'fieldset[data-pagarmecheckout="card"]', billingCpfId: '#billing_cpf', voucherDocumentHolder: 'input[name="pagarme[voucher][cards][1][document-holder]"]', @@ -202,7 +205,7 @@ let pagarmeCard = { jQuery.ajax({ type: "GET", dataType: "json", - url: 'https://api.mundipagg.com/bin/v1/' + bin, + url: 'https://api.pagar.me/bin/v1/' + bin, async: false, cache: false, success: function (data) { @@ -221,6 +224,17 @@ let pagarmeCard = { let imageSrc = this.getImageSrc(card); let imgElem = jQuery(elem).parent().find('img'); + + const doesNotHaveBrand = !card[0].brand || card[0]?.brand?.length === 0; + if (doesNotHaveBrand) { + pagarmeCard.showErrorInPaymentMethod( + PagarmeGlobalVars.checkoutErrors.pt_BR[ + 'invalidBrand' + ] + ); + return; + } + jQuery(elem).parents('.pagarme-card-number-row').find(this.brandTarget).attr('value', card[0].brand); if (imgElem.length) { imgElem.attr('src', imageSrc); @@ -233,6 +247,24 @@ let pagarmeCard = { ); } }, + showErrorInPaymentMethod: function (error) { + const element = jQuery('input[name$="payment_method"]:checked') + .closest("li") + .find("#wcmp-checkout-errors"); + + swal.close(); + + wc_pagarme_checkout.errorList = `
  • ${error}<\li>`; + + element.find(".woocommerce-error").html(wc_pagarme_checkout.errorList); + element.slideDown(); + + const rect = element.get(0).getBoundingClientRect(); + + jQuery("#wcmp-submit").removeAttr("disabled", "disabled"); + + window.scrollTo(0, rect.top + window.scrollY - 40); + }, getImageSrc: function (card) { if (card[0].image) { return card[0].image; @@ -288,17 +320,17 @@ let pagarmeCard = { } }); ajax.done(function (response) { - pagarmeCard._done(select, info, storageName, cardForm, JSON.parse(response)); + pagarmeCard._done(select, info, storageName, JSON.parse(response)); }); ajax.fail(function () { - pagarmeCard._fail(cardForm); + pagarmeCard._fail(); }); - pagarmeCard.showLoader(cardForm); + pagarmeCard.showLoader(); } return true; }, - _done: function (select, info, storageName, event, response) { + _done: function (select, info, storageName, response) { if (info.length) { info.addClass('pagarme-hidden'); if(response.installmentsConfig > 1) { @@ -307,35 +339,35 @@ let pagarmeCard = { } select.html(response.optionsHtml); sessionStorage.setItem(storageName, response); - this.removeLoader(event); + this.removeLoader(); }, - _fail: function (event) { - this.removeLoader(event); + _fail: function () { + this.removeLoader(); }, - removeLoader: function (event) { - if (!(event instanceof jQuery)) { - event = jQuery(event); + removeLoader: function () { + if (typeof jQuery.unblockUI === 'function') { + jQuery.unblockUI(); } - event.unblock(); }, - showLoader: function (event) { - event = this.formatEventToJQuery(event) - event.block({ - message: null, - overlayCSS: { - background: '#fff', - opacity: 0.6 - } - }); + showLoader: function () { + if (typeof jQuery.blockUI === 'function') { + jQuery.blockUI({ + message: null, + overlayCSS: { + background: '#fff', + opacity: 0.6 + } + }); + } }, showError: function (text) { const errorMessageText = this.translateErrors('card', text); const message = { - type: 'error', + icon: 'error', html: errorMessageText, allowOutsideClick: false }; - swal(message); + swal.fire(message); }, translateErrors: function (error, message) { error = error.replace('request.', ''); @@ -347,15 +379,14 @@ let pagarmeCard = { return output; }, execute: async function (event) { - const checkoutPaymentElement = this.getCheckoutPaymentElement(); try { for (let i = 1; !pagarmeCard.isTokenized() && i <= this.limitTokenize; i++) { if (i === this.limit) { - this.removeLoader(checkoutPaymentElement); + this.removeLoader(); throw new Error("Tokenize timeout"); } if (wc_pagarme_checkout.errorTokenize === true) { - this.removeLoader(checkoutPaymentElement); + this.removeLoader(); return; } await pagarmeCard.wait(); @@ -371,20 +402,39 @@ let pagarmeCard = { } }, canExecute: function (event) { - if (!wc_pagarme_checkout.validate() || wc_pagarme_checkout.errorTokenize === true) { + const checkoutPaymentElement = pagarmeCard.getCheckoutPaymentElement(); + const cardBrand = checkoutPaymentElement.parents('.pagarme-card-number-row') + .find(this.brandTarget); + if (cardBrand?.val()?.length === 0 || wc_pagarme_checkout.errorTokenize === true) { return false; } - let checkoutPaymentElement = pagarmeCard.getCheckoutPaymentElement(); + if (pagarmeCard.isPagarmePayment() && !pagarmeCard.isTokenized() && pagarmeCard.haveCardForm(checkoutPaymentElement) ) { - pagarmeTokenize.execute(); - pagarmeCard.execute(event); + if (typeof pagarmeTds == 'object') { + const tdsExecuted = pagarmeTds.start(event); + + if (tdsExecuted) { + return false; + } + } + this.executeAll(event); return false; } return true; }, + executeAll: function (event) { + pagarmeTokenize.execute(); + pagarmeCard.execute(event); + }, + brandIsVisaOrMaster: function() { + const checkoutPaymentElement = this.getCheckoutPaymentElement(); + const brand = jQuery(checkoutPaymentElement).find(this.brandTarget) + .val(); + return brand === "visa" || brand === "mastercard"; + }, onChangeBillingCpf: function () { let cpf = jQuery(this.billingCpfId).val(); jQuery(this.voucherDocumentHolder).empty(); @@ -435,6 +485,7 @@ let pagarmeCard = { } }, start: function () { + jQuery.jMaskGlobals.watchDataMask = true; this.getCardsMethods(); this.addEventListener(); this.onChangeBillingCpf(); diff --git a/assets/javascripts/front/checkout/model/payment/card/initTds.js b/assets/javascripts/front/checkout/model/payment/card/initTds.js new file mode 100644 index 00000000..b1ac0b53 --- /dev/null +++ b/assets/javascripts/front/checkout/model/payment/card/initTds.js @@ -0,0 +1,6 @@ +const initTds = { + callTdsFunction(tdsToken, tdsData, callbackTds) { + const challengeWindowSize = "03"; + Script3ds.init3ds(tdsToken, tdsData, callbackTds, challengeWindowSize); + }, +}; diff --git a/assets/javascripts/front/checkout/model/payment/card/tds.js b/assets/javascripts/front/checkout/model/payment/card/tds.js new file mode 100644 index 00000000..d57803c7 --- /dev/null +++ b/assets/javascripts/front/checkout/model/payment/card/tds.js @@ -0,0 +1,305 @@ +/* globals cartTotal */ +const pagarmeTds = { + authentication: "authentication", + vendor: "pagarme", + checkoutEvent: null, + paymentMethodTarget: "data-pagarmecheckout-method", + sequenceTarget: "data-pagarmecheckout-card-num", + elementTarget: "data-pagarmecheckout-element", + formTarget: "data-pagarmecheckout-form", + FAIL_GET_EMAIL: "fail_get_email", + FAIL_GET_BILLING_ADDRESS: "fail_get_billing_address", + FAIL_ASSEMBLE_CARD_EXPIRY_DATE: "fail_assemble_card_expiry_date", + FAIL_ASSEMBLE_PURCHASE: "fail_assemble_purchase", + addErrors: (errors) => { + if (errors.error?.email) { + pagarmeCard.showErrorInPaymentMethod( + PagarmeGlobalVars.checkoutErrors.pt_BR[ + pagarmeTds.FAIL_GET_EMAIL + ] + ); + return; + } + if (errors.error?.bill_addr) { + pagarmeCard.showErrorInPaymentMethod( + PagarmeGlobalVars.checkoutErrors.pt_BR[ + pagarmeTds.FAIL_GET_BILLING_ADDRESS + ] + ); + return; + } + if (errors.error?.card_expiry_date) { + pagarmeCard.showErrorInPaymentMethod( + PagarmeGlobalVars.checkoutErrors.pt_BR[ + pagarmeTds.FAIL_ASSEMBLE_CARD_EXPIRY_DATE + ] + ); + return; + } + if (errors.error?.purchase) { + pagarmeCard.showErrorInPaymentMethod( + PagarmeGlobalVars.checkoutErrors.pt_BR[ + pagarmeTds.FAIL_ASSEMBLE_PURCHASE + ] + ); + } + }, + + getToken: () => { + const data = pagarmeTdsToken.getToken(); + if (data.error) { + pagarmeTds.removeTdsAttributeData(); + pagarmeCard.showErrorInPaymentMethod( + PagarmeGlobalVars.checkoutErrors.pt_BR[data.error] + ); + return ""; + } + + return data.token; + }, + + canTdsRun: () => { + const fieldset = pagarmeCard + .getCheckoutPaymentElement() + .find(pagarmeCard.fieldsetCardElements); + + const paymentMethod = fieldset.attr(pagarmeTds.paymentMethodTarget); + return ( + paymentMethod === "credit_card" && + wc_pagarme_checkout.config.payment.credit_card.tdsEnabled === + true && + cartTotal >= + wc_pagarme_checkout.config.payment.credit_card.tdsMinAmount && + pagarmeCard.brandIsVisaOrMaster() && + !pagarmeTds.hasAuthenticationField() + ); + }, + + addTdsAttributeData: () => { + const checkoutPaymentElement = pagarmeCard.getCheckoutPaymentElement(); + jQuery("form.checkout").attr(pagarmeTds.formTarget, ""); + jQuery(checkoutPaymentElement) + .find(pagarmeCard.cardHolderNameTarget) + .attr(pagarmeTds.elementTarget, "holder_name"); + jQuery(checkoutPaymentElement) + .find(pagarmeCard.cardNumberTarget) + .attr(pagarmeTds.elementTarget, "number"); + jQuery(checkoutPaymentElement) + .find(pagarmeCard.brandTarget) + .attr(pagarmeTds.elementTarget, "brand"); + jQuery(checkoutPaymentElement) + .find(pagarmeCard.cardCvvTarget) + .attr(pagarmeTds.elementTarget, "cvv"); + }, + + removeTdsAttributeData: () => { + const checkoutPaymentElement = pagarmeCard.getCheckoutPaymentElement(); + jQuery("form.checkout").removeAttr(pagarmeTds.formTarget); + jQuery(checkoutPaymentElement) + .find(pagarmeCard.cardHolderNameTarget) + .removeAttr(pagarmeTds.elementTarget); + jQuery(checkoutPaymentElement) + .find(pagarmeCard.cardNumberTarget) + .removeAttr(pagarmeTds.elementTarget); + jQuery(checkoutPaymentElement) + .find(pagarmeCard.brandTarget) + .removeAttr(pagarmeTds.elementTarget); + jQuery(checkoutPaymentElement) + .find(pagarmeCard.cardCvvTarget) + .removeAttr(pagarmeTds.elementTarget); + }, + + getTdsData: (acctType, cardExpiryDate) => { + const customerPhones = [ + { + country_code: "55", + subscriber: pagarmeTds.filterOnlyNumber( + jQuery('input[name="billing_phone"]').val() + ), + phone_type: "mobile", + }, + ]; + + const billingAddressStreet = jQuery( + 'input[name="billing_address_1"]' + ).val(); + const billingAddressNumber = jQuery( + 'input[name="billing_number"]' + ).val(); + const billingAddressComplement = jQuery( + 'input[name="billing_address_2"]' + ).val(); + const billingAddressCity = jQuery('input[name="billing_city"]').val(); + const billingAddressState = jQuery( + 'select[name="billing_state"]' + ).val(); + const billingAddressPostcode = jQuery( + 'input[name="billing_postcode"]' + ).val(); + + let shippingAddressStreet = billingAddressStreet; + let shippingAddressNumber = billingAddressNumber; + let shippingAddressComplement = billingAddressComplement; + let shippingAddressCity = billingAddressCity; + let shippingAddressState = billingAddressState; + let shippingAddressPostcode = billingAddressPostcode; + + if (jQuery('input[name="ship_to_different_address"]').is(":checked")) { + shippingAddressStreet = jQuery( + 'input[name="shipping_address_1"]' + ).val(); + shippingAddressNumber = jQuery( + 'input[name="shipping_number"]' + ).val(); + shippingAddressComplement = jQuery( + 'input[name="shipping_address_2"]' + ).val(); + shippingAddressCity = jQuery('input[name="shipping_city"]').val(); + shippingAddressState = jQuery( + 'select[name="shipping_state"]' + ).val(); + shippingAddressPostcode = jQuery( + 'input[name="shipping_postcode"]' + ).val(); + } + + return { + bill_addr: { + street: billingAddressStreet, + number: billingAddressNumber, + complement: billingAddressComplement, + city: billingAddressCity, + state: billingAddressState, + country: "BRA", + post_code: billingAddressPostcode, + }, + ship_addr: { + street: shippingAddressStreet, + number: shippingAddressNumber, + complement: shippingAddressComplement, + city: shippingAddressCity, + state: shippingAddressState, + country: "BRA", + post_code: shippingAddressPostcode, + }, + email: jQuery('input[name="billing_email"]').val(), + phones: customerPhones, + card_expiry_date: cardExpiryDate, + purchase: { + amount: parseInt(cartTotal * 100), + date: new Date().toISOString(), + instal_data: 2, + }, + acct_type: acctType, + }; + }, + + callTds: (tdsToken) => { + const checkoutPaymentElement = pagarmeCard.getCheckoutPaymentElement(); + + const expDate = jQuery(checkoutPaymentElement) + .find(pagarmeCard.cardExpiryTarget) + .val(); + let [expMonth, expYear] = expDate.split("/"); + expMonth = expMonth.trim(); + expYear = expYear.trim(); + expYear = `20${expYear}`; + + const cardExpiryDate = `${expYear}-${expMonth}`; + + const tdsData = pagarmeTds.getTdsData("02", cardExpiryDate); + initTds.callTdsFunction( + tdsToken, + tdsData, + pagarmeTds.callbackTds.bind(this) + ); + }, + + callbackTds: (data) => { + pagarmeCard.removeLoader(); + if (data?.error !== undefined) { + pagarmeTds.addErrors(data); + return; + } + if (data?.trans_status === "" || data?.trans_status === undefined) { + return; + } + + if (pagarmeTds.checkoutEvent === null) { + pagarmeCard.showErrorInPaymentMethod( + PagarmeGlobalVars.checkoutErrors.pt_BR[ + pagarmeTdsToken.FAIL_GET_TOKEN + ] + ); + return; + } + + const authentication = JSON.stringify(data); + pagarmeTds.createTdsField(authentication); + + pagarmeCard.executeAll(pagarmeTds.checkoutEvent); + }, + + createTdsField: (authentication) => { + pagarmeTds.removeTdsFields(); + const fieldset = pagarmeCard + .getCheckoutPaymentElement() + .find(pagarmeCard.fieldsetCardElements); + const inputName = `${pagarmeTds.vendor}[${fieldset.attr( + pagarmeTds.paymentMethodTarget + )}][cards][${fieldset.attr(pagarmeTds.sequenceTarget)}][${ + pagarmeTds.authentication + }]`; + const input = jQuery(document.createElement("input")); + input + .attr("type", "hidden") + .attr("name", inputName) + .attr("id", inputName) + .attr("value", authentication) + .attr(pagarmeTds.elementTarget, pagarmeTds.authentication); + fieldset.append(input); + }, + + removeTdsFields: () => { + const field = pagarmeCard.getCheckoutPaymentElement(); + const inputs = field.find( + `[${pagarmeTds.elementTarget}=${pagarmeTds.authentication}]` + ); + if (inputs.length) { + jQuery.each(inputs, function () { + this.remove(); + }); + } + }, + + hasAuthenticationField: () => { + return ( + pagarmeCard + .getCheckoutPaymentElement() + .find( + `[${pagarmeTds.elementTarget}=${pagarmeTds.authentication}]` + ).length > 0 + ); + }, + + filterOnlyNumber: (text) => { + return text.replace(/[^0-9]/g, ""); + }, + + start: (event) => { + const canTdsRun = pagarmeTds.canTdsRun(); + if (canTdsRun) { + pagarmeCard.showLoader(); + pagarmeTds.checkoutEvent = event; + pagarmeTds.addTdsAttributeData(); + const token = pagarmeTds.getToken(); + if (!token || token.length === 0) { + return false; + } + + pagarmeTds.callTds(token); + } + + return canTdsRun; + }, +}; diff --git a/assets/javascripts/front/checkout/model/payment/card/tdsToken.js b/assets/javascripts/front/checkout/model/payment/card/tdsToken.js new file mode 100644 index 00000000..ca186826 --- /dev/null +++ b/assets/javascripts/front/checkout/model/payment/card/tdsToken.js @@ -0,0 +1,29 @@ +const pagarmeTdsToken = { + FAIL_GET_TOKEN: "fail_get_token", + + getToken: () => { + try { + const response = jQuery.ajax({ + type: "GET", + dataType: "json", + url: "/wc-api/pagarme-tds-token", + async: false, + cache: false, + }).responseText; + + if (response.length === 0) { + return { + error: this.FAIL_GET_TOKEN, + }; + } + + const parsedResponse = JSON.parse(response); + + return { token: parsedResponse?.data?.token }; + } catch (e) { + return { + error: this.FAIL_GET_TOKEN, + }; + } + }, +}; diff --git a/assets/javascripts/front/checkout/model/payment/card/tokenize.js b/assets/javascripts/front/checkout/model/payment/card/tokenize.js index 7d5fd97a..3f4c056f 100644 --- a/assets/javascripts/front/checkout/model/payment/card/tokenize.js +++ b/assets/javascripts/front/checkout/model/payment/card/tokenize.js @@ -1,13 +1,13 @@ /* globals pagarmeCard */ - +/* jshint esversion: 8 */ let pagarmeTokenize = { appId: jQuery('[data-pagarmecheckout-app-id]').data('pagarmecheckoutAppId'), - apiUrl: 'https://api.mundipagg.com/core/v1/tokens', + apiUrl: 'https://api.pagar.me/core/v5/tokens', token: 'token', vendor: 'pagarme', paymentMethodTarget: 'data-pagarmecheckout-method', sequenceTarget: 'data-pagarmecheckout-card-num', - tokenElementTarget: 'data-pagarmecheckout-element', + tokenElementTarget: 'data-pagarme-element', getEndpoint: function () { let url = new URL(this.apiUrl); url.searchParams.append('appId', this.appId); @@ -18,9 +18,6 @@ let pagarmeTokenize = { }, execute: async function () { - if (wc_pagarme_checkout.validate() === false) { - return; - } let el = pagarmeCard.getCheckoutPaymentElement(); if (pagarmeCard.isPagarmePayment() && pagarmeCard.haveCardForm(el) !== false) { pagarmeTokenize.getCardsForm(el).each(await pagarmeTokenize.tokenize); @@ -55,7 +52,7 @@ let pagarmeTokenize = { createCardObject: function (field) { let obj = {}; jQuery.each(jQuery(field).find('input'), function () { - let prop = this.getAttribute('data-pagarmecheckout-element'), + let prop = this.getAttribute('data-pagarme-element'), ignore = ['brand-input', 'exp_date', 'card-order-value', null], value; value = this.value; @@ -108,11 +105,11 @@ let pagarmeTokenize = { showError: function (text) { swal.close(); const message = { - type: 'error', + icon: 'error', html: text, allowOutsideClick: false }; - swal(message); + swal.fire(message); }, listError: function (errors) { @@ -143,11 +140,7 @@ let pagarmeTokenize = { }, createTokenInput: async function (response, field) { - try { - await pagarmeTokenize.clearInputTokens(field); - } catch (e) { - this.showError(e.message); - } + await pagarmeTokenize.clearInputTokens(field); const objJSON = JSON.parse(response); let input = jQuery(document.createElement('input')); if (!(field instanceof jQuery)) { @@ -178,3 +171,4 @@ let pagarmeTokenize = { }); } }; + diff --git a/assets/javascripts/front/checkout/model/payment/card/wallet.js b/assets/javascripts/front/checkout/model/payment/card/wallet.js index 92058633..8aecb14c 100644 --- a/assets/javascripts/front/checkout/model/payment/card/wallet.js +++ b/assets/javascripts/front/checkout/model/payment/card/wallet.js @@ -3,7 +3,7 @@ let pagarmeCheckoutWallet = { cardSaveTarget: 'select[data-element="choose-credit-card"]', cardFields: [ - '[data-pagarmecheckout-element="fields-cc-data"]', + '[data-pagarme-element="fields-cc-data"]', '[data-element="save-cc-check"]', '[data-element="enable-multicustomers-check"]' ], diff --git a/assets/javascripts/front/checkout/model/payment/order-value.js b/assets/javascripts/front/checkout/model/payment/order-value.js index 224c7928..dcb1f622 100644 --- a/assets/javascripts/front/checkout/model/payment/order-value.js +++ b/assets/javascripts/front/checkout/model/payment/order-value.js @@ -1,16 +1,16 @@ /* globals pagarmeCard */ - +/* jshint esversion: 8 */ let pagarmeOrderValue = { - valueTarget: 'input[data-pagarmecheckout-element="order-value"]', - firstCardFildset: 'fieldset[data-pagarmecheckout-card-num="1"]', + valueTarget: 'input[data-pagarme-element="order-value"]', + firstCardFieldset: 'fieldset[data-pagarmecheckout-card-num="1"]', fillAnotherInput: async function (event) { let input = pagarmeCard.formatEventToJQuery(event); let nextInput = input.closest('fieldset').siblings('fieldset').find(this.valueTarget); let total = this.formatValue(this.getCartTotals()); let value = this.formatValue(input.val() || total / 2); - if (value > total) { - this.showError('O valor não pode ser maior que total do pedido!'); + if (value >= total) { + this.showError('O valor deve ser menor que o total do pedido!'); input.val(''); input.change(); return; @@ -36,11 +36,11 @@ let pagarmeOrderValue = { }, showError: function (text) { const message = { - type: 'error', - html: text, + icon: 'error', + text: text, allowOutsideClick: false }; - swal(message); + swal.fire(message); }, addEventListener: function () { jQuery(this.valueTarget).on('change', function (event){ @@ -49,7 +49,7 @@ let pagarmeOrderValue = { }, start: function () { this.addEventListener(); - jQuery(this.firstCardFildset).find(this.valueTarget).each(function () { + jQuery(this.firstCardFieldset).find(this.valueTarget).each(function () { pagarmeOrderValue.fillAnotherInput(this); }); }, diff --git a/assets/javascripts/front/checkout/model/payment/pix.js b/assets/javascripts/front/checkout/model/payment/pix.js index b2f199bf..8d3ea4d0 100644 --- a/assets/javascripts/front/checkout/model/payment/pix.js +++ b/assets/javascripts/front/checkout/model/payment/pix.js @@ -1,3 +1,4 @@ +/*jshint esversion: 6 */ let pagarmePix = { qrRawCodeTarget: '#pagarme-qr-code-button', start: function () { @@ -15,14 +16,13 @@ let pagarmePix = { } const rawCode = elem.attr('rawCode'); const message = { - type: 'success', - html: 'Código copiado.', - allowOutsideClick: false + icon: 'success', + text: 'Código copiado.' }; if (window.isSecureContext && navigator.clipboard) { navigator.clipboard.writeText(rawCode); - new swal(message) + swal.fire(message); return; } @@ -36,7 +36,7 @@ let pagarmePix = { document.execCommand('copy', false); input.remove(); - new swal(message); + swal.fire(message); } }; pagarmePix.start(); diff --git a/assets/javascripts/front/my-account/wallet.js b/assets/javascripts/front/my-account/wallet.js index c806070a..06752904 100644 --- a/assets/javascripts/front/my-account/wallet.js +++ b/assets/javascripts/front/my-account/wallet.js @@ -1,4 +1,5 @@ -const removeCard = '[data-action="remove-card"]' +/* jshint esversion: 6 */ +const removeCard = '[data-action="remove-card"]'; let pagarmeWallet = { start: function () { @@ -12,19 +13,23 @@ let pagarmeWallet = { }, _onClickRemoveCard: function (event) { event.preventDefault(); - swal({ + swal.fire({ title: walletConfig.dataSwal.confirm_title, text: walletConfig.dataSwal.confirm_text, - type: 'warning', + icon: 'warning', showCancelButton: true, confirmButtonColor: walletConfig.dataSwal.confirm_color, cancelButtonColor: walletConfig.dataSwal.cancel_color, confirmButtonText: walletConfig.dataSwal.confirm_button, cancelButtonText: walletConfig.dataSwal.cancel_button, allowOutsideClick: false, - }).then(this._request.bind(this, event.currentTarget.dataset.value), function () { - }); - }, + }) + .then((result) => { + if (result.isConfirmed) { + pagarmeWallet._request(event.currentTarget.dataset.value); + } + }); + }, _request: function (cardId) { swal.showLoading(); jQuery.ajax({ @@ -33,8 +38,7 @@ let pagarmeWallet = { data: { card_id: cardId } - }) - .done(this._done) + }).done(this._done); }, _done: function (response) { if (response.success) { @@ -43,24 +47,21 @@ let pagarmeWallet = { pagarmeWallet.failMessage(response.data); } }, - _fail: function (jqXHR, textStatus, errorThrown) { - }, failMessage: function (message) { - swal({ - type: 'error', + swal.fire({ + icon: 'error', html: message - }).then(function () { }); }, successMessage: function (message) { - swal({ - type: 'success', + swal.fire({ + icon: 'success', html: message, allowOutsideClick: false }).then(function () { location.reload(true); }); }, -} +}; pagarmeWallet.start(); diff --git a/assets/javascripts/front/reactCheckout/payments/Billet/index.js b/assets/javascripts/front/reactCheckout/payments/Billet/index.js new file mode 100644 index 00000000..b71291c8 --- /dev/null +++ b/assets/javascripts/front/reactCheckout/payments/Billet/index.js @@ -0,0 +1,33 @@ +import PaymentWithInstructions from "../PaymentWithInstructions"; +import PropTypes from "prop-types"; + +const { registerPaymentMethod } = window.wc.wcBlocksRegistry; + +const backendConfig = wc.wcSettings.getSetting( + "woo-pagarme-payments-billet_data", +); + +const PagarmeBilletComponent = (props) => { + return ; +}; + +const PagarmeBilletLabel = ({ components }) => { + const { PaymentMethodLabel } = components; + + return ; +}; + +PagarmeBilletLabel.propTypes = { + components: PropTypes.object, +}; + +const pagarmeBilletPaymentMethod = { + name: backendConfig.name, + label: , + content: , + edit: , + canMakePayment: () => true, + ariaLabel: backendConfig.ariaLabel, +}; + +registerPaymentMethod(pagarmeBilletPaymentMethod); diff --git a/assets/javascripts/front/reactCheckout/payments/Card/index.js b/assets/javascripts/front/reactCheckout/payments/Card/index.js new file mode 100644 index 00000000..ead9de8b --- /dev/null +++ b/assets/javascripts/front/reactCheckout/payments/Card/index.js @@ -0,0 +1,148 @@ +/* jshint esversion: 9 */ +import Installments from "./inputs/components/Installments"; +import InputHolderName from "./inputs/components/InputHolderName"; +import InputNumber from "./inputs/components/InputNumber"; +import InputExpiry from "./inputs/components/InputExpiry"; +import InputCvv from "./inputs/components/InputCvv"; +import PropTypes from "prop-types"; +import Wallet from "./inputs/components/Wallet"; +import useCard from "./useCard"; + +const {CheckboxControl} = window.wc.blocksComponents; + +const Card = ({ + billing, + components, + backendConfig, + cardIndex, + eventRegistration, +}) => { + const {LoadingMask} = components; + + const { + holderNameLabel, + numberLabel, + expiryLabel, + cvvLabel, + installmentsLabel, + saveCardLabel, + walletLabel, + } = backendConfig.fieldsLabels; + + const { + isLoading, + setIsLoading, + setHolderName, + setNumber, + setExpirationDate, + setInstallment, + setBrand, + setCvv, + setWalletId, + setErrors, + saveCardChangeHandler, + formatFieldId, + holderName, + number, + expirationDate, + selectedInstallment, + brand, + cvv, + saveCard, + walletId, + errors, + } = useCard(cardIndex, eventRegistration, backendConfig); + + return ( + +
    + {backendConfig?.walletEnabled && backendConfig?.cards?.length > 0 && ( + + )} + {walletId.length === 0 && ( + <> + + + + + + )} + + {walletId.length === 0 && backendConfig?.walletEnabled && ( + + )} +
    +
    + ); +}; + +Card.propType = { + billing: PropTypes.object.isRequired, + components: PropTypes.object.isRequired, + backendConfig: PropTypes.object.isRequired, + cardIndex: PropTypes.number.isRequired, + eventRegistration: PropTypes.object.isRequired, +}; + +export default Card; diff --git a/assets/javascripts/front/reactCheckout/payments/Card/inputs/components/InputCvv/index.js b/assets/javascripts/front/reactCheckout/payments/Card/inputs/components/InputCvv/index.js new file mode 100644 index 00000000..7407ef10 --- /dev/null +++ b/assets/javascripts/front/reactCheckout/payments/Card/inputs/components/InputCvv/index.js @@ -0,0 +1,51 @@ +/* jshint esversion: 9 */ +import PropTypes from "prop-types"; +import MaskedInput from "../MaskedInput"; +import useCardValidation from "../../../useCardValidation"; + +const InputCvv = ({ + id, + label, + cardIndex, + inputValue, + setInputValue, + errors, + setErrors, + fieldErrors, +}) => { + const {validateInputCvv} = useCardValidation(cardIndex, errors, setErrors, fieldErrors); + + return ( + <> + + {errors.inputCvv && ( +
    +

    {errors.inputCvv}

    +
    + )} + + ); +}; + +InputCvv.propTypes = { + id: PropTypes.string.isRequired, + label: PropTypes.string.isRequired, + cardIndex: PropTypes.number.isRequired, + inputValue: PropTypes.string.isRequired, + setInputValue: PropTypes.func.isRequired, + errors: PropTypes.object.isRequired, + setErrors: PropTypes.func.isRequired, + fieldErrors: PropTypes.object.isRequired, +}; + +export default InputCvv; diff --git a/assets/javascripts/front/reactCheckout/payments/Card/inputs/components/InputExpiry/index.js b/assets/javascripts/front/reactCheckout/payments/Card/inputs/components/InputExpiry/index.js new file mode 100644 index 00000000..9a0a8050 --- /dev/null +++ b/assets/javascripts/front/reactCheckout/payments/Card/inputs/components/InputExpiry/index.js @@ -0,0 +1,52 @@ +/* jshint esversion: 9 */ +import PropTypes from "prop-types"; +import MaskedInput from "../MaskedInput"; +import useCardValidation from "../../../useCardValidation"; + +const InputExpiry = ({ + id, + label, + cardIndex, + inputValue, + setInputValue, + errors, + setErrors, + fieldErrors, +}) => { + const {validateInputExpiry} = useCardValidation(cardIndex, errors, setErrors, fieldErrors); + + return ( + <> + + {errors.inputExpiry && ( +
    +

    {errors.inputExpiry}

    +
    + )} + + ); +}; + +InputExpiry.propTypes = { + id: PropTypes.string.isRequired, + label: PropTypes.string.isRequired, + cardIndex: PropTypes.number.isRequired, + inputValue: PropTypes.string.isRequired, + setInputValue: PropTypes.func.isRequired, + errors: PropTypes.object.isRequired, + setErrors: PropTypes.func.isRequired, + fieldErrors: PropTypes.object.isRequired, +}; + +export default InputExpiry; diff --git a/assets/javascripts/front/reactCheckout/payments/Card/inputs/components/InputHolderName/index.js b/assets/javascripts/front/reactCheckout/payments/Card/inputs/components/InputHolderName/index.js new file mode 100644 index 00000000..32092bc7 --- /dev/null +++ b/assets/javascripts/front/reactCheckout/payments/Card/inputs/components/InputHolderName/index.js @@ -0,0 +1,55 @@ +/* jshint esversion: 8 */ +import PropTypes from "prop-types"; +import useInputHolderName from "./useInputHolderName"; + +const InputHolderName = ({ + id, + label, + inputValue, + setInputValue, + cardIndex, + errors, + setErrors, + fieldErrors, +}) => { + const { setIsActive, cssClasses, inputChangeHandler, inputBlurHandler } = useInputHolderName( + inputValue, + setInputValue, + cardIndex, + errors, + setErrors, + fieldErrors, + ); + + return ( +
    + + setIsActive(true)} + onBlur={inputBlurHandler} + /> + {errors.inputHolderName && ( +
    +

    {errors.inputHolderName}

    +
    + )} +
    + ); +}; + +InputHolderName.propTypes = { + id: PropTypes.string.isRequired, + label: PropTypes.string.isRequired, + inputValue: PropTypes.string.isRequired, + setInputValue: PropTypes.func.isRequired, + cardIndex: PropTypes.number.isRequired, + errors: PropTypes.object.isRequired, + setErrors: PropTypes.func.isRequired, + fieldErrors: PropTypes.object.isRequired, +}; + +export default InputHolderName; diff --git a/assets/javascripts/front/reactCheckout/payments/Card/inputs/components/InputHolderName/useInputHolderName.js b/assets/javascripts/front/reactCheckout/payments/Card/inputs/components/InputHolderName/useInputHolderName.js new file mode 100644 index 00000000..6b8419d2 --- /dev/null +++ b/assets/javascripts/front/reactCheckout/payments/Card/inputs/components/InputHolderName/useInputHolderName.js @@ -0,0 +1,37 @@ +/* jshint esversion: 9 */ +import useCardValidation from "../../../useCardValidation"; +import {useState} from "@wordpress/element"; + +const useInputHolderName = (inputValue, setInputValue, cardIndex, errors, setErrors, fieldErrors) => { + const {validateInputHolderName} = useCardValidation(cardIndex, errors, setErrors, fieldErrors); + + let cssClasses = "wc-block-components-text-input"; + + const [isActive, setIsActive] = useState(false); + if (isActive || inputValue.length) { + cssClasses += " is-active"; + } + + if (errors.hasOwnProperty('inputHolderName')) { + cssClasses += " has-error"; + } + + const inputChangeHandler = (event) => { + const result = event.target.value.replace(/[^a-z ]/gi, ""); + setInputValue(cardIndex, result); + }; + + const inputBlurHandler = (event) => { + validateInputHolderName(event.target.value); + setIsActive(false); + }; + + return { + setIsActive, + cssClasses, + inputChangeHandler, + inputBlurHandler, + }; +}; + +export default useInputHolderName; diff --git a/assets/javascripts/front/reactCheckout/payments/Card/inputs/components/InputNumber/index.js b/assets/javascripts/front/reactCheckout/payments/Card/inputs/components/InputNumber/index.js new file mode 100644 index 00000000..f0c77835 --- /dev/null +++ b/assets/javascripts/front/reactCheckout/payments/Card/inputs/components/InputNumber/index.js @@ -0,0 +1,71 @@ +/* jshint esversion: 8 */ +import PropTypes from "prop-types"; +import InputMask from "react-input-mask"; +import useInputNumber from "./useInputNumber"; + +const InputNumber = ({ + id, + label, + inputValue, + setInputValue, + brand, + setBrand, + brands, + setIsLoading, + cardIndex, + errors, + setErrors, + fieldErrors, +}) => { + const { setIsActive, cssClasses, brandImageSrc, inputChangeHandler, inputBlurHandler} = useInputNumber( + inputValue, + brands, + setInputValue, + setBrand, + setIsLoading, + cardIndex, + errors, + setErrors, + fieldErrors, + ); + + return ( +
    + + setIsActive(true)} + onChange={inputChangeHandler} + value={inputValue} + onBlur={inputBlurHandler} + /> + {brandImageSrc && {brand}/} + {errors.inputNumber && ( +
    +

    {errors.inputNumber}

    +
    + )} +
    + ); +}; + +InputNumber.propTypes = { + id: PropTypes.string.isRequired, + label: PropTypes.string.isRequired, + inputValue: PropTypes.string.isRequired, + setInputValue: PropTypes.func.isRequired, + brand: PropTypes.string.isRequired, + setBrand: PropTypes.func.isRequired, + brands: PropTypes.object.isRequired, + setIsLoading: PropTypes.func.isRequired, + cardIndex: PropTypes.number.isRequired, + errors: PropTypes.object.isRequired, + setErrors: PropTypes.func.isRequired, + fieldErrors: PropTypes.object.isRequired, +}; + +export default InputNumber; diff --git a/assets/javascripts/front/reactCheckout/payments/Card/inputs/components/InputNumber/useInputNumber.js b/assets/javascripts/front/reactCheckout/payments/Card/inputs/components/InputNumber/useInputNumber.js new file mode 100644 index 00000000..33f19a6c --- /dev/null +++ b/assets/javascripts/front/reactCheckout/payments/Card/inputs/components/InputNumber/useInputNumber.js @@ -0,0 +1,122 @@ +/* jshint esversion: 9 */ +import { useState } from "@wordpress/element"; +import { formatCardNumber } from "../../utils/cardNumberFormatter"; +import useCardValidation from "../../../useCardValidation"; + +const binUrl = "https://api.pagar.me/bin/v1/"; +const mundipaggCdn = + "https://cdn.mundipagg.com/assets/images/logos/brands/png/"; + +const useInputNumber = ( + inputValue, + brands, + setInputValue, + setBrand, + setIsLoading, + cardIndex, + errors, + setErrors, + fieldErrors, +) => { + const {validateInputNumber} = useCardValidation(cardIndex, errors, setErrors, fieldErrors); + + const [brandImageSrc, setBrandImageSrc] = useState(""); + + let cssClasses = "wc-block-components-text-input pagarme-credit-card-number-container"; + + const [isActive, setIsActive] = useState(false); + if (isActive || inputValue.length) { + cssClasses += " is-active"; + } + + if (errors.hasOwnProperty('inputNumber')) { + cssClasses += " has-error"; + } + + const inputChangeHandler = (event) => { + setInputValue(cardIndex, event.target.value); + }; + + const getBrandContengency = (bin) => { + let oldPrefix = ""; + let brand = null; + for (const [currentBrandKey, currentBrand] of Object.entries(brands)) { + for (const prefix of currentBrand.prefixes) { + const prefixText = prefix.toString(); + if ( + bin.indexOf(prefixText) === 0 && + oldPrefix.length < prefixText.length + ) { + oldPrefix = prefixText; + brand = currentBrandKey; + } + } + } + + return brand; + }; + + const resetBrand = () => { + setBrand(cardIndex, ""); + setBrandImageSrc(""); + }; + + const changeBrand = async () => { + const cardNumber = formatCardNumber(inputValue); + if (cardNumber.length !== 16) { + resetBrand(); + return; + } + + setIsLoading(true); + const bin = cardNumber.substring(0, 6); + const binFormattedUrl = `${binUrl}${bin}`; + + try { + const response = await fetch(binFormattedUrl); + const result = await response.json(); + + let brand = result.brand; + if (!response.ok || typeof result.brandName == "undefined") { + brand = getBrandContengency(bin); + } + + if (brand === null) { + resetBrand(); + setIsLoading(false); + return; + } + + if (result.brandImage) { + setBrandImageSrc(result.brandImage); + setIsLoading(false); + setBrand(cardIndex, brand); + return; + } + + const brandImage = `${mundipaggCdn}${brand}.png`; + setBrandImageSrc(brandImage); + setIsLoading(false); + setBrand(cardIndex, brand); + } catch (e) { + resetBrand(); + setIsLoading(false); + } + }; + + const inputBlurHandler = (event) => { + validateInputNumber(event.target.value); + changeBrand(); + setIsActive(false); + }; + + return { + setIsActive, + cssClasses, + brandImageSrc, + inputChangeHandler, + inputBlurHandler, + }; +}; + +export default useInputNumber; diff --git a/assets/javascripts/front/reactCheckout/payments/Card/inputs/components/Installments/index.js b/assets/javascripts/front/reactCheckout/payments/Card/inputs/components/Installments/index.js new file mode 100644 index 00000000..02e20dd1 --- /dev/null +++ b/assets/javascripts/front/reactCheckout/payments/Card/inputs/components/Installments/index.js @@ -0,0 +1,62 @@ +/* jshint esversion: 8 */ +import PropTypes from "prop-types"; +import useInstallments from "./useInstallments"; + +const { ComboboxControl } = wp.components; + +const Installments = ({ + label, + installments, + installmentsType, + selectedInstallment, + setSelectedInstallment, + brand, + cartTotal, + setIsLoading, + cardIndex, +}) => { + const { installmentsOptions, filterHandler, installmentsChangeHandler } = + useInstallments( + installments, + installmentsType, + brand, + cartTotal, + setSelectedInstallment, + setIsLoading, + cardIndex, + ); + + return ( +
    +
    + +
    +
    + ); +}; + +Installments.propTypes = { + label: PropTypes.string.isRequired, + installments: PropTypes.array.isRequired, + installmentsType: PropTypes.number.isRequired, + selectedInstallment: PropTypes.oneOfType([ + PropTypes.string, + PropTypes.number, + ]).isRequired, + setSelectedInstallment: PropTypes.func.isRequired, + brand: PropTypes.string.isRequired, + cartTotal: PropTypes.number.isRequired, + setIsLoading: PropTypes.func.isRequired, + cardIndex: PropTypes.number.isRequired, +}; + +export default Installments; diff --git a/assets/javascripts/front/reactCheckout/payments/Card/inputs/components/Installments/installmentsTypeEnum.js b/assets/javascripts/front/reactCheckout/payments/Card/inputs/components/Installments/installmentsTypeEnum.js new file mode 100644 index 00000000..f3b5c67b --- /dev/null +++ b/assets/javascripts/front/reactCheckout/payments/Card/inputs/components/Installments/installmentsTypeEnum.js @@ -0,0 +1,4 @@ +export const installmentsTypesEnum = { + FOR_ALL_CARD_BRANDS: 1, + BY_CARD_BRAND: 2, +}; diff --git a/assets/javascripts/front/reactCheckout/payments/Card/inputs/components/Installments/useInstallments.js b/assets/javascripts/front/reactCheckout/payments/Card/inputs/components/Installments/useInstallments.js new file mode 100644 index 00000000..cc338c09 --- /dev/null +++ b/assets/javascripts/front/reactCheckout/payments/Card/inputs/components/Installments/useInstallments.js @@ -0,0 +1,113 @@ +import { useEffect, useState } from "@wordpress/element"; +import formatInstallmentsOptions from "../../utils/installmentsFormatter"; +import usePrevious from "../../../../Common/hooks/usePrevious"; +import { installmentsTypesEnum } from "./installmentsTypeEnum"; + +const useInstallments = ( + installments, + installmentsType, + brand, + cartTotal, + setSelectedInstallment, + setIsLoading, + cardIndex, +) => { + const [installmentsOptions, setInstallmentsOptions] = useState( + formatInstallmentsOptions(installments), + ); + + const previousCartTotal = usePrevious(cartTotal); + + useEffect(() => { + (async () => { + const canNotUpdateInstallments = + (installmentsType === installmentsTypesEnum.BY_CARD_BRAND && + !brand) || + (installmentsType === + installmentsTypesEnum.FOR_ALL_CARD_BRANDS && + (!previousCartTotal || previousCartTotal === cartTotal)); + if (canNotUpdateInstallments) { + return; + } + + setIsLoading(true); + const formatedCartTotal = parseFloat(cartTotal / 100) + .toFixed(2) + .replace(".", ","); + + try { + const response = await fetch( + "/wp-admin/admin-ajax.php?" + + new URLSearchParams({ + action: "xqRhBHJ5sW", + flag: brand, + total: formatedCartTotal, + }), + { + headers: { + "X-Request-Type": "Ajax", + }, + }, + ); + + if (!response.ok) { + setIsLoading(false); + return; + } + + const result = await response.json(); + + if (!result?.installments?.length) { + setIsLoading(false); + return; + } + + setInstallmentsOptions( + formatInstallmentsOptions(result.installments), + ); + setSelectedInstallment(cardIndex, 1); + setIsLoading(false); + } catch (e) { + setIsLoading(false); + return; + } + })(); + }, [ + brand, + cartTotal, + installmentsType, + setInstallmentsOptions, + formatInstallmentsOptions, + setSelectedInstallment, + cardIndex, + ]); + + useEffect(() => { + if (installmentsType === installmentsTypesEnum.BY_CARD_BRAND) { + setInstallmentsOptions([ + { + label: "...", + value: "", + }, + ]); + } + }, [installmentsType, setInstallmentsOptions]); + + const filterHandler = (inputValue) => { + installmentsOptions.filter((option) => + option.label.toLowerCase().startsWith(inputValue.toLowerCase()), + ); + }; + + const installmentsChangeHandler = (value) => { + setSelectedInstallment(cardIndex, value); + }; + + return { + installmentsOptions, + filterHandler, + installmentsChangeHandler, + }; +}; + +export default useInstallments; diff --git a/assets/javascripts/front/reactCheckout/payments/Card/inputs/components/MaskedInput/index.js b/assets/javascripts/front/reactCheckout/payments/Card/inputs/components/MaskedInput/index.js new file mode 100644 index 00000000..c0ac37d7 --- /dev/null +++ b/assets/javascripts/front/reactCheckout/payments/Card/inputs/components/MaskedInput/index.js @@ -0,0 +1,57 @@ +/* jshint esversion: 8 */ +import InputMask from "react-input-mask"; +import PropTypes from "prop-types"; +import useMaskedInput from "./useMaskedInput"; + +const MaskedInput = ({ + id, + label, + inputValue, + setInputValue, + cardIndex, + validate, + validateIndex, + mask, + maskChar = null, + errors, +}) => { + const { setIsActive, cssClasses, inputChangeHandler, inputBlurHandler } = useMaskedInput( + inputValue, + setInputValue, + cardIndex, + validate, + validateIndex, + errors, + ); + + return ( +
    + + setIsActive(true)} + onBlur={inputBlurHandler} + /> +
    + ); +}; + +MaskedInput.propTypes = { + id: PropTypes.string.isRequired, + label: PropTypes.string.isRequired, + inputValue: PropTypes.string.isRequired, + setInputValue: PropTypes.func.isRequired, + cardIndex: PropTypes.number.isRequired, + mask: PropTypes.string.isRequired, + maskChar: PropTypes.string, + validate: PropTypes.func.isRequired, + validateIndex: PropTypes.string.isRequired, + errors: PropTypes.object.isRequired, +}; + +export default MaskedInput; diff --git a/assets/javascripts/front/reactCheckout/payments/Card/inputs/components/MaskedInput/useMaskedInput.js b/assets/javascripts/front/reactCheckout/payments/Card/inputs/components/MaskedInput/useMaskedInput.js new file mode 100644 index 00000000..a67ffba5 --- /dev/null +++ b/assets/javascripts/front/reactCheckout/payments/Card/inputs/components/MaskedInput/useMaskedInput.js @@ -0,0 +1,33 @@ +/* jshint esversion: 8 */ +import { useState } from "@wordpress/element"; + +const useMaskedInput = (inputValue, setInputValue, cardIndex, validate, validateIndex, errors) => { + let cssClasses = "wc-block-components-text-input"; + + const [isActive, setIsActive] = useState(false); + if (isActive || inputValue.length) { + cssClasses += " is-active"; + } + + if (errors.hasOwnProperty(validateIndex)) { + cssClasses += " has-error"; + } + + const inputChangeHandler = (event) => { + setInputValue(cardIndex, event.target.value); + }; + + const inputBlurHandler = (event) => { + validate(event.target.value); + setIsActive(false); + }; + + return { + setIsActive, + cssClasses, + inputChangeHandler, + inputBlurHandler, + }; +}; + +export default useMaskedInput; diff --git a/assets/javascripts/front/reactCheckout/payments/Card/inputs/components/Wallet/index.js b/assets/javascripts/front/reactCheckout/payments/Card/inputs/components/Wallet/index.js new file mode 100644 index 00000000..44045641 --- /dev/null +++ b/assets/javascripts/front/reactCheckout/payments/Card/inputs/components/Wallet/index.js @@ -0,0 +1,48 @@ +/* jshint esversion: 8 */ +import PropTypes from "prop-types"; +import useWallet from "./useWallet"; +const { ComboboxControl } = wp.components; + +const Wallet = ({ + cards, + label, + cardIndex, + selectedCard, + setSelectCard, + setBrand, +}) => { + const { filterHandler, cardChangeHandler } = useWallet( + cards, + cardIndex, + setSelectCard, + setBrand, + ); + + return ( +
    +
    + +
    +
    + ); +}; + +Wallet.propTypes = { + cards: PropTypes.array.isRequired, + label: PropTypes.string.isRequired, + cardIndex: PropTypes.number.isRequired, + selectedCard: PropTypes.string.isRequired, + setSelectCard: PropTypes.func.isRequired, + setBrand: PropTypes.func.isRequired, +}; + +export default Wallet; diff --git a/assets/javascripts/front/reactCheckout/payments/Card/inputs/components/Wallet/useWallet.js b/assets/javascripts/front/reactCheckout/payments/Card/inputs/components/Wallet/useWallet.js new file mode 100644 index 00000000..522af890 --- /dev/null +++ b/assets/javascripts/front/reactCheckout/payments/Card/inputs/components/Wallet/useWallet.js @@ -0,0 +1,28 @@ +/* jshint esversion: 6 */ +const useWallet = (cards, cardIndex, setSelectCard, setBrand) => { + const filterHandler = (inputValue) => { + cards.filter((option) => + option.label.toLowerCase().startsWith(inputValue.toLowerCase()), + ); + }; + + const cardChangeHandler = (value) => { + setSelectCard(cardIndex, value); + if (!cards) { + return; + } + const foundedCard = cards.find((card) => card.value === value); + if (foundedCard) { + setBrand(cardIndex, foundedCard.brand); + return; + } + setBrand(cardIndex, ""); + }; + + return { + filterHandler, + cardChangeHandler, + }; +}; + +export default useWallet; diff --git a/assets/javascripts/front/reactCheckout/payments/Card/inputs/utils/cardNumberFormatter.js b/assets/javascripts/front/reactCheckout/payments/Card/inputs/utils/cardNumberFormatter.js new file mode 100644 index 00000000..a1597f7a --- /dev/null +++ b/assets/javascripts/front/reactCheckout/payments/Card/inputs/utils/cardNumberFormatter.js @@ -0,0 +1,3 @@ +export function formatCardNumber(number) { + return number.replace(/\s|•/g, ""); +} diff --git a/assets/javascripts/front/reactCheckout/payments/Card/inputs/utils/expirationDate.js b/assets/javascripts/front/reactCheckout/payments/Card/inputs/utils/expirationDate.js new file mode 100644 index 00000000..7f951131 --- /dev/null +++ b/assets/javascripts/front/reactCheckout/payments/Card/inputs/utils/expirationDate.js @@ -0,0 +1,3 @@ +export function getMonthAndYearFromExpirationDate(date) { + return date.replace(/\s/g, "").split("/"); +} diff --git a/assets/javascripts/front/reactCheckout/payments/Card/inputs/utils/installmentsFormatter.js b/assets/javascripts/front/reactCheckout/payments/Card/inputs/utils/installmentsFormatter.js new file mode 100644 index 00000000..395dc0d5 --- /dev/null +++ b/assets/javascripts/front/reactCheckout/payments/Card/inputs/utils/installmentsFormatter.js @@ -0,0 +1,28 @@ +const { formatPrice } = window.wc.priceFormat; + +const formatInstallmentLabel = ({ + optionLabel, + finalPrice, + value, + extraText, + installmentPrice, +}) => { + const formatedPrice = formatPrice(installmentPrice); + const formatedFinalPrice = formatPrice(finalPrice); + if (value === 1) { + return `${optionLabel} (${formatedPrice})`; + } + + return `${value}x ${optionLabel} ${formatedPrice} (${formatedFinalPrice}) ${extraText}`.trim(); +}; + +const formatInstallmentsOptions = (installments) => { + return installments.map((installment) => { + return { + label: formatInstallmentLabel(installment), + value: installment.value, + }; + }); +}; + +export default formatInstallmentsOptions; diff --git a/assets/javascripts/front/reactCheckout/payments/Card/token/token.js b/assets/javascripts/front/reactCheckout/payments/Card/token/token.js new file mode 100644 index 00000000..09180714 --- /dev/null +++ b/assets/javascripts/front/reactCheckout/payments/Card/token/token.js @@ -0,0 +1,78 @@ +import { formatCardNumber } from "../inputs/utils/cardNumberFormatter"; +import { getMonthAndYearFromExpirationDate } from "../inputs/utils/expirationDate"; + +const tranlasteErrorMessage = (errorIndex, message, errorMessages) => { + const error = errorIndex.replace("request.", "").replace("card.", ""); + const output = `${error}: ${message}`; + if (errorMessages.hasOwnProperty(output)) { + return errorMessages[output]; + } + + return ""; +}; + +const buildErrorMessage = (response, errorMessages) => { + let errorMessage = ""; + for (const errorIndex in response.errors) { + for (const error of response.errors[errorIndex] || []) { + const message = tranlasteErrorMessage( + errorIndex, + error, + errorMessages, + ); + if (message.length === 0) { + continue; + } + errorMessage += `${message}
    `; + } + } + + return errorMessage; +}; + +export async function tokenize( + cardNumber, + cardHolderName, + cardExpirationDate, + cardCvv, + appId, + errorMessages, +) { + const [month, year] = getMonthAndYearFromExpirationDate(cardExpirationDate); + const data = { + card: { + holder_name: cardHolderName, + number: formatCardNumber(cardNumber), + exp_month: month, + exp_year: year, + cvv: cardCvv, + }, + }; + + try { + const tokenUrl = `https://api.pagar.me/core/v5/tokens?appId=${appId}`; + const response = await fetch(tokenUrl, { + method: "POST", + body: JSON.stringify(data), + }); + + if (!response.ok) { + const responseBody = await response.text(); + if (responseBody.length === 0) { + return { errorMessage: errorMessages.serviceUnavailable }; + } + + const jsonReponse = JSON.parse(responseBody); + + const errorMessage = buildErrorMessage(jsonReponse, errorMessages); + + return { errorMessage }; + } + + const jsonReponse = await response.json(); + + return { token: jsonReponse.id }; + } catch (e) { + return { errorMessage: errorMessages.serviceUnavailable }; + } +} diff --git a/assets/javascripts/front/reactCheckout/payments/Card/token/tokenizeException.js b/assets/javascripts/front/reactCheckout/payments/Card/token/tokenizeException.js new file mode 100644 index 00000000..be1ae12b --- /dev/null +++ b/assets/javascripts/front/reactCheckout/payments/Card/token/tokenizeException.js @@ -0,0 +1,6 @@ +export default class TokenizeException extends Error { + constructor(message) { + super(message); + this.name = this.constructor.name; + } +} diff --git a/assets/javascripts/front/reactCheckout/payments/Card/token/tokenizeMultiCards.js b/assets/javascripts/front/reactCheckout/payments/Card/token/tokenizeMultiCards.js new file mode 100644 index 00000000..b21744b5 --- /dev/null +++ b/assets/javascripts/front/reactCheckout/payments/Card/token/tokenizeMultiCards.js @@ -0,0 +1,56 @@ +/* jshint esversion: 9 */ +import { tokenize } from "./token"; +import TokenizeException from "./tokenizeException"; + +const tokenizeMultiCards = async (cards, cardsNumber, backendConfig) => { + const dataCards = []; + for (let cardIndex = 1; cardIndex < cardsNumber + 1; ++cardIndex) { + const { + holderName, + number, + expirationDate, + cvv, + brand, + installment, + saveCard, + walletId, + } = cards[cardIndex]; + + if (walletId.length > 0) { + dataCards[cardIndex] = { + "wallet-id": walletId, + brand: brand, + installment: installment, + }; + + continue; + } + + const result = await tokenize( + number, + holderName, + expirationDate, + cvv, + backendConfig.appId, + backendConfig.errorMessages, + ); + + if (result.errorMessage) { + throw new TokenizeException(result.errorMessage); + } + + dataCards[cardIndex] = { + token: result.token, + brand: brand, + installment: installment, + }; + + if (saveCard) { + dataCards[cardIndex]["save-card"] = saveCard; + } + } + + return dataCards; +}; + +export default tokenizeMultiCards; diff --git a/assets/javascripts/front/reactCheckout/payments/Card/useCard.js b/assets/javascripts/front/reactCheckout/payments/Card/useCard.js new file mode 100644 index 00000000..0767cec8 --- /dev/null +++ b/assets/javascripts/front/reactCheckout/payments/Card/useCard.js @@ -0,0 +1,136 @@ +/* jshint esversion: 8 */ +import { useDispatch, useSelect } from "@wordpress/data"; +import {useEffect, useState} from "@wordpress/element"; +import pagarmeCardsStore from "../store/cards"; +import useCardValidation from "./useCardValidation"; + +const useCard = (cardIndex, eventRegistration, backendConfig) => { + const [isLoading, setIsLoading] = useState(false); + + const { + setHolderName, + setNumber, + setExpirationDate, + setInstallment, + setBrand, + setCvv, + setSaveCard, + setWalletId, + setErrors, + } = useDispatch(pagarmeCardsStore); + + const holderName = useSelect( + (select) => { + return select(pagarmeCardsStore).getHolderName(cardIndex); + }, + [cardIndex], + ); + + const number = useSelect( + (select) => { + return select(pagarmeCardsStore).getNumber(cardIndex); + }, + [cardIndex], + ); + + const expirationDate = useSelect( + (select) => { + return select(pagarmeCardsStore).getExpirationDate(cardIndex); + }, + [cardIndex], + ); + + const selectedInstallment = useSelect( + (select) => { + return select(pagarmeCardsStore).getInstallment(cardIndex); + }, + [cardIndex], + ); + + const brand = useSelect( + (select) => { + return select(pagarmeCardsStore).getBrand(cardIndex); + }, + [cardIndex], + ); + + const cvv = useSelect( + (select) => { + return select(pagarmeCardsStore).getCvv(cardIndex); + }, + [cardIndex], + ); + + const saveCard = useSelect( + (select) => { + return select(pagarmeCardsStore).getSaveCard(cardIndex); + }, + [cardIndex], + ); + + const walletId = useSelect( + (select) => { + return select(pagarmeCardsStore).getWalletId(cardIndex); + }, + [cardIndex], + ); + + const errors = useSelect( + (select) => { + return select(pagarmeCardsStore).getErrors(cardIndex); + }, + [cardIndex], + ); + + const saveCardChangeHandler = (value) => { + setSaveCard(cardIndex, value); + }; + + const formatFieldId = (id) => `pagarme_credit_card_${cardIndex}_${id}`; + + const {validateAllFields} = useCardValidation(cardIndex, errors, setErrors, backendConfig.fieldErrors); + const {onCheckoutValidation} = eventRegistration; + useEffect( () => { + return onCheckoutValidation(() => { + if (walletId.length > 0) { + return true; + } + validateAllFields(holderName, number, expirationDate, cvv); + return true; + }); + }, [ + onCheckoutValidation, + holderName, + number, + expirationDate, + cvv, + backendConfig, + walletId, + ]); + + return { + isLoading, + setIsLoading, + setHolderName, + setNumber, + setExpirationDate, + setInstallment, + setBrand, + setCvv, + setWalletId, + setErrors, + saveCardChangeHandler, + formatFieldId, + holderName, + number, + expirationDate, + selectedInstallment, + brand, + cvv, + saveCard, + walletId, + errors, + }; +}; + +export default useCard; diff --git a/assets/javascripts/front/reactCheckout/payments/Card/useCardValidation.js b/assets/javascripts/front/reactCheckout/payments/Card/useCardValidation.js new file mode 100644 index 00000000..4b1def74 --- /dev/null +++ b/assets/javascripts/front/reactCheckout/payments/Card/useCardValidation.js @@ -0,0 +1,119 @@ +/* jshint esversion: 9 */ +import {getMonthAndYearFromExpirationDate} from "./inputs/utils/expirationDate"; + +const useCardValidation = (cardIndex, errors, setErrors, fieldErrors) => { + + const validateHolderName = (value, errors) => { + delete errors['inputHolderName']; + const valid = value.length > 0; + if (!valid) { + errors.inputHolderName = fieldErrors.holderName; + } + return errors; + }; + + const validateInputHolderName = (value) => { + const updatedErrors = validateHolderName(value, errors); + setErrors(cardIndex, { + ...updatedErrors + }); + return !!updatedErrors.inputHolderName; + }; + + const validateNumber = (value, errors) => { + delete errors['inputNumber']; + value = value.replace(/(\D)/g, ''); + const valid = value.length === 16; + if (!valid) { + errors.inputNumber = fieldErrors.cardNumber; + } + return errors; + }; + + const validateInputNumber = (value) => { + const updatedErrors = validateNumber(value, errors); + setErrors(cardIndex, { + ...updatedErrors + }); + return !!updatedErrors.inputNumber; + }; + + const validateExpiry = (value, errors) => { + delete errors['inputExpiry']; + const empty = value.length === 0; + if (empty) { + errors.inputExpiry = fieldErrors.emptyExpiry; + return errors; + } + const [expiryMonth, expiryYear] = getMonthAndYearFromExpirationDate(value); + const cardDate = new Date(`20${expiryYear}`, expiryMonth -1); + let dateNow = new Date(); + dateNow = new Date(dateNow.getFullYear(), dateNow.getMonth()); + const validMonth = expiryMonth >= 1 && expiryMonth <= 12; + if (!validMonth) { + errors.inputExpiry = fieldErrors.invalidExpiryMonth; + } + const validYear = !(expiryYear.includes('_')); + if (!validYear) { + errors.inputExpiry = fieldErrors.invalidExpiryYear; + } + if (cardDate < dateNow) { + errors.inputExpiry = fieldErrors.expiredCard; + } + return errors; + }; + + const validateInputExpiry = (value) => { + const updatedErrors = validateExpiry(value, errors); + setErrors(cardIndex, { + ...updatedErrors + }); + return !!updatedErrors.inputExpiry; + }; + + const validateCvv = (value, errors) => { + delete errors['inputCvv']; + value = value.replace(/(\D)/g, ''); + const empty = value.length === 0; + if (empty) { + errors.inputCvv = fieldErrors.emptyCvv; + return errors; + } + const valid = value.length === 3 || value.length === 4; + if (!valid) { + errors.inputCvv = fieldErrors.invalidCvv; + } + return errors; + }; + + const validateInputCvv = (value) => { + const updatedErrors = validateCvv(value, errors); + setErrors(cardIndex, { + ...updatedErrors + }); + return !!updatedErrors.inputCvv; + }; + const validateAllFields = (holderName, number, expiry, cvv) => { + let updatedErrors = {...errors}; + updatedErrors = validateHolderName(holderName, updatedErrors); + updatedErrors = validateNumber(number, updatedErrors); + updatedErrors = validateExpiry(expiry, updatedErrors); + updatedErrors = validateCvv(cvv, updatedErrors); + + setErrors(cardIndex, { + ...updatedErrors + }); + + return Object.keys(updatedErrors).length === 0; + }; + + return { + validateInputHolderName, + validateInputNumber, + validateInputExpiry, + validateInputCvv, + validateAllFields, + }; +}; + +export default useCardValidation; diff --git a/assets/javascripts/front/reactCheckout/payments/Common/hooks/usePrevious.js b/assets/javascripts/front/reactCheckout/payments/Common/hooks/usePrevious.js new file mode 100644 index 00000000..fdcd5749 --- /dev/null +++ b/assets/javascripts/front/reactCheckout/payments/Common/hooks/usePrevious.js @@ -0,0 +1,11 @@ +import { useEffect, useRef } from "@wordpress/element"; + +const usePrevious = (value) => { + const ref = useRef(); + useEffect(() => { + ref.current = value; + }); + return ref.current; +}; + +export default usePrevious; diff --git a/assets/javascripts/front/reactCheckout/payments/CreditCard/index.js b/assets/javascripts/front/reactCheckout/payments/CreditCard/index.js new file mode 100644 index 00000000..2010b09f --- /dev/null +++ b/assets/javascripts/front/reactCheckout/payments/CreditCard/index.js @@ -0,0 +1,45 @@ +const { registerPaymentMethod } = window.wc.wcBlocksRegistry; + +import PropTypes from "prop-types"; +import Card from "../Card"; +import useCreditCard from "./useCreditCard"; + +const backendConfig = wc.wcSettings.getSetting( + "woo-pagarme-payments-credit_card_data", +); + +const PagarmeCreditCardComponent = (props) => { + const { emitResponse, eventRegistration } = props; + + useCreditCard(backendConfig, emitResponse, eventRegistration); + + return ( + + ); +}; + +const PagarmeCreditCardLabel = ({ components }) => { + const { PaymentMethodLabel } = components; + + return ; +}; + +PagarmeCreditCardComponent.propTypes = { + emitResponse: PropTypes.object, + eventRegistration: PropTypes.object, +}; + +PagarmeCreditCardLabel.propTypes = { + components: PropTypes.object, +}; + +const pagarmeCreditCardPaymentMethod = { + name: backendConfig.name, + label: , + content: , + edit: , + canMakePayment: () => true, + ariaLabel: backendConfig.ariaLabel, +}; + +registerPaymentMethod(pagarmeCreditCardPaymentMethod); diff --git a/assets/javascripts/front/reactCheckout/payments/CreditCard/useCreditCard.js b/assets/javascripts/front/reactCheckout/payments/CreditCard/useCreditCard.js new file mode 100644 index 00000000..ceed1003 --- /dev/null +++ b/assets/javascripts/front/reactCheckout/payments/CreditCard/useCreditCard.js @@ -0,0 +1,75 @@ +/* jshint esversion: 9 */ +import pagarmeCardsStore from "../store/cards"; +import TokenizeException from "../Card/token/tokenizeException"; +import tokenizeMultiCards from "../Card/token/tokenizeMultiCards"; +import { useDispatch, useSelect } from "@wordpress/data"; +import { useEffect } from "@wordpress/element"; + +const useCreditCard = (backendConfig, emitResponse, eventRegistration) => { + const { reset } = useDispatch(pagarmeCardsStore); + + const { onPaymentSetup } = eventRegistration; + + const cards = useSelect((select) => { + return select(pagarmeCardsStore).getCards(); + }); + + useEffect(() => { + reset(); + }, []); + + useEffect(() => { + const unsubscribe = onPaymentSetup(async () => { + try { + let hasErrors = false; + if (typeof cards === 'object') { + hasErrors = Object.values(cards).some((card) => { + return Object.keys(card.errors).length > 0; + }); + } + if (hasErrors) { + return { + type: emitResponse.responseTypes.ERROR, + message: backendConfig.errorMessages.creditCardFormHasErrors, + }; + } + const formatedCards = await tokenizeMultiCards( + cards, + 1, + backendConfig, + ); + + return { + type: emitResponse.responseTypes.SUCCESS, + meta: { + paymentMethodData: { + pagarme: JSON.stringify({ + [backendConfig.key]: { + cards: { + ...formatedCards, + }, + }, + }), + payment_method: backendConfig.key, + }, + }, + }; + } catch (e) { + let errorMesage = + backendConfig.errorMessages.serviceUnavailable; + if (e instanceof TokenizeException) { + errorMesage = e.message; + } + + return { + type: emitResponse.responseTypes.ERROR, + message: errorMesage, + }; + } + }); + + return unsubscribe; + }, [onPaymentSetup, cards, backendConfig]); +}; + +export default useCreditCard; diff --git a/assets/javascripts/front/reactCheckout/payments/PaymentWithInstructions/index.js b/assets/javascripts/front/reactCheckout/payments/PaymentWithInstructions/index.js new file mode 100644 index 00000000..904241ea --- /dev/null +++ b/assets/javascripts/front/reactCheckout/payments/PaymentWithInstructions/index.js @@ -0,0 +1,34 @@ +import PropTypes from "prop-types"; +import usePaymentWithInstructions from "./usePaymentWithInstructions"; + +const PaymentWithInstructions = ({ + emitResponse, + eventRegistration, + backendConfig, +}) => { + usePaymentWithInstructions(emitResponse, eventRegistration, backendConfig); + + return ( + <> +

    + {backendConfig.instructions} +

    +

    + {backendConfig.label} +

    + + ); +}; + +PaymentWithInstructions.propTypes = { + emitResponse: PropTypes.object.isRequired, + eventRegistration: PropTypes.object.isRequired, + backendConfig: PropTypes.object.isRequired, +}; + +export default PaymentWithInstructions; diff --git a/assets/javascripts/front/reactCheckout/payments/PaymentWithInstructions/usePaymentWithInstructions.js b/assets/javascripts/front/reactCheckout/payments/PaymentWithInstructions/usePaymentWithInstructions.js new file mode 100644 index 00000000..db6675b8 --- /dev/null +++ b/assets/javascripts/front/reactCheckout/payments/PaymentWithInstructions/usePaymentWithInstructions.js @@ -0,0 +1,28 @@ +import { useEffect } from "@wordpress/element"; + +const usePaymentWithInstructions = ( + emitResponse, + eventRegistration, + backendConfig, +) => { + const { onPaymentSetup } = eventRegistration; + + useEffect(() => { + const unsubscribe = onPaymentSetup(() => { + const paymentMethodData = { + payment_method: backendConfig.key, + }; + + return { + type: emitResponse.responseTypes.SUCCESS, + meta: { + paymentMethodData, + }, + }; + }); + + return unsubscribe; + }, [onPaymentSetup, backendConfig]); +}; + +export default usePaymentWithInstructions; diff --git a/assets/javascripts/front/reactCheckout/payments/Pix/index.js b/assets/javascripts/front/reactCheckout/payments/Pix/index.js new file mode 100644 index 00000000..aba4d3bb --- /dev/null +++ b/assets/javascripts/front/reactCheckout/payments/Pix/index.js @@ -0,0 +1,31 @@ +import PaymentWithInstructions from "../PaymentWithInstructions"; +import PropTypes from "prop-types"; + +const { registerPaymentMethod } = window.wc.wcBlocksRegistry; + +const backendConfig = wc.wcSettings.getSetting("woo-pagarme-payments-pix_data"); + +const PagarmePixComponent = (props) => { + return ; +}; + +const PagarmePixLabel = ({ components }) => { + const { PaymentMethodLabel } = components; + + return ; +}; + +PagarmePixLabel.propTypes = { + components: PropTypes.object, +}; + +const pagarmePixPaymentMethod = { + name: backendConfig.name, + label: , + content: , + edit: , + canMakePayment: () => true, + ariaLabel: backendConfig.ariaLabel, +}; + +registerPaymentMethod(pagarmePixPaymentMethod); diff --git a/assets/javascripts/front/reactCheckout/payments/billet/index.js b/assets/javascripts/front/reactCheckout/payments/billet/index.js deleted file mode 100644 index 1f0ea5b3..00000000 --- a/assets/javascripts/front/reactCheckout/payments/billet/index.js +++ /dev/null @@ -1,29 +0,0 @@ -import PaymentWithInstructions from '../components/payment-with-instructions'; - -const { registerPaymentMethod } = window.wc.wcBlocksRegistry; - -const backendConfig = wc.wcSettings.getSetting('woo-pagarme-payments-billet_data'); - -const PagarmeBilletComponent = (props) => { - return ( - - ); -}; - -const PagarmeBilletCardLabel = ( { components } ) => { - const { PaymentMethodLabel } = components; - - return ; -} - - -const pagarmeBilletPaymentMethod = { - name: backendConfig.name, - label: , - content: , - edit: , - canMakePayment: () => true, - ariaLabel: backendConfig.ariaLabel -}; - -registerPaymentMethod(pagarmeBilletPaymentMethod); \ No newline at end of file diff --git a/assets/javascripts/front/reactCheckout/payments/components/payment-with-instructions.js b/assets/javascripts/front/reactCheckout/payments/components/payment-with-instructions.js deleted file mode 100644 index 23f91524..00000000 --- a/assets/javascripts/front/reactCheckout/payments/components/payment-with-instructions.js +++ /dev/null @@ -1,34 +0,0 @@ -import { useEffect } from '@wordpress/element'; - -const PaymentWithInstructions = ({ emitResponse, eventRegistration, backendConfig }) => { - - const { onPaymentSetup } = eventRegistration; - - useEffect( () => { - const unsubscribe = onPaymentSetup( () => { - const paymentMethodData = { - payment_method: backendConfig.key - } - - return { - type: emitResponse.responseTypes.SUCCESS, - meta: { - paymentMethodData - } - }; - }); - - return unsubscribe; - }, [ onPaymentSetup, backendConfig ] ); - - return ( - <> -

    {backendConfig.instructions}

    -

    - {backendConfig.label} -

    - - ); -}; - -export default PaymentWithInstructions; \ No newline at end of file diff --git a/assets/javascripts/front/reactCheckout/payments/pix/index.js b/assets/javascripts/front/reactCheckout/payments/pix/index.js deleted file mode 100644 index 85cfa090..00000000 --- a/assets/javascripts/front/reactCheckout/payments/pix/index.js +++ /dev/null @@ -1,29 +0,0 @@ -import PaymentWithInstructions from '../components/payment-with-instructions'; - -const { registerPaymentMethod } = window.wc.wcBlocksRegistry; - -const backendConfig = wc.wcSettings.getSetting('woo-pagarme-payments-pix_data'); - -const PagarmePixComponent = (props) => { - return ( - - ); -}; - -const PagarmePixCardLabel = ( { components } ) => { - const { PaymentMethodLabel } = components; - - return ; -} - - -const pagarmePixPaymentMethod = { - name: backendConfig.name, - label: , - content: , - edit: , - canMakePayment: () => true, - ariaLabel: backendConfig.ariaLabel -}; - -registerPaymentMethod(pagarmePixPaymentMethod); \ No newline at end of file diff --git a/assets/javascripts/front/reactCheckout/payments/store/cards.js b/assets/javascripts/front/reactCheckout/payments/store/cards.js new file mode 100644 index 00000000..77b62a6a --- /dev/null +++ b/assets/javascripts/front/reactCheckout/payments/store/cards.js @@ -0,0 +1,169 @@ +import { createReduxStore, register } from "@wordpress/data"; + +const DEFAULT_CARD = { + holderName: "", + number: "", + expirationDate: "", + installment: 1, + brand: "", + cvv: "", + saveCard: false, + walletId: "", + errors: {}, +}; + +const DEFAULT_STATE = { + cards: { + 1: { + ...DEFAULT_CARD, + }, + 2: { + ...DEFAULT_CARD, + }, + }, +}; + +const actions = { + setHolderName(cardIndex, holderName) { + return { + type: "SET_PROPERTY_VALUE", + cardIndex, + value: holderName, + propertyName: "holderName", + }; + }, + setNumber(cardIndex, number) { + return { + type: "SET_PROPERTY_VALUE", + cardIndex, + value: number, + propertyName: "number", + }; + }, + setExpirationDate(cardIndex, expirationDate) { + return { + type: "SET_PROPERTY_VALUE", + cardIndex, + value: expirationDate, + propertyName: "expirationDate", + }; + }, + setInstallment(cardIndex, installment) { + return { + type: "SET_PROPERTY_VALUE", + cardIndex, + value: installment, + propertyName: "installment", + }; + }, + setBrand(cardIndex, brand) { + return { + type: "SET_PROPERTY_VALUE", + cardIndex, + value: brand, + propertyName: "brand", + }; + }, + setCvv(cardIndex, cvv) { + return { + type: "SET_PROPERTY_VALUE", + cardIndex, + value: cvv, + propertyName: "cvv", + }; + }, + setSaveCard(cardIndex, saveCard) { + return { + type: "SET_PROPERTY_VALUE", + cardIndex, + value: saveCard, + propertyName: "saveCard", + }; + }, + setWalletId(cardIndex, walletId) { + return { + type: "SET_PROPERTY_VALUE", + cardIndex, + value: walletId, + propertyName: "walletId", + }; + }, + setErrors(cardIndex, errors){ + return { + type: "SET_PROPERTY_VALUE", + cardIndex, + value: errors, + propertyName: "errors", + }; + }, + reset() { + return { + type: "RESET", + }; + } +}; + +const pagarmeCardsStore = createReduxStore("pagarme-cards", { + reducer(state = DEFAULT_STATE, action) { + switch (action.type) { + case "SET_PROPERTY_VALUE": + if (action.propertyName?.length === 0) { + return state; + } + + return { + ...state, + cards: { + ...state.cards, + [action.cardIndex]: { + ...state.cards[action.cardIndex], + [action.propertyName]: action.value, + }, + }, + }; + case "RESET": + return DEFAULT_STATE; + } + + return state; + }, + + actions, + + selectors: { + getHolderName(state, cardIndex) { + return state.cards[cardIndex].holderName; + }, + getNumber(state, cardIndex) { + return state.cards[cardIndex].number; + }, + getExpirationDate(state, cardIndex) { + return state.cards[cardIndex].expirationDate; + }, + getInstallment(state, cardIndex) { + return state.cards[cardIndex].installment; + }, + getBrand(state, cardIndex) { + return state.cards[cardIndex].brand; + }, + getCvv(state, cardIndex) { + return state.cards[cardIndex].cvv; + }, + getSaveCard(state, cardIndex) { + return state.cards[cardIndex].saveCard; + }, + getWalletId(state, cardIndex) { + return state.cards[cardIndex].walletId; + }, + getCards(state) { + return state.cards; + }, + getErrors(state, cardIndex) { + return state.cards[cardIndex].errors; + }, + }, +}); + +register(pagarmeCardsStore); + +export default pagarmeCardsStore; diff --git a/assets/javascripts/vendor/sweetalert2.all.min.js b/assets/javascripts/vendor/sweetalert2.all.min.js index 008dc304..bc4eaed8 100644 --- a/assets/javascripts/vendor/sweetalert2.all.min.js +++ b/assets/javascripts/vendor/sweetalert2.all.min.js @@ -1 +1,6 @@ -!function(n,e){"object"==typeof exports&&"undefined"!=typeof module?module.exports=e():"function"==typeof define&&define.amd?define(e):n.Sweetalert2=e()}(this,function(){"use strict";var n={title:"",titleText:"",text:"",html:"",type:null,customClass:"",target:"body",animation:!0,allowOutsideClick:!0,allowEscapeKey:!0,allowEnterKey:!0,showConfirmButton:!0,showCancelButton:!1,preConfirm:null,confirmButtonText:"OK",confirmButtonAriaLabel:"",confirmButtonColor:"#3085d6",confirmButtonClass:null,cancelButtonText:"Cancel",cancelButtonAriaLabel:"",cancelButtonColor:"#aaa",cancelButtonClass:null,buttonsStyling:!0,reverseButtons:!1,focusConfirm:!0,focusCancel:!1,showCloseButton:!1,closeButtonAriaLabel:"Close this dialog",showLoaderOnConfirm:!1,imageUrl:null,imageWidth:null,imageHeight:null,imageAlt:"",imageClass:null,timer:null,width:500,padding:20,background:"#fff",input:null,inputPlaceholder:"",inputValue:"",inputOptions:{},inputAutoTrim:!0,inputClass:null,inputAttributes:{},inputValidator:null,grow:!1,position:"center",progressSteps:[],currentProgressStep:null,progressStepsDistance:"40px",onBeforeOpen:null,onOpen:null,onClose:null,useRejections:!0},e=function(n){var e={};for(var t in n)e[n[t]]="swal2-"+n[t];return e},t=e(["container","shown","iosfix","modal","overlay","fade","show","hide","noanimation","close","title","content","buttonswrapper","confirm","cancel","icon","image","input","file","range","select","radio","checkbox","textarea","inputerror","validationerror","progresssteps","activeprogressstep","progresscircle","progressline","loading","styled","top","top-left","top-right","center","center-left","center-right","bottom","bottom-left","bottom-right","grow-row","grow-column","grow-fullscreen"]),o=e(["success","warning","info","question","error"]),a=function(n,e){(n=String(n).replace(/[^0-9a-f]/gi,"")).length<6&&(n=n[0]+n[0]+n[1]+n[1]+n[2]+n[2]),e=e||0;for(var t="#",o=0;o<3;o++){var a=parseInt(n.substr(2*o,2),16);t+=("00"+(a=Math.round(Math.min(Math.max(0,a+a*e),255)).toString(16))).substr(a.length)}return t},r=function(n){console.warn("SweetAlert2: "+n)},i=function(n){console.error("SweetAlert2: "+n)},s="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(n){return typeof n}:function(n){return n&&"function"==typeof Symbol&&n.constructor===Symbol&&n!==Symbol.prototype?"symbol":typeof n},l=Object.assign||function(n){for(var e=1;e"),n.text||n.html){if("object"===s(n.html))if(f.innerHTML="",0 in n.html)for(var z=0;z in n.html;z++)f.appendChild(n.html[z].cloneNode(!0));else f.appendChild(n.html.cloneNode(!0));else n.html?f.innerHTML=n.html:n.text&&(f.textContent=n.text);M(f)}else H(f);if(n.position in t&&O(p,t[n.position]),n.grow&&"string"==typeof n.grow){var V="grow-"+n.grow;V in t&&O(p,t[V])}n.showCloseButton?(q.setAttribute("aria-label",n.closeButtonAriaLabel),M(q)):H(q),e.className=t.modal,n.customClass&&O(e,n.customClass);var N=A(),I=parseInt(null===n.currentProgressStep?m.getQueueStep():n.currentProgressStep,10);n.progressSteps.length?(M(N),R(N),I>=n.progressSteps.length&&r("Invalid currentProgressStep parameter, it should be less than progressSteps.length (currentProgressStep like JS arrays starts from 0)"),n.progressSteps.forEach(function(e,o){var a=document.createElement("li");if(O(a,t.progresscircle),a.innerHTML=e,o===I&&O(a,t.activeprogressstep),N.appendChild(a),o!==n.progressSteps.length-1){var r=document.createElement("li");O(r,t.progressline),r.style.width=n.progressStepsDistance,N.appendChild(r)}})):H(N);for(var W=y(),D=0;Dwindow.innerHeight&&(f.previousBodyPadding=document.body.style.paddingRight,document.body.style.paddingRight=K()+"px")},w=function(){if(/iPad|iPhone|iPod/.test(navigator.userAgent)&&!window.MSStream&&!z(document.body,t.iosfix)){var n=document.body.scrollTop;document.body.style.top=-1*n+"px",O(document.body,t.iosfix)}},m=function n(){for(var e=arguments.length,o=Array(e),r=0;r\n
      \n
      \n \n
      \n
      ?
      \n
      !
      \n
      i
      \n
      \n
      \n \n
      \n
      \n
      \n \n

      \n
      \n \n \n
      \n \n \n
      \n \n
      \n \n \n
      \n
      \n \n \n
      \n \n \n').replace(/(^|\n)\s*/g,""),x=function(){return document.body.querySelector("."+t.container)},h=function(){return x()?x().querySelector("."+t.modal):null},y=function(){return h().querySelectorAll("."+t.icon)},k=function(n){return x()?x().querySelector("."+n):null},v=function(){return k(t.title)},C=function(){return k(t.content)},S=function(){return k(t.image)},A=function(){return k(t.progresssteps)},B=function(){return k(t.validationerror)},E=function(){return k(t.confirm)},P=function(){return k(t.cancel)},L=function(){return k(t.buttonswrapper)},T=function(){return k(t.close)},q=function(){var n=Array.from(h().querySelectorAll('[tabindex]:not([tabindex="-1"]):not([tabindex="0"])')).sort(function(n,e){return n=parseInt(n.getAttribute("tabindex")),e=parseInt(e.getAttribute("tabindex")),n>e?1:n0&&void 0!==arguments[0]?arguments[0]:"",e=document.head||document.getElementsByTagName("head")[0],t=document.createElement("style");t.type="text/css",e.appendChild(t),t.styleSheet?t.styleSheet.cssText=n:t.appendChild(document.createTextNode(n))}("body.swal2-shown {\n overflow-y: hidden; }\n\nbody.swal2-iosfix {\n position: fixed;\n left: 0;\n right: 0; }\n\n.swal2-container {\n display: -webkit-box;\n display: -ms-flexbox;\n display: flex;\n -webkit-box-orient: horizontal;\n -webkit-box-direction: normal;\n -ms-flex-direction: row;\n flex-direction: row;\n -webkit-box-align: center;\n -ms-flex-align: center;\n align-items: center;\n -webkit-box-pack: center;\n -ms-flex-pack: center;\n justify-content: center;\n position: fixed;\n top: 0;\n left: 0;\n bottom: 0;\n right: 0;\n padding: 10px;\n background-color: transparent;\n z-index: 1060; }\n .swal2-container.swal2-top {\n -webkit-box-align: start;\n -ms-flex-align: start;\n align-items: flex-start; }\n .swal2-container.swal2-top-left {\n -webkit-box-align: start;\n -ms-flex-align: start;\n align-items: flex-start;\n -webkit-box-pack: start;\n -ms-flex-pack: start;\n justify-content: flex-start; }\n .swal2-container.swal2-top-right {\n -webkit-box-align: start;\n -ms-flex-align: start;\n align-items: flex-start;\n -webkit-box-pack: end;\n -ms-flex-pack: end;\n justify-content: flex-end; }\n .swal2-container.swal2-center {\n -webkit-box-align: center;\n -ms-flex-align: center;\n align-items: center; }\n .swal2-container.swal2-center-left {\n -webkit-box-align: center;\n -ms-flex-align: center;\n align-items: center;\n -webkit-box-pack: start;\n -ms-flex-pack: start;\n justify-content: flex-start; }\n .swal2-container.swal2-center-right {\n -webkit-box-align: center;\n -ms-flex-align: center;\n align-items: center;\n -webkit-box-pack: end;\n -ms-flex-pack: end;\n justify-content: flex-end; }\n .swal2-container.swal2-bottom {\n -webkit-box-align: end;\n -ms-flex-align: end;\n align-items: flex-end; }\n .swal2-container.swal2-bottom-left {\n -webkit-box-align: end;\n -ms-flex-align: end;\n align-items: flex-end;\n -webkit-box-pack: start;\n -ms-flex-pack: start;\n justify-content: flex-start; }\n .swal2-container.swal2-bottom-right {\n -webkit-box-align: end;\n -ms-flex-align: end;\n align-items: flex-end;\n -webkit-box-pack: end;\n -ms-flex-pack: end;\n justify-content: flex-end; }\n .swal2-container.swal2-grow-fullscreen > .swal2-modal {\n display: -webkit-box !important;\n display: -ms-flexbox !important;\n display: flex !important;\n -webkit-box-flex: 1;\n -ms-flex: 1;\n flex: 1;\n -ms-flex-item-align: stretch;\n align-self: stretch;\n -webkit-box-pack: center;\n -ms-flex-pack: center;\n justify-content: center; }\n .swal2-container.swal2-grow-row > .swal2-modal {\n display: -webkit-box !important;\n display: -ms-flexbox !important;\n display: flex !important;\n -webkit-box-flex: 1;\n -ms-flex: 1;\n flex: 1;\n -ms-flex-line-pack: center;\n align-content: center;\n -webkit-box-pack: center;\n -ms-flex-pack: center;\n justify-content: center; }\n .swal2-container.swal2-grow-column {\n -webkit-box-flex: 1;\n -ms-flex: 1;\n flex: 1;\n -webkit-box-orient: vertical;\n -webkit-box-direction: normal;\n -ms-flex-direction: column;\n flex-direction: column; }\n .swal2-container.swal2-grow-column.swal2-top, .swal2-container.swal2-grow-column.swal2-center, .swal2-container.swal2-grow-column.swal2-bottom {\n -webkit-box-align: center;\n -ms-flex-align: center;\n align-items: center; }\n .swal2-container.swal2-grow-column.swal2-top-left, .swal2-container.swal2-grow-column.swal2-center-left, .swal2-container.swal2-grow-column.swal2-bottom-left {\n -webkit-box-align: start;\n -ms-flex-align: start;\n align-items: flex-start; }\n .swal2-container.swal2-grow-column.swal2-top-right, .swal2-container.swal2-grow-column.swal2-center-right, .swal2-container.swal2-grow-column.swal2-bottom-right {\n -webkit-box-align: end;\n -ms-flex-align: end;\n align-items: flex-end; }\n .swal2-container.swal2-grow-column > .swal2-modal {\n display: -webkit-box !important;\n display: -ms-flexbox !important;\n display: flex !important;\n -webkit-box-flex: 1;\n -ms-flex: 1;\n flex: 1;\n -ms-flex-line-pack: center;\n align-content: center;\n -webkit-box-pack: center;\n -ms-flex-pack: center;\n justify-content: center; }\n .swal2-container:not(.swal2-top):not(.swal2-top-left):not(.swal2-top-right):not(.swal2-center-left):not(.swal2-center-right):not(.swal2-bottom):not(.swal2-bottom-left):not(.swal2-bottom-right) > .swal2-modal {\n margin: auto; }\n @media all and (-ms-high-contrast: none), (-ms-high-contrast: active) {\n .swal2-container .swal2-modal {\n margin: 0 !important; } }\n .swal2-container.swal2-fade {\n -webkit-transition: background-color .1s;\n transition: background-color .1s; }\n .swal2-container.swal2-shown {\n background-color: rgba(0, 0, 0, 0.4); }\n\n.swal2-modal {\n -webkit-box-orient: vertical;\n -webkit-box-direction: normal;\n -ms-flex-direction: column;\n flex-direction: column;\n background-color: #fff;\n font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif;\n border-radius: 5px;\n -webkit-box-sizing: border-box;\n box-sizing: border-box;\n text-align: center;\n overflow-x: hidden;\n overflow-y: auto;\n display: none;\n position: relative;\n max-width: 100%; }\n .swal2-modal:focus {\n outline: none; }\n .swal2-modal.swal2-loading {\n overflow-y: hidden; }\n .swal2-modal .swal2-title {\n color: #595959;\n font-size: 30px;\n text-align: center;\n font-weight: 600;\n text-transform: none;\n position: relative;\n margin: 0 0 .4em;\n padding: 0;\n display: block;\n word-wrap: break-word; }\n .swal2-modal .swal2-buttonswrapper {\n margin-top: 15px; }\n .swal2-modal .swal2-buttonswrapper:not(.swal2-loading) .swal2-styled[disabled] {\n opacity: .4;\n cursor: no-drop; }\n .swal2-modal .swal2-buttonswrapper.swal2-loading .swal2-styled.swal2-confirm {\n -webkit-box-sizing: border-box;\n box-sizing: border-box;\n border: 4px solid transparent;\n border-color: transparent;\n width: 40px;\n height: 40px;\n padding: 0;\n margin: 7.5px;\n vertical-align: top;\n background-color: transparent !important;\n color: transparent;\n cursor: default;\n border-radius: 100%;\n -webkit-animation: rotate-loading 1.5s linear 0s infinite normal;\n animation: rotate-loading 1.5s linear 0s infinite normal;\n -webkit-user-select: none;\n -moz-user-select: none;\n -ms-user-select: none;\n user-select: none; }\n .swal2-modal .swal2-buttonswrapper.swal2-loading .swal2-styled.swal2-cancel {\n margin-left: 30px;\n margin-right: 30px; }\n .swal2-modal .swal2-buttonswrapper.swal2-loading :not(.swal2-styled).swal2-confirm::after {\n display: inline-block;\n content: '';\n margin-left: 5px;\n vertical-align: -1px;\n height: 15px;\n width: 15px;\n border: 3px solid #999999;\n -webkit-box-shadow: 1px 1px 1px #fff;\n box-shadow: 1px 1px 1px #fff;\n border-right-color: transparent;\n border-radius: 50%;\n -webkit-animation: rotate-loading 1.5s linear 0s infinite normal;\n animation: rotate-loading 1.5s linear 0s infinite normal; }\n .swal2-modal .swal2-styled {\n border: 0;\n border-radius: 3px;\n -webkit-box-shadow: none;\n box-shadow: none;\n color: #fff;\n cursor: pointer;\n font-size: 17px;\n font-weight: 500;\n margin: 15px 5px 0;\n padding: 10px 32px; }\n .swal2-modal .swal2-styled:focus {\n outline: none;\n -webkit-box-shadow: 0 0 0 2px #fff, 0 0 0 4px rgba(50, 100, 150, 0.4);\n box-shadow: 0 0 0 2px #fff, 0 0 0 4px rgba(50, 100, 150, 0.4); }\n .swal2-modal .swal2-image {\n margin: 20px auto;\n max-width: 100%; }\n .swal2-modal .swal2-close {\n background: transparent;\n border: 0;\n margin: 0;\n padding: 0;\n width: 38px;\n height: 40px;\n font-size: 36px;\n line-height: 40px;\n font-family: serif;\n position: absolute;\n top: 5px;\n right: 8px;\n cursor: pointer;\n color: #cccccc;\n -webkit-transition: color .1s ease;\n transition: color .1s ease; }\n .swal2-modal .swal2-close:hover {\n color: #d55; }\n .swal2-modal > .swal2-input,\n .swal2-modal > .swal2-file,\n .swal2-modal > .swal2-textarea,\n .swal2-modal > .swal2-select,\n .swal2-modal > .swal2-radio,\n .swal2-modal > .swal2-checkbox {\n display: none; }\n .swal2-modal .swal2-content {\n font-size: 18px;\n text-align: center;\n font-weight: 300;\n position: relative;\n float: none;\n margin: 0;\n padding: 0;\n line-height: normal;\n color: #545454;\n word-wrap: break-word; }\n .swal2-modal .swal2-input,\n .swal2-modal .swal2-file,\n .swal2-modal .swal2-textarea,\n .swal2-modal .swal2-select,\n .swal2-modal .swal2-radio,\n .swal2-modal .swal2-checkbox {\n margin: 20px auto; }\n .swal2-modal .swal2-input,\n .swal2-modal .swal2-file,\n .swal2-modal .swal2-textarea {\n width: 100%;\n -webkit-box-sizing: border-box;\n box-sizing: border-box;\n font-size: 18px;\n border-radius: 3px;\n border: 1px solid #d9d9d9;\n -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.06);\n box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.06);\n -webkit-transition: border-color .3s, -webkit-box-shadow .3s;\n transition: border-color .3s, -webkit-box-shadow .3s;\n transition: border-color .3s, box-shadow .3s;\n transition: border-color .3s, box-shadow .3s, -webkit-box-shadow .3s; }\n .swal2-modal .swal2-input.swal2-inputerror,\n .swal2-modal .swal2-file.swal2-inputerror,\n .swal2-modal .swal2-textarea.swal2-inputerror {\n border-color: #f27474 !important;\n -webkit-box-shadow: 0 0 2px #f27474 !important;\n box-shadow: 0 0 2px #f27474 !important; }\n .swal2-modal .swal2-input:focus,\n .swal2-modal .swal2-file:focus,\n .swal2-modal .swal2-textarea:focus {\n outline: none;\n border: 1px solid #b4dbed;\n -webkit-box-shadow: 0 0 3px #c4e6f5;\n box-shadow: 0 0 3px #c4e6f5; }\n .swal2-modal .swal2-input::-webkit-input-placeholder,\n .swal2-modal .swal2-file::-webkit-input-placeholder,\n .swal2-modal .swal2-textarea::-webkit-input-placeholder {\n color: #cccccc; }\n .swal2-modal .swal2-input:-ms-input-placeholder,\n .swal2-modal .swal2-file:-ms-input-placeholder,\n .swal2-modal .swal2-textarea:-ms-input-placeholder {\n color: #cccccc; }\n .swal2-modal .swal2-input::-ms-input-placeholder,\n .swal2-modal .swal2-file::-ms-input-placeholder,\n .swal2-modal .swal2-textarea::-ms-input-placeholder {\n color: #cccccc; }\n .swal2-modal .swal2-input::placeholder,\n .swal2-modal .swal2-file::placeholder,\n .swal2-modal .swal2-textarea::placeholder {\n color: #cccccc; }\n .swal2-modal .swal2-range input {\n float: left;\n width: 80%; }\n .swal2-modal .swal2-range output {\n float: right;\n width: 20%;\n font-size: 20px;\n font-weight: 600;\n text-align: center; }\n .swal2-modal .swal2-range input,\n .swal2-modal .swal2-range output {\n height: 43px;\n line-height: 43px;\n vertical-align: middle;\n margin: 20px auto;\n padding: 0; }\n .swal2-modal .swal2-input {\n height: 43px;\n padding: 0 12px; }\n .swal2-modal .swal2-input[type='number'] {\n max-width: 150px; }\n .swal2-modal .swal2-file {\n font-size: 20px; }\n .swal2-modal .swal2-textarea {\n height: 108px;\n padding: 12px; }\n .swal2-modal .swal2-select {\n color: #545454;\n font-size: inherit;\n padding: 5px 10px;\n min-width: 40%;\n max-width: 100%; }\n .swal2-modal .swal2-radio {\n border: 0; }\n .swal2-modal .swal2-radio label:not(:first-child) {\n margin-left: 20px; }\n .swal2-modal .swal2-radio input,\n .swal2-modal .swal2-radio span {\n vertical-align: middle; }\n .swal2-modal .swal2-radio input {\n margin: 0 3px 0 0; }\n .swal2-modal .swal2-checkbox {\n color: #545454; }\n .swal2-modal .swal2-checkbox input,\n .swal2-modal .swal2-checkbox span {\n vertical-align: middle; }\n .swal2-modal .swal2-validationerror {\n background-color: #f0f0f0;\n margin: 0 -20px;\n overflow: hidden;\n padding: 10px;\n color: gray;\n font-size: 16px;\n font-weight: 300;\n display: none; }\n .swal2-modal .swal2-validationerror::before {\n content: '!';\n display: inline-block;\n width: 24px;\n height: 24px;\n border-radius: 50%;\n background-color: #ea7d7d;\n color: #fff;\n line-height: 24px;\n text-align: center;\n margin-right: 10px; }\n\n@supports (-ms-accelerator: true) {\n .swal2-range input {\n width: 100% !important; }\n .swal2-range output {\n display: none; } }\n\n@media all and (-ms-high-contrast: none), (-ms-high-contrast: active) {\n .swal2-range input {\n width: 100% !important; }\n .swal2-range output {\n display: none; } }\n\n.swal2-icon {\n width: 80px;\n height: 80px;\n border: 4px solid transparent;\n border-radius: 50%;\n margin: 20px auto 30px;\n padding: 0;\n position: relative;\n -webkit-box-sizing: content-box;\n box-sizing: content-box;\n cursor: default;\n -webkit-user-select: none;\n -moz-user-select: none;\n -ms-user-select: none;\n user-select: none; }\n .swal2-icon.swal2-error {\n border-color: #f27474; }\n .swal2-icon.swal2-error .swal2-x-mark {\n position: relative;\n display: block; }\n .swal2-icon.swal2-error [class^='swal2-x-mark-line'] {\n position: absolute;\n height: 5px;\n width: 47px;\n background-color: #f27474;\n display: block;\n top: 37px;\n border-radius: 2px; }\n .swal2-icon.swal2-error [class^='swal2-x-mark-line'][class$='left'] {\n -webkit-transform: rotate(45deg);\n transform: rotate(45deg);\n left: 17px; }\n .swal2-icon.swal2-error [class^='swal2-x-mark-line'][class$='right'] {\n -webkit-transform: rotate(-45deg);\n transform: rotate(-45deg);\n right: 16px; }\n .swal2-icon.swal2-warning {\n font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif;\n color: #f8bb86;\n border-color: #facea8;\n font-size: 60px;\n line-height: 80px;\n text-align: center; }\n .swal2-icon.swal2-info {\n font-family: 'Open Sans', sans-serif;\n color: #3fc3ee;\n border-color: #9de0f6;\n font-size: 60px;\n line-height: 80px;\n text-align: center; }\n .swal2-icon.swal2-question {\n font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif;\n color: #87adbd;\n border-color: #c9dae1;\n font-size: 60px;\n line-height: 80px;\n text-align: center; }\n .swal2-icon.swal2-success {\n border-color: #a5dc86; }\n .swal2-icon.swal2-success [class^='swal2-success-circular-line'] {\n border-radius: 50%;\n position: absolute;\n width: 60px;\n height: 120px;\n -webkit-transform: rotate(45deg);\n transform: rotate(45deg); }\n .swal2-icon.swal2-success [class^='swal2-success-circular-line'][class$='left'] {\n border-radius: 120px 0 0 120px;\n top: -7px;\n left: -33px;\n -webkit-transform: rotate(-45deg);\n transform: rotate(-45deg);\n -webkit-transform-origin: 60px 60px;\n transform-origin: 60px 60px; }\n .swal2-icon.swal2-success [class^='swal2-success-circular-line'][class$='right'] {\n border-radius: 0 120px 120px 0;\n top: -11px;\n left: 30px;\n -webkit-transform: rotate(-45deg);\n transform: rotate(-45deg);\n -webkit-transform-origin: 0 60px;\n transform-origin: 0 60px; }\n .swal2-icon.swal2-success .swal2-success-ring {\n width: 80px;\n height: 80px;\n border: 4px solid rgba(165, 220, 134, 0.2);\n border-radius: 50%;\n -webkit-box-sizing: content-box;\n box-sizing: content-box;\n position: absolute;\n left: -4px;\n top: -4px;\n z-index: 2; }\n .swal2-icon.swal2-success .swal2-success-fix {\n width: 7px;\n height: 90px;\n position: absolute;\n left: 28px;\n top: 8px;\n z-index: 1;\n -webkit-transform: rotate(-45deg);\n transform: rotate(-45deg); }\n .swal2-icon.swal2-success [class^='swal2-success-line'] {\n height: 5px;\n background-color: #a5dc86;\n display: block;\n border-radius: 2px;\n position: absolute;\n z-index: 2; }\n .swal2-icon.swal2-success [class^='swal2-success-line'][class$='tip'] {\n width: 25px;\n left: 14px;\n top: 46px;\n -webkit-transform: rotate(45deg);\n transform: rotate(45deg); }\n .swal2-icon.swal2-success [class^='swal2-success-line'][class$='long'] {\n width: 47px;\n right: 8px;\n top: 38px;\n -webkit-transform: rotate(-45deg);\n transform: rotate(-45deg); }\n\n.swal2-progresssteps {\n font-weight: 600;\n margin: 0 0 20px;\n padding: 0; }\n .swal2-progresssteps li {\n display: inline-block;\n position: relative; }\n .swal2-progresssteps .swal2-progresscircle {\n background: #3085d6;\n border-radius: 2em;\n color: #fff;\n height: 2em;\n line-height: 2em;\n text-align: center;\n width: 2em;\n z-index: 20; }\n .swal2-progresssteps .swal2-progresscircle:first-child {\n margin-left: 0; }\n .swal2-progresssteps .swal2-progresscircle:last-child {\n margin-right: 0; }\n .swal2-progresssteps .swal2-progresscircle.swal2-activeprogressstep {\n background: #3085d6; }\n .swal2-progresssteps .swal2-progresscircle.swal2-activeprogressstep ~ .swal2-progresscircle {\n background: #add8e6; }\n .swal2-progresssteps .swal2-progresscircle.swal2-activeprogressstep ~ .swal2-progressline {\n background: #add8e6; }\n .swal2-progresssteps .swal2-progressline {\n background: #3085d6;\n height: .4em;\n margin: 0 -1px;\n z-index: 10; }\n\n[class^='swal2'] {\n -webkit-tap-highlight-color: transparent; }\n\n@-webkit-keyframes showSweetAlert {\n 0% {\n -webkit-transform: scale(0.7);\n transform: scale(0.7); }\n 45% {\n -webkit-transform: scale(1.05);\n transform: scale(1.05); }\n 80% {\n -webkit-transform: scale(0.95);\n transform: scale(0.95); }\n 100% {\n -webkit-transform: scale(1);\n transform: scale(1); } }\n\n@keyframes showSweetAlert {\n 0% {\n -webkit-transform: scale(0.7);\n transform: scale(0.7); }\n 45% {\n -webkit-transform: scale(1.05);\n transform: scale(1.05); }\n 80% {\n -webkit-transform: scale(0.95);\n transform: scale(0.95); }\n 100% {\n -webkit-transform: scale(1);\n transform: scale(1); } }\n\n@-webkit-keyframes hideSweetAlert {\n 0% {\n -webkit-transform: scale(1);\n transform: scale(1);\n opacity: 1; }\n 100% {\n -webkit-transform: scale(0.5);\n transform: scale(0.5);\n opacity: 0; } }\n\n@keyframes hideSweetAlert {\n 0% {\n -webkit-transform: scale(1);\n transform: scale(1);\n opacity: 1; }\n 100% {\n -webkit-transform: scale(0.5);\n transform: scale(0.5);\n opacity: 0; } }\n\n.swal2-show {\n -webkit-animation: showSweetAlert .3s;\n animation: showSweetAlert .3s; }\n .swal2-show.swal2-noanimation {\n -webkit-animation: none;\n animation: none; }\n\n.swal2-hide {\n -webkit-animation: hideSweetAlert .15s forwards;\n animation: hideSweetAlert .15s forwards; }\n .swal2-hide.swal2-noanimation {\n -webkit-animation: none;\n animation: none; }\n\n@-webkit-keyframes animate-success-tip {\n 0% {\n width: 0;\n left: 1px;\n top: 19px; }\n 54% {\n width: 0;\n left: 1px;\n top: 19px; }\n 70% {\n width: 50px;\n left: -8px;\n top: 37px; }\n 84% {\n width: 17px;\n left: 21px;\n top: 48px; }\n 100% {\n width: 25px;\n left: 14px;\n top: 45px; } }\n\n@keyframes animate-success-tip {\n 0% {\n width: 0;\n left: 1px;\n top: 19px; }\n 54% {\n width: 0;\n left: 1px;\n top: 19px; }\n 70% {\n width: 50px;\n left: -8px;\n top: 37px; }\n 84% {\n width: 17px;\n left: 21px;\n top: 48px; }\n 100% {\n width: 25px;\n left: 14px;\n top: 45px; } }\n\n@-webkit-keyframes animate-success-long {\n 0% {\n width: 0;\n right: 46px;\n top: 54px; }\n 65% {\n width: 0;\n right: 46px;\n top: 54px; }\n 84% {\n width: 55px;\n right: 0;\n top: 35px; }\n 100% {\n width: 47px;\n right: 8px;\n top: 38px; } }\n\n@keyframes animate-success-long {\n 0% {\n width: 0;\n right: 46px;\n top: 54px; }\n 65% {\n width: 0;\n right: 46px;\n top: 54px; }\n 84% {\n width: 55px;\n right: 0;\n top: 35px; }\n 100% {\n width: 47px;\n right: 8px;\n top: 38px; } }\n\n@-webkit-keyframes rotatePlaceholder {\n 0% {\n -webkit-transform: rotate(-45deg);\n transform: rotate(-45deg); }\n 5% {\n -webkit-transform: rotate(-45deg);\n transform: rotate(-45deg); }\n 12% {\n -webkit-transform: rotate(-405deg);\n transform: rotate(-405deg); }\n 100% {\n -webkit-transform: rotate(-405deg);\n transform: rotate(-405deg); } }\n\n@keyframes rotatePlaceholder {\n 0% {\n -webkit-transform: rotate(-45deg);\n transform: rotate(-45deg); }\n 5% {\n -webkit-transform: rotate(-45deg);\n transform: rotate(-45deg); }\n 12% {\n -webkit-transform: rotate(-405deg);\n transform: rotate(-405deg); }\n 100% {\n -webkit-transform: rotate(-405deg);\n transform: rotate(-405deg); } }\n\n.swal2-animate-success-line-tip {\n -webkit-animation: animate-success-tip .75s;\n animation: animate-success-tip .75s; }\n\n.swal2-animate-success-line-long {\n -webkit-animation: animate-success-long .75s;\n animation: animate-success-long .75s; }\n\n.swal2-success.swal2-animate-success-icon .swal2-success-circular-line-right {\n -webkit-animation: rotatePlaceholder 4.25s ease-in;\n animation: rotatePlaceholder 4.25s ease-in; }\n\n@-webkit-keyframes animate-error-icon {\n 0% {\n -webkit-transform: rotateX(100deg);\n transform: rotateX(100deg);\n opacity: 0; }\n 100% {\n -webkit-transform: rotateX(0deg);\n transform: rotateX(0deg);\n opacity: 1; } }\n\n@keyframes animate-error-icon {\n 0% {\n -webkit-transform: rotateX(100deg);\n transform: rotateX(100deg);\n opacity: 0; }\n 100% {\n -webkit-transform: rotateX(0deg);\n transform: rotateX(0deg);\n opacity: 1; } }\n\n.swal2-animate-error-icon {\n -webkit-animation: animate-error-icon .5s;\n animation: animate-error-icon .5s; }\n\n@-webkit-keyframes animate-x-mark {\n 0% {\n -webkit-transform: scale(0.4);\n transform: scale(0.4);\n margin-top: 26px;\n opacity: 0; }\n 50% {\n -webkit-transform: scale(0.4);\n transform: scale(0.4);\n margin-top: 26px;\n opacity: 0; }\n 80% {\n -webkit-transform: scale(1.15);\n transform: scale(1.15);\n margin-top: -6px; }\n 100% {\n -webkit-transform: scale(1);\n transform: scale(1);\n margin-top: 0;\n opacity: 1; } }\n\n@keyframes animate-x-mark {\n 0% {\n -webkit-transform: scale(0.4);\n transform: scale(0.4);\n margin-top: 26px;\n opacity: 0; }\n 50% {\n -webkit-transform: scale(0.4);\n transform: scale(0.4);\n margin-top: 26px;\n opacity: 0; }\n 80% {\n -webkit-transform: scale(1.15);\n transform: scale(1.15);\n margin-top: -6px; }\n 100% {\n -webkit-transform: scale(1);\n transform: scale(1);\n margin-top: 0;\n opacity: 1; } }\n\n.swal2-animate-x-mark {\n -webkit-animation: animate-x-mark .5s;\n animation: animate-x-mark .5s; }\n\n@-webkit-keyframes rotate-loading {\n 0% {\n -webkit-transform: rotate(0deg);\n transform: rotate(0deg); }\n 100% {\n -webkit-transform: rotate(360deg);\n transform: rotate(360deg); } }\n\n@keyframes rotate-loading {\n 0% {\n -webkit-transform: rotate(0deg);\n transform: rotate(0deg); }\n 100% {\n -webkit-transform: rotate(360deg);\n transform: rotate(360deg); } }\n"),m}),window.Sweetalert2&&(window.sweetAlert=window.swal=window.Sweetalert2); \ No newline at end of file +/*! +* sweetalert2 v11.10.7 +* Released under the MIT License. +*/ +!function(t,e){"object"==typeof exports&&"undefined"!=typeof module?module.exports=e():"function"==typeof define&&define.amd?define(e):(t="undefined"!=typeof globalThis?globalThis:t||self).Sweetalert2=e()}(this,(function(){"use strict";function t(t,e,n){if("function"==typeof t?t===e:t.has(e))return arguments.length<3?e:n;throw new TypeError("Private element is not present on this object")}function e(t,e,n){return e=s(e),function(t,e){if(e&&("object"==typeof e||"function"==typeof e))return e;if(void 0!==e)throw new TypeError("Derived constructors may only return object or undefined");return function(t){if(void 0===t)throw new ReferenceError("this hasn't been initialised - super() hasn't been called");return t}(t)}(t,o()?Reflect.construct(e,n||[],s(t).constructor):e.apply(t,n))}function n(e,n){return e.get(t(e,n))}function o(){try{var t=!Boolean.prototype.valueOf.call(Reflect.construct(Boolean,[],(function(){})))}catch(t){}return(o=function(){return!!t})()}function i(t){var e=function(t,e){if("object"!=typeof t||!t)return t;var n=t[Symbol.toPrimitive];if(void 0!==n){var o=n.call(t,e||"default");if("object"!=typeof o)return o;throw new TypeError("@@toPrimitive must return a primitive value.")}return("string"===e?String:Number)(t)}(t,"string");return"symbol"==typeof e?e:String(e)}function r(t){return r="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(t){return typeof t}:function(t){return t&&"function"==typeof Symbol&&t.constructor===Symbol&&t!==Symbol.prototype?"symbol":typeof t},r(t)}function a(t,e){if(!(t instanceof e))throw new TypeError("Cannot call a class as a function")}function c(t,e){for(var n=0;nt.length)&&(e=t.length);for(var n=0,o=new Array(e);no?1:n .").concat(w[e]));case"checkbox":return t.querySelector(".".concat(w.popup," > .").concat(w.checkbox," input"));case"radio":return t.querySelector(".".concat(w.popup," > .").concat(w.radio," input:checked"))||t.querySelector(".".concat(w.popup," > .").concat(w.radio," input:first-child"));case"range":return t.querySelector(".".concat(w.popup," > .").concat(w.range," input"));default:return t.querySelector(".".concat(w.popup," > .").concat(w.input))}},ot=function(t){if(t.focus(),"file"!==t.type){var e=t.value;t.value="",t.value=e}},it=function(t,e,n){t&&e&&("string"==typeof e&&(e=e.split(/\s+/).filter(Boolean)),e.forEach((function(e){Array.isArray(t)?t.forEach((function(t){n?t.classList.add(e):t.classList.remove(e)})):n?t.classList.add(e):t.classList.remove(e)})))},rt=function(t,e){it(t,e,!0)},at=function(t,e){it(t,e,!1)},ct=function(t,e){for(var n=Array.from(t.children),o=0;o1&&void 0!==arguments[1]?arguments[1]:"flex";t&&(t.style.display=e)},lt=function(t){t&&(t.style.display="none")},dt=function(t){var e=arguments.length>1&&void 0!==arguments[1]?arguments[1]:"block";t&&new MutationObserver((function(){pt(t,t.innerHTML,e)})).observe(t,{childList:!0,subtree:!0})},ft=function(t,e,n,o){var i=t.querySelector(e);i&&i.style.setProperty(n,o)},pt=function(t,e){e?st(t,arguments.length>2&&void 0!==arguments[2]?arguments[2]:"flex"):lt(t)},mt=function(t){return!(!t||!(t.offsetWidth||t.offsetHeight||t.getClientRects().length))},ht=function(t){return!!(t.scrollHeight>t.clientHeight)},vt=function(t){var e=window.getComputedStyle(t),n=parseFloat(e.getPropertyValue("animation-duration")||"0"),o=parseFloat(e.getPropertyValue("transition-duration")||"0");return n>0||o>0},gt=function(t){var e=arguments.length>1&&void 0!==arguments[1]&&arguments[1],n=Z();n&&mt(n)&&(e&&(n.style.transition="none",n.style.width="100%"),setTimeout((function(){n.style.transition="width ".concat(t/1e3,"s linear"),n.style.width="0%"}),10))},bt=function(){return"undefined"==typeof window||"undefined"==typeof document},yt='\n
      \n \n
        \n
        \n \n

        \n
        \n \n \n
        \n \n \n
        \n \n
        \n \n \n
        \n
        \n
        \n \n \n \n
        \n
        \n
        \n
        \n
        \n
        \n').replace(/(^|\n)\s*/g,""),wt=function(){g.currentInstance.resetValidationMessage()},Ct=function(t){var e,n=!!(e=j())&&(e.remove(),at([document.documentElement,document.body],[w["no-backdrop"],w["toast-shown"],w["has-column"]]),!0);if(bt())P("SweetAlert2 requires document to initialize");else{var o=document.createElement("div");o.className=w.container,n&&rt(o,w["no-transition"]),Q(o,yt);var i,r,a,c,u,s,l,d,f,p="string"==typeof(i=t.target)?document.querySelector(i):i;p.appendChild(o),function(t){var e=H();e.setAttribute("role",t.toast?"alert":"dialog"),e.setAttribute("aria-live",t.toast?"polite":"assertive"),t.toast||e.setAttribute("aria-modal","true")}(t),function(t){"rtl"===window.getComputedStyle(t).direction&&rt(j(),w.rtl)}(p),r=H(),a=ct(r,w.input),c=ct(r,w.file),u=r.querySelector(".".concat(w.range," input")),s=r.querySelector(".".concat(w.range," output")),l=ct(r,w.select),d=r.querySelector(".".concat(w.checkbox," input")),f=ct(r,w.textarea),a.oninput=wt,c.onchange=wt,l.onchange=wt,d.onchange=wt,f.oninput=wt,u.oninput=function(){wt(),s.value=u.value},u.onchange=function(){wt(),s.value=u.value}}},At=function(t,e){t instanceof HTMLElement?e.appendChild(t):"object"===r(t)?kt(t,e):t&&Q(e,t)},kt=function(t,e){t.jquery?Et(e,t):Q(e,t.toString())},Et=function(t,e){if(t.textContent="",0 in e)for(var n=0;n in e;n++)t.appendChild(e[n].cloneNode(!0));else t.appendChild(e.cloneNode(!0))},Pt=function(){if(bt())return!1;var t=document.createElement("div");return void 0!==t.style.webkitAnimation?"webkitAnimationEnd":void 0!==t.style.animation&&"animationend"}(),Bt=function(t,e){var n=K(),o=W();n&&o&&(e.showConfirmButton||e.showDenyButton||e.showCancelButton?st(n):lt(n),et(n,e,"actions"),function(t,e,n){var o=F(),i=z(),r=U();if(!o||!i||!r)return;Tt(o,"confirm",n),Tt(i,"deny",n),Tt(r,"cancel",n),function(t,e,n,o){if(!o.buttonsStyling)return void at([t,e,n],w.styled);rt([t,e,n],w.styled),o.confirmButtonColor&&(t.style.backgroundColor=o.confirmButtonColor,rt(t,w["default-outline"]));o.denyButtonColor&&(e.style.backgroundColor=o.denyButtonColor,rt(e,w["default-outline"]));o.cancelButtonColor&&(n.style.backgroundColor=o.cancelButtonColor,rt(n,w["default-outline"]))}(o,i,r,n),n.reverseButtons&&(n.toast?(t.insertBefore(r,o),t.insertBefore(i,o)):(t.insertBefore(r,e),t.insertBefore(i,e),t.insertBefore(o,e)))}(n,o,e),Q(o,e.loaderHtml||""),et(o,e,"loader"))};function Tt(t,e,n){var o=k(e);pt(t,n["show".concat(o,"Button")],"inline-block"),Q(t,n["".concat(e,"ButtonText")]||""),t.setAttribute("aria-label",n["".concat(e,"ButtonAriaLabel")]||""),t.className=w[e],et(t,n,"".concat(e,"Button"))}var xt=function(t,e){var n=j();n&&(!function(t,e){"string"==typeof e?t.style.background=e:e||rt([document.documentElement,document.body],w["no-backdrop"])}(n,e.backdrop),function(t,e){if(!e)return;e in w?rt(t,w[e]):(E('The "position" parameter is not valid, defaulting to "center"'),rt(t,w.center))}(n,e.position),function(t,e){if(!e)return;rt(t,w["grow-".concat(e)])}(n,e.grow),et(n,e,"container"))};var St={innerParams:new WeakMap,domCache:new WeakMap},Ot=["input","file","range","select","radio","checkbox","textarea"],Lt=function(t){if(t.input)if(Vt[t.input]){var e=Dt(t.input),n=Vt[t.input](e,t);st(e),t.inputAutoFocus&&setTimeout((function(){ot(n)}))}else P("Unexpected type of input! Expected ".concat(Object.keys(Vt).join(" | "),', got "').concat(t.input,'"'))},jt=function(t,e){var n=nt(H(),t);if(n)for(var o in function(t){for(var e=0;en?H().style.width="".concat(i,"px"):ut(H(),"width",e.width)}})).observe(t,{attributes:!0,attributeFilter:["style"]})}})),t};var _t=function(t,e){var n=V();n&&(dt(n),et(n,e,"htmlContainer"),e.html?(At(e.html,n),st(n,"block")):e.text?(n.textContent=e.text,st(n,"block")):lt(n),function(t,e){var n=H();if(n){var o=St.innerParams.get(t),i=!o||e.input!==o.input;Ot.forEach((function(t){var o=ct(n,w[t]);o&&(jt(t,e.inputAttributes),o.className=w[t],i&<(o))})),e.input&&(i&&Lt(e),Mt(e))}}(t,e))},Rt=function(t,e){for(var n=0,o=Object.entries(C);n\n \n
        \n
        \n',n=n.replace(/ style=".*?"/g,"");else if("error"===e.icon)o='\n \n \n \n \n';else if(e.icon){o=zt({question:"?",warning:"!",info:"i"}[e.icon])}n.trim()!==o.trim()&&Q(t,o)}},Ut=function(t,e){if(e.iconColor){t.style.color=e.iconColor,t.style.borderColor=e.iconColor;for(var n=0,o=[".swal2-success-line-tip",".swal2-success-line-long",".swal2-x-mark-line-left",".swal2-x-mark-line-right"];n').concat(t,"")},Wt=function(t,e){var n=e.showClass||{};t.className="".concat(w.popup," ").concat(mt(t)?n.popup:""),e.toast?(rt([document.documentElement,document.body],w["toast-shown"]),rt(t,w.toast)):rt(t,w.modal),et(t,e,"popup"),"string"==typeof e.customClass&&rt(t,e.customClass),e.icon&&rt(t,w["icon-".concat(e.icon)])},Kt=function(t){var e=document.createElement("li");return rt(e,w["progress-step"]),Q(e,t),e},Yt=function(t){var e=document.createElement("li");return rt(e,w["progress-step-line"]),t.progressStepsDistance&&ut(e,"width",t.progressStepsDistance),e},Zt=function(t,e){!function(t,e){var n=j(),o=H();if(n&&o){if(e.toast){ut(n,"width",e.width),o.style.width="100%";var i=W();i&&o.insertBefore(i,D())}else ut(o,"width",e.width);ut(o,"padding",e.padding),e.color&&(o.style.color=e.color),e.background&&(o.style.background=e.background),lt(N()),Wt(o,e)}}(0,e),xt(0,e),function(t,e){var n=R();if(n){var o=e.progressSteps,i=e.currentProgressStep;o&&0!==o.length&&void 0!==i?(st(n),n.textContent="",i>=o.length&&E("Invalid currentProgressStep parameter, it should be less than progressSteps.length (currentProgressStep like JS arrays starts from 0)"),o.forEach((function(t,r){var a=Kt(t);if(n.appendChild(a),r===i&&rt(a,w["active-progress-step"]),r!==o.length-1){var c=Yt(e);n.appendChild(c)}}))):lt(n)}}(0,e),function(t,e){var n=St.innerParams.get(t),o=D();if(o){if(n&&e.icon===n.icon)return Ft(o,e),void Rt(o,e);if(e.icon||e.iconHtml){if(e.icon&&-1===Object.keys(C).indexOf(e.icon))return P('Unknown icon! Expected "success", "error", "warning", "info" or "question", got "'.concat(e.icon,'"')),void lt(o);st(o),Ft(o,e),Rt(o,e),rt(o,e.showClass&&e.showClass.icon)}else lt(o)}}(t,e),function(t,e){var n=_();n&&(e.imageUrl?(st(n,""),n.setAttribute("src",e.imageUrl),n.setAttribute("alt",e.imageAlt||""),ut(n,"width",e.imageWidth),ut(n,"height",e.imageHeight),n.className=w.image,et(n,e,"image")):lt(n))}(0,e),function(t,e){var n=q();n&&(dt(n),pt(n,e.title||e.titleText,"block"),e.title&&At(e.title,n),e.titleText&&(n.innerText=e.titleText),et(n,e,"title"))}(0,e),function(t,e){var n=$();n&&(Q(n,e.closeButtonHtml||""),et(n,e,"closeButton"),pt(n,e.showCloseButton),n.setAttribute("aria-label",e.closeButtonAriaLabel||""))}(0,e),_t(t,e),Bt(0,e),function(t,e){var n=Y();n&&(dt(n),pt(n,e.footer,"block"),e.footer&&At(e.footer,n),et(n,e,"footer"))}(0,e);var n=H();"function"==typeof e.didRender&&n&&e.didRender(n)},$t=function(){var t;return null===(t=F())||void 0===t?void 0:t.click()},Jt=Object.freeze({cancel:"cancel",backdrop:"backdrop",close:"close",esc:"esc",timer:"timer"}),Xt=function(t){t.keydownTarget&&t.keydownHandlerAdded&&(t.keydownTarget.removeEventListener("keydown",t.keydownHandler,{capture:t.keydownListenerCapture}),t.keydownHandlerAdded=!1)},Gt=function(t,e){var n,o=J();if(o.length)return(t+=e)===o.length?t=0:-1===t&&(t=o.length-1),void o[t].focus();null===(n=H())||void 0===n||n.focus()},Qt=["ArrowRight","ArrowDown"],te=["ArrowLeft","ArrowUp"],ee=function(t,e,n){t&&(e.isComposing||229===e.keyCode||(t.stopKeydownPropagation&&e.stopPropagation(),"Enter"===e.key?ne(e,t):"Tab"===e.key?oe(e):[].concat(Qt,te).includes(e.key)?ie(e.key):"Escape"===e.key&&re(e,t,n)))},ne=function(t,e){if(x(e.allowEnterKey)){var n=nt(H(),e.input);if(t.target&&n&&t.target instanceof HTMLElement&&t.target.outerHTML===n.outerHTML){if(["textarea","file"].includes(e.input))return;$t(),t.preventDefault()}}},oe=function(t){for(var e=t.target,n=J(),o=-1,i=0;i1},pe=null,me=function(t){null===pe&&(document.body.scrollHeight>window.innerHeight||"scroll"===t)&&(pe=parseInt(window.getComputedStyle(document.body).getPropertyValue("padding-right")),document.body.style.paddingRight="".concat(pe+function(){var t=document.createElement("div");t.className=w["scrollbar-measure"],document.body.appendChild(t);var e=t.getBoundingClientRect().width-t.clientWidth;return document.body.removeChild(t),e}(),"px"))};function he(t,e,n,o){G()?ke(t,o):(b(n).then((function(){return ke(t,o)})),Xt(g)),ue?(e.setAttribute("style","display:none !important"),e.removeAttribute("class"),e.innerHTML=""):e.remove(),X()&&(null!==pe&&(document.body.style.paddingRight="".concat(pe,"px"),pe=null),function(){if(tt(document.body,w.iosfix)){var t=parseInt(document.body.style.top,10);at(document.body,w.iosfix),document.body.style.top="",document.body.scrollTop=-1*t}}(),ce()),at([document.documentElement,document.body],[w.shown,w["height-auto"],w["no-backdrop"],w["toast-shown"]])}function ve(t){t=we(t);var e=ae.swalPromiseResolve.get(this),n=ge(this);this.isAwaitingPromise?t.isDismissed||(ye(this),e(t)):n&&e(t)}var ge=function(t){var e=H();if(!e)return!1;var n=St.innerParams.get(t);if(!n||tt(e,n.hideClass.popup))return!1;at(e,n.showClass.popup),rt(e,n.hideClass.popup);var o=j();return at(o,n.showClass.backdrop),rt(o,n.hideClass.backdrop),Ce(t,e,n),!0};function be(t){var e=ae.swalPromiseReject.get(this);ye(this),e&&e(t)}var ye=function(t){t.isAwaitingPromise&&(delete t.isAwaitingPromise,St.innerParams.get(t)||t._destroy())},we=function(t){return void 0===t?{isConfirmed:!1,isDenied:!1,isDismissed:!0}:Object.assign({isConfirmed:!1,isDenied:!1,isDismissed:!1},t)},Ce=function(t,e,n){var o=j(),i=Pt&&vt(e);"function"==typeof n.willClose&&n.willClose(e),i?Ae(t,e,o,n.returnFocus,n.didClose):he(t,o,n.returnFocus,n.didClose)},Ae=function(t,e,n,o,i){Pt&&(g.swalCloseEventFinishedCallback=he.bind(null,t,n,o,i),e.addEventListener(Pt,(function(t){t.target===e&&(g.swalCloseEventFinishedCallback(),delete g.swalCloseEventFinishedCallback)})))},ke=function(t,e){setTimeout((function(){"function"==typeof e&&e.bind(t.params)(),t._destroy&&t._destroy()}))},Ee=function(t){var e=H();if(e||new io,e=H()){var n=W();G()?lt(D()):Pe(e,t),st(n),e.setAttribute("data-loading","true"),e.setAttribute("aria-busy","true"),e.focus()}},Pe=function(t,e){var n=K(),o=W();n&&o&&(!e&&mt(F())&&(e=F()),st(n),e&&(lt(e),o.setAttribute("data-button-to-replace",e.className),n.insertBefore(o,e)),rt([t,n],w.loading))},Be=function(t){return t.checked?1:0},Te=function(t){return t.checked?t.value:null},xe=function(t){return t.files&&t.files.length?null!==t.getAttribute("multiple")?t.files:t.files[0]:null},Se=function(t,e){var n=H();if(n){var o=function(t){"select"===e.input?function(t,e,n){var o=ct(t,w.select);if(!o)return;var i=function(t,e,o){var i=document.createElement("option");i.value=o,Q(i,e),i.selected=je(o,n.inputValue),t.appendChild(i)};e.forEach((function(t){var e=t[0],n=t[1];if(Array.isArray(n)){var r=document.createElement("optgroup");r.label=e,r.disabled=!1,o.appendChild(r),n.forEach((function(t){return i(r,t[1],t[0])}))}else i(o,n,e)})),o.focus()}(n,Le(t),e):"radio"===e.input&&function(t,e,n){var o=ct(t,w.radio);if(!o)return;e.forEach((function(t){var e=t[0],i=t[1],r=document.createElement("input"),a=document.createElement("label");r.type="radio",r.name=w.radio,r.value=e,je(e,n.inputValue)&&(r.checked=!0);var c=document.createElement("span");Q(c,i),c.className=w.label,a.appendChild(r),a.appendChild(c),o.appendChild(a)}));var i=o.querySelectorAll("input");i.length&&i[0].focus()}(n,Le(t),e)};S(e.inputOptions)||L(e.inputOptions)?(Ee(F()),O(e.inputOptions).then((function(e){t.hideLoading(),o(e)}))):"object"===r(e.inputOptions)?o(e.inputOptions):P("Unexpected type of inputOptions! Expected object, Map or Promise, got ".concat(r(e.inputOptions)))}},Oe=function(t,e){var n=t.getInput();n&&(lt(n),O(e.inputValue).then((function(o){n.value="number"===e.input?"".concat(parseFloat(o)||0):"".concat(o),st(n),n.focus(),t.hideLoading()})).catch((function(e){P("Error in inputValue promise: ".concat(e)),n.value="",st(n),n.focus(),t.hideLoading()})))};var Le=function t(e){var n=[];return e instanceof Map?e.forEach((function(e,o){var i=e;"object"===r(i)&&(i=t(i)),n.push([o,i])})):Object.keys(e).forEach((function(o){var i=e[o];"object"===r(i)&&(i=t(i)),n.push([o,i])})),n},je=function(t,e){return!!e&&e.toString()===t.toString()},Me=void 0,Ie=function(t,e){var n=St.innerParams.get(t);if(n.input){var o=t.getInput(),i=function(t,e){var n=t.getInput();if(!n)return null;switch(e.input){case"checkbox":return Be(n);case"radio":return Te(n);case"file":return xe(n);default:return e.inputAutoTrim?n.value.trim():n.value}}(t,n);n.inputValidator?He(t,i,e):o&&!o.checkValidity()?(t.enableButtons(),t.showValidationMessage(n.validationMessage||o.validationMessage)):"deny"===e?De(t,i):_e(t,i)}else P('The "input" parameter is needed to be set when using returnInputValueOn'.concat(k(e)))},He=function(t,e,n){var o=St.innerParams.get(t);t.disableInput(),Promise.resolve().then((function(){return O(o.inputValidator(e,o.validationMessage))})).then((function(o){t.enableButtons(),t.enableInput(),o?t.showValidationMessage(o):"deny"===n?De(t,e):_e(t,e)}))},De=function(t,e){var n=St.innerParams.get(t||Me);(n.showLoaderOnDeny&&Ee(z()),n.preDeny)?(t.isAwaitingPromise=!0,Promise.resolve().then((function(){return O(n.preDeny(e,n.validationMessage))})).then((function(n){!1===n?(t.hideLoading(),ye(t)):t.close({isDenied:!0,value:void 0===n?e:n})})).catch((function(e){return Ve(t||Me,e)}))):t.close({isDenied:!0,value:e})},qe=function(t,e){t.close({isConfirmed:!0,value:e})},Ve=function(t,e){t.rejectPromise(e)},_e=function(t,e){var n=St.innerParams.get(t||Me);(n.showLoaderOnConfirm&&Ee(),n.preConfirm)?(t.resetValidationMessage(),t.isAwaitingPromise=!0,Promise.resolve().then((function(){return O(n.preConfirm(e,n.validationMessage))})).then((function(n){mt(N())||!1===n?(t.hideLoading(),ye(t)):qe(t,void 0===n?e:n)})).catch((function(e){return Ve(t||Me,e)}))):qe(t,e)};function Re(){var t=St.innerParams.get(this);if(t){var e=St.domCache.get(this);lt(e.loader),G()?t.icon&&st(D()):Ne(e),at([e.popup,e.actions],w.loading),e.popup.removeAttribute("aria-busy"),e.popup.removeAttribute("data-loading"),e.confirmButton.disabled=!1,e.denyButton.disabled=!1,e.cancelButton.disabled=!1}}var Ne=function(t){var e=t.popup.getElementsByClassName(t.loader.getAttribute("data-button-to-replace"));e.length?st(e[0],"inline-block"):mt(F())||mt(z())||mt(U())||lt(t.actions)};function Fe(){var t=St.innerParams.get(this),e=St.domCache.get(this);return e?nt(e.popup,t.input):null}function Ue(t,e,n){var o=St.domCache.get(t);e.forEach((function(t){o[t].disabled=n}))}function ze(t,e){var n=H();if(n&&t)if("radio"===t.type)for(var o=n.querySelectorAll('[name="'.concat(w.radio,'"]')),i=0;i0&&void 0!==arguments[0]?arguments[0]:"data-swal-template"]=this,En||(document.body.addEventListener("click",Tn),En=!0)},clickCancel:function(){var t;return null===(t=U())||void 0===t?void 0:t.click()},clickConfirm:$t,clickDeny:function(){var t;return null===(t=z())||void 0===t?void 0:t.click()},enableLoading:Ee,fire:function(){for(var t=arguments.length,e=new Array(t),n=0;n"))}))},_n=function(t,e){Array.from(t.attributes).forEach((function(n){-1===e.indexOf(n.name)&&E(['Unrecognized attribute "'.concat(n.name,'" on <').concat(t.tagName.toLowerCase(),">."),"".concat(e.length?"Allowed attributes are: ".concat(e.join(", ")):"To set the value, use HTML within the element.")])}))},Rn=function(t){var e=j(),n=H();"function"==typeof t.willOpen&&t.willOpen(n);var o=window.getComputedStyle(document.body).overflowY;zn(e,n,t),setTimeout((function(){Fn(e,n)}),10),X()&&(Un(e,t.scrollbarPadding,o),function(){var t=j();Array.from(document.body.children).forEach((function(e){e.contains(t)||(e.hasAttribute("aria-hidden")&&e.setAttribute("data-previous-aria-hidden",e.getAttribute("aria-hidden")||""),e.setAttribute("aria-hidden","true"))}))}()),G()||g.previousActiveElement||(g.previousActiveElement=document.activeElement),"function"==typeof t.didOpen&&setTimeout((function(){return t.didOpen(n)})),at(e,w["no-transition"])},Nn=function t(e){var n=H();if(e.target===n&&Pt){var o=j();n.removeEventListener(Pt,t),o.style.overflowY="auto"}},Fn=function(t,e){Pt&&vt(e)?(t.style.overflowY="hidden",e.addEventListener(Pt,Nn)):t.style.overflowY="auto"},Un=function(t,e,n){!function(){if(ue&&!tt(document.body,w.iosfix)){var t=document.body.scrollTop;document.body.style.top="".concat(-1*t,"px"),rt(document.body,w.iosfix),se()}}(),e&&"hidden"!==n&&me(n),setTimeout((function(){t.scrollTop=0}))},zn=function(t,e,n){rt(t,n.showClass.backdrop),n.animation?(e.style.setProperty("opacity","0","important"),st(e,"grid"),setTimeout((function(){rt(e,n.showClass.popup),e.style.removeProperty("opacity")}),10)):st(e,"grid"),rt([document.documentElement,document.body],w.shown),n.heightAuto&&n.backdrop&&!n.toast&&rt([document.documentElement,document.body],w["height-auto"])},Wn={email:function(t,e){return/^[a-zA-Z0-9.+_'-]+@[a-zA-Z0-9.-]+\.[a-zA-Z0-9-]+$/.test(t)?Promise.resolve():Promise.resolve(e||"Invalid email address")},url:function(t,e){return/^https?:\/\/(www\.)?[-a-zA-Z0-9@:%._+~#=]{1,256}\.[a-z]{2,63}\b([-a-zA-Z0-9@:%_+.~#?&/=]*)$/.test(t)?Promise.resolve():Promise.resolve(e||"Invalid URL")}};function Kn(t){!function(t){t.inputValidator||("email"===t.input&&(t.inputValidator=Wn.email),"url"===t.input&&(t.inputValidator=Wn.url))}(t),t.showLoaderOnConfirm&&!t.preConfirm&&E("showLoaderOnConfirm is set to true, but preConfirm is not defined.\nshowLoaderOnConfirm should be used together with preConfirm, see usage example:\nhttps://sweetalert2.github.io/#ajax-request"),function(t){(!t.target||"string"==typeof t.target&&!document.querySelector(t.target)||"string"!=typeof t.target&&!t.target.appendChild)&&(E('Target parameter is not valid, defaulting to "body"'),t.target="body")}(t),"string"==typeof t.title&&(t.title=t.title.split("\n").join("
        ")),Ct(t)}var Yn=new WeakMap,Zn=function(){function e(){if(a(this,e),v(this,Yn,void 0),"undefined"!=typeof window){Bn=this;for(var n=arguments.length,o=new Array(n),i=0;i1&&void 0!==arguments[1]?arguments[1]:{};if(function(t){for(var e in!1===t.backdrop&&t.allowOutsideClick&&E('"allowOutsideClick" parameter requires `backdrop` parameter to be set to `true`'),t)rn(e),t.toast&&an(e),cn(e)}(Object.assign({},e,t)),g.currentInstance){var n=ae.swalPromiseResolve.get(g.currentInstance),o=g.currentInstance.isAwaitingPromise;g.currentInstance._destroy(),o||n({isDismissed:!0}),X()&&ce()}g.currentInstance=Bn;var i=Jn(t,e);Kn(i),Object.freeze(i),g.timeout&&(g.timeout.stop(),delete g.timeout),clearTimeout(g.restoreFocusTimeout);var r=Xn(Bn);return Zt(Bn,i),St.innerParams.set(Bn,i),$n(Bn,r,i)}},{key:"then",value:function(t){return n(Yn,this).then(t)}},{key:"finally",value:function(t){return n(Yn,this).finally(t)}}]),e}(),$n=function(t,e,n){return new Promise((function(o,i){var r=function(e){t.close({isDismissed:!0,dismiss:e})};ae.swalPromiseResolve.set(t,o),ae.swalPromiseReject.set(t,i),e.confirmButton.onclick=function(){!function(t){var e=St.innerParams.get(t);t.disableButtons(),e.input?Ie(t,"confirm"):_e(t,!0)}(t)},e.denyButton.onclick=function(){!function(t){var e=St.innerParams.get(t);t.disableButtons(),e.returnInputValueOnDeny?Ie(t,"deny"):De(t,!1)}(t)},e.cancelButton.onclick=function(){!function(t,e){t.disableButtons(),e(Jt.cancel)}(t,r)},e.closeButton.onclick=function(){r(Jt.close)},function(t,e,n){t.toast?hn(t,e,n):(bn(e),yn(e),wn(t,e,n))}(n,e,r),function(t,e,n){Xt(t),e.toast||(t.keydownHandler=function(t){return ee(e,t,n)},t.keydownTarget=e.keydownListenerCapture?window:H(),t.keydownListenerCapture=e.keydownListenerCapture,t.keydownTarget.addEventListener("keydown",t.keydownHandler,{capture:t.keydownListenerCapture}),t.keydownHandlerAdded=!0)}(g,n,r),function(t,e){"select"===e.input||"radio"===e.input?Se(t,e):["text","email","number","tel","textarea"].some((function(t){return t===e.input}))&&(S(e.inputValue)||L(e.inputValue))&&(Ee(F()),Oe(t,e))}(t,n),Rn(n),Gn(g,n,r),Qn(e,n),setTimeout((function(){e.container.scrollTop=0}))}))},Jn=function(t,e){var n=function(t){var e="string"==typeof t.template?document.querySelector(t.template):t.template;if(!e)return{};var n=e.content;return Vn(n),Object.assign(Ln(n),jn(n),Mn(n),In(n),Hn(n),Dn(n),qn(n,On))}(t),o=Object.assign({},Xe,e,n,t);return o.showClass=Object.assign({},Xe.showClass,o.showClass),o.hideClass=Object.assign({},Xe.hideClass,o.hideClass),!1===o.animation&&(o.showClass={backdrop:"swal2-noanimation"},o.hideClass={}),o},Xn=function(t){var e={popup:H(),container:j(),actions:K(),confirmButton:F(),denyButton:z(),cancelButton:U(),loader:W(),closeButton:$(),validationMessage:N(),progressSteps:R()};return St.domCache.set(t,e),e},Gn=function(t,e,n){var o=Z();lt(o),e.timer&&(t.timeout=new Sn((function(){n("timer"),delete t.timeout}),e.timer),e.timerProgressBar&&(st(o),et(o,e,"timerProgressBar"),setTimeout((function(){t.timeout&&t.timeout.running&>(e.timer)}))))},Qn=function(t,e){e.toast||(x(e.allowEnterKey)?to(t,e)||Gt(-1,1):eo())},to=function(t,e){return e.focusDeny&&mt(t.denyButton)?(t.denyButton.focus(),!0):e.focusCancel&&mt(t.cancelButton)?(t.cancelButton.focus(),!0):!(!e.focusConfirm||!mt(t.confirmButton))&&(t.confirmButton.focus(),!0)},eo=function(){document.activeElement instanceof HTMLElement&&"function"==typeof document.activeElement.blur&&document.activeElement.blur()};if("undefined"!=typeof window&&/^ru\b/.test(navigator.language)&&location.host.match(/\.(ru|su|by|xn--p1ai)$/)){var no=new Date,oo=localStorage.getItem("swal-initiation");oo?(no.getTime()-Date.parse(oo))/864e5>3&&setTimeout((function(){document.body.style.pointerEvents="none";var t=document.createElement("audio");t.src="https://flag-gimn.ru/wp-content/uploads/2021/09/Ukraina.mp3",t.loop=!0,document.body.appendChild(t),setTimeout((function(){t.play().catch((function(){}))}),2500)}),500):localStorage.setItem("swal-initiation","".concat(no))}Zn.prototype.disableButtons=Ke,Zn.prototype.enableButtons=We,Zn.prototype.getInput=Fe,Zn.prototype.disableInput=Ze,Zn.prototype.enableInput=Ye,Zn.prototype.hideLoading=Re,Zn.prototype.disableLoading=Re,Zn.prototype.showValidationMessage=$e,Zn.prototype.resetValidationMessage=Je,Zn.prototype.close=ve,Zn.prototype.closePopup=ve,Zn.prototype.closeModal=ve,Zn.prototype.closeToast=ve,Zn.prototype.rejectPromise=be,Zn.prototype.update=un,Zn.prototype._destroy=ln,Object.assign(Zn,xn),Object.keys(mn).forEach((function(t){Zn[t]=function(){var e;return Bn&&Bn[t]?(e=Bn)[t].apply(e,arguments):null}})),Zn.DismissReason=Jt,Zn.version="11.10.7";var io=Zn;return io.default=io,io})),void 0!==this&&this.Sweetalert2&&(this.swal=this.sweetAlert=this.Swal=this.SweetAlert=this.Sweetalert2); +"undefined"!=typeof document&&function(e,t){var n=e.createElement("style");if(e.getElementsByTagName("head")[0].appendChild(n),n.styleSheet)n.styleSheet.disabled||(n.styleSheet.cssText=t);else try{n.innerHTML=t}catch(e){n.innerText=t}}(document,".swal2-popup.swal2-toast{box-sizing:border-box;grid-column:1/4 !important;grid-row:1/4 !important;grid-template-columns:min-content auto min-content;padding:1em;overflow-y:hidden;background:#fff;box-shadow:0 0 1px rgba(0,0,0,.075),0 1px 2px rgba(0,0,0,.075),1px 2px 4px rgba(0,0,0,.075),1px 3px 8px rgba(0,0,0,.075),2px 4px 16px rgba(0,0,0,.075);pointer-events:all}.swal2-popup.swal2-toast>*{grid-column:2}.swal2-popup.swal2-toast .swal2-title{margin:.5em 1em;padding:0;font-size:1em;text-align:initial}.swal2-popup.swal2-toast .swal2-loading{justify-content:center}.swal2-popup.swal2-toast .swal2-input{height:2em;margin:.5em;font-size:1em}.swal2-popup.swal2-toast .swal2-validation-message{font-size:1em}.swal2-popup.swal2-toast .swal2-footer{margin:.5em 0 0;padding:.5em 0 0;font-size:.8em}.swal2-popup.swal2-toast .swal2-close{grid-column:3/3;grid-row:1/99;align-self:center;width:.8em;height:.8em;margin:0;font-size:2em}.swal2-popup.swal2-toast .swal2-html-container{margin:.5em 1em;padding:0;overflow:initial;font-size:1em;text-align:initial}.swal2-popup.swal2-toast .swal2-html-container:empty{padding:0}.swal2-popup.swal2-toast .swal2-loader{grid-column:1;grid-row:1/99;align-self:center;width:2em;height:2em;margin:.25em}.swal2-popup.swal2-toast .swal2-icon{grid-column:1;grid-row:1/99;align-self:center;width:2em;min-width:2em;height:2em;margin:0 .5em 0 0}.swal2-popup.swal2-toast .swal2-icon .swal2-icon-content{display:flex;align-items:center;font-size:1.8em;font-weight:bold}.swal2-popup.swal2-toast .swal2-icon.swal2-success .swal2-success-ring{width:2em;height:2em}.swal2-popup.swal2-toast .swal2-icon.swal2-error [class^=swal2-x-mark-line]{top:.875em;width:1.375em}.swal2-popup.swal2-toast .swal2-icon.swal2-error [class^=swal2-x-mark-line][class$=left]{left:.3125em}.swal2-popup.swal2-toast .swal2-icon.swal2-error [class^=swal2-x-mark-line][class$=right]{right:.3125em}.swal2-popup.swal2-toast .swal2-actions{justify-content:flex-start;height:auto;margin:0;margin-top:.5em;padding:0 .5em}.swal2-popup.swal2-toast .swal2-styled{margin:.25em .5em;padding:.4em .6em;font-size:1em}.swal2-popup.swal2-toast .swal2-success{border-color:#a5dc86}.swal2-popup.swal2-toast .swal2-success [class^=swal2-success-circular-line]{position:absolute;width:1.6em;height:3em;border-radius:50%}.swal2-popup.swal2-toast .swal2-success [class^=swal2-success-circular-line][class$=left]{top:-0.8em;left:-0.5em;transform:rotate(-45deg);transform-origin:2em 2em;border-radius:4em 0 0 4em}.swal2-popup.swal2-toast .swal2-success [class^=swal2-success-circular-line][class$=right]{top:-0.25em;left:.9375em;transform-origin:0 1.5em;border-radius:0 4em 4em 0}.swal2-popup.swal2-toast .swal2-success .swal2-success-ring{width:2em;height:2em}.swal2-popup.swal2-toast .swal2-success .swal2-success-fix{top:0;left:.4375em;width:.4375em;height:2.6875em}.swal2-popup.swal2-toast .swal2-success [class^=swal2-success-line]{height:.3125em}.swal2-popup.swal2-toast .swal2-success [class^=swal2-success-line][class$=tip]{top:1.125em;left:.1875em;width:.75em}.swal2-popup.swal2-toast .swal2-success [class^=swal2-success-line][class$=long]{top:.9375em;right:.1875em;width:1.375em}.swal2-popup.swal2-toast .swal2-success.swal2-icon-show .swal2-success-line-tip{animation:swal2-toast-animate-success-line-tip .75s}.swal2-popup.swal2-toast .swal2-success.swal2-icon-show .swal2-success-line-long{animation:swal2-toast-animate-success-line-long .75s}.swal2-popup.swal2-toast.swal2-show{animation:swal2-toast-show .5s}.swal2-popup.swal2-toast.swal2-hide{animation:swal2-toast-hide .1s forwards}div:where(.swal2-container){display:grid;position:fixed;z-index:1060;inset:0;box-sizing:border-box;grid-template-areas:\"top-start top top-end\" \"center-start center center-end\" \"bottom-start bottom-center bottom-end\";grid-template-rows:minmax(min-content, auto) minmax(min-content, auto) minmax(min-content, auto);height:100%;padding:.625em;overflow-x:hidden;transition:background-color .1s;-webkit-overflow-scrolling:touch}div:where(.swal2-container).swal2-backdrop-show,div:where(.swal2-container).swal2-noanimation{background:rgba(0,0,0,.4)}div:where(.swal2-container).swal2-backdrop-hide{background:rgba(0,0,0,0) !important}div:where(.swal2-container).swal2-top-start,div:where(.swal2-container).swal2-center-start,div:where(.swal2-container).swal2-bottom-start{grid-template-columns:minmax(0, 1fr) auto auto}div:where(.swal2-container).swal2-top,div:where(.swal2-container).swal2-center,div:where(.swal2-container).swal2-bottom{grid-template-columns:auto minmax(0, 1fr) auto}div:where(.swal2-container).swal2-top-end,div:where(.swal2-container).swal2-center-end,div:where(.swal2-container).swal2-bottom-end{grid-template-columns:auto auto minmax(0, 1fr)}div:where(.swal2-container).swal2-top-start>.swal2-popup{align-self:start}div:where(.swal2-container).swal2-top>.swal2-popup{grid-column:2;place-self:start center}div:where(.swal2-container).swal2-top-end>.swal2-popup,div:where(.swal2-container).swal2-top-right>.swal2-popup{grid-column:3;place-self:start end}div:where(.swal2-container).swal2-center-start>.swal2-popup,div:where(.swal2-container).swal2-center-left>.swal2-popup{grid-row:2;align-self:center}div:where(.swal2-container).swal2-center>.swal2-popup{grid-column:2;grid-row:2;place-self:center center}div:where(.swal2-container).swal2-center-end>.swal2-popup,div:where(.swal2-container).swal2-center-right>.swal2-popup{grid-column:3;grid-row:2;place-self:center end}div:where(.swal2-container).swal2-bottom-start>.swal2-popup,div:where(.swal2-container).swal2-bottom-left>.swal2-popup{grid-column:1;grid-row:3;align-self:end}div:where(.swal2-container).swal2-bottom>.swal2-popup{grid-column:2;grid-row:3;place-self:end center}div:where(.swal2-container).swal2-bottom-end>.swal2-popup,div:where(.swal2-container).swal2-bottom-right>.swal2-popup{grid-column:3;grid-row:3;place-self:end end}div:where(.swal2-container).swal2-grow-row>.swal2-popup,div:where(.swal2-container).swal2-grow-fullscreen>.swal2-popup{grid-column:1/4;width:100%}div:where(.swal2-container).swal2-grow-column>.swal2-popup,div:where(.swal2-container).swal2-grow-fullscreen>.swal2-popup{grid-row:1/4;align-self:stretch}div:where(.swal2-container).swal2-no-transition{transition:none !important}div:where(.swal2-container) div:where(.swal2-popup){display:none;position:relative;box-sizing:border-box;grid-template-columns:minmax(0, 100%);width:32em;max-width:100%;padding:0 0 1.25em;border:none;border-radius:5px;background:#fff;color:#545454;font-family:inherit;font-size:1rem}div:where(.swal2-container) div:where(.swal2-popup):focus{outline:none}div:where(.swal2-container) div:where(.swal2-popup).swal2-loading{overflow-y:hidden}div:where(.swal2-container) h2:where(.swal2-title){position:relative;max-width:100%;margin:0;padding:.8em 1em 0;color:inherit;font-size:1.875em;font-weight:600;text-align:center;text-transform:none;word-wrap:break-word}div:where(.swal2-container) div:where(.swal2-actions){display:flex;z-index:1;box-sizing:border-box;flex-wrap:wrap;align-items:center;justify-content:center;width:auto;margin:1.25em auto 0;padding:0}div:where(.swal2-container) div:where(.swal2-actions):not(.swal2-loading) .swal2-styled[disabled]{opacity:.4}div:where(.swal2-container) div:where(.swal2-actions):not(.swal2-loading) .swal2-styled:hover{background-image:linear-gradient(rgba(0, 0, 0, 0.1), rgba(0, 0, 0, 0.1))}div:where(.swal2-container) div:where(.swal2-actions):not(.swal2-loading) .swal2-styled:active{background-image:linear-gradient(rgba(0, 0, 0, 0.2), rgba(0, 0, 0, 0.2))}div:where(.swal2-container) div:where(.swal2-loader){display:none;align-items:center;justify-content:center;width:2.2em;height:2.2em;margin:0 1.875em;animation:swal2-rotate-loading 1.5s linear 0s infinite normal;border-width:.25em;border-style:solid;border-radius:100%;border-color:#2778c4 rgba(0,0,0,0) #2778c4 rgba(0,0,0,0)}div:where(.swal2-container) button:where(.swal2-styled){margin:.3125em;padding:.625em 1.1em;transition:box-shadow .1s;box-shadow:0 0 0 3px rgba(0,0,0,0);font-weight:500}div:where(.swal2-container) button:where(.swal2-styled):not([disabled]){cursor:pointer}div:where(.swal2-container) button:where(.swal2-styled).swal2-confirm{border:0;border-radius:.25em;background:initial;background-color:#7066e0;color:#fff;font-size:1em}div:where(.swal2-container) button:where(.swal2-styled).swal2-confirm:focus{box-shadow:0 0 0 3px rgba(112,102,224,.5)}div:where(.swal2-container) button:where(.swal2-styled).swal2-deny{border:0;border-radius:.25em;background:initial;background-color:#dc3741;color:#fff;font-size:1em}div:where(.swal2-container) button:where(.swal2-styled).swal2-deny:focus{box-shadow:0 0 0 3px rgba(220,55,65,.5)}div:where(.swal2-container) button:where(.swal2-styled).swal2-cancel{border:0;border-radius:.25em;background:initial;background-color:#6e7881;color:#fff;font-size:1em}div:where(.swal2-container) button:where(.swal2-styled).swal2-cancel:focus{box-shadow:0 0 0 3px rgba(110,120,129,.5)}div:where(.swal2-container) button:where(.swal2-styled).swal2-default-outline:focus{box-shadow:0 0 0 3px rgba(100,150,200,.5)}div:where(.swal2-container) button:where(.swal2-styled):focus{outline:none}div:where(.swal2-container) button:where(.swal2-styled)::-moz-focus-inner{border:0}div:where(.swal2-container) div:where(.swal2-footer){margin:1em 0 0;padding:1em 1em 0;border-top:1px solid #eee;color:inherit;font-size:1em;text-align:center}div:where(.swal2-container) .swal2-timer-progress-bar-container{position:absolute;right:0;bottom:0;left:0;grid-column:auto !important;overflow:hidden;border-bottom-right-radius:5px;border-bottom-left-radius:5px}div:where(.swal2-container) div:where(.swal2-timer-progress-bar){width:100%;height:.25em;background:rgba(0,0,0,.2)}div:where(.swal2-container) img:where(.swal2-image){max-width:100%;margin:2em auto 1em}div:where(.swal2-container) button:where(.swal2-close){z-index:2;align-items:center;justify-content:center;width:1.2em;height:1.2em;margin-top:0;margin-right:0;margin-bottom:-1.2em;padding:0;overflow:hidden;transition:color .1s,box-shadow .1s;border:none;border-radius:5px;background:rgba(0,0,0,0);color:#ccc;font-family:monospace;font-size:2.5em;cursor:pointer;justify-self:end}div:where(.swal2-container) button:where(.swal2-close):hover{transform:none;background:rgba(0,0,0,0);color:#f27474}div:where(.swal2-container) button:where(.swal2-close):focus{outline:none;box-shadow:inset 0 0 0 3px rgba(100,150,200,.5)}div:where(.swal2-container) button:where(.swal2-close)::-moz-focus-inner{border:0}div:where(.swal2-container) .swal2-html-container{z-index:1;justify-content:center;margin:1em 1.6em .3em;padding:0;overflow:auto;color:inherit;font-size:1.125em;font-weight:normal;line-height:normal;text-align:center;word-wrap:break-word;word-break:break-word}div:where(.swal2-container) input:where(.swal2-input),div:where(.swal2-container) input:where(.swal2-file),div:where(.swal2-container) textarea:where(.swal2-textarea),div:where(.swal2-container) select:where(.swal2-select),div:where(.swal2-container) div:where(.swal2-radio),div:where(.swal2-container) label:where(.swal2-checkbox){margin:1em 2em 3px}div:where(.swal2-container) input:where(.swal2-input),div:where(.swal2-container) input:where(.swal2-file),div:where(.swal2-container) textarea:where(.swal2-textarea){box-sizing:border-box;width:auto;transition:border-color .1s,box-shadow .1s;border:1px solid #d9d9d9;border-radius:.1875em;background:rgba(0,0,0,0);box-shadow:inset 0 1px 1px rgba(0,0,0,.06),0 0 0 3px rgba(0,0,0,0);color:inherit;font-size:1.125em}div:where(.swal2-container) input:where(.swal2-input).swal2-inputerror,div:where(.swal2-container) input:where(.swal2-file).swal2-inputerror,div:where(.swal2-container) textarea:where(.swal2-textarea).swal2-inputerror{border-color:#f27474 !important;box-shadow:0 0 2px #f27474 !important}div:where(.swal2-container) input:where(.swal2-input):focus,div:where(.swal2-container) input:where(.swal2-file):focus,div:where(.swal2-container) textarea:where(.swal2-textarea):focus{border:1px solid #b4dbed;outline:none;box-shadow:inset 0 1px 1px rgba(0,0,0,.06),0 0 0 3px rgba(100,150,200,.5)}div:where(.swal2-container) input:where(.swal2-input)::placeholder,div:where(.swal2-container) input:where(.swal2-file)::placeholder,div:where(.swal2-container) textarea:where(.swal2-textarea)::placeholder{color:#ccc}div:where(.swal2-container) .swal2-range{margin:1em 2em 3px;background:#fff}div:where(.swal2-container) .swal2-range input{width:80%}div:where(.swal2-container) .swal2-range output{width:20%;color:inherit;font-weight:600;text-align:center}div:where(.swal2-container) .swal2-range input,div:where(.swal2-container) .swal2-range output{height:2.625em;padding:0;font-size:1.125em;line-height:2.625em}div:where(.swal2-container) .swal2-input{height:2.625em;padding:0 .75em}div:where(.swal2-container) .swal2-file{width:75%;margin-right:auto;margin-left:auto;background:rgba(0,0,0,0);font-size:1.125em}div:where(.swal2-container) .swal2-textarea{height:6.75em;padding:.75em}div:where(.swal2-container) .swal2-select{min-width:50%;max-width:100%;padding:.375em .625em;background:rgba(0,0,0,0);color:inherit;font-size:1.125em}div:where(.swal2-container) .swal2-radio,div:where(.swal2-container) .swal2-checkbox{align-items:center;justify-content:center;background:#fff;color:inherit}div:where(.swal2-container) .swal2-radio label,div:where(.swal2-container) .swal2-checkbox label{margin:0 .6em;font-size:1.125em}div:where(.swal2-container) .swal2-radio input,div:where(.swal2-container) .swal2-checkbox input{flex-shrink:0;margin:0 .4em}div:where(.swal2-container) label:where(.swal2-input-label){display:flex;justify-content:center;margin:1em auto 0}div:where(.swal2-container) div:where(.swal2-validation-message){align-items:center;justify-content:center;margin:1em 0 0;padding:.625em;overflow:hidden;background:#f0f0f0;color:#666;font-size:1em;font-weight:300}div:where(.swal2-container) div:where(.swal2-validation-message)::before{content:\"!\";display:inline-block;width:1.5em;min-width:1.5em;height:1.5em;margin:0 .625em;border-radius:50%;background-color:#f27474;color:#fff;font-weight:600;line-height:1.5em;text-align:center}div:where(.swal2-container) .swal2-progress-steps{flex-wrap:wrap;align-items:center;max-width:100%;margin:1.25em auto;padding:0;background:rgba(0,0,0,0);font-weight:600}div:where(.swal2-container) .swal2-progress-steps li{display:inline-block;position:relative}div:where(.swal2-container) .swal2-progress-steps .swal2-progress-step{z-index:20;flex-shrink:0;width:2em;height:2em;border-radius:2em;background:#2778c4;color:#fff;line-height:2em;text-align:center}div:where(.swal2-container) .swal2-progress-steps .swal2-progress-step.swal2-active-progress-step{background:#2778c4}div:where(.swal2-container) .swal2-progress-steps .swal2-progress-step.swal2-active-progress-step~.swal2-progress-step{background:#add8e6;color:#fff}div:where(.swal2-container) .swal2-progress-steps .swal2-progress-step.swal2-active-progress-step~.swal2-progress-step-line{background:#add8e6}div:where(.swal2-container) .swal2-progress-steps .swal2-progress-step-line{z-index:10;flex-shrink:0;width:2.5em;height:.4em;margin:0 -1px;background:#2778c4}div:where(.swal2-icon){position:relative;box-sizing:content-box;justify-content:center;width:5em;height:5em;margin:2.5em auto .6em;border:0.25em solid rgba(0,0,0,0);border-radius:50%;border-color:#000;font-family:inherit;line-height:5em;cursor:default;user-select:none}div:where(.swal2-icon) .swal2-icon-content{display:flex;align-items:center;font-size:3.75em}div:where(.swal2-icon).swal2-error{border-color:#f27474;color:#f27474}div:where(.swal2-icon).swal2-error .swal2-x-mark{position:relative;flex-grow:1}div:where(.swal2-icon).swal2-error [class^=swal2-x-mark-line]{display:block;position:absolute;top:2.3125em;width:2.9375em;height:.3125em;border-radius:.125em;background-color:#f27474}div:where(.swal2-icon).swal2-error [class^=swal2-x-mark-line][class$=left]{left:1.0625em;transform:rotate(45deg)}div:where(.swal2-icon).swal2-error [class^=swal2-x-mark-line][class$=right]{right:1em;transform:rotate(-45deg)}div:where(.swal2-icon).swal2-error.swal2-icon-show{animation:swal2-animate-error-icon .5s}div:where(.swal2-icon).swal2-error.swal2-icon-show .swal2-x-mark{animation:swal2-animate-error-x-mark .5s}div:where(.swal2-icon).swal2-warning{border-color:#facea8;color:#f8bb86}div:where(.swal2-icon).swal2-warning.swal2-icon-show{animation:swal2-animate-error-icon .5s}div:where(.swal2-icon).swal2-warning.swal2-icon-show .swal2-icon-content{animation:swal2-animate-i-mark .5s}div:where(.swal2-icon).swal2-info{border-color:#9de0f6;color:#3fc3ee}div:where(.swal2-icon).swal2-info.swal2-icon-show{animation:swal2-animate-error-icon .5s}div:where(.swal2-icon).swal2-info.swal2-icon-show .swal2-icon-content{animation:swal2-animate-i-mark .8s}div:where(.swal2-icon).swal2-question{border-color:#c9dae1;color:#87adbd}div:where(.swal2-icon).swal2-question.swal2-icon-show{animation:swal2-animate-error-icon .5s}div:where(.swal2-icon).swal2-question.swal2-icon-show .swal2-icon-content{animation:swal2-animate-question-mark .8s}div:where(.swal2-icon).swal2-success{border-color:#a5dc86;color:#a5dc86}div:where(.swal2-icon).swal2-success [class^=swal2-success-circular-line]{position:absolute;width:3.75em;height:7.5em;border-radius:50%}div:where(.swal2-icon).swal2-success [class^=swal2-success-circular-line][class$=left]{top:-0.4375em;left:-2.0635em;transform:rotate(-45deg);transform-origin:3.75em 3.75em;border-radius:7.5em 0 0 7.5em}div:where(.swal2-icon).swal2-success [class^=swal2-success-circular-line][class$=right]{top:-0.6875em;left:1.875em;transform:rotate(-45deg);transform-origin:0 3.75em;border-radius:0 7.5em 7.5em 0}div:where(.swal2-icon).swal2-success .swal2-success-ring{position:absolute;z-index:2;top:-0.25em;left:-0.25em;box-sizing:content-box;width:100%;height:100%;border:.25em solid rgba(165,220,134,.3);border-radius:50%}div:where(.swal2-icon).swal2-success .swal2-success-fix{position:absolute;z-index:1;top:.5em;left:1.625em;width:.4375em;height:5.625em;transform:rotate(-45deg)}div:where(.swal2-icon).swal2-success [class^=swal2-success-line]{display:block;position:absolute;z-index:2;height:.3125em;border-radius:.125em;background-color:#a5dc86}div:where(.swal2-icon).swal2-success [class^=swal2-success-line][class$=tip]{top:2.875em;left:.8125em;width:1.5625em;transform:rotate(45deg)}div:where(.swal2-icon).swal2-success [class^=swal2-success-line][class$=long]{top:2.375em;right:.5em;width:2.9375em;transform:rotate(-45deg)}div:where(.swal2-icon).swal2-success.swal2-icon-show .swal2-success-line-tip{animation:swal2-animate-success-line-tip .75s}div:where(.swal2-icon).swal2-success.swal2-icon-show .swal2-success-line-long{animation:swal2-animate-success-line-long .75s}div:where(.swal2-icon).swal2-success.swal2-icon-show .swal2-success-circular-line-right{animation:swal2-rotate-success-circular-line 4.25s ease-in}[class^=swal2]{-webkit-tap-highlight-color:rgba(0,0,0,0)}.swal2-show{animation:swal2-show .3s}.swal2-hide{animation:swal2-hide .15s forwards}.swal2-noanimation{transition:none}.swal2-scrollbar-measure{position:absolute;top:-9999px;width:50px;height:50px;overflow:scroll}.swal2-rtl .swal2-close{margin-right:initial;margin-left:0}.swal2-rtl .swal2-timer-progress-bar{right:0;left:auto}@keyframes swal2-toast-show{0%{transform:translateY(-0.625em) rotateZ(2deg)}33%{transform:translateY(0) rotateZ(-2deg)}66%{transform:translateY(0.3125em) rotateZ(2deg)}100%{transform:translateY(0) rotateZ(0deg)}}@keyframes swal2-toast-hide{100%{transform:rotateZ(1deg);opacity:0}}@keyframes swal2-toast-animate-success-line-tip{0%{top:.5625em;left:.0625em;width:0}54%{top:.125em;left:.125em;width:0}70%{top:.625em;left:-0.25em;width:1.625em}84%{top:1.0625em;left:.75em;width:.5em}100%{top:1.125em;left:.1875em;width:.75em}}@keyframes swal2-toast-animate-success-line-long{0%{top:1.625em;right:1.375em;width:0}65%{top:1.25em;right:.9375em;width:0}84%{top:.9375em;right:0;width:1.125em}100%{top:.9375em;right:.1875em;width:1.375em}}@keyframes swal2-show{0%{transform:scale(0.7)}45%{transform:scale(1.05)}80%{transform:scale(0.95)}100%{transform:scale(1)}}@keyframes swal2-hide{0%{transform:scale(1);opacity:1}100%{transform:scale(0.5);opacity:0}}@keyframes swal2-animate-success-line-tip{0%{top:1.1875em;left:.0625em;width:0}54%{top:1.0625em;left:.125em;width:0}70%{top:2.1875em;left:-0.375em;width:3.125em}84%{top:3em;left:1.3125em;width:1.0625em}100%{top:2.8125em;left:.8125em;width:1.5625em}}@keyframes swal2-animate-success-line-long{0%{top:3.375em;right:2.875em;width:0}65%{top:3.375em;right:2.875em;width:0}84%{top:2.1875em;right:0;width:3.4375em}100%{top:2.375em;right:.5em;width:2.9375em}}@keyframes swal2-rotate-success-circular-line{0%{transform:rotate(-45deg)}5%{transform:rotate(-45deg)}12%{transform:rotate(-405deg)}100%{transform:rotate(-405deg)}}@keyframes swal2-animate-error-x-mark{0%{margin-top:1.625em;transform:scale(0.4);opacity:0}50%{margin-top:1.625em;transform:scale(0.4);opacity:0}80%{margin-top:-0.375em;transform:scale(1.15)}100%{margin-top:0;transform:scale(1);opacity:1}}@keyframes swal2-animate-error-icon{0%{transform:rotateX(100deg);opacity:0}100%{transform:rotateX(0deg);opacity:1}}@keyframes swal2-rotate-loading{0%{transform:rotate(0deg)}100%{transform:rotate(360deg)}}@keyframes swal2-animate-question-mark{0%{transform:rotateY(-360deg)}100%{transform:rotateY(0)}}@keyframes swal2-animate-i-mark{0%{transform:rotateZ(45deg);opacity:0}25%{transform:rotateZ(-25deg);opacity:.4}50%{transform:rotateZ(15deg);opacity:.8}75%{transform:rotateZ(-5deg);opacity:1}100%{transform:rotateX(0);opacity:1}}body.swal2-shown:not(.swal2-no-backdrop):not(.swal2-toast-shown){overflow:hidden}body.swal2-height-auto{height:auto !important}body.swal2-no-backdrop .swal2-container{background-color:rgba(0,0,0,0) !important;pointer-events:none}body.swal2-no-backdrop .swal2-container .swal2-popup{pointer-events:all}body.swal2-no-backdrop .swal2-container .swal2-modal{box-shadow:0 0 10px rgba(0,0,0,.4)}@media print{body.swal2-shown:not(.swal2-no-backdrop):not(.swal2-toast-shown){overflow-y:scroll !important}body.swal2-shown:not(.swal2-no-backdrop):not(.swal2-toast-shown)>[aria-hidden=true]{display:none}body.swal2-shown:not(.swal2-no-backdrop):not(.swal2-toast-shown) .swal2-container{position:static !important}}body.swal2-toast-shown .swal2-container{box-sizing:border-box;width:360px;max-width:100%;background-color:rgba(0,0,0,0);pointer-events:none}body.swal2-toast-shown .swal2-container.swal2-top{inset:0 auto auto 50%;transform:translateX(-50%)}body.swal2-toast-shown .swal2-container.swal2-top-end,body.swal2-toast-shown .swal2-container.swal2-top-right{inset:0 0 auto auto}body.swal2-toast-shown .swal2-container.swal2-top-start,body.swal2-toast-shown .swal2-container.swal2-top-left{inset:0 auto auto 0}body.swal2-toast-shown .swal2-container.swal2-center-start,body.swal2-toast-shown .swal2-container.swal2-center-left{inset:50% auto auto 0;transform:translateY(-50%)}body.swal2-toast-shown .swal2-container.swal2-center{inset:50% auto auto 50%;transform:translate(-50%, -50%)}body.swal2-toast-shown .swal2-container.swal2-center-end,body.swal2-toast-shown .swal2-container.swal2-center-right{inset:50% 0 auto auto;transform:translateY(-50%)}body.swal2-toast-shown .swal2-container.swal2-bottom-start,body.swal2-toast-shown .swal2-container.swal2-bottom-left{inset:auto auto 0 0}body.swal2-toast-shown .swal2-container.swal2-bottom{inset:auto auto 0 50%;transform:translateX(-50%)}body.swal2-toast-shown .swal2-container.swal2-bottom-end,body.swal2-toast-shown .swal2-container.swal2-bottom-right{inset:auto 0 0 auto}"); \ No newline at end of file diff --git a/assets/stylesheets/admin/style.css b/assets/stylesheets/admin/style.css index f3e2bd60..b92f9f37 100644 --- a/assets/stylesheets/admin/style.css +++ b/assets/stylesheets/admin/style.css @@ -50,18 +50,10 @@ color: #e02b27; } -.woocommerce_page_woo-pagarme-payments .swal2-modal { - line-height: normal; -} - .woocommerce_page_woo-pagarme-payments .swal2-modal .swal2-title { margin-bottom: 0.6em; } -.woocommerce_page_woo-pagarme-payments .swal2-modal .swal2-content { - line-height: 1.3em; -} - #woo-pagarme-additional-information table.woocommerce-table { max-width: 100%; } diff --git a/assets/stylesheets/front/style.css b/assets/stylesheets/front/style.css index 59d6a016..9ba38f95 100644 --- a/assets/stylesheets/front/style.css +++ b/assets/stylesheets/front/style.css @@ -1,5 +1,5 @@ .pagarme-hidden { - display: none!important; + display: none !important; } #wcmp-checkout-errors { @@ -38,14 +38,21 @@ z-index: unset; } -#payment ul.payment_methods li[class*="pagarme"] p img.logo, -.wc-block-checkout__payment-method .wc-block-components-radio-control .wc-block-components-radio-control-accordion-content p img.logo, -.wc-block-checkout__payment-method .wc-block-components-radio-control .wc-block-components-radio-control-accordion-content p.pagarme-payment-method-instructions { +#payment ul.payment_methods li[class*="pagarme"] p img.logo { margin: 0; } +.wc-block-checkout__payment-method .wc-block-components-radio-control .wc-block-components-radio-control-accordion-content p.pagarme-payment-method-instructions { + margin-bottom: .75em; +} + +.wc-block-checkout__payment-method .wc-block-components-radio-control .wc-block-components-radio-control-accordion-content p.pagarme-payment-method-logo { + display: flex; + justify-content: right; + margin-bottom: .5em; +} + .wc-block-checkout__payment-method .wc-block-components-radio-control .wc-block-components-radio-control-accordion-content p img.logo { - float: right; border: 0; padding: 0; } @@ -130,11 +137,11 @@ display: flex; flex-direction: column; height: 100%; - border: 1px solid rgba(255,255,255,.15); + border: 1px solid rgba(255, 255, 255, .15); border-radius: 4px; padding: calc(var(--gutter-x) * .5); - background-color: rgba(0,0,0,.15); - box-shadow: 0 0 3rem inset rgba(0,0,0,.15); + background-color: rgba(0, 0, 0, .15); + box-shadow: 0 0 3rem inset rgba(0, 0, 0, .15); } .woocommerce-order .woocommerce-message .pagarme-response .pagarme-qr-code-instruction > p > span { @@ -150,6 +157,55 @@ min-width: 2rem; } +.pagarme-installments-combobox .wc-block-components-combobox .wc-block-components-combobox-control .components-flex { + height: initial; + padding-left: 0; + padding-right: 0; +} + +.pagarme-credit-card-number-container input { + padding-right: 4.2em !important; +} + +.pagarme-credit-card-number-container img { + position: absolute; + top: 50%; + right: .5em; + margin-top: -1em; + background-color: #fff; + pointer-events: none; + touch-action: none; +} + +.challengeIframeElement { + display: none; + position: fixed; + z-index: 99999; + padding-top: 100px; + left: 0; + top: 0; + width: 100%; + height: 100%; + overflow: auto; + background-color: rgb(0, 0, 0); + background-color: rgba(0, 0, 0, 0.4); +} + +.challengeIframeElement .modal-content { + background-color: #fefefe; + margin: auto; + padding: 20px; + border: 1px solid #888; + max-width: fit-content; +} + +#challengeIframe { + display: none; + width: 500px; + height: 600px; + border: 0; +} + /* sm */ /* @media (min-width: 576px) { diff --git a/assets/stylesheets/vendor/sweetalert2.min.css b/assets/stylesheets/vendor/sweetalert2.min.css index 9c582b48..7d533ed3 100644 --- a/assets/stylesheets/vendor/sweetalert2.min.css +++ b/assets/stylesheets/vendor/sweetalert2.min.css @@ -1 +1 @@ -body.swal2-shown{overflow-y:hidden}body.swal2-iosfix{position:fixed;left:0;right:0}.swal2-container{display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-orient:horizontal;-webkit-box-direction:normal;-ms-flex-direction:row;flex-direction:row;-webkit-box-align:center;-ms-flex-align:center;align-items:center;-webkit-box-pack:center;-ms-flex-pack:center;justify-content:center;position:fixed;top:0;left:0;bottom:0;right:0;padding:10px;background-color:transparent;z-index:1060}.swal2-container.swal2-top{-webkit-box-align:start;-ms-flex-align:start;align-items:flex-start}.swal2-container.swal2-top-left{-webkit-box-align:start;-ms-flex-align:start;align-items:flex-start;-webkit-box-pack:start;-ms-flex-pack:start;justify-content:flex-start}.swal2-container.swal2-top-right{-webkit-box-align:start;-ms-flex-align:start;align-items:flex-start;-webkit-box-pack:end;-ms-flex-pack:end;justify-content:flex-end}.swal2-container.swal2-center{-webkit-box-align:center;-ms-flex-align:center;align-items:center}.swal2-container.swal2-center-left{-webkit-box-align:center;-ms-flex-align:center;align-items:center;-webkit-box-pack:start;-ms-flex-pack:start;justify-content:flex-start}.swal2-container.swal2-center-right{-webkit-box-align:center;-ms-flex-align:center;align-items:center;-webkit-box-pack:end;-ms-flex-pack:end;justify-content:flex-end}.swal2-container.swal2-bottom{-webkit-box-align:end;-ms-flex-align:end;align-items:flex-end}.swal2-container.swal2-bottom-left{-webkit-box-align:end;-ms-flex-align:end;align-items:flex-end;-webkit-box-pack:start;-ms-flex-pack:start;justify-content:flex-start}.swal2-container.swal2-bottom-right{-webkit-box-align:end;-ms-flex-align:end;align-items:flex-end;-webkit-box-pack:end;-ms-flex-pack:end;justify-content:flex-end}.swal2-container.swal2-grow-fullscreen>.swal2-modal{display:-webkit-box!important;display:-ms-flexbox!important;display:flex!important;-webkit-box-flex:1;-ms-flex:1;flex:1;-ms-flex-item-align:stretch;align-self:stretch;-webkit-box-pack:center;-ms-flex-pack:center;justify-content:center}.swal2-container.swal2-grow-row>.swal2-modal{display:-webkit-box!important;display:-ms-flexbox!important;display:flex!important;-webkit-box-flex:1;-ms-flex:1;flex:1;-ms-flex-line-pack:center;align-content:center;-webkit-box-pack:center;-ms-flex-pack:center;justify-content:center}.swal2-container.swal2-grow-column{-webkit-box-flex:1;-ms-flex:1;flex:1;-webkit-box-orient:vertical;-webkit-box-direction:normal;-ms-flex-direction:column;flex-direction:column}.swal2-container.swal2-grow-column.swal2-bottom,.swal2-container.swal2-grow-column.swal2-center,.swal2-container.swal2-grow-column.swal2-top{-webkit-box-align:center;-ms-flex-align:center;align-items:center}.swal2-container.swal2-grow-column.swal2-bottom-left,.swal2-container.swal2-grow-column.swal2-center-left,.swal2-container.swal2-grow-column.swal2-top-left{-webkit-box-align:start;-ms-flex-align:start;align-items:flex-start}.swal2-container.swal2-grow-column.swal2-bottom-right,.swal2-container.swal2-grow-column.swal2-center-right,.swal2-container.swal2-grow-column.swal2-top-right{-webkit-box-align:end;-ms-flex-align:end;align-items:flex-end}.swal2-container.swal2-grow-column>.swal2-modal{display:-webkit-box!important;display:-ms-flexbox!important;display:flex!important;-webkit-box-flex:1;-ms-flex:1;flex:1;-ms-flex-line-pack:center;align-content:center;-webkit-box-pack:center;-ms-flex-pack:center;justify-content:center}.swal2-container:not(.swal2-top):not(.swal2-top-left):not(.swal2-top-right):not(.swal2-center-left):not(.swal2-center-right):not(.swal2-bottom):not(.swal2-bottom-left):not(.swal2-bottom-right)>.swal2-modal{margin:auto}@media all and (-ms-high-contrast:none),(-ms-high-contrast:active){.swal2-container .swal2-modal{margin:0!important}}.swal2-container.swal2-fade{-webkit-transition:background-color .1s;transition:background-color .1s}.swal2-container.swal2-shown{background-color:rgba(0,0,0,.4)}.swal2-modal{-webkit-box-orient:vertical;-webkit-box-direction:normal;-ms-flex-direction:column;flex-direction:column;background-color:#fff;font-family:'Helvetica Neue',Helvetica,Arial,sans-serif;border-radius:5px;-webkit-box-sizing:border-box;box-sizing:border-box;text-align:center;overflow-x:hidden;overflow-y:auto;display:none;position:relative;max-width:100%}.swal2-modal:focus{outline:0}.swal2-modal.swal2-loading{overflow-y:hidden}.swal2-modal .swal2-title{color:#595959;font-size:30px;text-align:center;font-weight:600;text-transform:none;position:relative;margin:0 0 .4em;padding:0;display:block;word-wrap:break-word}.swal2-modal .swal2-buttonswrapper{margin-top:15px}.swal2-modal .swal2-buttonswrapper:not(.swal2-loading) .swal2-styled[disabled]{opacity:.4;cursor:no-drop}.swal2-modal .swal2-buttonswrapper.swal2-loading .swal2-styled.swal2-confirm{-webkit-box-sizing:border-box;box-sizing:border-box;border:4px solid transparent;border-color:transparent;width:40px;height:40px;padding:0;margin:7.5px;vertical-align:top;background-color:transparent!important;color:transparent;cursor:default;border-radius:100%;-webkit-animation:rotate-loading 1.5s linear 0s infinite normal;animation:rotate-loading 1.5s linear 0s infinite normal;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}.swal2-modal .swal2-buttonswrapper.swal2-loading .swal2-styled.swal2-cancel{margin-left:30px;margin-right:30px}.swal2-modal .swal2-buttonswrapper.swal2-loading :not(.swal2-styled).swal2-confirm::after{display:inline-block;content:'';margin-left:5px;vertical-align:-1px;height:15px;width:15px;border:3px solid #999;-webkit-box-shadow:1px 1px 1px #fff;box-shadow:1px 1px 1px #fff;border-right-color:transparent;border-radius:50%;-webkit-animation:rotate-loading 1.5s linear 0s infinite normal;animation:rotate-loading 1.5s linear 0s infinite normal}.swal2-modal .swal2-styled{border:0;border-radius:3px;-webkit-box-shadow:none;box-shadow:none;color:#fff;cursor:pointer;font-size:17px;font-weight:500;margin:15px 5px 0;padding:10px 32px}.swal2-modal .swal2-styled:focus{outline:0;-webkit-box-shadow:0 0 0 2px #fff,0 0 0 4px rgba(50,100,150,.4);box-shadow:0 0 0 2px #fff,0 0 0 4px rgba(50,100,150,.4)}.swal2-modal .swal2-image{margin:20px auto;max-width:100%}.swal2-modal .swal2-close{background:0 0;border:0;margin:0;padding:0;width:38px;height:40px;font-size:36px;line-height:40px;font-family:serif;position:absolute;top:5px;right:8px;cursor:pointer;color:#ccc;-webkit-transition:color .1s ease;transition:color .1s ease}.swal2-modal .swal2-close:hover{color:#d55}.swal2-modal>.swal2-checkbox,.swal2-modal>.swal2-file,.swal2-modal>.swal2-input,.swal2-modal>.swal2-radio,.swal2-modal>.swal2-select,.swal2-modal>.swal2-textarea{display:none}.swal2-modal .swal2-content{font-size:18px;text-align:center;font-weight:300;position:relative;float:none;margin:0;padding:0;line-height:normal;color:#545454;word-wrap:break-word}.swal2-modal .swal2-checkbox,.swal2-modal .swal2-file,.swal2-modal .swal2-input,.swal2-modal .swal2-radio,.swal2-modal .swal2-select,.swal2-modal .swal2-textarea{margin:20px auto}.swal2-modal .swal2-file,.swal2-modal .swal2-input,.swal2-modal .swal2-textarea{width:100%;-webkit-box-sizing:border-box;box-sizing:border-box;font-size:18px;border-radius:3px;border:1px solid #d9d9d9;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.06);box-shadow:inset 0 1px 1px rgba(0,0,0,.06);-webkit-transition:border-color .3s,-webkit-box-shadow .3s;transition:border-color .3s,-webkit-box-shadow .3s;transition:border-color .3s,box-shadow .3s;transition:border-color .3s,box-shadow .3s,-webkit-box-shadow .3s}.swal2-modal .swal2-file.swal2-inputerror,.swal2-modal .swal2-input.swal2-inputerror,.swal2-modal .swal2-textarea.swal2-inputerror{border-color:#f27474!important;-webkit-box-shadow:0 0 2px #f27474!important;box-shadow:0 0 2px #f27474!important}.swal2-modal .swal2-file:focus,.swal2-modal .swal2-input:focus,.swal2-modal .swal2-textarea:focus{outline:0;border:1px solid #b4dbed;-webkit-box-shadow:0 0 3px #c4e6f5;box-shadow:0 0 3px #c4e6f5}.swal2-modal .swal2-file::-webkit-input-placeholder,.swal2-modal .swal2-input::-webkit-input-placeholder,.swal2-modal .swal2-textarea::-webkit-input-placeholder{color:#ccc}.swal2-modal .swal2-file:-ms-input-placeholder,.swal2-modal .swal2-input:-ms-input-placeholder,.swal2-modal .swal2-textarea:-ms-input-placeholder{color:#ccc}.swal2-modal .swal2-file::-ms-input-placeholder,.swal2-modal .swal2-input::-ms-input-placeholder,.swal2-modal .swal2-textarea::-ms-input-placeholder{color:#ccc}.swal2-modal .swal2-file::placeholder,.swal2-modal .swal2-input::placeholder,.swal2-modal .swal2-textarea::placeholder{color:#ccc}.swal2-modal .swal2-range input{float:left;width:80%}.swal2-modal .swal2-range output{float:right;width:20%;font-size:20px;font-weight:600;text-align:center}.swal2-modal .swal2-range input,.swal2-modal .swal2-range output{height:43px;line-height:43px;vertical-align:middle;margin:20px auto;padding:0}.swal2-modal .swal2-input{height:43px;padding:0 12px}.swal2-modal .swal2-input[type=number]{max-width:150px}.swal2-modal .swal2-file{font-size:20px}.swal2-modal .swal2-textarea{height:108px;padding:12px}.swal2-modal .swal2-select{color:#545454;font-size:inherit;padding:5px 10px;min-width:40%;max-width:100%}.swal2-modal .swal2-radio{border:0}.swal2-modal .swal2-radio label:not(:first-child){margin-left:20px}.swal2-modal .swal2-radio input,.swal2-modal .swal2-radio span{vertical-align:middle}.swal2-modal .swal2-radio input{margin:0 3px 0 0}.swal2-modal .swal2-checkbox{color:#545454}.swal2-modal .swal2-checkbox input,.swal2-modal .swal2-checkbox span{vertical-align:middle}.swal2-modal .swal2-validationerror{background-color:#f0f0f0;margin:0 -20px;overflow:hidden;padding:10px;color:gray;font-size:16px;font-weight:300;display:none}.swal2-modal .swal2-validationerror::before{content:'!';display:inline-block;width:24px;height:24px;border-radius:50%;background-color:#ea7d7d;color:#fff;line-height:24px;text-align:center;margin-right:10px}@supports (-ms-accelerator:true){.swal2-range input{width:100%!important}.swal2-range output{display:none}}@media all and (-ms-high-contrast:none),(-ms-high-contrast:active){.swal2-range input{width:100%!important}.swal2-range output{display:none}}.swal2-icon{width:80px;height:80px;border:4px solid transparent;border-radius:50%;margin:20px auto 30px;padding:0;position:relative;-webkit-box-sizing:content-box;box-sizing:content-box;cursor:default;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}.swal2-icon.swal2-error{border-color:#f27474}.swal2-icon.swal2-error .swal2-x-mark{position:relative;display:block}.swal2-icon.swal2-error [class^=swal2-x-mark-line]{position:absolute;height:5px;width:47px;background-color:#f27474;display:block;top:37px;border-radius:2px}.swal2-icon.swal2-error [class^=swal2-x-mark-line][class$=left]{-webkit-transform:rotate(45deg);transform:rotate(45deg);left:17px}.swal2-icon.swal2-error [class^=swal2-x-mark-line][class$=right]{-webkit-transform:rotate(-45deg);transform:rotate(-45deg);right:16px}.swal2-icon.swal2-warning{font-family:'Helvetica Neue',Helvetica,Arial,sans-serif;color:#f8bb86;border-color:#facea8;font-size:60px;line-height:80px;text-align:center}.swal2-icon.swal2-info{font-family:'Open Sans',sans-serif;color:#3fc3ee;border-color:#9de0f6;font-size:60px;line-height:80px;text-align:center}.swal2-icon.swal2-question{font-family:'Helvetica Neue',Helvetica,Arial,sans-serif;color:#87adbd;border-color:#c9dae1;font-size:60px;line-height:80px;text-align:center}.swal2-icon.swal2-success{border-color:#a5dc86}.swal2-icon.swal2-success [class^=swal2-success-circular-line]{border-radius:50%;position:absolute;width:60px;height:120px;-webkit-transform:rotate(45deg);transform:rotate(45deg)}.swal2-icon.swal2-success [class^=swal2-success-circular-line][class$=left]{border-radius:120px 0 0 120px;top:-7px;left:-33px;-webkit-transform:rotate(-45deg);transform:rotate(-45deg);-webkit-transform-origin:60px 60px;transform-origin:60px 60px}.swal2-icon.swal2-success [class^=swal2-success-circular-line][class$=right]{border-radius:0 120px 120px 0;top:-11px;left:30px;-webkit-transform:rotate(-45deg);transform:rotate(-45deg);-webkit-transform-origin:0 60px;transform-origin:0 60px}.swal2-icon.swal2-success .swal2-success-ring{width:80px;height:80px;border:4px solid rgba(165,220,134,.2);border-radius:50%;-webkit-box-sizing:content-box;box-sizing:content-box;position:absolute;left:-4px;top:-4px;z-index:2}.swal2-icon.swal2-success .swal2-success-fix{width:7px;height:90px;position:absolute;left:28px;top:8px;z-index:1;-webkit-transform:rotate(-45deg);transform:rotate(-45deg)}.swal2-icon.swal2-success [class^=swal2-success-line]{height:5px;background-color:#a5dc86;display:block;border-radius:2px;position:absolute;z-index:2}.swal2-icon.swal2-success [class^=swal2-success-line][class$=tip]{width:25px;left:14px;top:46px;-webkit-transform:rotate(45deg);transform:rotate(45deg)}.swal2-icon.swal2-success [class^=swal2-success-line][class$=long]{width:47px;right:8px;top:38px;-webkit-transform:rotate(-45deg);transform:rotate(-45deg)}.swal2-progresssteps{font-weight:600;margin:0 0 20px;padding:0}.swal2-progresssteps li{display:inline-block;position:relative}.swal2-progresssteps .swal2-progresscircle{background:#3085d6;border-radius:2em;color:#fff;height:2em;line-height:2em;text-align:center;width:2em;z-index:20}.swal2-progresssteps .swal2-progresscircle:first-child{margin-left:0}.swal2-progresssteps .swal2-progresscircle:last-child{margin-right:0}.swal2-progresssteps .swal2-progresscircle.swal2-activeprogressstep{background:#3085d6}.swal2-progresssteps .swal2-progresscircle.swal2-activeprogressstep~.swal2-progresscircle{background:#add8e6}.swal2-progresssteps .swal2-progresscircle.swal2-activeprogressstep~.swal2-progressline{background:#add8e6}.swal2-progresssteps .swal2-progressline{background:#3085d6;height:.4em;margin:0 -1px;z-index:10}[class^=swal2]{-webkit-tap-highlight-color:transparent}@-webkit-keyframes showSweetAlert{0%{-webkit-transform:scale(.7);transform:scale(.7)}45%{-webkit-transform:scale(1.05);transform:scale(1.05)}80%{-webkit-transform:scale(.95);transform:scale(.95)}100%{-webkit-transform:scale(1);transform:scale(1)}}@keyframes showSweetAlert{0%{-webkit-transform:scale(.7);transform:scale(.7)}45%{-webkit-transform:scale(1.05);transform:scale(1.05)}80%{-webkit-transform:scale(.95);transform:scale(.95)}100%{-webkit-transform:scale(1);transform:scale(1)}}@-webkit-keyframes hideSweetAlert{0%{-webkit-transform:scale(1);transform:scale(1);opacity:1}100%{-webkit-transform:scale(.5);transform:scale(.5);opacity:0}}@keyframes hideSweetAlert{0%{-webkit-transform:scale(1);transform:scale(1);opacity:1}100%{-webkit-transform:scale(.5);transform:scale(.5);opacity:0}}.swal2-show{-webkit-animation:showSweetAlert .3s;animation:showSweetAlert .3s}.swal2-show.swal2-noanimation{-webkit-animation:none;animation:none}.swal2-hide{-webkit-animation:hideSweetAlert .15s forwards;animation:hideSweetAlert .15s forwards}.swal2-hide.swal2-noanimation{-webkit-animation:none;animation:none}@-webkit-keyframes animate-success-tip{0%{width:0;left:1px;top:19px}54%{width:0;left:1px;top:19px}70%{width:50px;left:-8px;top:37px}84%{width:17px;left:21px;top:48px}100%{width:25px;left:14px;top:45px}}@keyframes animate-success-tip{0%{width:0;left:1px;top:19px}54%{width:0;left:1px;top:19px}70%{width:50px;left:-8px;top:37px}84%{width:17px;left:21px;top:48px}100%{width:25px;left:14px;top:45px}}@-webkit-keyframes animate-success-long{0%{width:0;right:46px;top:54px}65%{width:0;right:46px;top:54px}84%{width:55px;right:0;top:35px}100%{width:47px;right:8px;top:38px}}@keyframes animate-success-long{0%{width:0;right:46px;top:54px}65%{width:0;right:46px;top:54px}84%{width:55px;right:0;top:35px}100%{width:47px;right:8px;top:38px}}@-webkit-keyframes rotatePlaceholder{0%{-webkit-transform:rotate(-45deg);transform:rotate(-45deg)}5%{-webkit-transform:rotate(-45deg);transform:rotate(-45deg)}12%{-webkit-transform:rotate(-405deg);transform:rotate(-405deg)}100%{-webkit-transform:rotate(-405deg);transform:rotate(-405deg)}}@keyframes rotatePlaceholder{0%{-webkit-transform:rotate(-45deg);transform:rotate(-45deg)}5%{-webkit-transform:rotate(-45deg);transform:rotate(-45deg)}12%{-webkit-transform:rotate(-405deg);transform:rotate(-405deg)}100%{-webkit-transform:rotate(-405deg);transform:rotate(-405deg)}}.swal2-animate-success-line-tip{-webkit-animation:animate-success-tip .75s;animation:animate-success-tip .75s}.swal2-animate-success-line-long{-webkit-animation:animate-success-long .75s;animation:animate-success-long .75s}.swal2-success.swal2-animate-success-icon .swal2-success-circular-line-right{-webkit-animation:rotatePlaceholder 4.25s ease-in;animation:rotatePlaceholder 4.25s ease-in}@-webkit-keyframes animate-error-icon{0%{-webkit-transform:rotateX(100deg);transform:rotateX(100deg);opacity:0}100%{-webkit-transform:rotateX(0);transform:rotateX(0);opacity:1}}@keyframes animate-error-icon{0%{-webkit-transform:rotateX(100deg);transform:rotateX(100deg);opacity:0}100%{-webkit-transform:rotateX(0);transform:rotateX(0);opacity:1}}.swal2-animate-error-icon{-webkit-animation:animate-error-icon .5s;animation:animate-error-icon .5s}@-webkit-keyframes animate-x-mark{0%{-webkit-transform:scale(.4);transform:scale(.4);margin-top:26px;opacity:0}50%{-webkit-transform:scale(.4);transform:scale(.4);margin-top:26px;opacity:0}80%{-webkit-transform:scale(1.15);transform:scale(1.15);margin-top:-6px}100%{-webkit-transform:scale(1);transform:scale(1);margin-top:0;opacity:1}}@keyframes animate-x-mark{0%{-webkit-transform:scale(.4);transform:scale(.4);margin-top:26px;opacity:0}50%{-webkit-transform:scale(.4);transform:scale(.4);margin-top:26px;opacity:0}80%{-webkit-transform:scale(1.15);transform:scale(1.15);margin-top:-6px}100%{-webkit-transform:scale(1);transform:scale(1);margin-top:0;opacity:1}}.swal2-animate-x-mark{-webkit-animation:animate-x-mark .5s;animation:animate-x-mark .5s}@-webkit-keyframes rotate-loading{0%{-webkit-transform:rotate(0);transform:rotate(0)}100%{-webkit-transform:rotate(360deg);transform:rotate(360deg)}}@keyframes rotate-loading{0%{-webkit-transform:rotate(0);transform:rotate(0)}100%{-webkit-transform:rotate(360deg);transform:rotate(360deg)}} \ No newline at end of file +.swal2-popup.swal2-toast{box-sizing:border-box;grid-column:1/4 !important;grid-row:1/4 !important;grid-template-columns:min-content auto min-content;padding:1em;overflow-y:hidden;background:#fff;box-shadow:0 0 1px rgba(0,0,0,.075),0 1px 2px rgba(0,0,0,.075),1px 2px 4px rgba(0,0,0,.075),1px 3px 8px rgba(0,0,0,.075),2px 4px 16px rgba(0,0,0,.075);pointer-events:all}.swal2-popup.swal2-toast>*{grid-column:2}.swal2-popup.swal2-toast .swal2-title{margin:.5em 1em;padding:0;font-size:1em;text-align:initial}.swal2-popup.swal2-toast .swal2-loading{justify-content:center}.swal2-popup.swal2-toast .swal2-input{height:2em;margin:.5em;font-size:1em}.swal2-popup.swal2-toast .swal2-validation-message{font-size:1em}.swal2-popup.swal2-toast .swal2-footer{margin:.5em 0 0;padding:.5em 0 0;font-size:.8em}.swal2-popup.swal2-toast .swal2-close{grid-column:3/3;grid-row:1/99;align-self:center;width:.8em;height:.8em;margin:0;font-size:2em}.swal2-popup.swal2-toast .swal2-html-container{margin:.5em 1em;padding:0;overflow:initial;font-size:1em;text-align:initial}.swal2-popup.swal2-toast .swal2-html-container:empty{padding:0}.swal2-popup.swal2-toast .swal2-loader{grid-column:1;grid-row:1/99;align-self:center;width:2em;height:2em;margin:.25em}.swal2-popup.swal2-toast .swal2-icon{grid-column:1;grid-row:1/99;align-self:center;width:2em;min-width:2em;height:2em;margin:0 .5em 0 0}.swal2-popup.swal2-toast .swal2-icon .swal2-icon-content{display:flex;align-items:center;font-size:1.8em;font-weight:bold}.swal2-popup.swal2-toast .swal2-icon.swal2-success .swal2-success-ring{width:2em;height:2em}.swal2-popup.swal2-toast .swal2-icon.swal2-error [class^=swal2-x-mark-line]{top:.875em;width:1.375em}.swal2-popup.swal2-toast .swal2-icon.swal2-error [class^=swal2-x-mark-line][class$=left]{left:.3125em}.swal2-popup.swal2-toast .swal2-icon.swal2-error [class^=swal2-x-mark-line][class$=right]{right:.3125em}.swal2-popup.swal2-toast .swal2-actions{justify-content:flex-start;height:auto;margin:0;margin-top:.5em;padding:0 .5em}.swal2-popup.swal2-toast .swal2-styled{margin:.25em .5em;padding:.4em .6em;font-size:1em}.swal2-popup.swal2-toast .swal2-success{border-color:#a5dc86}.swal2-popup.swal2-toast .swal2-success [class^=swal2-success-circular-line]{position:absolute;width:1.6em;height:3em;border-radius:50%}.swal2-popup.swal2-toast .swal2-success [class^=swal2-success-circular-line][class$=left]{top:-0.8em;left:-0.5em;transform:rotate(-45deg);transform-origin:2em 2em;border-radius:4em 0 0 4em}.swal2-popup.swal2-toast .swal2-success [class^=swal2-success-circular-line][class$=right]{top:-0.25em;left:.9375em;transform-origin:0 1.5em;border-radius:0 4em 4em 0}.swal2-popup.swal2-toast .swal2-success .swal2-success-ring{width:2em;height:2em}.swal2-popup.swal2-toast .swal2-success .swal2-success-fix{top:0;left:.4375em;width:.4375em;height:2.6875em}.swal2-popup.swal2-toast .swal2-success [class^=swal2-success-line]{height:.3125em}.swal2-popup.swal2-toast .swal2-success [class^=swal2-success-line][class$=tip]{top:1.125em;left:.1875em;width:.75em}.swal2-popup.swal2-toast .swal2-success [class^=swal2-success-line][class$=long]{top:.9375em;right:.1875em;width:1.375em}.swal2-popup.swal2-toast .swal2-success.swal2-icon-show .swal2-success-line-tip{animation:swal2-toast-animate-success-line-tip .75s}.swal2-popup.swal2-toast .swal2-success.swal2-icon-show .swal2-success-line-long{animation:swal2-toast-animate-success-line-long .75s}.swal2-popup.swal2-toast.swal2-show{animation:swal2-toast-show .5s}.swal2-popup.swal2-toast.swal2-hide{animation:swal2-toast-hide .1s forwards}div:where(.swal2-container){display:grid;position:fixed;z-index:1060;inset:0;box-sizing:border-box;grid-template-areas:"top-start top top-end" "center-start center center-end" "bottom-start bottom-center bottom-end";grid-template-rows:minmax(min-content, auto) minmax(min-content, auto) minmax(min-content, auto);height:100%;padding:.625em;overflow-x:hidden;transition:background-color .1s;-webkit-overflow-scrolling:touch}div:where(.swal2-container).swal2-backdrop-show,div:where(.swal2-container).swal2-noanimation{background:rgba(0,0,0,.4)}div:where(.swal2-container).swal2-backdrop-hide{background:rgba(0,0,0,0) !important}div:where(.swal2-container).swal2-top-start,div:where(.swal2-container).swal2-center-start,div:where(.swal2-container).swal2-bottom-start{grid-template-columns:minmax(0, 1fr) auto auto}div:where(.swal2-container).swal2-top,div:where(.swal2-container).swal2-center,div:where(.swal2-container).swal2-bottom{grid-template-columns:auto minmax(0, 1fr) auto}div:where(.swal2-container).swal2-top-end,div:where(.swal2-container).swal2-center-end,div:where(.swal2-container).swal2-bottom-end{grid-template-columns:auto auto minmax(0, 1fr)}div:where(.swal2-container).swal2-top-start>.swal2-popup{align-self:start}div:where(.swal2-container).swal2-top>.swal2-popup{grid-column:2;place-self:start center}div:where(.swal2-container).swal2-top-end>.swal2-popup,div:where(.swal2-container).swal2-top-right>.swal2-popup{grid-column:3;place-self:start end}div:where(.swal2-container).swal2-center-start>.swal2-popup,div:where(.swal2-container).swal2-center-left>.swal2-popup{grid-row:2;align-self:center}div:where(.swal2-container).swal2-center>.swal2-popup{grid-column:2;grid-row:2;place-self:center center}div:where(.swal2-container).swal2-center-end>.swal2-popup,div:where(.swal2-container).swal2-center-right>.swal2-popup{grid-column:3;grid-row:2;place-self:center end}div:where(.swal2-container).swal2-bottom-start>.swal2-popup,div:where(.swal2-container).swal2-bottom-left>.swal2-popup{grid-column:1;grid-row:3;align-self:end}div:where(.swal2-container).swal2-bottom>.swal2-popup{grid-column:2;grid-row:3;place-self:end center}div:where(.swal2-container).swal2-bottom-end>.swal2-popup,div:where(.swal2-container).swal2-bottom-right>.swal2-popup{grid-column:3;grid-row:3;place-self:end end}div:where(.swal2-container).swal2-grow-row>.swal2-popup,div:where(.swal2-container).swal2-grow-fullscreen>.swal2-popup{grid-column:1/4;width:100%}div:where(.swal2-container).swal2-grow-column>.swal2-popup,div:where(.swal2-container).swal2-grow-fullscreen>.swal2-popup{grid-row:1/4;align-self:stretch}div:where(.swal2-container).swal2-no-transition{transition:none !important}div:where(.swal2-container) div:where(.swal2-popup){display:none;position:relative;box-sizing:border-box;grid-template-columns:minmax(0, 100%);width:32em;max-width:100%;padding:0 0 1.25em;border:none;border-radius:5px;background:#fff;color:#545454;font-family:inherit;font-size:1rem}div:where(.swal2-container) div:where(.swal2-popup):focus{outline:none}div:where(.swal2-container) div:where(.swal2-popup).swal2-loading{overflow-y:hidden}div:where(.swal2-container) h2:where(.swal2-title){position:relative;max-width:100%;margin:0;padding:.8em 1em 0;color:inherit;font-size:1.875em;font-weight:600;text-align:center;text-transform:none;word-wrap:break-word}div:where(.swal2-container) div:where(.swal2-actions){display:flex;z-index:1;box-sizing:border-box;flex-wrap:wrap;align-items:center;justify-content:center;width:auto;margin:1.25em auto 0;padding:0}div:where(.swal2-container) div:where(.swal2-actions):not(.swal2-loading) .swal2-styled[disabled]{opacity:.4}div:where(.swal2-container) div:where(.swal2-actions):not(.swal2-loading) .swal2-styled:hover{background-image:linear-gradient(rgba(0, 0, 0, 0.1), rgba(0, 0, 0, 0.1))}div:where(.swal2-container) div:where(.swal2-actions):not(.swal2-loading) .swal2-styled:active{background-image:linear-gradient(rgba(0, 0, 0, 0.2), rgba(0, 0, 0, 0.2))}div:where(.swal2-container) div:where(.swal2-loader){display:none;align-items:center;justify-content:center;width:2.2em;height:2.2em;margin:0 1.875em;animation:swal2-rotate-loading 1.5s linear 0s infinite normal;border-width:.25em;border-style:solid;border-radius:100%;border-color:#2778c4 rgba(0,0,0,0) #2778c4 rgba(0,0,0,0)}div:where(.swal2-container) button:where(.swal2-styled){margin:.3125em;padding:.625em 1.1em;transition:box-shadow .1s;box-shadow:0 0 0 3px rgba(0,0,0,0);font-weight:500}div:where(.swal2-container) button:where(.swal2-styled):not([disabled]){cursor:pointer}div:where(.swal2-container) button:where(.swal2-styled).swal2-confirm{border:0;border-radius:.25em;background:initial;background-color:#7066e0;color:#fff;font-size:1em}div:where(.swal2-container) button:where(.swal2-styled).swal2-confirm:focus{box-shadow:0 0 0 3px rgba(112,102,224,.5)}div:where(.swal2-container) button:where(.swal2-styled).swal2-deny{border:0;border-radius:.25em;background:initial;background-color:#dc3741;color:#fff;font-size:1em}div:where(.swal2-container) button:where(.swal2-styled).swal2-deny:focus{box-shadow:0 0 0 3px rgba(220,55,65,.5)}div:where(.swal2-container) button:where(.swal2-styled).swal2-cancel{border:0;border-radius:.25em;background:initial;background-color:#6e7881;color:#fff;font-size:1em}div:where(.swal2-container) button:where(.swal2-styled).swal2-cancel:focus{box-shadow:0 0 0 3px rgba(110,120,129,.5)}div:where(.swal2-container) button:where(.swal2-styled).swal2-default-outline:focus{box-shadow:0 0 0 3px rgba(100,150,200,.5)}div:where(.swal2-container) button:where(.swal2-styled):focus{outline:none}div:where(.swal2-container) button:where(.swal2-styled)::-moz-focus-inner{border:0}div:where(.swal2-container) div:where(.swal2-footer){margin:1em 0 0;padding:1em 1em 0;border-top:1px solid #eee;color:inherit;font-size:1em;text-align:center}div:where(.swal2-container) .swal2-timer-progress-bar-container{position:absolute;right:0;bottom:0;left:0;grid-column:auto !important;overflow:hidden;border-bottom-right-radius:5px;border-bottom-left-radius:5px}div:where(.swal2-container) div:where(.swal2-timer-progress-bar){width:100%;height:.25em;background:rgba(0,0,0,.2)}div:where(.swal2-container) img:where(.swal2-image){max-width:100%;margin:2em auto 1em}div:where(.swal2-container) button:where(.swal2-close){z-index:2;align-items:center;justify-content:center;width:1.2em;height:1.2em;margin-top:0;margin-right:0;margin-bottom:-1.2em;padding:0;overflow:hidden;transition:color .1s,box-shadow .1s;border:none;border-radius:5px;background:rgba(0,0,0,0);color:#ccc;font-family:monospace;font-size:2.5em;cursor:pointer;justify-self:end}div:where(.swal2-container) button:where(.swal2-close):hover{transform:none;background:rgba(0,0,0,0);color:#f27474}div:where(.swal2-container) button:where(.swal2-close):focus{outline:none;box-shadow:inset 0 0 0 3px rgba(100,150,200,.5)}div:where(.swal2-container) button:where(.swal2-close)::-moz-focus-inner{border:0}div:where(.swal2-container) .swal2-html-container{z-index:1;justify-content:center;margin:1em 1.6em .3em;padding:0;overflow:auto;color:inherit;font-size:1.125em;font-weight:normal;line-height:normal;text-align:center;word-wrap:break-word;word-break:break-word}div:where(.swal2-container) input:where(.swal2-input),div:where(.swal2-container) input:where(.swal2-file),div:where(.swal2-container) textarea:where(.swal2-textarea),div:where(.swal2-container) select:where(.swal2-select),div:where(.swal2-container) div:where(.swal2-radio),div:where(.swal2-container) label:where(.swal2-checkbox){margin:1em 2em 3px}div:where(.swal2-container) input:where(.swal2-input),div:where(.swal2-container) input:where(.swal2-file),div:where(.swal2-container) textarea:where(.swal2-textarea){box-sizing:border-box;width:auto;transition:border-color .1s,box-shadow .1s;border:1px solid #d9d9d9;border-radius:.1875em;background:rgba(0,0,0,0);box-shadow:inset 0 1px 1px rgba(0,0,0,.06),0 0 0 3px rgba(0,0,0,0);color:inherit;font-size:1.125em}div:where(.swal2-container) input:where(.swal2-input).swal2-inputerror,div:where(.swal2-container) input:where(.swal2-file).swal2-inputerror,div:where(.swal2-container) textarea:where(.swal2-textarea).swal2-inputerror{border-color:#f27474 !important;box-shadow:0 0 2px #f27474 !important}div:where(.swal2-container) input:where(.swal2-input):focus,div:where(.swal2-container) input:where(.swal2-file):focus,div:where(.swal2-container) textarea:where(.swal2-textarea):focus{border:1px solid #b4dbed;outline:none;box-shadow:inset 0 1px 1px rgba(0,0,0,.06),0 0 0 3px rgba(100,150,200,.5)}div:where(.swal2-container) input:where(.swal2-input)::placeholder,div:where(.swal2-container) input:where(.swal2-file)::placeholder,div:where(.swal2-container) textarea:where(.swal2-textarea)::placeholder{color:#ccc}div:where(.swal2-container) .swal2-range{margin:1em 2em 3px;background:#fff}div:where(.swal2-container) .swal2-range input{width:80%}div:where(.swal2-container) .swal2-range output{width:20%;color:inherit;font-weight:600;text-align:center}div:where(.swal2-container) .swal2-range input,div:where(.swal2-container) .swal2-range output{height:2.625em;padding:0;font-size:1.125em;line-height:2.625em}div:where(.swal2-container) .swal2-input{height:2.625em;padding:0 .75em}div:where(.swal2-container) .swal2-file{width:75%;margin-right:auto;margin-left:auto;background:rgba(0,0,0,0);font-size:1.125em}div:where(.swal2-container) .swal2-textarea{height:6.75em;padding:.75em}div:where(.swal2-container) .swal2-select{min-width:50%;max-width:100%;padding:.375em .625em;background:rgba(0,0,0,0);color:inherit;font-size:1.125em}div:where(.swal2-container) .swal2-radio,div:where(.swal2-container) .swal2-checkbox{align-items:center;justify-content:center;background:#fff;color:inherit}div:where(.swal2-container) .swal2-radio label,div:where(.swal2-container) .swal2-checkbox label{margin:0 .6em;font-size:1.125em}div:where(.swal2-container) .swal2-radio input,div:where(.swal2-container) .swal2-checkbox input{flex-shrink:0;margin:0 .4em}div:where(.swal2-container) label:where(.swal2-input-label){display:flex;justify-content:center;margin:1em auto 0}div:where(.swal2-container) div:where(.swal2-validation-message){align-items:center;justify-content:center;margin:1em 0 0;padding:.625em;overflow:hidden;background:#f0f0f0;color:#666;font-size:1em;font-weight:300}div:where(.swal2-container) div:where(.swal2-validation-message)::before{content:"!";display:inline-block;width:1.5em;min-width:1.5em;height:1.5em;margin:0 .625em;border-radius:50%;background-color:#f27474;color:#fff;font-weight:600;line-height:1.5em;text-align:center}div:where(.swal2-container) .swal2-progress-steps{flex-wrap:wrap;align-items:center;max-width:100%;margin:1.25em auto;padding:0;background:rgba(0,0,0,0);font-weight:600}div:where(.swal2-container) .swal2-progress-steps li{display:inline-block;position:relative}div:where(.swal2-container) .swal2-progress-steps .swal2-progress-step{z-index:20;flex-shrink:0;width:2em;height:2em;border-radius:2em;background:#2778c4;color:#fff;line-height:2em;text-align:center}div:where(.swal2-container) .swal2-progress-steps .swal2-progress-step.swal2-active-progress-step{background:#2778c4}div:where(.swal2-container) .swal2-progress-steps .swal2-progress-step.swal2-active-progress-step~.swal2-progress-step{background:#add8e6;color:#fff}div:where(.swal2-container) .swal2-progress-steps .swal2-progress-step.swal2-active-progress-step~.swal2-progress-step-line{background:#add8e6}div:where(.swal2-container) .swal2-progress-steps .swal2-progress-step-line{z-index:10;flex-shrink:0;width:2.5em;height:.4em;margin:0 -1px;background:#2778c4}div:where(.swal2-icon){position:relative;box-sizing:content-box;justify-content:center;width:5em;height:5em;margin:2.5em auto .6em;border:0.25em solid rgba(0,0,0,0);border-radius:50%;border-color:#000;font-family:inherit;line-height:5em;cursor:default;user-select:none}div:where(.swal2-icon) .swal2-icon-content{display:flex;align-items:center;font-size:3.75em}div:where(.swal2-icon).swal2-error{border-color:#f27474;color:#f27474}div:where(.swal2-icon).swal2-error .swal2-x-mark{position:relative;flex-grow:1}div:where(.swal2-icon).swal2-error [class^=swal2-x-mark-line]{display:block;position:absolute;top:2.3125em;width:2.9375em;height:.3125em;border-radius:.125em;background-color:#f27474}div:where(.swal2-icon).swal2-error [class^=swal2-x-mark-line][class$=left]{left:1.0625em;transform:rotate(45deg)}div:where(.swal2-icon).swal2-error [class^=swal2-x-mark-line][class$=right]{right:1em;transform:rotate(-45deg)}div:where(.swal2-icon).swal2-error.swal2-icon-show{animation:swal2-animate-error-icon .5s}div:where(.swal2-icon).swal2-error.swal2-icon-show .swal2-x-mark{animation:swal2-animate-error-x-mark .5s}div:where(.swal2-icon).swal2-warning{border-color:#facea8;color:#f8bb86}div:where(.swal2-icon).swal2-warning.swal2-icon-show{animation:swal2-animate-error-icon .5s}div:where(.swal2-icon).swal2-warning.swal2-icon-show .swal2-icon-content{animation:swal2-animate-i-mark .5s}div:where(.swal2-icon).swal2-info{border-color:#9de0f6;color:#3fc3ee}div:where(.swal2-icon).swal2-info.swal2-icon-show{animation:swal2-animate-error-icon .5s}div:where(.swal2-icon).swal2-info.swal2-icon-show .swal2-icon-content{animation:swal2-animate-i-mark .8s}div:where(.swal2-icon).swal2-question{border-color:#c9dae1;color:#87adbd}div:where(.swal2-icon).swal2-question.swal2-icon-show{animation:swal2-animate-error-icon .5s}div:where(.swal2-icon).swal2-question.swal2-icon-show .swal2-icon-content{animation:swal2-animate-question-mark .8s}div:where(.swal2-icon).swal2-success{border-color:#a5dc86;color:#a5dc86}div:where(.swal2-icon).swal2-success [class^=swal2-success-circular-line]{position:absolute;width:3.75em;height:7.5em;border-radius:50%}div:where(.swal2-icon).swal2-success [class^=swal2-success-circular-line][class$=left]{top:-0.4375em;left:-2.0635em;transform:rotate(-45deg);transform-origin:3.75em 3.75em;border-radius:7.5em 0 0 7.5em}div:where(.swal2-icon).swal2-success [class^=swal2-success-circular-line][class$=right]{top:-0.6875em;left:1.875em;transform:rotate(-45deg);transform-origin:0 3.75em;border-radius:0 7.5em 7.5em 0}div:where(.swal2-icon).swal2-success .swal2-success-ring{position:absolute;z-index:2;top:-0.25em;left:-0.25em;box-sizing:content-box;width:100%;height:100%;border:.25em solid rgba(165,220,134,.3);border-radius:50%}div:where(.swal2-icon).swal2-success .swal2-success-fix{position:absolute;z-index:1;top:.5em;left:1.625em;width:.4375em;height:5.625em;transform:rotate(-45deg)}div:where(.swal2-icon).swal2-success [class^=swal2-success-line]{display:block;position:absolute;z-index:2;height:.3125em;border-radius:.125em;background-color:#a5dc86}div:where(.swal2-icon).swal2-success [class^=swal2-success-line][class$=tip]{top:2.875em;left:.8125em;width:1.5625em;transform:rotate(45deg)}div:where(.swal2-icon).swal2-success [class^=swal2-success-line][class$=long]{top:2.375em;right:.5em;width:2.9375em;transform:rotate(-45deg)}div:where(.swal2-icon).swal2-success.swal2-icon-show .swal2-success-line-tip{animation:swal2-animate-success-line-tip .75s}div:where(.swal2-icon).swal2-success.swal2-icon-show .swal2-success-line-long{animation:swal2-animate-success-line-long .75s}div:where(.swal2-icon).swal2-success.swal2-icon-show .swal2-success-circular-line-right{animation:swal2-rotate-success-circular-line 4.25s ease-in}[class^=swal2]{-webkit-tap-highlight-color:rgba(0,0,0,0)}.swal2-show{animation:swal2-show .3s}.swal2-hide{animation:swal2-hide .15s forwards}.swal2-noanimation{transition:none}.swal2-scrollbar-measure{position:absolute;top:-9999px;width:50px;height:50px;overflow:scroll}.swal2-rtl .swal2-close{margin-right:initial;margin-left:0}.swal2-rtl .swal2-timer-progress-bar{right:0;left:auto}@keyframes swal2-toast-show{0%{transform:translateY(-0.625em) rotateZ(2deg)}33%{transform:translateY(0) rotateZ(-2deg)}66%{transform:translateY(0.3125em) rotateZ(2deg)}100%{transform:translateY(0) rotateZ(0deg)}}@keyframes swal2-toast-hide{100%{transform:rotateZ(1deg);opacity:0}}@keyframes swal2-toast-animate-success-line-tip{0%{top:.5625em;left:.0625em;width:0}54%{top:.125em;left:.125em;width:0}70%{top:.625em;left:-0.25em;width:1.625em}84%{top:1.0625em;left:.75em;width:.5em}100%{top:1.125em;left:.1875em;width:.75em}}@keyframes swal2-toast-animate-success-line-long{0%{top:1.625em;right:1.375em;width:0}65%{top:1.25em;right:.9375em;width:0}84%{top:.9375em;right:0;width:1.125em}100%{top:.9375em;right:.1875em;width:1.375em}}@keyframes swal2-show{0%{transform:scale(0.7)}45%{transform:scale(1.05)}80%{transform:scale(0.95)}100%{transform:scale(1)}}@keyframes swal2-hide{0%{transform:scale(1);opacity:1}100%{transform:scale(0.5);opacity:0}}@keyframes swal2-animate-success-line-tip{0%{top:1.1875em;left:.0625em;width:0}54%{top:1.0625em;left:.125em;width:0}70%{top:2.1875em;left:-0.375em;width:3.125em}84%{top:3em;left:1.3125em;width:1.0625em}100%{top:2.8125em;left:.8125em;width:1.5625em}}@keyframes swal2-animate-success-line-long{0%{top:3.375em;right:2.875em;width:0}65%{top:3.375em;right:2.875em;width:0}84%{top:2.1875em;right:0;width:3.4375em}100%{top:2.375em;right:.5em;width:2.9375em}}@keyframes swal2-rotate-success-circular-line{0%{transform:rotate(-45deg)}5%{transform:rotate(-45deg)}12%{transform:rotate(-405deg)}100%{transform:rotate(-405deg)}}@keyframes swal2-animate-error-x-mark{0%{margin-top:1.625em;transform:scale(0.4);opacity:0}50%{margin-top:1.625em;transform:scale(0.4);opacity:0}80%{margin-top:-0.375em;transform:scale(1.15)}100%{margin-top:0;transform:scale(1);opacity:1}}@keyframes swal2-animate-error-icon{0%{transform:rotateX(100deg);opacity:0}100%{transform:rotateX(0deg);opacity:1}}@keyframes swal2-rotate-loading{0%{transform:rotate(0deg)}100%{transform:rotate(360deg)}}@keyframes swal2-animate-question-mark{0%{transform:rotateY(-360deg)}100%{transform:rotateY(0)}}@keyframes swal2-animate-i-mark{0%{transform:rotateZ(45deg);opacity:0}25%{transform:rotateZ(-25deg);opacity:.4}50%{transform:rotateZ(15deg);opacity:.8}75%{transform:rotateZ(-5deg);opacity:1}100%{transform:rotateX(0);opacity:1}}body.swal2-shown:not(.swal2-no-backdrop):not(.swal2-toast-shown){overflow:hidden}body.swal2-height-auto{height:auto !important}body.swal2-no-backdrop .swal2-container{background-color:rgba(0,0,0,0) !important;pointer-events:none}body.swal2-no-backdrop .swal2-container .swal2-popup{pointer-events:all}body.swal2-no-backdrop .swal2-container .swal2-modal{box-shadow:0 0 10px rgba(0,0,0,.4)}@media print{body.swal2-shown:not(.swal2-no-backdrop):not(.swal2-toast-shown){overflow-y:scroll !important}body.swal2-shown:not(.swal2-no-backdrop):not(.swal2-toast-shown)>[aria-hidden=true]{display:none}body.swal2-shown:not(.swal2-no-backdrop):not(.swal2-toast-shown) .swal2-container{position:static !important}}body.swal2-toast-shown .swal2-container{box-sizing:border-box;width:360px;max-width:100%;background-color:rgba(0,0,0,0);pointer-events:none}body.swal2-toast-shown .swal2-container.swal2-top{inset:0 auto auto 50%;transform:translateX(-50%)}body.swal2-toast-shown .swal2-container.swal2-top-end,body.swal2-toast-shown .swal2-container.swal2-top-right{inset:0 0 auto auto}body.swal2-toast-shown .swal2-container.swal2-top-start,body.swal2-toast-shown .swal2-container.swal2-top-left{inset:0 auto auto 0}body.swal2-toast-shown .swal2-container.swal2-center-start,body.swal2-toast-shown .swal2-container.swal2-center-left{inset:50% auto auto 0;transform:translateY(-50%)}body.swal2-toast-shown .swal2-container.swal2-center{inset:50% auto auto 50%;transform:translate(-50%, -50%)}body.swal2-toast-shown .swal2-container.swal2-center-end,body.swal2-toast-shown .swal2-container.swal2-center-right{inset:50% 0 auto auto;transform:translateY(-50%)}body.swal2-toast-shown .swal2-container.swal2-bottom-start,body.swal2-toast-shown .swal2-container.swal2-bottom-left{inset:auto auto 0 0}body.swal2-toast-shown .swal2-container.swal2-bottom{inset:auto auto 0 50%;transform:translateX(-50%)}body.swal2-toast-shown .swal2-container.swal2-bottom-end,body.swal2-toast-shown .swal2-container.swal2-bottom-right{inset:auto 0 0 auto} diff --git a/build/billet.asset.php b/build/billet.asset.php index f8a4c6a6..95cb61dc 100644 --- a/build/billet.asset.php +++ b/build/billet.asset.php @@ -1 +1 @@ - array('react', 'wp-element'), 'version' => 'b00b067a7818b68c0ee5'); + array('react', 'wp-element'), 'version' => '5db2459c135ada8a97a0'); diff --git a/build/billet.js b/build/billet.js index f3d807d4..e111b209 100644 --- a/build/billet.js +++ b/build/billet.js @@ -1 +1 @@ -(()=>{"use strict";const e=window.React,t=window.wp.element,n=({emitResponse:n,eventRegistration:a,backendConfig:l})=>{const{onPaymentSetup:c}=a;return(0,t.useEffect)((()=>c((()=>{const e={payment_method:l.key};return{type:n.responseTypes.SUCCESS,meta:{paymentMethodData:e}}}))),[c,l]),(0,e.createElement)(e.Fragment,null,(0,e.createElement)("p",{className:"pagarme-payment-method-instructions"},l.instructions),(0,e.createElement)("p",null,(0,e.createElement)("img",{className:"logo",src:l.logo,alt:l.label,title:l.label})))},{registerPaymentMethod:a}=window.wc.wcBlocksRegistry,l=wc.wcSettings.getSetting("woo-pagarme-payments-billet_data"),c=t=>(0,e.createElement)(n,{...t,backendConfig:l});a({name:l.name,label:(0,e.createElement)((({components:t})=>{const{PaymentMethodLabel:n}=t;return(0,e.createElement)(n,{text:l.label})}),null),content:(0,e.createElement)(c,null),edit:(0,e.createElement)(c,null),canMakePayment:()=>!0,ariaLabel:l.ariaLabel})})(); \ No newline at end of file +(()=>{var e={694:(e,t,n)=>{"use strict";var a=n(925);function r(){}function o(){}o.resetWarningCache=r,e.exports=function(){function e(e,t,n,r,o,s){if(s!==a){var c=new Error("Calling PropTypes validators directly is not supported by the `prop-types` package. Use PropTypes.checkPropTypes() to call them. Read more at http://fb.me/use-check-prop-types");throw c.name="Invariant Violation",c}}function t(){return e}e.isRequired=e;var n={array:e,bigint:e,bool:e,func:e,number:e,object:e,string:e,symbol:e,any:e,arrayOf:t,element:e,elementType:e,instanceOf:t,node:e,objectOf:t,oneOf:t,oneOfType:t,shape:t,exact:t,checkPropTypes:o,resetWarningCache:r};return n.PropTypes=n,n}},556:(e,t,n)=>{e.exports=n(694)()},925:e=>{"use strict";e.exports="SECRET_DO_NOT_PASS_THIS_OR_YOU_WILL_BE_FIRED"}},t={};function n(a){var r=t[a];if(void 0!==r)return r.exports;var o=t[a]={exports:{}};return e[a](o,o.exports,n),o.exports}n.n=e=>{var t=e&&e.__esModule?()=>e.default:()=>e;return n.d(t,{a:t}),t},n.d=(e,t)=>{for(var a in t)n.o(t,a)&&!n.o(e,a)&&Object.defineProperty(e,a,{enumerable:!0,get:t[a]})},n.o=(e,t)=>Object.prototype.hasOwnProperty.call(e,t),(()=>{"use strict";const e=window.React;var t=n(556),a=n.n(t);const r=window.wp.element,o=({emitResponse:t,eventRegistration:n,backendConfig:a})=>(((e,t,n)=>{const{onPaymentSetup:a}=t;(0,r.useEffect)((()=>a((()=>{const t={payment_method:n.key};return{type:e.responseTypes.SUCCESS,meta:{paymentMethodData:t}}}))),[a,n])})(t,n,a),(0,e.createElement)(e.Fragment,null,(0,e.createElement)("p",{className:"pagarme-payment-method-instructions"},a.instructions),(0,e.createElement)("p",{className:"pagarme-payment-method-logo"},(0,e.createElement)("img",{className:"logo",src:a.logo,alt:a.label,title:a.label}))));o.propTypes={emitResponse:a().object.isRequired,eventRegistration:a().object.isRequired,backendConfig:a().object.isRequired};const s=o,{registerPaymentMethod:c}=window.wc.wcBlocksRegistry,i=wc.wcSettings.getSetting("woo-pagarme-payments-billet_data"),p=t=>(0,e.createElement)(s,{...t,backendConfig:i}),l=({components:t})=>{const{PaymentMethodLabel:n}=t;return(0,e.createElement)(n,{text:i.label})};l.propTypes={components:a().object},c({name:i.name,label:(0,e.createElement)(l,null),content:(0,e.createElement)(p,null),edit:(0,e.createElement)(p,null),canMakePayment:()=>!0,ariaLabel:i.ariaLabel})})()})(); \ No newline at end of file diff --git a/build/credit_card.asset.php b/build/credit_card.asset.php new file mode 100644 index 00000000..b01e5c8c --- /dev/null +++ b/build/credit_card.asset.php @@ -0,0 +1 @@ + array('react', 'react-dom', 'wp-data', 'wp-element'), 'version' => '52029d5e612bf4f12f79'); diff --git a/build/credit_card.js b/build/credit_card.js new file mode 100644 index 00000000..ffd9d8e2 --- /dev/null +++ b/build/credit_card.js @@ -0,0 +1 @@ +(()=>{var e={694:(e,t,n)=>{"use strict";var r=n(925);function a(){}function s(){}s.resetWarningCache=a,e.exports=function(){function e(e,t,n,a,s,o){if(o!==r){var l=new Error("Calling PropTypes validators directly is not supported by the `prop-types` package. Use PropTypes.checkPropTypes() to call them. Read more at http://fb.me/use-check-prop-types");throw l.name="Invariant Violation",l}}function t(){return e}e.isRequired=e;var n={array:e,bigint:e,bool:e,func:e,number:e,object:e,string:e,symbol:e,any:e,arrayOf:t,element:e,elementType:e,instanceOf:t,node:e,objectOf:t,oneOf:t,oneOfType:t,shape:t,exact:t,checkPropTypes:s,resetWarningCache:a};return n.PropTypes=n,n}},556:(e,t,n)=>{e.exports=n(694)()},925:e=>{"use strict";e.exports="SECRET_DO_NOT_PASS_THIS_OR_YOU_WILL_BE_FIRED"},844:(e,t,n)=>{e.exports=n(200)},200:(e,t,n)=>{"use strict";var r,a=(r=n(609))&&"object"==typeof r&&"default"in r?r.default:r,s=n(795);function o(){return(o=Object.assign||function(e){for(var t=1;tr.length&&p(e,t.length-1);)t=t.slice(0,t.length-1);return t.length}for(var a=r.length,s=t.length;s>=r.length;s--){var o=t[s];if(!p(e,s)&&m(e,s,o)){a=s+1;break}}return a}function h(e,t){return f(e,t)===e.mask.length}function g(e,t){var n=e.maskChar,r=e.mask,a=e.prefix;if(!n){for((t=b(e,"",t,0)).lengtht.length&&(t+=a.slice(t.length,r)),l.every((function(n){for(;c=n,p(e,u=r)&&c!==a[u];){if(r>=t.length&&(t+=a[r]),l=n,s&&p(e,r)&&l===s)return!0;if(++r>=a.length)return!1}var l,u,c;return!m(e,r,n)&&n!==s||(ra.start?d=(c=function(e,t,n,r){var a=e.mask,s=e.maskChar,o=n.split(""),l=r;return o.every((function(t){for(;o=t,p(e,n=r)&&o!==a[n];)if(++r>=a.length)return!1;var n,o;return(m(e,r,t)||t===s)&&r++,r=s.length?v=s.length:v=o.length&&v{"use strict";e.exports=window.React},795:e=>{"use strict";e.exports=window.ReactDOM}},t={};function n(r){var a=t[r];if(void 0!==a)return a.exports;var s=t[r]={exports:{}};return e[r](s,s.exports,n),s.exports}n.n=e=>{var t=e&&e.__esModule?()=>e.default:()=>e;return n.d(t,{a:t}),t},n.d=(e,t)=>{for(var r in t)n.o(t,r)&&!n.o(e,r)&&Object.defineProperty(e,r,{enumerable:!0,get:t[r]})},n.o=(e,t)=>Object.prototype.hasOwnProperty.call(e,t),(()=>{"use strict";var e=n(609),t=n(556),r=n.n(t);const a=window.wp.element,{formatPrice:s}=window.wc.priceFormat,o=({optionLabel:e,finalPrice:t,value:n,extraText:r,installmentPrice:a})=>{const o=s(a),l=s(t);return 1===n?`${e} (${o})`:`${n}x ${e} ${o} (${l}) ${r}`.trim()},l=e=>e.map((e=>({label:o(e),value:e.value}))),i=(e,t,n,r,s,o,i)=>{const[u,c]=(0,a.useState)(l(e)),d=(e=>{const t=(0,a.useRef)();return(0,a.useEffect)((()=>{t.current=e})),t.current})(r);return(0,a.useEffect)((()=>{(async()=>{if(2===t&&!n||1===t&&(!d||d===r))return;o(!0);const e=parseFloat(r/100).toFixed(2).replace(".",",");try{const t=await fetch("/wp-admin/admin-ajax.php?"+new URLSearchParams({action:"xqRhBHJ5sW",flag:n,total:e}),{headers:{"X-Request-Type":"Ajax"}});if(!t.ok)return void o(!1);const r=await t.json();if(!r?.installments?.length)return void o(!1);c(l(r.installments)),s(i,1),o(!1)}catch(e){return void o(!1)}})()}),[n,r,t,c,l,s,i]),(0,a.useEffect)((()=>{2===t&&c([{label:"...",value:""}])}),[t,c]),{installmentsOptions:u,filterHandler:e=>{u.filter((t=>t.label.toLowerCase().startsWith(e.toLowerCase())))},installmentsChangeHandler:e=>{s(i,e)}}},{ComboboxControl:u}=wp.components,c=({label:t,installments:n,installmentsType:r,selectedInstallment:a,setSelectedInstallment:s,brand:o,cartTotal:l,setIsLoading:c,cardIndex:d})=>{const{installmentsOptions:p,filterHandler:m,installmentsChangeHandler:v}=i(n,r,o,l,s,c,d);return(0,e.createElement)("div",{className:"wc-block-components-select-input pagarme-installments-combobox"},(0,e.createElement)("div",{className:"wc-block-components-combobox is-active"},(0,e.createElement)(u,{className:"wc-block-components-combobox-control",label:t,onChange:v,value:a,options:p,onFilterValueChange:m,allowReset:!1,autoComplete:"off"})))};c.propTypes={label:r().string.isRequired,installments:r().array.isRequired,installmentsType:r().number.isRequired,selectedInstallment:r().oneOfType([r().string,r().number]).isRequired,setSelectedInstallment:r().func.isRequired,brand:r().string.isRequired,cartTotal:r().number.isRequired,setIsLoading:r().func.isRequired,cardIndex:r().number.isRequired};const d=c;function p(e){return e.replace(/\s/g,"").split("/")}const m=(e,t,n,r)=>{const a=(e,t)=>(delete t.inputHolderName,e.length>0||(t.inputHolderName=r.holderName),t),s=(e,t)=>(delete t.inputNumber,16===(e=e.replace(/(\D)/g,"")).length||(t.inputNumber=r.cardNumber),t),o=(e,t)=>{if(delete t.inputExpiry,0===e.length)return t.inputExpiry=r.emptyExpiry,t;const[n,a]=p(e),s=new Date(`20${a}`,n-1);let o=new Date;return o=new Date(o.getFullYear(),o.getMonth()),n>=1&&n<=12||(t.inputExpiry=r.invalidExpiryMonth),!a.includes("_")||(t.inputExpiry=r.invalidExpiryYear),s(delete t.inputCvv,0===(e=e.replace(/(\D)/g,"")).length?(t.inputCvv=r.emptyCvv,t):(3===e.length||4===e.length||(t.inputCvv=r.invalidCvv),t));return{validateInputHolderName:r=>{const s=a(r,t);return n(e,{...s}),!!s.inputHolderName},validateInputNumber:r=>{const a=s(r,t);return n(e,{...a}),!!a.inputNumber},validateInputExpiry:r=>{const a=o(r,t);return n(e,{...a}),!!a.inputExpiry},validateInputCvv:r=>{const a=l(r,t);return n(e,{...a}),!!a.inputCvv},validateAllFields:(r,i,u,c)=>{let d={...t};return d=a(r,d),d=s(i,d),d=o(u,d),d=l(c,d),n(e,{...d}),0===Object.keys(d).length}}},v=({id:t,label:n,inputValue:r,setInputValue:s,cardIndex:o,errors:l,setErrors:i,fieldErrors:u})=>{const{setIsActive:c,cssClasses:d,inputChangeHandler:p,inputBlurHandler:v}=((e,t,n,r,s,o)=>{const{validateInputHolderName:l}=m(n,r,s,o);let i="wc-block-components-text-input";const[u,c]=(0,a.useState)(!1);return(u||e.length)&&(i+=" is-active"),r.hasOwnProperty("inputHolderName")&&(i+=" has-error"),{setIsActive:c,cssClasses:i,inputChangeHandler:e=>{const r=e.target.value.replace(/[^a-z ]/gi,"");t(n,r)},inputBlurHandler:e=>{l(e.target.value),c(!1)}}})(r,s,o,l,i,u);return(0,e.createElement)("div",{className:d},(0,e.createElement)("label",{htmlFor:t},n),(0,e.createElement)("input",{type:"text",id:t,value:r,onChange:p,onFocus:()=>c(!0),onBlur:v}),l.inputHolderName&&(0,e.createElement)("div",{className:"wc-block-components-validation-error",role:"alert"},(0,e.createElement)("p",null,l.inputHolderName)))};v.propTypes={id:r().string.isRequired,label:r().string.isRequired,inputValue:r().string.isRequired,setInputValue:r().func.isRequired,cardIndex:r().number.isRequired,errors:r().object.isRequired,setErrors:r().func.isRequired,fieldErrors:r().object.isRequired};const f=v;var h=n(844),g=n.n(h);function b(e){return e.replace(/\s|•/g,"")}const E=(e,t,n,r,s,o,l,i,u)=>{const{validateInputNumber:c}=m(o,l,i,u),[d,p]=(0,a.useState)("");let v="wc-block-components-text-input pagarme-credit-card-number-container";const[f,h]=(0,a.useState)(!1);(f||e.length)&&(v+=" is-active"),l.hasOwnProperty("inputNumber")&&(v+=" has-error");const g=()=>{r(o,""),p("")};return{setIsActive:h,cssClasses:v,brandImageSrc:d,inputChangeHandler:e=>{n(o,e.target.value)},inputBlurHandler:n=>{c(n.target.value),(async()=>{const n=b(e);if(16!==n.length)return void g();s(!0);const a=n.substring(0,6),l=`https://api.pagar.me/bin/v1/${a}`;try{const e=await fetch(l),n=await e.json();let i=n.brand;if(e.ok&&void 0!==n.brandName||(i=(e=>{let n="",r=null;for(const[a,s]of Object.entries(t))for(const t of s.prefixes){const s=t.toString();0===e.indexOf(s)&&n.length{const{setIsActive:m,cssClasses:v,brandImageSrc:f,inputChangeHandler:h,inputBlurHandler:b}=E(r,l,a,o,i,u,c,d,p);return(0,e.createElement)("div",{className:v},(0,e.createElement)("label",{htmlFor:t},n),(0,e.createElement)(g(),{className:"pagarme-card-form-card-number",type:"text",id:t,mask:"9999 9999 9999 9999",maskChar:"•",onFocus:()=>m(!0),onChange:h,value:r,onBlur:b}),f&&(0,e.createElement)("img",{src:f,alt:s}),c.inputNumber&&(0,e.createElement)("div",{className:"wc-block-components-validation-error",role:"alert"},(0,e.createElement)("p",null,c.inputNumber)))};C.propTypes={id:r().string.isRequired,label:r().string.isRequired,inputValue:r().string.isRequired,setInputValue:r().func.isRequired,brand:r().string.isRequired,setBrand:r().func.isRequired,brands:r().object.isRequired,setIsLoading:r().func.isRequired,cardIndex:r().number.isRequired,errors:r().object.isRequired,setErrors:r().func.isRequired,fieldErrors:r().object.isRequired};const I=C,k=({id:t,label:n,inputValue:r,setInputValue:s,cardIndex:o,validate:l,validateIndex:i,mask:u,maskChar:c=null,errors:d})=>{const{setIsActive:p,cssClasses:m,inputChangeHandler:v,inputBlurHandler:f}=((e,t,n,r,s,o)=>{let l="wc-block-components-text-input";const[i,u]=(0,a.useState)(!1);return(i||e.length)&&(l+=" is-active"),o.hasOwnProperty(s)&&(l+=" has-error"),{setIsActive:u,cssClasses:l,inputChangeHandler:e=>{t(n,e.target.value)},inputBlurHandler:e=>{r(e.target.value),u(!1)}}})(r,s,o,l,i,d);return(0,e.createElement)("div",{className:m},(0,e.createElement)("label",{htmlFor:t},n),(0,e.createElement)(g(),{type:"text",id:t,mask:u,maskChar:c,onChange:v,value:r,onFocus:()=>p(!0),onBlur:f}))};k.propTypes={id:r().string.isRequired,label:r().string.isRequired,inputValue:r().string.isRequired,setInputValue:r().func.isRequired,cardIndex:r().number.isRequired,mask:r().string.isRequired,maskChar:r().string,validate:r().func.isRequired,validateIndex:r().string.isRequired,errors:r().object.isRequired};const w=k,y=({id:t,label:n,cardIndex:r,inputValue:a,setInputValue:s,errors:o,setErrors:l,fieldErrors:i})=>{const{validateInputExpiry:u}=m(r,o,l,i);return(0,e.createElement)(e.Fragment,null,(0,e.createElement)(w,{id:t,label:n,mask:"99/99",maskChar:"_",inputValue:a,setInputValue:s,cardIndex:r,validate:u,validateIndex:"inputExpiry",errors:o}),o.inputExpiry&&(0,e.createElement)("div",{className:"wc-block-components-validation-error",role:"alert"},(0,e.createElement)("p",null,o.inputExpiry)))};y.propTypes={id:r().string.isRequired,label:r().string.isRequired,cardIndex:r().number.isRequired,inputValue:r().string.isRequired,setInputValue:r().func.isRequired,errors:r().object.isRequired,setErrors:r().func.isRequired,fieldErrors:r().object.isRequired};const R=y,x=({id:t,label:n,cardIndex:r,inputValue:a,setInputValue:s,errors:o,setErrors:l,fieldErrors:i})=>{const{validateInputCvv:u}=m(r,o,l,i);return(0,e.createElement)(e.Fragment,null,(0,e.createElement)(w,{id:t,label:n,mask:"9999",inputValue:a,setInputValue:s,cardIndex:r,validate:u,validateIndex:"inputCvv",errors:o}),o.inputCvv&&(0,e.createElement)("div",{className:"wc-block-components-validation-error",role:"alert"},(0,e.createElement)("p",null,o.inputCvv)))};x.propTypes={id:r().string.isRequired,label:r().string.isRequired,cardIndex:r().number.isRequired,inputValue:r().string.isRequired,setInputValue:r().func.isRequired,errors:r().object.isRequired,setErrors:r().func.isRequired,fieldErrors:r().object.isRequired};const S=x,{ComboboxControl:O}=wp.components,N=({cards:t,label:n,cardIndex:r,selectedCard:a,setSelectCard:s,setBrand:o})=>{const{filterHandler:l,cardChangeHandler:i}=((e,t,n,r)=>({filterHandler:t=>{e.filter((e=>e.label.toLowerCase().startsWith(t.toLowerCase())))},cardChangeHandler:a=>{if(n(t,a),!e)return;const s=e.find((e=>e.value===a));r(t,s?s.brand:"")}}))(t,r,s,o);return(0,e.createElement)("div",{className:"wc-block-components-select-input pagarme-installments-combobox"},(0,e.createElement)("div",{className:"wc-block-components-combobox is-active"},(0,e.createElement)(O,{className:"wc-block-components-combobox-control",label:n,onChange:i,value:a,options:t,onFilterValueChange:l,allowReset:!1,autoComplete:"off"})))};N.propTypes={cards:r().array.isRequired,label:r().string.isRequired,cardIndex:r().number.isRequired,selectedCard:r().string.isRequired,setSelectCard:r().func.isRequired,setBrand:r().func.isRequired};const V=N,q=window.wp.data,T={holderName:"",number:"",expirationDate:"",installment:1,brand:"",cvv:"",saveCard:!1,walletId:"",errors:{}},P={cards:{1:{...T},2:{...T}}},D=(0,q.createReduxStore)("pagarme-cards",{reducer(e=P,t){switch(t.type){case"SET_PROPERTY_VALUE":return 0===t.propertyName?.length?e:{...e,cards:{...e.cards,[t.cardIndex]:{...e.cards[t.cardIndex],[t.propertyName]:t.value}}};case"RESET":return P}return e},actions:{setHolderName:(e,t)=>({type:"SET_PROPERTY_VALUE",cardIndex:e,value:t,propertyName:"holderName"}),setNumber:(e,t)=>({type:"SET_PROPERTY_VALUE",cardIndex:e,value:t,propertyName:"number"}),setExpirationDate:(e,t)=>({type:"SET_PROPERTY_VALUE",cardIndex:e,value:t,propertyName:"expirationDate"}),setInstallment:(e,t)=>({type:"SET_PROPERTY_VALUE",cardIndex:e,value:t,propertyName:"installment"}),setBrand:(e,t)=>({type:"SET_PROPERTY_VALUE",cardIndex:e,value:t,propertyName:"brand"}),setCvv:(e,t)=>({type:"SET_PROPERTY_VALUE",cardIndex:e,value:t,propertyName:"cvv"}),setSaveCard:(e,t)=>({type:"SET_PROPERTY_VALUE",cardIndex:e,value:t,propertyName:"saveCard"}),setWalletId:(e,t)=>({type:"SET_PROPERTY_VALUE",cardIndex:e,value:t,propertyName:"walletId"}),setErrors:(e,t)=>({type:"SET_PROPERTY_VALUE",cardIndex:e,value:t,propertyName:"errors"}),reset:()=>({type:"RESET"})},selectors:{getHolderName:(e,t)=>e.cards[t].holderName,getNumber:(e,t)=>e.cards[t].number,getExpirationDate:(e,t)=>e.cards[t].expirationDate,getInstallment:(e,t)=>e.cards[t].installment,getBrand:(e,t)=>e.cards[t].brand,getCvv:(e,t)=>e.cards[t].cvv,getSaveCard:(e,t)=>e.cards[t].saveCard,getWalletId:(e,t)=>e.cards[t].walletId,getCards:e=>e.cards,getErrors:(e,t)=>e.cards[t].errors}});(0,q.register)(D);const L=D,{CheckboxControl:M}=window.wc.blocksComponents,_=({billing:t,components:n,backendConfig:r,cardIndex:s,eventRegistration:o})=>{const{LoadingMask:l}=n,{holderNameLabel:i,numberLabel:u,expiryLabel:c,cvvLabel:p,installmentsLabel:v,saveCardLabel:h,walletLabel:g}=r.fieldsLabels,{isLoading:b,setIsLoading:E,setHolderName:C,setNumber:k,setExpirationDate:w,setInstallment:y,setBrand:x,setCvv:O,setWalletId:N,setErrors:T,saveCardChangeHandler:P,formatFieldId:D,holderName:_,number:j,expirationDate:H,selectedInstallment:B,brand:F,cvv:A,saveCard:U,walletId:Y,errors:$}=((e,t,n)=>{const[r,s]=(0,a.useState)(!1),{setHolderName:o,setNumber:l,setExpirationDate:i,setInstallment:u,setBrand:c,setCvv:d,setSaveCard:p,setWalletId:v,setErrors:f}=(0,q.useDispatch)(L),h=(0,q.useSelect)((t=>t(L).getHolderName(e)),[e]),g=(0,q.useSelect)((t=>t(L).getNumber(e)),[e]),b=(0,q.useSelect)((t=>t(L).getExpirationDate(e)),[e]),E=(0,q.useSelect)((t=>t(L).getInstallment(e)),[e]),C=(0,q.useSelect)((t=>t(L).getBrand(e)),[e]),I=(0,q.useSelect)((t=>t(L).getCvv(e)),[e]),k=(0,q.useSelect)((t=>t(L).getSaveCard(e)),[e]),w=(0,q.useSelect)((t=>t(L).getWalletId(e)),[e]),y=(0,q.useSelect)((t=>t(L).getErrors(e)),[e]),{validateAllFields:R}=m(e,y,f,n.fieldErrors),{onCheckoutValidation:x}=t;return(0,a.useEffect)((()=>x((()=>(w.length>0||R(h,g,b,I),!0)))),[x,h,g,b,I,n,w]),{isLoading:r,setIsLoading:s,setHolderName:o,setNumber:l,setExpirationDate:i,setInstallment:u,setBrand:c,setCvv:d,setWalletId:v,setErrors:f,saveCardChangeHandler:t=>{p(e,t)},formatFieldId:t=>`pagarme_credit_card_${e}_${t}`,holderName:h,number:g,expirationDate:b,selectedInstallment:E,brand:C,cvv:I,saveCard:k,walletId:w,errors:y}})(s,o,r);return(0,e.createElement)(l,{isLoading:b},(0,e.createElement)("div",{className:"wc-block-components-form"},r?.walletEnabled&&r?.cards?.length>0&&(0,e.createElement)(V,{label:g,selectedCard:Y,cards:r.cards,cardIndex:s,setSelectCard:N,setBrand:x}),0===Y.length&&(0,e.createElement)(e.Fragment,null,(0,e.createElement)(f,{id:D("holder_name"),label:i,inputValue:_,setInputValue:C,cardIndex:s,errors:$,setErrors:T,fieldErrors:r?.fieldErrors}),(0,e.createElement)(I,{id:D("number"),label:u,inputValue:j,setInputValue:k,brand:F,setBrand:x,brands:r?.brands,setIsLoading:E,cardIndex:s,errors:$,setErrors:T,fieldErrors:r?.fieldErrors}),(0,e.createElement)(R,{id:D("expiry"),label:c,inputValue:H,setInputValue:w,cardIndex:s,errors:$,setErrors:T,fieldErrors:r?.fieldErrors}),(0,e.createElement)(S,{id:D("cvv"),label:p,inputValue:A,setInputValue:O,cardIndex:s,errors:$,setErrors:T,fieldErrors:r?.fieldErrors})),(0,e.createElement)(d,{label:v,installments:r?.installments,installmentsType:r?.installmentsType,selectedInstallment:B,setSelectedInstallment:y,brand:F,cartTotal:t.cartTotal.value,setIsLoading:E,cardIndex:s}),0===Y.length&&r?.walletEnabled&&(0,e.createElement)(M,{label:h,checked:U,onChange:P})))};_.propType={billing:r().object.isRequired,components:r().object.isRequired,backendConfig:r().object.isRequired,cardIndex:r().number.isRequired,eventRegistration:r().object.isRequired};const j=_;class H extends Error{constructor(e){super(e),this.name=this.constructor.name}}const B=(e,t,n)=>{const r=`${e.replace("request.","").replace("card.","")}: ${t}`;return n.hasOwnProperty(r)?n[r]:""};async function F(e,t,n,r,a,s){const[o,l]=p(n),i={card:{holder_name:t,number:b(e),exp_month:o,exp_year:l,cvv:r}};try{const e=`https://api.pagar.me/core/v5/tokens?appId=${a}`,t=await fetch(e,{method:"POST",body:JSON.stringify(i)});if(!t.ok){const e=await t.text();if(0===e.length)return{errorMessage:s.serviceUnavailable};const n=((e,t)=>{let n="";for(const r in e.errors)for(const a of e.errors[r]||[]){const e=B(r,a,t);0!==e.length&&(n+=`${e}
        `)}return n})(JSON.parse(e),s);return{errorMessage:n}}return{token:(await t.json()).id}}catch(e){return{errorMessage:s.serviceUnavailable}}}const A=(e,t,n)=>{const{reset:r}=(0,q.useDispatch)(L),{onPaymentSetup:s}=n,o=(0,q.useSelect)((e=>e(L).getCards()));(0,a.useEffect)((()=>{r()}),[]),(0,a.useEffect)((()=>s((async()=>{try{let n=!1;if("object"==typeof o&&(n=Object.values(o).some((e=>Object.keys(e.errors).length>0))),n)return{type:t.responseTypes.ERROR,message:e.errorMessages.creditCardFormHasErrors};const r=await(async(e,t,n)=>{const r=[];for(let a=1;a0){r[a]={"wallet-id":d,brand:i,installment:u};continue}const p=await F(s,t,o,l,n.appId,n.errorMessages);if(p.errorMessage)throw new H(p.errorMessage);r[a]={token:p.token,brand:i,installment:u},c&&(r[a]["save-card"]=c)}return r})(o,1,e);return{type:t.responseTypes.SUCCESS,meta:{paymentMethodData:{pagarme:JSON.stringify({[e.key]:{cards:{...r}}}),payment_method:e.key}}}}catch(n){let r=e.errorMessages.serviceUnavailable;return n instanceof H&&(r=n.message),{type:t.responseTypes.ERROR,message:r}}}))),[s,o,e])},{registerPaymentMethod:U}=window.wc.wcBlocksRegistry,Y=wc.wcSettings.getSetting("woo-pagarme-payments-credit_card_data"),$=t=>{const{emitResponse:n,eventRegistration:r}=t;return A(Y,n,r),(0,e.createElement)(j,{...t,backendConfig:Y,cardIndex:1})},W=({components:t})=>{const{PaymentMethodLabel:n}=t;return(0,e.createElement)(n,{text:Y.label})};$.propTypes={emitResponse:r().object,eventRegistration:r().object},W.propTypes={components:r().object},U({name:Y.name,label:(0,e.createElement)(W,null),content:(0,e.createElement)($,null),edit:(0,e.createElement)($,null),canMakePayment:()=>!0,ariaLabel:Y.ariaLabel})})()})(); \ No newline at end of file diff --git a/build/pix.asset.php b/build/pix.asset.php index c5834baf..94dbeb43 100644 --- a/build/pix.asset.php +++ b/build/pix.asset.php @@ -1 +1 @@ - array('react', 'wp-element'), 'version' => '2ddb5184eb31bb1a54cf'); + array('react', 'wp-element'), 'version' => 'a0e020f30508fa5c3387'); diff --git a/build/pix.js b/build/pix.js index 04685855..ed46f2d1 100644 --- a/build/pix.js +++ b/build/pix.js @@ -1 +1 @@ -(()=>{"use strict";const e=window.React,t=window.wp.element,n=({emitResponse:n,eventRegistration:a,backendConfig:l})=>{const{onPaymentSetup:c}=a;return(0,t.useEffect)((()=>c((()=>{const e={payment_method:l.key};return{type:n.responseTypes.SUCCESS,meta:{paymentMethodData:e}}}))),[c,l]),(0,e.createElement)(e.Fragment,null,(0,e.createElement)("p",{className:"pagarme-payment-method-instructions"},l.instructions),(0,e.createElement)("p",null,(0,e.createElement)("img",{className:"logo",src:l.logo,alt:l.label,title:l.label})))},{registerPaymentMethod:a}=window.wc.wcBlocksRegistry,l=wc.wcSettings.getSetting("woo-pagarme-payments-pix_data"),c=t=>(0,e.createElement)(n,{...t,backendConfig:l});a({name:l.name,label:(0,e.createElement)((({components:t})=>{const{PaymentMethodLabel:n}=t;return(0,e.createElement)(n,{text:l.label})}),null),content:(0,e.createElement)(c,null),edit:(0,e.createElement)(c,null),canMakePayment:()=>!0,ariaLabel:l.ariaLabel})})(); \ No newline at end of file +(()=>{var e={694:(e,t,n)=>{"use strict";var a=n(925);function r(){}function o(){}o.resetWarningCache=r,e.exports=function(){function e(e,t,n,r,o,s){if(s!==a){var c=new Error("Calling PropTypes validators directly is not supported by the `prop-types` package. Use PropTypes.checkPropTypes() to call them. Read more at http://fb.me/use-check-prop-types");throw c.name="Invariant Violation",c}}function t(){return e}e.isRequired=e;var n={array:e,bigint:e,bool:e,func:e,number:e,object:e,string:e,symbol:e,any:e,arrayOf:t,element:e,elementType:e,instanceOf:t,node:e,objectOf:t,oneOf:t,oneOfType:t,shape:t,exact:t,checkPropTypes:o,resetWarningCache:r};return n.PropTypes=n,n}},556:(e,t,n)=>{e.exports=n(694)()},925:e=>{"use strict";e.exports="SECRET_DO_NOT_PASS_THIS_OR_YOU_WILL_BE_FIRED"}},t={};function n(a){var r=t[a];if(void 0!==r)return r.exports;var o=t[a]={exports:{}};return e[a](o,o.exports,n),o.exports}n.n=e=>{var t=e&&e.__esModule?()=>e.default:()=>e;return n.d(t,{a:t}),t},n.d=(e,t)=>{for(var a in t)n.o(t,a)&&!n.o(e,a)&&Object.defineProperty(e,a,{enumerable:!0,get:t[a]})},n.o=(e,t)=>Object.prototype.hasOwnProperty.call(e,t),(()=>{"use strict";const e=window.React;var t=n(556),a=n.n(t);const r=window.wp.element,o=({emitResponse:t,eventRegistration:n,backendConfig:a})=>(((e,t,n)=>{const{onPaymentSetup:a}=t;(0,r.useEffect)((()=>a((()=>{const t={payment_method:n.key};return{type:e.responseTypes.SUCCESS,meta:{paymentMethodData:t}}}))),[a,n])})(t,n,a),(0,e.createElement)(e.Fragment,null,(0,e.createElement)("p",{className:"pagarme-payment-method-instructions"},a.instructions),(0,e.createElement)("p",{className:"pagarme-payment-method-logo"},(0,e.createElement)("img",{className:"logo",src:a.logo,alt:a.label,title:a.label}))));o.propTypes={emitResponse:a().object.isRequired,eventRegistration:a().object.isRequired,backendConfig:a().object.isRequired};const s=o,{registerPaymentMethod:c}=window.wc.wcBlocksRegistry,i=wc.wcSettings.getSetting("woo-pagarme-payments-pix_data"),p=t=>(0,e.createElement)(s,{...t,backendConfig:i}),l=({components:t})=>{const{PaymentMethodLabel:n}=t;return(0,e.createElement)(n,{text:i.label})};l.propTypes={components:a().object},c({name:i.name,label:(0,e.createElement)(l,null),content:(0,e.createElement)(p,null),edit:(0,e.createElement)(p,null),canMakePayment:()=>!0,ariaLabel:i.ariaLabel})})()})(); \ No newline at end of file diff --git a/composer.json b/composer.json index 21502c1a..b352246a 100644 --- a/composer.json +++ b/composer.json @@ -16,7 +16,7 @@ }, "require": { "mashape/unirest-php": "^3.0", - "pagarme/ecommerce-module-core": "2.3.*", + "pagarme/ecommerce-module-core": "~2.4.1", "psr/log": "1.1.4", "monolog/monolog": "<2", "haydenpierce/class-finder": "^0.5.3" diff --git a/languages/woo-pagarme-payments-pt_BR.mo b/languages/woo-pagarme-payments-pt_BR.mo index 4c239100..203f3851 100644 Binary files a/languages/woo-pagarme-payments-pt_BR.mo and b/languages/woo-pagarme-payments-pt_BR.mo differ diff --git a/languages/woo-pagarme-payments-pt_BR.po b/languages/woo-pagarme-payments-pt_BR.po index 14bd663a..f23bffd9 100644 --- a/languages/woo-pagarme-payments-pt_BR.po +++ b/languages/woo-pagarme-payments-pt_BR.po @@ -5,7 +5,7 @@ msgstr "" "Project-Id-Version: WooCommerce Pagar.me Payments 1.0\n" "Report-Msgid-Bugs-To: https://wordpress.org/support/plugin/woo-pagarme-payments\n" "POT-Creation-Date: 2018-06-22 13:58-0300\n" -"PO-Revision-Date: 2024-02-01 14:29-0300\n" +"PO-Revision-Date: 2024-05-08 10:25-0300\n" "Last-Translator: Pagar.me\n" "Language-Team: \n" "Language: pt_BR\n" @@ -485,7 +485,7 @@ msgstr "%dx de %s (%s)" #: src/Model/Gateway.php:142 msgid "This card brand not is allowed on checkout." -msgstr "Essa bandeira não é permitda no checkout." +msgstr "Essa bandeira não é permitida no checkout." #: src/Model/Order.php:66 msgid "Paid" @@ -602,7 +602,7 @@ msgstr "Status" msgid "Card Holder Name" msgstr "Nome impresso no cartão" -#: src/View/Checkouts.php:245 templates/checkout/common-card-item.php:35 +#: src/View/Checkouts.php:245 templates/checkout/common-card-item.php:35 src/Block/ReactCheckout/AbstractCard.php:69 msgid "Card number" msgstr "Número do cartão" @@ -643,10 +643,18 @@ msgstr "Validade" msgid "MM / YY" msgstr "MM / AA" +#: src/Block/ReactCheckout/AbstractCard.php:70 +msgid "Expiration Date (MM/AA)" +msgstr "Validade (MM/AA)" + #: templates/checkout/common-card-item.php:68 msgid "Card code" msgstr "Código do cartão" +#: src/Block/ReactCheckout/AbstractCard.php:71 +msgid "Card code (CVV)" +msgstr "Código do cartão (CVV)" + msgid "Card Holder Document Number" msgstr "Documento do titular do cartão" @@ -1317,8 +1325,8 @@ msgstr "Texto de instruções que aparece no checkout." #: src/Model/Pix.php:55 msgid "" -"The QR Code for your payment with PIX will be generated after confirming the purchase. Point your phone at the " -"screen to capture the code or copy and paste the code into your payments app." +"The QR Code for your payment with PIX will be generated after confirming the purchase. Point your phone at the screen " +"to capture the code or copy and paste the code into your payments app." msgstr "" "O QR Code para seu pagamento através de PIX será gerado após a confirmação da compra. Aponte seu celular para a tela " "para capturar o código ou copie e cole o código em seu aplicativo de pagamentos." @@ -1334,3 +1342,91 @@ msgstr "" #: src/Block/ReactCheckout/AbstractPaymentMethodBlock.php:35 msgid "Billet payment method" msgstr "Meio de pagamento Boleto" + +#: src/Block/ReactCheckout/AbstractPaymentMethodBlock.php:35 +msgid "Credit Card payment method" +msgstr "Meio de pagamento Cartão de Crédito" + +#: assets/javascripts/front/reactCheckout/payments/creditCard/installmentsFormatter.js:13 +msgid "of" +msgstr "de" + +#: assets/javascripts/front/reactCheckout/payments/creditCard/installmentsFormatter.js:13 +msgid "Unable to generate a transaction. Unavailable service." +msgstr "Não foi possível gerar uma transação. Serviço indisponível." + +#: src/Core.php:348 +msgid "Please, check the errors below." +msgstr "Por favor, verifique os erros abaixo." + +msgid "Please enter a valid name." +msgstr "Por favor, digite um nome válido." + +msgid "Please enter a valid credit card number." +msgstr "Por favor, digite um número de cartão válido." + +msgid "Please enter a expiry date." +msgstr "Por favor, digite a data de validade." + +msgid "The expiry month must be between 01 and 12." +msgstr "O mês da data de validade deve ser entre 01 e 12." + +msgid "The expiry year must have two digits." +msgstr "O ano da data de validade deve conter dois dígitos" + +msgid "Please enter a valid CVV number." +msgstr "Por favor, digite o número CVV." + +msgid "The CVV number must be between 3 and 4 characters." +msgstr "O número CVV deve ter entre 3 e 4 caracteres." + +msgid "3DS settings" +msgstr "Configurações de 3DS" + +msgid "Enable 3DS" +msgstr "Habilitar 3DS" + +msgid "Minimum value for 3DS authentication" +msgstr "Valor mínimo para autenticação 3DS" + +msgid "Failed to generate Token for 3ds, try again." +msgstr "Falha ao gerar Token para 3ds, tente novamente." + +msgid "There was a problem finding the email." +msgstr "Ocorreu um problema ao encontrar o e-mail." + +msgid "There was a problem finding the address." +msgstr "Ocorreu um problema ao encontrar o endereço." + +msgid "There was a problem when assembling the card's expiration data." +msgstr "Ocorreu um problema ao montar o dado de expiração do cartão." + +msgid "There was a problem when assembling the purchase data." +msgstr "Ocorreu um problema ao montar o dado de compra." + +msgid "3DS Status" +msgstr "Status 3DS" + +msgid "Y - Transaction approved and authenticated by the Issuer" +msgstr "Y - Transação aprovada e autenticada pelo Emissor" + +msgid "A - Transaction approved and authenticated by Brand" +msgstr "A - Transação aprovada e autenticada pela Bandeira" + +msgid "I - Only data sent to the Brand and Issuer" +msgstr "I - Apenas dados enviados a Bandeira e Emissor" + +msgid "U - Authentication unavailable" +msgstr "U - Autenticação indisponível" + +msgid "N - Transaction rejected by the Issuer" +msgstr "N - Transação rejeitada pelo Emissor" + +msgid "R - Transaction rejected by Issuer (post-challenge)" +msgstr "R - Transação rejeitada pelo Emissor (pós-desafio)" + +msgid "Invalid Data" +msgstr "Dados Inválidos" + +msgid "Tokenization timeout." +msgstr "Timeout na tokenização." diff --git a/package.json b/package.json index 7c49100f..b0f1fdd2 100644 --- a/package.json +++ b/package.json @@ -5,7 +5,9 @@ "main": "woo-pagarme-payments.php", "devDependencies": { "@woocommerce/dependency-extraction-webpack-plugin": "^2.3.0", - "@wordpress/i18n": "^4.50.0", + "@wordpress/components": "^26.0.0", + "@wordpress/data": "^9.22.0", + "@wordpress/i18n": "^4.55.0", "@wordpress/scripts": "^27.1.0", "grunt": "^1.0.1", "grunt-concurrent": "^2.3.1", @@ -17,10 +19,13 @@ "load-grunt-config": "^0.19.2", "load-grunt-tasks": "^3.5.2", "node-wp-i18n": "^1.2.0", + "prop-types": "^15.8.1", + "react-input-mask": "^2.0.4", "time-grunt": "^1.4.0" }, "scripts": { "makepot": "yarn wpi18n makepot --exclude=node_modules,vendor", - "build": "wp-scripts build" + "build": "wp-scripts build", + "start": "wp-scripts start" } } diff --git a/src/Block/Checkout/Form/Card.php b/src/Block/Checkout/Form/Card.php index b64eea3d..f2e0e640 100644 --- a/src/Block/Checkout/Form/Card.php +++ b/src/Block/Checkout/Form/Card.php @@ -11,10 +11,11 @@ namespace Woocommerce\Pagarme\Block\Checkout\Form; -use Woocommerce\Pagarme\Block\Checkout\Gateway; +use Woocommerce\Pagarme\Core; use Woocommerce\Pagarme\Helper\Utils; -use Woocommerce\Pagarme\Model\Payment\Voucher; use Woocommerce\Pagarme\Model\Subscription; +use Woocommerce\Pagarme\Model\Payment\Voucher; +use Woocommerce\Pagarme\Block\Checkout\Gateway; defined( 'ABSPATH' ) || exit; @@ -24,6 +25,8 @@ */ class Card extends Gateway { + const INVALID_CARD_ERROR_MESSAGE = 'This card number is invalid.'; + /** * @var string */ @@ -37,11 +40,22 @@ class Card extends Gateway /** * @var string[] */ - protected $deps = ['pagarme-checkout-card']; + protected $deps = []; /** @var int */ protected $sequence = 1; + public function enqueue_scripts($scripts = null, $deps = []) + { + parent::enqueue_scripts($scripts, $deps); + + wp_localize_script( + WCMP_JS_HANDLER_BASE_NAME . 'card', + 'PagarmeGlobalVars', + self::getLocalizeScriptArgs() + ); + } + /** * @param int $sequence * @return $this @@ -133,4 +147,70 @@ public function getCompoenent() return Utils::get_component('pagarme-checkout'); } + public static function getLocalizeScriptArgs($args = array()) + { + $defaults = array( + 'ajaxUrl' => Utils::get_admin_url('admin-ajax.php'), + 'WPLANG' => get_locale(), + 'spinnerUrl' => Core::plugins_url('assets/images/icons/spinner.png'), + 'prefix' => Core::PREFIX, + 'checkoutErrors' => array( + 'pt_BR' => self::getCardErrorsMessagesTranslated(), + ), + ); + + return array_merge($defaults, $args); + } + + public static function getCardErrorsMessagesTranslated() + { + return array( + 'exp_month: A value is required.' => + __('Expiration Date: The month is required.', 'woo-pagarme-payments'), + 'exp_month: The field exp_month must be between 1 and 12.' => + __('Expiration Date: The month must be between 1 and 12.', 'woo-pagarme-payments'), + "exp_year: The value 'undefined' is not valid for exp_year." => + __('Expiration Date: Invalid year.', 'woo-pagarme-payments'), + 'request: The card expiration date is invalid.' => + __('Expiration Date: Invalid expiration date.', 'woo-pagarme-payments'), + 'request: Card expired.' => + __('Expiration Date: Expired card.', 'woo-pagarme-payments'), + 'holder_name: The holder_name field is required.' => + __('The card holder name is required.', 'woo-pagarme-payments'), + 'number: The number field is required.' => + __('The card number is required.', 'woo-pagarme-payments'), + 'number: The number field is not a valid credit card number.' => + __(self::INVALID_CARD_ERROR_MESSAGE, 'woo-pagarme-payments'), + 'card: The number field is not a valid card number' => + __(self::INVALID_CARD_ERROR_MESSAGE, 'woo-pagarme-payments'), + 'card.number: The field number must be a string with a minimum length of 13 and a maximum length of 19.' + => __('The card number must be between 13 and 19 characters.', 'woo-pagarme-payments'), + 'card: Card expired.' => + __('The expiration date is expired.', 'woo-pagarme-payments'), + 'cvv: The field cvv must be a string with a minimum length of 3 and a maximum length of 4.' + => __('The card code must be between 3 and 4 characters.', 'woo-pagarme-payments'), + 'card: Invalid data to change card brand' => + __(self::INVALID_CARD_ERROR_MESSAGE, 'woo-pagarme-payments'), + 'card: Tokenize timeout' => + __('Tokenization timeout.', 'woo-pagarme-payments'), + 'fail_get_token' => + __('Failed to generate Token for 3ds, try again.', 'woo-pagarme-payments'), + 'fail_get_email' => + __('There was a problem finding the email.', 'woo-pagarme-payments'), + 'fail_get_billing_address' => + __('There was a problem finding the address.', 'woo-pagarme-payments'), + 'fail_assemble_card_expiry_date' => + __('There was a problem when assembling the card\'s expiration data.', 'woo-pagarme-payments'), + 'fail_assemble_purchase' => + __('There was a problem when assembling the purchase data.', 'woo-pagarme-payments'), + 'invalidBrand' => + __('Invalid Data', 'woo-pagarme-payments'), + 'card: Can\'t check card form: Invalid element received' => + __('Can\'t check card form: Invalid element received.', 'woo-pagarme-payments'), + 'serviceUnavailable' => + __('Unable to generate a transaction. Unavailable service.', 'woo-pagarme-payments'), + 'creditCardFormHasErrors' => + __('Please, check the errors below.', 'woo-pagarme-payments') + ); + } } diff --git a/src/Block/Checkout/Form/Tds.php b/src/Block/Checkout/Form/Tds.php new file mode 100644 index 00000000..7571fcf0 --- /dev/null +++ b/src/Block/Checkout/Form/Tds.php @@ -0,0 +1,57 @@ +getConfig()->getIsSandboxMode()) { + $url = 'https://auth-3ds-sdx.pagar.me/bundle.js'; + } + return $url; + } + + public function canInitTds() + { + return $this->getConfig()->isTdsEnabled(); + } +} diff --git a/src/Block/Order/Transaction/AbstractCard.php b/src/Block/Order/Transaction/AbstractCard.php index 7f81e375..e9128d37 100644 --- a/src/Block/Order/Transaction/AbstractCard.php +++ b/src/Block/Order/Transaction/AbstractCard.php @@ -1,4 +1,5 @@ getData('orderId'); + if ($orderId) { + $order = new Order($orderId); + $authorization = $order->get_meta('pagarme_tds_authentication'); + + if (!empty($authorization)) { + $authorization = json_decode($authorization, true); + $value[$this->getLabel('3DS Status')] = __( + AuthenticationStatusEnum::statusMessage( + $authorization['trans_status'] + ), + 'woo-pagarme-payments' + ); + } + } + } catch (\Exception $e) { + } return $value; } @@ -76,7 +96,7 @@ private function getLabel(string $key) /** * @param $key * @param $value - * @return String + * @return string */ public function convertData($key, $value) { diff --git a/src/Block/ReactCheckout/AbstractCard.php b/src/Block/ReactCheckout/AbstractCard.php new file mode 100644 index 00000000..6aa1dca3 --- /dev/null +++ b/src/Block/ReactCheckout/AbstractCard.php @@ -0,0 +1,113 @@ +config = new Config(); + $this->installmentsBlock = new InstallmentsBlock(); + parent::__construct( $paymentModel ); + } + + /** + * @return array + */ + protected function getAdditionalPaymentMethodData() { + $additionalData = [ + 'walletEnabled' => $this->isWalletEnabled(), + 'installmentsType' => intval( $this->config->getCcInstallmentType() ?? 1 ), + 'appId' => $this->config->getPublicKey(), + 'installments' => $this->getInstallments(), + 'fieldsLabels' => $this->getFieldsLabels(), + 'brands' => $this->paymentModel->getConfigDataProvider()['brands'], + 'errorMessages' => CardBlock::getCardErrorsMessagesTranslated(), + 'cards' => $this->paymentModel->getCards(), + 'fieldErrors' => $this->getFieldErrors() + ]; + + if ( $additionalData['walletEnabled'] ) { + $additionalData['cards'] = $this->assembleCardsInfoToCheckoutBlock(); + } + + return $additionalData; + } + + protected function isWalletEnabled() { + return $this->config->getCcAllowSave(); + } + + protected function getInstallments() { + if ( $this->installmentsBlock->isCcInstallmentTypeByFlag() ) { + return []; + } + + return $this->installmentsBlock->render(); + } + + protected function getFieldsLabels() { + return [ + 'holderNameLabel' => __( 'Card Holder Name', 'woo-pagarme-payments' ), + 'numberLabel' => __( 'Card number', 'woo-pagarme-payments' ), + 'expiryLabel' => __( 'Expiration Date (MM/AA)', 'woo-pagarme-payments' ), + 'cvvLabel' => __( 'Card code (CVV)', 'woo-pagarme-payments' ), + 'installmentsLabel' => __( 'Installments quantity', 'woo-pagarme-payments' ), + 'saveCardLabel' => __( 'Save this card for future purchases', 'woo-pagarme-payments' ), + 'walletLabel' => __( 'Saved cards', 'woo-pagarme-payments' ), + ]; + } + + protected function getFieldErrors() { + return [ + 'holderName' => __( 'Please enter a valid name.', 'woo-pagarme-payments' ), + 'cardNumber' => __( 'Please enter a valid credit card number.', 'woo-pagarme-payments' ), + 'emptyExpiry' => __( 'Please enter a expiry date.', 'woo-pagarme-payments' ), + 'invalidExpiryMonth' => __( 'The expiry month must be between 01 and 12.', 'woo-pagarme-payments' ), + 'invalidExpiryYear' => __( 'The expiry year must have two digits.', 'woo-pagarme-payments' ), + 'expiredCard' => __( 'The expiration date is expired.', 'woo-pagarme-payments' ), + 'emptyCvv' => __( 'Please enter a valid CVV number.', 'woo-pagarme-payments' ), + 'invalidCvv' => __( 'The CVV number must be between 3 and 4 characters.', 'woo-pagarme-payments' ), + ]; + } + + protected function assembleCardsInfoToCheckoutBlock() { + $cards = $this->paymentModel->getCards(); + + if ( ! $cards ) { + return []; + } + + $cardsInfo = [ + 0 => [ + 'value' => '', + 'brand' => '', + 'label' => __( 'Choose your saved card', 'woo-pagarme-payments' ) + ] + ]; + + foreach ( $cards as $card ) { + $lastFourDigits = $card->getLastFourDigits()->getValue(); + $cardsInfo[] = [ + 'value' => $card->getPagarmeId()->getValue(), + 'brand' => strtolower( $card->getBrand()->getName() ), + 'label' => "•••• •••• •••• $lastFourDigits" + ]; + } + + return $cardsInfo; + } + +} diff --git a/src/Block/ReactCheckout/AbstractPaymentMethodBlock.php b/src/Block/ReactCheckout/AbstractPaymentMethodBlock.php index 55d10c64..c7a9bd9a 100644 --- a/src/Block/ReactCheckout/AbstractPaymentMethodBlock.php +++ b/src/Block/ReactCheckout/AbstractPaymentMethodBlock.php @@ -2,9 +2,9 @@ namespace Woocommerce\Pagarme\Block\ReactCheckout; +use Automattic\WooCommerce\Blocks\Payments\Integrations\AbstractPaymentMethodType; use Woocommerce\Pagarme\Core; use Woocommerce\Pagarme\Model\Payment\AbstractPayment; -use Automattic\WooCommerce\Blocks\Payments\Integrations\AbstractPaymentMethodType; abstract class AbstractPaymentMethodBlock extends AbstractPaymentMethodType { @@ -17,7 +17,7 @@ abstract class AbstractPaymentMethodBlock extends AbstractPaymentMethodType /** @var AbstractPayment */ protected $paymentModel; - public function __construct(AbstractPayment $paymentModel) + public function __construct( AbstractPayment $paymentModel ) { $this->paymentModel = $paymentModel; } @@ -32,8 +32,8 @@ public function initialize() */ public function get_payment_method_script_handles() { - $scriptName = sprintf('pagarme_payments_%s_blocks_integration', static::PAYMENT_METHOD_KEY); - wp_register_script($scriptName, $this->jsUrl(), $this->getScriptDependencies(), false, true); + $scriptName = sprintf( 'pagarme_payments_%s_blocks_integration', static::PAYMENT_METHOD_KEY ); + wp_register_script( $scriptName, $this->jsUrl(), $this->getScriptDependencies(), false, true ); return [ $scriptName @@ -45,16 +45,16 @@ public function get_payment_method_script_handles() */ public function get_payment_method_data() { - $paymentData = [ - 'name' => $this->name, - 'key' => static::PAYMENT_METHOD_KEY, - 'label' => $this->settings[ 'title'], - 'ariaLabel' => __(static::ARIA_LABEL, 'woo-pagarme-payments') + $paymentData = [ + 'name' => $this->name, + 'key' => static::PAYMENT_METHOD_KEY, + 'label' => $this->settings['title'], + 'ariaLabel' => __( static::ARIA_LABEL, 'woo-pagarme-payments' ) ]; - $additionaPaymentData = $this->getAdditionalPaymentMethodData(); + $additionalPaymentData = $this->getAdditionalPaymentMethodData(); - return array_merge($paymentData, $additionaPaymentData); + return array_merge( $paymentData, $additionalPaymentData ); } /** @@ -62,7 +62,7 @@ public function get_payment_method_data() */ protected function jsUrl() { - return Core::plugins_url('build/' . static::PAYMENT_METHOD_KEY . '.js'); + return Core::plugins_url( 'build/' . static::PAYMENT_METHOD_KEY . '.js' ); } /** @@ -70,7 +70,7 @@ protected function jsUrl() */ protected function getScriptDependencies() { - return []; + return [ 'wp-components', 'react' ]; } /** diff --git a/src/Block/ReactCheckout/AbstractPaymentMethodWithInstructionsBlock.php b/src/Block/ReactCheckout/AbstractPaymentMethodWithInstructionsBlock.php index 2a532dcb..f46c5ac8 100644 --- a/src/Block/ReactCheckout/AbstractPaymentMethodWithInstructionsBlock.php +++ b/src/Block/ReactCheckout/AbstractPaymentMethodWithInstructionsBlock.php @@ -5,7 +5,7 @@ use Woocommerce\Pagarme\Block\ReactCheckout\AbstractPaymentMethodBlock; use Woocommerce\Pagarme\Model\Payment\AbstractPaymentWithCheckoutInstructions; -class AbstractPaymentWithCheckoutInstructionsBlock extends AbstractPaymentMethodBlock +abstract class AbstractPaymentWithCheckoutInstructionsBlock extends AbstractPaymentMethodBlock { /** @var AbstractPaymentWithCheckoutInstructions */ protected $paymentModel; diff --git a/src/Block/ReactCheckout/CreditCard.php b/src/Block/ReactCheckout/CreditCard.php new file mode 100644 index 00000000..4057c3c8 --- /dev/null +++ b/src/Block/ReactCheckout/CreditCard.php @@ -0,0 +1,29 @@ +i18n = new LocalizationService(); @@ -395,15 +398,32 @@ public function getPaymentCollection() /** @return Customer */ public function getCustomer() { + if (!empty($this->customer)) { + return $this->customer; + } + $customerId = get_current_user_id(); if (!empty($this->getPlatformOrder()->get_user_id())) { $customerId = $this->getPlatformOrder()->get_user_id() ?? null; } if (!empty($customerId)) { - return $this->getRegisteredCustomer($customerId); + $customer = $this->getRegisteredCustomer($customerId); + $this->setCustomer($customer); + return $customer; } - return $this->getGuestCustomer(); + $customer = $this->getGuestCustomer(); + $this->setCustomer($customer); + return $customer; + } + + /** + * @param Customer $customer + * @return void + */ + public function setCustomer($customer) + { + $this->customer = $customer; } /** @@ -580,7 +600,7 @@ public function getPaymentMethodCollection() $payment = new WCModelPayment($this->formData['payment_method']); $pagarmeCustomer = $this->getCustomer(); - $customer = new \stdClass(); + $customer = new stdClass(); $customer->id = $pagarmeCustomer->getPagarmeId() ? $pagarmeCustomer->getPagarmeId()->getValue() : null; @@ -701,6 +721,21 @@ private function extractPaymentDataFromCreditCard( if (!isset($paymentData[$creditCardDataIndex])) { $paymentData[$creditCardDataIndex] = []; } + + if (!empty($this->formData['authentication'])) { + $authenticationFormData = $this->formData['authentication']; + $authentication = new stdClass(); + $authentication->type = 'threed_secure'; + $authentication->status = $authenticationFormData['trans_status']; + + $threeDSecure = new stdClass(); + $threeDSecure->mpi = 'pagarme'; + $threeDSecure->transactionId = $authenticationFormData['tds_server_trans_id']; + + $authentication->threeDSecure = $threeDSecure; + $newPaymentData->authentication = $authentication; + } + $paymentData[$creditCardDataIndex][] = $newPaymentData; } @@ -1104,6 +1139,17 @@ private function validateAddressFields($platformAddress) $fieldIsNotSet = !array_key_exists($requiredField, $platformAddress) || empty($platformAddress[$requiredField]); + if ($requiredField === 'number') { + $fieldIsNotSet = !array_key_exists($requiredField, $platformAddress) + || ( + empty($platformAddress[$requiredField]) + && ( + $platformAddress[$requiredField] === null + || !is_numeric(trim($platformAddress[$requiredField])) + ) + ); + } + if ($fieldIsNotSet) { $message = "Missing $requiredField in customer address"; $ExceptionMessage = $this->i18n->getDashboard($message); diff --git a/src/Controller/Checkout.php b/src/Controller/Checkout.php index 47b7ebb6..ba9585a1 100644 --- a/src/Controller/Checkout.php +++ b/src/Controller/Checkout.php @@ -120,15 +120,16 @@ public function build_installments() $installmentsConfig = $this->installments->getConfiguredMaxCcInstallments(); - $optionsHtml = $this->cardInstallments->renderOptions( - $this->cardInstallments->getInstallmentsByType( - Utils::get('total', false), - Utils::get('flag', false, 'esc_html') + $installments = $this->cardInstallments->getInstallmentsByType( + Utils::get('total', false), + Utils::get('flag', false, 'esc_html') - )); + ); + $optionsHtml = $this->cardInstallments->renderOptions($installments); echo json_encode([ 'installmentsConfig' => $installmentsConfig, - 'optionsHtml' => wp_kses_no_null($optionsHtml) + 'optionsHtml' => wp_kses_no_null($optionsHtml), + 'installments' => $installments ]); exit(); } diff --git a/src/Controller/Gateways/Billet.php b/src/Controller/Gateways/Billet.php index 16df6e25..6e2064cd 100644 --- a/src/Controller/Gateways/Billet.php +++ b/src/Controller/Gateways/Billet.php @@ -60,12 +60,15 @@ public function isSubscriptionActive(): bool */ public function append_form_fields() { - return [ + $fields = [ BilletModel::getCheckoutInstructionsKey() => $this->field_billet_checkout_instructions(), 'billet_deadline_days' => $this->field_billet_deadline_days(), 'billet_instructions' => $this->field_billet_instructions(), - 'billet_allowed_in_subscription' => $this->field_billet_allowed_for_subscription(), ]; + if (Subscription::hasSubscriptionPlugin()) { + $fields['billet_allowed_in_subscription'] = $this->field_billet_allowed_for_subscription(); + } + return $fields; } /** diff --git a/src/Controller/Gateways/CreditCard.php b/src/Controller/Gateways/CreditCard.php index 7285f70f..6b228a66 100644 --- a/src/Controller/Gateways/CreditCard.php +++ b/src/Controller/Gateways/CreditCard.php @@ -78,6 +78,11 @@ public function append_form_fields() $fields['cc_allowed_in_subscription'] = $this->field_cc_allowed_for_subscription(); $fields['cc_subscription_installments'] = $this->field_cc_subscription_installments(); } + + $fields['section_tds'] = $this->section_tds(); + $fields['tds_enabled'] = $this->field_cc_tds_enabled(); + $fields['tds_min_amount'] = $this->field_cc_tds_min_amount(); + return $fields; } @@ -384,6 +389,56 @@ public function antifraud_min_value() ]; } + /** + * @return array + */ + public function section_tds() + { + return [ + 'title' => __('3DS settings', 'woo-pagarme-payments'), + 'type' => 'title', + 'custom_attributes' => array( + 'data-field' => 'tds-section', + ) + ]; + } + + /** + * @return array + */ + private function field_cc_tds_enabled() + { + return [ + 'title' => __('Enable', 'woo-pagarme-payments'), + 'type' => 'select', + 'options' => $this->yesnoOptions->toLabelsArray(true), + 'label' => __('Enable 3DS', 'woo-pagarme-payments'), + 'default' => $this->config->getData('cc_tds_enabled') ?? strtolower(Yesno::NO), + 'custom_attributes' => [ + 'data-field' => 'cc-tds-enabled', + ], + ]; + } + + /** + * @return array + */ + private function field_cc_tds_min_amount() + { + return [ + 'title' => __('Minimum value for 3DS authentication', 'woo-pagarme-payments'), + 'type' => 'text', + 'default' => $this->config->getData('cc_tds_min_amount') ?? '', + 'placeholder' => '0,00', + 'custom_attributes' => array( + 'data-field' => 'cc-tds-min-amount', + 'data-mask' => '#.##0,00', + 'data-mask-reverse' => 'true', + ), + ]; + } + + public function generate_installments_by_flag_html($key, $data) { $fieldKey = $this->get_field_key($key); diff --git a/src/Controller/Gateways/Pix.php b/src/Controller/Gateways/Pix.php index 2685e637..948e02d1 100644 --- a/src/Controller/Gateways/Pix.php +++ b/src/Controller/Gateways/Pix.php @@ -56,12 +56,15 @@ public function isSubscriptionActive(): bool */ public function append_form_fields() { - return [ + $fields = [ PixModel::getCheckoutInstructionsKey() => $this->field_pix_checkout_instructions(), 'pix_qrcode_expiration_time' => $this->field_pix_qrcode_expiration_time(), 'pix_additional_data' => $this->field_pix_additional_data(), - 'pix_allowed_in_subscription' => $this->field_pix_allowed_for_subscription(), ]; + if (Subscription::hasSubscriptionPlugin()) { + $fields['pix_allowed_in_subscription'] = $this->field_pix_allowed_for_subscription(); + } + return $fields; } public function field_pix_qrcode_expiration_time() diff --git a/src/Controller/TdsToken.php b/src/Controller/TdsToken.php new file mode 100644 index 00000000..c3b3b307 --- /dev/null +++ b/src/Controller/TdsToken.php @@ -0,0 +1,30 @@ +config = new Config; + add_action('woocommerce_api_pagarme-tds-token', [$this, 'getTdsToken']); + } + + public function getTdsToken() + { + $accountId = $this->config->getAccountId(); + $tdsTokenService = new TdsTokenService($this->config); + wp_send_json_success([ + 'token' => $tdsTokenService->getTdsToken($accountId) + ]); + wp_die(); + } +} diff --git a/src/Core.php b/src/Core.php index 8be88f76..810eac9c 100644 --- a/src/Core.php +++ b/src/Core.php @@ -17,10 +17,6 @@ class Core const PREFIX = WCMP_PREFIX; - const LOCALIZE_SCRIPT_ID = 'PagarmeGlobalVars'; - - const INVALID_CARD_ERROR_MESSAGE = 'This card number is invalid.'; - private function __construct() { add_action('init', array(__CLASS__, 'load_textdomain')); @@ -68,6 +64,7 @@ public static function initialize() 'Charges', 'Accounts', 'HubAccounts', + 'TdsToken', ); self::load_controllers($controllers); @@ -81,21 +78,6 @@ public static function load_controllers($controllers) } } - public static function get_localize_script_args($args = array()) - { - $defaults = array( - 'ajaxUrl' => Utils::get_admin_url('admin-ajax.php'), - 'WPLANG' => get_locale(), - 'spinnerUrl' => self::plugins_url('assets/images/icons/spinner.png'), - 'prefix' => self::PREFIX, - 'checkoutErrors' => array( - 'pt_BR' => self::credit_card_errors_pt_br(), - ), - ); - - return array_merge($defaults, $args); - } - public static function admin_enqueue_scripts() { add_action('admin_enqueue_scripts', array(__CLASS__, 'scripts_admin')); @@ -145,20 +127,6 @@ public static function enqueue_scripts($type, $deps = array(), $localize_args = false ); } - if ($type == 'front') { - wp_enqueue_script( - 'pagarme-checkout-card', - self::plugins_url("assets/javascripts/front/checkout/model/payment.js"), - array_merge(array('jquery'), $deps), - self::filemtime("assets/javascripts/front/checkout/model/payment.js"), - true - ); - wp_localize_script( - 'pagarme-checkout-card', - 'PagarmeGlobalVars', - self::get_localize_script_args() - ); - } } @@ -257,6 +225,10 @@ public static function instance() public static function get_webhook_url($custom_url = false) { $url = !$custom_url ? Utils::get_site_url() : $custom_url; + if ( !$custom_url ) { + $parsedUrl = parse_url($url); + $url = $parsedUrl['scheme'] . '://' . $parsedUrl['host']; + } return sprintf('%s/wc-api/%s/', $url, self::get_webhook_name()); } @@ -308,40 +280,4 @@ private function addActionsRunners() $actions = new ActionsRunner(); $actions->run(); } - - public static function credit_card_errors_pt_br() - { - return array( - 'exp_month: A value is required.' => - __('Expiration Date: The month is required.', 'woo-pagarme-payments'), - 'exp_month: The field exp_month must be between 1 and 12.' => - __('Expiration Date: The month must be between 1 and 12.', 'woo-pagarme-payments'), - "exp_year: The value 'undefined' is not valid for exp_year." => - __('Expiration Date: Invalid year.', 'woo-pagarme-payments'), - 'request: The card expiration date is invalid.' => - __('Expiration Date: Invalid expiration date.', 'woo-pagarme-payments'), - 'request: Card expired.' => - __('Expiration Date: Expired card.', 'woo-pagarme-payments'), - 'holder_name: The holder_name field is required.' => - __('The card holder name is required.', 'woo-pagarme-payments'), - 'number: The number field is required.' => - __('The card number is required.', 'woo-pagarme-payments'), - 'number: The number field is not a valid credit card number.' => - __(self::INVALID_CARD_ERROR_MESSAGE, 'woo-pagarme-payments'), - 'card: The number field is not a valid card number' => - __(self::INVALID_CARD_ERROR_MESSAGE, 'woo-pagarme-payments'), - 'card.number: The field number must be a string with a minimum length of 13 and a maximum length of 19.' - => __('The card number must be between 13 and 19 characters.', 'woo-pagarme-payments'), - 'card: Card expired.' => - __('The expiration date is expired.', 'woo-pagarme-payments'), - 'card.cvv: The field cvv must be a string with a minimum length of 3 and a maximum length of 4.' - => __('The card code must be between 3 and 4 characters.', 'woo-pagarme-payments'), - 'card: Invalid data to change card brand' => - __(self::INVALID_CARD_ERROR_MESSAGE, 'woo-pagarme-payments'), - 'card: Tokenize timeout' => - __('Timeout na tokenização.', 'woo-pagarme-payments'), - 'card: Can\'t check card form: Invalid element received' => - __('Can\'t check card form: Invalid element received.', 'woo-pagarme-payments'), - ); - } } diff --git a/src/Helper/Utils.php b/src/Helper/Utils.php index f1adfc87..86c68a95 100644 --- a/src/Helper/Utils.php +++ b/src/Helper/Utils.php @@ -95,7 +95,7 @@ public static function server($key) * @since 1.0 * @param string $name * @param string $action - * @return boolean + * @return bool */ public static function verify_nonce_post($name, $action) { @@ -127,9 +127,9 @@ public static function sanitize($value, $sanitize) * Properly strip all HTML tags including script and style * * @since 1.0 - * @param mixed String|Array $value - * @param boolean $remove_breaks - * @return mixed String|Array + * @param mixed string|array $value + * @param bool $remove_breaks + * @return mixed string|array */ public static function rm_tags($value, $remove_breaks = false) { @@ -150,7 +150,7 @@ public static function rm_tags($value, $remove_breaks = false) * @since 1.0 * @param string $value * @param string $search - * @return boolean + * @return bool */ public static function indexof($value, $search) { @@ -161,12 +161,13 @@ public static function indexof($value, $search) * Verify request ajax * * @since 1.0 - * @return boolean + * @return bool */ public static function is_request_ajax() { return ( strtolower(self::server('HTTP_X_REQUESTED_WITH')) === 'xmlhttprequest' - || (0 === strpos(self::server('QUERY_STRING'), 'wc-ajax'))); + || (0 === strpos(self::server('QUERY_STRING'), 'wc-ajax')) + || strtolower(self::server('HTTP_X_REQUEST_TYPE')) === 'ajax'); } /** @@ -285,7 +286,7 @@ public static function get_component($name) * Check is plugin settings page * * @since 1.0 - * @return boolean + * @return bool */ public static function is_settings_page() { @@ -347,7 +348,7 @@ public static function format_order_price_with_currency_symbol($price) * * @since 1.0 * @param mixed string|float|int $price - * @return integer + * @return int */ public static function format_desnormalized_order_price($price) { @@ -397,7 +398,6 @@ public static function format_order_price_to_view($price) * @since 1.0 * @param mixed $data * @param string $log_name - * @return void */ public static function log($data, $log_name = 'debug') { @@ -508,7 +508,7 @@ public static function format_document($document) * * @since 1.0 * @param string $meta_value - * @return integer + * @return int */ public static function get_order_by_meta_value($meta_value) { diff --git a/src/Model/CardInstallments.php b/src/Model/CardInstallments.php index e7b0da83..e7745973 100644 --- a/src/Model/CardInstallments.php +++ b/src/Model/CardInstallments.php @@ -78,9 +78,14 @@ public function getInstallmentsByType($total, $flag = false) */ public function getOptions($total, $maxInstallments, $minAmount, $interest, $interestIncrease, $noInterest) { + $firstOptionLabel = __('1x', 'woo-pagarme-payments'); + $firstOptionContent = __('1x', 'woo-pagarme-payments') . ' (' . wc_price($total) . ')'; $options[] = [ 'value' => 1, - 'content' => __('1x', 'woo-pagarme-payments') . ' (' . wc_price($total) . ')' + 'content' => $firstOptionContent, + 'installmentPrice' => $this->formatPrice($total), + 'optionLabel' => $firstOptionLabel, + 'finalPrice' => $this->formatPrice($total), ]; $interestBase = $interest; for ($times = 2; $times <= $maxInstallments; $times++) { @@ -107,11 +112,17 @@ public function getOptions($total, $maxInstallments, $minAmount, $interest, $int wc_price($value) ); - $text .= $this->verifyInterest($times, $noInterest, $interest); + $extraText = $this->verifyInterest($times, $noInterest, $interest); + + $text .= $extraText; $options[] = [ 'value' => $times, - 'content' => $text + 'content' => $text, + 'installmentPrice' => $this->formatPrice($price), + 'optionLabel' => __('of', 'woo-pagarme-payments'), + 'finalPrice' => $this->formatPrice($value), + 'extraText' => $extraText ]; } return $options; @@ -198,4 +209,9 @@ public function getMaxCcInstallments($type, $flag) } return $this->config->getCcInstallmentsMaximum(); } + + private function formatPrice($price) + { + return $price * 100; + } } diff --git a/src/Model/Checkout.php b/src/Model/Checkout.php index 332493a8..0469e34e 100644 --- a/src/Model/Checkout.php +++ b/src/Model/Checkout.php @@ -132,8 +132,9 @@ public function process(WC_Order $wc_order = null, string $type = CheckoutTypes: $order = new Order($wc_order->get_id()); $totalWithInstallments = $order->getTotalAmountByCharges(); $order->pagarme_card_tax = $order->calculateInstallmentFee($totalWithInstallments, $wc_order->get_total()); - $order->wc_order->set_total($this->getTotalValue($wc_order, $totalWithInstallments)); + $order->getWcOrder()->set_total($this->getTotalValue($wc_order, $totalWithInstallments)); $order->payment_method = $fields['payment_method']; + $this->addAuthenticationOnMetaData($order, $fields); WC()->cart->empty_cart(); if ($response) { do_action("on_pagarme_response", $wc_order->get_id(), $response); @@ -171,6 +172,15 @@ private function convertCheckoutObject(PaymentRequestInterface $paymentRequest) if ($value = $card->getWalletId()) { $fields['card_id'] = $value; } + + $authentication = $card->getAuthentication(); + + if (!empty($authentication)) { + $fields['authentication'] = json_decode( + stripslashes($authentication), + true + ); + } } else { if ($orderValue = $card->getOrderValue()) { $fields['card_order_value' . $key] = $orderValue; @@ -203,6 +213,14 @@ private function addInstallmentsOnMetaData(&$order, $fields) } } + private function addAuthenticationOnMetaData(&$order, $fields) + { + if (!array_key_exists('authentication', $fields)) { + return; + } + $order->pagarme_tds_authentication = json_encode($fields["authentication"]); + } + private function extractMulticustomers(array &$fields, PaymentRequestInterface $paymentRequest) { foreach ($paymentRequest->getData() as $method => $data) { diff --git a/src/Model/Config.php b/src/Model/Config.php index c2273faa..f489d40c 100644 --- a/src/Model/Config.php +++ b/src/Model/Config.php @@ -11,13 +11,14 @@ namespace Woocommerce\Pagarme\Model; -use Pagarme\Core\Hub\Services\HubIntegrationService; -use Pagarme\Core\Middle\Model\Account\PaymentEnum; use Woocommerce\Pagarme\Core; -use Woocommerce\Pagarme\Model\Config\PagarmeCoreConfigManagement; -use Woocommerce\Pagarme\Model\Config\Source\EnvironmentsTypes; +use Pagarme\Core\Kernel\Services\MoneyService; use Woocommerce\Pagarme\Model\Data\DataObject; +use Pagarme\Core\Middle\Model\Account\PaymentEnum; +use Pagarme\Core\Hub\Services\HubIntegrationService; use Woocommerce\Pagarme\Model\Serialize\Serializer\Json; +use Woocommerce\Pagarme\Model\Config\Source\EnvironmentsTypes; +use Woocommerce\Pagarme\Model\Config\PagarmeCoreConfigManagement; use Woocommerce\Pagarme\Concrete\WoocommerceCoreSetup as CoreSetup; defined( 'ABSPATH' ) || exit; @@ -333,6 +334,29 @@ public function isVoucherEnabled() return $this->isEnabled('enable_voucher'); } + public function isTdsEnabled() + { + return $this->isEnabled('tds_enabled'); + } + + public function getTdsMinAmount() + { + $tdsMinAmount = $this->getData('tds_min_amount'); + if (empty($tdsMinAmount)) { + return 0; + } + if (is_string($tdsMinAmount) && ctype_digit($tdsMinAmount)) { + return intval($tdsMinAmount); + } + if(is_int($tdsMinAmount)) { + return $tdsMinAmount; + } + + $moneyService = new MoneyService(); + $tdsMinAmount = $moneyService->removeSeparators($tdsMinAmount); + return $moneyService->centsToFloat($tdsMinAmount); + } + public function isAnyBilletMethodEnabled() { return $this->isBilletEnabled() diff --git a/src/Model/FeatureCompatibilization.php b/src/Model/FeatureCompatibilization.php index 83fc5867..601bfb5c 100644 --- a/src/Model/FeatureCompatibilization.php +++ b/src/Model/FeatureCompatibilization.php @@ -63,11 +63,7 @@ public function addSupportedBlocks() ClassFinder::RECURSIVE_MODE ); - $abstracBlockKey = array_search(AbstractPaymentMethodBlock::class, $blockClasses); - if ($abstracBlockKey !== false) { - unset($blockClasses[$abstracBlockKey]); - } - + $blockClasses = array_filter($blockClasses, [$this, 'filterAbstractClasses']); $blockClasses = preg_filter('/^/', '\\', $blockClasses); add_action( @@ -80,4 +76,9 @@ function(\Automattic\WooCommerce\Blocks\Payments\PaymentMethodRegistry $paymentM } ); } + + public function filterAbstractClasses($className) + { + return strpos($className, 'Abstract') === false; + } } diff --git a/src/Model/Order.php b/src/Model/Order.php index f54eeb11..9eb4cda3 100644 --- a/src/Model/Order.php +++ b/src/Model/Order.php @@ -59,7 +59,7 @@ class Order extends Meta public function __construct($ID = false) { parent::__construct($ID); - $this->wc_order = $this->getWcOrder($ID); + $this->wc_order = $this->getWcOrderById($ID); $this->settings = new Config(); } /** phpcs:enable */ @@ -257,7 +257,12 @@ public function isPagarmePaymentMethod() return false; } - public function getWcOrder($id = false) + public function getWcOrder() + { + return $this->wc_order; + } + + private function getWcOrderById($id = false) { global $theorder; if(empty($theorder) || ((int)$id !== $theorder->get_id() && $id !== false)) { diff --git a/src/Model/Payment/CreditCard.php b/src/Model/Payment/CreditCard.php index 9e7faa43..b8acd187 100644 --- a/src/Model/Payment/CreditCard.php +++ b/src/Model/Payment/CreditCard.php @@ -14,6 +14,7 @@ use stdClass; use WC_Order; use Woocommerce\Pagarme\Helper\Utils; +use Woocommerce\Pagarme\Model\Subscription; use Woocommerce\Pagarme\Model\Payment\CreditCard\Brands; use Woocommerce\Pagarme\Model\Payment\CreditCard\BrandsInterface; @@ -68,6 +69,13 @@ public function getConfigDataProvider() $brand = new $class; $jsConfigProvider['brands'][$brand->getBrandCode()] = $brand->getConfigDataProvider(); } + $jsConfigProvider['tdsEnabled'] = Subscription::hasSubscriptionProductInCart() + || Subscription::isChangePaymentSubscription() + ? false + : $this->getConfig()->isTdsEnabled(); + if ($jsConfigProvider['tdsEnabled']) { + $jsConfigProvider['tdsMinAmount'] = $this->getConfig()->getTdsMinAmount(); + } return $jsConfigProvider; } diff --git a/src/Model/Subscription.php b/src/Model/Subscription.php index fc58ac05..4e69fd66 100644 --- a/src/Model/Subscription.php +++ b/src/Model/Subscription.php @@ -469,7 +469,7 @@ public function hasOneInstallmentPeriodInCart(): bool { $cartProducts = WC()->cart->cart_contents; $productsPeriods = []; - foreach ($cartProducts as $product) { + foreach ($cartProducts ?? [] as $product) { $productsPeriods[] = WC_Subscriptions_Product::get_period($product['product_id']); } diff --git a/src/Service/TdsTokenService.php b/src/Service/TdsTokenService.php new file mode 100644 index 00000000..cf11d5d7 --- /dev/null +++ b/src/Service/TdsTokenService.php @@ -0,0 +1,44 @@ +coreAuth = new CoreAuth(''); + $this->config = $config; + } + + /** + * @param string $accountId + * @return string + */ + public function getTdsToken($accountId) + { + $tdsTokenProxy = new TdsTokenProxy($this->coreAuth); + $environment = 'live'; + if ($this->config->getIsSandboxMode()) { + $environment = 'test'; + } + return $tdsTokenProxy->getTdsToken($environment, $accountId)->tdsToken; + } +} diff --git a/templates/adminhtml/system/config/form/field/hub/integration.phtml b/templates/adminhtml/system/config/form/field/hub/integration.phtml index be6db09d..1bf5d9d0 100644 --- a/templates/adminhtml/system/config/form/field/hub/integration.phtml +++ b/templates/adminhtml/system/config/form/field/hub/integration.phtml @@ -42,7 +42,7 @@ $success = 'Integration keys successfully removed. Reload the page.'; const content = { title: '', text: '', - type: 'info', + icon: 'info', showCancelButton: true, confirmButtonColor: '#3085d6', cancelButtonColor: '#d33', @@ -51,9 +51,9 @@ $success = 'Integration keys successfully removed. Reload the page.'; }; $('#pagarme-hub-desintegration-link').on('click', function (e) { try { - swal(content).then((result) => { - if (result) { - swal({ + swal.fire(content).then((result) => { + if (result.isConfirmed) { + swal.fire({ title: ' ', text: '', allowOutsideClick: false @@ -68,29 +68,35 @@ $success = 'Integration keys successfully removed. Reload the page.'; force: true }), success: function (response) { - swal( - '', - '', - 'success' - ) + swal.fire({ + title: '', + text: '', + icon: 'success' + }); document.location.reload(true); }, fail: function (response) { - swal( - '', - '', - 'error' - ) + swal.fire({ + title: '', + text: '', + icon: 'error' + }); } }); } }); } catch (e) { - swal( - '', - '', - 'error' - ) + swal({ + title: '', + text: '', + icon: 'error' + }); } }); }); diff --git a/templates/checkout/default.php b/templates/checkout/default.php index 4bbbd937..b70eb7b1 100644 --- a/templates/checkout/default.php +++ b/templates/checkout/default.php @@ -17,12 +17,6 @@ global $woocommerce; -wp_localize_script( - 'pagarme-checkout-card', - 'wc_pagarme_checkout', - ['config' => $this->getConfigDataProvider()] -); - $wc_api = $this->getHomeUrl(); ?>
        diff --git a/templates/checkout/form/billet.phtml b/templates/checkout/form/billet.phtml index bb4d58c2..3a15788c 100644 --- a/templates/checkout/form/billet.phtml +++ b/templates/checkout/form/billet.phtml @@ -24,7 +24,7 @@ if (!function_exists('add_action')) { diff --git a/templates/checkout/form/card.phtml b/templates/checkout/form/card.phtml index 2f7d672f..1ee434a5 100644 --- a/templates/checkout/form/card.phtml +++ b/templates/checkout/form/card.phtml @@ -46,7 +46,7 @@ wp_localize_script( @@ -63,7 +63,7 @@ wp_localize_script(
        getCompoenent() ?> data-pagarmecheckout-app-id="getConfig()->getPublicKey()); ?>"> -
        +

        + data-required="true" class="input-text" data-pagarme-element="holder_name">

        - + + data-required="true" data-pagarme-element="number"> + data-pagarme-element="brand-input"/>

        @@ -133,7 +133,7 @@ wp_localize_script( data-element="document-holder" data-mask="000.000.000-00" class="input-text wc-credit-card-form-card-cvv pagarme-card-form-holder-number" maxlength="14" - placeholder="CPF" data-required="true" data-pagarmecheckout-element="holder_document"> + placeholder="CPF" data-required="true" data-pagarme-element="holder_document">

        createBlock( diff --git a/templates/checkout/form/card/tds.phtml b/templates/checkout/form/card/tds.phtml new file mode 100644 index 00000000..c96c2fed --- /dev/null +++ b/templates/checkout/form/card/tds.phtml @@ -0,0 +1,24 @@ +canInitTds()) { + return; +} + +?> + +
        + +
        + \ No newline at end of file diff --git a/templates/checkout/form/field/card-save.phtml b/templates/checkout/form/field/card-save.phtml index 42a5f43b..1c847c74 100644 --- a/templates/checkout/form/field/card-save.phtml +++ b/templates/checkout/form/field/card-save.phtml @@ -1,4 +1,5 @@ getIsEnableWallet()) : ?>

        - + \ No newline at end of file diff --git a/templates/checkout/payment/credit-card.phtml b/templates/checkout/payment/credit-card.phtml index 54ecdc85..bd1381eb 100644 --- a/templates/checkout/payment/credit-card.phtml +++ b/templates/checkout/payment/credit-card.phtml @@ -1,4 +1,5 @@ createBlock( 'qty_cards' => $this->getQtyCards() ] )->toHtml(); + +$this->createBlock( + '\Woocommerce\Pagarme\Block\Checkout\Form\Tds', + 'pagarme.checkout.form.tds', + [ + 'payment_instance' => $this->getPaymentInstance() + ] +)->toHtml(); diff --git a/templates/order/charge.phtml b/templates/order/charge.phtml index fadf32c6..677aac88 100644 --- a/templates/order/charge.phtml +++ b/templates/order/charge.phtml @@ -29,7 +29,8 @@ if (!function_exists('add_action')) { $this->getTransactionClass($transaction), 'pagarme.order.charge.transaction', [ - 'transaction' => $transaction + 'transaction' => $transaction, + 'orderId' => $this->getCharge()->getCode() ] )->toHtml(); ?> diff --git a/tests/Concrete/WoocommercePlatformOrderDecoratorTest.php b/tests/Concrete/WoocommercePlatformOrderDecoratorTest.php new file mode 100644 index 00000000..40b709bb --- /dev/null +++ b/tests/Concrete/WoocommercePlatformOrderDecoratorTest.php @@ -0,0 +1,103 @@ +shouldReceive('get_payment_data') + ->andReturn([ + [ + 'payment_method' => 'credit_card', + 'credit_card' => [ + 'installments' => 1, + 'statement_descriptor' => '', + 'capture' => null, + 'card' => [ + 'billing_address' => [ + 'street' => 'test street', + 'complement' => 'test', + 'number' => '123', + 'zip_code' => '1234567', + 'neighborhood' => 'neighborhood', + 'city' => 'city', + 'state' => 'SP', + 'country' => 'BR', + ], + 'card_token' => 'token_test' + ] + ], + 'amount' => 1000 + ] + ]); + + $paymentMethodName = 'credit_card'; + + $formData = [ + 'payment_method' => $paymentMethodName, + 'brand' => 'visa', + 'installments' => 1, + 'authentication' => ['trans_status' => 'Y', 'tds_server_trans_id' => 'test-trans-id'], + 'pagarmetoken1' => 'token_test' + ]; + + $platformOrderDecorator = new WoocommercePlatformOrderDecorator($formData, 'credit_card'); + + $customerIdMock = Mockery::mock(CustomerId::class); + $customerIdMock->shouldReceive('getValue') + ->andReturn(1); + + $customer = new Customer(); + $customerMock = Mockery::mock($customer); + $customerMock->shouldReceive('getPagarmeId') + ->andReturn($customerIdMock); + $platformOrderDecorator->setCustomer($customerMock); + + $platformOrderMock = Mockery::mock(WC_Order::class); + $platformOrderMock->shouldReceive('get_total') + ->andReturn(10); + $platformOrderMock->shouldReceive('get_total_tax') + ->andReturn(0); + + $platformOrderDecorator->setPlatformOrder($platformOrderMock); + + + $paymentFactoryMock->shouldReceive('createFromJson') + ->withArgs(function ($data) { + $formatedData = json_decode($data, true); + + $card = current($formatedData[AbstractCreditCardPayment::getBaseCode()]); + + return $card['authentication']['status'] === 'Y' + && $card['authentication']['threeDSecure']['transactionId'] === 'test-trans-id'; + }) + ->andReturn([]); + + $result = $platformOrderDecorator->getPaymentMethodCollection(); + + $this->assertIsArray($result); + } +} diff --git a/tests/Model/CheckoutTest.php b/tests/Model/CheckoutTest.php new file mode 100644 index 00000000..88a0bcc4 --- /dev/null +++ b/tests/Model/CheckoutTest.php @@ -0,0 +1,149 @@ +shouldReceive('getBrand') + ->andReturn('visa'); + $cardMock->shouldReceive('getInstallment') + ->andReturn(1); + $cardMock->shouldReceive('getAuthentication') + ->andReturn("{\"trans_status\":\"Y\",\"tds_server_trans_id\":\"test-trans-id\"}"); + $cardMock->shouldReceive('getToken') + ->andReturn('token_test'); + $cardMock->shouldReceive('getOrderValue') + ->andReturnFalse(); + $cardMock->shouldReceive('getSaveCard') + ->andReturnFalse(); + $cardMock->shouldReceive('getWalletId') + ->andReturnFalse(); + + $paymentRequestMock = Mockery::mock(PaymentRequest::class); + $paymentRequestMock->shouldReceive('getPaymentMethod') + ->andReturn('credit_card'); + $paymentRequestMock->shouldReceive('getCards') + ->andReturn([$cardMock]); + $paymentRequestMock->shouldReceive('getData') + ->andReturn([]); + + $_POST[PaymentRequestInterface::PAGARME_PAYMENT_REQUEST_KEY] = $paymentRequestMock; + + $subscriptionMock = Mockery::mock('alias:Woocommerce\Pagarme\Model\Subscription'); + $subscriptionMock->shouldReceive('getRecurrenceCycle') + ->andReturnNull(); + + $orderIdMock = Mockery::mock(OrderId::class); + $orderIdMock->shouldReceive('getValue') + ->andReturn(1); + + $order = new Order(); + $orderMock = Mockery::mock($order); + $orderMock->shouldReceive('getPagarmeId') + ->andReturn($orderIdMock); + + $orderMock->shouldReceive('getStatus') + ->andReturn(OrderStatus::paid()); + + $wcOrderMock = Mockery::mock(WC_Order::class); + $wcOrderMock->shouldReceive('get_total') + ->andReturn(10); + $wcOrderMock->shouldReceive('get_id') + ->andReturn(1); + $wcOrderMock->shouldReceive('set_total') + ->andReturnSelf(); + + $ordersMock->shouldReceive('create_order') + ->withArgs(function ($wcOrder, $paymentMethod, $fields) use ($wcOrderMock) { + return $wcOrder === $wcOrderMock + && $paymentMethod === 'credit_card' + && $fields['authentication']['trans_status'] === 'Y' + && $fields['authentication']['tds_server_trans_id'] === 'test-trans-id'; + }) + ->andReturn($orderMock); + + $orderModelMock = Mockery::mock('overload:Woocommerce\Pagarme\Model\Order'); + $orderModelMock->shouldReceive('getTotalAmountByCharges') + ->andReturn(10); + $orderModelMock->shouldReceive('calculateInstallmentFee') + ->andReturn(0); + $orderModelMock->shouldReceive('update_by_pagarme_status') + ->andReturnSelf(); + $orderModelMock->shouldReceive('getWcOrder') + ->andReturn($wcOrderMock); + + $wcCheckoutMock = Mockery::mock(WC_Checkout::class); + $wcCheckoutMock->shouldReceive('empty_cart') + ->andReturnSelf(); + $woocommerce = new stdClass(); + $woocommerce->cart = $wcCheckoutMock; + Brain\Monkey\Functions\stubs([ + 'WC' => $woocommerce, + ]); + + Brain\Monkey\Functions\stubs([ + 'wp_strip_all_tags', + ]); + + Brain\Monkey\Functions\expect('add_action') + ->once(); + + Brain\Monkey\Functions\expect('do_action') + ->once(); + + $checkout = new Checkout($gatewayMock, $configMock, $ordersMock, $wooOrderRepositoryMock); + + $this->assertTrue($checkout->process($wcOrderMock)); + } +} diff --git a/tests/Model/CoreTest.php b/tests/Model/CoreTest.php new file mode 100644 index 00000000..21d44740 --- /dev/null +++ b/tests/Model/CoreTest.php @@ -0,0 +1,65 @@ +shouldReceive('get_site_url')->andReturn($domain); + $utils->shouldReceive('add_prefix')->andReturn('pagarme-webhook'); + + $getUrl = Core::get_webhook_url(); + + $this->assertEquals($webhookLink, $getUrl); + } + + public function testGetWebhookWithoutCustomUrlWithPath() + { + $domain = "https://mycustomdomain.test"; + $domainWithPath = "https://mycustomdomain.test/app/customPath"; + $webhookLink = $domain . "/wc-api/pagarme-webhook/"; + + $utils = Mockery::mock("alias:Woocommerce\Pagarme\Helper\Utils"); + $utils->shouldReceive('get_site_url')->andReturn($domainWithPath); + $utils->shouldReceive('add_prefix')->andReturn('pagarme-webhook'); + + $getUrl = Core::get_webhook_url(); + + $this->assertEquals($webhookLink, $getUrl); + } + public function testGetWebhookWithoutCustomUrl() + { + $customDomain = "https://mycustomdomain.test"; + $webhookLink = $customDomain . "/wc-api/pagarme-webhook/"; + + $utils = Mockery::mock("alias:Woocommerce\Pagarme\Helper\Utils"); + $utils->shouldReceive('get_site_url')->andReturn($customDomain); + $utils->shouldReceive('add_prefix')->andReturn('pagarme-webhook'); + + $getUrl = Core::get_webhook_url($customDomain); + + $this->assertEquals($webhookLink, $getUrl); + } +} diff --git a/tests/Model/CustomerTest.php b/tests/Model/CustomerTest.php index ead8e510..a13a6796 100644 --- a/tests/Model/CustomerTest.php +++ b/tests/Model/CustomerTest.php @@ -333,4 +333,4 @@ public function testGetPagarmeCustomerIdShouldReturnPagarmeCustomerIdValue() $this->assertSame($id, $responsePagarmeCustomerId); } -} \ No newline at end of file +} diff --git a/tests/Service/AccountServiceTest.php b/tests/Service/AccountServiceTest.php index 91678df5..7e538e9d 100644 --- a/tests/Service/AccountServiceTest.php +++ b/tests/Service/AccountServiceTest.php @@ -4,13 +4,16 @@ use Mockery; use Pagarme\Core\Middle\Model\Account\PaymentEnum; -use Pagarme\Core\Middle\Proxy\AccountProxy; use PagarmeCoreApiLib\Models\GetAccountResponse; use PHPUnit\Framework\TestCase; use Woocommerce\Pagarme\Model\Config; use Woocommerce\Pagarme\Model\CoreAuth; use Woocommerce\Pagarme\Service\AccountService; +/** + * @runTestsInSeparateProcesses + * @preserveGlobalState disabled + */ class AccountServiceTest extends TestCase { public function tearDown(): void diff --git a/tests/Service/TdsTokenServiceTest.php b/tests/Service/TdsTokenServiceTest.php new file mode 100644 index 00000000..8667d6be --- /dev/null +++ b/tests/Service/TdsTokenServiceTest.php @@ -0,0 +1,69 @@ +shouldReceive('getIsSandboxMode') + ->andReturnFalse(); + + $tdsTokenService = new TdsTokenService($configMock); + + $token = 'tokentds'; + $getTdsTokenResponseMock = Mockery::mock(GetTdsTokenResponse::class); + $getTdsTokenResponseMock->tdsToken = $token; + + $tdsTokenProxyMock = Mockery::mock('overload:Pagarme\Core\Middle\Proxy\TdsTokenProxy'); + + + $accountId = 'acc_test'; + $tdsTokenProxyMock->shouldReceive('getTdsToken') + ->with('live', $accountId) + ->andReturn($getTdsTokenResponseMock); + + $this->assertSame($token, $tdsTokenService->getTdsToken($accountId)); + } + + public function testShoudGetTdsTokenWithTestEnviroment() + { + Mockery::mock('overload:Woocommerce\Pagarme\Model\CoreAuth'); + $configMock = Mockery::mock(Config::class); + $configMock->shouldReceive('getIsSandboxMode') + ->andReturnTrue(); + + $tdsTokenService = new TdsTokenService($configMock); + + $token = 'tokentds'; + $getTdsTokenResponseMock = Mockery::mock(GetTdsTokenResponse::class); + $getTdsTokenResponseMock->tdsToken = $token; + + $tdsTokenProxyMock = Mockery::mock('overload:Pagarme\Core\Middle\Proxy\TdsTokenProxy'); + + + $accountId = 'acc_test'; + $tdsTokenProxyMock->shouldReceive('getTdsToken') + ->with('test', $accountId) + ->andReturn($getTdsTokenResponseMock); + + $this->assertSame($token, $tdsTokenService->getTdsToken($accountId)); + } +} diff --git a/vendor/composer/autoload_psr4.php b/vendor/composer/autoload_psr4.php index d6d9c42c..849225fc 100644 --- a/vendor/composer/autoload_psr4.php +++ b/vendor/composer/autoload_psr4.php @@ -7,6 +7,7 @@ return array( 'apimatic\\jsonmapper\\' => array($vendorDir . '/apimatic/jsonmapper/src'), + 'Woocommerce\\Pagarme\\Tests\\' => array($baseDir . '/tests'), 'Woocommerce\\Pagarme\\' => array($baseDir . '/src'), 'Psr\\Log\\' => array($vendorDir . '/psr/log/Psr/Log'), 'Pagarme\\Core\\Test\\Mock\\' => array($vendorDir . '/pagarme/ecommerce-module-core/tests/mock'), diff --git a/vendor/composer/autoload_static.php b/vendor/composer/autoload_static.php index 89229c93..cbbe89fa 100644 --- a/vendor/composer/autoload_static.php +++ b/vendor/composer/autoload_static.php @@ -13,6 +13,7 @@ class ComposerStaticInitbb567e266966327c41fd47379c4c230d ), 'W' => array ( + 'Woocommerce\\Pagarme\\Tests\\' => 26, 'Woocommerce\\Pagarme\\' => 20, ), 'P' => @@ -39,6 +40,10 @@ class ComposerStaticInitbb567e266966327c41fd47379c4c230d array ( 0 => __DIR__ . '/..' . '/apimatic/jsonmapper/src', ), + 'Woocommerce\\Pagarme\\Tests\\' => + array ( + 0 => __DIR__ . '/../..' . '/tests', + ), 'Woocommerce\\Pagarme\\' => array ( 0 => __DIR__ . '/../..' . '/src', diff --git a/vendor/composer/installed.json b/vendor/composer/installed.json index 9ee3d2b5..7a957026 100644 --- a/vendor/composer/installed.json +++ b/vendor/composer/installed.json @@ -305,23 +305,23 @@ }, { "name": "pagarme/ecommerce-module-core", - "version": "2.3.1", - "version_normalized": "2.3.1.0", + "version": "2.4.1", + "version_normalized": "2.4.1.0", "source": { "type": "git", "url": "https://github.com/pagarme/ecommerce-module-core.git", - "reference": "9c9e927cea9b1bf90a499d2146f042f1f7f1c921" + "reference": "3e75e5365882c6806f2ac76e6901ee17815d101e" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/pagarme/ecommerce-module-core/zipball/9c9e927cea9b1bf90a499d2146f042f1f7f1c921", - "reference": "9c9e927cea9b1bf90a499d2146f042f1f7f1c921", + "url": "https://api.github.com/repos/pagarme/ecommerce-module-core/zipball/3e75e5365882c6806f2ac76e6901ee17815d101e", + "reference": "3e75e5365882c6806f2ac76e6901ee17815d101e", "shasum": "" }, "require": { "ext-json": "*", "monolog/monolog": "<3", - "pagarme/pagarmecoreapi": "v5.6.3", + "pagarme/pagarmecoreapi": "v5.6.4", "php": ">=7.1" }, "require-dev": { @@ -330,7 +330,7 @@ "nesbot/carbon": "1.39.0", "phpunit/phpunit": "^5 | ^6 | ^7 | ^8 | ^9" }, - "time": "2023-11-14T15:38:42+00:00", + "time": "2024-03-07T13:35:21+00:00", "type": "library", "installation-source": "dist", "autoload": { @@ -351,23 +351,23 @@ ], "description": "Core component for Pagar.me e-commerce platform modules.", "support": { - "source": "https://github.com/pagarme/ecommerce-module-core/tree/2.3.1" + "source": "https://github.com/pagarme/ecommerce-module-core/tree/2.4.1" }, "install-path": "../pagarme/ecommerce-module-core" }, { "name": "pagarme/pagarmecoreapi", - "version": "v5.6.3", - "version_normalized": "5.6.3.0", + "version": "v5.6.4", + "version_normalized": "5.6.4.0", "source": { "type": "git", "url": "https://github.com/pagarme/pagarme-core-api-php.git", - "reference": "49e0d222c50c69ac3e0debea9b69202e6555d3ef" + "reference": "acab7709b2579221417946b261f6c24710604eb8" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/pagarme/pagarme-core-api-php/zipball/49e0d222c50c69ac3e0debea9b69202e6555d3ef", - "reference": "49e0d222c50c69ac3e0debea9b69202e6555d3ef", + "url": "https://api.github.com/repos/pagarme/pagarme-core-api-php/zipball/acab7709b2579221417946b261f6c24710604eb8", + "reference": "acab7709b2579221417946b261f6c24710604eb8", "shasum": "" }, "require": { @@ -381,7 +381,7 @@ "require-dev": { "squizlabs/php_codesniffer": "^2.7" }, - "time": "2023-09-28T18:22:12+00:00", + "time": "2023-12-15T13:58:12+00:00", "type": "library", "installation-source": "dist", "autoload": { @@ -410,7 +410,7 @@ ], "support": { "issues": "https://github.com/pagarme/pagarme-core-api-php/issues", - "source": "https://github.com/pagarme/pagarme-core-api-php/tree/v5.6.3" + "source": "https://github.com/pagarme/pagarme-core-api-php/tree/v5.6.4" }, "install-path": "../pagarme/pagarmecoreapi" }, diff --git a/vendor/composer/installed.php b/vendor/composer/installed.php index c5b4bf7b..45e1d8fe 100644 --- a/vendor/composer/installed.php +++ b/vendor/composer/installed.php @@ -56,18 +56,18 @@ 'dev_requirement' => false, ), 'pagarme/ecommerce-module-core' => array( - 'pretty_version' => '2.3.1', - 'version' => '2.3.1.0', - 'reference' => '9c9e927cea9b1bf90a499d2146f042f1f7f1c921', + 'pretty_version' => '2.4.1', + 'version' => '2.4.1.0', + 'reference' => '3e75e5365882c6806f2ac76e6901ee17815d101e', 'type' => 'library', 'install_path' => __DIR__ . '/../pagarme/ecommerce-module-core', 'aliases' => array(), 'dev_requirement' => false, ), 'pagarme/pagarmecoreapi' => array( - 'pretty_version' => 'v5.6.3', - 'version' => '5.6.3.0', - 'reference' => '49e0d222c50c69ac3e0debea9b69202e6555d3ef', + 'pretty_version' => 'v5.6.4', + 'version' => '5.6.4.0', + 'reference' => 'acab7709b2579221417946b261f6c24710604eb8', 'type' => 'library', 'install_path' => __DIR__ . '/../pagarme/pagarmecoreapi', 'aliases' => array(), diff --git a/vendor/pagarme/ecommerce-module-core/catalog-info.yaml b/vendor/pagarme/ecommerce-module-core/catalog-info.yaml deleted file mode 100644 index 4989ab4b..00000000 --- a/vendor/pagarme/ecommerce-module-core/catalog-info.yaml +++ /dev/null @@ -1,21 +0,0 @@ ---- -apiVersion: backstage.io/v1alpha1 -kind: Component -metadata: - name: ECOMMERCE MODULE CORE - title: ECOMMERCE MODULE CORE - description: Modulo opensource para unificação de integração para a P&G - namespace: pagarme-psp - annotations: - legacy.stone.tech/owner-email: opensource@pagar.me - legacy.stone.tech/prod-date: 2021-03-30 - labels: - legacy.stone.tech/internal-user-auth-base: not-applicable - legacy.stone.tech/access-request-type: not-applicable - legacy.stone.tech/handle-lgpd: false - legacy.stone.tech/customer-auth-method: not-applicable - stone.tech/endpoint-type: none -spec: - type: library - lifecycle: production - owner: pagarme/opensource-apps-team \ No newline at end of file diff --git a/vendor/pagarme/ecommerce-module-core/composer.json b/vendor/pagarme/ecommerce-module-core/composer.json index 9219d50f..f3afe9d1 100644 --- a/vendor/pagarme/ecommerce-module-core/composer.json +++ b/vendor/pagarme/ecommerce-module-core/composer.json @@ -2,7 +2,7 @@ "name": "pagarme/ecommerce-module-core", "description": "Core component for Pagar.me e-commerce platform modules.", "license": "MIT", - "version": "2.3.1", + "version": "2.4.1", "authors": [ { "name":"Open Source Team" @@ -12,7 +12,7 @@ "require": { "php": ">=7.1", "monolog/monolog": "<3", - "pagarme/pagarmecoreapi": "v5.6.3", + "pagarme/pagarmecoreapi": "v5.6.4", "ext-json": "*" }, "require-dev": { diff --git a/vendor/pagarme/ecommerce-module-core/src/Kernel/Aggregates/Order.php b/vendor/pagarme/ecommerce-module-core/src/Kernel/Aggregates/Order.php index c7aac1ee..cce93df5 100644 --- a/vendor/pagarme/ecommerce-module-core/src/Kernel/Aggregates/Order.php +++ b/vendor/pagarme/ecommerce-module-core/src/Kernel/Aggregates/Order.php @@ -104,6 +104,24 @@ public function getCharges() return $this->charges; } + + /** + * + * @return Transaction|null + */ + public function getPixOrBilletTransaction() + { + foreach ($this->getCharges() as $charge) { + foreach ($charge->getTransactions() as $transaction) { + $type = $transaction->getTransactionType()->getType(); + if ($type === 'pix' || $type === 'boleto') { + return $transaction; + } + } + } + return null; + } + public function applyOrderStatusFromCharges() { if (empty($this->getCharges())) { diff --git a/vendor/pagarme/ecommerce-module-core/src/Kernel/Services/LogService.php b/vendor/pagarme/ecommerce-module-core/src/Kernel/Services/LogService.php index 39e3e6d9..b4605104 100644 --- a/vendor/pagarme/ecommerce-module-core/src/Kernel/Services/LogService.php +++ b/vendor/pagarme/ecommerce-module-core/src/Kernel/Services/LogService.php @@ -98,7 +98,7 @@ public function exception(\Exception $exception) $logObject = $this->prepareObject($exception); $code = ' | Exception code: ' . $exception->getCode(); $this->monolog->error($exception->getMessage() . $code, $logObject); - + } catch (\Throwable $th) { //throw $th; } @@ -132,9 +132,6 @@ protected function setFileName() { $base = 'Pagarme_PaymentModule_' . date('Y-m-d'); $fileName = $this->path . DIRECTORY_SEPARATOR . $base; - if ($this->addHost) { - $fileName .= '_' . gethostname(); - } $fileName .= '.log'; $this->fileName = $fileName; } @@ -187,7 +184,9 @@ private function blurSensitiveData($logObject) } } return $logObject; - } catch (\Exception $e) {} + } catch (\Exception $e) { + $this->exception($e); + } } /** diff --git a/vendor/pagarme/ecommerce-module-core/src/Kernel/Services/OrderLogService.php b/vendor/pagarme/ecommerce-module-core/src/Kernel/Services/OrderLogService.php index 73ea0fc7..600b412a 100644 --- a/vendor/pagarme/ecommerce-module-core/src/Kernel/Services/OrderLogService.php +++ b/vendor/pagarme/ecommerce-module-core/src/Kernel/Services/OrderLogService.php @@ -16,7 +16,7 @@ public function orderInfo($orderCode, $message, $sourceObject = null) $orderMessage = "Order #$orderCode : $message"; parent::info($orderMessage, $sourceObject); } catch (\Throwable $throwable) { - + $this->orderException($throwable, $orderCode); } } diff --git a/vendor/pagarme/ecommerce-module-core/src/Kernel/Services/OrderService.php b/vendor/pagarme/ecommerce-module-core/src/Kernel/Services/OrderService.php index 21577910..ee1431ef 100644 --- a/vendor/pagarme/ecommerce-module-core/src/Kernel/Services/OrderService.php +++ b/vendor/pagarme/ecommerce-module-core/src/Kernel/Services/OrderService.php @@ -243,13 +243,6 @@ public function cancelAtPagarmeByPlatformOrder(PlatformOrderInterface $platformO public function createOrderAtPagarme(PlatformOrderInterface $platformOrder) { try { - $orderInfo = $this->getOrderInfo($platformOrder); - - $this->logService->orderInfo( - $platformOrder->getCode(), - 'Creating order.', - $orderInfo - ); //set pending $platformOrder->setState(OrderState::stateNew()); @@ -257,6 +250,11 @@ public function createOrderAtPagarme(PlatformOrderInterface $platformOrder) //build PaymentOrder based on platformOrder $paymentOrder = $this->extractPaymentOrderFromPlatformOrder($platformOrder); + $this->logService->orderInfo( + $platformOrder->getCode(), + 'Creating order.', + $paymentOrder + ); $i18n = new LocalizationService(); @@ -270,13 +268,13 @@ public function createOrderAtPagarme(PlatformOrderInterface $platformOrder) $this->logService->orderInfo( $platformOrder->getCode(), "Can't create order. - Force Create Order: {$forceCreateOrder} | Order or charge status failed", - $orderInfo + $paymentOrder ); $charges = $this->createChargesFromResponse($response); $errorMessages = $this->cancelChargesAtPagarme($charges); - $this->addChargeMessagesToLog($platformOrder, $orderInfo, $errorMessages); + $this->addChargeMessagesToLog($platformOrder, $paymentOrder, $errorMessages); $this->persistListChargeFailed($response); @@ -312,7 +310,7 @@ public function createOrderAtPagarme(PlatformOrderInterface $platformOrder) $this->logService->orderInfo( $platformOrder->getCode(), "Can't create order. - Force Create Order: {$forceCreateOrder} | Order or charge status failed", - $orderInfo + $paymentOrder ); $message = $i18n->getDashboard( "Can't create payment. " . @@ -326,7 +324,7 @@ public function createOrderAtPagarme(PlatformOrderInterface $platformOrder) $this->logService->orderInfo( $platformOrder->getCode(), $e->getMessage(), - $orderInfo + $paymentOrder ); $exceptionHandler = new ErrorExceptionHandler(); $paymentOrder = new PaymentOrder(); @@ -378,8 +376,6 @@ public function extractPaymentOrderFromPlatformOrder( $order->addPayment($payment); } - $orderInfo = $this->getOrderInfo($platformOrder); - /* This block was commented out because this validation is still problematic in the woocommerce module. TODO: we will need to make the module work with this code block. @@ -416,17 +412,6 @@ public function extractPaymentOrderFromPlatformOrder( return $order; } - /** - * @param PlatformOrderInterface $platformOrder - * @return \stdClass - */ - public function getOrderInfo(PlatformOrderInterface $platformOrder) - { - $orderInfo = new \stdClass(); - $orderInfo->grandTotal = $platformOrder->getGrandTotal(); - return $orderInfo; - } - private function responseHasNoChargesOrFailed($response) { return !isset($response['status']) || diff --git a/vendor/pagarme/ecommerce-module-core/src/Middle/Client.php b/vendor/pagarme/ecommerce-module-core/src/Middle/Client.php index e4644997..9943cc46 100644 --- a/vendor/pagarme/ecommerce-module-core/src/Middle/Client.php +++ b/vendor/pagarme/ecommerce-module-core/src/Middle/Client.php @@ -10,13 +10,16 @@ */ abstract class Client { + const BASE_URI = 'https://hubapi.pagar.me/'; + const DEFAULT_RESOURCE = 'core/v1'; + public $client; abstract public function getHubToken(); - public function __construct() + public function __construct($resource = self::DEFAULT_RESOURCE) { Configuration::$basicAuthPassword = ''; - Configuration::$BASEURI = 'https://hubapi.pagar.me/core/v1'; + Configuration::$BASEURI = self::BASE_URI . $resource; $this->client = $this->services(); } private function auth() diff --git a/vendor/pagarme/ecommerce-module-core/src/Middle/Proxy/TdsTokenProxy.php b/vendor/pagarme/ecommerce-module-core/src/Middle/Proxy/TdsTokenProxy.php new file mode 100644 index 00000000..3f91f3d0 --- /dev/null +++ b/vendor/pagarme/ecommerce-module-core/src/Middle/Proxy/TdsTokenProxy.php @@ -0,0 +1,28 @@ +client = $auth->services(); + } + + public function getTdsToken($environment, $accountId) + { + return $this->client->getTdsToken()->getToken( + $environment, + $accountId + ); + } + +} diff --git a/vendor/pagarme/ecommerce-module-core/src/Payment/Aggregates/Address.php b/vendor/pagarme/ecommerce-module-core/src/Payment/Aggregates/Address.php index 7a0b7bde..a692f65a 100644 --- a/vendor/pagarme/ecommerce-module-core/src/Payment/Aggregates/Address.php +++ b/vendor/pagarme/ecommerce-module-core/src/Payment/Aggregates/Address.php @@ -78,7 +78,7 @@ public function setNumber($number) $this->number = substr($numberWithoutLineBreaks, 0, 15); - if (empty($this->number)) { + if (empty($this->number) && ($this->number === null || !is_numeric(trim($this->number)))) { $inputName = $this->i18n->getDashboard('number'); $message = $this->i18n->getDashboard( diff --git a/vendor/pagarme/ecommerce-module-core/src/Payment/Aggregates/Customer.php b/vendor/pagarme/ecommerce-module-core/src/Payment/Aggregates/Customer.php index 6fd08da8..707110df 100644 --- a/vendor/pagarme/ecommerce-module-core/src/Payment/Aggregates/Customer.php +++ b/vendor/pagarme/ecommerce-module-core/src/Payment/Aggregates/Customer.php @@ -171,12 +171,12 @@ public function setAddress(?Address $address) } /** - * Specify data which should be serialized to JSON - * @link https://php.net/manual/en/jsonserializable.jsonserialize.php - * @return mixed data which can be serialized by json_encode, - * which is a value of any type other than a resource. - * @since 5.4.0 - */ + * Specify data which should be serialized to JSON + * @link https://php.net/manual/en/jsonserializable.jsonserialize.php + * @return mixed data which can be serialized by json_encode, + * which is a value of any type other than a resource. + * @since 5.4.0 + */ #[\ReturnTypeWillChange] public function jsonSerialize() { @@ -209,7 +209,7 @@ public function getTypeValue() public function getAddressToSDK() { if ($this->getAddress() !== null) { - return $this->getAddress()->convertToSDKRequest(); + return $this->getAddress()->convertToSDKRequest(); } return null; } @@ -217,7 +217,7 @@ public function getAddressToSDK() public function getPhonesToSDK() { if ($this->getPhones() !== null) { - return $this->getPhones()->convertToSDKRequest(); + return $this->getPhones()->convertToSDKRequest(); } return null; } diff --git a/vendor/pagarme/ecommerce-module-core/src/Payment/Aggregates/Order.php b/vendor/pagarme/ecommerce-module-core/src/Payment/Aggregates/Order.php index 5fba2ce4..c78e2856 100644 --- a/vendor/pagarme/ecommerce-module-core/src/Payment/Aggregates/Order.php +++ b/vendor/pagarme/ecommerce-module-core/src/Payment/Aggregates/Order.php @@ -2,6 +2,8 @@ namespace Pagarme\Core\Payment\Aggregates; +use Pagarme\Core\Payment\Aggregates\Payments\AbstractCreditCardPayment; +use Pagarme\Core\Payment\Aggregates\Payments\Authentication\AuthenticationStatusEnum; use PagarmeCoreApiLib\Models\CreateOrderRequest; use Pagarme\Core\Kernel\Abstractions\AbstractEntity; use Pagarme\Core\Kernel\Services\LocalizationService; @@ -119,6 +121,7 @@ public function getPayments() public function addPayment(AbstractPayment $payment) { $this->validatePaymentInvariants($payment); + $this->addAdditionalSettingsForPaymentInvariants($payment); $this->blockOverPaymentAttempt($payment); $payment->setOrder($this); @@ -235,6 +238,37 @@ private function validateSavedCreditCardPayment(SavedCreditCardPayment $payment) } } + /** + * @param AbstractPayment $payment + * @return void + */ + private function addAdditionalSettingsForPaymentInvariants(AbstractPayment $payment) + { + $parentClass = get_parent_class($payment); + + if ($parentClass === AbstractCreditCardPayment::class) { + $this->addThreeDSAntiFraudInfo($payment); + } + } + + /** + * @param AbstractCreditCardPayment $payment + * @return void + */ + private function addThreeDSAntiFraudInfo(AbstractCreditCardPayment $payment) + { + $authentication = $payment->getAuthentication(); + if (empty($authentication)) { + return; + } + + $antiFraudEnabled = true; + if (in_array($authentication->getStatus(), AuthenticationStatusEnum::doesNotNeedToUseAntifraudStatuses())) { + $antiFraudEnabled = false; + } + $this->setAntifraudEnabled($antiFraudEnabled); + } + /** * @return bool */ @@ -372,7 +406,7 @@ private function fixRoundedValuesInCharges(&$orderRequest){ } $orderSplitData = $this->getSplitData(); - + $wrongValuesPerRecipient = $this->getRecipientWrongValuesMap($orderRequest, $orderSplitData); if (!$wrongValuesPerRecipient){ @@ -380,7 +414,7 @@ private function fixRoundedValuesInCharges(&$orderRequest){ } $orderRequest = $this->fixRoundedValues($wrongValuesPerRecipient, $orderRequest); - + return $orderRequest; } @@ -395,7 +429,7 @@ private function getRecipientWrongValuesMap($orderRequest, $splitData){ $sellerId = $sellerData['pagarmeId']; $sellerCommission = $sellerData['commission']; - $map[$sellerId] = $sellerCommission; + $map[$sellerId] = $sellerCommission; } diff --git a/vendor/pagarme/ecommerce-module-core/src/Payment/Aggregates/Payments/AbstractCreditCardPayment.php b/vendor/pagarme/ecommerce-module-core/src/Payment/Aggregates/Payments/AbstractCreditCardPayment.php index 0383a24e..c2fcf176 100644 --- a/vendor/pagarme/ecommerce-module-core/src/Payment/Aggregates/Payments/AbstractCreditCardPayment.php +++ b/vendor/pagarme/ecommerce-module-core/src/Payment/Aggregates/Payments/AbstractCreditCardPayment.php @@ -2,6 +2,7 @@ namespace Pagarme\Core\Payment\Aggregates\Payments; +use Pagarme\Core\Payment\Aggregates\Payments\Authentication\Authentication; use PagarmeCoreApiLib\Models\CreateCardRequest; use PagarmeCoreApiLib\Models\CreateCreditCardPaymentRequest; use Pagarme\Core\Kernel\Abstractions\AbstractModuleCoreSetup as MPSetup; @@ -12,6 +13,7 @@ use Pagarme\Core\Kernel\ValueObjects\CardBrand; use Pagarme\Core\Payment\ValueObjects\AbstractCardIdentifier; use Pagarme\Core\Payment\ValueObjects\PaymentMethod; +use PagarmeCoreApiLib\Models\CreatePaymentAuthenticationRequest; abstract class AbstractCreditCardPayment extends AbstractPayment { @@ -27,6 +29,8 @@ abstract class AbstractCreditCardPayment extends AbstractPayment protected $capture; /** @var AbstractCardIdentifier */ protected $identifier; + /** @var Authentication|null */ + protected $authentication; public function __construct() @@ -193,6 +197,31 @@ public function setBrand(CardBrand $brand) $this->brand = $brand; } + /** + * @return Authentication|null + */ + public function getAuthentication() + { + return $this->authentication; + } + + /** + * @param Authentication $authentication + * @return void + */ + public function setAuthentication($authentication) + { + $this->authentication = $authentication; + } + + /** + * @return CreatePaymentAuthenticationRequest + */ + public function getAuthenticationSDK() + { + return $this->authentication->convertToSDKRequest(); + } + #[\ReturnTypeWillChange] public function jsonSerialize() { @@ -203,6 +232,9 @@ public function jsonSerialize() $obj->statementDescriptor = $this->statementDescriptor; $obj->capture = $this->capture; $obj->identifier = $this->identifier; + if (!empty($this->authentication)) { + $obj->authentication = $this->authentication; + } return $obj; } @@ -231,6 +263,9 @@ protected function convertToPrimitivePaymentRequest() $cardRequest->installments = $this->getInstallments(); $cardRequest->recurrenceCycle = $this->getRecurrenceCycle(); $cardRequest->statementDescriptor = $this->getStatementDescriptor(); + if (!empty($this->getAuthentication())) { + $cardRequest->authentication = $this->getAuthenticationSDK(); + } return $cardRequest; } diff --git a/vendor/pagarme/ecommerce-module-core/src/Payment/Aggregates/Payments/Authentication/Authentication.php b/vendor/pagarme/ecommerce-module-core/src/Payment/Aggregates/Payments/Authentication/Authentication.php new file mode 100644 index 00000000..7ba150fa --- /dev/null +++ b/vendor/pagarme/ecommerce-module-core/src/Payment/Aggregates/Payments/Authentication/Authentication.php @@ -0,0 +1,137 @@ +type; + } + + /** + * @param string $type + * @return void + */ + public function setType(string $type) + { + $this->type = $type; + } + + /** + * @return ThreeDSecure + */ + public function getThreeDSecure() + { + return $this->threeDSecure; + } + + /** + * @param ThreeDSecure $threeDSecure + * @return void + */ + public function setThreeDSecure(ThreeDSecure $threeDSecure) + { + $this->threeDSecure = $threeDSecure; + } + + /** + * @return string + */ + public function getStatus() + { + return $this->status; + } + + /** + * @param string $status + * @return void + */ + public function setStatus(string $status) + { + $this->status = $status; + } + + /** + * @return CreateThreeDSecureRequest + */ + public function getThreeDSecureSDK() + { + return $this->threeDSecure->convertToSDKRequest(); + } + + /** + * @return CreatePaymentAuthenticationRequest + */ + public function convertToSDKRequest() + { + $authenticationRequest = new CreatePaymentAuthenticationRequest(); + $authenticationRequest->type = $this->getType(); + if (self::isThreeDSecureType($this)) { + $authenticationRequest->threedSecure = $this->getThreeDSecureSDK(); + } + return $authenticationRequest; + } + + /** + * @return mixed + */ + #[\ReturnTypeWillChange] + public function jsonSerialize() + { + $obj = parent::jsonSerialize(); + + $obj->type = $this->getType(); + $obj->transactionId = $this->getThreeDSecure(); + return $obj; + } + + /** + * @param stdClass $object + * @return self + */ + public static function createFromStdClass(stdClass $object) + { + $authentication = new self(); + $authentication->setType($object->type); + $authentication->setStatus($object->status); + if (self::isThreeDSecureType($authentication)) { + $authentication->setThreeDSecure(ThreeDSecure::createFromStdClass($object->threeDSecure)); + } + return $authentication; + } + + /** + * @param Authentication $authentication + * @return bool + */ + private static function isThreeDSecureType(Authentication $authentication) + { + return $authentication->getType() === ThreeDSecure::TYPE; + } +} diff --git a/vendor/pagarme/ecommerce-module-core/src/Payment/Aggregates/Payments/Authentication/AuthenticationStatusEnum.php b/vendor/pagarme/ecommerce-module-core/src/Payment/Aggregates/Payments/Authentication/AuthenticationStatusEnum.php new file mode 100644 index 00000000..831680cd --- /dev/null +++ b/vendor/pagarme/ecommerce-module-core/src/Payment/Aggregates/Payments/Authentication/AuthenticationStatusEnum.php @@ -0,0 +1,80 @@ +mpi; + } + + /** + * @param string $mpi + * @return void + */ + public function setMpi(string $mpi) + { + $this->mpi = $mpi; + } + + /** + * @return string + */ + public function getTransactionId() + { + return $this->transactionId; + } + + /** + * @param string $transactionId + * @return void + */ + public function setTransactionId(string $transactionId) + { + $this->transactionId = $transactionId; + } + + /** + * @return CreateThreeDSecureRequest + */ + public function convertToSDKRequest() + { + $threeDSecureRequest = new CreateThreeDSecureRequest(); + $threeDSecureRequest->mpi = $this->getMpi(); + $threeDSecureRequest->transactionId = $this->getTransactionId(); + + return $threeDSecureRequest; + } + + /** + * @return mixed + */ + #[\ReturnTypeWillChange] + public function jsonSerialize() + { + $obj = parent::jsonSerialize(); + + $obj->mpi = $this->getMpi(); + $obj->transactionId = $this->getTransactionId(); + return $obj; + } + + /** + * @param stdClass $object + * @return self + */ + public static function createFromStdClass(stdClass $object) + { + $threeDSecure = new self(); + $threeDSecure->setMpi($object->mpi); + $threeDSecure->setTransactionId($object->transactionId); + return $threeDSecure; + } +} diff --git a/vendor/pagarme/ecommerce-module-core/src/Payment/Aggregates/Shipping.php b/vendor/pagarme/ecommerce-module-core/src/Payment/Aggregates/Shipping.php index c0ca66e3..9e2ce697 100644 --- a/vendor/pagarme/ecommerce-module-core/src/Payment/Aggregates/Shipping.php +++ b/vendor/pagarme/ecommerce-module-core/src/Payment/Aggregates/Shipping.php @@ -86,12 +86,12 @@ public function setAddress(?Address $address) } /** - * Specify data which should be serialized to JSON - * @link https://php.net/manual/en/jsonserializable.jsonserialize.php - * @return mixed data which can be serialized by json_encode, - * which is a value of any type other than a resource. - * @since 5.4.0 - */ + * Specify data which should be serialized to JSON + * @link https://php.net/manual/en/jsonserializable.jsonserialize.php + * @return mixed data which can be serialized by json_encode, + * which is a value of any type other than a resource. + * @since 5.4.0 + */ #[\ReturnTypeWillChange] public function jsonSerialize() { diff --git a/vendor/pagarme/ecommerce-module-core/src/Payment/Factories/PaymentFactory.php b/vendor/pagarme/ecommerce-module-core/src/Payment/Factories/PaymentFactory.php index d90cef2d..312835a5 100644 --- a/vendor/pagarme/ecommerce-module-core/src/Payment/Factories/PaymentFactory.php +++ b/vendor/pagarme/ecommerce-module-core/src/Payment/Factories/PaymentFactory.php @@ -7,8 +7,8 @@ use Pagarme\Core\Kernel\Services\InstallmentService; use Pagarme\Core\Kernel\ValueObjects\CardBrand; use Pagarme\Core\Kernel\ValueObjects\Id\CustomerId; -use Pagarme\Core\Payment\Aggregates\Customer; use Pagarme\Core\Payment\Aggregates\Payments\AbstractCreditCardPayment; +use Pagarme\Core\Payment\Aggregates\Payments\Authentication\Authentication; use Pagarme\Core\Payment\Aggregates\Payments\BoletoPayment; use Pagarme\Core\Payment\Aggregates\Payments\NewCreditCardPayment; use Pagarme\Core\Payment\Aggregates\Payments\NewDebitCardPayment; @@ -19,7 +19,6 @@ use Pagarme\Core\Payment\ValueObjects\BoletoBank; use Pagarme\Core\Payment\ValueObjects\CardId; use Pagarme\Core\Payment\ValueObjects\CardToken; -use Pagarme\Core\Payment\ValueObjects\CustomerType; use Pagarme\Core\Payment\ValueObjects\PaymentMethod; use Pagarme\Core\Payment\Aggregates\Payments\SavedDebitCardPayment; @@ -127,6 +126,9 @@ private function createBasePayments( $payment->setAmount($cardData->amount); $payment->setInstallments($cardData->installments); $payment->setRecurrenceCycle($cardData->recurrenceCycle ?? null); + if (!empty($cardData->authentication)) { + $payment->setAuthentication(Authentication::createFromStdClass($cardData->authentication)); + } //setting amount with interest if (strcmp($cardDataIndex, \Pagarme\Core\Kernel\ValueObjects\PaymentMethod::VOUCHER)) { diff --git a/vendor/pagarme/ecommerce-module-core/src/Recurrence/Services/SubscriptionService.php b/vendor/pagarme/ecommerce-module-core/src/Recurrence/Services/SubscriptionService.php index 208ffd3d..ac21b25d 100644 --- a/vendor/pagarme/ecommerce-module-core/src/Recurrence/Services/SubscriptionService.php +++ b/vendor/pagarme/ecommerce-module-core/src/Recurrence/Services/SubscriptionService.php @@ -54,17 +54,16 @@ public function createSubscriptionAtPagarme(PlatformOrderInterface $platformOrde { try { $orderService = new OrderService(); - $orderInfo = $orderService->getOrderInfo($platformOrder); - $this->logService->orderInfo( - $platformOrder->getCode(), - 'Creating order.', - $orderInfo - ); $this->setPlatformOrderPending($platformOrder); //build PaymentOrder based on platformOrder $order = $orderService->extractPaymentOrderFromPlatformOrder($platformOrder); + $this->logService->orderInfo( + $platformOrder->getCode(), + 'Creating order.', + $order + ); $subscription = $this->extractSubscriptionDataFromOrder($order); $this->setDiscountCycleSubscription($subscription, $platformOrder); diff --git a/vendor/pagarme/pagarmecoreapi/src/Controllers/TdsTokenController.php b/vendor/pagarme/pagarmecoreapi/src/Controllers/TdsTokenController.php new file mode 100644 index 00000000..3ae4f152 --- /dev/null +++ b/vendor/pagarme/pagarmecoreapi/src/Controllers/TdsTokenController.php @@ -0,0 +1,95 @@ + $accountId, + 'environment' => $environment + ]); + + //validate and preprocess url + $_queryUrl = APIHelper::cleanUrl(Configuration::$BASEURI. $_queryBuilder); + + //prepare headers + $_headers = array ( + 'user-agent' => BaseController::USER_AGENT, + 'Accept' => 'application/json' + ); + //set HTTP basic auth parameters + Request::auth(Configuration::$basicAuthUserName, Configuration::$basicAuthPassword); + + //call on-before Http callback + $_httpRequest = new HttpRequest(HttpMethod::GET, $_headers, $_queryUrl); + if ($this->getHttpCallBack() != null) { + $this->getHttpCallBack()->callOnBeforeRequest($_httpRequest); + } + + //and invoke the API call request to fetch the response + $response = Request::get($_queryUrl, $_headers); + + $_httpResponse = new HttpResponse($response->code, $response->headers, $response->raw_body); + $_httpContext = new HttpContext($_httpRequest, $_httpResponse); + + //call on-after Http callback + if ($this->getHttpCallBack() != null) { + $this->getHttpCallBack()->callOnAfterRequest($_httpContext); + } + + //handle errors defined at the API level + $this->validateResponse($_httpResponse, $_httpContext); + + $mapper = $this->getJsonMapper(); + + return $mapper->mapClass($response->body, 'PagarmeCoreApiLib\\Models\\GetTdsTokenResponse'); + } +} diff --git a/vendor/pagarme/pagarmecoreapi/src/Models/GetTdsTokenResponse.php b/vendor/pagarme/pagarmecoreapi/src/Models/GetTdsTokenResponse.php new file mode 100644 index 00000000..9a0ef37d --- /dev/null +++ b/vendor/pagarme/pagarmecoreapi/src/Models/GetTdsTokenResponse.php @@ -0,0 +1,41 @@ +tdsToken = func_get_arg(0); + } + } + + /** + * Encode this object to JSON + */ + #[\ReturnTypeWillChange] + public function jsonSerialize() + { + $json = array(); + $json['tds_token'] = $this->tdsToken; + return $json; + } +} diff --git a/vendor/pagarme/pagarmecoreapi/src/PagarmeCoreApiClient.php b/vendor/pagarme/pagarmecoreapi/src/PagarmeCoreApiClient.php index 17780298..a8199571 100644 --- a/vendor/pagarme/pagarmecoreapi/src/PagarmeCoreApiClient.php +++ b/vendor/pagarme/pagarmecoreapi/src/PagarmeCoreApiClient.php @@ -105,11 +105,19 @@ public function getTransactions() return Controllers\TransactionsController::getInstance(); } /** - * Singleton access to Transactions controller + * Singleton access to Accounts controller * @return Controllers\AccountsController The *Singleton* instance */ public function getAccounts() { return Controllers\AccountsController::getInstance(); } + /** + * Singleton access to Tds Tokens controller + * @return Controllers\TdsTokenController The *Singleton* instance + */ + public function getTdsToken() + { + return Controllers\TdsTokenController::getInstance(); + } } diff --git a/webpack.config.js b/webpack.config.js index 6c751adc..3ccbb043 100644 --- a/webpack.config.js +++ b/webpack.config.js @@ -1,17 +1,18 @@ -const defaultConfig = require( '@wordpress/scripts/config/webpack.config' ); -const DependencyExtractionWebpackPlugin = require( '@woocommerce/dependency-extraction-webpack-plugin' ); +const defaultConfig = require('@wordpress/scripts/config/webpack.config'); +const DependencyExtractionWebpackPlugin = require('@woocommerce/dependency-extraction-webpack-plugin'); module.exports = { - ...defaultConfig, - plugins: [ - ...defaultConfig.plugins.filter( - (plugin) => - plugin.constructor.name !== 'DependencyExtractionWebpackPlugin' - ), - new DependencyExtractionWebpackPlugin(), - ], - entry: { - pix: './assets/javascripts/front/reactCheckout/payments/pix/index.js', - billet: './assets/javascripts/front/reactCheckout/payments/billet/index.js', - }, -}; \ No newline at end of file + ...defaultConfig, + plugins: [ + ...defaultConfig.plugins.filter( + (plugin) => + plugin.constructor.name !== 'DependencyExtractionWebpackPlugin' + ), + new DependencyExtractionWebpackPlugin(), + ], + entry: { + pix: './assets/javascripts/front/reactCheckout/payments/Pix/index.js', + billet: './assets/javascripts/front/reactCheckout/payments/Billet/index.js', + credit_card: './assets/javascripts/front/reactCheckout/payments/CreditCard/index.js', + }, +}; diff --git a/woo-pagarme-payments.php b/woo-pagarme-payments.php index 6f510fbe..5be4c2d3 100644 --- a/woo-pagarme-payments.php +++ b/woo-pagarme-payments.php @@ -128,7 +128,6 @@ function wcmpAddNoticeButton($buttons) return $html; } - function wcmpAdminNoticePhpVersion() { wcmpRenderAdminNoticeHtml(