WooCommerce PayPal Express Checkout Payment Gateway - Version 1.0.1

Version Description

Download this release

Release Info

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

Code changes from version 1.0.0 to 1.0.1

includes/abstracts/abstract-wc-gateway-ppec-client-credential.php CHANGED
@@ -95,7 +95,7 @@ abstract class WC_Gateway_PPEC_Client_Credential {
95
  * @return array An array of name-value pairs containing the API credentials
96
  * from this object.
97
  */
98
- protected function get_request_params() {
99
  $params = array(
100
  'USER' => $this->_username,
101
  'PWD' => $this->_password,
@@ -107,4 +107,21 @@ abstract class WC_Gateway_PPEC_Client_Credential {
107
 
108
  return $params;
109
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
110
  }
95
  * @return array An array of name-value pairs containing the API credentials
96
  * from this object.
97
  */
98
+ public function get_request_params() {
99
  $params = array(
100
  'USER' => $this->_username,
101
  'PWD' => $this->_password,
107
 
108
  return $params;
109
  }
110
+
111
+ /**
112
+ * Allow certificate-based credential to configure cURL, especially
113
+ * to set CURLOPT_SSLCERT and CURLOPT_SSLCERTPASSWD.
114
+ *
115
+ * @throws Exception
116
+ *
117
+ * @param resource &$handle The cURL handle returned by curl_init().
118
+ * @param array $r The HTTP request arguments.
119
+ * @param string $url The request URL.
120
+ *
121
+ * @return void
122
+ */
123
+ public function configure_curl( $handle, $r, $url ) {
124
+ curl_setopt( $handle, CURLOPT_CAINFO, wc_gateway_ppec()->includes_path . 'pem/bundle.pem' );
125
+ curl_setopt( $handle, CURLOPT_SSL_CIPHER_LIST, 'TLSv1' );
126
+ }
127
  }
includes/abstracts/abstract-wc-gateway-ppec.php CHANGED
@@ -225,7 +225,7 @@ abstract class WC_Gateway_PPEC extends WC_Payment_Gateway {
225
  $expires = __( 'expires on %s', 'woocommerce-gateway-paypal-express-checkout' );
226
  }
227
 
228
- $expires = sprintf( $out, date_i18n( get_option( 'date_format' ), $valid_until ) );
229
  $out = sprintf( __( 'Certificate belongs to API username %1$s; %2$s', 'woocommerce-gateway-paypal-express-checkout' ), $certinfo['subject']['CN'], $expires );
230
  } else {
231
  $out = __( 'The certificate on file is not valid.', 'woocommerce-gateway-paypal-express-checkout' );
225
  $expires = __( 'expires on %s', 'woocommerce-gateway-paypal-express-checkout' );
226
  }
227
 
228
+ $expires = sprintf( $expires, date_i18n( get_option( 'date_format' ), $valid_until ) );
229
  $out = sprintf( __( 'Certificate belongs to API username %1$s; %2$s', 'woocommerce-gateway-paypal-express-checkout' ), $certinfo['subject']['CN'], $expires );
230
  } else {
231
  $out = __( 'The certificate on file is not valid.', 'woocommerce-gateway-paypal-express-checkout' );
includes/class-wc-gateway-ppec-cart-handler.php CHANGED
@@ -159,7 +159,7 @@ class WC_Gateway_PPEC_Cart_Handler {
159
 
160
  $discounts = round( WC()->cart->get_cart_discount_total(), $decimals );
161
  foreach ( WC()->cart->cart_contents as $cart_item_key => $values ) {
162
- $amount = round( $values['line_total'] / $values['quantity'] , $decimals );
163
  $item = array(
164
  'name' => $values['data']->post->post_title,
165
  'description' => $values['data']->post->post_content,
@@ -172,12 +172,9 @@ class WC_Gateway_PPEC_Cart_Handler {
172
  $roundedPayPalTotal += round( $amount * $values['quantity'], $decimals );
173
  }
174
 
175
- $this->orderTax = round( WC()->cart->tax_total, $decimals );
176
  $this->shipping = round( WC()->cart->shipping_total, $decimals );
177
- if ( WC()->cart->shipping_tax_total != 0 ) {
178
- $this->orderTax += round( WC()->cart->shipping_tax_total, $decimals );
179
- }
180
- $this->totalItemAmount = round( WC()->cart->cart_contents_total, $decimals );
181
  $this->orderTotal = $this->totalItemAmount + $this->orderTax + $this->shipping;
182
 
183
  // need to compare WC totals with what PayPal will calculate to see if they match
@@ -200,6 +197,8 @@ class WC_Gateway_PPEC_Cart_Handler {
200
  );
201
 
202
  $this->items[] = $modifyLineItem;
 
 
203
 
204
  } elseif ( WC_Gateway_PPEC_Settings::subtotalMismatchBehaviorDropLineItems == $subtotalBehavior ) {
205
  // ...
@@ -211,7 +210,7 @@ class WC_Gateway_PPEC_Cart_Handler {
211
 
212
  // enter discount shenanigans. item total cannot be 0 so make modifications accordingly
213
  if ( $this->totalItemAmount == $discounts ) {
214
- $settings = wc_gateway_ppec()->loadSettings();
215
  $behavior = $settings->zeroSubtotalBehavior;
216
 
217
  if ( WC_Gateway_PPEC_Settings::zeroSubtotalBehaviorModifyItems == $behavior ) {
@@ -222,10 +221,10 @@ class WC_Gateway_PPEC_Cart_Handler {
222
  'name' => 'Discount',
223
  'description' => 'Discount Amount',
224
  'quantity' => 1,
225
- 'amount' => $discounts
226
  );
227
 
228
- $this->items[] = $discountLineItme;
229
 
230
  if ( $is_zdp_currency ) {
231
  $discount = 1;
@@ -241,18 +240,23 @@ class WC_Gateway_PPEC_Cart_Handler {
241
  );
242
 
243
  $this->items[] = $modifyLineItem;
244
- $this->shipDiscountAmount = $discount;
 
 
245
 
246
  } elseif ( WC_Gateway_PPEC_Settings::zeroSubtotalBehaviorOmitLineItems == $behavior ) {
247
  // ...
248
  // Omit line items altogether
249
  unset($this->items);
250
  $this->shipDiscountAmount = 0;
 
 
251
 
252
  } else {
253
  // ...
254
  // Increase SHIPDISCAMT by the amount of all the coupons in the cart
255
- $this->shipDiscountAmount = round( WC()->cart->get_order_discount_total(), $decimals );
 
256
 
257
  }
258
  } else {
@@ -269,6 +273,15 @@ class WC_Gateway_PPEC_Cart_Handler {
269
  }
270
 
271
  $this->shipDiscountAmount = 0;
 
 
 
 
 
 
 
 
 
272
  }
273
 
274
  // after all of the discount shenanigans, load up the other standard variables
@@ -280,7 +293,7 @@ class WC_Gateway_PPEC_Cart_Handler {
280
 
281
  if ( ! is_numeric( $this->shipping ) )
282
  $this->shipping = 0;
283
-
284
  }
285
 
286
  public function loadOrderDetails( $order_id ) {
@@ -301,7 +314,7 @@ class WC_Gateway_PPEC_Cart_Handler {
301
 
302
  $discounts = round( $order->get_total_discount(), $decimals );
303
  foreach ( $order->get_items() as $cart_item_key => $values ) {
304
- $amount = round( $values['line_total'] / $values['qty'] , $decimals );
305
  $item = array(
306
  'name' => $values['name'],
307
  'quantity' => $values['qty'],
@@ -309,7 +322,7 @@ class WC_Gateway_PPEC_Cart_Handler {
309
  );
310
 
311
  $this->items[] = $item;
312
-
313
  $roundedPayPalTotal += round( $amount * $values['qty'], $decimals );
314
  }
315
 
@@ -363,10 +376,10 @@ class WC_Gateway_PPEC_Cart_Handler {
363
  'name' => 'Discount',
364
  'description' => 'Discount Amount',
365
  'quantity' => 1,
366
- 'amount' => $discounts
367
  );
368
 
369
- $this->items[] = $discountLineItme;
370
 
371
  if ( $is_zdp_currency ) {
372
  $discount = 1;
@@ -382,19 +395,23 @@ class WC_Gateway_PPEC_Cart_Handler {
382
  );
383
 
384
  $this->items[] = $modifyLineItem;
385
- $this->shipDiscountAmount = $discount;
 
 
386
 
387
  } elseif ( WC_Gateway_PPEC_Settings::zeroSubtotalBehaviorOmitLineItems == $behavior ) {
388
  // ...
389
  // Omit line items altogether
390
  unset($this->items);
391
  $this->shipDiscountAmount = 0;
 
 
392
 
393
  } else {
394
  // ...
395
  // Increase SHIPDISCAMT by the amount of all the coupons in the cart
396
- $this->shipDiscountAmount = round( WC()->cart->get_order_discount_total(), $decimals );
397
-
398
  }
399
  } else {
400
  // Build PayPal_Cart object as normal
@@ -407,10 +424,19 @@ class WC_Gateway_PPEC_Cart_Handler {
407
  );
408
 
409
  $this->items[] = $discLineItem;
 
 
410
  }
411
 
412
  $this->shipDiscountAmount = 0;
413
  }
 
 
 
 
 
 
 
414
 
415
  // after all of the discount shenanigans, load up the other standard variables
416
  $this->insurance = 0;
159
 
160
  $discounts = round( WC()->cart->get_cart_discount_total(), $decimals );
161
  foreach ( WC()->cart->cart_contents as $cart_item_key => $values ) {
162
+ $amount = round( $values['line_subtotal'] / $values['quantity'] , $decimals );
163
  $item = array(
164
  'name' => $values['data']->post->post_title,
165
  'description' => $values['data']->post->post_content,
172
  $roundedPayPalTotal += round( $amount * $values['quantity'], $decimals );
173
  }
174
 
175
+ $this->orderTax = round( WC()->cart->tax_total + WC()->cart->shipping_tax_total, $decimals );
176
  $this->shipping = round( WC()->cart->shipping_total, $decimals );
177
+ $this->totalItemAmount = round( WC()->cart->cart_contents_total, $decimals ) + $discounts;
 
 
 
178
  $this->orderTotal = $this->totalItemAmount + $this->orderTax + $this->shipping;
179
 
180
  // need to compare WC totals with what PayPal will calculate to see if they match
197
  );
198
 
199
  $this->items[] = $modifyLineItem;
200
+ $this->totalItemAmount += $modifyLineItem[ 'amount' ];
201
+ $this->orderTotal += $modifyLineItem[ 'amount' ];
202
 
203
  } elseif ( WC_Gateway_PPEC_Settings::subtotalMismatchBehaviorDropLineItems == $subtotalBehavior ) {
204
  // ...
210
 
211
  // enter discount shenanigans. item total cannot be 0 so make modifications accordingly
212
  if ( $this->totalItemAmount == $discounts ) {
213
+ $settings = wc_gateway_ppec()->settings->loadSettings();
214
  $behavior = $settings->zeroSubtotalBehavior;
215
 
216
  if ( WC_Gateway_PPEC_Settings::zeroSubtotalBehaviorModifyItems == $behavior ) {
221
  'name' => 'Discount',
222
  'description' => 'Discount Amount',
223
  'quantity' => 1,
224
+ 'amount' => -$discounts
225
  );
226
 
227
+ $this->items[] = $discountLineItem;
228
 
229
  if ( $is_zdp_currency ) {
230
  $discount = 1;
240
  );
241
 
242
  $this->items[] = $modifyLineItem;
243
+ $this->shipDiscountAmount = -$discount;
244
+ $this->totalItemAmount = $this->totalItemAmount - $discounts + $discount;
245
+ $this->orderTotal -= $discounts;
246
 
247
  } elseif ( WC_Gateway_PPEC_Settings::zeroSubtotalBehaviorOmitLineItems == $behavior ) {
248
  // ...
249
  // Omit line items altogether
250
  unset($this->items);
251
  $this->shipDiscountAmount = 0;
252
+ $this->totalItemAmount -= $discounts;
253
+ $this->orderTotal -= $discounts;
254
 
255
  } else {
256
  // ...
257
  // Increase SHIPDISCAMT by the amount of all the coupons in the cart
258
+ $this->shipDiscountAmount = -$discounts;
259
+ $this->orderTotal -= $discounts;
260
 
261
  }
262
  } else {
273
  }
274
 
275
  $this->shipDiscountAmount = 0;
276
+ $this->totalItemAmount -= $discounts;
277
+ $this->orderTotal -= $discounts;
278
+ }
279
+
280
+ // If the totals don't line up, adjust the tax to make it work (cause it's probably a tax mismatch).
281
+ $wooOrderTotal = round( WC()->cart->total, $decimals );
282
+ if( $wooOrderTotal != $this->orderTotal ) {
283
+ $this->orderTax += $wooOrderTotal - $this->orderTotal;
284
+ $this->orderTotal = $wooOrderTotal;
285
  }
286
 
287
  // after all of the discount shenanigans, load up the other standard variables
293
 
294
  if ( ! is_numeric( $this->shipping ) )
295
  $this->shipping = 0;
296
+
297
  }
298
 
299
  public function loadOrderDetails( $order_id ) {
314
 
315
  $discounts = round( $order->get_total_discount(), $decimals );
316
  foreach ( $order->get_items() as $cart_item_key => $values ) {
317
+ $amount = round( $values['line_subtotal'] / $values['qty'] , $decimals );
318
  $item = array(
319
  'name' => $values['name'],
320
  'quantity' => $values['qty'],
322
  );
323
 
324
  $this->items[] = $item;
325
+
326
  $roundedPayPalTotal += round( $amount * $values['qty'], $decimals );
327
  }
328
 
376
  'name' => 'Discount',
377
  'description' => 'Discount Amount',
378
  'quantity' => 1,
379
+ 'amount' => -$discounts
380
  );
381
 
382
+ $this->items[] = $discountLineItem;
383
 
384
  if ( $is_zdp_currency ) {
385
  $discount = 1;
395
  );
396
 
397
  $this->items[] = $modifyLineItem;
398
+ $this->shipDiscountAmount = -$discount;
399
+ $this->totalItemAmount = $this->totalItemAmount - $discounts + $discount;
400
+ $this->orderTotal -= $discounts;
401
 
402
  } elseif ( WC_Gateway_PPEC_Settings::zeroSubtotalBehaviorOmitLineItems == $behavior ) {
403
  // ...
404
  // Omit line items altogether
405
  unset($this->items);
406
  $this->shipDiscountAmount = 0;
407
+ $this->totalItemAmount -= $discounts;
408
+ $this->orderTotal -= $discounts;
409
 
410
  } else {
411
  // ...
412
  // Increase SHIPDISCAMT by the amount of all the coupons in the cart
413
+ $this->shipDiscountAmount = -$discounts;
414
+ $this->orderTotal -= $discounts;
415
  }
416
  } else {
417
  // Build PayPal_Cart object as normal
424
  );
425
 
426
  $this->items[] = $discLineItem;
427
+ $this->totalItemAmount -= $discounts;
428
+ $this->orderTotal -= $discounts;
429
  }
430
 
431
  $this->shipDiscountAmount = 0;
432
  }
433
+
434
+ // If the totals don't line up, adjust the tax to make it work (cause it's probably a tax mismatch).
435
+ $wooOrderTotal = round( $order->get_total(), $decimals );
436
+ if( $wooOrderTotal != $this->orderTotal ) {
437
+ $this->orderTax += $wooOrderTotal - $this->orderTotal;
438
+ $this->orderTotal = $wooOrderTotal;
439
+ }
440
 
441
  // after all of the discount shenanigans, load up the other standard variables
442
  $this->insurance = 0;
includes/class-wc-gateway-ppec-client-credential-certificate.php CHANGED
@@ -43,4 +43,104 @@ class WC_Gateway_PPEC_Client_Credential_Certificate extends WC_Gateway_PPEC_Clie
43
  public function get_certificate() {
44
  return $this->_certificate;
45
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
46
  }
43
  public function get_certificate() {
44
  return $this->_certificate;
45
  }
46
+
47
+ /**
48
+ * Allow certificate-based credential to configure cURL, especially
49
+ * to set CURLOPT_SSLCERT and CURLOPT_SSLCERTPASSWD.
50
+ *
51
+ * @throws Exception
52
+ *
53
+ * @param resource &$handle The cURL handle returned by curl_init().
54
+ * @param array $r The HTTP request arguments.
55
+ * @param string $url The request URL.
56
+ *
57
+ * @return void
58
+ */
59
+ public function configure_curl( $handle, $r, $url ) {
60
+ parent::configure_curl( $handle, $r, $url );
61
+
62
+ $password = uniqid();
63
+ $certificate_file = $this->_maybe_create_certificate_file( $password );
64
+
65
+ if ( false === curl_setopt( $handle, CURLOPT_SSLCERT, $certificate_file ) ) {
66
+ throw new Exception( __( 'Unable to accept certificate during cURL configuration', 'woocommerce-gateway-ppec' ), WC_Gateway_PPEC_Client::INVALID_ENVIRONMENT_ERROR );
67
+ }
68
+
69
+ if ( $this->_use_secure_transport() && false === curl_setopt( $handle, CURLOPT_SSLCERTPASSWD, $password ) ) {
70
+ throw new Exception( __( 'Unable to accept certificate password during cURL configuration', 'woocommerce-gateway-ppec' ), WC_Gateway_PPEC_Client::INVALID_ENVIRONMENT_ERROR );
71
+ }
72
+ }
73
+
74
+ /**
75
+ * Dump the certificate out to a temporary file, because cURL can't accept
76
+ * it any other way.
77
+ *
78
+ * @throws Exception
79
+ *
80
+ * @param string $password Password for certificate when using secure transport
81
+ *
82
+ * @return string Filepath of certificate file
83
+ */
84
+ protected function _maybe_create_certificate_file( $password ) {
85
+ $temp_file = tempnam( sys_get_temp_dir(), 'pptmp_' );
86
+ if ( ! $temp_file ) {
87
+ throw new Exception( sprintf( __( 'Unable to write certificate file %s during cURL configuration', 'woocommerce-gateway-ppec' ), $temp_file ), WC_Gateway_PPEC_Client::INVALID_ENVIRONMENT_ERROR );
88
+ }
89
+
90
+ if ( $this->_use_secure_transport() ) {
91
+ $this->_maybe_create_secure_certificate_file( $temp_file, $password );
92
+ } else {
93
+ $this->_maybe_create_non_secure_certificate_file( $temp_file );
94
+ }
95
+
96
+ return $temp_file;
97
+ }
98
+
99
+ /**
100
+ * If we're using SecureTransport, we have to translate the certificate to
101
+ * PKCS12 before passing it to cURL.
102
+ *
103
+ * @throws Exception
104
+ *
105
+ * @param string $temp_file Filepath to temporary certificate file
106
+ *
107
+ * @return void
108
+ */
109
+ protected function _maybe_create_secure_certificate_file( $temp_file, $password ) {
110
+ $private_key = openssl_pkey_get_private( $this->_certificate );
111
+
112
+ if ( false === $private_key ) {
113
+ throw new Exception( __( 'Failed to retrieve private key during cURL configuration', 'woocommerce-gateway-ppec' ), WC_Gateway_PPEC_Client::INVALID_ENVIRONMENT_ERROR );
114
+ }
115
+
116
+ if ( ! openssl_pkcs12_export_to_file( $this->_certificate, $temp_file, $private_key, $password ) ) {
117
+ throw new Exception( __( 'Failed to export PKCS12 file during cURL configuration', 'woocommerce-gateway-ppec' ), WC_Gateway_PPEC_Client::INVALID_ENVIRONMENT_ERROR );
118
+ }
119
+ }
120
+
121
+ /**
122
+ * Create non-password certificate file. Basically just dump the certificate
123
+ * string to temporary file.
124
+ *
125
+ * @throws Exception
126
+ *
127
+ * @param string $temp_file Filepath to temporary certificate file
128
+ *
129
+ * @return void
130
+ */
131
+ protected function _maybe_create_non_secure_certificate_file( $temp_file ) {
132
+ if ( false === file_put_contents( $temp_file, $this->_certificate ) ) {
133
+ throw new Exception( sprintf( __( 'Unable to write certificate file %s during cURL configuration', 'woocommerce-gateway-ppec' ), $temp_file ), WC_Gateway_PPEC_Client::INVALID_ENVIRONMENT_ERROR );
134
+ }
135
+ }
136
+
137
+ /**
138
+ * Returns true if secure transport is available in current cURL.
139
+ *
140
+ * @return bool
141
+ */
142
+ protected function _use_secure_transport() {
143
+ $curl_version = curl_version();
144
+ return false !== strpos( $curl_version['ssl_version'], 'SecureTransport' );
145
+ }
146
  }
