PluginProbe
MakeCommerce for WooCommerce / 3.0.11
MakeCommerce for WooCommerce v3.0.11
4.1.1 4.1.0 4.0.8 trunk 1.0 1.0.1 1.0.2 1.0.3 1.1.0 1.1.1 1.1.2 1.1.3 1.1.4 1.1.5 1.1.6 1.1.7 2.0.0 2.1.0 2.1.1 2.1.2 2.1.3 2.1.4 2.1.5 2.2.0 2.2.1 All 97 releases
makecommerce / payment / gateway / woocommerce / paylater.php

paylater.php in MakeCommerce for WooCommerce 3.0.11, at payment/gateway/woocommerce/paylater.php

483 lines 17.0 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3 namespace MakeCommerce\Payment\Gateway\WooCommerce;
4
5 trait Paylater {
6
7 /**
8 * Allowed pay later product view methods
9 */
10 public $allowed_pl_product_view_methods = array(
11 'slice',
12 'indivy-go',
13 'liisi_ee',
14 'bigbank'
15 );
16
17 /**
18 * Allowed shop locations
19 */
20 public $allowed_pl_countries = array(
21 'EE',
22 'LV'
23 );
24
25 //needed so that the block is not show twice.
26 public static $pay_later_shown = false;
27
28 /**
29 * Returns description for pay later method
30 *
31 * @throws exception when method is not implemented
32 * @since 3.0.9
33 */
34 public function get_paylater_method_description( $method, $price ) {
35
36 switch ( $method ) {
37 case 'slice':
38
39 $amount = round( $price / 3, 2 );
40 $first_payment = date( 'Y-m-d', strtotime( '+30 days' ) );
41
42 return sprintf( __( 'Pay in <b>three equal parts, %s EUR per month</b>. First payment on <b>%s %s</b>', 'wc_makecommerce_domain' ), $amount, $this->month_to_text( strtotime( $first_payment ) ), $this->day_to_ordinal( strtotime( $first_payment ) ) );
43 case 'indivy-go':
44
45 return __( 'Buy now, <b>pay on the 15th of the next month</b>', 'wc_makecommerce_domain' );
46 case 'liisi_ee':
47
48 $interest = 11.9;
49 $downpayment = 0;
50 $months = 12;
51 $amount = ( ( $price - $downpayment ) * ( 1 + ( $interest / 100 ) * $months / 12 ) ) / ( $months );
52
53 return sprintf( __( 'Pay <b>%s EUR per month for 12 months</b>. Interest %s', 'wc_makecommerce_domain' ), ceil( $amount ), $interest ) . '%';
54 case 'bigbank':
55
56 $months = 12;
57 $downpayment = 0;
58 $interest = 12.9;
59 $contractfee = 3;
60 $managementfee = 0;
61
62 $contractconclusion = $price / 100 * $contractfee;
63 $creditamount = ( $price - $downpayment ) + $contractconclusion;
64
65 $monthlypayment = $this->pmt( $interest, $months, $creditamount );
66
67 $totalamount = $months * $monthlypayment;
68 $interestpayment = $totalamount - $creditamount - ( $months * $managementfee );
69 $annualinterest = $this->effect( $this->rate( $months, $monthlypayment, -( $creditamount - $contractconclusion ) ) * 12, 12 ) * 100;
70
71 return sprintf(
72 __( 'Pay <b>%s EUR per month</b> for 12 months<br>
73 <br>
74 <i>Borrowing rate %s&#37;, credit amount %s€, contract conclusion fee %s€, total amount payable %s€, annual interest rate %s&#37;
75 Calculation is only informative.</i>' , 'wc_makecommerce_domain'
76 ),
77 number_format( $monthlypayment, 2 ),
78 number_format( $interest, 2 ),
79 number_format( $creditamount, 2 ),
80 number_format( $contractconclusion, 2 ),
81 number_format( $totalamount, 2 ),
82 number_format( $annualinterest, 2 )
83 );
84 default:
85
86 return 'Pay with ' . $method;
87 }
88 }
89
90 /**
91 * Calculate rate
92 *
93 * @since 3.0.10
94 */
95 public function rate( $numberOfPeriods, $payment, $presentValue ) {
96
97 $rate = 0.1;
98 $close = false;
99 $iter = 0;
100
101 while ( !$close && $iter < 128 ) {
102
103 $nextdiff = $this->rateNextGuess( $rate, $numberOfPeriods, $payment, $presentValue );
104 if ( !is_numeric( $nextdiff ) ) {
105 break;
106 }
107
108 $rate1 = $rate - $nextdiff;
109 $close = abs( $rate1 - $rate ) < 1.0e-08;
110 $iter++;
111 $rate = $rate1;
112 }
113
114 return $rate;
115 }
116
117 /**
118 * Returns next rate guess
119 *
120 * @since 3.0.10
121 */
122 private function rateNextGuess( $rate, $numberOfPeriods, $payment, $presentValue, $futureValue = 0, $type = 0 )
123 {
124 $tt1 = ( $rate + 1 ) ** $numberOfPeriods;
125 $tt2 = ( $rate + 1 ) ** ( $numberOfPeriods - 1 );
126 $numerator = $futureValue + $tt1 * $presentValue + $payment * ( $tt1 - 1 ) * ( $rate * $type + 1 ) / $rate;
127 $denominator = $numberOfPeriods * $tt2 * $presentValue - $payment * ( $tt1 - 1 )
128 * ( $rate * $type + 1 ) / ( $rate * $rate ) + $numberOfPeriods
129 * $payment * $tt2 * ( $rate * $type + 1 ) / $rate + $payment * ( $tt1 - 1 ) * $type / $rate;
130
131 return $numerator / $denominator;
132 }
133
134 /**
135 * Calculate monthly payment
136 *
137 * @since 3.0.10
138 */
139 public function pmt( $interest, $months, $loan )
140 {
141 $interest = $interest / 1200;
142 $amount = $interest * -$loan * pow( ( 1 + $interest ), $months ) / ( 1 - pow( ( 1 + $interest ), $months ) );
143
144 return $amount;
145 }
146
147 /**
148 * Calculate effect
149 *
150 * @since 3.0.10
151 */
152 public function effect($nominalRate, $periodsPerYear)
153 {
154 return ( ( 1 + $nominalRate / $periodsPerYear ) ** $periodsPerYear ) - 1;
155 }
156
157 /**
158 * Adds pay later block to product view
159 *
160 * @since 3.0.9
161 */
162 public function add_pay_later_block_to_product() {
163
164 if ( !in_array( wc_get_base_location()['country'], $this->allowed_pl_countries ) ) {
165 return;
166 }
167
168 //don't show more than once
169 if ( self::$pay_later_shown ) {
170 return;
171 }
172
173 global $product;
174
175 //ignore for subscription and grouped products
176 if ( class_exists( '\WC_Subscriptions_Product' ) && \WC_Subscriptions_Product::is_subscription( $product ) ) {
177 return;
178 }
179
180 //get product using variation id
181 if ( isset( $_GET['paylater_variation_id'] ) ) {
182 $product = wc_get_product( $_GET['paylater_variation_id'] );
183 }
184
185 //dont use for grouped products. Too confusing to implement. Something for v2 perhaps
186 if ( $product->get_type() == 'grouped' ) {
187 return;
188 }
189
190 //get product price
191 $price = wc_get_price_including_tax( $product );
192
193 //get allowed methods
194 $methods = $this->get_allowed_pl_methods();
195
196 //add paylater css and js
197 wp_enqueue_style( 'mc_paylater', plugins_url( '/css/paylater.css', __FILE__ ), array(), $this->version );
198 \MakeCommerce::mc_enqueue_script(
199 'MC_PAYLATER',
200 dirname( __FILE__ ) . '/js/mc_paylater.js',
201 [ 'type' => $product->get_type() ],
202 [ 'jquery' ]
203 );
204
205 $logo = plugins_url( '/images/paylater-en.png', __FILE__ );
206 if ( file_exists( dirname( __FILE__ ) . '/images/paylater-' . \MakeCommerce\i18n::get_two_char_locale() .'.png' ) ) {
207 $logo = plugins_url( '/images/paylater-' . \MakeCommerce\i18n::get_two_char_locale() . '.png', __FILE__ );
208 }
209
210 $displaycss = '';
211 if ( $product->get_type() == 'variable' || isset( $_GET['paylater_variation_id'] ) ) {
212 $displaycss = 'style="display: none;"';
213 }
214
215 echo '<div id="mc_paylater_parent">';
216 $pl_html = '
217 <div class="mc_paylater_block" '.$displaycss.' id="mc_paylater_block">
218 <img src="' . $logo . '" />
219 <div class="mc_paylater_block_inner">
220 ';
221
222 $first = true;
223 foreach ( $methods as $method ) {
224
225 if ( in_array( $method->name, $this->settings["pl_show_methods"] )
226 && $price >= $method->min_amount
227 && $price <= $method->max_amount
228 ) {
229 if ( !$first ) {
230 $pl_html .= '<hr />';
231 }
232
233 $pl_html .= '
234 <a style="all: unset;" href="' . esc_url( $product->add_to_cart_url() ) .'&mc_paylater_method=' . $method->name . '&mc_paylater_method_country=' . $method->country . '">
235 <div class="mc_paylater_line" id="' . $method->name . '">
236 <div><img class="mc_paylater_image" src="' . $method->logo_url . '" /></div>
237 <div><p class="mc_paylater_text">' . $this->get_paylater_method_description( $method->name, $price ) . '</p></div>
238 </div>
239 </a>
240 ';
241
242 $first = false;
243 }
244 }
245
246 $pl_html .= '
247 </div>
248 </div>
249 ';
250
251 //if first is false then at least on of the methods was accepted. Otherwise dont show pay later block at all
252 if ( !$first ) {
253 echo $pl_html;
254 }
255
256 echo '</div>';
257
258 self::$pay_later_shown = true;
259 }
260
261 /**
262 * Returns all allowed paylater methods
263 *
264 * @since 3.0.9
265 */
266 public function get_allowed_pl_methods() {
267
268 global $wpdb;
269
270 return $wpdb->get_results( '
271 SELECT
272 *
273 FROM
274 ' . $wpdb->prefix . MAKECOMMERCE_TABLENAME . '
275 WHERE
276 `type` = "payLater" AND
277 `name` IN (\''.implode( "','", $this->allowed_pl_product_view_methods ).'\')
278 ' );
279 }
280
281 /**
282 * Sets pay later settings for admin
283 *
284 * @since 3.0.9
285 */
286 public function set_pay_later_settings() {
287
288 $methods = $this->get_allowed_pl_methods();
289
290 if ( !empty( $methods ) && in_array( wc_get_base_location()['country'], $this->allowed_pl_countries ) ) {
291
292 $this->form_fields['pl_title'] = array(
293 'title' => '<hr><br>'.__( 'Pay later Settings', 'wc_makecommerce_domain' ),
294 'type' => 'title',
295 );
296
297 $this->form_fields['pl_show_on_product_pages'] = array(
298 'title' => __( 'Show pay later options at product view', 'wc_makecommerce_domain' ),
299 'type' => 'checkbox',
300 'default' => 'no'
301 );
302
303 $options = array();
304 foreach ( $methods as $method ) {
305 if ( isset($method->display_name) ) {
306 $options[$method->name] = $method->display_name;
307 } else {
308 $options[$method->name] = $method->name;
309 }
310 }
311
312 $this->form_fields['pl_show_methods'] = array(
313 'title' => __( 'Select desired pay later methods to show in product view', 'wc_makecommerce_domain' ),
314 'type' => 'multiselect',
315 'options' => $options,
316 'desc_tip' => __( 'Select multiple methods by holding down Ctrl or Command button', 'wc_makecommerce_domain' ),
317 );
318 } else {
319
320 $description = __( 'Your shop doesn\'t currently offer pay later methods with Maksekeskus. Adding pay later options to your should increases number of customers and purchase amounts. Please <a target="_blank" href="https://makecommerce.net/contact/">get in touch</a> with us to enable pay later for your shop.', 'wc_makecommerce_domain' );
321
322 if ( !in_array( wc_get_base_location()['country'], $this->allowed_pl_countries ) ) {
323 $description = __( 'This pay later feature is not available in your country yet. <a target="_blank" href="https://makecommerce.net/contact/">Contact us</a> for more information!', 'wc_makecommerce_domain' );
324 }
325
326 $this->form_fields['pl_title'] = array(
327 'title' => '<hr><br>' . __( 'Pay later Settings', 'wc_makecommerce_domain' ),
328 'description' => $description,
329 'type' => 'title',
330 );
331 }
332 }
333
334 /**
335 * Redirect to checkout after cart add via paylater and set selected method to session
336 *
337 * @since 3.0.9
338 */
339 public function added_to_cart_via_paylater_redirect() {
340
341 if ( isset( $_GET['mc_paylater_method'] ) ) {
342 if ( !empty( $_GET['mc_paylater_method'] ) ) {
343
344 WC()->session->set( 'mc_selected_paylater_method', $_GET['mc_paylater_method']);
345 WC()->session->set( 'mc_selected_paylater_method_country', $_GET['mc_paylater_method_country']);
346
347 return wc_get_checkout_url();
348 }
349 }
350 }
351
352 static $autoselect_enqueued = false;
353
354 /**
355 * Automatically select chosen paylater method in checkout
356 *
357 * @since 3.0.9
358 */
359 public function autoselect_chosen_paylater_method( $wccm_after_checkout ) {
360
361 $selectedMethod = WC()->session->get( 'mc_selected_paylater_method' );
362
363 if ( $selectedMethod !== NULL && !self::$autoselect_enqueued ) {
364
365 \MakeCommerce::mc_enqueue_script(
366 'MC_PAYLATER_AUTOSELECT',
367 dirname( __FILE__ ) . '/js/mc_paylater_autoselect.js',
368 [ 'method' => $selectedMethod, 'country' => WC()->session->get( 'mc_selected_paylater_method_country' ), 'id' => $this->id ],
369 [ 'jquery' ]
370 );
371
372 self::$autoselect_enqueued = true;
373
374 //unset session after selecting once.
375 WC()->session->__unset( 'mc_selected_paylater_method' );
376 WC()->session->__unset( 'mc_selected_paylater_method_country' );
377 }
378 }
379
380 static $pl_notice_shown = false;
381 /**
382 * Adds notification to admin when paylater is loaded for the first time
383 *
384 * @since 3.0.9
385 */
386 public function paylater_first_time_notice() {
387
388 if ( !in_array( wc_get_base_location()['country'], $this->allowed_pl_countries ) ) {
389 return;
390 }
391
392 $user_id = get_current_user_id();
393 if ( isset( $_GET['mc_pay_later_notice_dismissed'] ) ) {
394 add_user_meta( $user_id, 'mc_pay_later_notice_dismissed', 'true', true );
395 }
396
397 if ( self::$pl_notice_shown || get_user_meta( $user_id, 'mc_pay_later_notice_dismissed' ) ) {
398 return;
399 }
400
401 echo '
402 <div class="notice notice-info">
403 <p>
404 <a style="float: right; " href="?mc_pay_later_notice_dismissed">' . __( 'Dismiss', 'wc_makecommerce_domain' ) . '</a>
405 ' . sprintf( __( 'MakeCommerce module now includes <a href="%s">option to display pay later options and payment terms examples in product view</a>. Having pay later options available potentially grows your customer base as well as average shopping cart. We recommend to use this option if considerable number of purchases are above 75 euros.', 'wc_makecommerce_domain' ), '/wp-admin/admin.php?page=wc-settings&tab=checkout&section=makecommerce&mc_pay_later_notice_dismissed' ). '
406 </p>
407 </div>';
408
409 self::$pl_notice_shown = true;
410 }
411
412 /**
413 * Converts date to textual representation
414 * Expects unixtime, returns textual month e.g. November, July
415 *
416 * @since 3.0.9
417 */
418 public function month_to_text( $timestamp ) {
419
420 $months = array(
421 1 => __( 'January', 'wc_makecommerce_domain' ),
422 2 => __( 'February', 'wc_makecommerce_domain' ),
423 3 => __( 'March', 'wc_makecommerce_domain' ),
424 4 => __( 'April', 'wc_makecommerce_domain' ),
425 5 => __( 'May', 'wc_makecommerce_domain' ),
426 6 => __( 'June', 'wc_makecommerce_domain' ),
427 7 => __( 'July', 'wc_makecommerce_domain' ),
428 8 => __( 'August', 'wc_makecommerce_domain' ),
429 9 => __( 'September', 'wc_makecommerce_domain' ),
430 10 => __( 'October', 'wc_makecommerce_domain' ),
431 11 => __( 'November', 'wc_makecommerce_domain' ),
432 12 => __( 'December', 'wc_makecommerce_domain' )
433 );
434
435 return $months[ date( 'n', $timestamp ) ];
436 }
437
438 /**
439 * Converts date to textual representation
440 * Expects unixtime, returns ordinal number/text mix e.g. 1st, 2nd
441 *
442 * @since 3.0.9
443 */
444 public function day_to_ordinal( $timestamp ) {
445
446 $days = array(
447 1 => __( '1st', 'wc_makecommerce_domain' ),
448 2 => __( '2nd', 'wc_makecommerce_domain' ),
449 3 => __( '3rd', 'wc_makecommerce_domain' ),
450 4 => __( '4th', 'wc_makecommerce_domain' ),
451 5 => __( '5th', 'wc_makecommerce_domain' ),
452 6 => __( '6th', 'wc_makecommerce_domain' ),
453 7 => __( '7th', 'wc_makecommerce_domain' ),
454 8 => __( '8th', 'wc_makecommerce_domain' ),
455 9 => __( '9th', 'wc_makecommerce_domain' ),
456 10 => __( '10th', 'wc_makecommerce_domain' ),
457 11 => __( '11th', 'wc_makecommerce_domain' ),
458 12 => __( '12th', 'wc_makecommerce_domain' ),
459 13 => __( '13th', 'wc_makecommerce_domain' ),
460 14 => __( '14th', 'wc_makecommerce_domain' ),
461 15 => __( '15th', 'wc_makecommerce_domain' ),
462 16 => __( '16th', 'wc_makecommerce_domain' ),
463 17 => __( '17th', 'wc_makecommerce_domain' ),
464 18 => __( '18th', 'wc_makecommerce_domain' ),
465 19 => __( '19th', 'wc_makecommerce_domain' ),
466 20 => __( '20th', 'wc_makecommerce_domain' ),
467 21 => __( '21st', 'wc_makecommerce_domain' ),
468 22 => __( '22nd', 'wc_makecommerce_domain' ),
469 23 => __( '23rd', 'wc_makecommerce_domain' ),
470 24 => __( '24th', 'wc_makecommerce_domain' ),
471 25 => __( '25th', 'wc_makecommerce_domain' ),
472 26 => __( '26th', 'wc_makecommerce_domain' ),
473 27 => __( '27th', 'wc_makecommerce_domain' ),
474 28 => __( '28th', 'wc_makecommerce_domain' ),
475 29 => __( '29th', 'wc_makecommerce_domain' ),
476 30 => __( '30th', 'wc_makecommerce_domain' ),
477 31 => __( '31st', 'wc_makecommerce_domain' )
478 );
479
480 return $days[ date( 'j', $timestamp ) ];
481 }
482 }
483