WooCommerce PayPal Express Checkout Payment Gateway - Version 1.4.2

Version Description

  • Fix - _paypal_status on Authorize transactions not updating to processing after capture.
  • Fix - 10413 (The totals of the cart item amounts do not match order amounts) error with discounts.
  • Fix - Shipping Address being required on Virtual products.
Download this release

Release Info

Developer bor0
Plugin Icon 128x128 WooCommerce PayPal Express Checkout Payment Gateway
Version 1.4.2
Comparing to
See all releases

Code changes from version 1.4.1 to 1.4.2

includes/class-wc-gateway-ppec-admin-handler.php CHANGED
@@ -167,6 +167,7 @@ class WC_Gateway_PPEC_Admin_Handler {
167
  if ( is_wp_error( $result ) ) {
168
  $order->add_order_note( __( 'Unable to capture charge!', 'woocommerce-gateway-paypal-express-checkout' ) . ' ' . $result->get_error_message() );
169
  } else {
 
170
  $order->add_order_note( sprintf( __( 'PayPal Express Checkout charge complete (Charge ID: %s)', 'woocommerce-gateway-paypal-express-checkout' ), $trans_id ) );
171
  }
172
  }
167
  if ( is_wp_error( $result ) ) {
168
  $order->add_order_note( __( 'Unable to capture charge!', 'woocommerce-gateway-paypal-express-checkout' ) . ' ' . $result->get_error_message() );
169
  } else {
170
+ update_post_meta( $order_id, '_paypal_status', ! empty( $trans_details['PAYMENTSTATUS'] ) ? $trans_details['PAYMENTSTATUS'] : 'completed' );
171
  $order->add_order_note( sprintf( __( 'PayPal Express Checkout charge complete (Charge ID: %s)', 'woocommerce-gateway-paypal-express-checkout' ), $trans_id ) );
172
  }
173
  }
