WooCommerce PayPal Express Checkout Payment Gateway - Version 1.4.0

Version Description

  • Tweak - Use shipping discount instead of tax when adjustment negative.
  • Fix - Cannot process refunds on "authorize" transactions.
  • Add - Option for displaying express checkout button on the product page.
  • Fix - If there are no shipping options in WooCommerce, PayPal doesn't pass a shipping address to WC.
  • Add - Option to set Billing phone number mandatory.
  • Add - Option to disable checkout with PayPal button on Cart page.
  • Fix - Trigger required shipping cost before checkout.
Download this release

Release Info

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

Code changes from version 1.3.0 to 1.4.0

assets/js/wc-gateway-ppec-frontend-in-context-checkout.js CHANGED
@@ -17,7 +17,35 @@
17
  }
18
  }
19
 
20
- if ( wc_ppec_context.show_modal ) {
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
21
  $wc_ppec.init();
22
  }
23
  })( jQuery, window, document );
17
  }
18
  }
19
 
20
+ var costs_updated = false;
21
+
22
+ $( '#woo_pp_ec_button' ).click( function( event ) {
23
+ if ( costs_updated ) {
24
+ costs_updated = false;
25
+
26
+ return;
27
+ }
28
+
29
+ event.stopPropagation();
30
+
31
+ var data = {
32
+ 'nonce': wc_ppec_context.update_shipping_costs_nonce,
33
+ };
34
+
35
+ var href = $(this).attr( 'href' );
36
+
37
+ $.ajax( {
38
+ type: 'POST',
39
+ data: data,
40
+ url: wc_ppec_context.ajaxurl,
41
+ success: function( response ) {
42
+ costs_updated = true;
43
+ $( '#woo_pp_ec_button' ).click();
44
+ }
45
+ } );
46
+ } );
47
+
48
+ if ( wc_ppec_context.show_modal ) {
49
  $wc_ppec.init();
50
  }
51
  })( jQuery, window, document );
