diff --git a/assets/javascripts/omise-installment-form.js b/assets/javascripts/omise-installment-form.js new file mode 100644 index 00000000..682e3443 --- /dev/null +++ b/assets/javascripts/omise-installment-form.js @@ -0,0 +1,28 @@ +function showOmiseInstallmentForm({ + element, + publicKey, + onSuccess, + onError, + locale, + amount, +}) { + const noop = () => { } + + element.style.height = 500 + 'px' + + OmiseCard.configure({ + publicKey: publicKey, + amount, + element, + iframeAppId: 'omise-checkout-installment-form', + customCardForm: false, + customInstallmentForm: true, + locale: locale, + defaultPaymentMethod: 'installment' + }); + + OmiseCard.open({ + onCreateSuccess: onSuccess ?? noop, + onError: onError ?? noop + }); +} diff --git a/assets/javascripts/omise-payment-form-handler.js b/assets/javascripts/omise-payment-form-handler.js index 25457834..d99ca737 100755 --- a/assets/javascripts/omise-payment-form-handler.js +++ b/assets/javascripts/omise-payment-form-handler.js @@ -66,6 +66,31 @@ } } + function omiseInstallmentFormHandler() { + function getSelectedCardId() { + const $selected_card_id = $("input[name='card_id']:checked"); + if ($selected_card_id.length > 0) { + return $selected_card_id.val(); + } + + return ""; + } + + if ($('#payment_method_omise_installment').is(':checked')) { + if (getSelectedCardId() !== "") { + //submit the form right away if the card_id is not blank + return true; + } + + if (0 === $('input.omise_token').length && 0 === $('input.omise_source').length) { + requestCardToken(); + return false; + } + return true; + } + return true; + } + function traditionalForm() { $form.block({ message: null, @@ -250,42 +275,84 @@ $('.omise_save_customer_card').val(payload.remember) } $form.append(''); + if (payload.source) { + $form.append(''); + } + $form.submit(); + } else { + if (payload.source) { + $form.append(''); + } $form.submit(); } } function initializeSecureCardForm() { - // This will be undefined when WC block is enabled in Checkout page - if (typeof HIDE_REMEMBER_CARD !== 'undefined') { - const omiseCardElement = document.getElementById('omise-card'); - if (omiseCardElement && Boolean(omise_params.secure_form_enabled)) { - showOmiseEmbeddedCardForm({ - element: omiseCardElement, - publicKey: omise_params.key, - hideRememberCard: HIDE_REMEMBER_CARD, - locale: LOCALE, - theme: CARD_FORM_THEME ?? 'light', - design: FORM_DESIGN, - brandIcons: CARD_BRAND_ICONS, - onSuccess: handleCreateOrder, - onError: (error) => { - showError(error) - $form.unblock() - } - }) - } + const omiseCardElement = document.getElementById('omise-card'); + if (omiseCardElement && Boolean(omise_params.secure_form_enabled) && $('#payment_method_omise').is(':checked')) { + showOmiseEmbeddedCardForm({ + element: omiseCardElement, + publicKey: omise_params.key, + hideRememberCard: HIDE_REMEMBER_CARD, + locale: LOCALE, + theme: CARD_FORM_THEME ?? 'light', + design: FORM_DESIGN, + brandIcons: CARD_BRAND_ICONS, + onSuccess: handleCreateOrder, + onError: (error) => { + showError(error) + $form.unblock() + } + }) + } else { + OmiseCard.destroy(); + } + } + + function initializeInstallmentForm() { + const omiseInstallmentElement = document.getElementById('omise-installment'); + if (omiseInstallmentElement && $('#payment_method_omise_installment').is(':checked')){ + showOmiseInstallmentForm({ + element: omiseInstallmentElement, + publicKey: omise_installment_params.key, + amount: omise_installment_params.amount, + locale: LOCALE, + onSuccess: handleCreateOrder, + onError: (error) => { + showError(error) + $form.unblock() + } + }) + } else { + OmiseCard.destroy(); } } + function setupOmiseForm() { + var selectedPaymentMethod = $('input[name="payment_method"]:checked').val(); + if (selectedPaymentMethod === 'omise') { + initializeSecureCardForm(); + } else if (selectedPaymentMethod === 'omise_installment') { + initializeInstallmentForm(); + } else { + OmiseCard.destroy(); + } + } + $(function () { $('body').on('checkout_error', function () { $('.omise_token').remove(); + $('.omise_source').remove(); }); $('form.checkout').unbind('checkout_place_order_omise'); $('form.checkout').on('checkout_place_order_omise', function () { return omiseFormHandler(); }); + $('form.checkout').unbind('checkout_place_order_omise_installment'); + $('form.checkout').on('checkout_place_order_omise_installment', function () { + return omiseInstallmentFormHandler(); + }); /* Pay Page Form */ $('form#order_review').on('submit', function () { @@ -295,13 +362,18 @@ /* Both Forms */ $('form.checkout, form#order_review').on('change', '#omise_cc_form input', function() { $('.omise_token').remove(); + $('.omise_source').remove(); + }); + + $('form.checkout').on('change', 'input[name="payment_method"]', function() { + setupOmiseForm(); }); $(document).on('updated_checkout', function () { - initializeSecureCardForm(); + setupOmiseForm(); }); - initializeSecureCardForm(); + setupOmiseForm(); googlePay(); }) })(jQuery) diff --git a/includes/gateway/class-omise-payment-installment.php b/includes/gateway/class-omise-payment-installment.php index 7dc60580..5f3e8a74 100644 --- a/includes/gateway/class-omise-payment-installment.php +++ b/includes/gateway/class-omise-payment-installment.php @@ -31,6 +31,7 @@ public function __construct() add_action('woocommerce_update_options_payment_gateways_' . $this->id, array($this, 'process_admin_options')); add_action('woocommerce_order_action_' . $this->id . '_sync_payment', array($this, 'sync_payment')); add_action('woocommerce_api_' . $this->id . '_callback', 'Omise_Callback::execute'); + add_action('wp_enqueue_scripts', array( $this, 'omise_scripts' )); } /** @@ -107,6 +108,14 @@ public function get_total_amount() return WC()->cart->total; } + /** + * Get the total amount of an order in cents + */ + public function convertToCents($amount) + { + return intval(floatval($amount) * 100); + } + /** * @inheritdoc */ @@ -140,9 +149,8 @@ public function get_charge_request($order_id, $order) $payload['zero_interest_installments'] = $provider['zero_interest_installments']; } - $requestData['source'] = array_merge($requestData['source'], [ - 'installment_terms' => sanitize_text_field($installment_terms) - ]); + $requestData['source'] = isset( $_POST['omise_source'] ) ? wc_clean( $_POST['omise_source'] ) : ''; + $requestData['card'] = isset( $_POST['omise_token'] ) ? wc_clean( $_POST['omise_token'] ) : ''; return $requestData; } @@ -158,4 +166,49 @@ public function is_capability_support($available_payment_methods) { return preg_grep('/^installment_/', $available_payment_methods); } + + /** + * @codeCoverageIgnore + */ + public function omise_scripts() { + if ( is_checkout() && $this->is_available() ) { + wp_enqueue_script( + 'omise-js', + Omise::OMISE_JS_LINK, + [ 'jquery' ], + OMISE_WOOCOMMERCE_PLUGIN_VERSION, + true + ); + + wp_enqueue_script( + 'omise-installment-form', + plugins_url( '../../assets/javascripts/omise-installment-form.js', __FILE__ ), + [ 'omise-js' ], + OMISE_WOOCOMMERCE_PLUGIN_VERSION, + true + ); + + wp_enqueue_script( + 'omise-payment-form-handler', + plugins_url( '../../assets/javascripts/omise-payment-form-handler.js', __FILE__ ), + [ 'omise-js' ], + OMISE_WOOCOMMERCE_PLUGIN_VERSION, + true + ); + + wp_localize_script( + 'omise-payment-form-handler', + 'omise_installment_params', + $this->getParamsForJS() + ); + } + } + + public function getParamsForJS() + { + return [ + 'key' => $this->public_key(), + 'amount' => $this->convertToCents($this->getTotalAmount()), + ]; + } } diff --git a/templates/payment/form-installment.php b/templates/payment/form-installment.php index ec61dfed..6806f6b6 100644 --- a/templates/payment/form-installment.php +++ b/templates/payment/form-installment.php @@ -1,49 +1,11 @@ - -
- -
-

- -

-
-
+ +
+

- + diff --git a/tests/unit/includes/gateway/class-omise-offsite-test.php b/tests/unit/includes/gateway/class-omise-offsite-test.php index a40c50cc..23b93ed1 100644 --- a/tests/unit/includes/gateway/class-omise-offsite-test.php +++ b/tests/unit/includes/gateway/class-omise-offsite-test.php @@ -15,6 +15,10 @@ protected function setUp(): void $offsite->shouldReceive('init_settings'); $offsite->shouldReceive('get_option'); $offsite->shouldReceive('get_provider'); + $offsite->shouldReceive('public_key') + ->andReturn('pkey_test_123'); + $offsite->shouldReceive('is_available') + ->andReturn(true); $offsite->shouldReceive('build_charge_request') ->andReturn([ 'source' => [ 'type' => $this->sourceType ] diff --git a/tests/unit/includes/gateway/class-omise-payment-installment-test.php b/tests/unit/includes/gateway/class-omise-payment-installment-test.php index fc437799..2626b798 100644 --- a/tests/unit/includes/gateway/class-omise-payment-installment-test.php +++ b/tests/unit/includes/gateway/class-omise-payment-installment-test.php @@ -81,26 +81,6 @@ public function get_total_amount_from_cart() $this->assertEquals($total, 999999); } - public function test_get_charge_request() - { - $this->backend_installment_mock->shouldReceive('get_provider'); - - Monkey\Functions\expect('add_action'); - - $expectedAmount = 999999; - $expectedCurrency = 'thb'; - $orderId = 'order_123'; - $orderMock = $this->getOrderMock($expectedAmount, $expectedCurrency); - - $_POST['source'] = ['type' => $this->sourceType]; - $_POST[$this->sourceType . '_installment_terms'] = 3; - - $installment = new Omise_Payment_Installment(); - $result = $installment->get_charge_request($orderId, $orderMock); - - $this->assertEquals($this->sourceType, $result['source']['type']); - } - public function test_charge() { $this->backend_installment_mock->shouldReceive('get_provider');