includes/class-wc-gateway-ppec-checkout-handler.php CHANGED
@@ -827,12 +827,8 @@ class WC_Gateway_PPEC_Checkout_Handler {
827
  public function handle_payment_response( $order, $payment ) {
828
  // Store meta data to order
829
  $old_wc = version_compare( WC_VERSION, '3.0', '<' );
830
- if ( $old_wc ) {
831
- update_post_meta( $order->id, '_paypal_status', strtolower( $payment->payment_status ) );
832
- } else {
833
- $order->update_meta_data( '_paypal_status', strtolower( $payment->payment_status ) );
834
- }
835
 
 
836
  update_post_meta( $old_wc ? $order->id : $order->get_id(), '_transaction_id', $payment->transaction_id );
837
 
838
  // Handle $payment response
827
  public function handle_payment_response( $order, $payment ) {
828
  // Store meta data to order
829
  $old_wc = version_compare( WC_VERSION, '3.0', '<' );
 
 
 
 
 
830
 
831
+ update_post_meta( $old_wc ? $order->id : $order->get_id(), '_paypal_status', strtolower( $payment->payment_status ) );
832
  update_post_meta( $old_wc ? $order->id : $order->get_id(), '_transaction_id', $payment->transaction_id );
833
 
834
  // Handle $payment response
includes/class-wc-gateway-ppec-client.php CHANGED
@@ -448,8 +448,8 @@ class WC_Gateway_PPEC_Client {
448
  $settings = wc_gateway_ppec()->settings;
449
 
450
  $decimals = $settings->get_number_of_decimal_digits();
451
- $discounts = round( WC()->cart->get_cart_discount_total(), $decimals );
452
  $rounded_total = $this->_get_rounded_total_in_cart();
 
453
 
454
  $details = array(
455
  'total_item_amount' => round( WC()->cart->cart_contents_total, $decimals ) + $discounts,
@@ -458,72 +458,7 @@ class WC_Gateway_PPEC_Client {
458
  'items' => $this->_get_paypal_line_items_from_cart(),
459
  );
460
 
461
- $details['order_total'] = round(
462
- $details['total_item_amount'] + $details['order_tax'] + $details['shipping'],
463
- $decimals
464
- );
465
-
466
- // Compare WC totals with what PayPal will calculate to see if they match.
467
- // if they do not match, check to see what the merchant would like to do.
468
- // Options are to remove line items or add a line item to adjust for
469
- // the difference.
470
- if ( $details['total_item_amount'] != $rounded_total ) {
471
- if ( 'add' === $settings->get_subtotal_mismatch_behavior() ) {
472
- // Add line item to make up different between WooCommerce
473
- // calculations and PayPal calculations.
474
- $diff = round( $details['total_item_amount'] - $rounded_total, $decimals );
475
- if ( $diff != 0 ) {
476
- $extra_line_item = $this->_get_extra_offset_line_item( $diff );
477
-
478
- $details['items'][] = $extra_line_item;
479
- $details['total_item_amount'] += $extra_line_item['amount'];
480
- $details['order_total'] += $extra_line_item['amount'];
481
- }
482
- } else {
483
- // Omit line items altogether.
484
- unset( $details['items'] );
485
- }
486
- }
487
-
488
- // Enter discount shenanigans. Item total cannot be 0 so make modifications
489
- // accordingly.
490
- if ( $details['total_item_amount'] == $discounts ) {
491
- // Omit line items altogether.
492
- unset( $details['items'] );
493
- $details['ship_discount_amount'] = 0;
494
- $details['total_item_amount'] -= $discounts;
495
- $details['order_total'] -= $discounts;
496
- } else {
497
- if ( $discounts > 0 ) {
498
- $details['items'][] = $this->_get_extra_offset_line_item( - abs( $discounts ) );
499
- }
500
-
501
- $details['ship_discount_amount'] = 0;
502
- $details['total_item_amount'] -= $discounts;
503
- $details['order_total'] -= $discounts;
504
- }
505
-
506
- // If the totals don't line up, adjust the tax to make it work (it's
507
- // probably a tax mismatch).
508
- $wc_order_total = round( WC()->cart->total, $decimals );
509
- if ( $wc_order_total != $details['order_total'] ) {
510
- // tax cannot be negative
511
- if ( $details['order_total'] < $wc_order_total ) {
512
- $details['order_tax'] += $wc_order_total - $details['order_total'];
513
- $details['order_tax'] = round( $details['order_tax'], $decimals );
514
- } else {
515
- $details['ship_discount_amount'] += $wc_order_total - $details['order_total'];
516
- $details['ship_discount_amount'] = round( $details['ship_discount_amount'], $decimals );
517
- }
518
-
519
- $details['order_total'] = $wc_order_total;
520
- }
521
-
522
- if ( ! is_numeric( $details['shipping'] ) ) {
523
- $details['shipping'] = 0;
524
- }
525
-
526
- return $details;
527
  }
528
 
529
  /**
@@ -584,33 +519,25 @@ class WC_Gateway_PPEC_Client {
584
  }
585
 
586
  /**
587
- * Get details from given order_id.
588
  *
589
- * This is the details when buyer is checking out from checkout page.
590
  *
591
- * @since 1.2.0
592
  *
593
- * @param int $order_id Order ID
594
- *
595
- * @return array Order details
596
  */
597
- protected function _get_details_from_order( $order_id ) {
598
- $order = wc_get_order( $order_id );
599
  $settings = wc_gateway_ppec()->settings;
 
600
 
601
- $decimals = $settings->is_currency_supports_zero_decimal() ? 0 : 2;
602
- $discounts = round( $order->get_total_discount(), $decimals );
603
- $rounded_total = $this->_get_rounded_total_in_order( $order );
604
 
605
- $details = array(
606
- 'order_tax' => round( $order->get_total_tax(), $decimals ),
607
- 'shipping' => round( ( version_compare( WC_VERSION, '3.0', '<' ) ? $order->get_total_shipping() : $order->get_shipping_total() ), $decimals ),
608
- 'total_item_amount' => round( $order->get_subtotal(), $decimals ),
609
- 'items' => $this->_get_paypal_line_items_from_order( $order ),
610
  );
611
 
612
- $details['order_total'] = round( $details['total_item_amount'] + $details['order_tax'] + $details['shipping'], $decimals );
613
-
614
  // Compare WC totals with what PayPal will calculate to see if they match.
615
  // if they do not match, check to see what the merchant would like to do.
616
  // Options are to remove line items or add a line item to adjust for
@@ -620,9 +547,13 @@ class WC_Gateway_PPEC_Client {
620
  // Add line item to make up different between WooCommerce
621
  // calculations and PayPal calculations.
622
  $diff = round( $details['total_item_amount'] - $rounded_total, $decimals );
 
 
623
 
624
- $details['items'][] = $this->_get_extra_offset_line_item( $diff );
625
-
 
 
626
  } else {
627
  // Omit line items altogether.
628
  unset( $details['items'] );
@@ -634,30 +565,28 @@ class WC_Gateway_PPEC_Client {
634
  if ( $details['total_item_amount'] == $discounts ) {
635
  // Omit line items altogether.
636
  unset( $details['items'] );
637
- $details['ship_discount_amount'] = 0;
638
- $details['total_item_amount'] -= $discounts;
639
- $details['order_total'] -= $discounts;
640
- } else {
641
- if ( $discounts > 0 ) {
642
- $details['items'][] = $this->_get_extra_discount_line_item( $discounts );
643
 
644
- $details['total_item_amount'] -= $discounts;
645
- $details['order_total'] -= $discounts;
646
- }
647
 
648
- $details['ship_discount_amount'] = 0;
649
- }
 
 
 
650
 
651
  // If the totals don't line up, adjust the tax to make it work (it's
652
  // probably a tax mismatch).
653
- $wc_order_total = round( $order->get_total(), $decimals );
654
- if ( $wc_order_total != $details['order_total'] ) {
 
 
655
  // tax cannot be negative
656
- if ( $details['order_total'] < $wc_order_total ) {
657
- $details['order_tax'] += $wc_order_total - $details['order_total'];
658
  $details['order_tax'] = round( $details['order_tax'], $decimals );
659
  } else {
660
- $details['ship_discount_amount'] += $wc_order_total - $details['order_total'];
661
  $details['ship_discount_amount'] = round( $details['ship_discount_amount'], $decimals );
662
  }
663
 
@@ -668,6 +597,47 @@ class WC_Gateway_PPEC_Client {
668
  $details['shipping'] = 0;
669
  }
670
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
671
  // PayPal shipping address from order.
672
  $shipping_address = new PayPal_Address;
673
 
448
  $settings = wc_gateway_ppec()->settings;
449
 
450
  $decimals = $settings->get_number_of_decimal_digits();
 
451
  $rounded_total = $this->_get_rounded_total_in_cart();
452
+ $discounts = WC()->cart->get_cart_discount_total();
453
 
454
  $details = array(
455
  'total_item_amount' => round( WC()->cart->cart_contents_total, $decimals ) + $discounts,
458
  'items' => $this->_get_paypal_line_items_from_cart(),
459
  );
460
 
461
+ return $this->get_details( $details, $discounts, $rounded_total, WC()->cart->total );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
462
  }
463
 
464
  /**
519
  }
520
 
521
  /**
522
+ * Get details from populated price array
523
  *
524
+ * @since 1.4.1
525
  *
526
+ * @param array $details Prices
527
  *
528
+ * @return array Details
 
 
529
  */
530
+ protected function get_details( $details, $discounts, $rounded_total, $total ) {
 
531
  $settings = wc_gateway_ppec()->settings;
532
+ $decimals = $settings->get_number_of_decimal_digits();
533
 
534
+ $discounts = round( $discounts, $decimals );
 
 
535
 
536
+ $details['order_total'] = round(
537
+ $details['total_item_amount'] + $details['order_tax'] + $details['shipping'],
538
+ $decimals
 
 
539
  );
540
 
 
 
541
  // Compare WC totals with what PayPal will calculate to see if they match.
542
  // if they do not match, check to see what the merchant would like to do.
543
  // Options are to remove line items or add a line item to adjust for
547
  // Add line item to make up different between WooCommerce
548
  // calculations and PayPal calculations.
549
  $diff = round( $details['total_item_amount'] - $rounded_total, $decimals );
550
+ if ( $diff != 0 ) {
551
+ $extra_line_item = $this->_get_extra_offset_line_item( $diff );
552
 
553
+ $details['items'][] = $extra_line_item;
554
+ $details['total_item_amount'] += $extra_line_item['amount'];
555
+ $details['order_total'] += $extra_line_item['amount'];
556
+ }
557
  } else {
558
  // Omit line items altogether.
559
  unset( $details['items'] );
565
  if ( $details['total_item_amount'] == $discounts ) {
566
  // Omit line items altogether.
567
  unset( $details['items'] );
568
+ }
 
 
 
 
 
569
 
570
+ $details['ship_discount_amount'] = 0;
 
 
571
 
572
+ // AMT
573
+ $details['order_total'] = $details['order_total'] - $discounts;
574
+
575
+ // ITEMAMT
576
+ $details['total_item_amount'] = $details['total_item_amount'] - $discounts;
577
 
578
  // If the totals don't line up, adjust the tax to make it work (it's
579
  // probably a tax mismatch).
580
+ $wc_order_total = round( $total, $decimals );
581
+ $discounted_total = $details['order_total'];
582
+
583
+ if ( $wc_order_total != $discounted_total ) {
584
  // tax cannot be negative
585
+ if ( $discounted_total < $wc_order_total ) {
586
+ $details['order_tax'] += $wc_order_total - $discounted_total;
587
  $details['order_tax'] = round( $details['order_tax'], $decimals );
588
  } else {
589
+ $details['ship_discount_amount'] += $wc_order_total - $discounted_total;
590
  $details['ship_discount_amount'] = round( $details['ship_discount_amount'], $decimals );
591
  }
592
 
597
  $details['shipping'] = 0;
598
  }
599
 
600
+ $lisum = 0;
601
+
602
+ foreach ( $details['items'] as $li => $values ) {
603
+ $lisum += $values['quantity'] * $values['amount'];
604
+ }
605
+
606
+ if ( 0 !== $lisum ) {
607
+ $details['items'][] = $this->_get_extra_offset_line_item( $details['total_item_amount'] - $lisum );
608
+ }
609
+
610
+ return $details;
611
+ }
612
+
613
+ /**
614
+ * Get details from given order_id.
615
+ *
616
+ * This is the details when buyer is checking out from checkout page.
617
+ *
618
+ * @since 1.2.0
619
+ *
620
+ * @param int $order_id Order ID
621
+ *
622
+ * @return array Order details
623
+ */
624
+ protected function _get_details_from_order( $order_id ) {
625
+ $order = wc_get_order( $order_id );
626
+ $settings = wc_gateway_ppec()->settings;
627
+
628
+ $decimals = $settings->is_currency_supports_zero_decimal() ? 0 : 2;
629
+ $rounded_total = $this->_get_rounded_total_in_order( $order );
630
+ $discounts = $order->get_total_discount();
631
+
632
+ $details = array(
633
+ 'total_item_amount' => round( $order->get_subtotal(), $decimals ) + $discounts,
634
+ 'order_tax' => round( $order->get_total_tax(), $decimals ),
635
+ 'shipping' => round( ( version_compare( WC_VERSION, '3.0', '<' ) ? $order->get_total_shipping() : $order->get_shipping_total() ), $decimals ),
636
+ 'items' => $this->_get_paypal_line_items_from_order( $order ),
637
+ );
638
+
639
+ $details = $this->get_details( $details, $order->get_total_discount(), $rounded_total, $order->get_total() );
640
+
641
  // PayPal shipping address from order.
642
  $shipping_address = new PayPal_Address;
643
 
includes/class-wc-gateway-ppec-plugin.php CHANGED
@@ -374,7 +374,8 @@ class WC_Gateway_PPEC_Plugin {
374
  }
375
 
376
  /**
377
- * Check if shipping is needed for PayPal.
 
378
  *
379
  * @since 1.4.1
380
  * @version 1.4.1
@@ -382,12 +383,18 @@ class WC_Gateway_PPEC_Plugin {
382
  * @return bool
383
  */
384
  public static function needs_shipping() {
385
- // In case there are no shipping methods defined, we still return true (see #249)
386
- if ( ! wc_shipping_enabled() || 0 === wc_get_shipping_method_count( true ) ) {
387
- return true;
 
 
 
 
 
 
 
388
  }
389
 
390
- // Otherwise go through all items and see if they require shipping (e.g. virtual items will not, see #286)
391
- return WC()->cart->needs_shipping();
392
  }
393
  }
374
  }
375
 
376
  /**
377
+ * Check if shipping is needed for PayPal. This only checks for virtual products (#286),
378
+ * but skips the check if there are no shipping methods enabled (#249).
379
  *
380
  * @since 1.4.1
381
  * @version 1.4.1
383
  * @return bool
384
  */
385
  public static function needs_shipping() {
386
+ $cart_contents = WC()->cart->cart_contents;
387
+ $needs_shipping = false;
388
+
389
+ if ( ! empty( $cart_contents ) ) {
390
+ foreach ( $cart_contents as $cart_item_key => $values ) {
391
+ if ( $values['data']->needs_shipping() ) {
392
+ $needs_shipping = true;
393
+ break;
394
+ }
395
+ }
396
  }
397
 
398
+ return apply_filters( 'woocommerce_cart_needs_shipping', $needs_shipping );
 
399
  }
400
  }
readme.txt CHANGED
@@ -3,7 +3,7 @@ Contributors: automattic, woothemes, akeda, dwainm, royho, allendav, slash1andy,
3
  Tags: ecommerce, e-commerce, commerce, woothemes, wordpress ecommerce, store, sales, sell, shop, shopping, cart, checkout, configurable, paypal
4
  Requires at least: 4.4
5
  Tested up to: 4.7
6
- Stable tag: 1.4.1
7
  License: GPLv3
8
  License URI: http://www.gnu.org/licenses/gpl-3.0.html
9
 
@@ -85,6 +85,11 @@ https://gist.github.com/mikejolley/ad2ecc286c9ad6cefbb7065ba6dfef48
85
 
86
  == Changelog ==
87
 
 
 
 
 
 
88
  = 1.4.1 =
89
  * Fix - Properly calculate whether Billing phone is required or not.
90
  * Fix - Set NOSHIPPING based on product shipping requiredness (e.g. virtual products do not need shipping, etc)
3
  Tags: ecommerce, e-commerce, commerce, woothemes, wordpress ecommerce, store, sales, sell, shop, shopping, cart, checkout, configurable, paypal
4
  Requires at least: 4.4
5
  Tested up to: 4.7
6
+ Stable tag: 1.4.2
7
  License: GPLv3
8
  License URI: http://www.gnu.org/licenses/gpl-3.0.html
9
 
85
 
86
  == Changelog ==
87
 
88
+ = 1.4.2 =
89
+ * Fix - _paypal_status on Authorize transactions not updating to processing after capture.
90
+ * Fix - 10413 (The totals of the cart item amounts do not match order amounts) error with discounts.
91
+ * Fix - Shipping Address being required on Virtual products.
92
+
93
  = 1.4.1 =
94
  * Fix - Properly calculate whether Billing phone is required or not.
95
  * Fix - Set NOSHIPPING based on product shipping requiredness (e.g. virtual products do not need shipping, etc)
woocommerce-gateway-paypal-express-checkout.php CHANGED
@@ -3,7 +3,7 @@
3
  * Plugin Name: WooCommerce PayPal Express Checkout Gateway
4
  * Plugin URI: https://woocommerce.com/products/woocommerce-gateway-paypal-express-checkout/
5
  * Description: A payment gateway for PayPal Express Checkout (https://www.paypal.com/us/webapps/mpp/express-checkout).
6
- * Version: 1.4.1
7
  * Author: WooCommerce
8
  * Author URI: https://woocommerce.com
9
  * Copyright: © 2017 WooCommerce / PayPal.
@@ -25,7 +25,7 @@ if ( ! defined( 'ABSPATH' ) ) {
25
  exit; // Exit if accessed directly
26
  }
27
 
28
- define( 'WC_GATEWAY_PPEC_VERSION', '1.4.1' );
29
 
30
  /**
31
  * Return instance of WC_Gateway_PPEC_Plugin.
3
  * Plugin Name: WooCommerce PayPal Express Checkout Gateway
4
  * Plugin URI: https://woocommerce.com/products/woocommerce-gateway-paypal-express-checkout/
5
  * Description: A payment gateway for PayPal Express Checkout (https://www.paypal.com/us/webapps/mpp/express-checkout).
6
+ * Version: 1.4.2
7
  * Author: WooCommerce
8
  * Author URI: https://woocommerce.com
9
  * Copyright: © 2017 WooCommerce / PayPal.
25
  exit; // Exit if accessed directly
26
  }
27
 
28
+ define( 'WC_GATEWAY_PPEC_VERSION', '1.4.2' );
29
 
30
  /**
31
  * Return instance of WC_Gateway_PPEC_Plugin.