From 51782ceab60d6be9f555edcdba7d02021aee5492 Mon Sep 17 00:00:00 2001 From: Aashish Gurung <101558497+aashishgurung@users.noreply.github.com> Date: Wed, 22 Mar 2023 12:43:09 +0700 Subject: [PATCH 1/6] [ENGA3-1056]: Added feature flag options in the credit card page to switch between credit card forms (#354) * [ENGA3-1056]: Added feature flag options in the credit card page to switch between secure and insecure form. * [ENGA3-1056]: Updated the label and description of embedded form. * [ENGA3-1056]: Removed unnecessary file. * [ENGA3-1056]: Added new line. * [ENGA3-1056]: Fixed some issues. * [EGNA3-1056]: Added discover card. * [ENGA3-1056]: Changed the deploy branch from master to develop --------- Co-authored-by: Aashish --- .github/workflows/deploy-staging.yml | 2 +- assets/css/card-form-customization.css | 153 ++++++++++++++ assets/css/omise-css.css | 6 +- assets/images/green-check.svg | 6 +- assets/javascripts/card-form-customization.js | 93 +++++++++ assets/javascripts/omise-embedded-card.js | 67 ++++++ .../omise-myaccount-card-handler.js | 79 +++++-- .../javascripts/omise-payment-credit-card.js | 16 ++ .../javascripts/omise-payment-form-handler.js | 160 ++++++++++----- ...ass-omise-page-card-form-customization.php | 158 ++++++++++++++ .../omise-page-card-form-customization.php | 194 ++++++++++++++++++ includes/class-omise-admin.php | 68 ++++-- includes/class-omise-wc-myaccount.php | 25 ++- includes/classes/class-omise-card-image.php | 28 +++ .../classes/class-omise-customer-card.php | 3 +- .../abstract-omise-payment-base-card.php | 24 ++- .../class-omise-payment-creditcard.php | 108 ++++++---- .../gateway/class-omise-payment-googlepay.php | 2 +- .../class-omise-payment-rabbit-linepay.php | 2 +- languages/omise-ja.po | 2 +- languages/omise.pot | 2 +- omise-woocommerce.php | 11 + templates/myaccount/my-card.php | 23 ++- templates/payment/form.php | 58 ++++-- 24 files changed, 1127 insertions(+), 163 deletions(-) create mode 100644 assets/css/card-form-customization.css create mode 100644 assets/javascripts/card-form-customization.js create mode 100644 assets/javascripts/omise-embedded-card.js create mode 100644 assets/javascripts/omise-payment-credit-card.js create mode 100644 includes/admin/class-omise-page-card-form-customization.php create mode 100644 includes/admin/views/omise-page-card-form-customization.php diff --git a/.github/workflows/deploy-staging.yml b/.github/workflows/deploy-staging.yml index 9b249920..7753145b 100644 --- a/.github/workflows/deploy-staging.yml +++ b/.github/workflows/deploy-staging.yml @@ -1,7 +1,7 @@ name: Deploy to Staging on: push: - branches: [ 'master' ] + branches: [ 'develop' ] jobs: static: diff --git a/assets/css/card-form-customization.css b/assets/css/card-form-customization.css new file mode 100644 index 00000000..f563f4d8 --- /dev/null +++ b/assets/css/card-form-customization.css @@ -0,0 +1,153 @@ +.omise .text-bold { + font-weight: 500; +} + +.omise .text-extra-bold { + font-weight: 800; +} + +.omise .color-input-container { + display: flex; + align-items: center; + gap: 7px; + border: 0.5px solid #CCCCCC; + border-radius: 3px; + padding: 0px 5px; + width: 347px; + background: white; + height: 36px; +} + +.omise .color-input { + border: none; + box-shadow: none; + background: transparent; + width: 25px; + height: 25px; + padding: 2px; +} + +.omise .color-input:focus { + box-shadow: none; +} + +.omise .color-input-container>span { + color: #131926; + ; +} + +.omise .color-input::-moz-color-swatch { + border: 1px solid #CCCCCC; + border-radius: 3px; +} + +.omise .color-input::-webkit-color-swatch-wrapper { + padding: 0; + border-radius: 0; +} + +.omise .color-input::-webkit-color-swatch { + border: 1px solid #CCCCCC; + border-radius: 3px; +} + +.omise .select-input, +.omise .omise-input { + border: 0.5px solid #CCCCCC; + border-radius: 3px; + width: 357px; + height: 36px; +} + +.omise .select-input:focus, +.omise .omise-input:focus { + box-shadow: none; +} + +.omise .description { + color: #475266; + font-size: 12px; + padding: 3px 0px 0px 10px; +} + +.omise td { + padding: 10px 0px !important; + vertical-align: baseline; +} + +.omise .button-reset { + background: #F24949; + border: 0.5px solid #D8D8D8; + border-radius: 3px; + color: white; +} + +.omise .button-reset:hover { + background: #BF0A19; + border: 0.5px solid #D8D8D8; + border-radius: 3px; + color: white; +} + +.omise .button-preview { + background: #D7D7D9; + border: 0.5px solid #D8D8D8; + border-radius: 3px; + color: #000000; +} + +.omise .button-preview:hover { + background: #CED3DE; + border: 0.5px solid #D8D8D8; + border-radius: 3px; + color: #000000; +} + +.omise .updated { + background: #E8FAF3 !important; + border: 1px solid #30AD7F !important; + border-radius: 8px; + box-shadow: none !important; + font-weight: 600 !important; + display: flex !important; + flex-direction: row; + align-items: center; +} + +.omise .updated::before { + content: url("data:image/svg+xml,%3Csvg width='18' height='19' viewBox='0 0 18 19' fill='none' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath d='M0 9.25C0 4.29297 4.00781 0.25 9 0.25C13.957 0.25 18 4.29297 18 9.25C18 14.2422 13.957 18.25 9 18.25C4.00781 18.25 0 14.2422 0 9.25ZM13.043 7.70312C13.4297 7.31641 13.4297 6.71875 13.043 6.33203C12.6562 5.94531 12.0586 5.94531 11.6719 6.33203L7.875 10.1289L6.29297 8.58203C5.90625 8.19531 5.30859 8.19531 4.92188 8.58203C4.53516 8.96875 4.53516 9.56641 4.92188 9.95312L7.17188 12.2031C7.55859 12.5898 8.15625 12.5898 8.54297 12.2031L13.043 7.70312Z' fill='%2330AD7F'/%3E%3C/svg%3E%0A"); + height: 18px; + margin-right: 6px; +} + +.omise-modal { + position: fixed; + display: none; + left: 0; + right: 0; + bottom: 0; + top: 0; + width: 100%; + height: 100vh; + background: rgb(42 43 55 / 77%); + z-index: 9999999999; + align-items: center; + justify-content: center; +} + +.omise-modal .content { + background-color: white; + border-radius: 8px; + padding: 20px; + width: 450px; + margin-top: -200px; +} + +.omise-modal .body { + padding: 10px; + padding-top: 10px; +} + +.omise-modal .footer { + padding: 10px; +} diff --git a/assets/css/omise-css.css b/assets/css/omise-css.css index 28da9ac3..ae4037a4 100644 --- a/assets/css/omise-css.css +++ b/assets/css/omise-css.css @@ -30,11 +30,13 @@ label.omise-label-inline { display: inline-block; } -fieldset.card-exists { +fieldset.card-exists, +.omise-new-card-form.card-exists { display: none; } -#new_card_info:checked ~ fieldset.card-exists { +#new_card_info:checked ~ fieldset.card-exists, +#new_card_info:checked ~ .omise-new-card-form.card-exists { display: flex; } diff --git a/assets/images/green-check.svg b/assets/images/green-check.svg index 7ceef80e..4f3eec4b 100644 --- a/assets/images/green-check.svg +++ b/assets/images/green-check.svg @@ -1,3 +1,3 @@ - \ No newline at end of file + + + diff --git a/assets/javascripts/card-form-customization.js b/assets/javascripts/card-form-customization.js new file mode 100644 index 00000000..b87123e4 --- /dev/null +++ b/assets/javascripts/card-form-customization.js @@ -0,0 +1,93 @@ +function setDesignFormValues() { + Object.keys(DEFAULT_FORM_DESIGN).forEach(function (componentKey) { + componentValues = DEFAULT_FORM_DESIGN[componentKey]; + Object.keys(componentValues).forEach(function (key) { + setInputValue(`${componentKey}\\[${key}\\]`, componentValues[key]) + }) + }); +} + +function setInputValue(name, val) { + document.querySelector(`[name=${name}]`).value = val +} + +function getInputValue(name) { + return document.querySelector(`[name=${name}]`).value +} + +function setColorInputValue(element) { + valueElement = element.nextElementSibling + if (!valueElement) { + element.insertAdjacentHTML('afterend', `${element.value}`); + } else { + valueElement.innerHTML = element.value; + } +} + +function handleColorInputChanges() { + var colorInputs = document.querySelectorAll('.color-input-container'); + + colorInputs.forEach((element) => { + const input = element.querySelector('.color-input') + + setColorInputValue(input) + input.addEventListener('change', (event) => { + setColorInputValue(event.target) + }); + + element.addEventListener('click', (event) => { + let input = event.target.querySelector('.color-input') + if (!input) { + input = event.target.previousElementSibling + } + var clickEvent = new MouseEvent('click'); + input.dispatchEvent(clickEvent); + }); + }) +} + +function getDesignFormValues() { + let formValues = DEFAULT_FORM_DESIGN + Object.keys(DEFAULT_FORM_DESIGN).forEach(function (componentKey) { + componentValues = DEFAULT_FORM_DESIGN[componentKey]; + Object.keys(componentValues).forEach(function (key) { + const val = getInputValue(`${componentKey}\\[${key}\\]`) + formValues[componentKey][key] = val; + }) + }); + return formValues; +} + +function initOmiseCardForm() { + const customCardFormTheme = CARD_FORM_THEME ?? 'light'; + document.querySelector('.omise-modal .content').style.background = + customCardFormTheme == 'light' ? 'white' : '#272934' + showOmiseEmbeddedCardForm({ + element: document.getElementById('omise-card'), + publicKey: PUBLIC_KEY, + locale: LOCALE, + theme: customCardFormTheme, + brandIcons: CARD_BRAND_ICONS, + design: getDesignFormValues() + }) +} + +document.getElementById('form-preview').addEventListener('click', (event) => { + event.preventDefault() + initOmiseCardForm() + document.querySelector('.omise-modal').style.display = 'flex' +}); + +document.getElementById('close-form-preview').addEventListener('click', (event) => { + event.preventDefault() + document.querySelector('.omise-modal').style.display = 'none' +}); + +document.getElementById('omise-modal').addEventListener('click', (event) => { + if (event.target.id == 'omise-modal') { + document.querySelector('.omise-modal').style.display = 'none' + } +}); + +setDesignFormValues(); +handleColorInputChanges(); diff --git a/assets/javascripts/omise-embedded-card.js b/assets/javascripts/omise-embedded-card.js new file mode 100644 index 00000000..e4ed6b1f --- /dev/null +++ b/assets/javascripts/omise-embedded-card.js @@ -0,0 +1,67 @@ +function showOmiseEmbeddedCardForm({ + element, + publicKey, + theme, + design, + onSuccess, + onError, + locale, + hideRememberCard, + brandIcons +}) { + const noop = () => { } + const iframeHeightMatching = { + '40px': 258, + '44px': 270, + '48px': 282, + '52px': 295, + } + const { input, font, checkbox } = design; + + let iframeElementHeight = iframeHeightMatching[input.height] + + if (hideRememberCard) { + iframeElementHeight = iframeElementHeight - 25 + } + element.style.height = iframeElementHeight + 'px' + + const localeMatching = { + en_US: 'en', + ja_JP: 'ja', + th_TH: 'th' + } + + OmiseCard.configure({ + publicKey: publicKey, + element, + customCardForm: true, + locale: localeMatching[locale] ?? 'en', + customCardFormTheme: theme, + customCardFormHideRememberCard: hideRememberCard ?? false, + customCardFormBrandIcons: brandIcons ?? null, + style: { + fontFamily: font.name, + fontSize: font.size, + input: { + height: input.height, + borderRadius: input.border_radius, + border: `1.2px solid ${input.border_color}`, + focusBorder: `1.2px solid ${input.active_border_color}`, + background: input.background_color, + color: input.text_color, + labelColor: input.label_color, + placeholderColor: input.placeholder_color, + }, + checkBox: { + textColor: checkbox.text_color, + themeColor: checkbox.theme_color, + border: `1.2px solid ${input.border_color}`, + } + }, + }); + + OmiseCard.open({ + onCreateTokenSuccess: onSuccess ?? noop, + onError: onError ?? noop + }); +} diff --git a/assets/javascripts/omise-myaccount-card-handler.js b/assets/javascripts/omise-myaccount-card-handler.js index 8d8a9e8e..30a3e581 100755 --- a/assets/javascripts/omise-myaccount-card-handler.js +++ b/assets/javascripts/omise-myaccount-card-handler.js @@ -60,6 +60,34 @@ } }); + if(Boolean(parseInt(omise_params.embedded_form_enabled))) { + hideError(); + OmiseCard.requestCardToken() + } else { + saveCardTraditional() + } + } + + $(".delete_card").click(function(event){ + if(confirm('Confirm delete card?')){ + let $button = $(this); + $button.block({ + message: null, + overlayCSS: { + background: '#fff url(' + omise_params.ajax_loader_url + ') no-repeat center', + backgroundSize: '16px 16px', + opacity: 0.6 + } + }); + delete_card($button.data("card-id"), $button.data("delete-card-nonce")); + } + }); + + $("#omise_add_new_card").click(function(event){ + create_card(); + }); + + function saveCardTraditional() { let errors = [], omise_card = {}, omise_card_number_field = 'number', @@ -123,24 +151,39 @@ } } } - - $(".delete_card").click(function(event){ - if(confirm('Confirm delete card?')){ - let $button = $(this); - $button.block({ - message: null, - overlayCSS: { - background: '#fff url(' + omise_params.ajax_loader_url + ') no-repeat center', - backgroundSize: '16px 16px', - opacity: 0.6 + + function saveCardEmbedded(payload) { + const data = { + action: "omise_create_card", + omise_token: payload.token, + omise_nonce: $("#omise_add_card_nonce").val() + }; + $.post(omise_params.ajax_url, data, + function(wp_response){ + if(wp_response.id){ + window.location.reload(); + }else{ + showError(wp_response.message, $form); } - }); - delete_card($button.data("card-id"), $button.data("delete-card-nonce")); - } - }); - - $("#omise_add_new_card").click(function(event){ - create_card(); - }); + }, "json" + ); + } + + if(Boolean(parseInt(omise_params.embedded_form_enabled))) { + showOmiseEmbeddedCardForm({ + element: document.getElementById('omise-card'), + publicKey: omise_params.key, + locale: LOCALE, + theme: CARD_FORM_THEME ?? 'light', + design: FORM_DESIGN, + brandIcons: CARD_BRAND_ICONS, + hideRememberCard: true, + onSuccess: saveCardEmbedded, + onError: (error) => { + showError(error) + $form.unblock() + } + }) + } } )(jQuery); diff --git a/assets/javascripts/omise-payment-credit-card.js b/assets/javascripts/omise-payment-credit-card.js new file mode 100644 index 00000000..d09bd04a --- /dev/null +++ b/assets/javascripts/omise-payment-credit-card.js @@ -0,0 +1,16 @@ +(function ($) { + const creditCardFormType = $('#woocommerce_omise_embedded_form_enabled'); + const cardFormTheme = $('#woocommerce_omise_card_form_theme'); + const cardFormThemeParent = cardFormTheme.closest("tr[valign='top']"); + + Boolean(parseInt(creditCardFormType.val())) + ? cardFormThemeParent.show() + : cardFormThemeParent.hide(); + + // Add an event listener to the Product Type field + creditCardFormType.on('change', function(e) { + Boolean(parseInt($(this).val())) + ? cardFormThemeParent.show() + : cardFormThemeParent.hide(); + }); +})(jQuery); diff --git a/assets/javascripts/omise-payment-form-handler.js b/assets/javascripts/omise-payment-form-handler.js index 3c81a6de..d3626ccd 100755 --- a/assets/javascripts/omise-payment-form-handler.js +++ b/assets/javascripts/omise-payment-form-handler.js @@ -14,7 +14,7 @@ let $ulError = $("