Skip to content

Commit

Permalink
Merge pull request #115 from omise/installment-filter-terms
Browse files Browse the repository at this point in the history
Installment, display instalment monthly amount & interest fee at the checkout page.
  • Loading branch information
guzzilar authored Jun 7, 2019
2 parents 111d141 + 0dfec40 commit 3594022
Show file tree
Hide file tree
Showing 12 changed files with 409 additions and 22 deletions.
23 changes: 21 additions & 2 deletions assets/css/omise-css.css
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,16 @@ fieldset.card-exists {
font-size: 80%;
}

#payment .payment_methods li .payment_box fieldset#omise-form-installment .omise-buttom-note {
margin-top: 4em;
}

#payment .payment_methods li .payment_box fieldset#omise-form-installment .omise-installment-interest-rate {
color: #aaa;
font-size: 80%;
line-height: 1;
}


/**
* 2). Components
Expand All @@ -51,7 +61,16 @@ fieldset.card-exists {
}

/**
* 2.2). Form, bank list components
* 2.2). Components
*/
.omise-buttom-note {
margin-top: 2em;
color: #aaa;
font-size: 80%;
}

/**
* 2.3). Form, bank list components
*/
ul.omise-banks-list {
margin: 0;
Expand Down Expand Up @@ -149,7 +168,7 @@ ul.omise-banks-list {
}

/**
* 2.3). Bank logos
* 2.4). Bank logos
*/
/** BAY **/
.bank-logo.bay {
Expand Down
9 changes: 9 additions & 0 deletions composer.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
{
"name": "omise/omise-woocommerce",
"description": "An official payment extension which provides support for Omise payment gateway for store builders working on the WooCommerce platform.",
"homepage": "https://www.omise.co/",
"license": "MIT",
"require-dev": {
"phpunit/phpunit": "^8.1"
}
}
127 changes: 127 additions & 0 deletions includes/backends/class-omise-backend-installment.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,127 @@
<?php
/**
* Note: all calculations in this class are based only on Thailand VAT and fee
* as currently Installment feature supported only for merchants
* that have registered with Omise Thailand account.
*
* @since 3.4
*
* @method public initiate
* @method public get_available_providers
* @method public get_available_plans
* @method public calculate_monthly_payment_amount
*/
class Omise_Backend_Installment extends Omise_Backend {
/**
* @var array of known installment providers.
*/
protected static $providers = array();

public function initiate() {
self::$providers = array(
'installment_first_choice' => array(
'bank_code' => 'first_choice',
'title' => __( 'Krungsri First Choice', 'omise' ),
'interest_rate' => 1.3,
'min_allowed_amount' => 300.00,
),

'installment_bay' => array(
'bank_code' => 'bay',
'title' => __( 'Krungsri', 'omise' ),
'interest_rate' => 0.8,
'min_allowed_amount' => 300.00,
),

'installment_ktc' => array(
'bank_code' => 'ktc',
'title' => __( 'Krungthai Card (KTC)', 'omise' ),
'interest_rate' => 0.8,
'min_allowed_amount' => 300.00,
),

'installment_bbl' => array(
'bank_code' => 'bbl',
'title' => __( 'Bangkok Bank', 'omise' ),
'interest_rate' => 0.8,
'min_allowed_amount' => 500.00,
),

'installment_kbank' => array(
'bank_code' => 'kbank',
'title' => __( 'Kasikorn Bank', 'omise' ),
'interest_rate' => 0.65,
'min_allowed_amount' => 500.00,
),
);
}

/**
* @param string $currency
* @param float $purchase_amount
*
* @return array of an available installment providers
*/
public function get_available_providers( $currency, $purchase_amount ) {
// Note: as installment payment at the moment only supports for THB currency, so the
// $purchase_amount is multiplied with 100 to convert the amount into subunit (satang).
$providers = $this->capabilities()->getInstallmentBackends( $currency, ( $purchase_amount * 100 ) );

foreach ( $providers as &$provider ) {
$provider_detail = self::$providers[ $provider->_id ];

$provider->provider_code = str_replace( 'installment_', '', $provider->_id );
$provider->provider_name = isset( $provider_detail ) ? $provider_detail['title'] : strtoupper( $provider->code );
$provider->interest_rate = $this->capabilities()->is_zero_interest() ? 0 : ( $provider_detail['interest_rate'] );
$provider->available_plans = $this->get_available_plans(
$purchase_amount,
$provider->allowed_installment_terms,
$provider->interest_rate,
$provider_detail['min_allowed_amount']
);
}

return $providers;
}

/**
* @param float $purchase_amount
* @param array $allowed_installment_terms
* @param float $interest_rate
* @param float $min_allowed_amount
*
* @return array of an filtered available terms
*/
public function get_available_plans( $purchase_amount, $allowed_installment_terms, $interest_rate, $min_allowed_amount ) {
$plans = array();

sort( $allowed_installment_terms );

foreach ( $allowed_installment_terms as $term_length ) {
$monthly_amount = $this->calculate_monthly_payment_amount( $purchase_amount, $term_length, $interest_rate );

if ( $monthly_amount < $min_allowed_amount ) {
break;
}

$plans[] = array(
'term_length' => $term_length,
'monthly_amount' => $monthly_amount
);
}

return $plans;
}

/**
* @param float $purchase_amount
* @param int $term_length A length of a given installment term.
* @param float $interest_rate Its value can be '0' if merchant absorbs an interest.
*
* @return float of a installment monthly payment (round up to 2 decimals).
*/
public function calculate_monthly_payment_amount( $purchase_amount, $term_length, $interest_rate ) {
$interest = $purchase_amount * $interest_rate * $term_length / 100;
return round( ( $purchase_amount + $interest ) / $term_length, 2 );
}
}
25 changes: 25 additions & 0 deletions includes/backends/class-omise-backend.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
<?php
/**
* @since 3.4
*/
class Omise_Backend {
public function __construct() {
$this->initiate();
}

/**
* Class initiation.
*
* @return void
*/
public function initiate() {
return;
}

/**
* @return Omise_Capabilities Instant.
*/
public function capabilities() {
return Omise_Capabilities::retrieve();
}
}
7 changes: 7 additions & 0 deletions includes/class-omise-capabilities.php
Original file line number Diff line number Diff line change
Expand Up @@ -45,4 +45,11 @@ public function getInstallmentBackends( $currency = '', $amount = null ) {

return $this->capabilities->getBackends( $params );
}

/**
* @return bool True if merchant absorbs the interest or else, false.
*/
public function is_zero_interest() {
return $this->capabilities['zero_interest_installments'];
}
}
26 changes: 8 additions & 18 deletions includes/gateway/class-omise-payment-installment.php
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,8 @@ public function __construct() {
$this->title = $this->get_option( 'title' );
$this->description = $this->get_option( 'description' );

$this->backend = new Omise_Backend_Installment;

add_action( 'woocommerce_update_options_payment_gateways_' . $this->id, array( $this, 'process_admin_options' ) );
add_action( 'woocommerce_api_' . $this->id . '_callback', array( $this, 'callback' ) );
}
Expand Down Expand Up @@ -69,27 +71,15 @@ public function init_form_fields() {
* @inheritdoc
*/
public function payment_fields() {
$provider_names = array(
'installment_bay' => __( 'Krungsri', 'omise' ),
'installment_first_choice' => __( 'Krungsri First Choice', 'omise' ),
'installment_kbank' => __( 'Kasikorn Bank', 'omise' ),
'installment_bbl' => __( 'Bangkok Bank', 'omise' ),
'installment_ktc' => __( 'Krungthai Card (KTC)', 'omise' ),
);

$currency = get_woocommerce_currency();
$cart_total = WC()->cart->total;
$capabilities = Omise_Capabilities::retrieve();
$installment_backends = $capabilities->getInstallmentBackends( $currency, $this->format_amount_subunit( $cart_total, $currency ) );

foreach ( $installment_backends as &$backend ) {
$backend->provider_code = str_replace( 'installment_', '', $backend->_id );
$backend->provider_name = isset( $provider_names[ $backend->_id ] ) ? $provider_names[ $backend->_id ] : strtoupper( $backend->provider_code );
}
$currency = get_woocommerce_currency();
$cart_total = WC()->cart->total;

Omise_Util::render_view(
'templates/payment/form-installment.php',
array( 'installment_backends' => $installment_backends )
array(
'installment_backends' => $this->backend->get_available_providers( $currency, $cart_total ),
'is_zero_interest' => $this->backend->capabilities()->is_zero_interest()
)
);
}

Expand Down
7 changes: 7 additions & 0 deletions includes/gateway/class-omise-payment.php
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,13 @@ abstract class Omise_Payment extends WC_Payment_Gateway {
*/
public $id = 'omise';

/**
* @since 3.4
*
* @var \Omise_Backend
*/
protected $backend;

/**
* @see omise/includes/class-omise-setting.php
*
Expand Down
2 changes: 2 additions & 0 deletions omise-woocommerce.php
Original file line number Diff line number Diff line change
Expand Up @@ -117,6 +117,8 @@ private function define_constants() {
private function include_classes() {
defined( 'OMISE_WOOCOMMERCE_PLUGIN_PATH' ) || define( 'OMISE_WOOCOMMERCE_PLUGIN_PATH', __DIR__ );

require_once OMISE_WOOCOMMERCE_PLUGIN_PATH . '/includes/backends/class-omise-backend.php';
require_once OMISE_WOOCOMMERCE_PLUGIN_PATH . '/includes/backends/class-omise-backend-installment.php';
require_once OMISE_WOOCOMMERCE_PLUGIN_PATH . '/includes/classes/class-omise-charge.php';
require_once OMISE_WOOCOMMERCE_PLUGIN_PATH . '/includes/classes/class-omise-card-image.php';
require_once OMISE_WOOCOMMERCE_PLUGIN_PATH . '/includes/events/class-omise-event-charge-capture.php';
Expand Down
18 changes: 18 additions & 0 deletions phpunit.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
<phpunit
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="https://schema.phpunit.de/8.1/phpunit.xsd"
backupGlobals="true"
backupStaticAttributes="false"
colors="true"
stopOnError="false"
stopOnFailure="false"
stopOnIncomplete="false"
stopOnSkipped="false"
stopOnRisky="false"
verbose="true">
<testsuites>
<testsuite name="Omise WooCommerce Test Suite">
<directory suffix="-test.php">tests/unit</directory>
</testsuite>
</testsuites>
</phpunit>
28 changes: 26 additions & 2 deletions templates/payment/form-installment.php
Original file line number Diff line number Diff line change
Expand Up @@ -10,15 +10,39 @@
<span class="title"><?php echo $backend->provider_name; ?></span><br/>
<select id="<?php echo $backend->_id; ?>_installment_terms" name="<?php echo $backend->_id; ?>_installment_terms" class="installment-term-select-box">
<option>Select term</option>
<?php foreach ( $backend->allowed_installment_terms as $term ) : ?>
<option value="<?php echo $term; ?>"><?php echo $term; ?> <?php echo __('months'); ?></option>
<?php foreach ( $backend->available_plans as $installment_plan ) : ?>
<option value="<?php echo $installment_plan['term_length']; ?>">
<?php
echo sprintf(
__( '%d months', 'omise', 'omise_installment_term_option' ),
$installment_plan['term_length']
);
?>

<?php
echo sprintf(
__( '( %s / months )', 'omise', 'omise_installment_payment_per_month' ),
wc_price( $installment_plan['monthly_amount'] )
);
?>
</option>
<?php endforeach; ?>
</select>
<?php if ( ! $viewData['is_zero_interest'] ): ?>
<br/><span class="omise-installment-interest-rate">
<?php echo sprintf( __( '( interest %g%% )', 'omise' ), $backend->interest_rate ); ?>
</span>
<?php endif; ?>
</div>
</label>
</li>
<?php endforeach; ?>
</ul>
<div class="omise-buttom-note">
<p>
<?php echo $viewData['is_zero_interest'] ? __( 'All installment payments are interest free', 'omise' ) : __( 'Monthly payment rates shown may be inaccurate as interest rates are subject to change by its bank issuer.', 'omise' ); ?>
</p>
</div>
</fieldset>
<?php else: ?>
<p>
Expand Down
16 changes: 16 additions & 0 deletions tests/unit/class-omise-unit-test.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
<?php

class Omise_Unit_Test {
public static function include_class( $path ): void {
require_once __DIR__ . '/../../includes/' . $path;
}
}

/**
* Mock WordPress __() function.
*
* @see wp-includes/l10n.php
*/
function __( $text, $domain = 'default' ) {
return $text;
}
Loading

0 comments on commit 3594022

Please sign in to comment.