assets/js/wc-gateway-ppec-generate-cart.js ADDED
@@ -0,0 +1,51 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /* global wc_ppec_context */
2
+ ;(function( $, window, document ) {
3
+ 'use strict';
4
+
5
+ var get_attributes = function() {
6
+ var select = $( '.variations_form' ).find( '.variations select' ),
7
+ data = {},
8
+ count = 0,
9
+ chosen = 0;
10
+
11
+ select.each( function() {
12
+ var attribute_name = $( this ).data( 'attribute_name' ) || $( this ).attr( 'name' );
13
+ var value = $( this ).val() || '';
14
+
15
+ if ( value.length > 0 ) {
16
+ chosen++;
17
+ }
18
+
19
+ count++;
20
+ data[ attribute_name ] = value;
21
+ } );
22
+
23
+ return {
24
+ 'count' : count,
25
+ 'chosenCount': chosen,
26
+ 'data' : data
27
+ };
28
+ };
29
+
30
+ $( '#woo_pp_ec_button' ).click( function( event ) {
31
+ event.preventDefault();
32
+
33
+ var data = {
34
+ 'nonce': wc_ppec_context.generate_cart_nonce,
35
+ 'qty': $( '.quantity .qty' ).val(),
36
+ 'attributes': $( '.variations_form' ).length ? get_attributes().data : []
37
+ };
38
+
39
+ var href = $(this).attr( 'href' );
40
+
41
+ $.ajax( {
42
+ type: 'POST',
43
+ data: data,
44
+ url: wc_ppec_context.ajaxurl,
45
+ success: function( response ) {
46
+ window.location.href = href;
47
+ }
48
+ } );
49
+ } );
50
+
51
+ })( jQuery, window, document );
includes/class-wc-gateway-ppec-admin-handler.php CHANGED
@@ -152,7 +152,7 @@ class WC_Gateway_PPEC_Admin_Handler {
152
  $payment_method = $old_wc ? $order->payment_method : $order->get_payment_method();
153
  if ( 'ppec_paypal' === $payment_method ) {
154
 
155
- $trans_id = $old_wc ? get_post_meta( $order_id, '_transaction_id', true ) : $order->get_meta( '_transaction_id', true );
156
  $trans_details = wc_gateway_ppec()->client->get_transaction_details( array( 'TRANSACTIONID' => $trans_id ) );
157
 
158
  if ( $trans_id && $this->is_authorized_only( $trans_details ) ) {
@@ -200,7 +200,7 @@ class WC_Gateway_PPEC_Admin_Handler {
200
 
201
  if ( 'ppec_paypal' === $payment_method ) {
202
 
203
- $trans_id = $old_wc ? get_post_meta( $order_id, '_transaction_id', true ) : $order->get_meta( '_transaction_id', true );
204
  $trans_details = wc_gateway_ppec()->client->get_transaction_details( array( 'TRANSACTIONID' => $trans_id ) );
205
 
206
  if ( $trans_id && $this->is_authorized_only( $trans_details ) ) {
152
  $payment_method = $old_wc ? $order->payment_method : $order->get_payment_method();
153
  if ( 'ppec_paypal' === $payment_method ) {
154
 
155
+ $trans_id = get_post_meta( $order_id, '_transaction_id', true );
156
  $trans_details = wc_gateway_ppec()->client->get_transaction_details( array( 'TRANSACTIONID' => $trans_id ) );
157
 
158
  if ( $trans_id && $this->is_authorized_only( $trans_details ) ) {
200
 
201
  if ( 'ppec_paypal' === $payment_method ) {
202
 
203
+ $trans_id = get_post_meta( $order_id, '_transaction_id', true );
204
  $trans_details = wc_gateway_ppec()->client->get_transaction_details( array( 'TRANSACTIONID' => $trans_id ) );
205
 
206
  if ( $trans_id && $this->is_authorized_only( $trans_details ) ) {
includes/class-wc-gateway-ppec-cart-handler.php CHANGED
@@ -23,6 +23,13 @@ class WC_Gateway_PPEC_Cart_Handler {
23
  add_action( 'woocommerce_widget_shopping_cart_buttons', array( $this, 'display_mini_paypal_button' ), 20 );
24
  add_action( 'woocommerce_proceed_to_checkout', array( $this, 'display_paypal_button' ), 20 );
25
  add_action( 'wp_enqueue_scripts', array( $this, 'enqueue_scripts' ) );
 
 
 
 
 
 
 
26
  }
27
 
28
  /**
@@ -38,20 +45,115 @@ class WC_Gateway_PPEC_Cart_Handler {
38
  }
39
 
40
  /**
41
- * Display paypal button on the cart page.
 
 
42
  */
43
- public function display_paypal_button() {
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
44
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
45
  $gateways = WC()->payment_gateways->get_available_payment_gateways();
 
 
 
 
 
46
  $settings = wc_gateway_ppec()->settings;
47
 
48
  $express_checkout_img_url = apply_filters( 'woocommerce_paypal_express_checkout_button_img_url', sprintf( 'https://www.paypalobjects.com/webstatic/en_US/i/buttons/checkout-logo-%s.png', $settings->button_size ) );
49
- $paypal_credit_img_url = apply_filters( 'woocommerce_paypal_express_checkout_credit_button_img_url', sprintf( 'https://www.paypalobjects.com/webstatic/en_US/i/buttons/ppcredit-logo-%s.png', $settings->button_size ) );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
50
 
51
  // billing details on checkout page to calculate shipping costs
52
- if ( ! isset( $gateways['ppec_paypal'] ) ) {
53
  return;
54
  }
 
 
 
55
  ?>
56
  <div class="wcppec-checkout-buttons woo_pp_cart_buttons_div">
57
 
@@ -80,9 +182,10 @@ class WC_Gateway_PPEC_Cart_Handler {
80
  public function display_mini_paypal_button() {
81
 
82
  $gateways = WC()->payment_gateways->get_available_payment_gateways();
 
83
 
84
  // billing details on checkout page to calculate shipping costs
85
- if ( ! isset( $gateways['ppec_paypal'] ) ) {
86
  return;
87
  }
88
  ?>
@@ -115,6 +218,18 @@ class WC_Gateway_PPEC_Cart_Handler {
115
  'locale' => $settings->get_paypal_locale(),
116
  'start_flow' => esc_url( add_query_arg( array( 'startcheckout' => 'true' ), wc_get_page_permalink( 'cart' ) ) ),
117
  'show_modal' => apply_filters( 'woocommerce_paypal_express_checkout_show_cart_modal', true ),
 
 
 
 
 
 
 
 
 
 
 
 
118
  )
119
  );
120
  }
23
  add_action( 'woocommerce_widget_shopping_cart_buttons', array( $this, 'display_mini_paypal_button' ), 20 );
24
  add_action( 'woocommerce_proceed_to_checkout', array( $this, 'display_paypal_button' ), 20 );
25
  add_action( 'wp_enqueue_scripts', array( $this, 'enqueue_scripts' ) );
26
+
27
+ if ( 'yes' === wc_gateway_ppec()->settings->checkout_on_single_product_enabled ) {
28
+ add_action( 'woocommerce_after_add_to_cart_form', array( $this, 'display_paypal_button_product' ), 1 );
29
+ add_action( 'wc_ajax_wc_ppec_generate_cart', array( $this, 'wc_ajax_generate_cart' ) );
30
+ }
31
+
32
+ add_action( 'wc_ajax_wc_ppec_update_shipping_costs', array( $this, 'wc_ajax_update_shipping_costs' ) );
33
  }
34
 
35
  /**
45
  }
46
 
47
  /**
48
+ * Generates the cart for express checkout on a product level.
49
+ *
50
+ * @since 1.4.0
51
  */
52
+ public function wc_ajax_generate_cart() {
53
+ global $post;
54
+
55
+ if ( ! wp_verify_nonce( $_POST['nonce'], '_wc_ppec_generate_cart_nonce' ) ) {
56
+ wp_die( __( 'Cheatin&#8217; huh?', 'woocommerce-gateway-paypal-express-checkout' ) );
57
+ }
58
+
59
+ if ( ! defined( 'WOOCOMMERCE_CART' ) ) {
60
+ define( 'WOOCOMMERCE_CART', true );
61
+ }
62
+
63
+ WC()->shipping->reset_shipping();
64
+
65
+ /**
66
+ * If this page is single product page, we need to simulate
67
+ * adding the product to the cart taken account if it is a
68
+ * simple or variable product.
69
+ */
70
+ if ( is_product() ) {
71
+ $product = wc_get_product( $post->ID );
72
+ $qty = ! isset( $_POST['qty'] ) ? 1 : absint( $_POST['qty'] );
73
+
74
+ if ( $product->is_type( 'variable' ) ) {
75
+ $attributes = array_map( 'wc_clean', $_POST['attributes'] );
76
+
77
+ if ( version_compare( WC_VERSION, '3.0', '<' ) ) {
78
+ $variation_id = $product->get_matching_variation( $attributes );
79
+ } else {
80
+ $data_store = WC_Data_Store::load( 'product' );
81
+ $variation_id = $data_store->find_matching_product_variation( $product, $attributes );
82
+ }
83
+
84
+ WC()->cart->add_to_cart( $product->get_id(), $qty, $variation_id, $attributes );
85
+ } elseif ( $product->is_type( 'simple' ) ) {
86
+ WC()->cart->add_to_cart( $product->get_id(), $qty );
87
+ }
88
+
89
+ WC()->cart->calculate_totals();
90
+ }
91
 
92
+ wp_send_json( new stdClass() );
93
+ }
94
+
95
+ /**
96
+ * Update shipping costs. Trigger this update before checking out to have total costs up to date.
97
+ *
98
+ * @since 1.4.0
99
+ */
100
+ public function wc_ajax_update_shipping_costs() {
101
+ if ( ! wp_verify_nonce( $_POST['nonce'], '_wc_ppec_update_shipping_costs_nonce' ) ) {
102
+ wp_die( __( 'Cheatin&#8217; huh?', 'woocommerce-gateway-paypal-express-checkout' ) );
103
+ }
104
+
105
+ if ( ! defined( 'WOOCOMMERCE_CART' ) ) {
106
+ define( 'WOOCOMMERCE_CART', true );
107
+ }
108
+
109
+ WC()->shipping->reset_shipping();
110
+
111
+ WC()->cart->calculate_totals();
112
+
113
+ wp_send_json( new stdClass() );
114
+ }
115
+
116
+ /**
117
+ * Display paypal button on the product page.
118
+ *
119
+ * @since 1.4.0
120
+ */
121
+ public function display_paypal_button_product() {
122
  $gateways = WC()->payment_gateways->get_available_payment_gateways();
123
+
124
+ if ( ! is_product() || ! isset( $gateways['ppec_paypal'] ) ) {
125
+ return;
126
+ }
127
+
128
  $settings = wc_gateway_ppec()->settings;
129
 
130
  $express_checkout_img_url = apply_filters( 'woocommerce_paypal_express_checkout_button_img_url', sprintf( 'https://www.paypalobjects.com/webstatic/en_US/i/buttons/checkout-logo-%s.png', $settings->button_size ) );
131
+
132
+ ?>
133
+ <div class="wcppec-checkout-buttons woo_pp_cart_buttons_div">
134
+
135
+ <a href="<?php echo esc_url( add_query_arg( array( 'startcheckout' => 'true' ), wc_get_page_permalink( 'cart' ) ) ); ?>" id="woo_pp_ec_button" class="wcppec-checkout-buttons__button">
136
+ <img src="<?php echo esc_url( $express_checkout_img_url ); ?>" alt="<?php _e( 'Check out with PayPal', 'woocommerce-gateway-paypal-express-checkout' ); ?>" style="width: auto; height: auto;">
137
+ </a>
138
+ </div>
139
+ <?php
140
+ }
141
+
142
+ /**
143
+ * Display paypal button on the cart page.
144
+ */
145
+ public function display_paypal_button() {
146
+
147
+ $gateways = WC()->payment_gateways->get_available_payment_gateways();
148
+ $settings = wc_gateway_ppec()->settings;
149
 
150
  // billing details on checkout page to calculate shipping costs
151
+ if ( ! isset( $gateways['ppec_paypal'] ) || 'no' === $settings->cart_checkout_enabled ) {
152
  return;
153
  }
154
+
155
+ $express_checkout_img_url = apply_filters( 'woocommerce_paypal_express_checkout_button_img_url', sprintf( 'https://www.paypalobjects.com/webstatic/en_US/i/buttons/checkout-logo-%s.png', $settings->button_size ) );
156
+ $paypal_credit_img_url = apply_filters( 'woocommerce_paypal_express_checkout_credit_button_img_url', sprintf( 'https://www.paypalobjects.com/webstatic/en_US/i/buttons/ppcredit-logo-%s.png', $settings->button_size ) );
157
  ?>
158
  <div class="wcppec-checkout-buttons woo_pp_cart_buttons_div">
159
 
182
  public function display_mini_paypal_button() {
183
 
184
  $gateways = WC()->payment_gateways->get_available_payment_gateways();
185
+ $settings = wc_gateway_ppec()->settings;
186
 
187
  // billing details on checkout page to calculate shipping costs
188
+ if ( ! isset( $gateways['ppec_paypal'] ) || 'no' === $settings->cart_checkout_enabled ) {
189
  return;
190
  }
191
  ?>
218
  'locale' => $settings->get_paypal_locale(),
219
  'start_flow' => esc_url( add_query_arg( array( 'startcheckout' => 'true' ), wc_get_page_permalink( 'cart' ) ) ),
220
  'show_modal' => apply_filters( 'woocommerce_paypal_express_checkout_show_cart_modal', true ),
221
+ 'update_shipping_costs_nonce' => wp_create_nonce( '_wc_ppec_update_shipping_costs_nonce' ),
222
+ 'ajaxurl' => WC_AJAX::get_endpoint( 'wc_ppec_update_shipping_costs' ),
223
+ )
224
+ );
225
+ }
226
+
227
+ if ( is_product() ) {
228
+ wp_enqueue_script( 'wc-gateway-ppec-generate-cart', wc_gateway_ppec()->plugin_url . 'assets/js/wc-gateway-ppec-generate-cart.js', array( 'jquery' ), wc_gateway_ppec()->version, true );
229
+ wp_localize_script( 'wc-gateway-ppec-generate-cart', 'wc_ppec_context',
230
+ array(
231
+ 'generate_cart_nonce' => wp_create_nonce( '_wc_ppec_generate_cart_nonce' ),
232
+ 'ajaxurl' => WC_AJAX::get_endpoint( 'wc_ppec_generate_cart' ),
233
  )
234
  );
235
  }
includes/class-wc-gateway-ppec-checkout-handler.php CHANGED
@@ -142,8 +142,10 @@ class WC_Gateway_PPEC_Checkout_Handler {
142
  * @return array
143
  */
144
  public function filter_billing_fields( $billing_fields ) {
 
 
145
  if ( array_key_exists( 'billing_phone', $billing_fields ) ) {
146
- $billing_fields['billing_phone']['required'] = false;
147
  };
148
 
149
  return $billing_fields;
@@ -293,9 +295,6 @@ class WC_Gateway_PPEC_Checkout_Handler {
293
  return;
294
  }
295
 
296
- if ( ! WC()->cart->needs_shipping() ) {
297
- return;
298
- }
299
  ?>
300
  <h3><?php _e( 'Shipping details', 'woocommerce-gateway-paypal-express-checkout' ); ?></h3>
301
  <?php
@@ -783,20 +782,20 @@ class WC_Gateway_PPEC_Checkout_Handler {
783
  }
784
 
785
  $paymentAction = $settings->get_paymentaction();
786
- if ( 'sale' == $paymentAction ) {
787
- $txn = array(
788
- 'txnID' => $payment_details->payments[0]->transaction_id,
789
- 'amount' => $order->get_total(),
790
- 'refunded_amount' => 0
791
- );
792
- if ( 'Completed' == $payment_details->payments[0]->payment_status ) {
793
- $txn['status'] = 'Completed';
794
- } else {
795
- $txn['status'] = $payment_details->payments[0]->payment_status . '_' . $payment_details->payments[0]->pending_reason;
796
- }
797
- $txnData['refundable_txns'][] = $txn;
798
 
799
- } elseif ( 'authorization' == $paymentAction ) {
 
 
 
 
 
 
 
 
 
 
 
 
800
  $txnData['auth_status'] = 'NotCompleted';
801
  }
802
 
@@ -826,12 +825,12 @@ class WC_Gateway_PPEC_Checkout_Handler {
826
  $old_wc = version_compare( WC_VERSION, '3.0', '<' );
827
  if ( $old_wc ) {
828
  update_post_meta( $order->id, '_paypal_status', strtolower( $payment->payment_status ) );
829
- update_post_meta( $order->id, '_transaction_id', $payment->transaction_id );
830
  } else {
831
  $order->update_meta_data( '_paypal_status', strtolower( $payment->payment_status ) );
832
- $order->update_meta_data( '_transaction_id', $payment->transaction_id );
833
  }
834
 
 
 
835
  // Handle $payment response
836
  if ( 'completed' === strtolower( $payment->payment_status ) ) {
837
  $order->payment_complete( $payment->transaction_id );
142
  * @return array
143
  */
144
  public function filter_billing_fields( $billing_fields ) {
145
+ $require_phone_number = wc_gateway_ppec()->settings->require_phone_number;
146
+
147
  if ( array_key_exists( 'billing_phone', $billing_fields ) ) {
148
+ $billing_fields['billing_phone']['required'] = 'no' !== $require_phone_number;
149
  };
150
 
151
  return $billing_fields;
295
  return;
296
  }
297
 
 
 
 
298
  ?>
299
  <h3><?php _e( 'Shipping details', 'woocommerce-gateway-paypal-express-checkout' ); ?></h3>
300
  <?php
782
  }
783
 
784
  $paymentAction = $settings->get_paymentaction();
 
 
 
 
 
 
 
 
 
 
 
 
785
 
786
+ $txn = array(
787
+ 'txnID' => $payment_details->payments[0]->transaction_id,
788
+ 'amount' => $order->get_total(),
789
+ 'refunded_amount' => 0
790
+ );
791
+ if ( 'Completed' == $payment_details->payments[0]->payment_status ) {
792
+ $txn['status'] = 'Completed';
793
+ } else {
794
+ $txn['status'] = $payment_details->payments[0]->payment_status . '_' . $payment_details->payments[0]->pending_reason;
795
+ }
796
+ $txnData['refundable_txns'][] = $txn;
797
+
798
+ if ( 'authorization' == $paymentAction ) {
799
  $txnData['auth_status'] = 'NotCompleted';
800
  }
801
 
825
  $old_wc = version_compare( WC_VERSION, '3.0', '<' );
826
  if ( $old_wc ) {
827
  update_post_meta( $order->id, '_paypal_status', strtolower( $payment->payment_status ) );
 
828
  } else {
829
  $order->update_meta_data( '_paypal_status', strtolower( $payment->payment_status ) );
 
830
  }
831
 
832
+ update_post_meta( $old_wc ? $order->id : $order->get_id(), '_transaction_id', $payment->transaction_id );
833
+
834
  // Handle $payment response
835
  if ( 'completed' === strtolower( $payment->payment_status ) ) {
836
  $order->payment_complete( $payment->transaction_id );
includes/class-wc-gateway-ppec-client.php CHANGED
@@ -303,7 +303,7 @@ class WC_Gateway_PPEC_Client {
303
  'PAYMENTREQUEST_0_SHIPPINGAMT' => $details['shipping'],
304
  'PAYMENTREQUEST_0_TAXAMT' => $details['order_tax'],
305
  'PAYMENTREQUEST_0_SHIPDISCAMT' => $details['ship_discount_amount'],
306
- 'NOSHIPPING' => WC()->cart->needs_shipping() ? 0 : 1,
307
  )
308
  );
309
 
@@ -507,10 +507,17 @@ class WC_Gateway_PPEC_Client {
507
  // probably a tax mismatch).
508
  $wc_order_total = round( WC()->cart->total, $decimals );
509
  if ( $wc_order_total != $details['order_total'] ) {
510
- $details['order_tax'] += $wc_order_total - $details['order_total'];
 
 
 
 
 
 
 
 
511
  $details['order_total'] = $wc_order_total;
512
  }
513
- $details['order_tax'] = round( $details['order_tax'], $decimals );
514
 
515
  if ( ! is_numeric( $details['shipping'] ) ) {
516
  $details['shipping'] = 0;
@@ -645,10 +652,17 @@ class WC_Gateway_PPEC_Client {
645
  // probably a tax mismatch).
646
  $wc_order_total = round( $order->get_total(), $decimals );
647
  if ( $wc_order_total != $details['order_total'] ) {
648
- $details['order_tax'] += $wc_order_total - $details['order_total'];
 
 
 
 
 
 
 
 
649
  $details['order_total'] = $wc_order_total;
650
  }
651
- $details['order_tax'] = round( $details['order_tax'], $decimals );
652
 
653
  if ( ! is_numeric( $details['shipping'] ) ) {
654
  $details['shipping'] = 0;
@@ -658,14 +672,28 @@ class WC_Gateway_PPEC_Client {
658
  $shipping_address = new PayPal_Address;
659
 
660
  $old_wc = version_compare( WC_VERSION, '3.0', '<' );
661
- $shipping_first_name = $old_wc ? $order->shipping_first_name : $order->get_shipping_first_name();
662
- $shipping_last_name = $old_wc ? $order->shipping_last_name : $order->get_shipping_last_name();
663
- $shipping_address_1 = $old_wc ? $order->shipping_address_1 : $order->get_shipping_address_1();
664
- $shipping_address_2 = $old_wc ? $order->shipping_address_2 : $order->get_shipping_address_2();
665
- $shipping_city = $old_wc ? $order->shipping_city : $order->get_shipping_city();
666
- $shipping_state = $old_wc ? $order->shipping_state : $order->get_shipping_state();
667
- $shipping_postcode = $old_wc ? $order->shipping_postcode : $order->get_shipping_postcode();
668
- $shipping_country = $old_wc ? $order->shipping_country : $order->get_shipping_country();
 
 
 
 
 
 
 
 
 
 
 
 
 
 
669
 
670
  $shipping_address->setName( $shipping_first_name . ' ' . $shipping_last_name );
671
  $shipping_address->setStreet1( $shipping_address_1 );
@@ -812,10 +840,10 @@ class WC_Gateway_PPEC_Client {
812
  'order_id' => $order_id,
813
  'order_key' => $order_key,
814
  ) ),
815
- 'NOSHIPPING' => WC()->cart->needs_shipping() ? 0 : 1,
816
  );
817
 
818
- if ( WC()->cart->needs_shipping() && ! empty( $details['shipping_address'] ) ) {
819
  $params = array_merge(
820
  $params,
821
  $details['shipping_address']->getAddressParams( 'PAYMENTREQUEST_0_SHIPTO' )
303
  'PAYMENTREQUEST_0_SHIPPINGAMT' => $details['shipping'],
304
  'PAYMENTREQUEST_0_TAXAMT' => $details['order_tax'],
305
  'PAYMENTREQUEST_0_SHIPDISCAMT' => $details['ship_discount_amount'],
306
+ 'NOSHIPPING' => 0,
307
  )
308
  );
309
 
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;
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
+
664
  $details['order_total'] = $wc_order_total;
665
  }
 
666
 
667
  if ( ! is_numeric( $details['shipping'] ) ) {
668
  $details['shipping'] = 0;
672
  $shipping_address = new PayPal_Address;
673
 
674
  $old_wc = version_compare( WC_VERSION, '3.0', '<' );
675
+
676
+ if ( ( $old_wc && ( $order->shipping_address_1 || $order->shipping_address_2 ) ) || ( ! $old_wc && $order->has_shipping_address() ) ) {
677
+ $shipping_first_name = $old_wc ? $order->shipping_first_name : $order->get_shipping_first_name();
678
+ $shipping_last_name = $old_wc ? $order->shipping_last_name : $order->get_shipping_last_name();
679
+ $shipping_address_1 = $old_wc ? $order->shipping_address_1 : $order->get_shipping_address_1();
680
+ $shipping_address_2 = $old_wc ? $order->shipping_address_2 : $order->get_shipping_address_2();
681
+ $shipping_city = $old_wc ? $order->shipping_city : $order->get_shipping_city();
682
+ $shipping_state = $old_wc ? $order->shipping_state : $order->get_shipping_state();
683
+ $shipping_postcode = $old_wc ? $order->shipping_postcode : $order->get_shipping_postcode();
684
+ $shipping_country = $old_wc ? $order->shipping_country : $order->get_shipping_country();
685
+ } else {
686
+ // Fallback to billing in case no shipping methods are set. The address returned from PayPal
687
+ // will be stored in the order as billing.
688
+ $shipping_first_name = $old_wc ? $order->billing_first_name : $order->get_billing_first_name();
689
+ $shipping_last_name = $old_wc ? $order->billing_last_name : $order->get_billing_last_name();
690
+ $shipping_address_1 = $old_wc ? $order->billing_address_1 : $order->get_billing_address_1();
691
+ $shipping_address_2 = $old_wc ? $order->billing_address_2 : $order->get_billing_address_2();
692
+ $shipping_city = $old_wc ? $order->billing_city : $order->get_billing_city();
693
+ $shipping_state = $old_wc ? $order->billing_state : $order->get_billing_state();
694
+ $shipping_postcode = $old_wc ? $order->billing_postcode : $order->get_billing_postcode();
695
+ $shipping_country = $old_wc ? $order->billing_country : $order->get_billing_country();
696
+ }
697
 
698
  $shipping_address->setName( $shipping_first_name . ' ' . $shipping_last_name );
699
  $shipping_address->setStreet1( $shipping_address_1 );
840
  'order_id' => $order_id,
841
  'order_key' => $order_key,
842
  ) ),
843
+ 'NOSHIPPING' => 0,
844
  );
845
 
846
+ if ( ! empty( $details['shipping_address'] ) ) {
847
  $params = array_merge(
848
  $params,
849
  $details['shipping_address']->getAddressParams( 'PAYMENTREQUEST_0_SHIPTO' )
includes/class-wc-gateway-ppec-ipn-handler.php CHANGED
@@ -311,7 +311,6 @@ class WC_Gateway_PPEC_IPN_Handler extends WC_Gateway_PPEC_PayPal_Request_Handler
311
  'first_name' => 'Payer first name',
312
  'last_name' => 'Payer last name',
313
  'payment_type' => 'Payment type',
314
- 'txn_id' => '_transaction_id',
315
  'payment_status' => '_paypal_status'
316
  );
317
 
@@ -326,6 +325,10 @@ class WC_Gateway_PPEC_IPN_Handler extends WC_Gateway_PPEC_PayPal_Request_Handler
326
  }
327
  }
328
  }
 
 
 
 
329
  }
330
 
331
  /**
311
  'first_name' => 'Payer first name',
312
  'last_name' => 'Payer last name',
313
  'payment_type' => 'Payment type',
 
314
  'payment_status' => '_paypal_status'
315
  );
316
 
325
  }
326
  }
327
  }
328
+
329
+ if ( ! empty( $posted_data['txn_id'] ) ) {
330
+ update_post_meta( $old_wc ? $order->id : $order->get_id(), '_transaction_id', wc_clean( $posted_data['txn_id'] ) );
331
+ }
332
  }
333
 
334
  /**
includes/settings/settings-ppec.php CHANGED
@@ -263,6 +263,14 @@ return array(
263
  'large' => __( 'Large', 'woocommerce-gateway-paypal-express-checkout' ),
264
  ),
265
  ),
 
 
 
 
 
 
 
 
266
  'mark_enabled' => array(
267
  'title' => __( 'PayPal Mark', 'woocommerce-gateway-paypal-express-checkout' ),
268
  'type' => 'checkbox',
@@ -316,6 +324,13 @@ return array(
316
  'desc_tip' => true,
317
  'description' => __( 'This enables PayPal Credit, which displays a PayPal Credit button next to the Express Checkout button. PayPal Express Checkout lets you give customers access to financing through PayPal Credit® - at no additional cost to you. You get paid up front, even though customers have more time to pay. A pre-integrated payment button shows up next to the PayPal Button, and lets customers pay quickly with PayPal Credit®.', 'woocommerce-gateway-paypal-express-checkout' ),
318
  ),
 
 
 
 
 
 
 
319
 
320
  'advanced' => array(
321
  'title' => __( 'Advanced Settings', 'woocommerce-gateway-paypal-express-checkout' ),
@@ -342,8 +357,14 @@ return array(
342
  'type' => 'checkbox',
343
  'label' => __( 'Require Billing Address', 'woocommerce-gateway-paypal-express-checkout' ),
344
  'default' => 'no',
345
- 'desc_tip' => true,
346
- 'description' => __( 'PayPal does not share buyer billing details with you. However, there are times when you must collect the buyer billing address to fulfill an essential business function (such as determining whether you must charge the buyer tax). Enable this function to collect the address before payment is taken. To enable this functionality on your PayPal account, please call PayPal customer support.', 'woocommerce-gateway-paypal-express-checkout' ),
 
 
 
 
 
 
347
  ),
348
  'paymentaction' => array(
349
  'title' => __( 'Payment Action', 'woocommerce-gateway-paypal-express-checkout' ),
263
  'large' => __( 'Large', 'woocommerce-gateway-paypal-express-checkout' ),
264
  ),
265
  ),
266
+ 'cart_checkout_enabled' => array(
267
+ 'title' => __( 'Checkout on cart page', 'woocommerce-gateway-paypal-express-checkout' ),
268
+ 'type' => 'checkbox',
269
+ 'label' => __( 'Enable PayPal checkout on the cart page', 'woocommerce-gateway-paypal-express-checkout' ),
270
+ 'description' => __( 'This shows or hides the PayPal checkout button on the cart page.', 'woocommerce-gateway-paypal-express-checkout' ),
271
+ 'desc_tip' => true,
272
+ 'default' => 'yes',
273
+ ),
274
  'mark_enabled' => array(
275
  'title' => __( 'PayPal Mark', 'woocommerce-gateway-paypal-express-checkout' ),
276
  'type' => 'checkbox',
324
  'desc_tip' => true,
325
  'description' => __( 'This enables PayPal Credit, which displays a PayPal Credit button next to the Express Checkout button. PayPal Express Checkout lets you give customers access to financing through PayPal Credit® - at no additional cost to you. You get paid up front, even though customers have more time to pay. A pre-integrated payment button shows up next to the PayPal Button, and lets customers pay quickly with PayPal Credit®.', 'woocommerce-gateway-paypal-express-checkout' ),
326
  ),
327
+ 'checkout_on_single_product_enabled' => array(
328
+ 'title' => __( 'Checkout on Single Product', 'woocommerce-gateway-paypal-express-checkout' ),
329
+ 'type' => 'checkbox',
330
+ 'label' => __( 'Checkout on Single Product', 'woocommerce-gateway-paypal-express-checkout' ),
331
+ 'default' => 'no',
332
+ 'description' => __( 'Enable Express checkout on Single Product view.', 'woocommerce-gateway-paypal-express-checkout' ),
333
+ ),
334
 
335
  'advanced' => array(
336
  'title' => __( 'Advanced Settings', 'woocommerce-gateway-paypal-express-checkout' ),
357
  'type' => 'checkbox',
358
  'label' => __( 'Require Billing Address', 'woocommerce-gateway-paypal-express-checkout' ),
359
  'default' => 'no',
360
+ 'description' => sprintf( __( 'PayPal only returns a shipping address back to the website. To make sure billing address is returned as well, please enable this functionality on your PayPal account by calling %1$sPayPal Technical Support%2$s.', 'woocommerce-gateway-paypal-express-checkout' ), '<a href="https://www.paypal.com/us/selfhelp/contact/call">', '</a>' ),
361
+ ),
362
+ 'require_phone_number' => array(
363
+ 'title' => __( 'Require Phone Number', 'woocommerce-gateway-paypal-express-checkout' ),
364
+ 'type' => 'checkbox',
365
+ 'label' => __( 'Require Phone Number', 'woocommerce-gateway-paypal-express-checkout' ),
366
+ 'default' => 'no',
367
+ 'description' => __( 'Require buyer to enter their telephone number during checkout if none is provided by PayPal', 'woocommerce-gateway-paypal-express-checkout' ),
368
  ),
369
  'paymentaction' => array(
370
  'title' => __( 'Payment Action', 'woocommerce-gateway-paypal-express-checkout' ),
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.3.0
7
  License: GPLv3
8
  License URI: http://www.gnu.org/licenses/gpl-3.0.html
9
 
@@ -85,6 +85,15 @@ https://gist.github.com/mikejolley/ad2ecc286c9ad6cefbb7065ba6dfef48
85
 
86
  == Changelog ==
87
 
 
 
 
 
 
 
 
 
 
88
  = 1.3.0 =
89
  * Fix - Fatal Error calling is_main_query.
90
  * Fix - Customer invoice email doesn't allow payment with PPEC.
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.0
7
  License: GPLv3
8
  License URI: http://www.gnu.org/licenses/gpl-3.0.html
9
 
85
 
86
  == Changelog ==
87
 
88
+ = 1.4.0 =
89
+ * Tweak - Use shipping discount instead of tax when adjustment negative.
90
+ * Fix - Cannot process refunds on "authorize" transactions.
91
+ * Add - Option for displaying express checkout button on the product page.
92
+ * Fix - If there are no shipping options in WooCommerce, PayPal doesn't pass a shipping address to WC.
93
+ * Add - Option to set Billing phone number mandatory.
94
+ * Add - Option to disable checkout with PayPal button on Cart page.
95
+ * Fix - Trigger required shipping cost before checkout.
96
+
97
  = 1.3.0 =
98
  * Fix - Fatal Error calling is_main_query.
99
  * Fix - Customer invoice email doesn't allow payment with PPEC.
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.3.0
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.3.0' );
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.0
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.0' );
29
 
30
  /**
31
  * Return instance of WC_Gateway_PPEC_Plugin.