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 e346f84d..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,13 +275,21 @@ $('.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() { const omiseCardElement = document.getElementById('omise-card'); - if (omiseCardElement && Boolean(omise_params.secure_form_enabled)) { + if (omiseCardElement && Boolean(omise_params.secure_form_enabled) && $('#payment_method_omise').is(':checked')) { showOmiseEmbeddedCardForm({ element: omiseCardElement, publicKey: omise_params.key, @@ -271,18 +304,55 @@ $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 () { @@ -292,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 e9d350d5..3f974c26 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' )); } /** @@ -105,6 +106,14 @@ public function getTotalAmount() return WC()->cart->total; } + /** + * Get the total amount of an order in cents + */ + public function convertToCents($amount) + { + return intval(floatval($amount) * 100); + } + /** * @inheritdoc */ @@ -133,9 +142,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; } @@ -151,4 +159,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 f6918934..f7cf4f42 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 @@ public 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 c967a050..8c378804 100644 --- a/tests/unit/includes/gateway/class-omise-payment-installment-test.php +++ b/tests/unit/includes/gateway/class-omise-payment-installment-test.php @@ -72,6 +72,11 @@ function WC() { public function testGetChargeRequest() { + if (!function_exists('wc_clean')) { + function wc_clean() { + return 'src_test_123'; + } + } $expectedAmount = 999999; $expectedCurrency = 'thb'; $orderId = 'order_123'; @@ -79,11 +84,11 @@ public function testGetChargeRequest() $_POST['source'] = ['type' => $this->sourceType]; $_POST[$this->sourceType . '_installment_terms'] = 3; - + $_POST['omise_source'] = 'src_test_123'; $installment = new Omise_Payment_Installment(); $result = $installment->get_charge_request($orderId, $orderMock); - $this->assertEquals($this->sourceType, $result['source']['type']); + $this->assertEquals('src_test_123', $result['source']); } public function testCharge() @@ -94,4 +99,32 @@ public function testCharge() $obj = new Omise_Payment_Installment(); $this->getChargeTest($obj); } + + public function testGetParamsForJS() + { + $mock = Mockery::mock('overload:Omise_Payment_Offsite'); + $instance = new Omise_Payment_Installment($mock); + $result = $instance->getParamsForJS(); + + $this->assertIsArray($result); + $this->assertArrayHasKey('key', $result); + $this->assertArrayHasKey('amount', $result); + $this->assertEquals('pkey_test_123', $result['key']); + $this->assertEquals(99999900, $result['amount']); + } + + public function testConvertToCents() + { + $instance = new Omise_Payment_Installment(); + $this->assertEquals(100, $instance->convertToCents(1.00)); + $this->assertEquals(150, $instance->convertToCents(1.50)); + $this->assertEquals(0, $instance->convertToCents(0.00)); + + $this->assertEquals(10000, $instance->convertToCents(100)); + $this->assertEquals(0, $instance->convertToCents(0)); + + $this->assertEquals(100, $instance->convertToCents('1.00')); + $this->assertEquals(0, $instance->convertToCents('0.00')); + $this->assertEquals(10000, $instance->convertToCents('100')); + } }