includes/class-wc-gateway-ppec-client.php CHANGED
@@ -115,6 +115,9 @@ class WC_Gateway_PPEC_Client {
115
  'httpversion' => '1.1',
116
  );
117
 
 
 
 
118
  wc_gateway_ppec_log( sprintf( '%s: remote request to %s with args: %s', __METHOD__, $this->get_endpoint(), print_r( $args, true ) ) );
119
 
120
  $resp = wp_safe_remote_post( $this->get_endpoint(), $args );
@@ -133,11 +136,15 @@ class WC_Gateway_PPEC_Client {
133
 
134
  wc_gateway_ppec_log( sprintf( '%s: acknowleged response body: %s', __METHOD__, print_r( $result, true ) ) );
135
 
 
 
136
  // Let the caller deals with the response.
137
  return $result;
138
 
139
  } catch ( Exception $e ) {
140
 
 
 
141
  // TODO: Maybe returns WP_Error ?
142
  $error = array(
143
  'ACK' => 'Failure',
115
  'httpversion' => '1.1',
116
  );
117
 
118
+ // For cURL transport.
119
+ add_action( 'http_api_curl', array( $this->_credential, 'configure_curl' ), 10, 3 );
120
+
121
  wc_gateway_ppec_log( sprintf( '%s: remote request to %s with args: %s', __METHOD__, $this->get_endpoint(), print_r( $args, true ) ) );
122
 
123
  $resp = wp_safe_remote_post( $this->get_endpoint(), $args );
136
 
137
  wc_gateway_ppec_log( sprintf( '%s: acknowleged response body: %s', __METHOD__, print_r( $result, true ) ) );
138
 
139
+ remove_action( 'http_api_curl', array( $this->_credential, 'configure_curl' ), 10 );
140
+
141
  // Let the caller deals with the response.
142
  return $result;
143
 
144
  } catch ( Exception $e ) {
145
 
146
+ remove_action( 'http_api_curl', array( $this->_credential, 'configure_curl' ), 10 );
147
+
148
  // TODO: Maybe returns WP_Error ?
149
  $error = array(
150
  'ACK' => 'Failure',
includes/class-wc-gateway-ppec-plugin.php CHANGED
@@ -128,6 +128,25 @@ class WC_Gateway_PPEC_Plugin {
128
  if ( version_compare( WC()->version, '2.5', '<' ) ) {
129
  throw new Exception( __( 'WooCommerce Gateway PayPal Express Checkout requires WooCommerce version 2.5 or greater', 'woocommerce-gateway-paypal-express-checkout' ) );
130
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
131
  }
132
 
133
  /**
128
  if ( version_compare( WC()->version, '2.5', '<' ) ) {
129
  throw new Exception( __( 'WooCommerce Gateway PayPal Express Checkout requires WooCommerce version 2.5 or greater', 'woocommerce-gateway-paypal-express-checkout' ) );
130
  }
131
+
132
+ if ( ! function_exists( 'curl_init' ) ) {
133
+ throw new Exception( __( 'WooCommerce Gateway PayPal Express Checkout requires cURL to be installed on your server', 'woocommerce-gateway-paypal-express-checkout' ) );
134
+ }
135
+
136
+ $openssl_warning = __( 'WooCommerce Gateway PayPal Express Checkout requires OpenSSL >= 1.0.1 to be installed on your server', 'woocommerce-gateway-paypal-express-checkout' );
137
+ if ( ! defined( 'OPENSSL_VERSION_TEXT' ) ) {
138
+ throw new Exception( $openssl_warning );
139
+ }
140
+
141
+ preg_match( '/^OpenSSL ([\d.]+)/', OPENSSL_VERSION_TEXT, $matches );
142
+ if ( empty( $matches[1] ) ) {
143
+ throw new Exception( $openssl_warning );
144
+ }
145
+
146
+
147
+ if ( ! version_compare( $matches[1], '1.0.1', '>=' ) ) {
148
+ throw new Exception( $openssl_warning );
149
+ }
150
  }
151
 
152
  /**
includes/pem/bundle.pem ADDED
@@ -0,0 +1,117 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ -----BEGIN CERTIFICATE-----
2
+ MIIFWDCCBECgAwIBAgIQB8o+TSd/21eGoIdLI1qp6zANBgkqhkiG9w0BAQUFADCB
3
+ tTELMAkGA1UEBhMCVVMxFzAVBgNVBAoTDlZlcmlTaWduLCBJbmMuMR8wHQYDVQQL
4
+ ExZWZXJpU2lnbiBUcnVzdCBOZXR3b3JrMTswOQYDVQQLEzJUZXJtcyBvZiB1c2Ug
5
+ YXQgaHR0cHM6Ly93d3cudmVyaXNpZ24uY29tL3JwYSAoYykxMDEvMC0GA1UEAxMm
6
+ VmVyaVNpZ24gQ2xhc3MgMyBTZWN1cmUgU2VydmVyIENBIC0gRzMwHhcNMTMwODAx
7
+ MDAwMDAwWhcNMTUwOTE4MjM1OTU5WjCBjDELMAkGA1UEBhMCVVMxEzARBgNVBAgT
8
+ CkNhbGlmb3JuaWExETAPBgNVBAcUCFNhbiBKb3NlMRUwEwYDVQQKFAxQYXlQYWws
9
+ IEluYy4xGjAYBgNVBAsUEVBheVBhbCBQcm9kdWN0aW9uMSIwIAYDVQQDFBlhcGkt
10
+ M3Quc2FuZGJveC5wYXlwYWwuY29tMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIB
11
+ CgKCAQEAqpUTPy8lOveTpJd8RBUWI73HcyLtNw+RbS2sxXa+7t3XTc6IEF0bF6dS
12
+ 55d4r4GjU+eiFKYXx9atIO7aNnIp7ebVtPJTBBdRLFHwzpKmOhNPbwOozrThfY5F
13
+ KKVAjniUS+5qnxrRVGB3c42W+EVLu8xagQvRnTKr5DYA1lSLHmiXYUcuGgpvSF6p
14
+ OcHy5iKM3FIVTc98rxgUdlbh4L3Sv0HdGaPbx4UPJ41ft7ZsjHqoCIjNP9tZuMBn
15
+ 6m/l+eCIiTvZYVJgHXkwz6pm5WP92hqsl3Ts+V/7jyJYJIqg+aWUc/DjZVkU9JND
16
+ PqQUuj88uM695MZyzS2pdbPAeQZ57wIDAQABo4IBiTCCAYUwJAYDVR0RBB0wG4IZ
17
+ YXBpLTN0LnNhbmRib3gucGF5cGFsLmNvbTAJBgNVHRMEAjAAMA4GA1UdDwEB/wQE
18
+ AwIFoDAdBgNVHSUEFjAUBggrBgEFBQcDAQYIKwYBBQUHAwIwQwYDVR0gBDwwOjA4
19
+ BgpghkgBhvhFAQc2MCowKAYIKwYBBQUHAgEWHGh0dHBzOi8vd3d3LnZlcmlzaWdu
20
+ LmNvbS9jcHMwHwYDVR0jBBgwFoAUDURcFlNEwYJ+HSCrJfQBY9i+eaUwRQYDVR0f
21
+ BD4wPDA6oDigNoY0aHR0cDovL1NWUlNlY3VyZS1HMy1jcmwudmVyaXNpZ24uY29t
22
+ L1NWUlNlY3VyZUczLmNybDB2BggrBgEFBQcBAQRqMGgwJAYIKwYBBQUHMAGGGGh0
23
+ dHA6Ly9vY3NwLnZlcmlzaWduLmNvbTBABggrBgEFBQcwAoY0aHR0cDovL1NWUlNl
24
+ Y3VyZS1HMy1haWEudmVyaXNpZ24uY29tL1NWUlNlY3VyZUczLmNlcjANBgkqhkiG
25
+ 9w0BAQUFAAOCAQEASUdxPQFgUi6sSDJ4Aw071gf0sHRiiFMdZSJazmVxQA8/bpiD
26
+ CFDq5rYEMR8jqQMx4bPfeUjAZVwmT0q7YlLRGnDEyur6fd7yv1pbCCN0anfwORE2
27
+ tn/6yxgBp9JPaOc4k8mWbYr/1p94V/tlvaqZ52Cz8gQ7pMuvmWLgJuAhk0hdtNXq
28
+ vktqDfGCxdv+8CgoUdTQOdqQEkcz7HueAQ7DLCXum530p+QpQQy0xKT2+EzIXnHC
29
+ erln4DHogkj8dWt+oehtRZwChX5Aczig1P3zBW8SBuZwS1b8XZKudr7kFpZg1/S3
30
+ U30gP7d3TEvbnVtXSjTl3xLT3848FbJbfGmNKg==
31
+ -----END CERTIFICATE-----
32
+ -----BEGIN CERTIFICATE-----
33
+ MIIF7DCCBNSgAwIBAgIQbsx6pacDIAm4zrz06VLUkTANBgkqhkiG9w0BAQUFADCB
34
+ yjELMAkGA1UEBhMCVVMxFzAVBgNVBAoTDlZlcmlTaWduLCBJbmMuMR8wHQYDVQQL
35
+ ExZWZXJpU2lnbiBUcnVzdCBOZXR3b3JrMTowOAYDVQQLEzEoYykgMjAwNiBWZXJp
36
+ U2lnbiwgSW5jLiAtIEZvciBhdXRob3JpemVkIHVzZSBvbmx5MUUwQwYDVQQDEzxW
37
+ ZXJpU2lnbiBDbGFzcyAzIFB1YmxpYyBQcmltYXJ5IENlcnRpZmljYXRpb24gQXV0
38
+ aG9yaXR5IC0gRzUwHhcNMTAwMjA4MDAwMDAwWhcNMjAwMjA3MjM1OTU5WjCBtTEL
39
+ MAkGA1UEBhMCVVMxFzAVBgNVBAoTDlZlcmlTaWduLCBJbmMuMR8wHQYDVQQLExZW
40
+ ZXJpU2lnbiBUcnVzdCBOZXR3b3JrMTswOQYDVQQLEzJUZXJtcyBvZiB1c2UgYXQg
41
+ aHR0cHM6Ly93d3cudmVyaXNpZ24uY29tL3JwYSAoYykxMDEvMC0GA1UEAxMmVmVy
42
+ aVNpZ24gQ2xhc3MgMyBTZWN1cmUgU2VydmVyIENBIC0gRzMwggEiMA0GCSqGSIb3
43
+ DQEBAQUAA4IBDwAwggEKAoIBAQCxh4QfwgxF9byrJZenraI+nLr2wTm4i8rCrFbG
44
+ 5btljkRPTc5v7QlK1K9OEJxoiy6Ve4mbE8riNDTB81vzSXtig0iBdNGIeGwCU/m8
45
+ f0MmV1gzgzszChew0E6RJK2GfWQS3HRKNKEdCuqWHQsV/KNLO85jiND4LQyUhhDK
46
+ tpo9yus3nABINYYpUHjoRWPNGUFP9ZXse5jUxHGzUL4os4+guVOc9cosI6n9FAbo
47
+ GLSa6Dxugf3kzTU2s1HTaewSulZub5tXxYsU5w7HnO1KVGrJTcW/EbGuHGeBy0RV
48
+ M5l/JJs/U0V/hhrzPPptf4H1uErT9YU3HLWm0AnkGHs4TvoPAgMBAAGjggHfMIIB
49
+ 2zA0BggrBgEFBQcBAQQoMCYwJAYIKwYBBQUHMAGGGGh0dHA6Ly9vY3NwLnZlcmlz
50
+ aWduLmNvbTASBgNVHRMBAf8ECDAGAQH/AgEAMHAGA1UdIARpMGcwZQYLYIZIAYb4
51
+ RQEHFwMwVjAoBggrBgEFBQcCARYcaHR0cHM6Ly93d3cudmVyaXNpZ24uY29tL2Nw
52
+ czAqBggrBgEFBQcCAjAeGhxodHRwczovL3d3dy52ZXJpc2lnbi5jb20vcnBhMDQG
53
+ A1UdHwQtMCswKaAnoCWGI2h0dHA6Ly9jcmwudmVyaXNpZ24uY29tL3BjYTMtZzUu
54
+ Y3JsMA4GA1UdDwEB/wQEAwIBBjBtBggrBgEFBQcBDARhMF+hXaBbMFkwVzBVFglp
55
+ bWFnZS9naWYwITAfMAcGBSsOAwIaBBSP5dMahqyNjmvDz4Bq1EgYLHsZLjAlFiNo
56
+ dHRwOi8vbG9nby52ZXJpc2lnbi5jb20vdnNsb2dvLmdpZjAoBgNVHREEITAfpB0w
57
+ GzEZMBcGA1UEAxMQVmVyaVNpZ25NUEtJLTItNjAdBgNVHQ4EFgQUDURcFlNEwYJ+
58
+ HSCrJfQBY9i+eaUwHwYDVR0jBBgwFoAUf9Nlp8Ld7LvwMAnzQzn6Aq8zMTMwDQYJ
59
+ KoZIhvcNAQEFBQADggEBAAyDJO/dwwzZWJz+NrbrioBL0aP3nfPMU++CnqOh5pfB
60
+ WJ11bOAdG0z60cEtBcDqbrIicFXZIDNAMwfCZYP6j0M3m+oOmmxw7vacgDvZN/R6
61
+ bezQGH1JSsqZxxkoor7YdyT3hSaGbYcFQEFn0Sc67dxIHSLNCwuLvPSxe/20majp
62
+ dirhGi2HbnTTiN0eIsbfFrYrghQKlFzyUOyvzv9iNw2tZdMGQVPtAhTItVgooazg
63
+ W+yzf5VK+wPIrSbb5mZ4EkrZn0L74ZjmQoObj49nJOhhGbXdzbULJgWOw27EyHW4
64
+ Rs/iGAZeqa6ogZpHFt4MKGwlJ7net4RYxh84HqTEy2Y=
65
+ -----END CERTIFICATE-----
66
+ -----BEGIN CERTIFICATE-----
67
+ MIIFyTCCBTKgAwIBAgIQek8uV8VnNIp7IFhGnUesRTANBgkqhkiG9w0BAQUFADCB
68
+ wTELMAkGA1UEBhMCVVMxFzAVBgNVBAoTDlZlcmlTaWduLCBJbmMuMTwwOgYDVQQL
69
+ EzNDbGFzcyAzIFB1YmxpYyBQcmltYXJ5IENlcnRpZmljYXRpb24gQXV0aG9yaXR5
70
+ IC0gRzIxOjA4BgNVBAsTMShjKSAxOTk4IFZlcmlTaWduLCBJbmMuIC0gRm9yIGF1
71
+ dGhvcml6ZWQgdXNlIG9ubHkxHzAdBgNVBAsTFlZlcmlTaWduIFRydXN0IE5ldHdv
72
+ cmswHhcNMDYxMTA4MDAwMDAwWhcNMjExMTA3MjM1OTU5WjCByjELMAkGA1UEBhMC
73
+ VVMxFzAVBgNVBAoTDlZlcmlTaWduLCBJbmMuMR8wHQYDVQQLExZWZXJpU2lnbiBU
74
+ cnVzdCBOZXR3b3JrMTowOAYDVQQLEzEoYykgMjAwNiBWZXJpU2lnbiwgSW5jLiAt
75
+ IEZvciBhdXRob3JpemVkIHVzZSBvbmx5MUUwQwYDVQQDEzxWZXJpU2lnbiBDbGFz
76
+ cyAzIFB1YmxpYyBQcmltYXJ5IENlcnRpZmljYXRpb24gQXV0aG9yaXR5IC0gRzUw
77
+ ggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCvJAgIKXo1nmAMqudLO07c
78
+ fLw8RRy7K+D+KQL5VwijZIUVJ/XxrcgxiV0i6CqqpkKzj/i5Vbext0uz/o9+B1fs
79
+ 70PbZmIVYc9gDaTY3vjgw2IIPVQT60nKWVSFJuUrjxuf6/WhkcIzSdhDY2pSS9KP
80
+ 6HBRTdGJaXvHcPaz3BJ023tdS1bTlr8Vd6Gw9KIl8q8ckmcY5fQGBO+QueQA5N06
81
+ tRn/Arr0PO7gi+s3i+z016zy9vA9r911kTMZHRxAy3QkGSGT2RT+rCpSx4/VBEnk
82
+ jWNHiDxpg8v+R70rfk/Fla4OndTRQ8Bnc+MUCH7lP59zuDMKz10/NIeWiu5T6CUV
83
+ AgMBAAGjggIxMIICLTAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIBBjA9
84
+ BgNVHSAENjA0MDIGBFUdIAAwKjAoBggrBgEFBQcCARYcaHR0cHM6Ly93d3cudmVy
85
+ aXNpZ24uY29tL2NwczAdBgNVHQ4EFgQUf9Nlp8Ld7LvwMAnzQzn6Aq8zMTMwbQYI
86
+ KwYBBQUHAQwEYTBfoV2gWzBZMFcwVRYJaW1hZ2UvZ2lmMCEwHzAHBgUrDgMCGgQU
87
+ j+XTGoasjY5rw8+AatRIGCx7GS4wJRYjaHR0cDovL2xvZ28udmVyaXNpZ24uY29t
88
+ L3ZzbG9nby5naWYwNAYDVR0fBC0wKzApoCegJYYjaHR0cDovL2NybC52ZXJpc2ln
89
+ bi5jb20vcGNhMy1nMi5jcmwwHQYDVR0lBBYwFAYIKwYBBQUHAwEGCCsGAQUFBwMC
90
+ MIHnBgNVHSMEgd8wgdyhgcekgcQwgcExCzAJBgNVBAYTAlVTMRcwFQYDVQQKEw5W
91
+ ZXJpU2lnbiwgSW5jLjE8MDoGA1UECxMzQ2xhc3MgMyBQdWJsaWMgUHJpbWFyeSBD
92
+ ZXJ0aWZpY2F0aW9uIEF1dGhvcml0eSAtIEcyMTowOAYDVQQLEzEoYykgMTk5OCBW
93
+ ZXJpU2lnbiwgSW5jLiAtIEZvciBhdXRob3JpemVkIHVzZSBvbmx5MR8wHQYDVQQL
94
+ ExZWZXJpU2lnbiBUcnVzdCBOZXR3b3JrghB92f4Hz6getxB5Z/uniTTGMA0GCSqG
95
+ SIb3DQEBBQUAA4GBACca3K/R32nu+7tGBJ42k7SZ2f8Qk1+WLePXvICJmPKoaa87
96
+ LDVJgn/0lLMfmSON8O9Y1Z3ERVtwScITLo8C3ycnXngGNOQgRQJ9+pGhjE7rPGhF
97
+ Gx57i4p49zVt5Xh9uE50iML9njdENzUc6Tgi7e3Pp9Z3RDZqA0WjAQ3vq/uC
98
+ -----END CERTIFICATE-----
99
+ -----BEGIN CERTIFICATE-----
100
+ MIIDAjCCAmsCEH3Z/gfPqB63EHln+6eJNMYwDQYJKoZIhvcNAQEFBQAwgcExCzAJ
101
+ BgNVBAYTAlVTMRcwFQYDVQQKEw5WZXJpU2lnbiwgSW5jLjE8MDoGA1UECxMzQ2xh
102
+ c3MgMyBQdWJsaWMgUHJpbWFyeSBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eSAtIEcy
103
+ MTowOAYDVQQLEzEoYykgMTk5OCBWZXJpU2lnbiwgSW5jLiAtIEZvciBhdXRob3Jp
104
+ emVkIHVzZSBvbmx5MR8wHQYDVQQLExZWZXJpU2lnbiBUcnVzdCBOZXR3b3JrMB4X
105
+ DTk4MDUxODAwMDAwMFoXDTI4MDgwMTIzNTk1OVowgcExCzAJBgNVBAYTAlVTMRcw
106
+ FQYDVQQKEw5WZXJpU2lnbiwgSW5jLjE8MDoGA1UECxMzQ2xhc3MgMyBQdWJsaWMg
107
+ UHJpbWFyeSBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eSAtIEcyMTowOAYDVQQLEzEo
108
+ YykgMTk5OCBWZXJpU2lnbiwgSW5jLiAtIEZvciBhdXRob3JpemVkIHVzZSBvbmx5
109
+ MR8wHQYDVQQLExZWZXJpU2lnbiBUcnVzdCBOZXR3b3JrMIGfMA0GCSqGSIb3DQEB
110
+ AQUAA4GNADCBiQKBgQDMXtERXVxp0KvTuWpMmR9ZmDCOFoUgRm1HP9SFIIThbbP4
111
+ pO0M8RcPO/mn+SXXwc+EY/J8Y8+iR/LGWzOOZEAEaMGAuWQcRXfH2G71lSk8UOg0
112
+ 13gfqLptQ5GVj0VXXn7F+8qkBOvqlzdUMG+7AUcyM83cV5tkaWH4mx0ciU9cZwID
113
+ AQABMA0GCSqGSIb3DQEBBQUAA4GBAFFNzb5cy5gZnBWyATl4Lk0PZ3BwmcYQWpSk
114
+ U01UbSuvDV1Ai2TT1+7eVmGSX6bEHRBhNtMsJzzoKQm5EWR0zLVznxxIqbxhAe7i
115
+ F6YM40AIOw7n60RzKprxaZLvcRTDOaxxp5EJb+RxBrO6WVcmeQD2+A2iMzAo1KpY
116
+ oJ2daZH9
117
+ -----END CERTIFICATE-----
readme.txt CHANGED
@@ -1,9 +1,9 @@
1
  === WooCommerce PayPal Express Checkout Payment Gateway ===
2
- Contributors: automattic, woothemes, akeda, dwainm, royho, allendav, slash1andy, woosteve, spraveenitpro, mikedmoore, fernashes, shellbeezy
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.4
6
- Stable tag: 1.0.0
7
  License: GPLv3
8
  License URI: http://www.gnu.org/licenses/gpl-3.0.html
9
 
@@ -56,7 +56,7 @@ Yes it does - production and sandbox mode is driven by how you connect. You may
56
 
57
  = Where can I find documentation? =
58
 
59
- For help setting up and configuring, please refer to our [user guide](http://docs.woothemes.com/document/woocommerce-gateway-paypal-express-checkout/)
60
 
61
  = Where can I get support or talk to other users? =
62
 
@@ -80,6 +80,13 @@ New feature requests and bugs reports can be made in the plugin forum.
80
 
81
  == Changelog ==
82
 
 
 
 
 
 
 
 
83
  = 1.0.0 =
84
  * Initial stable release
85
 
1
  === WooCommerce PayPal Express Checkout Payment Gateway ===
2
+ Contributors: automattic, woothemes, akeda, dwainm, royho, allendav, slash1andy, woosteve, spraveenitpro, mikedmoore, fernashes, shellbeezy, danieldudzic, mikaey
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.4
6
+ Stable tag: 1.0.1
7
  License: GPLv3
8
  License URI: http://www.gnu.org/licenses/gpl-3.0.html
9
 
56
 
57
  = Where can I find documentation? =
58
 
59
+ For help setting up and configuring, please refer to our [user guide](https://www.woothemes.com/products/woocommerce-gateway-paypal-express-checkout/)
60
 
61
  = Where can I get support or talk to other users? =
62
 
80
 
81
  == Changelog ==
82
 
83
+ = 1.0.1
84
+ * Fix - Make sure OpenSSL is installed with 1.0.1 as the minium required version, otherwise display warning
85
+ * Fix - Make sure cURL transport is available for WP HTTP API, otherwise display warning
86
+ * Fix - Unhandled certificate-style API credential
87
+ * Fix - Fixed calculated tax and coupons data that sent over to PayPal
88
+ * Fix - Fixed calculated shipping discount data that sent over to PayPal
89
+
90
  = 1.0.0 =
91
  * Initial stable release
92
 
woocommerce-gateway-paypal-express-checkout.php CHANGED
@@ -3,7 +3,7 @@
3
  * Plugin Name: WooCommerce PayPal Express Checkout Gateway
4
  * Plugin URI: https://woothemes.com
5
  * Description: A payment gateway for PayPal Express Checkout ( https://www.paypal.com/us/webapps/mpp/express-checkout ). Requires WC 2.5+
6
- * Version: 1.0.0
7
  * Author: Automattic/WooCommerce
8
  * Author URI: https://woocommerce.com
9
  * Copyright: © 2016 WooCommerce / PayPal.
@@ -36,7 +36,7 @@ function wc_gateway_ppec() {
36
  if ( ! isset( $plugin ) ) {
37
  require_once( 'includes/class-wc-gateway-ppec-plugin.php' );
38
 
39
- $plugin = new WC_Gateway_PPEC_Plugin( __FILE__, '1.0.0' );
40
  }
41
 
42
  return $plugin;
3
  * Plugin Name: WooCommerce PayPal Express Checkout Gateway
4
  * Plugin URI: https://woothemes.com
5
  * Description: A payment gateway for PayPal Express Checkout ( https://www.paypal.com/us/webapps/mpp/express-checkout ). Requires WC 2.5+
6
+ * Version: 1.0.1
7
  * Author: Automattic/WooCommerce
8
  * Author URI: https://woocommerce.com
9
  * Copyright: © 2016 WooCommerce / PayPal.
36
  if ( ! isset( $plugin ) ) {
37
  require_once( 'includes/class-wc-gateway-ppec-plugin.php' );
38
 
39
+ $plugin = new WC_Gateway_PPEC_Plugin( __FILE__, '1.0.1' );
40
  }
41
 
42
  return $plugin;