WooCommerce Stripe Payment Gateway - Version 5.0.0

Version Description

  • 2021-03-17 =

  • Add - Display time of last Stripe webhook in settings.

  • Add - wc_stripe_webhook_validate_user_agent filter to customize webhook user-agent validation.

  • Fix - Payment Request Buttons for Chinese provinces in Chrome.

  • Fix - Enable wc_stripe_send_stripe_receipt filter to send Stripe emails.

  • Fix - Check for more errors when attaching sources to customers.

See changelog for all versions.

Download this release

Release Info

Developer automattic
Plugin Icon 128x128 WooCommerce Stripe Payment Gateway
Version 5.0.0
Comparing to
See all releases

Code changes from version 4.9.0 to 5.0.0

Files changed (57) hide show
  1. changelog.txt +7 -0
  2. includes/abstracts/abstract-wc-stripe-connect-rest-controller.php +21 -19
  3. includes/abstracts/abstract-wc-stripe-payment-gateway.php +139 -116
  4. includes/admin/class-wc-stripe-admin-notices.php +21 -11
  5. includes/admin/class-wc-stripe-inbox-notes.php +7 -7
  6. includes/admin/class-wc-stripe-privacy.php +75 -78
  7. includes/admin/stripe-alipay-settings.php +16 -16
  8. includes/admin/stripe-bancontact-settings.php +16 -16
  9. includes/admin/stripe-eps-settings.php +14 -14
  10. includes/admin/stripe-giropay-settings.php +16 -16
  11. includes/admin/stripe-ideal-settings.php +16 -16
  12. includes/admin/stripe-multibanco-settings.php +14 -14
  13. includes/admin/stripe-p24-settings.php +14 -14
  14. includes/admin/stripe-sepa-settings.php +16 -16
  15. includes/admin/stripe-settings.php +67 -67
  16. includes/admin/stripe-sofort-settings.php +16 -16
  17. includes/class-wc-gateway-stripe.php +74 -67
  18. includes/class-wc-stripe-api.php +22 -19
  19. includes/class-wc-stripe-apple-pay-registration.php +23 -23
  20. includes/class-wc-stripe-customer.php +39 -25
  21. includes/class-wc-stripe-exception.php +4 -1
  22. includes/class-wc-stripe-helper.php +15 -15
  23. includes/class-wc-stripe-intent-controller.php +11 -8
  24. includes/class-wc-stripe-logger.php +1 -1
  25. includes/class-wc-stripe-order-handler.php +29 -28
  26. includes/class-wc-stripe-payment-tokens.php +8 -8
  27. includes/class-wc-stripe-sepa-payment-token.php +10 -3
  28. includes/class-wc-stripe-webhook-handler.php +79 -48
  29. includes/class-wc-stripe-webhook-state.php +248 -0
  30. includes/compat/class-wc-stripe-email-failed-authentication-retry.php +5 -5
  31. includes/compat/class-wc-stripe-email-failed-authentication.php +8 -8
  32. includes/compat/class-wc-stripe-email-failed-preorder-authentication.php +5 -5
  33. includes/compat/class-wc-stripe-email-failed-renewal-authentication.php +6 -6
  34. includes/compat/class-wc-stripe-pre-orders-compat.php +14 -11
  35. includes/compat/class-wc-stripe-sepa-subs-compat.php +46 -42
  36. includes/compat/class-wc-stripe-subs-compat.php +71 -62
  37. includes/connect/class-wc-stripe-connect-api.php +15 -15
  38. includes/connect/class-wc-stripe-connect-rest-oauth-connect-controller.php +3 -3
  39. includes/connect/class-wc-stripe-connect-rest-oauth-init-controller.php +3 -3
  40. includes/connect/class-wc-stripe-connect.php +11 -11
  41. includes/payment-methods/class-wc-gateway-stripe-alipay.php +16 -15
  42. includes/payment-methods/class-wc-gateway-stripe-bancontact.php +17 -20
  43. includes/payment-methods/class-wc-gateway-stripe-eps.php +16 -19
  44. includes/payment-methods/class-wc-gateway-stripe-giropay.php +16 -19
  45. includes/payment-methods/class-wc-gateway-stripe-ideal.php +16 -19
  46. includes/payment-methods/class-wc-gateway-stripe-multibanco.php +22 -25
  47. includes/payment-methods/class-wc-gateway-stripe-p24.php +16 -19
  48. includes/payment-methods/class-wc-gateway-stripe-sepa.php +15 -18
  49. includes/payment-methods/class-wc-gateway-stripe-sofort.php +18 -21
  50. includes/payment-methods/class-wc-stripe-payment-request.php +180 -146
  51. languages/woocommerce-gateway-stripe.pot +333 -223
  52. readme.txt +7 -9
  53. templates/emails/failed-preorder-authentication.php +5 -3
  54. templates/emails/failed-renewal-authentication.php +2 -1
  55. templates/emails/plain/failed-preorder-authentication.php +1 -1
  56. uninstall.php +2 -2
  57. woocommerce-gateway-stripe.php +21 -21
changelog.txt CHANGED
@@ -1,4 +1,11 @@
1
  *** Changelog ***
 
 
 
 
 
 
 
2
  = 4.9.0 - 2021-02-24 =
3
  * Fix - Add fees as line items sent to Stripe to prevent Level 3 errors.
4
  * Fix - Adding a SEPA payment method doesn't work.
1
  *** Changelog ***
2
+ = 5.0.0 - 2021-03-17 =
3
+ * Add - Display time of last Stripe webhook in settings.
4
+ * Add - wc_stripe_webhook_validate_user_agent filter to customize webhook user-agent validation.
5
+ * Fix - Payment Request Buttons for Chinese provinces in Chrome.
6
+ * Fix - Enable wc_stripe_send_stripe_receipt filter to send Stripe emails.
7
+ * Fix - Check for more errors when attaching sources to customers.
8
+
9
  = 4.9.0 - 2021-02-24 =
10
  * Fix - Add fees as line items sent to Stripe to prevent Level 3 errors.
11
  * Fix - Adding a SEPA payment method doesn't work.
includes/abstracts/abstract-wc-stripe-connect-rest-controller.php CHANGED
@@ -4,6 +4,8 @@ if ( ! defined( 'ABSPATH' ) ) {
4
  exit;
5
  }
6
 
 
 
7
  /**
8
  * Stripe Connect base REST controller class.
9
  */
@@ -42,13 +44,13 @@ abstract class WC_Stripe_Connect_REST_Controller extends WP_REST_Controller {
42
  register_rest_route(
43
  $this->namespace,
44
  '/' . $this->rest_base,
45
- array(
46
- array(
47
  'methods' => 'GET',
48
- 'callback' => array( $this, 'get_internal' ),
49
- 'permission_callback' => array( $this, 'check_permission' ),
50
- ),
51
- )
52
  );
53
  }
54
 
@@ -56,13 +58,13 @@ abstract class WC_Stripe_Connect_REST_Controller extends WP_REST_Controller {
56
  register_rest_route(
57
  $this->namespace,
58
  '/' . $this->rest_base,
59
- array(
60
- array(
61
  'methods' => 'POST',
62
- 'callback' => array( $this, 'post_internal' ),
63
- 'permission_callback' => array( $this, 'check_permission' ),
64
- ),
65
- )
66
  );
67
  }
68
 
@@ -70,13 +72,13 @@ abstract class WC_Stripe_Connect_REST_Controller extends WP_REST_Controller {
70
  register_rest_route(
71
  $this->namespace,
72
  '/' . $this->rest_base,
73
- array(
74
- array(
75
  'methods' => 'DELETE',
76
- 'callback' => array( $this, 'delete_internal' ),
77
- 'permission_callback' => array( $this, 'check_permission' ),
78
- ),
79
- )
80
  );
81
  }
82
  }
@@ -145,7 +147,7 @@ abstract class WC_Stripe_Connect_REST_Controller extends WP_REST_Controller {
145
  }
146
 
147
  // Prevent our REST API endpoint responses from being added to browser cache.
148
- add_filter( 'rest_post_dispatch', array( $this, 'send_nocache_header' ), PHP_INT_MAX, 2 );
149
  }
150
 
151
  /**
4
  exit;
5
  }
6
 
7
+ // phpcs:disable WordPress.Files.FileName
8
+
9
  /**
10
  * Stripe Connect base REST controller class.
11
  */
44
  register_rest_route(
45
  $this->namespace,
46
  '/' . $this->rest_base,
47
+ [
48
+ [
49
  'methods' => 'GET',
50
+ 'callback' => [ $this, 'get_internal' ],
51
+ 'permission_callback' => [ $this, 'check_permission' ],
52
+ ],
53
+ ]
54
  );
55
  }
56
 
58
  register_rest_route(
59
  $this->namespace,
60
  '/' . $this->rest_base,
61
+ [
62
+ [
63
  'methods' => 'POST',
64
+ 'callback' => [ $this, 'post_internal' ],
65
+ 'permission_callback' => [ $this, 'check_permission' ],
66
+ ],
67
+ ]
68
  );
69
  }
70
 
72
  register_rest_route(
73
  $this->namespace,
74
  '/' . $this->rest_base,
75
+ [
76
+ [
77
  'methods' => 'DELETE',
78
+ 'callback' => [ $this, 'delete_internal' ],
79
+ 'permission_callback' => [ $this, 'check_permission' ],
80
+ ],
81
+ ]
82
  );
83
  }
84
  }
147
  }
148
 
149
  // Prevent our REST API endpoint responses from being added to browser cache.
150
+ add_filter( 'rest_post_dispatch', [ $this, 'send_nocache_header' ], PHP_INT_MAX, 2 );
151
  }
152
 
153
  /**
includes/abstracts/abstract-wc-stripe-payment-gateway.php CHANGED
@@ -17,11 +17,16 @@ abstract class WC_Stripe_Payment_Gateway extends WC_Payment_Gateway_CC {
17
  * Displays the admin settings webhook description.
18
  *
19
  * @since 4.1.0
 
20
  * @return mixed
21
  */
22
  public function display_admin_settings_webhook_description() {
23
  /* translators: 1) webhook url */
24
- return sprintf( __( 'You must add the following webhook endpoint <strong style="background-color:#ddd;">&nbsp;%s&nbsp;</strong> to your <a href="https://dashboard.stripe.com/account/webhooks" target="_blank">Stripe account settings</a>. This will enable you to receive notifications on the charge statuses.', 'woocommerce-gateway-stripe' ), WC_Stripe_Helper::get_webhook_url() );
 
 
 
 
25
  }
26
 
27
  /**
@@ -166,7 +171,7 @@ abstract class WC_Stripe_Payment_Gateway extends WC_Payment_Gateway_CC {
166
  && preg_match( '/^[rs]k_test_/', $this->secret_key );
167
  } else {
168
  return preg_match( '/^pk_live_/', $this->publishable_key )
169
- && preg_match( '/^[rs]k_live_/', $this->secret_key );
170
  }
171
  }
172
 
@@ -211,7 +216,7 @@ abstract class WC_Stripe_Payment_Gateway extends WC_Payment_Gateway_CC {
211
  public function payment_icons() {
212
  return apply_filters(
213
  'wc_stripe_payment_icons',
214
- array(
215
  'visa' => '<img src="' . WC_STRIPE_PLUGIN_URL . '/assets/images/visa.svg" class="stripe-visa-icon stripe-icon" alt="Visa" />',
216
  'amex' => '<img src="' . WC_STRIPE_PLUGIN_URL . '/assets/images/amex.svg" class="stripe-amex-icon stripe-icon" alt="American Express" />',
217
  'mastercard' => '<img src="' . WC_STRIPE_PLUGIN_URL . '/assets/images/mastercard.svg" class="stripe-mastercard-icon stripe-icon" alt="Mastercard" />',
@@ -228,7 +233,7 @@ abstract class WC_Stripe_Payment_Gateway extends WC_Payment_Gateway_CC {
228
  'multibanco' => '<img src="' . WC_STRIPE_PLUGIN_URL . '/assets/images/multibanco.svg" class="stripe-multibanco-icon stripe-icon" alt="Multibanco" />',
229
  'sofort' => '<img src="' . WC_STRIPE_PLUGIN_URL . '/assets/images/sofort.svg" class="stripe-sofort-icon stripe-icon" alt="SOFORT" />',
230
  'sepa' => '<img src="' . WC_STRIPE_PLUGIN_URL . '/assets/images/sepa.svg" class="stripe-sepa-icon stripe-icon" alt="SEPA" />',
231
- )
232
  );
233
  }
234
 
@@ -288,7 +293,7 @@ abstract class WC_Stripe_Payment_Gateway extends WC_Payment_Gateway_CC {
288
  * @since 4.0.0
289
  * @version 4.0.0
290
  * @param object $order
291
- * @param int $id Stripe session id.
292
  */
293
  public function get_stripe_return_url( $order = null, $id = null ) {
294
  if ( is_object( $order ) ) {
@@ -298,20 +303,21 @@ abstract class WC_Stripe_Payment_Gateway extends WC_Payment_Gateway_CC {
298
 
299
  $order_id = $order->get_id();
300
 
301
- $args = array(
302
  'utm_nooverride' => '1',
303
  'order_id' => $order_id,
304
- );
305
 
306
  return wp_sanitize_redirect( esc_url_raw( add_query_arg( $args, $this->get_return_url( $order ) ) ) );
307
  }
308
 
309
- return wp_sanitize_redirect( esc_url_raw( add_query_arg( array( 'utm_nooverride' => '1' ), $this->get_return_url() ) ) );
310
  }
311
 
312
  /**
313
  * Is $order_id a subscription?
314
- * @param int $order_id
 
315
  * @return boolean
316
  */
317
  public function has_subscription( $order_id ) {
@@ -324,14 +330,14 @@ abstract class WC_Stripe_Payment_Gateway extends WC_Payment_Gateway_CC {
324
  * @since 3.1.0
325
  * @version 4.5.4
326
  * @param WC_Order $order
327
- * @param object $prepared_source
328
  * @return array()
329
  */
330
  public function generate_payment_request( $order, $prepared_source ) {
331
- $settings = get_option( 'woocommerce_stripe_settings', array() );
332
  $statement_descriptor = ! empty( $settings['statement_descriptor'] ) ? str_replace( "'", '', $settings['statement_descriptor'] ) : '';
333
  $capture = ! empty( $settings['capture'] ) && 'yes' === $settings['capture'] ? true : false;
334
- $post_data = array();
335
  $post_data['currency'] = strtolower( $order->get_currency() );
336
  $post_data['amount'] = WC_Stripe_Helper::get_stripe_amount( $order->get_total(), $post_data['currency'] );
337
  /* translators: 1) blog name 2) order number */
@@ -360,32 +366,32 @@ abstract class WC_Stripe_Payment_Gateway extends WC_Payment_Gateway_CC {
360
  }
361
 
362
  if ( method_exists( $order, 'get_shipping_postcode' ) && ! empty( $order->get_shipping_postcode() ) ) {
363
- $post_data['shipping'] = array(
364
  'name' => trim( $order->get_shipping_first_name() . ' ' . $order->get_shipping_last_name() ),
365
- 'address' => array(
366
  'line1' => $order->get_shipping_address_1(),
367
  'line2' => $order->get_shipping_address_2(),
368
  'city' => $order->get_shipping_city(),
369
  'country' => $order->get_shipping_country(),
370
  'postal_code' => $order->get_shipping_postcode(),
371
  'state' => $order->get_shipping_state(),
372
- )
373
- );
374
  }
375
 
376
  $post_data['expand[]'] = 'balance_transaction';
377
 
378
- $metadata = array(
379
  __( 'customer_name', 'woocommerce-gateway-stripe' ) => sanitize_text_field( $billing_first_name ) . ' ' . sanitize_text_field( $billing_last_name ),
380
  __( 'customer_email', 'woocommerce-gateway-stripe' ) => sanitize_email( $billing_email ),
381
  'order_id' => $order->get_order_number(),
382
  'site_url' => esc_url( get_site_url() ),
383
- );
384
 
385
  if ( $this->has_subscription( $order->get_id() ) ) {
386
- $metadata += array(
387
  'payment_type' => 'recurring',
388
- );
389
  }
390
 
391
  $post_data['metadata'] = apply_filters( 'wc_stripe_payment_metadata', $metadata, $order, $prepared_source );
@@ -459,7 +465,7 @@ abstract class WC_Stripe_Payment_Gateway extends WC_Payment_Gateway_CC {
459
  } else {
460
  $order->set_transaction_id( $response->id );
461
 
462
- if ( $order->has_status( array( 'pending', 'failed' ) ) ) {
463
  wc_reduce_stock_levels( $order_id );
464
  }
465
 
@@ -467,7 +473,7 @@ abstract class WC_Stripe_Payment_Gateway extends WC_Payment_Gateway_CC {
467
  $order->update_status( 'on-hold', sprintf( __( 'Stripe charge authorized (Charge ID: %s). Process order to take payment, or cancel to remove the pre-authorization. Attempting to refund the order in part or in full will release the authorization and cancel the payment.', 'woocommerce-gateway-stripe' ), $response->id ) );
468
  }
469
 
470
- if ( is_callable( array( $order, 'save' ) ) ) {
471
  $order->save();
472
  }
473
 
@@ -503,7 +509,7 @@ abstract class WC_Stripe_Payment_Gateway extends WC_Payment_Gateway_CC {
503
  $billing_first_name = $order->get_billing_first_name();
504
  $billing_last_name = $order->get_billing_last_name();
505
 
506
- $details = array();
507
 
508
  $name = $billing_first_name . ' ' . $billing_last_name;
509
  $email = $order->get_billing_email();
@@ -584,7 +590,7 @@ abstract class WC_Stripe_Payment_Gateway extends WC_Payment_Gateway_CC {
584
  * @return bool
585
  */
586
  public function is_using_saved_payment_method() {
587
- $payment_method = isset( $_POST['payment_method'] ) ? wc_clean( $_POST['payment_method'] ) : 'stripe';
588
 
589
  return ( isset( $_POST[ 'wc-' . $payment_method . '-payment-token' ] ) && 'new' !== $_POST[ 'wc-' . $payment_method . '-payment-token' ] );
590
  }
@@ -597,7 +603,7 @@ abstract class WC_Stripe_Payment_Gateway extends WC_Payment_Gateway_CC {
597
  * @since 3.1.0
598
  * @version 4.0.0
599
  * @param string $user_id
600
- * @param bool $force_save_source Should we force save payment source.
601
  *
602
  * @throws Exception When card was not added or for and invalid card.
603
  * @return object
@@ -612,12 +618,12 @@ abstract class WC_Stripe_Payment_Gateway extends WC_Payment_Gateway_CC {
612
  $source_object = '';
613
  $source_id = '';
614
  $wc_token_id = false;
615
- $payment_method = isset( $_POST['payment_method'] ) ? wc_clean( $_POST['payment_method'] ) : 'stripe';
616
  $is_token = false;
617
 
618
  // New CC info was entered and we have a new source to process.
619
  if ( ! empty( $_POST['stripe_source'] ) ) {
620
- $source_object = self::get_source_object( wc_clean( $_POST['stripe_source'] ) );
621
  $source_id = $source_object->id;
622
 
623
  // This checks to see if customer opted to save the payment method to file.
@@ -634,10 +640,13 @@ abstract class WC_Stripe_Payment_Gateway extends WC_Payment_Gateway_CC {
634
  if ( ! empty( $response->error ) ) {
635
  throw new WC_Stripe_Exception( print_r( $response, true ), $this->get_localized_error_message_from_response( $response ) );
636
  }
 
 
 
637
  }
638
  } elseif ( $this->is_using_saved_payment_method() ) {
639
  // Use an existing token, and then process the payment.
640
- $wc_token_id = wc_clean( $_POST[ 'wc-' . $payment_method . '-payment-token' ] );
641
  $wc_token = WC_Payment_Tokens::get( $wc_token_id );
642
 
643
  if ( ! $wc_token || $wc_token->get_user_id() !== get_current_user_id() ) {
@@ -651,7 +660,7 @@ abstract class WC_Stripe_Payment_Gateway extends WC_Payment_Gateway_CC {
651
  $is_token = true;
652
  }
653
  } elseif ( isset( $_POST['stripe_token'] ) && 'new' !== $_POST['stripe_token'] ) {
654
- $stripe_token = wc_clean( $_POST['stripe_token'] );
655
  $maybe_saved_card = isset( $_POST[ 'wc-' . $payment_method . '-new-payment-method' ] ) && ! empty( $_POST[ 'wc-' . $payment_method . '-new-payment-method' ] );
656
 
657
  // This is true if the user wants to store the card to their account.
@@ -661,10 +670,13 @@ abstract class WC_Stripe_Payment_Gateway extends WC_Payment_Gateway_CC {
661
  if ( ! empty( $response->error ) ) {
662
  throw new WC_Stripe_Exception( print_r( $response, true ), $response->error->message );
663
  }
664
- $source_id = $response;
 
 
 
665
  } else {
666
- $source_id = $stripe_token;
667
- $is_token = true;
668
  }
669
  }
670
 
@@ -680,12 +692,12 @@ abstract class WC_Stripe_Payment_Gateway extends WC_Payment_Gateway_CC {
680
  $source_object = self::get_source_object( $source_id );
681
  }
682
 
683
- return (object) array(
684
  'token_id' => $wc_token_id,
685
  'customer' => $customer_id,
686
  'source' => $source_id,
687
  'source_object' => $source_object,
688
- );
689
  }
690
 
691
  /**
@@ -725,7 +737,7 @@ abstract class WC_Stripe_Payment_Gateway extends WC_Payment_Gateway_CC {
725
  // Take this opportunity to update the key name.
726
  $order->update_meta_data( '_stripe_source_id', $source_id );
727
 
728
- if ( is_callable( array( $order, 'save' ) ) ) {
729
  $order->save();
730
  }
731
  }
@@ -742,12 +754,12 @@ abstract class WC_Stripe_Payment_Gateway extends WC_Payment_Gateway_CC {
742
  }
743
  }
744
 
745
- return (object) array(
746
  'token_id' => $token_id,
747
  'customer' => $stripe_customer ? $stripe_customer->get_id() : false,
748
  'source' => $stripe_source,
749
  'source_object' => $source_object,
750
- );
751
  }
752
 
753
  /**
@@ -768,7 +780,7 @@ abstract class WC_Stripe_Payment_Gateway extends WC_Payment_Gateway_CC {
768
  $order->update_meta_data( '_stripe_source_id', $source->source );
769
  }
770
 
771
- if ( is_callable( array( $order, 'save' ) ) ) {
772
  $order->save();
773
  }
774
  }
@@ -780,7 +792,7 @@ abstract class WC_Stripe_Payment_Gateway extends WC_Payment_Gateway_CC {
780
  * @since 4.0.0
781
  * @version 4.0.6
782
  * @param object $order The order object
783
- * @param int $balance_transaction_id
784
  */
785
  public function update_fees( $order, $balance_transaction_id ) {
786
  $balance_transaction = WC_Stripe_API::retrieve( 'balance/history/' . $balance_transaction_id );
@@ -806,7 +818,7 @@ abstract class WC_Stripe_Payment_Gateway extends WC_Payment_Gateway_CC {
806
  $currency = ! empty( $balance_transaction->currency ) ? strtoupper( $balance_transaction->currency ) : null;
807
  WC_Stripe_Helper::update_stripe_currency( $order, $currency );
808
 
809
- if ( is_callable( array( $order, 'save' ) ) ) {
810
  $order->save();
811
  }
812
  }
@@ -833,7 +845,7 @@ abstract class WC_Stripe_Payment_Gateway extends WC_Payment_Gateway_CC {
833
  return false;
834
  }
835
 
836
- $request = array();
837
 
838
  $order_currency = $order->get_currency();
839
  $captured = $order->get_meta( '_stripe_charge_captured', true );
@@ -860,9 +872,9 @@ abstract class WC_Stripe_Payment_Gateway extends WC_Payment_Gateway_CC {
860
  $reason = $reason . '... [See WooCommerce order page for full text.]';
861
  }
862
 
863
- $request['metadata'] = array(
864
  'reason' => $reason,
865
- );
866
  }
867
 
868
  $request['charge'] = $charge_id;
@@ -870,16 +882,16 @@ abstract class WC_Stripe_Payment_Gateway extends WC_Payment_Gateway_CC {
870
 
871
  $request = apply_filters( 'wc_stripe_refund_request', $request, $order );
872
 
873
- $intent = $this->get_intent_from_order( $order );
874
  $intent_cancelled = false;
875
  if ( $intent ) {
876
  // If the order has a Payment Intent pending capture, then the Intent itself must be refunded (cancelled), not the Charge.
877
  if ( ! empty( $intent->error ) ) {
878
- $response = $intent;
879
  $intent_cancelled = true;
880
  } elseif ( 'requires_capture' === $intent->status ) {
881
- $result = WC_Stripe_API::request(
882
- array(),
883
  'payment_intents/' . $intent->id . '/cancel'
884
  );
885
  $intent_cancelled = true;
@@ -887,7 +899,7 @@ abstract class WC_Stripe_Payment_Gateway extends WC_Payment_Gateway_CC {
887
  if ( ! empty( $result->error ) ) {
888
  $response = $result;
889
  } else {
890
- $charge = end( $result->charges->data );
891
  $response = end( $charge->refunds->data );
892
  }
893
  }
@@ -957,7 +969,7 @@ abstract class WC_Stripe_Payment_Gateway extends WC_Payment_Gateway_CC {
957
 
958
  $stripe_customer = new WC_Stripe_Customer( get_current_user_id() );
959
 
960
- $source = ! empty( $_POST['stripe_source'] ) ? wc_clean( $_POST['stripe_source'] ) : '';
961
 
962
  $source_object = WC_Stripe_API::retrieve( 'sources/' . $source );
963
 
@@ -968,7 +980,7 @@ abstract class WC_Stripe_Payment_Gateway extends WC_Payment_Gateway_CC {
968
 
969
  $source_id = $source_object->id;
970
  } elseif ( isset( $_POST['stripe_token'] ) ) {
971
- $source_id = wc_clean( $_POST['stripe_token'] );
972
  }
973
 
974
  $response = $stripe_customer->add_source( $source_id );
@@ -983,12 +995,12 @@ abstract class WC_Stripe_Payment_Gateway extends WC_Payment_Gateway_CC {
983
  return;
984
  }
985
 
986
- do_action( 'wc_stripe_add_payment_method_' . $_POST['payment_method'] . '_success', $source_id, $source_object );
987
 
988
- return array(
989
  'result' => 'success',
990
  'redirect' => wc_get_endpoint_url( 'payment-methods' ),
991
- );
992
  }
993
 
994
  /**
@@ -1019,7 +1031,7 @@ abstract class WC_Stripe_Payment_Gateway extends WC_Payment_Gateway_CC {
1019
  *
1020
  * @since 4.0.6
1021
  * @param string $idempotency_key
1022
- * @param array $request
1023
  */
1024
  public function change_idempotency_key( $idempotency_key, $request ) {
1025
  $customer = ! empty( $request['customer'] ) ? $request['customer'] : '';
@@ -1056,17 +1068,17 @@ abstract class WC_Stripe_Payment_Gateway extends WC_Payment_Gateway_CC {
1056
  // The request for a charge contains metadata for the intent.
1057
  $full_request = $this->generate_payment_request( $order, $prepared_source );
1058
 
1059
- $request = array(
1060
  'source' => $prepared_source->source,
1061
  'amount' => WC_Stripe_Helper::get_stripe_amount( $order->get_total() ),
1062
  'currency' => strtolower( $order->get_currency() ),
1063
  'description' => $full_request['description'],
1064
  'metadata' => $full_request['metadata'],
1065
  'capture_method' => ( 'true' === $full_request['capture'] ) ? 'automatic' : 'manual',
1066
- 'payment_method_types' => array(
1067
  'card',
1068
- ),
1069
- );
1070
 
1071
  if ( $prepared_source->customer ) {
1072
  $request['customer'] = $prepared_source->customer;
@@ -1080,6 +1092,10 @@ abstract class WC_Stripe_Payment_Gateway extends WC_Payment_Gateway_CC {
1080
  $request['shipping'] = $full_request['shipping'];
1081
  }
1082
 
 
 
 
 
1083
  /**
1084
  * Filter the return value of the WC_Payment_Gateway_CC::generate_create_intent_request.
1085
  *
@@ -1103,38 +1119,41 @@ abstract class WC_Stripe_Payment_Gateway extends WC_Payment_Gateway_CC {
1103
  $order_items = array_values( $order->get_items( [ 'line_item', 'fee' ] ) );
1104
  $currency = $order->get_currency();
1105
 
1106
- $stripe_line_items = array_map( function( $item ) use ( $currency ) {
1107
- if ( is_a( $item, 'WC_Order_Item_Product' ) ) {
1108
- $product_id = $item->get_variation_id()
1109
- ? $item->get_variation_id()
1110
- : $item->get_product_id();
1111
- $subtotal = $item->get_subtotal();
1112
- } else {
1113
- $product_id = substr( sanitize_title( $item->get_name() ), 0, 12 );
1114
- $subtotal = $item->get_total();
1115
- }
1116
- $product_description = substr( $item->get_name(), 0, 26 );
1117
- $quantity = $item->get_quantity();
1118
- $unit_cost = WC_Stripe_Helper::get_stripe_amount( ( $subtotal / $quantity ), $currency );
1119
- $tax_amount = WC_Stripe_Helper::get_stripe_amount( $item->get_total_tax(), $currency );
1120
- $discount_amount = WC_Stripe_Helper::get_stripe_amount( $subtotal - $item->get_total(), $currency );
1121
-
1122
- return (object) array(
1123
- 'product_code' => (string) $product_id, // Up to 12 characters that uniquely identify the product.
1124
- 'product_description' => $product_description, // Up to 26 characters long describing the product.
1125
- 'unit_cost' => $unit_cost, // Cost of the product, in cents, as a non-negative integer.
1126
- 'quantity' => $quantity, // The number of items of this type sold, as a non-negative integer.
1127
- 'tax_amount' => $tax_amount, // The amount of tax this item had added to it, in cents, as a non-negative integer.
1128
- 'discount_amount' => $discount_amount, // The amount an item was discounted—if there was a sale,for example, as a non-negative integer.
1129
- );
1130
- }, $order_items);
1131
-
1132
- $level3_data = array(
1133
- 'merchant_reference' => $order->get_id(), // An alphanumeric string of up to characters in length. This unique value is assigned by the merchant to identify the order. Also known as an “Order ID”.
1134
- 'shipping_amount' => WC_Stripe_Helper::get_stripe_amount( (float) $order->get_shipping_total() + (float) $order->get_shipping_tax(), $currency), // The shipping cost, in cents, as a non-negative integer.
1135
- 'line_items' => $stripe_line_items,
1136
  );
1137
 
 
 
 
 
 
 
1138
  // The customer’s U.S. shipping ZIP code.
1139
  $shipping_address_zip = $order->get_shipping_postcode();
1140
  if ( $this->is_valid_us_zip_code( $shipping_address_zip ) ) {
@@ -1184,7 +1203,7 @@ abstract class WC_Stripe_Payment_Gateway extends WC_Payment_Gateway_CC {
1184
  * @return object An updated intent.
1185
  */
1186
  public function update_existing_intent( $intent, $order, $prepared_source ) {
1187
- $request = array();
1188
 
1189
  if ( $prepared_source->source !== $intent->source ) {
1190
  $request['source'] = $prepared_source->source;
@@ -1233,11 +1252,11 @@ abstract class WC_Stripe_Payment_Gateway extends WC_Payment_Gateway_CC {
1233
  }
1234
 
1235
  // Try to confirm the intent & capture the charge (if 3DS is not required).
1236
- $confirm_request = array(
1237
  'source' => $prepared_source->source,
1238
- );
1239
 
1240
- $level3_data = $this->get_level3_data_from_order( $order );
1241
  $confirmed_intent = WC_Stripe_API::request_with_level3_data(
1242
  $confirm_request,
1243
  "payment_intents/$intent->id/confirm",
@@ -1270,7 +1289,7 @@ abstract class WC_Stripe_Payment_Gateway extends WC_Payment_Gateway_CC {
1270
  public function save_intent_to_order( $order, $intent ) {
1271
  $order->update_meta_data( '_stripe_intent_id', $intent->id );
1272
 
1273
- if ( is_callable( array( $order, 'save' ) ) ) {
1274
  $order->save();
1275
  }
1276
  }
@@ -1302,22 +1321,22 @@ abstract class WC_Stripe_Payment_Gateway extends WC_Payment_Gateway_CC {
1302
  /**
1303
  * Retrieves intent from Stripe API by intent id.
1304
  *
1305
- * @param string $intent_type Either 'payment_intents' or 'setup_intents'.
1306
- * @param string $intent_id Intent id.
1307
- * @return object|bool Either the intent object or `false`.
1308
- * @throws Exception Throws exception for unknown $intent_type.
1309
  */
1310
  private function get_intent( $intent_type, $intent_id ) {
1311
  if ( ! in_array( $intent_type, [ 'payment_intents', 'setup_intents' ] ) ) {
1312
  throw new Exception( "Failed to get intent of type $intent_type. Type is not allowed" );
1313
  }
1314
 
1315
- $response = WC_Stripe_API::request( array(), "$intent_type/$intent_id", 'GET' );
1316
 
1317
  if ( $response && isset( $response->{ 'error' } ) ) {
1318
  $error_response_message = print_r( $response, true );
1319
- WC_Stripe_Logger::log("Failed to get Stripe intent $intent_type/$intent_id.");
1320
- WC_Stripe_Logger::log("Response: $error_response_message");
1321
  return false;
1322
  }
1323
 
@@ -1338,7 +1357,7 @@ abstract class WC_Stripe_Payment_Gateway extends WC_Payment_Gateway_CC {
1338
  $processing = get_transient( $transient_name );
1339
 
1340
  // Block the process if the same intent is already being handled.
1341
- if ( "-1" === $processing || ( isset( $intent->id ) && $processing === $intent->id ) ) {
1342
  return true;
1343
  }
1344
 
@@ -1380,11 +1399,14 @@ abstract class WC_Stripe_Payment_Gateway extends WC_Payment_Gateway_CC {
1380
  */
1381
  public function setup_intent( $order, $prepared_source ) {
1382
  $order_id = $order->get_id();
1383
- $setup_intent = WC_Stripe_API::request( array(
1384
- 'payment_method' => $prepared_source->source,
1385
- 'customer' => $prepared_source->customer,
1386
- 'confirm' => 'true',
1387
- ), 'setup_intents' );
 
 
 
1388
 
1389
  if ( is_wp_error( $setup_intent ) ) {
1390
  WC_Stripe_Logger::log( "Unable to create SetupIntent for Order #$order_id: " . print_r( $setup_intent, true ) );
@@ -1404,22 +1426,22 @@ abstract class WC_Stripe_Payment_Gateway extends WC_Payment_Gateway_CC {
1404
  * @param float $amount The amount to charge. If not specified, it will be read from the order.
1405
  * @return object An intent or an error.
1406
  */
1407
- public function create_and_confirm_intent_for_off_session( $order, $prepared_source, $amount = NULL ) {
1408
  // The request for a charge contains metadata for the intent.
1409
  $full_request = $this->generate_payment_request( $order, $prepared_source );
1410
 
1411
- $request = array(
1412
  'amount' => $amount ? WC_Stripe_Helper::get_stripe_amount( $amount, $full_request['currency'] ) : $full_request['amount'],
1413
  'currency' => $full_request['currency'],
1414
  'description' => $full_request['description'],
1415
  'metadata' => $full_request['metadata'],
1416
- 'payment_method_types' => array(
1417
  'card',
1418
- ),
1419
  'off_session' => 'true',
1420
  'confirm' => 'true',
1421
  'confirmation_method' => 'automatic',
1422
- );
1423
 
1424
  if ( isset( $full_request['statement_descriptor'] ) ) {
1425
  $request['statement_descriptor'] = $full_request['statement_descriptor'];
@@ -1442,14 +1464,14 @@ abstract class WC_Stripe_Payment_Gateway extends WC_Payment_Gateway_CC {
1442
  * @param WC_Order $order
1443
  * @param object $source
1444
  */
1445
- $request = apply_filters('wc_stripe_generate_create_intent_request', $request, $order, $prepared_source );
1446
 
1447
  if ( isset( $full_request['shipping'] ) ) {
1448
  $request['shipping'] = $full_request['shipping'];
1449
  }
1450
 
1451
- $level3_data = $this->get_level3_data_from_order( $order );
1452
- $intent = WC_Stripe_API::request_with_level3_data(
1453
  $request,
1454
  'payment_intents',
1455
  $level3_data,
@@ -1482,11 +1504,12 @@ abstract class WC_Stripe_Payment_Gateway extends WC_Payment_Gateway_CC {
1482
  * Checks if subscription has a Stripe customer ID and adds it if doesn't.
1483
  *
1484
  * Fix renewal for existing subscriptions affected by https://github.com/woocommerce/woocommerce-gateway-stripe/issues/1072.
 
1485
  * @param int $order_id subscription renewal order id.
1486
  */
1487
  public function ensure_subscription_has_customer_id( $order_id ) {
1488
- $subscriptions_ids = wcs_get_subscriptions_for_order( $order_id, array( 'order_type' => 'any' ) );
1489
- foreach( $subscriptions_ids as $subscription_id => $subscription ) {
1490
  if ( ! metadata_exists( 'post', $subscription_id, '_stripe_customer_id' ) ) {
1491
  $stripe_customer = new WC_Stripe_Customer( $subscription->get_user_id() );
1492
  update_post_meta( $subscription_id, '_stripe_customer_id', $stripe_customer->get_id() );
17
  * Displays the admin settings webhook description.
18
  *
19
  * @since 4.1.0
20
+ * @version 5.0.0
21
  * @return mixed
22
  */
23
  public function display_admin_settings_webhook_description() {
24
  /* translators: 1) webhook url */
25
+ $description = sprintf( __( 'You must add the following webhook endpoint <strong style="background-color:#ddd;">&nbsp;%s&nbsp;</strong> to your <a href="https://dashboard.stripe.com/account/webhooks" target="_blank">Stripe account settings</a> (if there isn\'t one already enabled). This will enable you to receive notifications on the charge statuses.', 'woocommerce-gateway-stripe' ), WC_Stripe_Helper::get_webhook_url() );
26
+
27
+ $webhook_status = WC_Stripe_Webhook_State::get_webhook_status_message();
28
+
29
+ return $description . '<br><br>' . $webhook_status;
30
  }
31
 
32
  /**
171
  && preg_match( '/^[rs]k_test_/', $this->secret_key );
172
  } else {
173
  return preg_match( '/^pk_live_/', $this->publishable_key )
174
+ && preg_match( '/^[rs]k_live_/', $this->secret_key );
175
  }
176
  }
177
 
216
  public function payment_icons() {
217
  return apply_filters(
218
  'wc_stripe_payment_icons',
219
+ [
220
  'visa' => '<img src="' . WC_STRIPE_PLUGIN_URL . '/assets/images/visa.svg" class="stripe-visa-icon stripe-icon" alt="Visa" />',
221
  'amex' => '<img src="' . WC_STRIPE_PLUGIN_URL . '/assets/images/amex.svg" class="stripe-amex-icon stripe-icon" alt="American Express" />',
222
  'mastercard' => '<img src="' . WC_STRIPE_PLUGIN_URL . '/assets/images/mastercard.svg" class="stripe-mastercard-icon stripe-icon" alt="Mastercard" />',
233
  'multibanco' => '<img src="' . WC_STRIPE_PLUGIN_URL . '/assets/images/multibanco.svg" class="stripe-multibanco-icon stripe-icon" alt="Multibanco" />',
234
  'sofort' => '<img src="' . WC_STRIPE_PLUGIN_URL . '/assets/images/sofort.svg" class="stripe-sofort-icon stripe-icon" alt="SOFORT" />',
235
  'sepa' => '<img src="' . WC_STRIPE_PLUGIN_URL . '/assets/images/sepa.svg" class="stripe-sepa-icon stripe-icon" alt="SEPA" />',
236
+ ]
237
  );
238
  }
239
 
293
  * @since 4.0.0
294
  * @version 4.0.0
295
  * @param object $order
296
+ * @param int $id Stripe session id.
297
  */
298
  public function get_stripe_return_url( $order = null, $id = null ) {
299
  if ( is_object( $order ) ) {
303
 
304
  $order_id = $order->get_id();
305
 
306
+ $args = [
307
  'utm_nooverride' => '1',
308
  'order_id' => $order_id,
309
+ ];
310
 
311
  return wp_sanitize_redirect( esc_url_raw( add_query_arg( $args, $this->get_return_url( $order ) ) ) );
312
  }
313
 
314
+ return wp_sanitize_redirect( esc_url_raw( add_query_arg( [ 'utm_nooverride' => '1' ], $this->get_return_url() ) ) );
315
  }
316
 
317
  /**
318
  * Is $order_id a subscription?
319
+ *
320
+ * @param int $order_id
321
  * @return boolean
322
  */
323
  public function has_subscription( $order_id ) {
330
  * @since 3.1.0
331
  * @version 4.5.4
332
  * @param WC_Order $order
333
+ * @param object $prepared_source
334
  * @return array()
335
  */
336
  public function generate_payment_request( $order, $prepared_source ) {
337
+ $settings = get_option( 'woocommerce_stripe_settings', [] );
338
  $statement_descriptor = ! empty( $settings['statement_descriptor'] ) ? str_replace( "'", '', $settings['statement_descriptor'] ) : '';
339
  $capture = ! empty( $settings['capture'] ) && 'yes' === $settings['capture'] ? true : false;
340
+ $post_data = [];
341
  $post_data['currency'] = strtolower( $order->get_currency() );
342
  $post_data['amount'] = WC_Stripe_Helper::get_stripe_amount( $order->get_total(), $post_data['currency'] );
343
  /* translators: 1) blog name 2) order number */
366
  }
367
 
368
  if ( method_exists( $order, 'get_shipping_postcode' ) && ! empty( $order->get_shipping_postcode() ) ) {
369
+ $post_data['shipping'] = [
370
  'name' => trim( $order->get_shipping_first_name() . ' ' . $order->get_shipping_last_name() ),
371
+ 'address' => [
372
  'line1' => $order->get_shipping_address_1(),
373
  'line2' => $order->get_shipping_address_2(),
374
  'city' => $order->get_shipping_city(),
375
  'country' => $order->get_shipping_country(),
376
  'postal_code' => $order->get_shipping_postcode(),
377
  'state' => $order->get_shipping_state(),
378
+ ],
379
+ ];
380
  }
381
 
382
  $post_data['expand[]'] = 'balance_transaction';
383
 
384
+ $metadata = [
385
  __( 'customer_name', 'woocommerce-gateway-stripe' ) => sanitize_text_field( $billing_first_name ) . ' ' . sanitize_text_field( $billing_last_name ),
386
  __( 'customer_email', 'woocommerce-gateway-stripe' ) => sanitize_email( $billing_email ),
387
  'order_id' => $order->get_order_number(),
388
  'site_url' => esc_url( get_site_url() ),
389
+ ];
390
 
391
  if ( $this->has_subscription( $order->get_id() ) ) {
392
+ $metadata += [
393
  'payment_type' => 'recurring',
394
+ ];
395
  }
396
 
397
  $post_data['metadata'] = apply_filters( 'wc_stripe_payment_metadata', $metadata, $order, $prepared_source );
465
  } else {
466
  $order->set_transaction_id( $response->id );
467
 
468
+ if ( $order->has_status( [ 'pending', 'failed' ] ) ) {
469
  wc_reduce_stock_levels( $order_id );
470
  }
471
 
473
  $order->update_status( 'on-hold', sprintf( __( 'Stripe charge authorized (Charge ID: %s). Process order to take payment, or cancel to remove the pre-authorization. Attempting to refund the order in part or in full will release the authorization and cancel the payment.', 'woocommerce-gateway-stripe' ), $response->id ) );
474
  }
475
 
476
+ if ( is_callable( [ $order, 'save' ] ) ) {
477
  $order->save();
478
  }
479
 
509
  $billing_first_name = $order->get_billing_first_name();
510
  $billing_last_name = $order->get_billing_last_name();
511
 
512
+ $details = [];
513
 
514
  $name = $billing_first_name . ' ' . $billing_last_name;
515
  $email = $order->get_billing_email();
590
  * @return bool
591
  */
592
  public function is_using_saved_payment_method() {
593
+ $payment_method = isset( $_POST['payment_method'] ) ? wc_clean( wp_unslash( $_POST['payment_method'] ) ) : 'stripe';
594
 
595
  return ( isset( $_POST[ 'wc-' . $payment_method . '-payment-token' ] ) && 'new' !== $_POST[ 'wc-' . $payment_method . '-payment-token' ] );
596
  }
603
  * @since 3.1.0
604
  * @version 4.0.0
605
  * @param string $user_id
606
+ * @param bool $force_save_source Should we force save payment source.
607
  *
608
  * @throws Exception When card was not added or for and invalid card.
609
  * @return object
618
  $source_object = '';
619
  $source_id = '';
620
  $wc_token_id = false;
621
+ $payment_method = isset( $_POST['payment_method'] ) ? wc_clean( wp_unslash( $_POST['payment_method'] ) ) : 'stripe';
622
  $is_token = false;
623
 
624
  // New CC info was entered and we have a new source to process.
625
  if ( ! empty( $_POST['stripe_source'] ) ) {
626
+ $source_object = self::get_source_object( wc_clean( wp_unslash( $_POST['stripe_source'] ) ) );
627
  $source_id = $source_object->id;
628
 
629
  // This checks to see if customer opted to save the payment method to file.
640
  if ( ! empty( $response->error ) ) {
641
  throw new WC_Stripe_Exception( print_r( $response, true ), $this->get_localized_error_message_from_response( $response ) );
642
  }
643
+ if ( is_wp_error( $response ) ) {
644
+ throw new WC_Stripe_Exception( $response->get_error_message(), $response->get_error_message() );
645
+ }
646
  }
647
  } elseif ( $this->is_using_saved_payment_method() ) {
648
  // Use an existing token, and then process the payment.
649
+ $wc_token_id = isset( $_POST[ 'wc-' . $payment_method . '-payment-token' ] ) ? wc_clean( wp_unslash( $_POST[ 'wc-' . $payment_method . '-payment-token' ] ) ) : '';
650
  $wc_token = WC_Payment_Tokens::get( $wc_token_id );
651
 
652
  if ( ! $wc_token || $wc_token->get_user_id() !== get_current_user_id() ) {
660
  $is_token = true;
661
  }
662
  } elseif ( isset( $_POST['stripe_token'] ) && 'new' !== $_POST['stripe_token'] ) {
663
+ $stripe_token = wc_clean( wp_unslash( $_POST['stripe_token'] ) );
664
  $maybe_saved_card = isset( $_POST[ 'wc-' . $payment_method . '-new-payment-method' ] ) && ! empty( $_POST[ 'wc-' . $payment_method . '-new-payment-method' ] );
665
 
666
  // This is true if the user wants to store the card to their account.
670
  if ( ! empty( $response->error ) ) {
671
  throw new WC_Stripe_Exception( print_r( $response, true ), $response->error->message );
672
  }
673
+ if ( is_wp_error( $response ) ) {
674
+ throw new WC_Stripe_Exception( $response->get_error_message(), $response->get_error_message() );
675
+ }
676
+ $source_id = $response;
677
  } else {
678
+ $source_id = $stripe_token;
679
+ $is_token = true;
680
  }
681
  }
682
 
692
  $source_object = self::get_source_object( $source_id );
693
  }
694
 
695
+ return (object) [
696
  'token_id' => $wc_token_id,
697
  'customer' => $customer_id,
698
  'source' => $source_id,
699
  'source_object' => $source_object,
700
+ ];
701
  }
702
 
703
  /**
737
  // Take this opportunity to update the key name.
738
  $order->update_meta_data( '_stripe_source_id', $source_id );
739
 
740
+ if ( is_callable( [ $order, 'save' ] ) ) {
741
  $order->save();
742
  }
743
  }
754
  }
755
  }
756
 
757
+ return (object) [
758
  'token_id' => $token_id,
759
  'customer' => $stripe_customer ? $stripe_customer->get_id() : false,
760
  'source' => $stripe_source,
761
  'source_object' => $source_object,
762
+ ];
763
  }
764
 
765
  /**
780
  $order->update_meta_data( '_stripe_source_id', $source->source );
781
  }
782
 
783
+ if ( is_callable( [ $order, 'save' ] ) ) {
784
  $order->save();
785
  }
786
  }
792
  * @since 4.0.0
793
  * @version 4.0.6
794
  * @param object $order The order object
795
+ * @param int $balance_transaction_id
796
  */
797
  public function update_fees( $order, $balance_transaction_id ) {
798
  $balance_transaction = WC_Stripe_API::retrieve( 'balance/history/' . $balance_transaction_id );
818
  $currency = ! empty( $balance_transaction->currency ) ? strtoupper( $balance_transaction->currency ) : null;
819
  WC_Stripe_Helper::update_stripe_currency( $order, $currency );
820
 
821
+ if ( is_callable( [ $order, 'save' ] ) ) {
822
  $order->save();
823
  }
824
  }
845
  return false;
846
  }
847
 
848
+ $request = [];
849
 
850
  $order_currency = $order->get_currency();
851
  $captured = $order->get_meta( '_stripe_charge_captured', true );
872
  $reason = $reason . '... [See WooCommerce order page for full text.]';
873
  }
874
 
875
+ $request['metadata'] = [
876
  'reason' => $reason,
877
+ ];
878
  }
879
 
880
  $request['charge'] = $charge_id;
882
 
883
  $request = apply_filters( 'wc_stripe_refund_request', $request, $order );
884
 
885
+ $intent = $this->get_intent_from_order( $order );
886
  $intent_cancelled = false;
887
  if ( $intent ) {
888
  // If the order has a Payment Intent pending capture, then the Intent itself must be refunded (cancelled), not the Charge.
889
  if ( ! empty( $intent->error ) ) {
890
+ $response = $intent;
891
  $intent_cancelled = true;
892
  } elseif ( 'requires_capture' === $intent->status ) {
893
+ $result = WC_Stripe_API::request(
894
+ [],
895
  'payment_intents/' . $intent->id . '/cancel'
896
  );
897
  $intent_cancelled = true;
899
  if ( ! empty( $result->error ) ) {
900
  $response = $result;
901
  } else {
902
+ $charge = end( $result->charges->data );
903
  $response = end( $charge->refunds->data );
904
  }
905
  }
969
 
970
  $stripe_customer = new WC_Stripe_Customer( get_current_user_id() );
971
 
972
+ $source = ! empty( $_POST['stripe_source'] ) ? wc_clean( wp_unslash( $_POST['stripe_source'] ) ) : '';
973
 
974
  $source_object = WC_Stripe_API::retrieve( 'sources/' . $source );
975
 
980
 
981
  $source_id = $source_object->id;
982
  } elseif ( isset( $_POST['stripe_token'] ) ) {
983
+ $source_id = wc_clean( wp_unslash( $_POST['stripe_token'] ) );
984
  }
985
 
986
  $response = $stripe_customer->add_source( $source_id );
995
  return;
996
  }
997
 
998
+ do_action( 'wc_stripe_add_payment_method_' . ( isset( $_POST['payment_method'] ) ? wc_clean( wp_unslash( $_POST['payment_method'] ) ) : '' ) . '_success', $source_id, $source_object );
999
 
1000
+ return [
1001
  'result' => 'success',
1002
  'redirect' => wc_get_endpoint_url( 'payment-methods' ),
1003
+ ];
1004
  }
1005
 
1006
  /**
1031
  *
1032
  * @since 4.0.6
1033
  * @param string $idempotency_key
1034
+ * @param array $request
1035
  */
1036
  public function change_idempotency_key( $idempotency_key, $request ) {
1037
  $customer = ! empty( $request['customer'] ) ? $request['customer'] : '';
1068
  // The request for a charge contains metadata for the intent.
1069
  $full_request = $this->generate_payment_request( $order, $prepared_source );
1070
 
1071
+ $request = [
1072
  'source' => $prepared_source->source,
1073
  'amount' => WC_Stripe_Helper::get_stripe_amount( $order->get_total() ),
1074
  'currency' => strtolower( $order->get_currency() ),
1075
  'description' => $full_request['description'],
1076
  'metadata' => $full_request['metadata'],
1077
  'capture_method' => ( 'true' === $full_request['capture'] ) ? 'automatic' : 'manual',
1078
+ 'payment_method_types' => [
1079
  'card',
1080
+ ],
1081
+ ];
1082
 
1083
  if ( $prepared_source->customer ) {
1084
  $request['customer'] = $prepared_source->customer;
1092
  $request['shipping'] = $full_request['shipping'];
1093
  }
1094
 
1095
+ if ( isset( $full_request['receipt_email'] ) ) {
1096
+ $request['receipt_email'] = $full_request['receipt_email'];
1097
+ }
1098
+
1099
  /**
1100
  * Filter the return value of the WC_Payment_Gateway_CC::generate_create_intent_request.
1101
  *
1119
  $order_items = array_values( $order->get_items( [ 'line_item', 'fee' ] ) );
1120
  $currency = $order->get_currency();
1121
 
1122
+ $stripe_line_items = array_map(
1123
+ function( $item ) use ( $currency ) {
1124
+ if ( is_a( $item, 'WC_Order_Item_Product' ) ) {
1125
+ $product_id = $item->get_variation_id()
1126
+ ? $item->get_variation_id()
1127
+ : $item->get_product_id();
1128
+ $subtotal = $item->get_subtotal();
1129
+ } else {
1130
+ $product_id = substr( sanitize_title( $item->get_name() ), 0, 12 );
1131
+ $subtotal = $item->get_total();
1132
+ }
1133
+ $product_description = substr( $item->get_name(), 0, 26 );
1134
+ $quantity = $item->get_quantity();
1135
+ $unit_cost = WC_Stripe_Helper::get_stripe_amount( ( $subtotal / $quantity ), $currency );
1136
+ $tax_amount = WC_Stripe_Helper::get_stripe_amount( $item->get_total_tax(), $currency );
1137
+ $discount_amount = WC_Stripe_Helper::get_stripe_amount( $subtotal - $item->get_total(), $currency );
1138
+
1139
+ return (object) [
1140
+ 'product_code' => (string) $product_id, // Up to 12 characters that uniquely identify the product.
1141
+ 'product_description' => $product_description, // Up to 26 characters long describing the product.
1142
+ 'unit_cost' => $unit_cost, // Cost of the product, in cents, as a non-negative integer.
1143
+ 'quantity' => $quantity, // The number of items of this type sold, as a non-negative integer.
1144
+ 'tax_amount' => $tax_amount, // The amount of tax this item had added to it, in cents, as a non-negative integer.
1145
+ 'discount_amount' => $discount_amount, // The amount an item was discounted—if there was a sale,for example, as a non-negative integer.
1146
+ ];
1147
+ },
1148
+ $order_items
 
 
 
1149
  );
1150
 
1151
+ $level3_data = [
1152
+ 'merchant_reference' => $order->get_id(), // An alphanumeric string of up to characters in length. This unique value is assigned by the merchant to identify the order. Also known as an “Order ID”.
1153
+ 'shipping_amount' => WC_Stripe_Helper::get_stripe_amount( (float) $order->get_shipping_total() + (float) $order->get_shipping_tax(), $currency ), // The shipping cost, in cents, as a non-negative integer.
1154
+ 'line_items' => $stripe_line_items,
1155
+ ];
1156
+
1157
  // The customer’s U.S. shipping ZIP code.
1158
  $shipping_address_zip = $order->get_shipping_postcode();
1159
  if ( $this->is_valid_us_zip_code( $shipping_address_zip ) ) {
1203
  * @return object An updated intent.
1204
  */
1205
  public function update_existing_intent( $intent, $order, $prepared_source ) {
1206
+ $request = [];
1207
 
1208
  if ( $prepared_source->source !== $intent->source ) {
1209
  $request['source'] = $prepared_source->source;
1252
  }
1253
 
1254
  // Try to confirm the intent & capture the charge (if 3DS is not required).
1255
+ $confirm_request = [
1256
  'source' => $prepared_source->source,
1257
+ ];
1258
 
1259
+ $level3_data = $this->get_level3_data_from_order( $order );
1260
  $confirmed_intent = WC_Stripe_API::request_with_level3_data(
1261
  $confirm_request,
1262
  "payment_intents/$intent->id/confirm",
1289
  public function save_intent_to_order( $order, $intent ) {
1290
  $order->update_meta_data( '_stripe_intent_id', $intent->id );
1291
 
1292
+ if ( is_callable( [ $order, 'save' ] ) ) {
1293
  $order->save();
1294
  }
1295
  }
1321
  /**
1322
  * Retrieves intent from Stripe API by intent id.
1323
  *
1324
+ * @param string $intent_type Either 'payment_intents' or 'setup_intents'.
1325
+ * @param string $intent_id Intent id.
1326
+ * @return object|bool Either the intent object or `false`.
1327
+ * @throws Exception Throws exception for unknown $intent_type.
1328
  */
1329
  private function get_intent( $intent_type, $intent_id ) {
1330
  if ( ! in_array( $intent_type, [ 'payment_intents', 'setup_intents' ] ) ) {
1331
  throw new Exception( "Failed to get intent of type $intent_type. Type is not allowed" );
1332
  }
1333
 
1334
+ $response = WC_Stripe_API::request( [], "$intent_type/$intent_id", 'GET' );
1335
 
1336
  if ( $response && isset( $response->{ 'error' } ) ) {
1337
  $error_response_message = print_r( $response, true );
1338
+ WC_Stripe_Logger::log( "Failed to get Stripe intent $intent_type/$intent_id." );
1339
+ WC_Stripe_Logger::log( "Response: $error_response_message" );
1340
  return false;
1341
  }
1342
 
1357
  $processing = get_transient( $transient_name );
1358
 
1359
  // Block the process if the same intent is already being handled.
1360
+ if ( '-1' === $processing || ( isset( $intent->id ) && $processing === $intent->id ) ) {
1361
  return true;
1362
  }
1363
 
1399
  */
1400
  public function setup_intent( $order, $prepared_source ) {
1401
  $order_id = $order->get_id();
1402
+ $setup_intent = WC_Stripe_API::request(
1403
+ [
1404
+ 'payment_method' => $prepared_source->source,
1405
+ 'customer' => $prepared_source->customer,
1406
+ 'confirm' => 'true',
1407
+ ],
1408
+ 'setup_intents'
1409
+ );
1410
 
1411
  if ( is_wp_error( $setup_intent ) ) {
1412
  WC_Stripe_Logger::log( "Unable to create SetupIntent for Order #$order_id: " . print_r( $setup_intent, true ) );
1426
  * @param float $amount The amount to charge. If not specified, it will be read from the order.
1427
  * @return object An intent or an error.
1428
  */
1429
+ public function create_and_confirm_intent_for_off_session( $order, $prepared_source, $amount = null ) {
1430
  // The request for a charge contains metadata for the intent.
1431
  $full_request = $this->generate_payment_request( $order, $prepared_source );
1432
 
1433
+ $request = [
1434
  'amount' => $amount ? WC_Stripe_Helper::get_stripe_amount( $amount, $full_request['currency'] ) : $full_request['amount'],
1435
  'currency' => $full_request['currency'],
1436
  'description' => $full_request['description'],
1437
  'metadata' => $full_request['metadata'],
1438
+ 'payment_method_types' => [
1439
  'card',
1440
+ ],
1441
  'off_session' => 'true',
1442
  'confirm' => 'true',
1443
  'confirmation_method' => 'automatic',
1444
+ ];
1445
 
1446
  if ( isset( $full_request['statement_descriptor'] ) ) {
1447
  $request['statement_descriptor'] = $full_request['statement_descriptor'];
1464
  * @param WC_Order $order
1465
  * @param object $source
1466
  */
1467
+ $request = apply_filters( 'wc_stripe_generate_create_intent_request', $request, $order, $prepared_source );
1468
 
1469
  if ( isset( $full_request['shipping'] ) ) {
1470
  $request['shipping'] = $full_request['shipping'];
1471
  }
1472
 
1473
+ $level3_data = $this->get_level3_data_from_order( $order );
1474
+ $intent = WC_Stripe_API::request_with_level3_data(
1475
  $request,
1476
  'payment_intents',
1477
  $level3_data,
1504
  * Checks if subscription has a Stripe customer ID and adds it if doesn't.
1505
  *
1506
  * Fix renewal for existing subscriptions affected by https://github.com/woocommerce/woocommerce-gateway-stripe/issues/1072.
1507
+ *
1508
  * @param int $order_id subscription renewal order id.
1509
  */
1510
  public function ensure_subscription_has_customer_id( $order_id ) {
1511
+ $subscriptions_ids = wcs_get_subscriptions_for_order( $order_id, [ 'order_type' => 'any' ] );
1512
+ foreach ( $subscriptions_ids as $subscription_id => $subscription ) {
1513
  if ( ! metadata_exists( 'post', $subscription_id, '_stripe_customer_id' ) ) {
1514
  $stripe_customer = new WC_Stripe_Customer( $subscription->get_user_id() );
1515
  update_post_meta( $subscription_id, '_stripe_customer_id', $stripe_customer->get_id() );
includes/admin/class-wc-stripe-admin-notices.php CHANGED
@@ -11,9 +11,10 @@ if ( ! defined( 'ABSPATH' ) ) {
11
  class WC_Stripe_Admin_Notices {
12
  /**
13
  * Notices (array)
 
14
  * @var array
15
  */
16
- public $notices = array();
17
 
18
  /**
19
  * Constructor
@@ -21,9 +22,9 @@ class WC_Stripe_Admin_Notices {
21
  * @since 4.1.0
22
  */
23
  public function __construct() {
24
- add_action( 'admin_notices', array( $this, 'admin_notices' ) );
25
- add_action( 'wp_loaded', array( $this, 'hide_notices' ) );
26
- add_action( 'woocommerce_stripe_updated', array( $this, 'stripe_updated' ) );
27
  }
28
 
29
  /**
@@ -33,11 +34,11 @@ class WC_Stripe_Admin_Notices {
33
  * @version 4.0.0
34
  */
35
  public function add_admin_notice( $slug, $class, $message, $dismissible = false ) {
36
- $this->notices[ $slug ] = array(
37
  'class' => $class,
38
  'message' => $message,
39
  'dismissible' => $dismissible,
40
- );
41
  }
42
 
43
  /**
@@ -67,7 +68,15 @@ class WC_Stripe_Admin_Notices {
67
  }
68
 
69
  echo '<p>';
70
- echo wp_kses( $notice['message'], array( 'a' => array( 'href' => array(), 'target' => array() ) ) );
 
 
 
 
 
 
 
 
71
  echo '</p></div>';
72
  }
73
  }
@@ -79,7 +88,7 @@ class WC_Stripe_Admin_Notices {
79
  * @return array
80
  */
81
  public function get_payment_methods() {
82
- return array(
83
  'Alipay' => 'WC_Gateway_Stripe_Alipay',
84
  'Bancontact' => 'WC_Gateway_Stripe_Bancontact',
85
  'EPS' => 'WC_Gateway_Stripe_EPS',
@@ -89,7 +98,7 @@ class WC_Stripe_Admin_Notices {
89
  'P24' => 'WC_Gateway_Stripe_p24',
90
  'SEPA' => 'WC_Gateway_Stripe_Sepa',
91
  'SOFORT' => 'WC_Gateway_Stripe_Sofort',
92
- );
93
  }
94
 
95
  /**
@@ -199,6 +208,7 @@ class WC_Stripe_Admin_Notices {
199
  }
200
 
201
  if ( empty( $show_sca_notice ) ) {
 
202
  $this->add_admin_notice( 'sca', 'notice notice-success', sprintf( __( 'Stripe is now ready for Strong Customer Authentication (SCA) and 3D Secure 2! <a href="%1$s" target="_blank">Read about SCA</a>', 'woocommerce-gateway-stripe' ), 'https://woocommerce.com/posts/introducing-strong-customer-authentication-sca/' ), true );
203
  }
204
 
@@ -240,7 +250,7 @@ class WC_Stripe_Admin_Notices {
240
  */
241
  public function hide_notices() {
242
  if ( isset( $_GET['wc-stripe-hide-notice'] ) && isset( $_GET['_wc_stripe_notice_nonce'] ) ) {
243
- if ( ! wp_verify_nonce( $_GET['_wc_stripe_notice_nonce'], 'wc_stripe_hide_notices_nonce' ) ) {
244
  wp_die( __( 'Action failed. Please refresh the page and retry.', 'woocommerce-gateway-stripe' ) );
245
  }
246
 
@@ -248,7 +258,7 @@ class WC_Stripe_Admin_Notices {
248
  wp_die( __( 'Cheatin&#8217; huh?', 'woocommerce-gateway-stripe' ) );
249
  }
250
 
251
- $notice = wc_clean( $_GET['wc-stripe-hide-notice'] );
252
 
253
  switch ( $notice ) {
254
  case 'style':
11
  class WC_Stripe_Admin_Notices {
12
  /**
13
  * Notices (array)
14
+ *
15
  * @var array
16
  */
17
+ public $notices = [];
18
 
19
  /**
20
  * Constructor
22
  * @since 4.1.0
23
  */
24
  public function __construct() {
25
+ add_action( 'admin_notices', [ $this, 'admin_notices' ] );
26
+ add_action( 'wp_loaded', [ $this, 'hide_notices' ] );
27
+ add_action( 'woocommerce_stripe_updated', [ $this, 'stripe_updated' ] );
28
  }
29
 
30
  /**
34
  * @version 4.0.0
35
  */
36
  public function add_admin_notice( $slug, $class, $message, $dismissible = false ) {
37
+ $this->notices[ $slug ] = [
38
  'class' => $class,
39
  'message' => $message,
40
  'dismissible' => $dismissible,
41
+ ];
42
  }
43
 
44
  /**
68
  }
69
 
70
  echo '<p>';
71
+ echo wp_kses(
72
+ $notice['message'],
73
+ [
74
+ 'a' => [
75
+ 'href' => [],
76
+ 'target' => [],
77
+ ],
78
+ ]
79
+ );
80
  echo '</p></div>';
81
  }
82
  }
88
  * @return array
89
  */
90
  public function get_payment_methods() {
91
+ return [
92
  'Alipay' => 'WC_Gateway_Stripe_Alipay',
93
  'Bancontact' => 'WC_Gateway_Stripe_Bancontact',
94
  'EPS' => 'WC_Gateway_Stripe_EPS',
98
  'P24' => 'WC_Gateway_Stripe_p24',
99
  'SEPA' => 'WC_Gateway_Stripe_Sepa',
100
  'SOFORT' => 'WC_Gateway_Stripe_Sofort',
101
+ ];
102
  }
103
 
104
  /**
208
  }
209
 
210
  if ( empty( $show_sca_notice ) ) {
211
+ /* translators: %1 is the URL for the link */
212
  $this->add_admin_notice( 'sca', 'notice notice-success', sprintf( __( 'Stripe is now ready for Strong Customer Authentication (SCA) and 3D Secure 2! <a href="%1$s" target="_blank">Read about SCA</a>', 'woocommerce-gateway-stripe' ), 'https://woocommerce.com/posts/introducing-strong-customer-authentication-sca/' ), true );
213
  }
214
 
250
  */
251
  public function hide_notices() {
252
  if ( isset( $_GET['wc-stripe-hide-notice'] ) && isset( $_GET['_wc_stripe_notice_nonce'] ) ) {
253
+ if ( ! wp_verify_nonce( wc_clean( wp_unslash( $_GET['_wc_stripe_notice_nonce'] ) ), 'wc_stripe_hide_notices_nonce' ) ) {
254
  wp_die( __( 'Action failed. Please refresh the page and retry.', 'woocommerce-gateway-stripe' ) );
255
  }
256
 
258
  wp_die( __( 'Cheatin&#8217; huh?', 'woocommerce-gateway-stripe' ) );
259
  }
260
 
261
+ $notice = wc_clean( wp_unslash( $_GET['wc-stripe-hide-notice'] ) );
262
 
263
  switch ( $notice ) {
264
  case 'style':
includes/admin/class-wc-stripe-inbox-notes.php CHANGED
@@ -19,13 +19,13 @@ class WC_Stripe_Inbox_Notes {
19
  const CAMPAIGN_2020_CLEANUP_ACTION = 'wc_stripe_apple_pay_2020_cleanup';
20
 
21
  public function __construct() {
22
- add_action( self::POST_SETUP_SUCCESS_ACTION, array( self::class, 'create_marketing_note' ) );
23
- add_action( self::CAMPAIGN_2020_CLEANUP_ACTION, array( self::class, 'cleanup_campaign_2020' ) );
24
 
25
  // Schedule a 2020 holiday campaign cleanup action if needed.
26
  // First, check to see if we are still before the cutoff.
27
  // We don't need to (re)schedule this after the cutoff.
28
- if ( current_time( 'timestamp', true ) < self::get_campaign_2020_cutoff() ) {
29
  // If we don't have the clean up action scheduled, add it.
30
  if ( ! wp_next_scheduled( self::CAMPAIGN_2020_CLEANUP_ACTION ) ) {
31
  wp_schedule_single_event( self::get_campaign_2020_cutoff(), self::CAMPAIGN_2020_CLEANUP_ACTION );
@@ -38,7 +38,7 @@ class WC_Stripe_Inbox_Notes {
38
  }
39
 
40
  public static function get_success_title() {
41
- if ( current_time( 'timestamp', true ) < self::get_campaign_2020_cutoff() ) {
42
  return __( 'Boost sales this holiday season with Apple Pay!', 'woocommerce-gateway-stripe' );
43
  }
44
 
@@ -89,7 +89,7 @@ class WC_Stripe_Inbox_Notes {
89
  }
90
 
91
  // Make sure Apple Pay is enabled and setup is successful.
92
- $stripe_settings = get_option( 'woocommerce_stripe_settings', array() );
93
  $stripe_enabled = isset( $stripe_settings['enabled'] ) && 'yes' === $stripe_settings['enabled'];
94
  $button_enabled = isset( $stripe_settings['payment_request'] ) && 'yes' === $stripe_settings['payment_request'];
95
  $verification_complete = isset( $stripe_settings['apple_pay_domain_set'] ) && 'yes' === $stripe_settings['apple_pay_domain_set'];
@@ -162,7 +162,7 @@ class WC_Stripe_Inbox_Notes {
162
  * on/about 2020 Dec 22.
163
  */
164
  public static function cleanup_campaign_2020() {
165
- if ( ! class_exists( 'Automattic\WooCommerce\Admin\Notes\WC_Admin_Notes') ) {
166
  return;
167
  }
168
 
@@ -170,7 +170,7 @@ class WC_Stripe_Inbox_Notes {
170
  return;
171
  }
172
 
173
- $note_ids = array();
174
 
175
  try {
176
  $data_store = WC_Data_Store::load( 'admin-note' );
19
  const CAMPAIGN_2020_CLEANUP_ACTION = 'wc_stripe_apple_pay_2020_cleanup';
20
 
21
  public function __construct() {
22
+ add_action( self::POST_SETUP_SUCCESS_ACTION, [ self::class, 'create_marketing_note' ] );
23
+ add_action( self::CAMPAIGN_2020_CLEANUP_ACTION, [ self::class, 'cleanup_campaign_2020' ] );
24
 
25
  // Schedule a 2020 holiday campaign cleanup action if needed.
26
  // First, check to see if we are still before the cutoff.
27
  // We don't need to (re)schedule this after the cutoff.
28
+ if ( time() < self::get_campaign_2020_cutoff() ) {
29
  // If we don't have the clean up action scheduled, add it.
30
  if ( ! wp_next_scheduled( self::CAMPAIGN_2020_CLEANUP_ACTION ) ) {
31
  wp_schedule_single_event( self::get_campaign_2020_cutoff(), self::CAMPAIGN_2020_CLEANUP_ACTION );
38
  }
39
 
40
  public static function get_success_title() {
41
+ if ( time() < self::get_campaign_2020_cutoff() ) {
42
  return __( 'Boost sales this holiday season with Apple Pay!', 'woocommerce-gateway-stripe' );
43
  }
44
 
89
  }
90
 
91
  // Make sure Apple Pay is enabled and setup is successful.
92
+ $stripe_settings = get_option( 'woocommerce_stripe_settings', [] );
93
  $stripe_enabled = isset( $stripe_settings['enabled'] ) && 'yes' === $stripe_settings['enabled'];
94
  $button_enabled = isset( $stripe_settings['payment_request'] ) && 'yes' === $stripe_settings['payment_request'];
95
  $verification_complete = isset( $stripe_settings['apple_pay_domain_set'] ) && 'yes' === $stripe_settings['apple_pay_domain_set'];
162
  * on/about 2020 Dec 22.
163
  */
164
  public static function cleanup_campaign_2020() {
165
+ if ( ! class_exists( 'Automattic\WooCommerce\Admin\Notes\WC_Admin_Notes' ) ) {
166
  return;
167
  }
168
 
170
  return;
171
  }
172
 
173
+ $note_ids = [];
174
 
175
  try {
176
  $data_store = WC_Data_Store::load( 'admin-note' );
includes/admin/class-wc-stripe-privacy.php CHANGED
@@ -6,23 +6,22 @@ if ( ! class_exists( 'WC_Abstract_Privacy' ) ) {
6
  class WC_Stripe_Privacy extends WC_Abstract_Privacy {
7
  /**
8
  * Constructor
9
- *
10
  */
11
  public function __construct() {
12
  parent::__construct( __( 'Stripe', 'woocommerce-gateway-stripe' ) );
13
 
14
- $this->add_exporter( 'woocommerce-gateway-stripe-order-data', __( 'WooCommerce Stripe Order Data', 'woocommerce-gateway-stripe' ), array( $this, 'order_data_exporter' ) );
15
 
16
  if ( function_exists( 'wcs_get_subscriptions' ) ) {
17
- $this->add_exporter( 'woocommerce-gateway-stripe-subscriptions-data', __( 'WooCommerce Stripe Subscriptions Data', 'woocommerce-gateway-stripe' ), array( $this, 'subscriptions_data_exporter' ) );
18
  }
19
 
20
- $this->add_exporter( 'woocommerce-gateway-stripe-customer-data', __( 'WooCommerce Stripe Customer Data', 'woocommerce-gateway-stripe' ), array( $this, 'customer_data_exporter' ) );
21
 
22
- $this->add_eraser( 'woocommerce-gateway-stripe-customer-data', __( 'WooCommerce Stripe Customer Data', 'woocommerce-gateway-stripe' ), array( $this, 'customer_data_eraser' ) );
23
- $this->add_eraser( 'woocommerce-gateway-stripe-order-data', __( 'WooCommerce Stripe Data', 'woocommerce-gateway-stripe' ), array( $this, 'order_data_eraser' ) );
24
 
25
- add_filter( 'woocommerce_get_settings_account', array( $this, 'account_settings' ) );
26
  }
27
 
28
  /**
@@ -32,8 +31,8 @@ class WC_Stripe_Privacy extends WC_Abstract_Privacy {
32
  * @return array $settings Updated
33
  */
34
  public function account_settings( $settings ) {
35
- $insert_setting = array(
36
- array(
37
  'title' => __( 'Retain Stripe Data', 'woocommerce-gateway-stripe' ),
38
  'desc_tip' => __( 'Retains any Stripe data such as Stripe customer ID, source ID.', 'woocommerce-gateway-stripe' ),
39
  'id' => 'woocommerce_gateway_stripe_retention',
@@ -41,13 +40,13 @@ class WC_Stripe_Privacy extends WC_Abstract_Privacy {
41
  'placeholder' => __( 'N/A', 'woocommerce-gateway-stripe' ),
42
  'default' => '',
43
  'autoload' => false,
44
- ),
45
- );
46
 
47
  $index = null;
48
 
49
- foreach ( $settings as $key => $value) {
50
- if ( 'sectionend' === $value[ 'type' ] && 'personal_data_retention' === $value[ 'id' ] ) {
51
  $index = $key;
52
  break;
53
  }
@@ -63,19 +62,19 @@ class WC_Stripe_Privacy extends WC_Abstract_Privacy {
63
  /**
64
  * Returns a list of orders that are using one of Stripe's payment methods.
65
  *
66
- * @param string $email_address
67
- * @param int $page
68
  *
69
  * @return array WP_Post
70
  */
71
  protected function get_stripe_orders( $email_address, $page ) {
72
  $user = get_user_by( 'email', $email_address ); // Check if user has an ID in the DB to load stored personal data.
73
 
74
- $order_query = array(
75
- 'payment_method' => array( 'stripe', 'stripe_alipay', 'stripe_bancontact', 'stripe_eps', 'stripe_giropay', 'stripe_ideal', 'stripe_multibanco', 'stripe_p24', 'stripe_sepa', 'stripe_sofort' ),
76
  'limit' => 10,
77
  'page' => $page,
78
- );
79
 
80
  if ( $user instanceof WP_User ) {
81
  $order_query['customer_id'] = (int) $user->ID;
@@ -88,7 +87,6 @@ class WC_Stripe_Privacy extends WC_Abstract_Privacy {
88
 
89
  /**
90
  * Gets the message of the privacy to display.
91
- *
92
  */
93
  public function get_privacy_message() {
94
  /* translators: %s URL to docs */
@@ -105,7 +103,7 @@ class WC_Stripe_Privacy extends WC_Abstract_Privacy {
105
  */
106
  public function order_data_exporter( $email_address, $page = 1 ) {
107
  $done = false;
108
- $data_to_export = array();
109
 
110
  $orders = $this->get_stripe_orders( $email_address, (int) $page );
111
 
@@ -113,30 +111,30 @@ class WC_Stripe_Privacy extends WC_Abstract_Privacy {
113
 
114
  if ( 0 < count( $orders ) ) {
115
  foreach ( $orders as $order ) {
116
- $data_to_export[] = array(
117
  'group_id' => 'woocommerce_orders',
118
  'group_label' => __( 'Orders', 'woocommerce-gateway-stripe' ),
119
  'item_id' => 'order-' . $order->get_id(),
120
- 'data' => array(
121
- array(
122
  'name' => __( 'Stripe payment id', 'woocommerce-gateway-stripe' ),
123
  'value' => get_post_meta( $order->get_id(), '_stripe_source_id', true ),
124
- ),
125
- array(
126
  'name' => __( 'Stripe customer id', 'woocommerce-gateway-stripe' ),
127
  'value' => get_post_meta( $order->get_id(), '_stripe_customer_id', true ),
128
- ),
129
- ),
130
- );
131
  }
132
 
133
  $done = 10 > count( $orders );
134
  }
135
 
136
- return array(
137
  'data' => $data_to_export,
138
  'done' => $done,
139
- );
140
  }
141
 
142
  /**
@@ -150,27 +148,27 @@ class WC_Stripe_Privacy extends WC_Abstract_Privacy {
150
  public function subscriptions_data_exporter( $email_address, $page = 1 ) {
151
  $done = false;
152
  $page = (int) $page;
153
- $data_to_export = array();
154
 
155
- $meta_query = array(
156
  'relation' => 'AND',
157
- array(
158
  'key' => '_payment_method',
159
- 'value' => array( 'stripe', 'stripe_alipay', 'stripe_bancontact', 'stripe_eps', 'stripe_giropay', 'stripe_ideal', 'stripe_multibanco', 'stripe_p24', 'stripe_sepa', 'stripe_sofort' ),
160
  'compare' => 'IN',
161
- ),
162
- array(
163
  'key' => '_billing_email',
164
  'value' => $email_address,
165
  'compare' => '=',
166
- ),
167
- );
168
 
169
- $subscription_query = array(
170
  'posts_per_page' => 10,
171
  'page' => $page,
172
  'meta_query' => $meta_query,
173
- );
174
 
175
  $subscriptions = wcs_get_subscriptions( $subscription_query );
176
 
@@ -178,30 +176,30 @@ class WC_Stripe_Privacy extends WC_Abstract_Privacy {
178
 
179
  if ( 0 < count( $subscriptions ) ) {
180
  foreach ( $subscriptions as $subscription ) {
181
- $data_to_export[] = array(
182
  'group_id' => 'woocommerce_subscriptions',
183
  'group_label' => __( 'Subscriptions', 'woocommerce-gateway-stripe' ),
184
  'item_id' => 'subscription-' . $subscription->get_id(),
185
- 'data' => array(
186
- array(
187
  'name' => __( 'Stripe payment id', 'woocommerce-gateway-stripe' ),
188
  'value' => get_post_meta( $subscription->get_id(), '_stripe_source_id', true ),
189
- ),
190
- array(
191
  'name' => __( 'Stripe customer id', 'woocommerce-gateway-stripe' ),
192
  'value' => get_post_meta( $subscription->get_id(), '_stripe_customer_id', true ),
193
- ),
194
- ),
195
- );
196
  }
197
 
198
  $done = 10 > count( $subscriptions );
199
  }
200
 
201
- return array(
202
  'data' => $data_to_export,
203
  'done' => $done,
204
- );
205
  }
206
 
207
  /**
@@ -213,32 +211,32 @@ class WC_Stripe_Privacy extends WC_Abstract_Privacy {
213
  */
214
  public function customer_data_exporter( $email_address, $page ) {
215
  $user = get_user_by( 'email', $email_address ); // Check if user has an ID in the DB to load stored personal data.
216
- $data_to_export = array();
217
 
218
  if ( $user instanceof WP_User ) {
219
  $stripe_user = new WC_Stripe_Customer( $user->ID );
220
 
221
- $data_to_export[] = array(
222
  'group_id' => 'woocommerce_customer',
223
  'group_label' => __( 'Customer Data', 'woocommerce-gateway-stripe' ),
224
  'item_id' => 'user',
225
- 'data' => array(
226
- array(
227
  'name' => __( 'Stripe payment id', 'woocommerce-gateway-stripe' ),
228
  'value' => get_user_option( '_stripe_source_id', $user->ID ),
229
- ),
230
- array(
231
  'name' => __( 'Stripe customer id', 'woocommerce-gateway-stripe' ),
232
  'value' => $stripe_user->get_id(),
233
- ),
234
- ),
235
- );
236
  }
237
 
238
- return array(
239
  'data' => $data_to_export,
240
  'done' => true,
241
- );
242
  }
243
 
244
  /**
@@ -260,7 +258,7 @@ class WC_Stripe_Privacy extends WC_Abstract_Privacy {
260
  }
261
 
262
  $items_removed = false;
263
- $messages = array();
264
 
265
  if ( ! empty( $stripe_customer_id ) || ! empty( $stripe_source_id ) ) {
266
  $items_removed = true;
@@ -269,12 +267,12 @@ class WC_Stripe_Privacy extends WC_Abstract_Privacy {
269
  $messages[] = __( 'Stripe User Data Erased.', 'woocommerce-gateway-stripe' );
270
  }
271
 
272
- return array(
273
  'items_removed' => $items_removed,
274
  'items_retained' => false,
275
  'messages' => $messages,
276
  'done' => true,
277
- );
278
  }
279
 
280
  /**
@@ -289,7 +287,7 @@ class WC_Stripe_Privacy extends WC_Abstract_Privacy {
289
 
290
  $items_removed = false;
291
  $items_retained = false;
292
- $messages = array();
293
 
294
  foreach ( (array) $orders as $order ) {
295
  $order = wc_get_order( $order->get_id() );
@@ -308,12 +306,12 @@ class WC_Stripe_Privacy extends WC_Abstract_Privacy {
308
  // Tell core if we have more orders to work on still
309
  $done = count( $orders ) < 10;
310
 
311
- return array(
312
  'items_removed' => $items_removed,
313
  'items_retained' => $items_retained,
314
  'messages' => $messages,
315
  'done' => $done,
316
- );
317
  }
318
 
319
  /**
@@ -324,11 +322,11 @@ class WC_Stripe_Privacy extends WC_Abstract_Privacy {
324
  */
325
  protected function maybe_handle_subscription( $order ) {
326
  if ( ! class_exists( 'WC_Subscriptions' ) ) {
327
- return array( false, false, array() );
328
  }
329
 
330
  if ( ! wcs_order_contains_subscription( $order ) ) {
331
- return array( false, false, array() );
332
  }
333
 
334
  $subscription = current( wcs_get_subscriptions_for_order( $order->get_id() ) );
@@ -337,17 +335,17 @@ class WC_Stripe_Privacy extends WC_Abstract_Privacy {
337
  $stripe_source_id = get_post_meta( $subscription_id, '_stripe_source_id', true );
338
 
339
  if ( empty( $stripe_source_id ) ) {
340
- return array( false, false, array() );
341
  }
342
 
343
  if ( ! $this->is_retention_expired( $order->get_date_created()->getTimestamp() ) ) {
344
  /* translators: %d Order ID */
345
- return array( false, true, array( sprintf( __( 'Order ID %d is less than set retention days. Personal data retained. (Stripe)', 'woocommerce-gateway-stripe' ), $order->get_id() ) ) );
346
  }
347
 
348
- if ( $subscription->has_status( apply_filters( 'wc_stripe_privacy_eraser_subs_statuses', array( 'on-hold', 'active' ) ) ) ) {
349
  /* translators: %d Order ID */
350
- return array( false, true, array( sprintf( __( 'Order ID %d contains an active Subscription. Personal data retained. (Stripe)', 'woocommerce-gateway-stripe' ), $order->get_id() ) ) );
351
  }
352
 
353
  $renewal_orders = WC_Subscriptions_Renewal_Order::get_renewal_orders( $order->get_id() );
@@ -362,7 +360,7 @@ class WC_Stripe_Privacy extends WC_Abstract_Privacy {
362
  delete_post_meta( $subscription_id, '_stripe_refund_id' );
363
  delete_post_meta( $subscription_id, '_stripe_customer_id' );
364
 
365
- return array( true, false, array( __( 'Stripe Subscription Data Erased.', 'woocommerce-gateway-stripe' ) ) );
366
  }
367
 
368
  /**
@@ -379,23 +377,22 @@ class WC_Stripe_Privacy extends WC_Abstract_Privacy {
379
 
380
  if ( ! $this->is_retention_expired( $order->get_date_created()->getTimestamp() ) ) {
381
  /* translators: %d Order ID */
382
- return array( false, true, array( sprintf( __( 'Order ID %d is less than set retention days. Personal data retained. (Stripe)', 'woocommerce-gateway-stripe' ), $order->get_id() ) ) );
383
  }
384
 
385
  if ( empty( $stripe_source_id ) && empty( $stripe_refund_id ) && empty( $stripe_customer_id ) ) {
386
- return array( false, false, array() );
387
  }
388
 
389
  delete_post_meta( $order_id, '_stripe_source_id' );
390
  delete_post_meta( $order_id, '_stripe_refund_id' );
391
  delete_post_meta( $order_id, '_stripe_customer_id' );
392
 
393
- return array( true, false, array( __( 'Stripe personal data erased.', 'woocommerce-gateway-stripe' ) ) );
394
  }
395
 
396
  /**
397
  * Checks if create date is passed retention duration.
398
- *
399
  */
400
  public function is_retention_expired( $created_date ) {
401
  $retention = wc_parse_relative_date_option( get_option( 'woocommerce_gateway_stripe_retention' ) );
6
  class WC_Stripe_Privacy extends WC_Abstract_Privacy {
7
  /**
8
  * Constructor
 
9
  */
10
  public function __construct() {
11
  parent::__construct( __( 'Stripe', 'woocommerce-gateway-stripe' ) );
12
 
13
+ $this->add_exporter( 'woocommerce-gateway-stripe-order-data', __( 'WooCommerce Stripe Order Data', 'woocommerce-gateway-stripe' ), [ $this, 'order_data_exporter' ] );
14
 
15
  if ( function_exists( 'wcs_get_subscriptions' ) ) {
16
+ $this->add_exporter( 'woocommerce-gateway-stripe-subscriptions-data', __( 'WooCommerce Stripe Subscriptions Data', 'woocommerce-gateway-stripe' ), [ $this, 'subscriptions_data_exporter' ] );
17
  }
18
 
19
+ $this->add_exporter( 'woocommerce-gateway-stripe-customer-data', __( 'WooCommerce Stripe Customer Data', 'woocommerce-gateway-stripe' ), [ $this, 'customer_data_exporter' ] );
20
 
21
+ $this->add_eraser( 'woocommerce-gateway-stripe-customer-data', __( 'WooCommerce Stripe Customer Data', 'woocommerce-gateway-stripe' ), [ $this, 'customer_data_eraser' ] );
22
+ $this->add_eraser( 'woocommerce-gateway-stripe-order-data', __( 'WooCommerce Stripe Data', 'woocommerce-gateway-stripe' ), [ $this, 'order_data_eraser' ] );
23
 
24
+ add_filter( 'woocommerce_get_settings_account', [ $this, 'account_settings' ] );
25
  }
26
 
27
  /**
31
  * @return array $settings Updated
32
  */
33
  public function account_settings( $settings ) {
34
+ $insert_setting = [
35
+ [
36
  'title' => __( 'Retain Stripe Data', 'woocommerce-gateway-stripe' ),
37
  'desc_tip' => __( 'Retains any Stripe data such as Stripe customer ID, source ID.', 'woocommerce-gateway-stripe' ),
38
  'id' => 'woocommerce_gateway_stripe_retention',
40
  'placeholder' => __( 'N/A', 'woocommerce-gateway-stripe' ),
41
  'default' => '',
42
  'autoload' => false,
43
+ ],
44
+ ];
45
 
46
  $index = null;
47
 
48
+ foreach ( $settings as $key => $value ) {
49
+ if ( 'sectionend' === $value['type'] && 'personal_data_retention' === $value['id'] ) {
50
  $index = $key;
51
  break;
52
  }
62
  /**
63
  * Returns a list of orders that are using one of Stripe's payment methods.
64
  *
65
+ * @param string $email_address
66
+ * @param int $page
67
  *
68
  * @return array WP_Post
69
  */
70
  protected function get_stripe_orders( $email_address, $page ) {
71
  $user = get_user_by( 'email', $email_address ); // Check if user has an ID in the DB to load stored personal data.
72
 
73
+ $order_query = [
74
+ 'payment_method' => [ 'stripe', 'stripe_alipay', 'stripe_bancontact', 'stripe_eps', 'stripe_giropay', 'stripe_ideal', 'stripe_multibanco', 'stripe_p24', 'stripe_sepa', 'stripe_sofort' ],
75
  'limit' => 10,
76
  'page' => $page,
77
+ ];
78
 
79
  if ( $user instanceof WP_User ) {
80
  $order_query['customer_id'] = (int) $user->ID;
87
 
88
  /**
89
  * Gets the message of the privacy to display.
 
90
  */
91
  public function get_privacy_message() {
92
  /* translators: %s URL to docs */
103
  */
104
  public function order_data_exporter( $email_address, $page = 1 ) {
105
  $done = false;
106
+ $data_to_export = [];
107
 
108
  $orders = $this->get_stripe_orders( $email_address, (int) $page );
109
 
111
 
112
  if ( 0 < count( $orders ) ) {
113
  foreach ( $orders as $order ) {
114
+ $data_to_export[] = [
115
  'group_id' => 'woocommerce_orders',
116
  'group_label' => __( 'Orders', 'woocommerce-gateway-stripe' ),
117
  'item_id' => 'order-' . $order->get_id(),
118
+ 'data' => [
119
+ [
120
  'name' => __( 'Stripe payment id', 'woocommerce-gateway-stripe' ),
121
  'value' => get_post_meta( $order->get_id(), '_stripe_source_id', true ),
122
+ ],
123
+ [
124
  'name' => __( 'Stripe customer id', 'woocommerce-gateway-stripe' ),
125
  'value' => get_post_meta( $order->get_id(), '_stripe_customer_id', true ),
126
+ ],
127
+ ],
128
+ ];
129
  }
130
 
131
  $done = 10 > count( $orders );
132
  }
133
 
134
+ return [
135
  'data' => $data_to_export,
136
  'done' => $done,
137
+ ];
138
  }
139
 
140
  /**
148
  public function subscriptions_data_exporter( $email_address, $page = 1 ) {
149
  $done = false;
150
  $page = (int) $page;
151
+ $data_to_export = [];
152
 
153
+ $meta_query = [
154
  'relation' => 'AND',
155
+ [
156
  'key' => '_payment_method',
157
+ 'value' => [ 'stripe', 'stripe_alipay', 'stripe_bancontact', 'stripe_eps', 'stripe_giropay', 'stripe_ideal', 'stripe_multibanco', 'stripe_p24', 'stripe_sepa', 'stripe_sofort' ],
158
  'compare' => 'IN',
159
+ ],
160
+ [
161
  'key' => '_billing_email',
162
  'value' => $email_address,
163
  'compare' => '=',
164
+ ],
165
+ ];
166
 
167
+ $subscription_query = [
168
  'posts_per_page' => 10,
169
  'page' => $page,
170
  'meta_query' => $meta_query,
171
+ ];
172
 
173
  $subscriptions = wcs_get_subscriptions( $subscription_query );
174
 
176
 
177
  if ( 0 < count( $subscriptions ) ) {
178
  foreach ( $subscriptions as $subscription ) {
179
+ $data_to_export[] = [
180
  'group_id' => 'woocommerce_subscriptions',
181
  'group_label' => __( 'Subscriptions', 'woocommerce-gateway-stripe' ),
182
  'item_id' => 'subscription-' . $subscription->get_id(),
183
+ 'data' => [
184
+ [
185
  'name' => __( 'Stripe payment id', 'woocommerce-gateway-stripe' ),
186
  'value' => get_post_meta( $subscription->get_id(), '_stripe_source_id', true ),
187
+ ],
188
+ [
189
  'name' => __( 'Stripe customer id', 'woocommerce-gateway-stripe' ),
190
  'value' => get_post_meta( $subscription->get_id(), '_stripe_customer_id', true ),
191
+ ],
192
+ ],
193
+ ];
194
  }
195
 
196
  $done = 10 > count( $subscriptions );
197
  }
198
 
199
+ return [
200
  'data' => $data_to_export,
201
  'done' => $done,
202
+ ];
203
  }
204
 
205
  /**
211
  */
212
  public function customer_data_exporter( $email_address, $page ) {
213
  $user = get_user_by( 'email', $email_address ); // Check if user has an ID in the DB to load stored personal data.
214
+ $data_to_export = [];
215
 
216
  if ( $user instanceof WP_User ) {
217
  $stripe_user = new WC_Stripe_Customer( $user->ID );
218
 
219
+ $data_to_export[] = [
220
  'group_id' => 'woocommerce_customer',
221
  'group_label' => __( 'Customer Data', 'woocommerce-gateway-stripe' ),
222
  'item_id' => 'user',
223
+ 'data' => [
224
+ [
225
  'name' => __( 'Stripe payment id', 'woocommerce-gateway-stripe' ),
226
  'value' => get_user_option( '_stripe_source_id', $user->ID ),
227
+ ],
228
+ [
229
  'name' => __( 'Stripe customer id', 'woocommerce-gateway-stripe' ),
230
  'value' => $stripe_user->get_id(),
231
+ ],
232
+ ],
233
+ ];
234
  }
235
 
236
+ return [
237
  'data' => $data_to_export,
238
  'done' => true,
239
+ ];
240
  }
241
 
242
  /**
258
  }
259
 
260
  $items_removed = false;
261
+ $messages = [];
262
 
263
  if ( ! empty( $stripe_customer_id ) || ! empty( $stripe_source_id ) ) {
264
  $items_removed = true;
267
  $messages[] = __( 'Stripe User Data Erased.', 'woocommerce-gateway-stripe' );
268
  }
269
 
270
+ return [
271
  'items_removed' => $items_removed,
272
  'items_retained' => false,
273
  'messages' => $messages,
274
  'done' => true,
275
+ ];
276
  }
277
 
278
  /**
287
 
288
  $items_removed = false;
289
  $items_retained = false;
290
+ $messages = [];
291
 
292
  foreach ( (array) $orders as $order ) {
293
  $order = wc_get_order( $order->get_id() );
306
  // Tell core if we have more orders to work on still
307
  $done = count( $orders ) < 10;
308
 
309
+ return [
310
  'items_removed' => $items_removed,
311
  'items_retained' => $items_retained,
312
  'messages' => $messages,
313
  'done' => $done,
314
+ ];
315
  }
316
 
317
  /**
322
  */
323
  protected function maybe_handle_subscription( $order ) {
324
  if ( ! class_exists( 'WC_Subscriptions' ) ) {
325
+ return [ false, false, [] ];
326
  }
327
 
328
  if ( ! wcs_order_contains_subscription( $order ) ) {
329
+ return [ false, false, [] ];
330
  }
331
 
332
  $subscription = current( wcs_get_subscriptions_for_order( $order->get_id() ) );
335
  $stripe_source_id = get_post_meta( $subscription_id, '_stripe_source_id', true );
336
 
337
  if ( empty( $stripe_source_id ) ) {
338
+ return [ false, false, [] ];
339
  }
340
 
341
  if ( ! $this->is_retention_expired( $order->get_date_created()->getTimestamp() ) ) {
342
  /* translators: %d Order ID */
343
+ return [ false, true, [ sprintf( __( 'Order ID %d is less than set retention days. Personal data retained. (Stripe)', 'woocommerce-gateway-stripe' ), $order->get_id() ) ] ];
344
  }
345
 
346
+ if ( $subscription->has_status( apply_filters( 'wc_stripe_privacy_eraser_subs_statuses', [ 'on-hold', 'active' ] ) ) ) {
347
  /* translators: %d Order ID */
348
+ return [ false, true, [ sprintf( __( 'Order ID %d contains an active Subscription. Personal data retained. (Stripe)', 'woocommerce-gateway-stripe' ), $order->get_id() ) ] ];
349
  }
350
 
351
  $renewal_orders = WC_Subscriptions_Renewal_Order::get_renewal_orders( $order->get_id() );
360
  delete_post_meta( $subscription_id, '_stripe_refund_id' );
361
  delete_post_meta( $subscription_id, '_stripe_customer_id' );
362
 
363
+ return [ true, false, [ __( 'Stripe Subscription Data Erased.', 'woocommerce-gateway-stripe' ) ] ];
364
  }
365
 
366
  /**
377
 
378
  if ( ! $this->is_retention_expired( $order->get_date_created()->getTimestamp() ) ) {
379
  /* translators: %d Order ID */
380
+ return [ false, true, [ sprintf( __( 'Order ID %d is less than set retention days. Personal data retained. (Stripe)', 'woocommerce-gateway-stripe' ), $order->get_id() ) ] ];
381
  }
382
 
383
  if ( empty( $stripe_source_id ) && empty( $stripe_refund_id ) && empty( $stripe_customer_id ) ) {
384
+ return [ false, false, [] ];
385
  }
386
 
387
  delete_post_meta( $order_id, '_stripe_source_id' );
388
  delete_post_meta( $order_id, '_stripe_refund_id' );
389
  delete_post_meta( $order_id, '_stripe_customer_id' );
390
 
391
+ return [ true, false, [ __( 'Stripe personal data erased.', 'woocommerce-gateway-stripe' ) ] ];
392
  }
393
 
394
  /**
395
  * Checks if create date is passed retention duration.
 
396
  */
397
  public function is_retention_expired( $created_date ) {
398
  $retention = wc_parse_relative_date_option( get_option( 'woocommerce_gateway_stripe_retention' ) );
includes/admin/stripe-alipay-settings.php CHANGED
@@ -5,45 +5,45 @@ if ( ! defined( 'ABSPATH' ) ) {
5
 
6
  return apply_filters(
7
  'wc_stripe_alipay_settings',
8
- array(
9
- 'geo_target' => array(
10
  'description' => __( 'Customer Geography: China', 'woocommerce-gateway-stripe' ),
11
  'type' => 'title',
12
- ),
13
- 'guide' => array(
14
  'description' => __( '<a href="https://stripe.com/payments/payment-methods-guide#alipay" target="_blank">Payment Method Guide</a>', 'woocommerce-gateway-stripe' ),
15
  'type' => 'title',
16
- ),
17
- 'activation' => array(
18
  'description' => __( 'Must be activated from your Stripe Dashboard Settings <a href="https://dashboard.stripe.com/account/payments/settings" target="_blank">here</a>', 'woocommerce-gateway-stripe' ),
19
  'type' => 'title',
20
- ),
21
- 'enabled' => array(
22
  'title' => __( 'Enable/Disable', 'woocommerce-gateway-stripe' ),
23
  'label' => __( 'Enable Stripe Alipay', 'woocommerce-gateway-stripe' ),
24
  'type' => 'checkbox',
25
  'description' => '',
26
  'default' => 'no',
27
- ),
28
- 'title' => array(
29
  'title' => __( 'Title', 'woocommerce-gateway-stripe' ),
30
  'type' => 'text',
31
  'description' => __( 'This controls the title which the user sees during checkout.', 'woocommerce-gateway-stripe' ),
32
  'default' => __( 'Alipay', 'woocommerce-gateway-stripe' ),
33
  'desc_tip' => true,
34
- ),
35
- 'description' => array(
36
  'title' => __( 'Description', 'woocommerce-gateway-stripe' ),
37
  'type' => 'text',
38
  'description' => __( 'This controls the description which the user sees during checkout.', 'woocommerce-gateway-stripe' ),
39
  'default' => __( 'You will be redirected to Alipay.', 'woocommerce-gateway-stripe' ),
40
  'desc_tip' => true,
41
- ),
42
- 'webhook' => array(
43
  'title' => __( 'Webhook Endpoints', 'woocommerce-gateway-stripe' ),
44
  'type' => 'title',
45
  /* translators: webhook URL */
46
  'description' => $this->display_admin_settings_webhook_description(),
47
- ),
48
- )
49
  );
5
 
6
  return apply_filters(
7
  'wc_stripe_alipay_settings',
8
+ [
9
+ 'geo_target' => [
10
  'description' => __( 'Customer Geography: China', 'woocommerce-gateway-stripe' ),
11
  'type' => 'title',
12
+ ],
13
+ 'guide' => [
14
  'description' => __( '<a href="https://stripe.com/payments/payment-methods-guide#alipay" target="_blank">Payment Method Guide</a>', 'woocommerce-gateway-stripe' ),
15
  'type' => 'title',
16
+ ],
17
+ 'activation' => [
18
  'description' => __( 'Must be activated from your Stripe Dashboard Settings <a href="https://dashboard.stripe.com/account/payments/settings" target="_blank">here</a>', 'woocommerce-gateway-stripe' ),
19
  'type' => 'title',
20
+ ],
21
+ 'enabled' => [
22
  'title' => __( 'Enable/Disable', 'woocommerce-gateway-stripe' ),
23
  'label' => __( 'Enable Stripe Alipay', 'woocommerce-gateway-stripe' ),
24
  'type' => 'checkbox',
25
  'description' => '',
26
  'default' => 'no',
27
+ ],
28
+ 'title' => [
29
  'title' => __( 'Title', 'woocommerce-gateway-stripe' ),
30
  'type' => 'text',
31
  'description' => __( 'This controls the title which the user sees during checkout.', 'woocommerce-gateway-stripe' ),
32
  'default' => __( 'Alipay', 'woocommerce-gateway-stripe' ),
33
  'desc_tip' => true,
34
+ ],
35
+ 'description' => [
36
  'title' => __( 'Description', 'woocommerce-gateway-stripe' ),
37
  'type' => 'text',
38
  'description' => __( 'This controls the description which the user sees during checkout.', 'woocommerce-gateway-stripe' ),
39
  'default' => __( 'You will be redirected to Alipay.', 'woocommerce-gateway-stripe' ),
40
  'desc_tip' => true,
41
+ ],
42
+ 'webhook' => [
43
  'title' => __( 'Webhook Endpoints', 'woocommerce-gateway-stripe' ),
44
  'type' => 'title',
45
  /* translators: webhook URL */
46
  'description' => $this->display_admin_settings_webhook_description(),
47
+ ],
48
+ ]
49
  );
includes/admin/stripe-bancontact-settings.php CHANGED
@@ -5,45 +5,45 @@ if ( ! defined( 'ABSPATH' ) ) {
5
 
6
  return apply_filters(
7
  'wc_stripe_bancontact_settings',
8
- array(
9
- 'geo_target' => array(
10
  'description' => __( 'Customer Geography: Belgium', 'woocommerce-gateway-stripe' ),
11
  'type' => 'title',
12
- ),
13
- 'guide' => array(
14
  'description' => __( '<a href="https://stripe.com/payments/payment-methods-guide#bancontact" target="_blank">Payment Method Guide</a>', 'woocommerce-gateway-stripe' ),
15
  'type' => 'title',
16
- ),
17
- 'activation' => array(
18
  'description' => __( 'Must be activated from your Stripe Dashboard Settings <a href="https://dashboard.stripe.com/account/payments/settings" target="_blank">here</a>', 'woocommerce-gateway-stripe' ),
19
  'type' => 'title',
20
- ),
21
- 'enabled' => array(
22
  'title' => __( 'Enable/Disable', 'woocommerce-gateway-stripe' ),
23
  'label' => __( 'Enable Stripe Bancontact', 'woocommerce-gateway-stripe' ),
24
  'type' => 'checkbox',
25
  'description' => '',
26
  'default' => 'no',
27
- ),
28
- 'title' => array(
29
  'title' => __( 'Title', 'woocommerce-gateway-stripe' ),
30
  'type' => 'text',
31
  'description' => __( 'This controls the title which the user sees during checkout.', 'woocommerce-gateway-stripe' ),
32
  'default' => __( 'Bancontact', 'woocommerce-gateway-stripe' ),
33
  'desc_tip' => true,
34
- ),
35
- 'description' => array(
36
  'title' => __( 'Description', 'woocommerce-gateway-stripe' ),
37
  'type' => 'text',
38
  'description' => __( 'This controls the description which the user sees during checkout.', 'woocommerce-gateway-stripe' ),
39
  'default' => __( 'You will be redirected to Bancontact.', 'woocommerce-gateway-stripe' ),
40
  'desc_tip' => true,
41
- ),
42
- 'webhook' => array(
43
  'title' => __( 'Webhook Endpoints', 'woocommerce-gateway-stripe' ),
44
  'type' => 'title',
45
  /* translators: webhook URL */
46
  'description' => $this->display_admin_settings_webhook_description(),
47
- ),
48
- )
49
  );
5
 
6
  return apply_filters(
7
  'wc_stripe_bancontact_settings',
8
+ [
9
+ 'geo_target' => [
10
  'description' => __( 'Customer Geography: Belgium', 'woocommerce-gateway-stripe' ),
11
  'type' => 'title',
12
+ ],
13
+ 'guide' => [
14
  'description' => __( '<a href="https://stripe.com/payments/payment-methods-guide#bancontact" target="_blank">Payment Method Guide</a>', 'woocommerce-gateway-stripe' ),
15
  'type' => 'title',
16
+ ],
17
+ 'activation' => [
18
  'description' => __( 'Must be activated from your Stripe Dashboard Settings <a href="https://dashboard.stripe.com/account/payments/settings" target="_blank">here</a>', 'woocommerce-gateway-stripe' ),
19
  'type' => 'title',
20
+ ],
21
+ 'enabled' => [
22
  'title' => __( 'Enable/Disable', 'woocommerce-gateway-stripe' ),
23
  'label' => __( 'Enable Stripe Bancontact', 'woocommerce-gateway-stripe' ),
24
  'type' => 'checkbox',
25
  'description' => '',
26
  'default' => 'no',
27
+ ],
28
+ 'title' => [
29
  'title' => __( 'Title', 'woocommerce-gateway-stripe' ),
30
  'type' => 'text',
31
  'description' => __( 'This controls the title which the user sees during checkout.', 'woocommerce-gateway-stripe' ),
32
  'default' => __( 'Bancontact', 'woocommerce-gateway-stripe' ),
33
  'desc_tip' => true,
34
+ ],
35
+ 'description' => [
36
  'title' => __( 'Description', 'woocommerce-gateway-stripe' ),
37
  'type' => 'text',
38
  'description' => __( 'This controls the description which the user sees during checkout.', 'woocommerce-gateway-stripe' ),
39
  'default' => __( 'You will be redirected to Bancontact.', 'woocommerce-gateway-stripe' ),
40
  'desc_tip' => true,
41
+ ],
42
+ 'webhook' => [
43
  'title' => __( 'Webhook Endpoints', 'woocommerce-gateway-stripe' ),
44
  'type' => 'title',
45
  /* translators: webhook URL */
46
  'description' => $this->display_admin_settings_webhook_description(),
47
+ ],
48
+ ]
49
  );
includes/admin/stripe-eps-settings.php CHANGED
@@ -5,41 +5,41 @@ if ( ! defined( 'ABSPATH' ) ) {
5
 
6
  return apply_filters(
7
  'wc_stripe_eps_settings',
8
- array(
9
- 'geo_target' => array(
10
  'description' => __( 'Customer Geography: Austria', 'woocommerce-gateway-stripe' ),
11
  'type' => 'title',
12
- ),
13
- 'activation' => array(
14
  'description' => __( 'Must be activated from your Stripe Dashboard Settings <a href="https://dashboard.stripe.com/account/payments/settings" target="_blank">here</a>', 'woocommerce-gateway-stripe' ),
15
  'type' => 'title',
16
- ),
17
- 'enabled' => array(
18
  'title' => __( 'Enable/Disable', 'woocommerce-gateway-stripe' ),
19
  'label' => __( 'Enable Stripe EPS', 'woocommerce-gateway-stripe' ),
20
  'type' => 'checkbox',
21
  'description' => '',
22
  'default' => 'no',
23
- ),
24
- 'title' => array(
25
  'title' => __( 'Title', 'woocommerce-gateway-stripe' ),
26
  'type' => 'text',
27
  'description' => __( 'This controls the title which the user sees during checkout.', 'woocommerce-gateway-stripe' ),
28
  'default' => __( 'EPS', 'woocommerce-gateway-stripe' ),
29
  'desc_tip' => true,
30
- ),
31
- 'description' => array(
32
  'title' => __( 'Description', 'woocommerce-gateway-stripe' ),
33
  'type' => 'text',
34
  'description' => __( 'This controls the description which the user sees during checkout.', 'woocommerce-gateway-stripe' ),
35
  'default' => __( 'You will be redirected to EPS.', 'woocommerce-gateway-stripe' ),
36
  'desc_tip' => true,
37
- ),
38
- 'webhook' => array(
39
  'title' => __( 'Webhook Endpoints', 'woocommerce-gateway-stripe' ),
40
  'type' => 'title',
41
  /* translators: webhook URL */
42
  'description' => $this->display_admin_settings_webhook_description(),
43
- ),
44
- )
45
  );
5
 
6
  return apply_filters(
7
  'wc_stripe_eps_settings',
8
+ [
9
+ 'geo_target' => [
10
  'description' => __( 'Customer Geography: Austria', 'woocommerce-gateway-stripe' ),
11
  'type' => 'title',
12
+ ],
13
+ 'activation' => [
14
  'description' => __( 'Must be activated from your Stripe Dashboard Settings <a href="https://dashboard.stripe.com/account/payments/settings" target="_blank">here</a>', 'woocommerce-gateway-stripe' ),
15
  'type' => 'title',
16
+ ],
17
+ 'enabled' => [
18
  'title' => __( 'Enable/Disable', 'woocommerce-gateway-stripe' ),
19
  'label' => __( 'Enable Stripe EPS', 'woocommerce-gateway-stripe' ),
20
  'type' => 'checkbox',
21
  'description' => '',
22
  'default' => 'no',
23
+ ],
24
+ 'title' => [
25
  'title' => __( 'Title', 'woocommerce-gateway-stripe' ),
26
  'type' => 'text',
27
  'description' => __( 'This controls the title which the user sees during checkout.', 'woocommerce-gateway-stripe' ),
28
  'default' => __( 'EPS', 'woocommerce-gateway-stripe' ),
29
  'desc_tip' => true,
30
+ ],
31
+ 'description' => [
32
  'title' => __( 'Description', 'woocommerce-gateway-stripe' ),
33
  'type' => 'text',
34
  'description' => __( 'This controls the description which the user sees during checkout.', 'woocommerce-gateway-stripe' ),
35
  'default' => __( 'You will be redirected to EPS.', 'woocommerce-gateway-stripe' ),
36
  'desc_tip' => true,
37
+ ],
38
+ 'webhook' => [
39
  'title' => __( 'Webhook Endpoints', 'woocommerce-gateway-stripe' ),
40
  'type' => 'title',
41
  /* translators: webhook URL */
42
  'description' => $this->display_admin_settings_webhook_description(),
43
+ ],
44
+ ]
45
  );
includes/admin/stripe-giropay-settings.php CHANGED
@@ -5,45 +5,45 @@ if ( ! defined( 'ABSPATH' ) ) {
5
 
6
  return apply_filters(
7
  'wc_stripe_giropay_settings',
8
- array(
9
- 'geo_target' => array(
10
  'description' => __( 'Customer Geography: Germany', 'woocommerce-gateway-stripe' ),
11
  'type' => 'title',
12
- ),
13
- 'guide' => array(
14
  'description' => __( '<a href="https://stripe.com/payments/payment-methods-guide#giropay" target="_blank">Payment Method Guide</a>', 'woocommerce-gateway-stripe' ),
15
  'type' => 'title',
16
- ),
17
- 'activation' => array(
18
  'description' => __( 'Must be activated from your Stripe Dashboard Settings <a href="https://dashboard.stripe.com/account/payments/settings" target="_blank">here</a>', 'woocommerce-gateway-stripe' ),
19
  'type' => 'title',
20
- ),
21
- 'enabled' => array(
22
  'title' => __( 'Enable/Disable', 'woocommerce-gateway-stripe' ),
23
  'label' => __( 'Enable Stripe Giropay', 'woocommerce-gateway-stripe' ),
24
  'type' => 'checkbox',
25
  'description' => '',
26
  'default' => 'no',
27
- ),
28
- 'title' => array(
29
  'title' => __( 'Title', 'woocommerce-gateway-stripe' ),
30
  'type' => 'text',
31
  'description' => __( 'This controls the title which the user sees during checkout.', 'woocommerce-gateway-stripe' ),
32
  'default' => __( 'Giropay', 'woocommerce-gateway-stripe' ),
33
  'desc_tip' => true,
34
- ),
35
- 'description' => array(
36
  'title' => __( 'Description', 'woocommerce-gateway-stripe' ),
37
  'type' => 'text',
38
  'description' => __( 'This controls the description which the user sees during checkout.', 'woocommerce-gateway-stripe' ),
39
  'default' => __( 'You will be redirected to Giropay.', 'woocommerce-gateway-stripe' ),
40
  'desc_tip' => true,
41
- ),
42
- 'webhook' => array(
43
  'title' => __( 'Webhook Endpoints', 'woocommerce-gateway-stripe' ),
44
  'type' => 'title',
45
  /* translators: webhook URL */
46
  'description' => $this->display_admin_settings_webhook_description(),
47
- ),
48
- )
49
  );
5
 
6
  return apply_filters(
7
  'wc_stripe_giropay_settings',
8
+ [
9
+ 'geo_target' => [
10
  'description' => __( 'Customer Geography: Germany', 'woocommerce-gateway-stripe' ),
11
  'type' => 'title',
12
+ ],
13
+ 'guide' => [
14
  'description' => __( '<a href="https://stripe.com/payments/payment-methods-guide#giropay" target="_blank">Payment Method Guide</a>', 'woocommerce-gateway-stripe' ),
15
  'type' => 'title',
16
+ ],
17
+ 'activation' => [
18
  'description' => __( 'Must be activated from your Stripe Dashboard Settings <a href="https://dashboard.stripe.com/account/payments/settings" target="_blank">here</a>', 'woocommerce-gateway-stripe' ),
19
  'type' => 'title',
20
+ ],
21
+ 'enabled' => [
22
  'title' => __( 'Enable/Disable', 'woocommerce-gateway-stripe' ),
23
  'label' => __( 'Enable Stripe Giropay', 'woocommerce-gateway-stripe' ),
24
  'type' => 'checkbox',
25
  'description' => '',
26
  'default' => 'no',
27
+ ],
28
+ 'title' => [
29
  'title' => __( 'Title', 'woocommerce-gateway-stripe' ),
30
  'type' => 'text',
31
  'description' => __( 'This controls the title which the user sees during checkout.', 'woocommerce-gateway-stripe' ),
32
  'default' => __( 'Giropay', 'woocommerce-gateway-stripe' ),
33
  'desc_tip' => true,
34
+ ],
35
+ 'description' => [
36
  'title' => __( 'Description', 'woocommerce-gateway-stripe' ),
37
  'type' => 'text',
38
  'description' => __( 'This controls the description which the user sees during checkout.', 'woocommerce-gateway-stripe' ),
39
  'default' => __( 'You will be redirected to Giropay.', 'woocommerce-gateway-stripe' ),
40
  'desc_tip' => true,
41
+ ],
42
+ 'webhook' => [
43
  'title' => __( 'Webhook Endpoints', 'woocommerce-gateway-stripe' ),
44
  'type' => 'title',
45
  /* translators: webhook URL */
46
  'description' => $this->display_admin_settings_webhook_description(),
47
+ ],
48
+ ]
49
  );
includes/admin/stripe-ideal-settings.php CHANGED
@@ -5,45 +5,45 @@ if ( ! defined( 'ABSPATH' ) ) {
5
 
6
  return apply_filters(
7
  'wc_stripe_ideal_settings',
8
- array(
9
- 'geo_target' => array(
10
  'description' => __( 'Customer Geography: The Netherlands', 'woocommerce-gateway-stripe' ),
11
  'type' => 'title',
12
- ),
13
- 'guide' => array(
14
  'description' => __( '<a href="https://stripe.com/payments/payment-methods-guide#ideal" target="_blank">Payment Method Guide</a>', 'woocommerce-gateway-stripe' ),
15
  'type' => 'title',
16
- ),
17
- 'activation' => array(
18
  'description' => __( 'Must be activated from your Stripe Dashboard Settings <a href="https://dashboard.stripe.com/account/payments/settings" target="_blank">here</a>', 'woocommerce-gateway-stripe' ),
19
  'type' => 'title',
20
- ),
21
- 'enabled' => array(
22
  'title' => __( 'Enable/Disable', 'woocommerce-gateway-stripe' ),
23
  'label' => __( 'Enable Stripe iDeal', 'woocommerce-gateway-stripe' ),
24
  'type' => 'checkbox',
25
  'description' => '',
26
  'default' => 'no',
27
- ),
28
- 'title' => array(
29
  'title' => __( 'Title', 'woocommerce-gateway-stripe' ),
30
  'type' => 'text',
31
  'description' => __( 'This controls the title which the user sees during checkout.', 'woocommerce-gateway-stripe' ),
32
  'default' => __( 'iDeal', 'woocommerce-gateway-stripe' ),
33
  'desc_tip' => true,
34
- ),
35
- 'description' => array(
36
  'title' => __( 'Description', 'woocommerce-gateway-stripe' ),
37
  'type' => 'text',
38
  'description' => __( 'This controls the description which the user sees during checkout.', 'woocommerce-gateway-stripe' ),
39
  'default' => __( 'You will be redirected to iDeal.', 'woocommerce-gateway-stripe' ),
40
  'desc_tip' => true,
41
- ),
42
- 'webhook' => array(
43
  'title' => __( 'Webhook Endpoints', 'woocommerce-gateway-stripe' ),
44
  'type' => 'title',
45
  /* translators: webhook URL */
46
  'description' => $this->display_admin_settings_webhook_description(),
47
- ),
48
- )
49
  );
5
 
6
  return apply_filters(
7
  'wc_stripe_ideal_settings',
8
+ [
9
+ 'geo_target' => [
10
  'description' => __( 'Customer Geography: The Netherlands', 'woocommerce-gateway-stripe' ),
11
  'type' => 'title',
12
+ ],
13
+ 'guide' => [
14
  'description' => __( '<a href="https://stripe.com/payments/payment-methods-guide#ideal" target="_blank">Payment Method Guide</a>', 'woocommerce-gateway-stripe' ),
15
  'type' => 'title',
16
+ ],
17
+ 'activation' => [
18
  'description' => __( 'Must be activated from your Stripe Dashboard Settings <a href="https://dashboard.stripe.com/account/payments/settings" target="_blank">here</a>', 'woocommerce-gateway-stripe' ),
19
  'type' => 'title',
20
+ ],
21
+ 'enabled' => [
22
  'title' => __( 'Enable/Disable', 'woocommerce-gateway-stripe' ),
23
  'label' => __( 'Enable Stripe iDeal', 'woocommerce-gateway-stripe' ),
24
  'type' => 'checkbox',
25
  'description' => '',
26
  'default' => 'no',
27
+ ],
28
+ 'title' => [
29
  'title' => __( 'Title', 'woocommerce-gateway-stripe' ),
30
  'type' => 'text',
31
  'description' => __( 'This controls the title which the user sees during checkout.', 'woocommerce-gateway-stripe' ),
32
  'default' => __( 'iDeal', 'woocommerce-gateway-stripe' ),
33
  'desc_tip' => true,
34
+ ],
35
+ 'description' => [
36
  'title' => __( 'Description', 'woocommerce-gateway-stripe' ),
37
  'type' => 'text',
38
  'description' => __( 'This controls the description which the user sees during checkout.', 'woocommerce-gateway-stripe' ),
39
  'default' => __( 'You will be redirected to iDeal.', 'woocommerce-gateway-stripe' ),
40
  'desc_tip' => true,
41
+ ],
42
+ 'webhook' => [
43
  'title' => __( 'Webhook Endpoints', 'woocommerce-gateway-stripe' ),
44
  'type' => 'title',
45
  /* translators: webhook URL */
46
  'description' => $this->display_admin_settings_webhook_description(),
47
+ ],
48
+ ]
49
  );
includes/admin/stripe-multibanco-settings.php CHANGED
@@ -5,41 +5,41 @@ if ( ! defined( 'ABSPATH' ) ) {
5
 
6
  return apply_filters(
7
  'wc_stripe_multibanco_settings',
8
- array(
9
- 'geo_target' => array(
10
  'description' => __( 'Customer Geography: Portugal', 'woocommerce-gateway-stripe' ),
11
  'type' => 'title',
12
- ),
13
- 'activation' => array(
14
  'description' => __( 'Must be activated from your Stripe Dashboard Settings <a href="https://dashboard.stripe.com/account/payments/settings" target="_blank">here</a>', 'woocommerce-gateway-stripe' ),
15
  'type' => 'title',
16
- ),
17
- 'enabled' => array(
18
  'title' => __( 'Enable/Disable', 'woocommerce-gateway-stripe' ),
19
  'label' => __( 'Enable Stripe Multibanco', 'woocommerce-gateway-stripe' ),
20
  'type' => 'checkbox',
21
  'description' => '',
22
  'default' => 'no',
23
- ),
24
- 'title' => array(
25
  'title' => __( 'Title', 'woocommerce-gateway-stripe' ),
26
  'type' => 'text',
27
  'description' => __( 'This controls the title which the user sees during checkout.', 'woocommerce-gateway-stripe' ),
28
  'default' => __( 'Multibanco', 'woocommerce-gateway-stripe' ),
29
  'desc_tip' => true,
30
- ),
31
- 'description' => array(
32
  'title' => __( 'Description', 'woocommerce-gateway-stripe' ),
33
  'type' => 'text',
34
  'description' => __( 'This controls the description which the user sees during checkout.', 'woocommerce-gateway-stripe' ),
35
  'default' => __( 'You will be redirected to Multibanco.', 'woocommerce-gateway-stripe' ),
36
  'desc_tip' => true,
37
- ),
38
- 'webhook' => array(
39
  'title' => __( 'Webhook Endpoints', 'woocommerce-gateway-stripe' ),
40
  'type' => 'title',
41
  /* translators: webhook URL */
42
  'description' => $this->display_admin_settings_webhook_description(),
43
- ),
44
- )
45
  );
5
 
6
  return apply_filters(
7
  'wc_stripe_multibanco_settings',
8
+ [
9
+ 'geo_target' => [
10
  'description' => __( 'Customer Geography: Portugal', 'woocommerce-gateway-stripe' ),
11
  'type' => 'title',
12
+ ],
13
+ 'activation' => [
14
  'description' => __( 'Must be activated from your Stripe Dashboard Settings <a href="https://dashboard.stripe.com/account/payments/settings" target="_blank">here</a>', 'woocommerce-gateway-stripe' ),
15
  'type' => 'title',
16
+ ],
17
+ 'enabled' => [
18
  'title' => __( 'Enable/Disable', 'woocommerce-gateway-stripe' ),
19
  'label' => __( 'Enable Stripe Multibanco', 'woocommerce-gateway-stripe' ),
20
  'type' => 'checkbox',
21
  'description' => '',
22
  'default' => 'no',
23
+ ],
24
+ 'title' => [
25
  'title' => __( 'Title', 'woocommerce-gateway-stripe' ),
26
  'type' => 'text',
27
  'description' => __( 'This controls the title which the user sees during checkout.', 'woocommerce-gateway-stripe' ),
28
  'default' => __( 'Multibanco', 'woocommerce-gateway-stripe' ),
29
  'desc_tip' => true,
30
+ ],
31
+ 'description' => [
32
  'title' => __( 'Description', 'woocommerce-gateway-stripe' ),
33
  'type' => 'text',
34
  'description' => __( 'This controls the description which the user sees during checkout.', 'woocommerce-gateway-stripe' ),
35
  'default' => __( 'You will be redirected to Multibanco.', 'woocommerce-gateway-stripe' ),
36
  'desc_tip' => true,
37
+ ],
38
+ 'webhook' => [
39
  'title' => __( 'Webhook Endpoints', 'woocommerce-gateway-stripe' ),
40
  'type' => 'title',
41
  /* translators: webhook URL */
42
  'description' => $this->display_admin_settings_webhook_description(),
43
+ ],
44
+ ]
45
  );
includes/admin/stripe-p24-settings.php CHANGED
@@ -5,41 +5,41 @@ if ( ! defined( 'ABSPATH' ) ) {
5
 
6
  return apply_filters(
7
  'wc_stripe_p24_settings',
8
- array(
9
- 'geo_target' => array(
10
  'description' => __( 'Customer Geography: Poland', 'woocommerce-gateway-stripe' ),
11
  'type' => 'title',
12
- ),
13
- 'activation' => array(
14
  'description' => __( 'Must be activated from your Stripe Dashboard Settings <a href="https://dashboard.stripe.com/account/payments/settings" target="_blank">here</a>', 'woocommerce-gateway-stripe' ),
15
  'type' => 'title',
16
- ),
17
- 'enabled' => array(
18
  'title' => __( 'Enable/Disable', 'woocommerce-gateway-stripe' ),
19
  'label' => __( 'Enable Stripe P24', 'woocommerce-gateway-stripe' ),
20
  'type' => 'checkbox',
21
  'description' => '',
22
  'default' => 'no',
23
- ),
24
- 'title' => array(
25
  'title' => __( 'Title', 'woocommerce-gateway-stripe' ),
26
  'type' => 'text',
27
  'description' => __( 'This controls the title which the user sees during checkout.', 'woocommerce-gateway-stripe' ),
28
  'default' => __( 'Przelewy24 (P24)', 'woocommerce-gateway-stripe' ),
29
  'desc_tip' => true,
30
- ),
31
- 'description' => array(
32
  'title' => __( 'Description', 'woocommerce-gateway-stripe' ),
33
  'type' => 'text',
34
  'description' => __( 'This controls the description which the user sees during checkout.', 'woocommerce-gateway-stripe' ),
35
  'default' => __( 'You will be redirected to P24.', 'woocommerce-gateway-stripe' ),
36
  'desc_tip' => true,
37
- ),
38
- 'webhook' => array(
39
  'title' => __( 'Webhook Endpoints', 'woocommerce-gateway-stripe' ),
40
  'type' => 'title',
41
  /* translators: webhook URL */
42
  'description' => $this->display_admin_settings_webhook_description(),
43
- ),
44
- )
45
  );
5
 
6
  return apply_filters(
7
  'wc_stripe_p24_settings',
8
+ [
9
+ 'geo_target' => [
10
  'description' => __( 'Customer Geography: Poland', 'woocommerce-gateway-stripe' ),
11
  'type' => 'title',
12
+ ],
13
+ 'activation' => [
14
  'description' => __( 'Must be activated from your Stripe Dashboard Settings <a href="https://dashboard.stripe.com/account/payments/settings" target="_blank">here</a>', 'woocommerce-gateway-stripe' ),
15
  'type' => 'title',
16
+ ],
17
+ 'enabled' => [
18
  'title' => __( 'Enable/Disable', 'woocommerce-gateway-stripe' ),
19
  'label' => __( 'Enable Stripe P24', 'woocommerce-gateway-stripe' ),
20
  'type' => 'checkbox',
21
  'description' => '',
22
  'default' => 'no',
23
+ ],
24
+ 'title' => [
25
  'title' => __( 'Title', 'woocommerce-gateway-stripe' ),
26
  'type' => 'text',
27
  'description' => __( 'This controls the title which the user sees during checkout.', 'woocommerce-gateway-stripe' ),
28
  'default' => __( 'Przelewy24 (P24)', 'woocommerce-gateway-stripe' ),
29
  'desc_tip' => true,
30
+ ],
31
+ 'description' => [
32
  'title' => __( 'Description', 'woocommerce-gateway-stripe' ),
33
  'type' => 'text',
34
  'description' => __( 'This controls the description which the user sees during checkout.', 'woocommerce-gateway-stripe' ),
35
  'default' => __( 'You will be redirected to P24.', 'woocommerce-gateway-stripe' ),
36
  'desc_tip' => true,
37
+ ],
38
+ 'webhook' => [
39
  'title' => __( 'Webhook Endpoints', 'woocommerce-gateway-stripe' ),
40
  'type' => 'title',
41
  /* translators: webhook URL */
42
  'description' => $this->display_admin_settings_webhook_description(),
43
+ ],
44
+ ]
45
  );
includes/admin/stripe-sepa-settings.php CHANGED
@@ -5,45 +5,45 @@ if ( ! defined( 'ABSPATH' ) ) {
5
 
6
  return apply_filters(
7
  'wc_stripe_sepa_settings',
8
- array(
9
- 'geo_target' => array(
10
  'description' => __( 'Customer Geography: France, Germany, Spain, Belgium, Netherlands, Luxembourg, Italy, Portugal, Austria, Ireland', 'woocommerce-gateway-stripe' ),
11
  'type' => 'title',
12
- ),
13
- 'guide' => array(
14
  'description' => __( '<a href="https://stripe.com/payments/payment-methods-guide#sepa-direct-debit" target="_blank">Payment Method Guide</a>', 'woocommerce-gateway-stripe' ),
15
  'type' => 'title',
16
- ),
17
- 'activation' => array(
18
  'description' => __( 'Must be activated from your Stripe Dashboard Settings <a href="https://dashboard.stripe.com/account/payments/settings" target="_blank">here</a>', 'woocommerce-gateway-stripe' ),
19
  'type' => 'title',
20
- ),
21
- 'enabled' => array(
22
  'title' => __( 'Enable/Disable', 'woocommerce-gateway-stripe' ),
23
  'label' => __( 'Enable Stripe SEPA Direct Debit', 'woocommerce-gateway-stripe' ),
24
  'type' => 'checkbox',
25
  'description' => '',
26
  'default' => 'no',
27
- ),
28
- 'title' => array(
29
  'title' => __( 'Title', 'woocommerce-gateway-stripe' ),
30
  'type' => 'text',
31
  'description' => __( 'This controls the title which the user sees during checkout.', 'woocommerce-gateway-stripe' ),
32
  'default' => __( 'SEPA Direct Debit', 'woocommerce-gateway-stripe' ),
33
  'desc_tip' => true,
34
- ),
35
- 'description' => array(
36
  'title' => __( 'Description', 'woocommerce-gateway-stripe' ),
37
  'type' => 'text',
38
  'description' => __( 'This controls the description which the user sees during checkout.', 'woocommerce-gateway-stripe' ),
39
  'default' => __( 'Mandate Information.', 'woocommerce-gateway-stripe' ),
40
  'desc_tip' => true,
41
- ),
42
- 'webhook' => array(
43
  'title' => __( 'Webhook Endpoints', 'woocommerce-gateway-stripe' ),
44
  'type' => 'title',
45
  /* translators: webhook URL */
46
  'description' => $this->display_admin_settings_webhook_description(),
47
- ),
48
- )
49
  );
5
 
6
  return apply_filters(
7
  'wc_stripe_sepa_settings',
8
+ [
9
+ 'geo_target' => [
10
  'description' => __( 'Customer Geography: France, Germany, Spain, Belgium, Netherlands, Luxembourg, Italy, Portugal, Austria, Ireland', 'woocommerce-gateway-stripe' ),
11
  'type' => 'title',
12
+ ],
13
+ 'guide' => [
14
  'description' => __( '<a href="https://stripe.com/payments/payment-methods-guide#sepa-direct-debit" target="_blank">Payment Method Guide</a>', 'woocommerce-gateway-stripe' ),
15
  'type' => 'title',
16
+ ],
17
+ 'activation' => [
18
  'description' => __( 'Must be activated from your Stripe Dashboard Settings <a href="https://dashboard.stripe.com/account/payments/settings" target="_blank">here</a>', 'woocommerce-gateway-stripe' ),
19
  'type' => 'title',
20
+ ],
21
+ 'enabled' => [
22
  'title' => __( 'Enable/Disable', 'woocommerce-gateway-stripe' ),
23
  'label' => __( 'Enable Stripe SEPA Direct Debit', 'woocommerce-gateway-stripe' ),
24
  'type' => 'checkbox',
25
  'description' => '',
26
  'default' => 'no',
27
+ ],
28
+ 'title' => [
29
  'title' => __( 'Title', 'woocommerce-gateway-stripe' ),
30
  'type' => 'text',
31
  'description' => __( 'This controls the title which the user sees during checkout.', 'woocommerce-gateway-stripe' ),
32
  'default' => __( 'SEPA Direct Debit', 'woocommerce-gateway-stripe' ),
33
  'desc_tip' => true,
34
+ ],
35
+ 'description' => [
36
  'title' => __( 'Description', 'woocommerce-gateway-stripe' ),
37
  'type' => 'text',
38
  'description' => __( 'This controls the description which the user sees during checkout.', 'woocommerce-gateway-stripe' ),
39
  'default' => __( 'Mandate Information.', 'woocommerce-gateway-stripe' ),
40
  'desc_tip' => true,
41
+ ],
42
+ 'webhook' => [
43
  'title' => __( 'Webhook Endpoints', 'woocommerce-gateway-stripe' ),
44
  'type' => 'title',
45
  /* translators: webhook URL */
46
  'description' => $this->display_admin_settings_webhook_description(),
47
+ ],
48
+ ]
49
  );
includes/admin/stripe-settings.php CHANGED
@@ -5,14 +5,15 @@ if ( ! defined( 'ABSPATH' ) ) {
5
 
6
  if ( woocommerce_gateway_stripe()->connect->is_connected() ) {
7
  $reset_link = add_query_arg(
8
- array(
9
  '_wpnonce' => wp_create_nonce( 'reset_stripe_api_credentials' ),
10
  'reset_stripe_api_credentials' => true,
11
- ),
12
  admin_url( 'admin.php?page=wc-settings&tab=checkout&section=stripe' )
13
  );
14
 
15
  $api_credentials_text = sprintf(
 
16
  __( '%1$sClear all Stripe account keys.%2$s %3$sThis will disable any connection to Stripe.%4$s', 'woocommerce-gateway-stripe' ),
17
  '<a id="wc_stripe_connect_button" href="' . $reset_link . '" class="button button-secondary">',
18
  '</a>',
@@ -24,11 +25,11 @@ if ( woocommerce_gateway_stripe()->connect->is_connected() ) {
24
 
25
  if ( ! is_wp_error( $oauth_url ) ) {
26
  $api_credentials_text = sprintf(
 
27
  __( '%1$sSetup or link an existing Stripe account.%2$s By clicking this button you agree to the %3$sTerms of Service%2$s. Or, manually enter Stripe account keys below.', 'woocommerce-gateway-stripe' ),
28
  '<a id="wc_stripe_connect_button" href="' . $oauth_url . '" class="button button-primary">',
29
  '</a>',
30
  '<a href="https://wordpress.com/tos">'
31
-
32
  );
33
  } else {
34
  $api_credentials_text = __( 'Manually enter Stripe keys below.', 'woocommerce-gateway-stripe' );
@@ -37,112 +38,111 @@ if ( woocommerce_gateway_stripe()->connect->is_connected() ) {
37
 
38
  return apply_filters(
39
  'wc_stripe_settings',
40
- array(
41
- 'enabled' => array(
42
  'title' => __( 'Enable/Disable', 'woocommerce-gateway-stripe' ),
43
  'label' => __( 'Enable Stripe', 'woocommerce-gateway-stripe' ),
44
  'type' => 'checkbox',
45
  'description' => '',
46
  'default' => 'no',
47
- ),
48
- 'title' => array(
49
  'title' => __( 'Title', 'woocommerce-gateway-stripe' ),
50
  'type' => 'text',
51
  'description' => __( 'This controls the title which the user sees during checkout.', 'woocommerce-gateway-stripe' ),
52
  'default' => __( 'Credit Card (Stripe)', 'woocommerce-gateway-stripe' ),
53
  'desc_tip' => true,
54
- ),
55
- 'description' => array(
56
  'title' => __( 'Description', 'woocommerce-gateway-stripe' ),
57
  'type' => 'text',
58
  'description' => __( 'This controls the description which the user sees during checkout.', 'woocommerce-gateway-stripe' ),
59
  'default' => __( 'Pay with your credit card via Stripe.', 'woocommerce-gateway-stripe' ),
60
  'desc_tip' => true,
61
- ),
62
- 'webhook' => array(
63
- 'title' => __( 'Webhook Endpoints', 'woocommerce-gateway-stripe' ),
64
- 'type' => 'title',
65
- /* translators: webhook URL */
66
- 'description' => $this->display_admin_settings_webhook_description(),
67
- ),
68
- 'api_credentials' => array(
69
  'title' => __( 'Stripe Account Keys', 'woocommerce-gateway-stripe' ),
70
  'type' => 'title',
71
- 'description' => $api_credentials_text
72
- ),
73
- 'testmode' => array(
74
  'title' => __( 'Test mode', 'woocommerce-gateway-stripe' ),
75
  'label' => __( 'Enable Test Mode', 'woocommerce-gateway-stripe' ),
76
  'type' => 'checkbox',
77
  'description' => __( 'Place the payment gateway in test mode using test API keys.', 'woocommerce-gateway-stripe' ),
78
  'default' => 'yes',
79
  'desc_tip' => true,
80
- ),
81
- 'test_publishable_key' => array(
82
  'title' => __( 'Test Publishable Key', 'woocommerce-gateway-stripe' ),
83
  'type' => 'text',
84
  'description' => __( 'Get your API keys from your stripe account. Invalid values will be rejected. Only values starting with "pk_test_" will be saved.', 'woocommerce-gateway-stripe' ),
85
  'default' => '',
86
  'desc_tip' => true,
87
- ),
88
- 'test_secret_key' => array(
89
  'title' => __( 'Test Secret Key', 'woocommerce-gateway-stripe' ),
90
  'type' => 'password',
91
  'description' => __( 'Get your API keys from your stripe account. Invalid values will be rejected. Only values starting with "sk_test_" or "rk_test_" will be saved.', 'woocommerce-gateway-stripe' ),
92
  'default' => '',
93
  'desc_tip' => true,
94
- ),
95
- 'test_webhook_secret' => array(
96
- 'title' => __( 'Test Webhook Secret', 'woocommerce-gateway-stripe' ),
97
- 'type' => 'password',
98
- 'description' => __( 'Get your webhook signing secret from the webhooks section in your stripe account.', 'woocommerce-gateway-stripe' ),
99
- 'default' => '',
100
- 'desc_tip' => true,
101
- ),
102
- 'publishable_key' => array(
103
  'title' => __( 'Live Publishable Key', 'woocommerce-gateway-stripe' ),
104
  'type' => 'text',
105
  'description' => __( 'Get your API keys from your stripe account. Invalid values will be rejected. Only values starting with "pk_live_" will be saved.', 'woocommerce-gateway-stripe' ),
106
  'default' => '',
107
  'desc_tip' => true,
108
- ),
109
- 'secret_key' => array(
110
  'title' => __( 'Live Secret Key', 'woocommerce-gateway-stripe' ),
111
  'type' => 'password',
112
  'description' => __( 'Get your API keys from your stripe account. Invalid values will be rejected. Only values starting with "sk_live_" or "rk_live_" will be saved.', 'woocommerce-gateway-stripe' ),
113
  'default' => '',
114
  'desc_tip' => true,
115
- ),
116
- 'webhook_secret' => array(
 
 
 
 
 
 
 
 
 
 
 
 
117
  'title' => __( 'Webhook Secret', 'woocommerce-gateway-stripe' ),
118
  'type' => 'password',
119
  'description' => __( 'Get your webhook signing secret from the webhooks section in your stripe account.', 'woocommerce-gateway-stripe' ),
120
  'default' => '',
121
  'desc_tip' => true,
122
- ),
123
- 'inline_cc_form' => array(
124
  'title' => __( 'Inline Credit Card Form', 'woocommerce-gateway-stripe' ),
125
  'type' => 'checkbox',
126
  'description' => __( 'Choose the style you want to show for your credit card form. When unchecked, the credit card form will display separate credit card number field, expiry date field and cvc field.', 'woocommerce-gateway-stripe' ),
127
  'default' => 'no',
128
  'desc_tip' => true,
129
- ),
130
- 'statement_descriptor' => array(
131
  'title' => __( 'Statement Descriptor', 'woocommerce-gateway-stripe' ),
132
  'type' => 'text',
133
  'description' => __( 'Statement descriptors are limited to 22 characters, cannot use the special characters >, <, ", \, \', *, /, (, ), {, }, and must not consist solely of numbers. This will appear on your customer\'s statement in capital letters.', 'woocommerce-gateway-stripe' ),
134
  'default' => '',
135
  'desc_tip' => true,
136
- ),
137
- 'capture' => array(
138
  'title' => __( 'Capture', 'woocommerce-gateway-stripe' ),
139
  'label' => __( 'Capture charge immediately', 'woocommerce-gateway-stripe' ),
140
  'type' => 'checkbox',
141
  'description' => __( 'Whether or not to immediately capture the charge. When unchecked, the charge issues an authorization and will need to be captured later. Uncaptured charges expire in 7 days.', 'woocommerce-gateway-stripe' ),
142
  'default' => 'yes',
143
  'desc_tip' => true,
144
- ),
145
- 'payment_request' => array(
146
  'title' => __( 'Payment Request Buttons', 'woocommerce-gateway-stripe' ),
147
  'label' => sprintf(
148
  /* translators: 1) br tag 2) Stripe anchor tag 3) Apple anchor tag 4) Stripe dashboard opening anchor tag 5) Stripe dashboard closing anchor tag */
@@ -157,78 +157,78 @@ return apply_filters(
157
  'description' => __( 'If enabled, users will be able to pay using Apple Pay or Chrome Payment Request if supported by the browser.', 'woocommerce-gateway-stripe' ),
158
  'default' => 'yes',
159
  'desc_tip' => true,
160
- ),
161
- 'payment_request_button_type' => array(
162
  'title' => __( 'Payment Request Button Type', 'woocommerce-gateway-stripe' ),
163
  'label' => __( 'Button Type', 'woocommerce-gateway-stripe' ),
164
  'type' => 'select',
165
  'description' => __( 'Select the button type you would like to show.', 'woocommerce-gateway-stripe' ),
166
  'default' => 'buy',
167
  'desc_tip' => true,
168
- 'options' => array(
169
  'default' => __( 'Default', 'woocommerce-gateway-stripe' ),
170
  'buy' => __( 'Buy', 'woocommerce-gateway-stripe' ),
171
  'donate' => __( 'Donate', 'woocommerce-gateway-stripe' ),
172
  'branded' => __( 'Branded', 'woocommerce-gateway-stripe' ),
173
  'custom' => __( 'Custom', 'woocommerce-gateway-stripe' ),
174
- ),
175
- ),
176
- 'payment_request_button_theme' => array(
177
  'title' => __( 'Payment Request Button Theme', 'woocommerce-gateway-stripe' ),
178
  'label' => __( 'Button Theme', 'woocommerce-gateway-stripe' ),
179
  'type' => 'select',
180
  'description' => __( 'Select the button theme you would like to show.', 'woocommerce-gateway-stripe' ),
181
  'default' => 'dark',
182
  'desc_tip' => true,
183
- 'options' => array(
184
  'dark' => __( 'Dark', 'woocommerce-gateway-stripe' ),
185
  'light' => __( 'Light', 'woocommerce-gateway-stripe' ),
186
  'light-outline' => __( 'Light-Outline', 'woocommerce-gateway-stripe' ),
187
- ),
188
- ),
189
- 'payment_request_button_height' => array(
190
  'title' => __( 'Payment Request Button Height', 'woocommerce-gateway-stripe' ),
191
  'label' => __( 'Button Height', 'woocommerce-gateway-stripe' ),
192
  'type' => 'text',
193
  'description' => __( 'Enter the height you would like the button to be in pixels. Width will always be 100%.', 'woocommerce-gateway-stripe' ),
194
  'default' => '44',
195
  'desc_tip' => true,
196
- ),
197
- 'payment_request_button_label' => array(
198
  'title' => __( 'Payment Request Button Label', 'woocommerce-gateway-stripe' ),
199
  'label' => __( 'Button Label', 'woocommerce-gateway-stripe' ),
200
  'type' => 'text',
201
  'description' => __( 'Enter the custom text you would like the button to have.', 'woocommerce-gateway-stripe' ),
202
  'default' => __( 'Buy now', 'woocommerce-gateway-stripe' ),
203
  'desc_tip' => true,
204
- ),
205
- 'payment_request_button_branded_type' => array(
206
  'title' => __( 'Payment Request Branded Button Label Format', 'woocommerce-gateway-stripe' ),
207
  'label' => __( 'Branded Button Label Format', 'woocommerce-gateway-stripe' ),
208
  'type' => 'select',
209
  'description' => __( 'Select the branded button label format.', 'woocommerce-gateway-stripe' ),
210
  'default' => 'long',
211
  'desc_tip' => true,
212
- 'options' => array(
213
  'short' => __( 'Logo only', 'woocommerce-gateway-stripe' ),
214
  'long' => __( 'Text and logo', 'woocommerce-gateway-stripe' ),
215
- ),
216
- ),
217
- 'saved_cards' => array(
218
  'title' => __( 'Saved Cards', 'woocommerce-gateway-stripe' ),
219
  'label' => __( 'Enable Payment via Saved Cards', 'woocommerce-gateway-stripe' ),
220
  'type' => 'checkbox',
221
  'description' => __( 'If enabled, users will be able to pay with a saved card during checkout. Card details are saved on Stripe servers, not on your store.', 'woocommerce-gateway-stripe' ),
222
  'default' => 'yes',
223
  'desc_tip' => true,
224
- ),
225
- 'logging' => array(
226
  'title' => __( 'Logging', 'woocommerce-gateway-stripe' ),
227
  'label' => __( 'Log debug messages', 'woocommerce-gateway-stripe' ),
228
  'type' => 'checkbox',
229
  'description' => __( 'Save debug messages to the WooCommerce System Status log.', 'woocommerce-gateway-stripe' ),
230
  'default' => 'no',
231
  'desc_tip' => true,
232
- ),
233
- )
234
  );
5
 
6
  if ( woocommerce_gateway_stripe()->connect->is_connected() ) {
7
  $reset_link = add_query_arg(
8
+ [
9
  '_wpnonce' => wp_create_nonce( 'reset_stripe_api_credentials' ),
10
  'reset_stripe_api_credentials' => true,
11
+ ],
12
  admin_url( 'admin.php?page=wc-settings&tab=checkout&section=stripe' )
13
  );
14
 
15
  $api_credentials_text = sprintf(
16
+ /* translators: %1, %2, %3, and %4 are all HTML markup tags */
17
  __( '%1$sClear all Stripe account keys.%2$s %3$sThis will disable any connection to Stripe.%4$s', 'woocommerce-gateway-stripe' ),
18
  '<a id="wc_stripe_connect_button" href="' . $reset_link . '" class="button button-secondary">',
19
  '</a>',
25
 
26
  if ( ! is_wp_error( $oauth_url ) ) {
27
  $api_credentials_text = sprintf(
28
+ /* translators: %1, %2 and %3 are all HTML markup tags */
29
  __( '%1$sSetup or link an existing Stripe account.%2$s By clicking this button you agree to the %3$sTerms of Service%2$s. Or, manually enter Stripe account keys below.', 'woocommerce-gateway-stripe' ),
30
  '<a id="wc_stripe_connect_button" href="' . $oauth_url . '" class="button button-primary">',
31
  '</a>',
32
  '<a href="https://wordpress.com/tos">'
 
33
  );
34
  } else {
35
  $api_credentials_text = __( 'Manually enter Stripe keys below.', 'woocommerce-gateway-stripe' );
38
 
39
  return apply_filters(
40
  'wc_stripe_settings',
41
+ [
42
+ 'enabled' => [
43
  'title' => __( 'Enable/Disable', 'woocommerce-gateway-stripe' ),
44
  'label' => __( 'Enable Stripe', 'woocommerce-gateway-stripe' ),
45
  'type' => 'checkbox',
46
  'description' => '',
47
  'default' => 'no',
48
+ ],
49
+ 'title' => [
50
  'title' => __( 'Title', 'woocommerce-gateway-stripe' ),
51
  'type' => 'text',
52
  'description' => __( 'This controls the title which the user sees during checkout.', 'woocommerce-gateway-stripe' ),
53
  'default' => __( 'Credit Card (Stripe)', 'woocommerce-gateway-stripe' ),
54
  'desc_tip' => true,
55
+ ],
56
+ 'description' => [
57
  'title' => __( 'Description', 'woocommerce-gateway-stripe' ),
58
  'type' => 'text',
59
  'description' => __( 'This controls the description which the user sees during checkout.', 'woocommerce-gateway-stripe' ),
60
  'default' => __( 'Pay with your credit card via Stripe.', 'woocommerce-gateway-stripe' ),
61
  'desc_tip' => true,
62
+ ],
63
+ 'api_credentials' => [
 
 
 
 
 
 
64
  'title' => __( 'Stripe Account Keys', 'woocommerce-gateway-stripe' ),
65
  'type' => 'title',
66
+ 'description' => $api_credentials_text,
67
+ ],
68
+ 'testmode' => [
69
  'title' => __( 'Test mode', 'woocommerce-gateway-stripe' ),
70
  'label' => __( 'Enable Test Mode', 'woocommerce-gateway-stripe' ),
71
  'type' => 'checkbox',
72
  'description' => __( 'Place the payment gateway in test mode using test API keys.', 'woocommerce-gateway-stripe' ),
73
  'default' => 'yes',
74
  'desc_tip' => true,
75
+ ],
76
+ 'test_publishable_key' => [
77
  'title' => __( 'Test Publishable Key', 'woocommerce-gateway-stripe' ),
78
  'type' => 'text',
79
  'description' => __( 'Get your API keys from your stripe account. Invalid values will be rejected. Only values starting with "pk_test_" will be saved.', 'woocommerce-gateway-stripe' ),
80
  'default' => '',
81
  'desc_tip' => true,
82
+ ],
83
+ 'test_secret_key' => [
84
  'title' => __( 'Test Secret Key', 'woocommerce-gateway-stripe' ),
85
  'type' => 'password',
86
  'description' => __( 'Get your API keys from your stripe account. Invalid values will be rejected. Only values starting with "sk_test_" or "rk_test_" will be saved.', 'woocommerce-gateway-stripe' ),
87
  'default' => '',
88
  'desc_tip' => true,
89
+ ],
90
+ 'publishable_key' => [
 
 
 
 
 
 
 
91
  'title' => __( 'Live Publishable Key', 'woocommerce-gateway-stripe' ),
92
  'type' => 'text',
93
  'description' => __( 'Get your API keys from your stripe account. Invalid values will be rejected. Only values starting with "pk_live_" will be saved.', 'woocommerce-gateway-stripe' ),
94
  'default' => '',
95
  'desc_tip' => true,
96
+ ],
97
+ 'secret_key' => [
98
  'title' => __( 'Live Secret Key', 'woocommerce-gateway-stripe' ),
99
  'type' => 'password',
100
  'description' => __( 'Get your API keys from your stripe account. Invalid values will be rejected. Only values starting with "sk_live_" or "rk_live_" will be saved.', 'woocommerce-gateway-stripe' ),
101
  'default' => '',
102
  'desc_tip' => true,
103
+ ],
104
+ 'webhook' => [
105
+ 'title' => __( 'Webhook Endpoints', 'woocommerce-gateway-stripe' ),
106
+ 'type' => 'title',
107
+ 'description' => $this->display_admin_settings_webhook_description(),
108
+ ],
109
+ 'test_webhook_secret' => [
110
+ 'title' => __( 'Test Webhook Secret', 'woocommerce-gateway-stripe' ),
111
+ 'type' => 'password',
112
+ 'description' => __( 'Get your webhook signing secret from the webhooks section in your stripe account.', 'woocommerce-gateway-stripe' ),
113
+ 'default' => '',
114
+ 'desc_tip' => true,
115
+ ],
116
+ 'webhook_secret' => [
117
  'title' => __( 'Webhook Secret', 'woocommerce-gateway-stripe' ),
118
  'type' => 'password',
119
  'description' => __( 'Get your webhook signing secret from the webhooks section in your stripe account.', 'woocommerce-gateway-stripe' ),
120
  'default' => '',
121
  'desc_tip' => true,
122
+ ],
123
+ 'inline_cc_form' => [
124
  'title' => __( 'Inline Credit Card Form', 'woocommerce-gateway-stripe' ),
125
  'type' => 'checkbox',
126
  'description' => __( 'Choose the style you want to show for your credit card form. When unchecked, the credit card form will display separate credit card number field, expiry date field and cvc field.', 'woocommerce-gateway-stripe' ),
127
  'default' => 'no',
128
  'desc_tip' => true,
129
+ ],
130
+ 'statement_descriptor' => [
131
  'title' => __( 'Statement Descriptor', 'woocommerce-gateway-stripe' ),
132
  'type' => 'text',
133
  'description' => __( 'Statement descriptors are limited to 22 characters, cannot use the special characters >, <, ", \, \', *, /, (, ), {, }, and must not consist solely of numbers. This will appear on your customer\'s statement in capital letters.', 'woocommerce-gateway-stripe' ),
134
  'default' => '',
135
  'desc_tip' => true,
136
+ ],
137
+ 'capture' => [
138
  'title' => __( 'Capture', 'woocommerce-gateway-stripe' ),
139
  'label' => __( 'Capture charge immediately', 'woocommerce-gateway-stripe' ),
140
  'type' => 'checkbox',
141
  'description' => __( 'Whether or not to immediately capture the charge. When unchecked, the charge issues an authorization and will need to be captured later. Uncaptured charges expire in 7 days.', 'woocommerce-gateway-stripe' ),
142
  'default' => 'yes',
143
  'desc_tip' => true,
144
+ ],
145
+ 'payment_request' => [
146
  'title' => __( 'Payment Request Buttons', 'woocommerce-gateway-stripe' ),
147
  'label' => sprintf(
148
  /* translators: 1) br tag 2) Stripe anchor tag 3) Apple anchor tag 4) Stripe dashboard opening anchor tag 5) Stripe dashboard closing anchor tag */
157
  'description' => __( 'If enabled, users will be able to pay using Apple Pay or Chrome Payment Request if supported by the browser.', 'woocommerce-gateway-stripe' ),
158
  'default' => 'yes',
159
  'desc_tip' => true,
160
+ ],
161
+ 'payment_request_button_type' => [
162
  'title' => __( 'Payment Request Button Type', 'woocommerce-gateway-stripe' ),
163
  'label' => __( 'Button Type', 'woocommerce-gateway-stripe' ),
164
  'type' => 'select',
165
  'description' => __( 'Select the button type you would like to show.', 'woocommerce-gateway-stripe' ),
166
  'default' => 'buy',
167
  'desc_tip' => true,
168
+ 'options' => [
169
  'default' => __( 'Default', 'woocommerce-gateway-stripe' ),
170
  'buy' => __( 'Buy', 'woocommerce-gateway-stripe' ),
171
  'donate' => __( 'Donate', 'woocommerce-gateway-stripe' ),
172
  'branded' => __( 'Branded', 'woocommerce-gateway-stripe' ),
173
  'custom' => __( 'Custom', 'woocommerce-gateway-stripe' ),
174
+ ],
175
+ ],
176
+ 'payment_request_button_theme' => [
177
  'title' => __( 'Payment Request Button Theme', 'woocommerce-gateway-stripe' ),
178
  'label' => __( 'Button Theme', 'woocommerce-gateway-stripe' ),
179
  'type' => 'select',
180
  'description' => __( 'Select the button theme you would like to show.', 'woocommerce-gateway-stripe' ),
181
  'default' => 'dark',
182
  'desc_tip' => true,
183
+ 'options' => [
184
  'dark' => __( 'Dark', 'woocommerce-gateway-stripe' ),
185
  'light' => __( 'Light', 'woocommerce-gateway-stripe' ),
186
  'light-outline' => __( 'Light-Outline', 'woocommerce-gateway-stripe' ),
187
+ ],
188
+ ],
189
+ 'payment_request_button_height' => [
190
  'title' => __( 'Payment Request Button Height', 'woocommerce-gateway-stripe' ),
191
  'label' => __( 'Button Height', 'woocommerce-gateway-stripe' ),
192
  'type' => 'text',
193
  'description' => __( 'Enter the height you would like the button to be in pixels. Width will always be 100%.', 'woocommerce-gateway-stripe' ),
194
  'default' => '44',
195
  'desc_tip' => true,
196
+ ],
197
+ 'payment_request_button_label' => [
198
  'title' => __( 'Payment Request Button Label', 'woocommerce-gateway-stripe' ),
199
  'label' => __( 'Button Label', 'woocommerce-gateway-stripe' ),
200
  'type' => 'text',
201
  'description' => __( 'Enter the custom text you would like the button to have.', 'woocommerce-gateway-stripe' ),
202
  'default' => __( 'Buy now', 'woocommerce-gateway-stripe' ),
203
  'desc_tip' => true,
204
+ ],
205
+ 'payment_request_button_branded_type' => [
206
  'title' => __( 'Payment Request Branded Button Label Format', 'woocommerce-gateway-stripe' ),
207
  'label' => __( 'Branded Button Label Format', 'woocommerce-gateway-stripe' ),
208
  'type' => 'select',
209
  'description' => __( 'Select the branded button label format.', 'woocommerce-gateway-stripe' ),
210
  'default' => 'long',
211
  'desc_tip' => true,
212
+ 'options' => [
213
  'short' => __( 'Logo only', 'woocommerce-gateway-stripe' ),
214
  'long' => __( 'Text and logo', 'woocommerce-gateway-stripe' ),
215
+ ],
216
+ ],
217
+ 'saved_cards' => [
218
  'title' => __( 'Saved Cards', 'woocommerce-gateway-stripe' ),
219
  'label' => __( 'Enable Payment via Saved Cards', 'woocommerce-gateway-stripe' ),
220
  'type' => 'checkbox',
221
  'description' => __( 'If enabled, users will be able to pay with a saved card during checkout. Card details are saved on Stripe servers, not on your store.', 'woocommerce-gateway-stripe' ),
222
  'default' => 'yes',
223
  'desc_tip' => true,
224
+ ],
225
+ 'logging' => [
226
  'title' => __( 'Logging', 'woocommerce-gateway-stripe' ),
227
  'label' => __( 'Log debug messages', 'woocommerce-gateway-stripe' ),
228
  'type' => 'checkbox',
229
  'description' => __( 'Save debug messages to the WooCommerce System Status log.', 'woocommerce-gateway-stripe' ),
230
  'default' => 'no',
231
  'desc_tip' => true,
232
+ ],
233
+ ]
234
  );
includes/admin/stripe-sofort-settings.php CHANGED
@@ -5,45 +5,45 @@ if ( ! defined( 'ABSPATH' ) ) {
5
 
6
  return apply_filters(
7
  'wc_stripe_sofort_settings',
8
- array(
9
- 'geo_target' => array(
10
  'description' => __( 'Customer Geography: Germany, Austria', 'woocommerce-gateway-stripe' ),
11
  'type' => 'title',
12
- ),
13
- 'guide' => array(
14
  'description' => __( '<a href="https://stripe.com/payments/payment-methods-guide#sofort" target="_blank">Payment Method Guide</a>', 'woocommerce-gateway-stripe' ),
15
  'type' => 'title',
16
- ),
17
- 'activation' => array(
18
  'description' => __( 'Must be activated from your Stripe Dashboard Settings <a href="https://dashboard.stripe.com/account/payments/settings" target="_blank">here</a>', 'woocommerce-gateway-stripe' ),
19
  'type' => 'title',
20
- ),
21
- 'enabled' => array(
22
  'title' => __( 'Enable/Disable', 'woocommerce-gateway-stripe' ),
23
  'label' => __( 'Enable Stripe SOFORT', 'woocommerce-gateway-stripe' ),
24
  'type' => 'checkbox',
25
  'description' => '',
26
  'default' => 'no',
27
- ),
28
- 'title' => array(
29
  'title' => __( 'Title', 'woocommerce-gateway-stripe' ),
30
  'type' => 'text',
31
  'description' => __( 'This controls the title which the user sees during checkout.', 'woocommerce-gateway-stripe' ),
32
  'default' => __( 'SOFORT', 'woocommerce-gateway-stripe' ),
33
  'desc_tip' => true,
34
- ),
35
- 'description' => array(
36
  'title' => __( 'Description', 'woocommerce-gateway-stripe' ),
37
  'type' => 'text',
38
  'description' => __( 'This controls the description which the user sees during checkout.', 'woocommerce-gateway-stripe' ),
39
  'default' => __( 'You will be redirected to SOFORT.', 'woocommerce-gateway-stripe' ),
40
  'desc_tip' => true,
41
- ),
42
- 'webhook' => array(
43
  'title' => __( 'Webhook Endpoints', 'woocommerce-gateway-stripe' ),
44
  'type' => 'title',
45
  /* translators: webhook URL */
46
  'description' => $this->display_admin_settings_webhook_description(),
47
- ),
48
- )
49
  );
5
 
6
  return apply_filters(
7
  'wc_stripe_sofort_settings',
8
+ [
9
+ 'geo_target' => [
10
  'description' => __( 'Customer Geography: Germany, Austria', 'woocommerce-gateway-stripe' ),
11
  'type' => 'title',
12
+ ],
13
+ 'guide' => [
14
  'description' => __( '<a href="https://stripe.com/payments/payment-methods-guide#sofort" target="_blank">Payment Method Guide</a>', 'woocommerce-gateway-stripe' ),
15
  'type' => 'title',
16
+ ],
17
+ 'activation' => [
18
  'description' => __( 'Must be activated from your Stripe Dashboard Settings <a href="https://dashboard.stripe.com/account/payments/settings" target="_blank">here</a>', 'woocommerce-gateway-stripe' ),
19
  'type' => 'title',
20
+ ],
21
+ 'enabled' => [
22
  'title' => __( 'Enable/Disable', 'woocommerce-gateway-stripe' ),
23
  'label' => __( 'Enable Stripe SOFORT', 'woocommerce-gateway-stripe' ),
24
  'type' => 'checkbox',
25
  'description' => '',
26
  'default' => 'no',
27
+ ],
28
+ 'title' => [
29
  'title' => __( 'Title', 'woocommerce-gateway-stripe' ),
30
  'type' => 'text',
31
  'description' => __( 'This controls the title which the user sees during checkout.', 'woocommerce-gateway-stripe' ),
32
  'default' => __( 'SOFORT', 'woocommerce-gateway-stripe' ),
33
  'desc_tip' => true,
34
+ ],
35
+ 'description' => [
36
  'title' => __( 'Description', 'woocommerce-gateway-stripe' ),
37
  'type' => 'text',
38
  'description' => __( 'This controls the description which the user sees during checkout.', 'woocommerce-gateway-stripe' ),
39
  'default' => __( 'You will be redirected to SOFORT.', 'woocommerce-gateway-stripe' ),
40
  'desc_tip' => true,
41
+ ],
42
+ 'webhook' => [
43
  'title' => __( 'Webhook Endpoints', 'woocommerce-gateway-stripe' ),
44
  'type' => 'title',
45
  /* translators: webhook URL */
46
  'description' => $this->display_admin_settings_webhook_description(),
47
+ ],
48
+ ]
49
  );
includes/class-wc-gateway-stripe.php CHANGED
@@ -89,7 +89,7 @@ class WC_Gateway_Stripe extends WC_Stripe_Payment_Gateway {
89
  /* translators: 1) link to Stripe register page 2) link to Stripe api keys page */
90
  $this->method_description = __( 'Stripe works by adding payment fields on the checkout and then sending the details to Stripe for verification.', 'woocommerce-gateway-stripe' );
91
  $this->has_fields = true;
92
- $this->supports = array(
93
  'products',
94
  'refunds',
95
  'tokenization',
@@ -105,7 +105,7 @@ class WC_Gateway_Stripe extends WC_Stripe_Payment_Gateway {
105
  'subscription_payment_method_change_admin',
106
  'multiple_subscriptions',
107
  'pre-orders',
108
- );
109
 
110
  // Load the form fields.
111
  $this->init_form_fields();
@@ -129,26 +129,26 @@ class WC_Gateway_Stripe extends WC_Stripe_Payment_Gateway {
129
  WC_Stripe_API::set_secret_key( $this->secret_key );
130
 
131
  // Hooks.
132
- add_action( 'wp_enqueue_scripts', array( $this, 'payment_scripts' ) );
133
- add_action( 'admin_enqueue_scripts', array( $this, 'admin_scripts' ) );
134
- add_action( 'woocommerce_update_options_payment_gateways_' . $this->id, array( $this, 'process_admin_options' ) );
135
- add_action( 'woocommerce_admin_order_totals_after_total', array( $this, 'display_order_fee' ) );
136
- add_action( 'woocommerce_admin_order_totals_after_total', array( $this, 'display_order_payout' ), 20 );
137
- add_action( 'woocommerce_customer_save_address', array( $this, 'show_update_card_notice' ), 10, 2 );
138
- add_filter( 'woocommerce_available_payment_gateways', array( $this, 'prepare_order_pay_page' ) );
139
- add_action( 'woocommerce_account_view-order_endpoint', array( $this, 'check_intent_status_on_order_page' ), 1 );
140
- add_filter( 'woocommerce_payment_successful_result', array( $this, 'modify_successful_payment_result' ), 99999, 2 );
141
- add_action( 'set_logged_in_cookie', array( $this, 'set_cookie_on_current_request' ) );
142
- add_filter( 'woocommerce_get_checkout_payment_url', array( $this, 'get_checkout_payment_url' ), 10, 2 );
143
- add_filter( 'woocommerce_settings_api_sanitized_fields_' . $this->id, array( $this, 'settings_api_sanitized_fields' ) );
144
 
145
  // Note: display error is in the parent class.
146
- add_action( 'admin_notices', array( $this, 'display_errors' ), 9999 );
147
 
148
  if ( WC_Stripe_Helper::is_pre_orders_exists() ) {
149
  $this->pre_orders = new WC_Stripe_Pre_Orders_Compat();
150
 
151
- add_action( 'wc_pre_orders_process_pre_order_completion_payment_' . $this->id, array( $this->pre_orders, 'process_pre_order_release_payment' ) );
152
  }
153
  }
154
 
@@ -189,13 +189,13 @@ class WC_Gateway_Stripe extends WC_Stripe_Payment_Gateway {
189
  * @return string
190
  */
191
  public function get_icon() {
192
- $icons = $this->payment_icons();
193
  $supported_card_brands = WC_Stripe_Helper::get_supported_card_brands();
194
 
195
  $icons_str = '';
196
 
197
  foreach ( $supported_card_brands as $brand ) {
198
- $icons_str .= isset( $icons[ $brand ] ) ? $icons[ $brand ] : '';
199
  }
200
 
201
  return apply_filters( 'woocommerce_gateway_icon', $icons_str, $this->id );
@@ -205,7 +205,7 @@ class WC_Gateway_Stripe extends WC_Stripe_Payment_Gateway {
205
  * Initialise Gateway Settings Form Fields
206
  */
207
  public function init_form_fields() {
208
- $this->form_fields = require( dirname( __FILE__ ) . '/admin/stripe-settings.php' );
209
  }
210
 
211
  /**
@@ -235,8 +235,8 @@ class WC_Gateway_Stripe extends WC_Stripe_Payment_Gateway {
235
  }
236
 
237
  if ( is_add_payment_method_page() ) {
238
- $firstname = $user->user_firstname;
239
- $lastname = $user->user_lastname;
240
  }
241
 
242
  ob_start();
@@ -346,15 +346,15 @@ class WC_Gateway_Stripe extends WC_Stripe_Payment_Gateway {
346
 
347
  $suffix = defined( 'SCRIPT_DEBUG' ) && SCRIPT_DEBUG ? '' : '.min';
348
 
349
- wp_register_script( 'woocommerce_stripe_admin', plugins_url( 'assets/js/stripe-admin' . $suffix . '.js', WC_STRIPE_MAIN_FILE ), array(), WC_STRIPE_VERSION, true );
350
 
351
- $params = array(
352
  'time' => time(),
353
  'i18n_out_of_sync' => wp_kses(
354
  __( '<strong>Warning:</strong> your site\'s time does not match the time on your browser and may be incorrect. Some payment methods depend on webhook verification and verifying webhooks with a signing secret depends on your site\'s time being correct, so please check your site\'s time before setting a webhook secret. You may need to contact your site\'s hosting provider to correct the site\'s time.', 'woocommerce-gateway-stripe' ),
355
- array( 'strong' => array() )
356
  ),
357
- );
358
  wp_localize_script( 'woocommerce_stripe_admin', 'wc_stripe_settings_params', $params );
359
 
360
  wp_enqueue_script( 'woocommerce_stripe_admin' );
@@ -404,17 +404,17 @@ class WC_Gateway_Stripe extends WC_Stripe_Payment_Gateway {
404
 
405
  $suffix = defined( 'SCRIPT_DEBUG' ) && SCRIPT_DEBUG ? '' : '.min';
406
 
407
- wp_register_style( 'stripe_styles', plugins_url( 'assets/css/stripe-styles.css', WC_STRIPE_MAIN_FILE ), array(), WC_STRIPE_VERSION );
408
  wp_enqueue_style( 'stripe_styles' );
409
 
410
  wp_register_script( 'stripe', 'https://js.stripe.com/v3/', '', '3.0', true );
411
- wp_register_script( 'woocommerce_stripe', plugins_url( 'assets/js/stripe' . $suffix . '.js', WC_STRIPE_MAIN_FILE ), array( 'jquery-payment', 'stripe' ), WC_STRIPE_VERSION, true );
412
 
413
- $stripe_params = array(
414
  'key' => $this->publishable_key,
415
  'i18n_terms' => __( 'Please accept the terms and conditions first', 'woocommerce-gateway-stripe' ),
416
  'i18n_required_fields' => __( 'Please fill in required checkout fields first', 'woocommerce-gateway-stripe' ),
417
- );
418
 
419
  // If we're on the pay page we need to pass stripe.js the address of the order.
420
  if ( isset( $_GET['pay_for_order'] ) && 'true' === $_GET['pay_for_order'] ) { // wpcs: csrf ok.
@@ -435,11 +435,11 @@ class WC_Gateway_Stripe extends WC_Stripe_Payment_Gateway {
435
 
436
  $sepa_elements_options = apply_filters(
437
  'wc_stripe_sepa_elements_options',
438
- array(
439
- 'supportedCountries' => array( 'SEPA' ),
440
  'placeholderCountry' => WC()->countries->get_base_country(),
441
- 'style' => array( 'base' => array( 'fontSize' => '15px' ) ),
442
- )
443
  );
444
 
445
  $stripe_params['no_prepaid_card_msg'] = __( 'Sorry, we\'re not accepting prepaid cards at this time. Your credit card has not been charged. Please try with alternative payment method.', 'woocommerce-gateway-stripe' );
@@ -454,7 +454,7 @@ class WC_Gateway_Stripe extends WC_Stripe_Payment_Gateway {
454
  $stripe_params['ajaxurl'] = WC_AJAX::get_endpoint( '%%endpoint%%' );
455
  $stripe_params['stripe_nonce'] = wp_create_nonce( '_wc_stripe_nonce' );
456
  $stripe_params['statement_descriptor'] = $this->statement_descriptor;
457
- $stripe_params['elements_options'] = apply_filters( 'wc_stripe_elements_options', array() );
458
  $stripe_params['sepa_elements_options'] = $sepa_elements_options;
459
  $stripe_params['invalid_owner_name'] = __( 'Billing First Name and Last Name are required.', 'woocommerce-gateway-stripe' );
460
  $stripe_params['is_change_payment_page'] = isset( $_GET['change_payment_method'] ) ? 'yes' : 'no'; // wpcs: csrf ok.
@@ -540,11 +540,11 @@ class WC_Gateway_Stripe extends WC_Stripe_Payment_Gateway {
540
 
541
  if ( ! empty( $intent_secret ) ) {
542
  // `get_return_url()` must be called immediately before returning a value.
543
- return array(
544
  'result' => 'success',
545
  'redirect' => $this->get_return_url( $order ),
546
  'setup_intent_secret' => $intent_secret,
547
- );
548
  }
549
  }
550
 
@@ -554,10 +554,10 @@ class WC_Gateway_Stripe extends WC_Stripe_Payment_Gateway {
554
  $order->payment_complete();
555
 
556
  // Return thank you page redirect.
557
- return array(
558
  'result' => 'success',
559
  'redirect' => $this->get_return_url( $order ),
560
- );
561
  }
562
 
563
  /**
@@ -650,10 +650,10 @@ class WC_Gateway_Stripe extends WC_Stripe_Payment_Gateway {
650
  if ( is_wc_endpoint_url( 'order-pay' ) ) {
651
  $redirect_url = add_query_arg( 'wc-stripe-confirmation', 1, $order->get_checkout_payment_url( false ) );
652
 
653
- return array(
654
  'result' => 'success',
655
  'redirect' => $redirect_url,
656
- );
657
  } else {
658
  /**
659
  * This URL contains only a hash, which will be sent to `checkout.js` where it will be set like this:
@@ -661,11 +661,11 @@ class WC_Gateway_Stripe extends WC_Stripe_Payment_Gateway {
661
  * Once this redirect is sent to JS, the `onHashChange` function will execute `handleCardPayment`.
662
  */
663
 
664
- return array(
665
  'result' => 'success',
666
  'redirect' => $this->get_return_url( $order ),
667
  'payment_intent_secret' => $intent->client_secret,
668
- );
669
  }
670
  }
671
  }
@@ -682,10 +682,10 @@ class WC_Gateway_Stripe extends WC_Stripe_Payment_Gateway {
682
  $this->unlock_order_payment( $order );
683
 
684
  // Return thank you page redirect.
685
- return array(
686
  'result' => 'success',
687
  'redirect' => $this->get_return_url( $order ),
688
- );
689
 
690
  } catch ( WC_Stripe_Exception $e ) {
691
  wc_add_notice( $e->getLocalizedMessage(), 'error' );
@@ -696,10 +696,10 @@ class WC_Gateway_Stripe extends WC_Stripe_Payment_Gateway {
696
  /* translators: error message */
697
  $order->update_status( 'failed' );
698
 
699
- return array(
700
  'result' => 'fail',
701
  'redirect' => '',
702
- );
703
  }
704
  }
705
 
@@ -733,7 +733,7 @@ class WC_Gateway_Stripe extends WC_Stripe_Payment_Gateway {
733
  </td>
734
  <td width="1%"></td>
735
  <td class="total">
736
- -<?php echo wc_price( $fee, array( 'currency' => $currency ) ); // wpcs: xss ok. ?>
737
  </td>
738
  </tr>
739
 
@@ -770,7 +770,7 @@ class WC_Gateway_Stripe extends WC_Stripe_Payment_Gateway {
770
  </td>
771
  <td width="1%"></td>
772
  <td class="total">
773
- <?php echo wc_price( $net, array( 'currency' => $currency ) ); // wpcs: xss ok. ?>
774
  </td>
775
  </tr>
776
 
@@ -868,10 +868,10 @@ class WC_Gateway_Stripe extends WC_Stripe_Payment_Gateway {
868
  add_filter( 'woocommerce_checkout_show_terms', '__return_false' );
869
  add_filter( 'woocommerce_pay_order_button_html', '__return_false' );
870
  add_filter( 'woocommerce_available_payment_gateways', '__return_empty_array' );
871
- add_filter( 'woocommerce_no_available_payment_methods_message', array( $this, 'change_no_available_methods_message' ) );
872
- add_action( 'woocommerce_pay_order_after_submit', array( $this, 'render_payment_intent_inputs' ) );
873
 
874
- return array();
875
  }
876
 
877
  /**
@@ -900,16 +900,23 @@ class WC_Gateway_Stripe extends WC_Stripe_Payment_Gateway {
900
  $intent = $this->get_intent_from_order( $order );
901
 
902
  if ( ! $intent ) {
903
- throw new WC_Stripe_Exception( 'Payment Intent not found', __( 'Payment Intent not found for order #' . $order->get_id(), 'woocommerce-gateway-stripe' ) );
 
 
 
 
 
 
 
904
  }
905
 
906
  if ( 'requires_payment_method' === $intent->status && isset( $intent->last_payment_error )
907
- && 'authentication_required' === $intent->last_payment_error->code ) {
908
  $level3_data = $this->get_level3_data_from_order( $order );
909
  $intent = WC_Stripe_API::request_with_level3_data(
910
- array(
911
  'payment_method' => $intent->last_payment_error->source->id,
912
- ),
913
  'payment_intents/' . $intent->id . '/confirm',
914
  $level3_data,
915
  $order
@@ -940,12 +947,12 @@ class WC_Gateway_Stripe extends WC_Stripe_Payment_Gateway {
940
  }
941
 
942
  $verification_url = add_query_arg(
943
- array(
944
  'order' => $order->get_id(),
945
  'nonce' => wp_create_nonce( 'wc_stripe_confirm_pi' ),
946
  'redirect_to' => rawurlencode( $this->get_return_url( $order ) ),
947
  'is_pay_for_order' => true,
948
- ),
949
  WC_AJAX::get_endpoint( 'wc_stripe_verify_intent' )
950
  );
951
 
@@ -1007,24 +1014,24 @@ class WC_Gateway_Stripe extends WC_Stripe_Payment_Gateway {
1007
 
1008
  // Put the final thank you page redirect into the verification URL.
1009
  $verification_url = add_query_arg(
1010
- array(
1011
  'order' => $order_id,
1012
  'nonce' => wp_create_nonce( 'wc_stripe_confirm_pi' ),
1013
  'redirect_to' => rawurlencode( $result['redirect'] ),
1014
- ),
1015
  WC_AJAX::get_endpoint( 'wc_stripe_verify_intent' )
1016
  );
1017
 
1018
  if ( isset( $result['payment_intent_secret'] ) ) {
1019
  $redirect = sprintf( '#confirm-pi-%s:%s', $result['payment_intent_secret'], rawurlencode( $verification_url ) );
1020
- } else if ( isset( $result['setup_intent_secret'] ) ) {
1021
  $redirect = sprintf( '#confirm-si-%s:%s', $result['setup_intent_secret'], rawurlencode( $verification_url ) );
1022
  }
1023
 
1024
- return array(
1025
  'result' => 'success',
1026
  'redirect' => $redirect,
1027
- );
1028
  }
1029
 
1030
  /**
@@ -1058,7 +1065,7 @@ class WC_Gateway_Stripe extends WC_Stripe_Payment_Gateway {
1058
  clean_post_cache( $order->get_id() );
1059
  $order = wc_get_order( $order->get_id() );
1060
 
1061
- if ( ! $order->has_status( array( 'pending', 'failed' ) ) ) {
1062
  // If payment has already been completed, this function is redundant.
1063
  return;
1064
  }
@@ -1074,10 +1081,10 @@ class WC_Gateway_Stripe extends WC_Stripe_Payment_Gateway {
1074
  } else {
1075
  $order->payment_complete();
1076
  }
1077
- } else if ( 'succeeded' === $intent->status || 'requires_capture' === $intent->status ) {
1078
  // Proceed with the payment completion.
1079
  $this->handle_intent_verification_success( $order, $intent );
1080
- } else if ( 'requires_payment_method' === $intent->status ) {
1081
  // `requires_payment_method` means that SCA got denied for the current payment method.
1082
  $this->handle_intent_verification_failure( $order, $intent );
1083
  }
@@ -1131,7 +1138,7 @@ class WC_Gateway_Stripe extends WC_Stripe_Payment_Gateway {
1131
  /**
1132
  * Preserves the "wc-stripe-confirmation" URL parameter so the user can complete the SCA authentication after logging in.
1133
  *
1134
- * @param string $pay_url Current computed checkout URL for the given order.
1135
  * @param WC_Order $order Order object.
1136
  *
1137
  * @return string Checkout URL for the given order.
@@ -1220,7 +1227,7 @@ class WC_Gateway_Stripe extends WC_Stripe_Payment_Gateway {
1220
  public function settings_api_sanitized_fields( $settings ) {
1221
  if ( is_array( $settings ) ) {
1222
  if ( array_key_exists( 'statement_descriptor', $settings ) ) {
1223
- $settings['statement_descriptor'] = WC_Stripe_Helper::clean_statement_descriptor( $settings['statement_descriptor']);
1224
  }
1225
  }
1226
  return $settings;
89
  /* translators: 1) link to Stripe register page 2) link to Stripe api keys page */
90
  $this->method_description = __( 'Stripe works by adding payment fields on the checkout and then sending the details to Stripe for verification.', 'woocommerce-gateway-stripe' );
91
  $this->has_fields = true;
92
+ $this->supports = [
93
  'products',
94
  'refunds',
95
  'tokenization',
105
  'subscription_payment_method_change_admin',
106
  'multiple_subscriptions',
107
  'pre-orders',
108
+ ];
109
 
110
  // Load the form fields.
111
  $this->init_form_fields();
129
  WC_Stripe_API::set_secret_key( $this->secret_key );
130
 
131
  // Hooks.
132
+ add_action( 'wp_enqueue_scripts', [ $this, 'payment_scripts' ] );
133
+ add_action( 'admin_enqueue_scripts', [ $this, 'admin_scripts' ] );
134
+ add_action( 'woocommerce_update_options_payment_gateways_' . $this->id, [ $this, 'process_admin_options' ] );
135
+ add_action( 'woocommerce_admin_order_totals_after_total', [ $this, 'display_order_fee' ] );
136
+ add_action( 'woocommerce_admin_order_totals_after_total', [ $this, 'display_order_payout' ], 20 );
137
+ add_action( 'woocommerce_customer_save_address', [ $this, 'show_update_card_notice' ], 10, 2 );
138
+ add_filter( 'woocommerce_available_payment_gateways', [ $this, 'prepare_order_pay_page' ] );
139
+ add_action( 'woocommerce_account_view-order_endpoint', [ $this, 'check_intent_status_on_order_page' ], 1 );
140
+ add_filter( 'woocommerce_payment_successful_result', [ $this, 'modify_successful_payment_result' ], 99999, 2 );
141
+ add_action( 'set_logged_in_cookie', [ $this, 'set_cookie_on_current_request' ] );
142
+ add_filter( 'woocommerce_get_checkout_payment_url', [ $this, 'get_checkout_payment_url' ], 10, 2 );
143
+ add_filter( 'woocommerce_settings_api_sanitized_fields_' . $this->id, [ $this, 'settings_api_sanitized_fields' ] );
144
 
145
  // Note: display error is in the parent class.
146
+ add_action( 'admin_notices', [ $this, 'display_errors' ], 9999 );
147
 
148
  if ( WC_Stripe_Helper::is_pre_orders_exists() ) {
149
  $this->pre_orders = new WC_Stripe_Pre_Orders_Compat();
150
 
151
+ add_action( 'wc_pre_orders_process_pre_order_completion_payment_' . $this->id, [ $this->pre_orders, 'process_pre_order_release_payment' ] );
152
  }
153
  }
154
 
189
  * @return string
190
  */
191
  public function get_icon() {
192
+ $icons = $this->payment_icons();
193
  $supported_card_brands = WC_Stripe_Helper::get_supported_card_brands();
194
 
195
  $icons_str = '';
196
 
197
  foreach ( $supported_card_brands as $brand ) {
198
+ $icons_str .= isset( $icons[ $brand ] ) ? $icons[ $brand ] : '';
199
  }
200
 
201
  return apply_filters( 'woocommerce_gateway_icon', $icons_str, $this->id );
205
  * Initialise Gateway Settings Form Fields
206
  */
207
  public function init_form_fields() {
208
+ $this->form_fields = require dirname( __FILE__ ) . '/admin/stripe-settings.php';
209
  }
210
 
211
  /**
235
  }
236
 
237
  if ( is_add_payment_method_page() ) {
238
+ $firstname = $user->user_firstname;
239
+ $lastname = $user->user_lastname;
240
  }
241
 
242
  ob_start();
346
 
347
  $suffix = defined( 'SCRIPT_DEBUG' ) && SCRIPT_DEBUG ? '' : '.min';
348
 
349
+ wp_register_script( 'woocommerce_stripe_admin', plugins_url( 'assets/js/stripe-admin' . $suffix . '.js', WC_STRIPE_MAIN_FILE ), [], WC_STRIPE_VERSION, true );
350
 
351
+ $params = [
352
  'time' => time(),
353
  'i18n_out_of_sync' => wp_kses(
354
  __( '<strong>Warning:</strong> your site\'s time does not match the time on your browser and may be incorrect. Some payment methods depend on webhook verification and verifying webhooks with a signing secret depends on your site\'s time being correct, so please check your site\'s time before setting a webhook secret. You may need to contact your site\'s hosting provider to correct the site\'s time.', 'woocommerce-gateway-stripe' ),
355
+ [ 'strong' => [] ]
356
  ),
357
+ ];
358
  wp_localize_script( 'woocommerce_stripe_admin', 'wc_stripe_settings_params', $params );
359
 
360
  wp_enqueue_script( 'woocommerce_stripe_admin' );
404
 
405
  $suffix = defined( 'SCRIPT_DEBUG' ) && SCRIPT_DEBUG ? '' : '.min';
406
 
407
+ wp_register_style( 'stripe_styles', plugins_url( 'assets/css/stripe-styles.css', WC_STRIPE_MAIN_FILE ), [], WC_STRIPE_VERSION );
408
  wp_enqueue_style( 'stripe_styles' );
409
 
410
  wp_register_script( 'stripe', 'https://js.stripe.com/v3/', '', '3.0', true );
411
+ wp_register_script( 'woocommerce_stripe', plugins_url( 'assets/js/stripe' . $suffix . '.js', WC_STRIPE_MAIN_FILE ), [ 'jquery-payment', 'stripe' ], WC_STRIPE_VERSION, true );
412
 
413
+ $stripe_params = [
414
  'key' => $this->publishable_key,
415
  'i18n_terms' => __( 'Please accept the terms and conditions first', 'woocommerce-gateway-stripe' ),
416
  'i18n_required_fields' => __( 'Please fill in required checkout fields first', 'woocommerce-gateway-stripe' ),
417
+ ];
418
 
419
  // If we're on the pay page we need to pass stripe.js the address of the order.
420
  if ( isset( $_GET['pay_for_order'] ) && 'true' === $_GET['pay_for_order'] ) { // wpcs: csrf ok.
435
 
436
  $sepa_elements_options = apply_filters(
437
  'wc_stripe_sepa_elements_options',
438
+ [
439
+ 'supportedCountries' => [ 'SEPA' ],
440
  'placeholderCountry' => WC()->countries->get_base_country(),
441
+ 'style' => [ 'base' => [ 'fontSize' => '15px' ] ],
442
+ ]
443
  );
444
 
445
  $stripe_params['no_prepaid_card_msg'] = __( 'Sorry, we\'re not accepting prepaid cards at this time. Your credit card has not been charged. Please try with alternative payment method.', 'woocommerce-gateway-stripe' );
454
  $stripe_params['ajaxurl'] = WC_AJAX::get_endpoint( '%%endpoint%%' );
455
  $stripe_params['stripe_nonce'] = wp_create_nonce( '_wc_stripe_nonce' );
456
  $stripe_params['statement_descriptor'] = $this->statement_descriptor;
457
+ $stripe_params['elements_options'] = apply_filters( 'wc_stripe_elements_options', [] );
458
  $stripe_params['sepa_elements_options'] = $sepa_elements_options;
459
  $stripe_params['invalid_owner_name'] = __( 'Billing First Name and Last Name are required.', 'woocommerce-gateway-stripe' );
460
  $stripe_params['is_change_payment_page'] = isset( $_GET['change_payment_method'] ) ? 'yes' : 'no'; // wpcs: csrf ok.
540
 
541
  if ( ! empty( $intent_secret ) ) {
542
  // `get_return_url()` must be called immediately before returning a value.
543
+ return [
544
  'result' => 'success',
545
  'redirect' => $this->get_return_url( $order ),
546
  'setup_intent_secret' => $intent_secret,
547
+ ];
548
  }
549
  }
550
 
554
  $order->payment_complete();
555
 
556
  // Return thank you page redirect.
557
+ return [
558
  'result' => 'success',
559
  'redirect' => $this->get_return_url( $order ),
560
+ ];
561
  }
562
 
563
  /**
650
  if ( is_wc_endpoint_url( 'order-pay' ) ) {
651
  $redirect_url = add_query_arg( 'wc-stripe-confirmation', 1, $order->get_checkout_payment_url( false ) );
652
 
653
+ return [
654
  'result' => 'success',
655
  'redirect' => $redirect_url,
656
+ ];
657
  } else {
658
  /**
659
  * This URL contains only a hash, which will be sent to `checkout.js` where it will be set like this:
661
  * Once this redirect is sent to JS, the `onHashChange` function will execute `handleCardPayment`.
662
  */
663
 
664
+ return [
665
  'result' => 'success',
666
  'redirect' => $this->get_return_url( $order ),
667
  'payment_intent_secret' => $intent->client_secret,
668
+ ];
669
  }
670
  }
671
  }
682
  $this->unlock_order_payment( $order );
683
 
684
  // Return thank you page redirect.
685
+ return [
686
  'result' => 'success',
687
  'redirect' => $this->get_return_url( $order ),
688
+ ];
689
 
690
  } catch ( WC_Stripe_Exception $e ) {
691
  wc_add_notice( $e->getLocalizedMessage(), 'error' );
696
  /* translators: error message */
697
  $order->update_status( 'failed' );
698
 
699
+ return [
700
  'result' => 'fail',
701
  'redirect' => '',
702
+ ];
703
  }
704
  }
705
 
733
  </td>
734
  <td width="1%"></td>
735
  <td class="total">
736
+ -<?php echo wc_price( $fee, [ 'currency' => $currency ] ); // wpcs: xss ok. ?>
737
  </td>
738
  </tr>
739
 
770
  </td>
771
  <td width="1%"></td>
772
  <td class="total">
773
+ <?php echo wc_price( $net, [ 'currency' => $currency ] ); // wpcs: xss ok. ?>
774
  </td>
775
  </tr>
776
 
868
  add_filter( 'woocommerce_checkout_show_terms', '__return_false' );
869
  add_filter( 'woocommerce_pay_order_button_html', '__return_false' );
870
  add_filter( 'woocommerce_available_payment_gateways', '__return_empty_array' );
871
+ add_filter( 'woocommerce_no_available_payment_methods_message', [ $this, 'change_no_available_methods_message' ] );
872
+ add_action( 'woocommerce_pay_order_after_submit', [ $this, 'render_payment_intent_inputs' ] );
873
 
874
+ return [];
875
  }
876
 
877
  /**
900
  $intent = $this->get_intent_from_order( $order );
901
 
902
  if ( ! $intent ) {
903
+ throw new WC_Stripe_Exception(
904
+ 'Payment Intent not found',
905
+ sprintf(
906
+ /* translators: %s is the order Id */
907
+ __( 'Payment Intent not found for order #%s', 'woocommerce-gateway-stripe' ),
908
+ $order->get_id()
909
+ )
910
+ );
911
  }
912
 
913
  if ( 'requires_payment_method' === $intent->status && isset( $intent->last_payment_error )
914
+ && 'authentication_required' === $intent->last_payment_error->code ) {
915
  $level3_data = $this->get_level3_data_from_order( $order );
916
  $intent = WC_Stripe_API::request_with_level3_data(
917
+ [
918
  'payment_method' => $intent->last_payment_error->source->id,
919
+ ],
920
  'payment_intents/' . $intent->id . '/confirm',
921
  $level3_data,
922
  $order
947
  }
948
 
949
  $verification_url = add_query_arg(
950
+ [
951
  'order' => $order->get_id(),
952
  'nonce' => wp_create_nonce( 'wc_stripe_confirm_pi' ),
953
  'redirect_to' => rawurlencode( $this->get_return_url( $order ) ),
954
  'is_pay_for_order' => true,
955
+ ],
956
  WC_AJAX::get_endpoint( 'wc_stripe_verify_intent' )
957
  );
958
 
1014
 
1015
  // Put the final thank you page redirect into the verification URL.
1016
  $verification_url = add_query_arg(
1017
+ [
1018
  'order' => $order_id,
1019
  'nonce' => wp_create_nonce( 'wc_stripe_confirm_pi' ),
1020
  'redirect_to' => rawurlencode( $result['redirect'] ),
1021
+ ],
1022
  WC_AJAX::get_endpoint( 'wc_stripe_verify_intent' )
1023
  );
1024
 
1025
  if ( isset( $result['payment_intent_secret'] ) ) {
1026
  $redirect = sprintf( '#confirm-pi-%s:%s', $result['payment_intent_secret'], rawurlencode( $verification_url ) );
1027
+ } elseif ( isset( $result['setup_intent_secret'] ) ) {
1028
  $redirect = sprintf( '#confirm-si-%s:%s', $result['setup_intent_secret'], rawurlencode( $verification_url ) );
1029
  }
1030
 
1031
+ return [
1032
  'result' => 'success',
1033
  'redirect' => $redirect,
1034
+ ];
1035
  }
1036
 
1037
  /**
1065
  clean_post_cache( $order->get_id() );
1066
  $order = wc_get_order( $order->get_id() );
1067
 
1068
+ if ( ! $order->has_status( [ 'pending', 'failed' ] ) ) {
1069
  // If payment has already been completed, this function is redundant.
1070
  return;
1071
  }
1081
  } else {
1082
  $order->payment_complete();
1083
  }
1084
+ } elseif ( 'succeeded' === $intent->status || 'requires_capture' === $intent->status ) {
1085
  // Proceed with the payment completion.
1086
  $this->handle_intent_verification_success( $order, $intent );
1087
+ } elseif ( 'requires_payment_method' === $intent->status ) {
1088
  // `requires_payment_method` means that SCA got denied for the current payment method.
1089
  $this->handle_intent_verification_failure( $order, $intent );
1090
  }
1138
  /**
1139
  * Preserves the "wc-stripe-confirmation" URL parameter so the user can complete the SCA authentication after logging in.
1140
  *
1141
+ * @param string $pay_url Current computed checkout URL for the given order.
1142
  * @param WC_Order $order Order object.
1143
  *
1144
  * @return string Checkout URL for the given order.
1227
  public function settings_api_sanitized_fields( $settings ) {
1228
  if ( is_array( $settings ) ) {
1229
  if ( array_key_exists( 'statement_descriptor', $settings ) ) {
1230
+ $settings['statement_descriptor'] = WC_Stripe_Helper::clean_statement_descriptor( $settings['statement_descriptor'] );
1231
  }
1232
  }
1233
  return $settings;
includes/class-wc-stripe-api.php CHANGED
@@ -18,12 +18,14 @@ class WC_Stripe_API {
18
 
19
  /**
20
  * Secret API Key.
 
21
  * @var string
22
  */
23
  private static $secret_key = '';
24
 
25
  /**
26
  * Set secret API Key.
 
27
  * @param string $key
28
  */
29
  public static function set_secret_key( $secret_key ) {
@@ -32,6 +34,7 @@ class WC_Stripe_API {
32
 
33
  /**
34
  * Get secret key.
 
35
  * @return string
36
  */
37
  public static function get_secret_key() {
@@ -53,19 +56,19 @@ class WC_Stripe_API {
53
  * @version 4.0.0
54
  */
55
  public static function get_user_agent() {
56
- $app_info = array(
57
  'name' => 'WooCommerce Stripe Gateway',
58
  'version' => WC_STRIPE_VERSION,
59
  'url' => 'https://woocommerce.com/products/stripe/',
60
- );
61
 
62
- return array(
63
  'lang' => 'php',
64
  'lang_version' => phpversion(),
65
  'publisher' => 'woocommerce',
66
  'uname' => php_uname(),
67
  'application' => $app_info,
68
- );
69
  }
70
 
71
  /**
@@ -80,12 +83,12 @@ class WC_Stripe_API {
80
 
81
  return apply_filters(
82
  'woocommerce_stripe_request_headers',
83
- array(
84
  'Authorization' => 'Basic ' . base64_encode( self::get_secret_key() . ':' ),
85
  'Stripe-Version' => self::STRIPE_API_VERSION,
86
  'User-Agent' => $app_info['name'] . '/' . $app_info['version'] . ' (' . $app_info['url'] . ')',
87
- 'X-Stripe-Client-User-Agent' => json_encode( $user_agent ),
88
- )
89
  );
90
  }
91
 
@@ -94,10 +97,10 @@ class WC_Stripe_API {
94
  *
95
  * @since 3.1.0
96
  * @version 4.0.6
97
- * @param array $request
98
  * @param string $api
99
  * @param string $method
100
- * @param bool $with_headers To get the response with headers.
101
  * @return stdClass|array
102
  * @throws WC_Stripe_Exception
103
  */
@@ -117,22 +120,22 @@ class WC_Stripe_API {
117
 
118
  $response = wp_safe_remote_post(
119
  self::ENDPOINT . $api,
120
- array(
121
  'method' => $method,
122
  'headers' => $headers,
123
  'body' => apply_filters( 'woocommerce_stripe_request_body', $request, $api ),
124
  'timeout' => 70,
125
- )
126
  );
127
 
128
  if ( is_wp_error( $response ) || empty( $response['body'] ) ) {
129
  WC_Stripe_Logger::log(
130
  'Error Response: ' . print_r( $response, true ) . PHP_EOL . PHP_EOL . 'Failed request: ' . print_r(
131
- array(
132
  'api' => $api,
133
  'request' => $request,
134
  'idempotency_key' => $idempotency_key,
135
- ),
136
  true
137
  )
138
  );
@@ -141,10 +144,10 @@ class WC_Stripe_API {
141
  }
142
 
143
  if ( $with_headers ) {
144
- return array(
145
  'headers' => wp_remote_retrieve_headers( $response ),
146
  'body' => json_decode( $response['body'] ),
147
- );
148
  }
149
 
150
  return json_decode( $response['body'] );
@@ -162,11 +165,11 @@ class WC_Stripe_API {
162
 
163
  $response = wp_safe_remote_get(
164
  self::ENDPOINT . $api,
165
- array(
166
  'method' => 'GET',
167
  'headers' => self::get_headers(),
168
  'timeout' => 70,
169
- )
170
  );
171
 
172
  if ( is_wp_error( $response ) || empty( $response['body'] ) ) {
@@ -237,7 +240,7 @@ class WC_Stripe_API {
237
  // Set a transient so that future requests do not add level 3 data.
238
  // Transient is set to expire in 3 months, can be manually removed if needed.
239
  set_transient( 'wc_stripe_level3_not_allowed', true, 3 * MONTH_IN_SECONDS );
240
- } else if ( $is_level_3data_incorrect ) {
241
  // Log the issue so we could debug it.
242
  WC_Stripe_Logger::log(
243
  'Level3 data sum incorrect: ' . PHP_EOL
@@ -254,7 +257,7 @@ class WC_Stripe_API {
254
  // Make the request again without level 3 data.
255
  if ( $is_level3_param_not_allowed || $is_level_3data_incorrect ) {
256
  unset( $request['level3'] );
257
- return WC_Stripe_API::request(
258
  $request,
259
  $api
260
  );
18
 
19
  /**
20
  * Secret API Key.
21
+ *
22
  * @var string
23
  */
24
  private static $secret_key = '';
25
 
26
  /**
27
  * Set secret API Key.
28
+ *
29
  * @param string $key
30
  */
31
  public static function set_secret_key( $secret_key ) {
34
 
35
  /**
36
  * Get secret key.
37
+ *
38
  * @return string
39
  */
40
  public static function get_secret_key() {
56
  * @version 4.0.0
57
  */
58
  public static function get_user_agent() {
59
+ $app_info = [
60
  'name' => 'WooCommerce Stripe Gateway',
61
  'version' => WC_STRIPE_VERSION,
62
  'url' => 'https://woocommerce.com/products/stripe/',
63
+ ];
64
 
65
+ return [
66
  'lang' => 'php',
67
  'lang_version' => phpversion(),
68
  'publisher' => 'woocommerce',
69
  'uname' => php_uname(),
70
  'application' => $app_info,
71
+ ];
72
  }
73
 
74
  /**
83
 
84
  return apply_filters(
85
  'woocommerce_stripe_request_headers',
86
+ [
87
  'Authorization' => 'Basic ' . base64_encode( self::get_secret_key() . ':' ),
88
  'Stripe-Version' => self::STRIPE_API_VERSION,
89
  'User-Agent' => $app_info['name'] . '/' . $app_info['version'] . ' (' . $app_info['url'] . ')',
90
+ 'X-Stripe-Client-User-Agent' => wp_json_encode( $user_agent ),
91
+ ]
92
  );
93
  }
94
 
97
  *
98
  * @since 3.1.0
99
  * @version 4.0.6
100
+ * @param array $request
101
  * @param string $api
102
  * @param string $method
103
+ * @param bool $with_headers To get the response with headers.
104
  * @return stdClass|array
105
  * @throws WC_Stripe_Exception
106
  */
120
 
121
  $response = wp_safe_remote_post(
122
  self::ENDPOINT . $api,
123
+ [
124
  'method' => $method,
125
  'headers' => $headers,
126
  'body' => apply_filters( 'woocommerce_stripe_request_body', $request, $api ),
127
  'timeout' => 70,
128
+ ]
129
  );
130
 
131
  if ( is_wp_error( $response ) || empty( $response['body'] ) ) {
132
  WC_Stripe_Logger::log(
133
  'Error Response: ' . print_r( $response, true ) . PHP_EOL . PHP_EOL . 'Failed request: ' . print_r(
134
+ [
135
  'api' => $api,
136
  'request' => $request,
137
  'idempotency_key' => $idempotency_key,
138
+ ],
139
  true
140
  )
141
  );
144
  }
145
 
146
  if ( $with_headers ) {
147
+ return [
148
  'headers' => wp_remote_retrieve_headers( $response ),
149
  'body' => json_decode( $response['body'] ),
150
+ ];
151
  }
152
 
153
  return json_decode( $response['body'] );
165
 
166
  $response = wp_safe_remote_get(
167
  self::ENDPOINT . $api,
168
+ [
169
  'method' => 'GET',
170
  'headers' => self::get_headers(),
171
  'timeout' => 70,
172
+ ]
173
  );
174
 
175
  if ( is_wp_error( $response ) || empty( $response['body'] ) ) {
240
  // Set a transient so that future requests do not add level 3 data.
241
  // Transient is set to expire in 3 months, can be manually removed if needed.
242
  set_transient( 'wc_stripe_level3_not_allowed', true, 3 * MONTH_IN_SECONDS );
243
+ } elseif ( $is_level_3data_incorrect ) {
244
  // Log the issue so we could debug it.
245
  WC_Stripe_Logger::log(
246
  'Level3 data sum incorrect: ' . PHP_EOL
257
  // Make the request again without level 3 data.
258
  if ( $is_level3_param_not_allowed || $is_level_3data_incorrect ) {
259
  unset( $request['level3'] );
260
+ return self::request(
261
  $request,
262
  $api
263
  );
includes/class-wc-stripe-apple-pay-registration.php CHANGED
@@ -43,17 +43,17 @@ class WC_Stripe_Apple_Pay_Registration {
43
  public $apple_pay_verify_notice;
44
 
45
  public function __construct() {
46
- add_action( 'init', array( $this, 'add_domain_association_rewrite_rule' ) );
47
- add_action( 'admin_init', array( $this, 'verify_domain_on_domain_name_change' ) );
48
- add_action( 'admin_notices', array( $this, 'admin_notices' ) );
49
- add_filter( 'query_vars', array( $this, 'whitelist_domain_association_query_param' ), 10, 1 );
50
- add_action( 'parse_request', array( $this, 'parse_domain_association_request' ), 10, 1 );
51
 
52
- add_action( 'woocommerce_stripe_updated', array( $this, 'verify_domain_if_configured' ) );
53
- add_action( 'add_option_woocommerce_stripe_settings', array( $this, 'verify_domain_on_new_settings' ), 10, 2 );
54
- add_action( 'update_option_woocommerce_stripe_settings', array( $this, 'verify_domain_on_updated_settings' ), 10, 2 );
55
 
56
- $this->stripe_settings = get_option( 'woocommerce_stripe_settings', array() );
57
  $this->domain_name = isset( $_SERVER['HTTP_HOST'] ) ? $_SERVER['HTTP_HOST'] : str_replace( array( 'https://', 'http://' ), '', get_site_url() ); // @codingStandardsIgnoreLine
58
  $this->apple_pay_domain_set = 'yes' === $this->get_option( 'apple_pay_domain_set', 'no' );
59
  $this->apple_pay_verify_notice = '';
@@ -63,7 +63,7 @@ class WC_Stripe_Apple_Pay_Registration {
63
  * Gets the Stripe settings.
64
  *
65
  * @since 4.0.6
66
- * @param string $setting
67
  * @param string default
68
  * @return string $setting_value
69
  */
@@ -234,22 +234,22 @@ class WC_Stripe_Apple_Pay_Registration {
234
 
235
  $endpoint = 'https://api.stripe.com/v1/apple_pay/domains';
236
 
237
- $data = array(
238
  'domain_name' => $this->domain_name,
239
- );
240
 
241
- $headers = array(
242
  'User-Agent' => 'WooCommerce Stripe Apple Pay',
243
  'Authorization' => 'Bearer ' . $secret_key,
244
- );
245
 
246
  $response = wp_remote_post(
247
  $endpoint,
248
- array(
249
  'headers' => $headers,
250
  'body' => http_build_query( $data ),
251
  'timeout' => 30,
252
- )
253
  );
254
 
255
  if ( is_wp_error( $response ) ) {
@@ -339,7 +339,7 @@ class WC_Stripe_Apple_Pay_Registration {
339
  * @version 4.5.4
340
  */
341
  public function verify_domain_on_new_settings( $option, $settings ) {
342
- $this->verify_domain_on_updated_settings( array(), $settings );
343
  }
344
 
345
  /**
@@ -385,12 +385,12 @@ class WC_Stripe_Apple_Pay_Registration {
385
  * when setting screen is displayed. So if domain verification is not set,
386
  * something went wrong so lets notify user.
387
  */
388
- $allowed_html = array(
389
- 'a' => array(
390
- 'href' => array(),
391
- 'title' => array(),
392
- ),
393
- );
394
  $verification_failed_without_error = __( 'Apple Pay domain verification failed.', 'woocommerce-gateway-stripe' );
395
  $verification_failed_with_error = __( 'Apple Pay domain verification failed with the following error:', 'woocommerce-gateway-stripe' );
396
  $check_log_text = sprintf(
43
  public $apple_pay_verify_notice;
44
 
45
  public function __construct() {
46
+ add_action( 'init', [ $this, 'add_domain_association_rewrite_rule' ] );
47
+ add_action( 'admin_init', [ $this, 'verify_domain_on_domain_name_change' ] );
48
+ add_action( 'admin_notices', [ $this, 'admin_notices' ] );
49
+ add_filter( 'query_vars', [ $this, 'whitelist_domain_association_query_param' ], 10, 1 );
50
+ add_action( 'parse_request', [ $this, 'parse_domain_association_request' ], 10, 1 );
51
 
52
+ add_action( 'woocommerce_stripe_updated', [ $this, 'verify_domain_if_configured' ] );
53
+ add_action( 'add_option_woocommerce_stripe_settings', [ $this, 'verify_domain_on_new_settings' ], 10, 2 );
54
+ add_action( 'update_option_woocommerce_stripe_settings', [ $this, 'verify_domain_on_updated_settings' ], 10, 2 );
55
 
56
+ $this->stripe_settings = get_option( 'woocommerce_stripe_settings', [] );
57
  $this->domain_name = isset( $_SERVER['HTTP_HOST'] ) ? $_SERVER['HTTP_HOST'] : str_replace( array( 'https://', 'http://' ), '', get_site_url() ); // @codingStandardsIgnoreLine
58
  $this->apple_pay_domain_set = 'yes' === $this->get_option( 'apple_pay_domain_set', 'no' );
59
  $this->apple_pay_verify_notice = '';
63
  * Gets the Stripe settings.
64
  *
65
  * @since 4.0.6
66
+ * @param string $setting
67
  * @param string default
68
  * @return string $setting_value
69
  */
234
 
235
  $endpoint = 'https://api.stripe.com/v1/apple_pay/domains';
236
 
237
+ $data = [
238
  'domain_name' => $this->domain_name,
239
+ ];
240
 
241
+ $headers = [
242
  'User-Agent' => 'WooCommerce Stripe Apple Pay',
243
  'Authorization' => 'Bearer ' . $secret_key,
244
+ ];
245
 
246
  $response = wp_remote_post(
247
  $endpoint,
248
+ [
249
  'headers' => $headers,
250
  'body' => http_build_query( $data ),
251
  'timeout' => 30,
252
+ ]
253
  );
254
 
255
  if ( is_wp_error( $response ) ) {
339
  * @version 4.5.4
340
  */
341
  public function verify_domain_on_new_settings( $option, $settings ) {
342
+ $this->verify_domain_on_updated_settings( [], $settings );
343
  }
344
 
345
  /**
385
  * when setting screen is displayed. So if domain verification is not set,
386
  * something went wrong so lets notify user.
387
  */
388
+ $allowed_html = [
389
+ 'a' => [
390
+ 'href' => [],
391
+ 'title' => [],
392
+ ],
393
+ ];
394
  $verification_failed_without_error = __( 'Apple Pay domain verification failed.', 'woocommerce-gateway-stripe' );
395
  $verification_failed_with_error = __( 'Apple Pay domain verification failed with the following error:', 'woocommerce-gateway-stripe' );
396
  $check_log_text = sprintf(
includes/class-wc-stripe-customer.php CHANGED
@@ -12,24 +12,28 @@ class WC_Stripe_Customer {
12
 
13
  /**
14
  * Stripe customer ID
 
15
  * @var string
16
  */
17
  private $id = '';
18
 
19
  /**
20
  * WP User ID
 
21
  * @var integer
22
  */
23
  private $user_id = 0;
24
 
25
  /**
26
  * Data from API
 
27
  * @var array
28
  */
29
- private $customer_data = array();
30
 
31
  /**
32
  * Constructor
 
33
  * @param int $user_id The WP user ID
34
  */
35
  public function __construct( $user_id = 0 ) {
@@ -41,6 +45,7 @@ class WC_Stripe_Customer {
41
 
42
  /**
43
  * Get Stripe customer ID.
 
44
  * @return string
45
  */
46
  public function get_id() {
@@ -49,6 +54,7 @@ class WC_Stripe_Customer {
49
 
50
  /**
51
  * Set Stripe customer ID.
 
52
  * @param [type] $id [description]
53
  */
54
  public function set_id( $id ) {
@@ -64,6 +70,7 @@ class WC_Stripe_Customer {
64
 
65
  /**
66
  * User ID in WordPress.
 
67
  * @return int
68
  */
69
  public function get_user_id() {
@@ -72,6 +79,7 @@ class WC_Stripe_Customer {
72
 
73
  /**
74
  * Set User ID used by WordPress.
 
75
  * @param int $user_id
76
  */
77
  public function set_user_id( $user_id ) {
@@ -80,6 +88,7 @@ class WC_Stripe_Customer {
80
 
81
  /**
82
  * Get user object.
 
83
  * @return WP_User
84
  */
85
  protected function get_user() {
@@ -99,8 +108,8 @@ class WC_Stripe_Customer {
99
  * @param array $args Additional arguments (optional).
100
  * @return array
101
  */
102
- protected function generate_customer_request( $args = array() ) {
103
- $billing_email = isset( $_POST['billing_email'] ) ? filter_var( $_POST['billing_email'], FILTER_SANITIZE_EMAIL ) : '';
104
  $user = $this->get_user();
105
 
106
  if ( $user ) {
@@ -118,12 +127,12 @@ class WC_Stripe_Customer {
118
  }
119
 
120
  // translators: %1$s First name, %2$s Second name, %3$s Username.
121
- $description = sprintf( __( 'Name: %1$s %2$s, Username: %s', 'woocommerce-gateway-stripe' ), $billing_first_name, $billing_last_name, $user->user_login );
122
 
123
- $defaults = array(
124
  'email' => $user->user_email,
125
  'description' => $description,
126
- );
127
 
128
  $billing_full_name = trim( $billing_first_name . ' ' . $billing_last_name );
129
  if ( ! empty( $billing_full_name ) ) {
@@ -136,10 +145,10 @@ class WC_Stripe_Customer {
136
  // translators: %1$s First name, %2$s Second name.
137
  $description = sprintf( __( 'Name: %1$s %2$s, Guest', 'woocommerce-gateway-stripe' ), $billing_first_name, $billing_last_name );
138
 
139
- $defaults = array(
140
  'email' => $billing_email,
141
  'description' => $description,
142
- );
143
 
144
  $billing_full_name = trim( $billing_first_name . ' ' . $billing_last_name );
145
  if ( ! empty( $billing_full_name ) ) {
@@ -147,7 +156,7 @@ class WC_Stripe_Customer {
147
  }
148
  }
149
 
150
- $metadata = array();
151
  $defaults['metadata'] = apply_filters( 'wc_stripe_customer_metadata', $metadata, $user );
152
 
153
  return wp_parse_args( $args, $defaults );
@@ -155,10 +164,11 @@ class WC_Stripe_Customer {
155
 
156
  /**
157
  * Create a customer via API.
 
158
  * @param array $args
159
  * @return WP_Error|int
160
  */
161
- public function create_customer( $args = array() ) {
162
  $args = $this->generate_customer_request( $args );
163
  $response = WC_Stripe_API::request( apply_filters( 'wc_stripe_create_customer_args', $args ), 'customers' );
164
 
@@ -189,7 +199,7 @@ class WC_Stripe_Customer {
189
  *
190
  * @throws WC_Stripe_Exception
191
  */
192
- public function update_customer( $args = array(), $is_retry = false ) {
193
  if ( empty( $this->get_id() ) ) {
194
  throw new WC_Stripe_Exception( 'id_required_to_update_user', __( 'Attempting to update a Stripe customer without a customer ID.', 'woocommerce-gateway-stripe' ) );
195
  }
@@ -250,12 +260,14 @@ class WC_Stripe_Customer {
250
 
251
  /**
252
  * Add a source for this stripe customer.
 
253
  * @param string $source_id
254
  * @return WP_Error|int
255
  */
256
  public function add_source( $source_id ) {
257
  $response = $this->attach_source( $source_id );
258
- if ( is_wp_error( $response ) ) {
 
259
  return $response;
260
  }
261
 
@@ -319,9 +331,9 @@ class WC_Stripe_Customer {
319
  }
320
 
321
  $response = WC_Stripe_API::request(
322
- array(
323
  'source' => $source_id,
324
- ),
325
  'customers/' . $this->get_id() . '/sources'
326
  );
327
 
@@ -332,8 +344,8 @@ class WC_Stripe_Customer {
332
  if ( $this->is_no_such_customer_error( $response->error ) ) {
333
  $this->recreate_customer();
334
  return $this->attach_source( $source_id );
335
- } elseif( $this->is_source_already_attached_error( $response->error ) ) {
336
- return WC_Stripe_API::request( array(), 'sources/' . $source_id, 'GET' );
337
  } else {
338
  return $response;
339
  }
@@ -352,22 +364,22 @@ class WC_Stripe_Customer {
352
  */
353
  public function get_sources() {
354
  if ( ! $this->get_id() ) {
355
- return array();
356
  }
357
 
358
  $sources = get_transient( 'stripe_sources_' . $this->get_id() );
359
 
360
  if ( false === $sources ) {
361
  $response = WC_Stripe_API::request(
362
- array(
363
  'limit' => 100,
364
- ),
365
  'customers/' . $this->get_id() . '/sources',
366
  'GET'
367
  );
368
 
369
  if ( ! empty( $response->error ) ) {
370
- return array();
371
  }
372
 
373
  if ( is_array( $response->data ) ) {
@@ -377,11 +389,12 @@ class WC_Stripe_Customer {
377
  set_transient( 'stripe_sources_' . $this->get_id(), $sources, DAY_IN_SECONDS );
378
  }
379
 
380
- return empty( $sources ) ? array() : $sources;
381
  }
382
 
383
  /**
384
  * Delete a source from stripe.
 
385
  * @param string $source_id
386
  */
387
  public function delete_source( $source_id ) {
@@ -389,7 +402,7 @@ class WC_Stripe_Customer {
389
  return false;
390
  }
391
 
392
- $response = WC_Stripe_API::request( array(), 'customers/' . $this->get_id() . '/sources/' . sanitize_text_field( $source_id ), 'DELETE' );
393
 
394
  $this->clear_cache();
395
 
@@ -404,13 +417,14 @@ class WC_Stripe_Customer {
404
 
405
  /**
406
  * Set default source in Stripe
 
407
  * @param string $source_id
408
  */
409
  public function set_default_source( $source_id ) {
410
  $response = WC_Stripe_API::request(
411
- array(
412
  'default_source' => sanitize_text_field( $source_id ),
413
- ),
414
  'customers/' . $this->get_id(),
415
  'POST'
416
  );
@@ -432,7 +446,7 @@ class WC_Stripe_Customer {
432
  public function clear_cache() {
433
  delete_transient( 'stripe_sources_' . $this->get_id() );
434
  delete_transient( 'stripe_customer_' . $this->get_id() );
435
- $this->customer_data = array();
436
  }
437
 
438
  /**
12
 
13
  /**
14
  * Stripe customer ID
15
+ *
16
  * @var string
17
  */
18
  private $id = '';
19
 
20
  /**
21
  * WP User ID
22
+ *
23
  * @var integer
24
  */
25
  private $user_id = 0;
26
 
27
  /**
28
  * Data from API
29
+ *
30
  * @var array
31
  */
32
+ private $customer_data = [];
33
 
34
  /**
35
  * Constructor
36
+ *
37
  * @param int $user_id The WP user ID
38
  */
39
  public function __construct( $user_id = 0 ) {
45
 
46
  /**
47
  * Get Stripe customer ID.
48
+ *
49
  * @return string
50
  */
51
  public function get_id() {
54
 
55
  /**
56
  * Set Stripe customer ID.
57
+ *
58
  * @param [type] $id [description]
59
  */
60
  public function set_id( $id ) {
70
 
71
  /**
72
  * User ID in WordPress.
73
+ *
74
  * @return int
75
  */
76
  public function get_user_id() {
79
 
80
  /**
81
  * Set User ID used by WordPress.
82
+ *
83
  * @param int $user_id
84
  */
85
  public function set_user_id( $user_id ) {
88
 
89
  /**
90
  * Get user object.
91
+ *
92
  * @return WP_User
93
  */
94
  protected function get_user() {
108
  * @param array $args Additional arguments (optional).
109
  * @return array
110
  */
111
+ protected function generate_customer_request( $args = [] ) {
112
+ $billing_email = isset( $_POST['billing_email'] ) ? filter_var( wp_unslash( $_POST['billing_email'] ), FILTER_SANITIZE_EMAIL ) : '';
113
  $user = $this->get_user();
114
 
115
  if ( $user ) {
127
  }
128
 
129
  // translators: %1$s First name, %2$s Second name, %3$s Username.
130
+ $description = sprintf( __( 'Name: %1$s %2$s, Username: %3$s', 'woocommerce-gateway-stripe' ), $billing_first_name, $billing_last_name, $user->user_login );
131
 
132
+ $defaults = [
133
  'email' => $user->user_email,
134
  'description' => $description,
135
+ ];
136
 
137
  $billing_full_name = trim( $billing_first_name . ' ' . $billing_last_name );
138
  if ( ! empty( $billing_full_name ) ) {
145
  // translators: %1$s First name, %2$s Second name.
146
  $description = sprintf( __( 'Name: %1$s %2$s, Guest', 'woocommerce-gateway-stripe' ), $billing_first_name, $billing_last_name );
147
 
148
+ $defaults = [
149
  'email' => $billing_email,
150
  'description' => $description,
151
+ ];
152
 
153
  $billing_full_name = trim( $billing_first_name . ' ' . $billing_last_name );
154
  if ( ! empty( $billing_full_name ) ) {
156
  }
157
  }
158
 
159
+ $metadata = [];
160
  $defaults['metadata'] = apply_filters( 'wc_stripe_customer_metadata', $metadata, $user );
161
 
162
  return wp_parse_args( $args, $defaults );
164
 
165
  /**
166
  * Create a customer via API.
167
+ *
168
  * @param array $args
169
  * @return WP_Error|int
170
  */
171
+ public function create_customer( $args = [] ) {
172
  $args = $this->generate_customer_request( $args );
173
  $response = WC_Stripe_API::request( apply_filters( 'wc_stripe_create_customer_args', $args ), 'customers' );
174
 
199
  *
200
  * @throws WC_Stripe_Exception
201
  */
202
+ public function update_customer( $args = [], $is_retry = false ) {
203
  if ( empty( $this->get_id() ) ) {
204
  throw new WC_Stripe_Exception( 'id_required_to_update_user', __( 'Attempting to update a Stripe customer without a customer ID.', 'woocommerce-gateway-stripe' ) );
205
  }
260
 
261
  /**
262
  * Add a source for this stripe customer.
263
+ *
264
  * @param string $source_id
265
  * @return WP_Error|int
266
  */
267
  public function add_source( $source_id ) {
268
  $response = $this->attach_source( $source_id );
269
+
270
+ if ( ! empty( $response->error ) || is_wp_error( $response ) ) {
271
  return $response;
272
  }
273
 
331
  }
332
 
333
  $response = WC_Stripe_API::request(
334
+ [
335
  'source' => $source_id,
336
+ ],
337
  'customers/' . $this->get_id() . '/sources'
338
  );
339
 
344
  if ( $this->is_no_such_customer_error( $response->error ) ) {
345
  $this->recreate_customer();
346
  return $this->attach_source( $source_id );
347
+ } elseif ( $this->is_source_already_attached_error( $response->error ) ) {
348
+ return WC_Stripe_API::request( [], 'sources/' . $source_id, 'GET' );
349
  } else {
350
  return $response;
351
  }
364
  */
365
  public function get_sources() {
366
  if ( ! $this->get_id() ) {
367
+ return [];
368
  }
369
 
370
  $sources = get_transient( 'stripe_sources_' . $this->get_id() );
371
 
372
  if ( false === $sources ) {
373
  $response = WC_Stripe_API::request(
374
+ [
375
  'limit' => 100,
376
+ ],
377
  'customers/' . $this->get_id() . '/sources',
378
  'GET'
379
  );
380
 
381
  if ( ! empty( $response->error ) ) {
382
+ return [];
383
  }
384
 
385
  if ( is_array( $response->data ) ) {
389
  set_transient( 'stripe_sources_' . $this->get_id(), $sources, DAY_IN_SECONDS );
390
  }
391
 
392
+ return empty( $sources ) ? [] : $sources;
393
  }
394
 
395
  /**
396
  * Delete a source from stripe.
397
+ *
398
  * @param string $source_id
399
  */
400
  public function delete_source( $source_id ) {
402
  return false;
403
  }
404
 
405
+ $response = WC_Stripe_API::request( [], 'customers/' . $this->get_id() . '/sources/' . sanitize_text_field( $source_id ), 'DELETE' );
406
 
407
  $this->clear_cache();
408
 
417
 
418
  /**
419
  * Set default source in Stripe
420
+ *
421
  * @param string $source_id
422
  */
423
  public function set_default_source( $source_id ) {
424
  $response = WC_Stripe_API::request(
425
+ [
426
  'default_source' => sanitize_text_field( $source_id ),
427
+ ],
428
  'customers/' . $this->get_id(),
429
  'POST'
430
  );
446
  public function clear_cache() {
447
  delete_transient( 'stripe_sources_' . $this->get_id() );
448
  delete_transient( 'stripe_customer_' . $this->get_id() );
449
+ $this->customer_data = [];
450
  }
451
 
452
  /**
includes/class-wc-stripe-exception.php CHANGED
@@ -13,7 +13,10 @@ if ( ! defined( 'ABSPATH' ) ) {
13
 
14
  class WC_Stripe_Exception extends Exception {
15
 
16
- /** @var string sanitized/localized error message */
 
 
 
17
  protected $localized_message;
18
 
19
  /**
13
 
14
  class WC_Stripe_Exception extends Exception {
15
 
16
+ /**
17
+ * String sanitized/localized error message.
18
+ *
19
+ * @var string */
20
  protected $localized_message;
21
 
22
  /**
includes/class-wc-stripe-helper.php CHANGED
@@ -37,7 +37,7 @@ class WC_Stripe_Helper {
37
  * @param object $order
38
  * @param string $currency
39
  */
40
- public static function update_stripe_currency( $order = null, $currency ) {
41
  if ( is_null( $order ) ) {
42
  return false;
43
  }
@@ -77,7 +77,7 @@ class WC_Stripe_Helper {
77
  *
78
  * @since 4.1.0
79
  * @param object $order
80
- * @param float $amount
81
  */
82
  public static function update_stripe_fee( $order = null, $amount = 0.0 ) {
83
  if ( is_null( $order ) ) {
@@ -136,7 +136,7 @@ class WC_Stripe_Helper {
136
  *
137
  * @since 4.1.0
138
  * @param object $order
139
- * @param float $amount
140
  */
141
  public static function update_stripe_net( $order = null, $amount = 0.0 ) {
142
  if ( is_null( $order ) ) {
@@ -193,7 +193,7 @@ class WC_Stripe_Helper {
193
  public static function get_localized_messages() {
194
  return apply_filters(
195
  'wc_stripe_localized_messages',
196
- array(
197
  'invalid_number' => __( 'The card number is not a valid credit card number.', 'woocommerce-gateway-stripe' ),
198
  'invalid_expiry_month' => __( 'The card\'s expiration month is invalid.', 'woocommerce-gateway-stripe' ),
199
  'invalid_expiry_year' => __( 'The card\'s expiration year is invalid.', 'woocommerce-gateway-stripe' ),
@@ -214,7 +214,7 @@ class WC_Stripe_Helper {
214
  'invalid_request_error' => is_add_payment_method_page()
215
  ? __( 'Unable to save this payment method, please try again or use alternative method.', 'woocommerce-gateway-stripe' )
216
  : __( 'Unable to process this payment, please try again or use alternative method.', 'woocommerce-gateway-stripe' ),
217
- )
218
  );
219
  }
220
 
@@ -225,7 +225,7 @@ class WC_Stripe_Helper {
225
  * @return array $currencies
226
  */
227
  public static function no_decimal_currencies() {
228
- return array(
229
  'bif', // Burundian Franc
230
  'clp', // Chilean Peso
231
  'djf', // Djiboutian Franc
@@ -242,7 +242,7 @@ class WC_Stripe_Helper {
242
  'xaf', // Central African Cfa Franc
243
  'xof', // West African Cfa Franc
244
  'xpf', // Cfp Franc
245
- );
246
  }
247
 
248
  /**
@@ -324,17 +324,17 @@ class WC_Stripe_Helper {
324
  * @return array
325
  */
326
  public static function get_supported_card_brands() {
327
- $base_country = wc_get_base_location()['country'];
328
  $base_currency = get_woocommerce_currency();
329
 
330
- $supported_card_brands = array( 'visa', 'mastercard' );
331
 
332
  // American Express is not supported in Brazil and Malaysia (https://stripe.com/docs/payments/cards/supported-card-brands).
333
- if ( ! in_array( $base_country, array( 'BR', 'MY' ) ) ) {
334
  array_push( $supported_card_brands, 'amex' );
335
  }
336
 
337
- // Discover and Diners Club are only supported in the US and Canada. If the store is in the US, USD must be used. (https://stripe.com/docs/currencies#presentment-currencies).
338
  if ( 'US' === $base_country && 'USD' === $base_currency || 'CA' === $base_country ) {
339
  array_push( $supported_card_brands, 'discover', 'diners' );
340
  }
@@ -342,7 +342,7 @@ class WC_Stripe_Helper {
342
  // See: https://support.stripe.com/questions/accepting-japan-credit-bureau-(jcb)-payments.
343
  if ( 'US' === $base_country && 'USD' === $base_currency ||
344
  'JP' === $base_country && 'JPY' === $base_currency ||
345
- in_array( $base_country, array( 'CA', 'AU', 'NZ' ) )
346
  ) {
347
  array_push( $supported_card_brands, 'jcb' );
348
  }
@@ -360,7 +360,7 @@ class WC_Stripe_Helper {
360
  * @param string $setting The name of the setting to get.
361
  */
362
  public static function get_settings( $method = null, $setting = null ) {
363
- $all_settings = null === $method ? get_option( 'woocommerce_stripe_settings', array() ) : get_option( 'woocommerce_stripe_' . $method . '_settings', array() );
364
 
365
  if ( null === $setting ) {
366
  return $all_settings;
@@ -493,14 +493,14 @@ class WC_Stripe_Helper {
493
  * @return string $statement_descriptor Sanitized statement descriptor
494
  */
495
  public static function clean_statement_descriptor( $statement_descriptor = '' ) {
496
- $disallowed_characters = array( '<', '>', '\\', '*', '"', "'", '/', '(', ')', '{', '}' );
497
 
498
  // Strip any tags.
499
  $statement_descriptor = strip_tags( $statement_descriptor );
500
 
501
  // Strip any HTML entities.
502
  // Props https://stackoverflow.com/questions/657643/how-to-remove-html-special-chars .
503
- $statement_descriptor = preg_replace( "/&#?[a-z0-9]{2,8};/i", "", $statement_descriptor );
504
 
505
  // Next, remove any remaining disallowed characters.
506
  $statement_descriptor = str_replace( $disallowed_characters, '', $statement_descriptor );
37
  * @param object $order
38
  * @param string $currency
39
  */
40
+ public static function update_stripe_currency( $order, $currency ) {
41
  if ( is_null( $order ) ) {
42
  return false;
43
  }
77
  *
78
  * @since 4.1.0
79
  * @param object $order
80
+ * @param float $amount
81
  */
82
  public static function update_stripe_fee( $order = null, $amount = 0.0 ) {
83
  if ( is_null( $order ) ) {
136
  *
137
  * @since 4.1.0
138
  * @param object $order
139
+ * @param float $amount
140
  */
141
  public static function update_stripe_net( $order = null, $amount = 0.0 ) {
142
  if ( is_null( $order ) ) {
193
  public static function get_localized_messages() {
194
  return apply_filters(
195
  'wc_stripe_localized_messages',
196
+ [
197
  'invalid_number' => __( 'The card number is not a valid credit card number.', 'woocommerce-gateway-stripe' ),
198
  'invalid_expiry_month' => __( 'The card\'s expiration month is invalid.', 'woocommerce-gateway-stripe' ),
199
  'invalid_expiry_year' => __( 'The card\'s expiration year is invalid.', 'woocommerce-gateway-stripe' ),
214
  'invalid_request_error' => is_add_payment_method_page()
215
  ? __( 'Unable to save this payment method, please try again or use alternative method.', 'woocommerce-gateway-stripe' )
216
  : __( 'Unable to process this payment, please try again or use alternative method.', 'woocommerce-gateway-stripe' ),
217
+ ]
218
  );
219
  }
220
 
225
  * @return array $currencies
226
  */
227
  public static function no_decimal_currencies() {
228
+ return [
229
  'bif', // Burundian Franc
230
  'clp', // Chilean Peso
231
  'djf', // Djiboutian Franc
242
  'xaf', // Central African Cfa Franc
243
  'xof', // West African Cfa Franc
244
  'xpf', // Cfp Franc
245
+ ];
246
  }
247
 
248
  /**
324
  * @return array
325
  */
326
  public static function get_supported_card_brands() {
327
+ $base_country = wc_get_base_location()['country'];
328
  $base_currency = get_woocommerce_currency();
329
 
330
+ $supported_card_brands = [ 'visa', 'mastercard' ];
331
 
332
  // American Express is not supported in Brazil and Malaysia (https://stripe.com/docs/payments/cards/supported-card-brands).
333
+ if ( ! in_array( $base_country, [ 'BR', 'MY' ] ) ) {
334
  array_push( $supported_card_brands, 'amex' );
335
  }
336
 
337
+ // Discover and Diners Club are only supported in the US and Canada. If the store is in the US, USD must be used. (https://stripe.com/docs/currencies#presentment-currencies).
338
  if ( 'US' === $base_country && 'USD' === $base_currency || 'CA' === $base_country ) {
339
  array_push( $supported_card_brands, 'discover', 'diners' );
340
  }
342
  // See: https://support.stripe.com/questions/accepting-japan-credit-bureau-(jcb)-payments.
343
  if ( 'US' === $base_country && 'USD' === $base_currency ||
344
  'JP' === $base_country && 'JPY' === $base_currency ||
345
+ in_array( $base_country, [ 'CA', 'AU', 'NZ' ] )
346
  ) {
347
  array_push( $supported_card_brands, 'jcb' );
348
  }
360
  * @param string $setting The name of the setting to get.
361
  */
362
  public static function get_settings( $method = null, $setting = null ) {
363
+ $all_settings = null === $method ? get_option( 'woocommerce_stripe_settings', [] ) : get_option( 'woocommerce_stripe_' . $method . '_settings', [] );
364
 
365
  if ( null === $setting ) {
366
  return $all_settings;
493
  * @return string $statement_descriptor Sanitized statement descriptor
494
  */
495
  public static function clean_statement_descriptor( $statement_descriptor = '' ) {
496
+ $disallowed_characters = [ '<', '>', '\\', '*', '"', "'", '/', '(', ')', '{', '}' ];
497
 
498
  // Strip any tags.
499
  $statement_descriptor = strip_tags( $statement_descriptor );
500
 
501
  // Strip any HTML entities.
502
  // Props https://stackoverflow.com/questions/657643/how-to-remove-html-special-chars .
503
+ $statement_descriptor = preg_replace( '/&#?[a-z0-9]{2,8};/i', '', $statement_descriptor );
504
 
505
  // Next, remove any remaining disallowed characters.
506
  $statement_descriptor = str_replace( $disallowed_characters, '', $statement_descriptor );
includes/class-wc-stripe-intent-controller.php CHANGED
@@ -23,8 +23,8 @@ class WC_Stripe_Intent_Controller {
23
  * @since 4.2.0
24
  */
25
  public function __construct() {
26
- add_action( 'wc_ajax_wc_stripe_verify_intent', array( $this, 'verify_intent' ) );
27
- add_action( 'wc_ajax_wc_stripe_create_setup_intent', array( $this, 'create_setup_intent' ) );
28
  }
29
 
30
  /**
@@ -150,7 +150,7 @@ class WC_Stripe_Intent_Controller {
150
  }
151
 
152
  try {
153
- $source_id = wc_clean( $_POST['stripe_source_id'] );
154
 
155
  // 1. Verify.
156
  if (
@@ -160,12 +160,15 @@ class WC_Stripe_Intent_Controller {
160
  throw new Exception( __( 'Unable to verify your request. Please reload the page and try again.', 'woocommerce-gateway-stripe' ) );
161
  }
162
 
163
-
164
  // 2. Load the customer ID (and create a customer eventually).
165
  $customer = new WC_Stripe_Customer( wp_get_current_user()->ID );
166
 
167
  // 3. Attach the source to the customer (Setup Intents require that).
168
  $source_object = $customer->attach_source( $source_id );
 
 
 
 
169
  if ( is_wp_error( $source_object ) ) {
170
  throw new Exception( $source_object->get_error_message() );
171
  }
@@ -192,8 +195,8 @@ class WC_Stripe_Intent_Controller {
192
 
193
  if ( ! empty( $setup_intent->error ) ) {
194
  $error_response_message = print_r( $setup_intent, true );
195
- WC_Stripe_Logger::log("Failed create Setup Intent while saving a card.");
196
- WC_Stripe_Logger::log("Response: $error_response_message");
197
  throw new Exception( __( 'Your card could not be set up for future usage.', 'woocommerce-gateway-stripe' ) );
198
  }
199
 
@@ -224,10 +227,10 @@ class WC_Stripe_Intent_Controller {
224
  } catch ( Exception $e ) {
225
  $response = [
226
  'status' => 'error',
227
- 'error' => array(
228
  'type' => 'setup_intent_error',
229
  'message' => $e->getMessage(),
230
- ),
231
  ];
232
  }
233
 
23
  * @since 4.2.0
24
  */
25
  public function __construct() {
26
+ add_action( 'wc_ajax_wc_stripe_verify_intent', [ $this, 'verify_intent' ] );
27
+ add_action( 'wc_ajax_wc_stripe_create_setup_intent', [ $this, 'create_setup_intent' ] );
28
  }
29
 
30
  /**
150
  }
151
 
152
  try {
153
+ $source_id = wc_clean( wp_unslash( $_POST['stripe_source_id'] ) );
154
 
155
  // 1. Verify.
156
  if (
160
  throw new Exception( __( 'Unable to verify your request. Please reload the page and try again.', 'woocommerce-gateway-stripe' ) );
161
  }
162
 
 
163
  // 2. Load the customer ID (and create a customer eventually).
164
  $customer = new WC_Stripe_Customer( wp_get_current_user()->ID );
165
 
166
  // 3. Attach the source to the customer (Setup Intents require that).
167
  $source_object = $customer->attach_source( $source_id );
168
+
169
+ if ( ! empty( $source_object->error ) ) {
170
+ throw new Exception( $source_object->error->message );
171
+ }
172
  if ( is_wp_error( $source_object ) ) {
173
  throw new Exception( $source_object->get_error_message() );
174
  }
195
 
196
  if ( ! empty( $setup_intent->error ) ) {
197
  $error_response_message = print_r( $setup_intent, true );
198
+ WC_Stripe_Logger::log( 'Failed create Setup Intent while saving a card.' );
199
+ WC_Stripe_Logger::log( "Response: $error_response_message" );
200
  throw new Exception( __( 'Your card could not be set up for future usage.', 'woocommerce-gateway-stripe' ) );
201
  }
202
 
227
  } catch ( Exception $e ) {
228
  $response = [
229
  'status' => 'error',
230
+ 'error' => [
231
  'type' => 'setup_intent_error',
232
  'message' => $e->getMessage(),
233
+ ],
234
  ];
235
  }
236
 
includes/class-wc-stripe-logger.php CHANGED
@@ -53,7 +53,7 @@ class WC_Stripe_Logger {
53
 
54
  }
55
 
56
- self::$logger->debug( $log_entry, array( 'source' => self::WC_LOG_FILENAME ) );
57
  }
58
  }
59
  }
53
 
54
  }
55
 
56
+ self::$logger->debug( $log_entry, [ 'source' => self::WC_LOG_FILENAME ] );
57
  }
58
  }
59
  }
includes/class-wc-stripe-order-handler.php CHANGED
@@ -23,12 +23,12 @@ class WC_Stripe_Order_Handler extends WC_Stripe_Payment_Gateway {
23
 
24
  $this->retry_interval = 1;
25
 
26
- add_action( 'wp', array( $this, 'maybe_process_redirect_order' ) );
27
- add_action( 'woocommerce_order_status_processing', array( $this, 'capture_payment' ) );
28
- add_action( 'woocommerce_order_status_completed', array( $this, 'capture_payment' ) );
29
- add_action( 'woocommerce_order_status_cancelled', array( $this, 'cancel_payment' ) );
30
- add_action( 'woocommerce_order_status_refunded', array( $this, 'cancel_payment' ) );
31
- add_filter( 'woocommerce_tracks_event_properties', array( $this, 'woocommerce_tracks_event_properties' ), 10, 2 );
32
  }
33
 
34
  /**
@@ -48,13 +48,13 @@ class WC_Stripe_Order_Handler extends WC_Stripe_Payment_Gateway {
48
  *
49
  * @since 4.0.0
50
  * @since 4.1.8 Add $previous_error parameter.
51
- * @param int $order_id
52
  * @param bool $retry
53
- * @param mix $previous_error Any error message from previous request.
54
  */
55
  public function process_redirect_payment( $order_id, $retry = true, $previous_error = false ) {
56
  try {
57
- $source = wc_clean( $_GET['source'] );
58
 
59
  if ( empty( $source ) ) {
60
  return;
@@ -70,7 +70,7 @@ class WC_Stripe_Order_Handler extends WC_Stripe_Payment_Gateway {
70
  return;
71
  }
72
 
73
- if ( $order->has_status( array( 'processing', 'completed', 'on-hold' ) ) ) {
74
  return;
75
  }
76
 
@@ -113,11 +113,12 @@ class WC_Stripe_Order_Handler extends WC_Stripe_Payment_Gateway {
113
  $source_object->source = $source_info->id;
114
  $source_object->status = 'chargeable';
115
 
116
- /* If we're doing a retry and source is chargeable, we need to pass
 
117
  * a different idempotency key and retry for success.
118
  */
119
  if ( $this->need_update_idempotency_key( $source_object, $previous_error ) ) {
120
- add_filter( 'wc_stripe_idempotency_key', array( $this, 'change_idempotency_key' ), 10, 2 );
121
  }
122
 
123
  // Make the request.
@@ -206,7 +207,7 @@ class WC_Stripe_Order_Handler extends WC_Stripe_Payment_Gateway {
206
  return;
207
  }
208
 
209
- $order_id = wc_clean( $_GET['order_id'] );
210
 
211
  $this->process_redirect_payment( $order_id );
212
  }
@@ -241,11 +242,11 @@ class WC_Stripe_Order_Handler extends WC_Stripe_Payment_Gateway {
241
  $order->add_order_note( sprintf( __( 'Unable to capture charge! %s', 'woocommerce-gateway-stripe' ), $intent->error->message ) );
242
  } elseif ( 'requires_capture' === $intent->status ) {
243
  $level3_data = $this->get_level3_data_from_order( $order );
244
- $result = WC_Stripe_API::request_with_level3_data(
245
- array(
246
  'amount' => WC_Stripe_Helper::get_stripe_amount( $order_total ),
247
  'expand[]' => 'charges.data.balance_transaction',
248
- ),
249
  'payment_intents/' . $intent->id . '/capture',
250
  $level3_data,
251
  $order
@@ -256,7 +257,7 @@ class WC_Stripe_Order_Handler extends WC_Stripe_Payment_Gateway {
256
  $order->update_status( 'failed', sprintf( __( 'Unable to capture charge! %s', 'woocommerce-gateway-stripe' ), $result->error->message ) );
257
  } else {
258
  $is_stripe_captured = true;
259
- $result = end( $result->charges->data );
260
  }
261
  } elseif ( 'succeeded' === $intent->status ) {
262
  $is_stripe_captured = true;
@@ -272,11 +273,11 @@ class WC_Stripe_Order_Handler extends WC_Stripe_Payment_Gateway {
272
  $order->add_order_note( sprintf( __( 'Unable to capture charge! %s', 'woocommerce-gateway-stripe' ), $result->error->message ) );
273
  } elseif ( false === $result->captured ) {
274
  $level3_data = $this->get_level3_data_from_order( $order );
275
- $result = WC_Stripe_API::request_with_level3_data(
276
- array(
277
  'amount' => WC_Stripe_Helper::get_stripe_amount( $order_total ),
278
  'expand[]' => 'balance_transaction',
279
- ),
280
  'charges/' . $charge . '/capture',
281
  $level3_data,
282
  $order
@@ -301,7 +302,7 @@ class WC_Stripe_Order_Handler extends WC_Stripe_Payment_Gateway {
301
  // Store other data such as fees
302
  $order->set_transaction_id( $result->id );
303
 
304
- if ( is_callable( array( $order, 'save' ) ) ) {
305
  $order->save();
306
  }
307
 
@@ -360,21 +361,21 @@ class WC_Stripe_Order_Handler extends WC_Stripe_Payment_Gateway {
360
  }
361
 
362
  // Not stripe? Bail.
363
- if ( 'stripe' != $properties[ 'payment_method' ] ) {
364
  return $properties;
365
  }
366
 
367
  // Due diligence done. Collect the metadata.
368
  $is_live = true;
369
- $stripe_settings = get_option( 'woocommerce_stripe_settings', array() );
370
  if ( array_key_exists( 'testmode', $stripe_settings ) ) {
371
- $is_live = 'no' === $stripe_settings[ 'testmode' ];
372
  }
373
 
374
- $properties[ 'admin_email' ] = get_option( 'admin_email' );
375
- $properties[ 'is_live' ] = $is_live;
376
- $properties[ 'woocommerce_gateway_stripe_version' ] = WC_STRIPE_VERSION;
377
- $properties[ 'woocommerce_default_country' ] = get_option( 'woocommerce_default_country' );
378
 
379
  return $properties;
380
  }
23
 
24
  $this->retry_interval = 1;
25
 
26
+ add_action( 'wp', [ $this, 'maybe_process_redirect_order' ] );
27
+ add_action( 'woocommerce_order_status_processing', [ $this, 'capture_payment' ] );
28
+ add_action( 'woocommerce_order_status_completed', [ $this, 'capture_payment' ] );
29
+ add_action( 'woocommerce_order_status_cancelled', [ $this, 'cancel_payment' ] );
30
+ add_action( 'woocommerce_order_status_refunded', [ $this, 'cancel_payment' ] );
31
+ add_filter( 'woocommerce_tracks_event_properties', [ $this, 'woocommerce_tracks_event_properties' ], 10, 2 );
32
  }
33
 
34
  /**
48
  *
49
  * @since 4.0.0
50
  * @since 4.1.8 Add $previous_error parameter.
51
+ * @param int $order_id
52
  * @param bool $retry
53
+ * @param mix $previous_error Any error message from previous request.
54
  */
55
  public function process_redirect_payment( $order_id, $retry = true, $previous_error = false ) {
56
  try {
57
+ $source = isset( $_GET['source'] ) ? wc_clean( wp_unslash( $_GET['source'] ) ) : '';
58
 
59
  if ( empty( $source ) ) {
60
  return;
70
  return;
71
  }
72
 
73
+ if ( $order->has_status( [ 'processing', 'completed', 'on-hold' ] ) ) {
74
  return;
75
  }
76
 
113
  $source_object->source = $source_info->id;
114
  $source_object->status = 'chargeable';
115
 
116
+ /*
117
+ * If we're doing a retry and source is chargeable, we need to pass
118
  * a different idempotency key and retry for success.
119
  */
120
  if ( $this->need_update_idempotency_key( $source_object, $previous_error ) ) {
121
+ add_filter( 'wc_stripe_idempotency_key', [ $this, 'change_idempotency_key' ], 10, 2 );
122
  }
123
 
124
  // Make the request.
207
  return;
208
  }
209
 
210
+ $order_id = isset( $_GET['order_id'] ) ? wc_clean( wp_unslash( $_GET['order_id'] ) ) : '';
211
 
212
  $this->process_redirect_payment( $order_id );
213
  }
242
  $order->add_order_note( sprintf( __( 'Unable to capture charge! %s', 'woocommerce-gateway-stripe' ), $intent->error->message ) );
243
  } elseif ( 'requires_capture' === $intent->status ) {
244
  $level3_data = $this->get_level3_data_from_order( $order );
245
+ $result = WC_Stripe_API::request_with_level3_data(
246
+ [
247
  'amount' => WC_Stripe_Helper::get_stripe_amount( $order_total ),
248
  'expand[]' => 'charges.data.balance_transaction',
249
+ ],
250
  'payment_intents/' . $intent->id . '/capture',
251
  $level3_data,
252
  $order
257
  $order->update_status( 'failed', sprintf( __( 'Unable to capture charge! %s', 'woocommerce-gateway-stripe' ), $result->error->message ) );
258
  } else {
259
  $is_stripe_captured = true;
260
+ $result = end( $result->charges->data );
261
  }
262
  } elseif ( 'succeeded' === $intent->status ) {
263
  $is_stripe_captured = true;
273
  $order->add_order_note( sprintf( __( 'Unable to capture charge! %s', 'woocommerce-gateway-stripe' ), $result->error->message ) );
274
  } elseif ( false === $result->captured ) {
275
  $level3_data = $this->get_level3_data_from_order( $order );
276
+ $result = WC_Stripe_API::request_with_level3_data(
277
+ [
278
  'amount' => WC_Stripe_Helper::get_stripe_amount( $order_total ),
279
  'expand[]' => 'balance_transaction',
280
+ ],
281
  'charges/' . $charge . '/capture',
282
  $level3_data,
283
  $order
302
  // Store other data such as fees
303
  $order->set_transaction_id( $result->id );
304
 
305
+ if ( is_callable( [ $order, 'save' ] ) ) {
306
  $order->save();
307
  }
308
 
361
  }
362
 
363
  // Not stripe? Bail.
364
+ if ( 'stripe' != $properties['payment_method'] ) {
365
  return $properties;
366
  }
367
 
368
  // Due diligence done. Collect the metadata.
369
  $is_live = true;
370
+ $stripe_settings = get_option( 'woocommerce_stripe_settings', [] );
371
  if ( array_key_exists( 'testmode', $stripe_settings ) ) {
372
+ $is_live = 'no' === $stripe_settings['testmode'];
373
  }
374
 
375
+ $properties['admin_email'] = get_option( 'admin_email' );
376
+ $properties['is_live'] = $is_live;
377
+ $properties['woocommerce_gateway_stripe_version'] = WC_STRIPE_VERSION;
378
+ $properties['woocommerce_default_country'] = get_option( 'woocommerce_default_country' );
379
 
380
  return $properties;
381
  }
includes/class-wc-stripe-payment-tokens.php CHANGED
@@ -21,11 +21,11 @@ class WC_Stripe_Payment_Tokens {
21
  public function __construct() {
22
  self::$_this = $this;
23
 
24
- add_filter( 'woocommerce_get_customer_payment_tokens', array( $this, 'woocommerce_get_customer_payment_tokens' ), 10, 3 );
25
- add_filter( 'woocommerce_payment_methods_list_item', array( $this, 'get_account_saved_payment_methods_list_item_sepa' ), 10, 2 );
26
- add_filter( 'woocommerce_get_credit_card_type_label', array( $this, 'normalize_sepa_label' ) );
27
- add_action( 'woocommerce_payment_token_deleted', array( $this, 'woocommerce_payment_token_deleted' ), 10, 2 );
28
- add_action( 'woocommerce_payment_token_set_default', array( $this, 'woocommerce_payment_token_set_default' ) );
29
  }
30
 
31
  /**
@@ -62,7 +62,7 @@ class WC_Stripe_Payment_Tokens {
62
  * @return bool
63
  */
64
  public static function customer_has_saved_methods( $customer_id ) {
65
- $gateways = array( 'stripe', 'stripe_sepa' );
66
 
67
  if ( empty( $customer_id ) ) {
68
  return false;
@@ -92,7 +92,7 @@ class WC_Stripe_Payment_Tokens {
92
  */
93
  public function woocommerce_get_customer_payment_tokens( $tokens, $customer_id, $gateway_id ) {
94
  if ( is_user_logged_in() && class_exists( 'WC_Payment_Token_CC' ) ) {
95
- $stored_tokens = array();
96
 
97
  foreach ( $tokens as $token ) {
98
  $stored_tokens[] = $token->get_token();
@@ -165,7 +165,7 @@ class WC_Stripe_Payment_Tokens {
165
  *
166
  * @since 4.0.0
167
  * @version 4.0.0
168
- * @param array $item Individual list item from woocommerce_saved_payment_methods_list
169
  * @param WC_Payment_Token $payment_token The payment token associated with this method entry
170
  * @return array Filtered item
171
  */
21
  public function __construct() {
22
  self::$_this = $this;
23
 
24
+ add_filter( 'woocommerce_get_customer_payment_tokens', [ $this, 'woocommerce_get_customer_payment_tokens' ], 10, 3 );
25
+ add_filter( 'woocommerce_payment_methods_list_item', [ $this, 'get_account_saved_payment_methods_list_item_sepa' ], 10, 2 );
26
+ add_filter( 'woocommerce_get_credit_card_type_label', [ $this, 'normalize_sepa_label' ] );
27
+ add_action( 'woocommerce_payment_token_deleted', [ $this, 'woocommerce_payment_token_deleted' ], 10, 2 );
28
+ add_action( 'woocommerce_payment_token_set_default', [ $this, 'woocommerce_payment_token_set_default' ] );
29
  }
30
 
31
  /**
62
  * @return bool
63
  */
64
  public static function customer_has_saved_methods( $customer_id ) {
65
+ $gateways = [ 'stripe', 'stripe_sepa' ];
66
 
67
  if ( empty( $customer_id ) ) {
68
  return false;
92
  */
93
  public function woocommerce_get_customer_payment_tokens( $tokens, $customer_id, $gateway_id ) {
94
  if ( is_user_logged_in() && class_exists( 'WC_Payment_Token_CC' ) ) {
95
+ $stored_tokens = [];
96
 
97
  foreach ( $tokens as $token ) {
98
  $stored_tokens[] = $token->get_token();
165
  *
166
  * @since 4.0.0
167
  * @version 4.0.0
168
+ * @param array $item Individual list item from woocommerce_saved_payment_methods_list
169
  * @param WC_Payment_Token $payment_token The payment token associated with this method entry
170
  * @return array Filtered item
171
  */
includes/class-wc-stripe-sepa-payment-token.php CHANGED
@@ -4,6 +4,8 @@ if ( ! defined( 'ABSPATH' ) ) {
4
  exit; // Exit if accessed directly
5
  }
6
 
 
 
7
  /**
8
  * WooCommerce Stripe SEPA Direct Debit Payment Token.
9
  *
@@ -15,7 +17,11 @@ if ( ! defined( 'ABSPATH' ) ) {
15
  */
16
  class WC_Payment_Token_SEPA extends WC_Payment_Token {
17
 
18
- /** @protected string Token Type String. */
 
 
 
 
19
  protected $type = 'sepa';
20
 
21
  /**
@@ -23,9 +29,9 @@ class WC_Payment_Token_SEPA extends WC_Payment_Token {
23
  *
24
  * @var array
25
  */
26
- protected $extra_data = array(
27
  'last4' => '',
28
- );
29
 
30
  /**
31
  * Get type to display to user.
@@ -91,6 +97,7 @@ class WC_Payment_Token_SEPA extends WC_Payment_Token {
91
 
92
  /**
93
  * Set the last four digits.
 
94
  * @since 4.0.0
95
  * @version 4.0.0
96
  * @param string $last4
4
  exit; // Exit if accessed directly
5
  }
6
 
7
+ // phpcs:disable WordPress.Files.FileName
8
+
9
  /**
10
  * WooCommerce Stripe SEPA Direct Debit Payment Token.
11
  *
17
  */
18
  class WC_Payment_Token_SEPA extends WC_Payment_Token {
19
 
20
+ /**
21
+ * Stores payment type.
22
+ *
23
+ * @protected string
24
+ */
25
  protected $type = 'sepa';
26
 
27
  /**
29
  *
30
  * @var array
31
  */
32
+ protected $extra_data = [
33
  'last4' => '',
34
+ ];
35
 
36
  /**
37
  * Get type to display to user.
97
 
98
  /**
99
  * Set the last four digits.
100
+ *
101
  * @since 4.0.0
102
  * @version 4.0.0
103
  * @param string $last4
includes/class-wc-stripe-webhook-handler.php CHANGED
@@ -7,6 +7,7 @@ if ( ! defined( 'ABSPATH' ) ) {
7
  * Class WC_Stripe_Webhook_Handler.
8
  *
9
  * Handles webhooks from Stripe on sources that are not immediately chargeable.
 
10
  * @since 4.0.0
11
  */
12
  class WC_Stripe_Webhook_Handler extends WC_Stripe_Payment_Gateway {
@@ -35,26 +36,32 @@ class WC_Stripe_Webhook_Handler extends WC_Stripe_Payment_Gateway {
35
  * Constructor.
36
  *
37
  * @since 4.0.0
38
- * @version 4.0.0
39
  */
40
  public function __construct() {
41
  $this->retry_interval = 2;
42
- $stripe_settings = get_option( 'woocommerce_stripe_settings', array() );
43
  $this->testmode = ( ! empty( $stripe_settings['testmode'] ) && 'yes' === $stripe_settings['testmode'] ) ? true : false;
44
  $secret_key = ( $this->testmode ? 'test_' : '' ) . 'webhook_secret';
45
  $this->secret = ! empty( $stripe_settings[ $secret_key ] ) ? $stripe_settings[ $secret_key ] : false;
46
 
47
- add_action( 'woocommerce_api_wc_stripe', array( $this, 'check_for_webhook' ) );
 
 
 
 
 
48
  }
49
 
50
  /**
51
  * Check incoming requests for Stripe Webhook data and process them.
52
  *
53
  * @since 4.0.0
54
- * @version 4.0.0
55
  */
56
  public function check_for_webhook() {
57
- if ( ( 'POST' !== $_SERVER['REQUEST_METHOD'] )
 
58
  || ! isset( $_GET['wc-api'] )
59
  || ( 'wc_stripe' !== $_GET['wc-api'] )
60
  ) {
@@ -65,12 +72,20 @@ class WC_Stripe_Webhook_Handler extends WC_Stripe_Payment_Gateway {
65
  $request_headers = array_change_key_case( $this->get_request_headers(), CASE_UPPER );
66
 
67
  // Validate it to make sure it is legit.
68
- if ( $this->is_valid_request( $request_headers, $request_body ) ) {
 
69
  $this->process_webhook( $request_body );
 
 
 
 
70
  status_header( 200 );
71
  exit;
72
  } else {
73
  WC_Stripe_Logger::log( 'Incoming webhook failed validation: ' . print_r( $request_body, true ) );
 
 
 
74
  status_header( 400 );
75
  exit;
76
  }
@@ -80,44 +95,60 @@ class WC_Stripe_Webhook_Handler extends WC_Stripe_Payment_Gateway {
80
  * Verify the incoming webhook notification to make sure it is legit.
81
  *
82
  * @since 4.0.0
83
- * @version 4.0.0
84
- * @param string $request_headers The request headers from Stripe.
85
- * @param string $request_body The request body from Stripe.
86
- * @return bool
87
  */
88
- public function is_valid_request( $request_headers = null, $request_body = null ) {
89
- if ( null === $request_headers || null === $request_body ) {
90
- return false;
 
 
 
91
  }
92
 
93
- if ( ! empty( $request_headers['USER-AGENT'] ) && ! preg_match( '/Stripe/', $request_headers['USER-AGENT'] ) ) {
94
- return false;
95
  }
96
 
97
- if ( ! empty( $this->secret ) ) {
98
- // Check for a valid signature.
99
- $signature_format = '/^t=(?P<timestamp>\d+)(?P<signatures>(,v\d+=[a-z0-9]+){1,2})$/';
100
- if ( empty( $request_headers['STRIPE-SIGNATURE'] ) || ! preg_match( $signature_format, $request_headers['STRIPE-SIGNATURE'], $matches ) ) {
101
- return false;
102
- }
103
 
104
- // Verify the timestamp.
105
- $timestamp = intval( $matches['timestamp'] );
106
- if ( abs( $timestamp - time() ) > 5 * MINUTE_IN_SECONDS ) {
107
- return false;
108
- }
109
 
110
- // Generate the expected signature.
111
- $signed_payload = $timestamp . '.' . $request_body;
112
- $expected_signature = hash_hmac( 'sha256', $signed_payload, $this->secret );
113
 
114
- // Check if the expected signature is present.
115
- if ( ! preg_match( '/,v\d+=' . preg_quote( $expected_signature, '/' ) . '/', $matches['signatures'] ) ) {
116
- return false;
117
- }
118
  }
119
 
120
- return true;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
121
  }
122
 
123
  /**
@@ -130,7 +161,7 @@ class WC_Stripe_Webhook_Handler extends WC_Stripe_Payment_Gateway {
130
  */
131
  public function get_request_headers() {
132
  if ( ! function_exists( 'getallheaders' ) ) {
133
- $headers = array();
134
 
135
  foreach ( $_SERVER as $name => $value ) {
136
  if ( 'HTTP_' === substr( $name, 0, 5 ) ) {
@@ -151,7 +182,7 @@ class WC_Stripe_Webhook_Handler extends WC_Stripe_Payment_Gateway {
151
  * @since 4.0.0
152
  * @version 4.0.0
153
  * @param object $notification
154
- * @param bool $retry
155
  */
156
  public function process_webhook_payment( $notification, $retry = true ) {
157
  // The following 3 payment methods are synchronous so does not need to be handle via webhook.
@@ -172,7 +203,7 @@ class WC_Stripe_Webhook_Handler extends WC_Stripe_Payment_Gateway {
172
  $is_pending_receiver = ( 'receiver' === $notification->data->object->flow );
173
 
174
  try {
175
- if ( $order->has_status( array( 'processing', 'completed' ) ) ) {
176
  return;
177
  }
178
 
@@ -263,7 +294,7 @@ class WC_Stripe_Webhook_Handler extends WC_Stripe_Payment_Gateway {
263
 
264
  do_action( 'wc_gateway_stripe_process_webhook_payment_error', $order, $notification, $e );
265
 
266
- $statuses = array( 'pending', 'failed' );
267
 
268
  if ( $order->has_status( $statuses ) ) {
269
  $this->send_failed_order_email( $order_id );
@@ -384,7 +415,7 @@ class WC_Stripe_Webhook_Handler extends WC_Stripe_Payment_Gateway {
384
  $order->add_order_note( sprintf( __( 'Stripe charge complete (Charge ID: %s)', 'woocommerce-gateway-stripe' ), $notification->data->object->id ) );
385
  }
386
 
387
- if ( is_callable( array( $order, 'save' ) ) ) {
388
  $order->save();
389
  }
390
  }
@@ -433,7 +464,7 @@ class WC_Stripe_Webhook_Handler extends WC_Stripe_Payment_Gateway {
433
  /* translators: transaction id */
434
  $order->add_order_note( sprintf( __( 'Stripe charge complete (Charge ID: %s)', 'woocommerce-gateway-stripe' ), $notification->data->object->id ) );
435
 
436
- if ( is_callable( array( $order, 'save' ) ) ) {
437
  $order->save();
438
  }
439
  }
@@ -555,11 +586,11 @@ class WC_Stripe_Webhook_Handler extends WC_Stripe_Payment_Gateway {
555
 
556
  // Create the refund.
557
  $refund = wc_create_refund(
558
- array(
559
  'order_id' => $order_id,
560
  'amount' => $this->get_refund_amount( $notification ),
561
  'reason' => $reason,
562
- )
563
  );
564
 
565
  if ( is_wp_error( $refund ) ) {
@@ -705,14 +736,14 @@ class WC_Stripe_Webhook_Handler extends WC_Stripe_Payment_Gateway {
705
 
706
  public function process_payment_intent_success( $notification ) {
707
  $intent = $notification->data->object;
708
- $order = WC_Stripe_Helper::get_order_by_intent_id( $intent->id );
709
 
710
  if ( ! $order ) {
711
  WC_Stripe_Logger::log( 'Could not find order via intent ID: ' . $intent->id );
712
  return;
713
  }
714
 
715
- if ( ! $order->has_status( array( 'pending', 'failed' ) ) ) {
716
  return;
717
  }
718
 
@@ -731,7 +762,7 @@ class WC_Stripe_Webhook_Handler extends WC_Stripe_Payment_Gateway {
731
  $this->process_response( $charge, $order );
732
 
733
  } else {
734
- $error_message = $intent->last_payment_error ? $intent->last_payment_error->message : "";
735
 
736
  /* translators: 1) The error message that was received from Stripe. */
737
  $message = sprintf( __( 'Stripe SCA authentication failed. Reason: %s', 'woocommerce-gateway-stripe' ), $error_message );
@@ -752,14 +783,14 @@ class WC_Stripe_Webhook_Handler extends WC_Stripe_Payment_Gateway {
752
 
753
  public function process_setup_intent( $notification ) {
754
  $intent = $notification->data->object;
755
- $order = WC_Stripe_Helper::get_order_by_setup_intent_id( $intent->id );
756
 
757
  if ( ! $order ) {
758
  WC_Stripe_Logger::log( 'Could not find order via setup intent ID: ' . $intent->id );
759
  return;
760
  }
761
 
762
- if ( ! $order->has_status( array( 'pending', 'failed' ) ) ) {
763
  return;
764
  }
765
 
@@ -776,7 +807,7 @@ class WC_Stripe_Webhook_Handler extends WC_Stripe_Payment_Gateway {
776
  $order->payment_complete();
777
  }
778
  } else {
779
- $error_message = $intent->last_setup_error ? $intent->last_setup_error->message : "";
780
 
781
  /* translators: 1) The error message that was received from Stripe. */
782
  $message = sprintf( __( 'Stripe SCA authentication failed. Reason: %s', 'woocommerce-gateway-stripe' ), $error_message );
7
  * Class WC_Stripe_Webhook_Handler.
8
  *
9
  * Handles webhooks from Stripe on sources that are not immediately chargeable.
10
+ *
11
  * @since 4.0.0
12
  */
13
  class WC_Stripe_Webhook_Handler extends WC_Stripe_Payment_Gateway {
36
  * Constructor.
37
  *
38
  * @since 4.0.0
39
+ * @version 5.0.0
40
  */
41
  public function __construct() {
42
  $this->retry_interval = 2;
43
+ $stripe_settings = get_option( 'woocommerce_stripe_settings', [] );
44
  $this->testmode = ( ! empty( $stripe_settings['testmode'] ) && 'yes' === $stripe_settings['testmode'] ) ? true : false;
45
  $secret_key = ( $this->testmode ? 'test_' : '' ) . 'webhook_secret';
46
  $this->secret = ! empty( $stripe_settings[ $secret_key ] ) ? $stripe_settings[ $secret_key ] : false;
47
 
48
+ add_action( 'woocommerce_api_wc_stripe', [ $this, 'check_for_webhook' ] );
49
+
50
+ // Get/set the time we began monitoring the health of webhooks by fetching it.
51
+ // This should be roughly the same as the activation time of the version of the
52
+ // plugin when this code first appears.
53
+ WC_Stripe_Webhook_State::get_monitoring_began_at();
54
  }
55
 
56
  /**
57
  * Check incoming requests for Stripe Webhook data and process them.
58
  *
59
  * @since 4.0.0
60
+ * @version 5.0.0
61
  */
62
  public function check_for_webhook() {
63
+ if ( ! isset( $_SERVER['REQUEST_METHOD'] )
64
+ || ( 'POST' !== $_SERVER['REQUEST_METHOD'] )
65
  || ! isset( $_GET['wc-api'] )
66
  || ( 'wc_stripe' !== $_GET['wc-api'] )
67
  ) {
72
  $request_headers = array_change_key_case( $this->get_request_headers(), CASE_UPPER );
73
 
74
  // Validate it to make sure it is legit.
75
+ $validation_result = $this->validate_request( $request_headers, $request_body );
76
+ if ( WC_Stripe_Webhook_State::VALIDATION_SUCCEEDED === $validation_result ) {
77
  $this->process_webhook( $request_body );
78
+
79
+ $notification = json_decode( $request_body );
80
+ WC_Stripe_Webhook_State::set_last_webhook_success_at( $notification->created );
81
+
82
  status_header( 200 );
83
  exit;
84
  } else {
85
  WC_Stripe_Logger::log( 'Incoming webhook failed validation: ' . print_r( $request_body, true ) );
86
+ WC_Stripe_Webhook_State::set_last_webhook_failure_at( time() );
87
+ WC_Stripe_Webhook_State::set_last_error_reason( $validation_result );
88
+
89
  status_header( 400 );
90
  exit;
91
  }
95
  * Verify the incoming webhook notification to make sure it is legit.
96
  *
97
  * @since 4.0.0
98
+ * @version 5.0.0
99
+ * @param array $request_headers The request headers from Stripe.
100
+ * @param array $request_body The request body from Stripe.
101
+ * @return string The validation result (e.g. self::VALIDATION_SUCCEEDED )
102
  */
103
+ public function validate_request( $request_headers, $request_body ) {
104
+ if ( empty( $request_headers ) ) {
105
+ return WC_Stripe_Webhook_State::VALIDATION_FAILED_EMPTY_HEADERS;
106
+ }
107
+ if ( empty( $request_body ) ) {
108
+ return WC_Stripe_Webhook_State::VALIDATION_FAILED_EMPTY_BODY;
109
  }
110
 
111
+ if ( empty( $this->secret ) ) {
112
+ return $this->validate_request_user_agent( $request_headers );
113
  }
114
 
115
+ // Check for a valid signature.
116
+ $signature_format = '/^t=(?P<timestamp>\d+)(?P<signatures>(,v\d+=[a-z0-9]+){1,2})$/';
117
+ if ( empty( $request_headers['STRIPE-SIGNATURE'] ) || ! preg_match( $signature_format, $request_headers['STRIPE-SIGNATURE'], $matches ) ) {
118
+ return WC_Stripe_Webhook_State::VALIDATION_FAILED_SIGNATURE_INVALID;
119
+ }
 
120
 
121
+ // Verify the timestamp.
122
+ $timestamp = intval( $matches['timestamp'] );
123
+ if ( abs( $timestamp - time() ) > 5 * MINUTE_IN_SECONDS ) {
124
+ return WC_Stripe_Webhook_State::VALIDATION_FAILED_TIMESTAMP_MISMATCH;
125
+ }
126
 
127
+ // Generate the expected signature.
128
+ $signed_payload = $timestamp . '.' . $request_body;
129
+ $expected_signature = hash_hmac( 'sha256', $signed_payload, $this->secret );
130
 
131
+ // Check if the expected signature is present.
132
+ if ( ! preg_match( '/,v\d+=' . preg_quote( $expected_signature, '/' ) . '/', $matches['signatures'] ) ) {
133
+ return WC_Stripe_Webhook_State::VALIDATION_FAILED_SIGNATURE_MISMATCH;
 
134
  }
135
 
136
+ return WC_Stripe_Webhook_State::VALIDATION_SUCCEEDED;
137
+ }
138
+
139
+ /**
140
+ * Verify User Agent of the incoming webhook notification. Used as fallback for the cases when webhook secret is missing.
141
+ *
142
+ * @since 5.0.0
143
+ * @version 5.0.0
144
+ * @param array $request_headers The request headers from Stripe.
145
+ * @return string The validation result (e.g. self::VALIDATION_SUCCEEDED )
146
+ */
147
+ private function validate_request_user_agent( $request_headers ) {
148
+ $ua_is_valid = empty( $request_headers['USER-AGENT'] ) || preg_match( '/Stripe/', $request_headers['USER-AGENT'] );
149
+ $ua_is_valid = apply_filters( 'wc_stripe_webhook_is_user_agent_valid', $ua_is_valid, $request_headers );
150
+
151
+ return $ua_is_valid ? WC_Stripe_Webhook_State::VALIDATION_SUCCEEDED : WC_Stripe_Webhook_State::VALIDATION_FAILED_USER_AGENT_INVALID;
152
  }
153
 
154
  /**
161
  */
162
  public function get_request_headers() {
163
  if ( ! function_exists( 'getallheaders' ) ) {
164
+ $headers = [];
165
 
166
  foreach ( $_SERVER as $name => $value ) {
167
  if ( 'HTTP_' === substr( $name, 0, 5 ) ) {
182
  * @since 4.0.0
183
  * @version 4.0.0
184
  * @param object $notification
185
+ * @param bool $retry
186
  */
187
  public function process_webhook_payment( $notification, $retry = true ) {
188
  // The following 3 payment methods are synchronous so does not need to be handle via webhook.
203
  $is_pending_receiver = ( 'receiver' === $notification->data->object->flow );
204
 
205
  try {
206
+ if ( $order->has_status( [ 'processing', 'completed' ] ) ) {
207
  return;
208
  }
209
 
294
 
295
  do_action( 'wc_gateway_stripe_process_webhook_payment_error', $order, $notification, $e );
296
 
297
+ $statuses = [ 'pending', 'failed' ];
298
 
299
  if ( $order->has_status( $statuses ) ) {
300
  $this->send_failed_order_email( $order_id );
415
  $order->add_order_note( sprintf( __( 'Stripe charge complete (Charge ID: %s)', 'woocommerce-gateway-stripe' ), $notification->data->object->id ) );
416
  }
417
 
418
+ if ( is_callable( [ $order, 'save' ] ) ) {
419
  $order->save();
420
  }
421
  }
464
  /* translators: transaction id */
465
  $order->add_order_note( sprintf( __( 'Stripe charge complete (Charge ID: %s)', 'woocommerce-gateway-stripe' ), $notification->data->object->id ) );
466
 
467
+ if ( is_callable( [ $order, 'save' ] ) ) {
468
  $order->save();
469
  }
470
  }
586
 
587
  // Create the refund.
588
  $refund = wc_create_refund(
589
+ [
590
  'order_id' => $order_id,
591
  'amount' => $this->get_refund_amount( $notification ),
592
  'reason' => $reason,
593
+ ]
594
  );
595
 
596
  if ( is_wp_error( $refund ) ) {
736
 
737
  public function process_payment_intent_success( $notification ) {
738
  $intent = $notification->data->object;
739
+ $order = WC_Stripe_Helper::get_order_by_intent_id( $intent->id );
740
 
741
  if ( ! $order ) {
742
  WC_Stripe_Logger::log( 'Could not find order via intent ID: ' . $intent->id );
743
  return;
744
  }
745
 
746
+ if ( ! $order->has_status( [ 'pending', 'failed' ] ) ) {
747
  return;
748
  }
749
 
762
  $this->process_response( $charge, $order );
763
 
764
  } else {
765
+ $error_message = $intent->last_payment_error ? $intent->last_payment_error->message : '';
766
 
767
  /* translators: 1) The error message that was received from Stripe. */
768
  $message = sprintf( __( 'Stripe SCA authentication failed. Reason: %s', 'woocommerce-gateway-stripe' ), $error_message );
783
 
784
  public function process_setup_intent( $notification ) {
785
  $intent = $notification->data->object;
786
+ $order = WC_Stripe_Helper::get_order_by_setup_intent_id( $intent->id );
787
 
788
  if ( ! $order ) {
789
  WC_Stripe_Logger::log( 'Could not find order via setup intent ID: ' . $intent->id );
790
  return;
791
  }
792
 
793
+ if ( ! $order->has_status( [ 'pending', 'failed' ] ) ) {
794
  return;
795
  }
796
 
807
  $order->payment_complete();
808
  }
809
  } else {
810
+ $error_message = $intent->last_setup_error ? $intent->last_setup_error->message : '';
811
 
812
  /* translators: 1) The error message that was received from Stripe. */
813
  $message = sprintf( __( 'Stripe SCA authentication failed. Reason: %s', 'woocommerce-gateway-stripe' ), $error_message );
includes/class-wc-stripe-webhook-state.php ADDED
@@ -0,0 +1,248 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ if ( ! defined( 'ABSPATH' ) ) {
3
+ exit;
4
+ }
5
+
6
+ /**
7
+ * Class WC_Stripe_Webhook_State.
8
+ *
9
+ * Tracks the most recent successful and unsuccessful webhooks in test and live modes.
10
+ *
11
+ * @since 5.0.0
12
+ */
13
+ class WC_Stripe_Webhook_State {
14
+ const OPTION_LIVE_MONITORING_BEGAN_AT = 'wc_stripe_wh_monitor_began_at';
15
+ const OPTION_LIVE_LAST_SUCCESS_AT = 'wc_stripe_wh_last_success_at';
16
+ const OPTION_LIVE_LAST_FAILURE_AT = 'wc_stripe_wh_last_failure_at';
17
+ const OPTION_LIVE_LAST_ERROR = 'wc_stripe_wh_last_error';
18
+
19
+ const OPTION_TEST_MONITORING_BEGAN_AT = 'wc_stripe_wh_test_monitor_began_at';
20
+ const OPTION_TEST_LAST_SUCCESS_AT = 'wc_stripe_wh_test_last_success_at';
21
+ const OPTION_TEST_LAST_FAILURE_AT = 'wc_stripe_wh_test_last_failure_at';
22
+ const OPTION_TEST_LAST_ERROR = 'wc_stripe_wh_test_last_error';
23
+
24
+ const VALIDATION_SUCCEEDED = 'validation_succeeded';
25
+ const VALIDATION_FAILED_EMPTY_HEADERS = 'empty_headers';
26
+ const VALIDATION_FAILED_EMPTY_BODY = 'empty_body';
27
+ const VALIDATION_FAILED_USER_AGENT_INVALID = 'user_agent_invalid';
28
+ const VALIDATION_FAILED_SIGNATURE_INVALID = 'signature_invalid';
29
+ const VALIDATION_FAILED_TIMESTAMP_MISMATCH = 'timestamp_out_of_range';
30
+ const VALIDATION_FAILED_SIGNATURE_MISMATCH = 'signature_mismatch';
31
+
32
+ /**
33
+ * Gets whether Stripe is in test mode or not
34
+ *
35
+ * @since 5.0.0
36
+ * @return bool
37
+ */
38
+ public static function get_testmode() {
39
+ $stripe_settings = get_option( 'woocommerce_stripe_settings', [] );
40
+ return ( ! empty( $stripe_settings['testmode'] ) && 'yes' === $stripe_settings['testmode'] ) ? true : false;
41
+ }
42
+
43
+ /**
44
+ * Gets (and sets, if unset) the timestamp the plugin first
45
+ * started tracking webhook failure and successes.
46
+ *
47
+ * @since 5.0.0
48
+ * @return integer UTC seconds since 1970.
49
+ */
50
+ public static function get_monitoring_began_at() {
51
+ $option = self::get_testmode() ? self::OPTION_TEST_MONITORING_BEGAN_AT : self::OPTION_LIVE_MONITORING_BEGAN_AT;
52
+ $monitoring_began_at = get_option( $option, 0 );
53
+ if ( 0 == $monitoring_began_at ) {
54
+ $monitoring_began_at = time();
55
+ update_option( $option, $monitoring_began_at );
56
+
57
+ // Enforce database consistency. This should only be needed if the user
58
+ // has modified the database directly. We should not allow timestamps
59
+ // before monitoring began.
60
+ self::set_last_webhook_success_at( 0 );
61
+ self::set_last_webhook_failure_at( 0 );
62
+ self::set_last_error_reason( self::VALIDATION_SUCCEEDED );
63
+ }
64
+ return $monitoring_began_at;
65
+ }
66
+
67
+ /**
68
+ * Sets the timestamp of the last successfully processed webhook.
69
+ *
70
+ * @since 5.0.0
71
+ * @param integer UTC seconds since 1970.
72
+ */
73
+ public static function set_last_webhook_success_at( $timestamp ) {
74
+ $option = self::get_testmode() ? self::OPTION_TEST_LAST_SUCCESS_AT : self::OPTION_LIVE_LAST_SUCCESS_AT;
75
+ update_option( $option, $timestamp );
76
+ }
77
+
78
+ /**
79
+ * Gets the timestamp of the last successfully processed webhook,
80
+ * or returns 0 if no webhook has ever been successfully processed.
81
+ *
82
+ * @since 5.0.0
83
+ * @return integer UTC seconds since 1970 | 0.
84
+ */
85
+ public static function get_last_webhook_success_at() {
86
+ $option = self::get_testmode() ? self::OPTION_TEST_LAST_SUCCESS_AT : self::OPTION_LIVE_LAST_SUCCESS_AT;
87
+ return get_option( $option, 0 );
88
+ }
89
+
90
+ /**
91
+ * Sets the timestamp of the last failed webhook.
92
+ *
93
+ * @since 5.0.0
94
+ * @param integer UTC seconds since 1970.
95
+ */
96
+ public static function set_last_webhook_failure_at( $timestamp ) {
97
+ $option = self::get_testmode() ? self::OPTION_TEST_LAST_FAILURE_AT : self::OPTION_LIVE_LAST_FAILURE_AT;
98
+ update_option( $option, $timestamp );
99
+ }
100
+
101
+ /**
102
+ * Gets the timestamp of the last failed webhook,
103
+ * or returns 0 if no webhook has ever failed to process.
104
+ *
105
+ * @since 5.0.0
106
+ * @return integer UTC seconds since 1970 | 0.
107
+ */
108
+ public static function get_last_webhook_failure_at() {
109
+ $option = self::get_testmode() ? self::OPTION_TEST_LAST_FAILURE_AT : self::OPTION_LIVE_LAST_FAILURE_AT;
110
+ return get_option( $option, 0 );
111
+ }
112
+
113
+ /**
114
+ * Sets the reason for the last failed webhook.
115
+ *
116
+ * @since 5.0.0
117
+ * @param string Reason code.
118
+ */
119
+ public static function set_last_error_reason( $reason ) {
120
+ $option = self::get_testmode() ? self::OPTION_TEST_LAST_ERROR : self::OPTION_LIVE_LAST_ERROR;
121
+ update_option( $option, $reason );
122
+ }
123
+
124
+ /**
125
+ * Returns the localized reason the last webhook failed.
126
+ *
127
+ * @since 5.0.0
128
+ * @return string Reason the last webhook failed.
129
+ */
130
+ public static function get_last_error_reason() {
131
+ $option = self::get_testmode() ? self::OPTION_TEST_LAST_ERROR : self::OPTION_LIVE_LAST_ERROR;
132
+ $last_error = get_option( $option, false );
133
+
134
+ if ( self::VALIDATION_SUCCEEDED == $last_error ) {
135
+ return( __( 'No error', 'woocommerce-gateway-stripe' ) );
136
+ }
137
+
138
+ if ( self::VALIDATION_FAILED_EMPTY_HEADERS == $last_error ) {
139
+ return( __( 'The webhook was missing expected headers', 'woocommerce-gateway-stripe' ) );
140
+ }
141
+
142
+ if ( self::VALIDATION_FAILED_EMPTY_BODY == $last_error ) {
143
+ return( __( 'The webhook was missing expected body', 'woocommerce-gateway-stripe' ) );
144
+ }
145
+
146
+ if ( self::VALIDATION_FAILED_USER_AGENT_INVALID == $last_error ) {
147
+ return( __( 'The webhook received did not come from Stripe', 'woocommerce-gateway-stripe' ) );
148
+ }
149
+
150
+ if ( self::VALIDATION_FAILED_SIGNATURE_INVALID == $last_error ) {
151
+ return( __( 'The webhook signature was missing or was incorrectly formatted', 'woocommerce-gateway-stripe' ) );
152
+ }
153
+
154
+ if ( self::VALIDATION_FAILED_TIMESTAMP_MISMATCH == $last_error ) {
155
+ return( __( 'The timestamp in the webhook differed more than five minutes from the site time', 'woocommerce-gateway-stripe' ) );
156
+ }
157
+
158
+ if ( self::VALIDATION_FAILED_SIGNATURE_MISMATCH == $last_error ) {
159
+ return( __( 'The webhook was not signed with the expected signing secret', 'woocommerce-gateway-stripe' ) );
160
+ }
161
+
162
+ return( __( 'Unknown error.', 'woocommerce-gateway-stripe' ) );
163
+ }
164
+
165
+ /**
166
+ * Gets the state of webhook processing in a human readable format.
167
+ *
168
+ * @since 5.0.0
169
+ * @return string Details on recent webhook successes and failures.
170
+ */
171
+ public static function get_webhook_status_message() {
172
+ $monitoring_began_at = self::get_monitoring_began_at();
173
+ $last_success_at = self::get_last_webhook_success_at();
174
+ $last_failure_at = self::get_last_webhook_failure_at();
175
+ $last_error = self::get_last_error_reason();
176
+ $test_mode = self::get_testmode();
177
+
178
+ $date_format = 'Y-m-d H:i:s e';
179
+
180
+ // Case 1 (Nominal case): Most recent = success
181
+ if ( $last_success_at > $last_failure_at ) {
182
+ $message = sprintf(
183
+ $test_mode ?
184
+ /* translators: 1) date and time of last webhook received, e.g. 2020-06-28 10:30:50 UTC */
185
+ __( 'The most recent test webhook, timestamped %s, was processed successfully.', 'woocommerce-gateway-stripe' ) :
186
+ /* translators: 1) date and time of last webhook received, e.g. 2020-06-28 10:30:50 UTC */
187
+ __( 'The most recent live webhook, timestamped %s, was processed successfully.', 'woocommerce-gateway-stripe' ),
188
+ gmdate( $date_format, $last_success_at )
189
+ );
190
+ return $message;
191
+ }
192
+
193
+ // Case 2: No webhooks received yet
194
+ if ( ( 0 == $last_success_at ) && ( 0 == $last_failure_at ) ) {
195
+ $message = sprintf(
196
+ $test_mode ?
197
+ /* translators: 1) date and time webhook monitoring began, e.g. 2020-06-28 10:30:50 UTC */
198
+ __( 'No test webhooks have been received since monitoring began at %s.', 'woocommerce-gateway-stripe' ) :
199
+ /* translators: 1) date and time webhook monitoring began, e.g. 2020-06-28 10:30:50 UTC */
200
+ __( 'No live webhooks have been received since monitoring began at %s.', 'woocommerce-gateway-stripe' ),
201
+ gmdate( $date_format, $monitoring_began_at )
202
+ );
203
+ return $message;
204
+ }
205
+
206
+ // Case 3: Failure after success
207
+ if ( $last_success_at > 0 ) {
208
+ $message = sprintf(
209
+ $test_mode ?
210
+ /*
211
+ * translators: 1) date and time of last failed webhook e.g. 2020-06-28 10:30:50 UTC
212
+ * translators: 2) reason webhook failed
213
+ * translators: 3) date and time of last successful webhook e.g. 2020-05-28 10:30:50 UTC
214
+ */
215
+ __( 'Warning: The most recent test webhook, received at %1$s, could not be processed. Reason: %2$s. (The last test webhook to process successfully was timestamped %3$s.)', 'woocommerce-gateway-stripe' ) :
216
+ /*
217
+ * translators: 1) date and time of last failed webhook e.g. 2020-06-28 10:30:50 UTC
218
+ * translators: 2) reason webhook failed
219
+ * translators: 3) date and time of last successful webhook e.g. 2020-05-28 10:30:50 UTC
220
+ */
221
+ __( 'Warning: The most recent live webhook, received at %1$s, could not be processed. Reason: %2$s. (The last live webhook to process successfully was timestamped %3$s.)', 'woocommerce-gateway-stripe' ),
222
+ gmdate( $date_format, $last_failure_at ),
223
+ $last_error,
224
+ gmdate( $date_format, $last_success_at )
225
+ );
226
+ return $message;
227
+ }
228
+
229
+ // Case 4: Failure with no prior success
230
+ $message = sprintf(
231
+ $test_mode ?
232
+ /* translators: 1) date and time of last failed webhook e.g. 2020-06-28 10:30:50 UTC
233
+ * translators: 2) reason webhook failed
234
+ * translators: 3) date and time webhook monitoring began e.g. 2020-05-28 10:30:50 UTC
235
+ */
236
+ __( 'Warning: The most recent test webhook, received at %1$s, could not be processed. Reason: %2$s. (No test webhooks have been processed successfully since monitoring began at %3$s.)', 'woocommerce-gateway-stripe' ) :
237
+ /* translators: 1) date and time of last failed webhook e.g. 2020-06-28 10:30:50 UTC
238
+ * translators: 2) reason webhook failed
239
+ * translators: 3) date and time webhook monitoring began e.g. 2020-05-28 10:30:50 UTC
240
+ */
241
+ __( 'Warning: The most recent live webhook, received at %1$s, could not be processed. Reason: %2$s. (No live webhooks have been processed successfully since monitoring began at %3$s.)', 'woocommerce-gateway-stripe' ),
242
+ gmdate( $date_format, $last_failure_at ),
243
+ $last_error,
244
+ gmdate( $date_format, $monitoring_began_at )
245
+ );
246
+ return $message;
247
+ }
248
+ };
includes/compat/class-wc-stripe-email-failed-authentication-retry.php CHANGED
@@ -71,7 +71,7 @@ class WC_Stripe_Email_Failed_Authentication_Retry extends WC_Email_Failed_Order
71
 
72
  $this->find['retry-time'] = '{retry_time}';
73
  if ( class_exists( 'WCS_Retry_Manager' ) && function_exists( 'wcs_get_human_time_diff' ) ) {
74
- $this->retry = WCS_Retry_Manager::store()->get_last_retry_for_order( wcs_get_objects_property( $order, 'id' ) );
75
  $this->replace['retry-time'] = wcs_get_human_time_diff( $this->retry->get_time() );
76
  } else {
77
  WC_Stripe_Logger::log( 'WCS_Retry_Manager class or does not exist. Not able to send admnin email about customer notification for authentication required for renewal payment.' );
@@ -96,14 +96,14 @@ class WC_Stripe_Email_Failed_Authentication_Retry extends WC_Email_Failed_Order
96
  public function get_content_html() {
97
  return wc_get_template_html(
98
  $this->template_html,
99
- array(
100
  'order' => $this->object,
101
  'retry' => $this->retry,
102
  'email_heading' => $this->get_heading(),
103
  'sent_to_admin' => true,
104
  'plain_text' => false,
105
  'email' => $this,
106
- ),
107
  '',
108
  $this->template_base
109
  );
@@ -117,14 +117,14 @@ class WC_Stripe_Email_Failed_Authentication_Retry extends WC_Email_Failed_Order
117
  public function get_content_plain() {
118
  return wc_get_template_html(
119
  $this->template_plain,
120
- array(
121
  'order' => $this->object,
122
  'retry' => $this->retry,
123
  'email_heading' => $this->get_heading(),
124
  'sent_to_admin' => true,
125
  'plain_text' => true,
126
  'email' => $this,
127
- ),
128
  '',
129
  $this->template_base
130
  );
71
 
72
  $this->find['retry-time'] = '{retry_time}';
73
  if ( class_exists( 'WCS_Retry_Manager' ) && function_exists( 'wcs_get_human_time_diff' ) ) {
74
+ $this->retry = WCS_Retry_Manager::store()->get_last_retry_for_order( wcs_get_objects_property( $order, 'id' ) );
75
  $this->replace['retry-time'] = wcs_get_human_time_diff( $this->retry->get_time() );
76
  } else {
77
  WC_Stripe_Logger::log( 'WCS_Retry_Manager class or does not exist. Not able to send admnin email about customer notification for authentication required for renewal payment.' );
96
  public function get_content_html() {
97
  return wc_get_template_html(
98
  $this->template_html,
99
+ [
100
  'order' => $this->object,
101
  'retry' => $this->retry,
102
  'email_heading' => $this->get_heading(),
103
  'sent_to_admin' => true,
104
  'plain_text' => false,
105
  'email' => $this,
106
+ ],
107
  '',
108
  $this->template_base
109
  );
117
  public function get_content_plain() {
118
  return wc_get_template_html(
119
  $this->template_plain,
120
+ [
121
  'order' => $this->object,
122
  'retry' => $this->retry,
123
  'email_heading' => $this->get_heading(),
124
  'sent_to_admin' => true,
125
  'plain_text' => true,
126
  'email' => $this,
127
+ ],
128
  '',
129
  $this->template_base
130
  );
includes/compat/class-wc-stripe-email-failed-authentication.php CHANGED
@@ -25,14 +25,14 @@ abstract class WC_Stripe_Email_Failed_Authentication extends WC_Email {
25
  ob_start();
26
  wc_get_template(
27
  $this->template_html,
28
- array(
29
  'order' => $this->object,
30
  'email_heading' => $this->get_heading(),
31
  'sent_to_admin' => false,
32
  'plain_text' => false,
33
  'authorization_url' => $this->get_authorization_url( $this->object ),
34
  'email' => $this,
35
- ),
36
  '',
37
  $this->template_base
38
  );
@@ -48,14 +48,14 @@ abstract class WC_Stripe_Email_Failed_Authentication extends WC_Email {
48
  ob_start();
49
  wc_get_template(
50
  $this->template_plain,
51
- array(
52
  'order' => $this->object,
53
  'email_heading' => $this->get_heading(),
54
  'sent_to_admin' => false,
55
  'plain_text' => true,
56
  'authorization_url' => $this->get_authorization_url( $this->object ),
57
  'email' => $this,
58
- ),
59
  '',
60
  $this->template_base
61
  );
@@ -79,18 +79,18 @@ abstract class WC_Stripe_Email_Failed_Authentication extends WC_Email {
79
  parent::init_form_fields();
80
  $base_fields = $this->form_fields;
81
 
82
- $this->form_fields = array(
83
- 'enabled' => array(
84
  'title' => _x( 'Enable/Disable', 'an email notification', 'woocommerce-gateway-stripe' ),
85
  'type' => 'checkbox',
86
  'label' => __( 'Enable this email notification', 'woocommerce-gateway-stripe' ),
87
  'default' => 'yes',
88
- ),
89
 
90
  'subject' => $base_fields['subject'],
91
  'heading' => $base_fields['heading'],
92
  'email_type' => $base_fields['email_type'],
93
- );
94
  }
95
 
96
  /**
25
  ob_start();
26
  wc_get_template(
27
  $this->template_html,
28
+ [
29
  'order' => $this->object,
30
  'email_heading' => $this->get_heading(),
31
  'sent_to_admin' => false,
32
  'plain_text' => false,
33
  'authorization_url' => $this->get_authorization_url( $this->object ),
34
  'email' => $this,
35
+ ],
36
  '',
37
  $this->template_base
38
  );
48
  ob_start();
49
  wc_get_template(
50
  $this->template_plain,
51
+ [
52
  'order' => $this->object,
53
  'email_heading' => $this->get_heading(),
54
  'sent_to_admin' => false,
55
  'plain_text' => true,
56
  'authorization_url' => $this->get_authorization_url( $this->object ),
57
  'email' => $this,
58
+ ],
59
  '',
60
  $this->template_base
61
  );
79
  parent::init_form_fields();
80
  $base_fields = $this->form_fields;
81
 
82
+ $this->form_fields = [
83
+ 'enabled' => [
84
  'title' => _x( 'Enable/Disable', 'an email notification', 'woocommerce-gateway-stripe' ),
85
  'type' => 'checkbox',
86
  'label' => __( 'Enable this email notification', 'woocommerce-gateway-stripe' ),
87
  'default' => 'yes',
88
+ ],
89
 
90
  'subject' => $base_fields['subject'],
91
  'heading' => $base_fields['heading'],
92
  'email_type' => $base_fields['email_type'],
93
+ ];
94
  }
95
 
96
  /**
includes/compat/class-wc-stripe-email-failed-preorder-authentication.php CHANGED
@@ -21,7 +21,7 @@ class WC_Stripe_Email_Failed_Preorder_Authentication extends WC_Stripe_Email_Fai
21
  *
22
  * @param WC_Email[] $email_classes All existing instances of WooCommerce emails.
23
  */
24
- public function __construct( $email_classes = array() ) {
25
  $this->id = 'failed_preorder_sca_authentication';
26
  $this->title = __( 'Pre-order Payment Action Needed', 'woocommerce-gateway-stripe' );
27
  $this->description = __( 'This is an order notification sent to the customer once a pre-order is complete, but additional payment steps are required.', 'woocommerce-gateway-stripe' );
@@ -32,7 +32,7 @@ class WC_Stripe_Email_Failed_Preorder_Authentication extends WC_Stripe_Email_Fai
32
  $this->template_base = plugin_dir_path( WC_STRIPE_MAIN_FILE ) . 'templates/';
33
 
34
  // Use the "authentication required" hook to add the correct, later hook.
35
- add_action( 'wc_gateway_stripe_process_payment_authentication_required', array( $this, 'trigger' ) );
36
 
37
  if ( isset( $email_classes['WC_Pre_Orders_Email_Pre_Order_Available'] ) ) {
38
  $this->original_email = $email_classes['WC_Pre_Orders_Email_Pre_Order_Available'];
@@ -51,10 +51,10 @@ class WC_Stripe_Email_Failed_Preorder_Authentication extends WC_Stripe_Email_Fai
51
  public function trigger( $order ) {
52
  if ( class_exists( 'WC_Pre_Orders_Order' ) && WC_Pre_Orders_Order::order_contains_pre_order( $order->get_id() ) ) {
53
  if ( isset( $this->original_email ) ) {
54
- remove_action( 'wc_pre_order_status_completed_notification', array( $this->original_email, 'trigger' ), 10, 2 );
55
  }
56
 
57
- add_action( 'wc_pre_orders_pre_order_completed', array( $this, 'send_email' ), 10, 2 );
58
  }
59
  }
60
 
@@ -71,7 +71,7 @@ class WC_Stripe_Email_Failed_Preorder_Authentication extends WC_Stripe_Email_Fai
71
 
72
  // Restore the action of the original email for other bulk actions.
73
  if ( isset( $this->original_email ) ) {
74
- add_action( 'wc_pre_order_status_completed_notification', array( $this->original_email, 'trigger' ), 10, 2 );
75
  }
76
  }
77
 
21
  *
22
  * @param WC_Email[] $email_classes All existing instances of WooCommerce emails.
23
  */
24
+ public function __construct( $email_classes = [] ) {
25
  $this->id = 'failed_preorder_sca_authentication';
26
  $this->title = __( 'Pre-order Payment Action Needed', 'woocommerce-gateway-stripe' );
27
  $this->description = __( 'This is an order notification sent to the customer once a pre-order is complete, but additional payment steps are required.', 'woocommerce-gateway-stripe' );
32
  $this->template_base = plugin_dir_path( WC_STRIPE_MAIN_FILE ) . 'templates/';
33
 
34
  // Use the "authentication required" hook to add the correct, later hook.
35
+ add_action( 'wc_gateway_stripe_process_payment_authentication_required', [ $this, 'trigger' ] );
36
 
37
  if ( isset( $email_classes['WC_Pre_Orders_Email_Pre_Order_Available'] ) ) {
38
  $this->original_email = $email_classes['WC_Pre_Orders_Email_Pre_Order_Available'];
51
  public function trigger( $order ) {
52
  if ( class_exists( 'WC_Pre_Orders_Order' ) && WC_Pre_Orders_Order::order_contains_pre_order( $order->get_id() ) ) {
53
  if ( isset( $this->original_email ) ) {
54
+ remove_action( 'wc_pre_order_status_completed_notification', [ $this->original_email, 'trigger' ], 10, 2 );
55
  }
56
 
57
+ add_action( 'wc_pre_orders_pre_order_completed', [ $this, 'send_email' ], 10, 2 );
58
  }
59
  }
60
 
71
 
72
  // Restore the action of the original email for other bulk actions.
73
  if ( isset( $this->original_email ) ) {
74
+ add_action( 'wc_pre_order_status_completed_notification', [ $this->original_email, 'trigger' ], 10, 2 );
75
  }
76
  }
77
 
includes/compat/class-wc-stripe-email-failed-renewal-authentication.php CHANGED
@@ -14,7 +14,7 @@ class WC_Stripe_Email_Failed_Renewal_Authentication extends WC_Stripe_Email_Fail
14
  *
15
  * @param WC_Email[] $email_classes All existing instances of WooCommerce emails.
16
  */
17
- public function __construct( $email_classes = array() ) {
18
  $this->id = 'failed_renewal_authentication';
19
  $this->title = __( 'Failed Subscription Renewal SCA Authentication', 'woocommerce-gateway-stripe' );
20
  $this->description = __( 'Sent to a customer when a renewal fails because the transaction requires an SCA verification. The email contains renewal order information and payment links.', 'woocommerce-gateway-stripe' );
@@ -25,7 +25,7 @@ class WC_Stripe_Email_Failed_Renewal_Authentication extends WC_Stripe_Email_Fail
25
  $this->template_base = plugin_dir_path( WC_STRIPE_MAIN_FILE ) . 'templates/';
26
 
27
  // Triggers the email at the correct hook.
28
- add_action( 'wc_gateway_stripe_process_payment_authentication_required', array( $this, 'trigger' ) );
29
 
30
  if ( isset( $email_classes['WCS_Email_Customer_Renewal_Invoice'] ) ) {
31
  $this->original_email = $email_classes['WCS_Email_Customer_Renewal_Invoice'];
@@ -46,15 +46,15 @@ class WC_Stripe_Email_Failed_Renewal_Authentication extends WC_Stripe_Email_Fail
46
 
47
  // Prevent the renewal email from WooCommerce Subscriptions from being sent.
48
  if ( isset( $this->original_email ) ) {
49
- remove_action( 'woocommerce_generated_manual_renewal_order_renewal_notification', array( $this->original_email, 'trigger' ) );
50
- remove_action( 'woocommerce_order_status_failed_renewal_notification', array( $this->original_email, 'trigger' ) );
51
  }
52
 
53
  // Prevent the retry email from WooCommerce Subscriptions from being sent.
54
- add_filter( 'wcs_get_retry_rule_raw', array( $this, 'prevent_retry_notification_email' ), 100, 3 );
55
 
56
  // Send email to store owner indicating communication is happening with the customer to request authentication.
57
- add_filter( 'wcs_get_retry_rule_raw', array( $this, 'set_store_owner_custom_email' ), 100, 3 );
58
  }
59
  }
60
 
14
  *
15
  * @param WC_Email[] $email_classes All existing instances of WooCommerce emails.
16
  */
17
+ public function __construct( $email_classes = [] ) {
18
  $this->id = 'failed_renewal_authentication';
19
  $this->title = __( 'Failed Subscription Renewal SCA Authentication', 'woocommerce-gateway-stripe' );
20
  $this->description = __( 'Sent to a customer when a renewal fails because the transaction requires an SCA verification. The email contains renewal order information and payment links.', 'woocommerce-gateway-stripe' );
25
  $this->template_base = plugin_dir_path( WC_STRIPE_MAIN_FILE ) . 'templates/';
26
 
27
  // Triggers the email at the correct hook.
28
+ add_action( 'wc_gateway_stripe_process_payment_authentication_required', [ $this, 'trigger' ] );
29
 
30
  if ( isset( $email_classes['WCS_Email_Customer_Renewal_Invoice'] ) ) {
31
  $this->original_email = $email_classes['WCS_Email_Customer_Renewal_Invoice'];
46
 
47
  // Prevent the renewal email from WooCommerce Subscriptions from being sent.
48
  if ( isset( $this->original_email ) ) {
49
+ remove_action( 'woocommerce_generated_manual_renewal_order_renewal_notification', [ $this->original_email, 'trigger' ] );
50
+ remove_action( 'woocommerce_order_status_failed_renewal_notification', [ $this->original_email, 'trigger' ] );
51
  }
52
 
53
  // Prevent the retry email from WooCommerce Subscriptions from being sent.
54
+ add_filter( 'wcs_get_retry_rule_raw', [ $this, 'prevent_retry_notification_email' ], 100, 3 );
55
 
56
  // Send email to store owner indicating communication is happening with the customer to request authentication.
57
+ add_filter( 'wcs_get_retry_rule_raw', [ $this, 'set_store_owner_custom_email' ], 100, 3 );
58
  }
59
  }
60
 
includes/compat/class-wc-stripe-pre-orders-compat.php CHANGED
@@ -5,7 +5,6 @@ if ( ! defined( 'ABSPATH' ) ) {
5
 
6
  /**
7
  * Compatibility class for Pre-Orders.
8
- *
9
  */
10
  class WC_Stripe_Pre_Orders_Compat extends WC_Stripe_Payment_Gateway {
11
  public $saved_cards;
@@ -16,7 +15,8 @@ class WC_Stripe_Pre_Orders_Compat extends WC_Stripe_Payment_Gateway {
16
 
17
  /**
18
  * Is $order_id a pre-order?
19
- * @param int $order_id
 
20
  * @return boolean
21
  */
22
  public function is_pre_order( $order_id ) {
@@ -25,6 +25,7 @@ class WC_Stripe_Pre_Orders_Compat extends WC_Stripe_Payment_Gateway {
25
 
26
  /**
27
  * Remove order meta
 
28
  * @param object $order
29
  */
30
  public function remove_order_source_before_retry( $order ) {
@@ -35,6 +36,7 @@ class WC_Stripe_Pre_Orders_Compat extends WC_Stripe_Payment_Gateway {
35
 
36
  /**
37
  * Process the pre-order when pay upon release is used.
 
38
  * @param int $order_id
39
  */
40
  public function process_pre_order( $order_id ) {
@@ -52,10 +54,10 @@ class WC_Stripe_Pre_Orders_Compat extends WC_Stripe_Payment_Gateway {
52
  }
53
 
54
  // Setup the response early to allow later modifications.
55
- $response = array(
56
  'result' => 'success',
57
  'redirect' => $this->get_return_url( $order ),
58
- );
59
 
60
  $this->save_source_to_order( $order, $prepared_source );
61
 
@@ -78,10 +80,10 @@ class WC_Stripe_Pre_Orders_Compat extends WC_Stripe_Payment_Gateway {
78
  wc_add_notice( $e->getLocalizedMessage(), 'error' );
79
  WC_Stripe_Logger::log( 'Pre Orders Error: ' . $e->getMessage() );
80
 
81
- return array(
82
  'result' => 'success',
83
  'redirect' => $order->get_checkout_payment_url( true ),
84
- );
85
  }
86
  }
87
 
@@ -89,7 +91,7 @@ class WC_Stripe_Pre_Orders_Compat extends WC_Stripe_Payment_Gateway {
89
  * Process a pre-order payment when the pre-order is released.
90
  *
91
  * @param WC_Order $order
92
- * @param bool $retry
93
  *
94
  * @return void
95
  */
@@ -106,13 +108,14 @@ class WC_Stripe_Pre_Orders_Compat extends WC_Stripe_Payment_Gateway {
106
  }
107
  $this->remove_order_source_before_retry( $order );
108
  $this->process_pre_order_release_payment( $order, false );
109
- } else if ( $is_authentication_required ) {
110
  $charge = end( $response->error->payment_intent->charges->data );
111
- $id = $charge->id;
112
 
113
  $order->set_transaction_id( $id );
 
114
  $order->update_status( 'failed', sprintf( __( 'Stripe charge awaiting authentication by user: %s.', 'woocommerce-gateway-stripe' ), $id ) );
115
- if ( is_callable( array( $order, 'save' ) ) ) {
116
  $order->save();
117
  }
118
 
@@ -126,7 +129,7 @@ class WC_Stripe_Pre_Orders_Compat extends WC_Stripe_Payment_Gateway {
126
  $this->process_response( end( $response->charges->data ), $order );
127
  }
128
  } catch ( Exception $e ) {
129
- $error_message = is_callable( array( $e, 'getLocalizedMessage' ) ) ? $e->getLocalizedMessage() : $e->getMessage();
130
  /* translators: error message */
131
  $order_note = sprintf( __( 'Stripe Transaction Failed (%s)', 'woocommerce-gateway-stripe' ), $error_message );
132
 
5
 
6
  /**
7
  * Compatibility class for Pre-Orders.
 
8
  */
9
  class WC_Stripe_Pre_Orders_Compat extends WC_Stripe_Payment_Gateway {
10
  public $saved_cards;
15
 
16
  /**
17
  * Is $order_id a pre-order?
18
+ *
19
+ * @param int $order_id
20
  * @return boolean
21
  */
22
  public function is_pre_order( $order_id ) {
25
 
26
  /**
27
  * Remove order meta
28
+ *
29
  * @param object $order
30
  */
31
  public function remove_order_source_before_retry( $order ) {
36
 
37
  /**
38
  * Process the pre-order when pay upon release is used.
39
+ *
40
  * @param int $order_id
41
  */
42
  public function process_pre_order( $order_id ) {
54
  }
55
 
56
  // Setup the response early to allow later modifications.
57
+ $response = [
58
  'result' => 'success',
59
  'redirect' => $this->get_return_url( $order ),
60
+ ];
61
 
62
  $this->save_source_to_order( $order, $prepared_source );
63
 
80
  wc_add_notice( $e->getLocalizedMessage(), 'error' );
81
  WC_Stripe_Logger::log( 'Pre Orders Error: ' . $e->getMessage() );
82
 
83
+ return [
84
  'result' => 'success',
85
  'redirect' => $order->get_checkout_payment_url( true ),
86
+ ];
87
  }
88
  }
89
 
91
  * Process a pre-order payment when the pre-order is released.
92
  *
93
  * @param WC_Order $order
94
+ * @param bool $retry
95
  *
96
  * @return void
97
  */
108
  }
109
  $this->remove_order_source_before_retry( $order );
110
  $this->process_pre_order_release_payment( $order, false );
111
+ } elseif ( $is_authentication_required ) {
112
  $charge = end( $response->error->payment_intent->charges->data );
113
+ $id = $charge->id;
114
 
115
  $order->set_transaction_id( $id );
116
+ /* translators: %s is the charge Id */
117
  $order->update_status( 'failed', sprintf( __( 'Stripe charge awaiting authentication by user: %s.', 'woocommerce-gateway-stripe' ), $id ) );
118
+ if ( is_callable( [ $order, 'save' ] ) ) {
119
  $order->save();
120
  }
121
 
129
  $this->process_response( end( $response->charges->data ), $order );
130
  }
131
  } catch ( Exception $e ) {
132
+ $error_message = is_callable( [ $e, 'getLocalizedMessage' ] ) ? $e->getLocalizedMessage() : $e->getMessage();
133
  /* translators: error message */
134
  $order_note = sprintf( __( 'Stripe Transaction Failed (%s)', 'woocommerce-gateway-stripe' ), $error_message );
135
 
includes/compat/class-wc-stripe-sepa-subs-compat.php CHANGED
@@ -16,20 +16,20 @@ class WC_Stripe_Sepa_Subs_Compat extends WC_Gateway_Stripe_Sepa {
16
  parent::__construct();
17
 
18
  if ( class_exists( 'WC_Subscriptions_Order' ) ) {
19
- add_action( 'woocommerce_scheduled_subscription_payment_' . $this->id, array( $this, 'scheduled_subscription_payment' ), 10, 2 );
20
- add_action( 'wcs_resubscribe_order_created', array( $this, 'delete_resubscribe_meta' ), 10 );
21
- add_action( 'wcs_renewal_order_created', array( $this, 'delete_renewal_meta' ), 10 );
22
- add_action( 'woocommerce_subscription_failing_payment_method_updated_stripe', array( $this, 'update_failing_payment_method' ), 10, 2 );
23
- add_action( 'wc_stripe_sepa_payment_fields', array( $this, 'display_update_subs_payment_checkout' ) );
24
- add_action( 'wc_stripe_add_payment_method_' . $this->id . '_success', array( $this, 'handle_add_payment_method_success' ), 10, 2 );
25
 
26
  // Display the credit card used for a subscription in the "My Subscriptions" table.
27
- add_filter( 'woocommerce_my_subscriptions_payment_method', array( $this, 'maybe_render_subscription_payment_method' ), 10, 2 );
28
 
29
  // Allow store managers to manually set Stripe as the payment method on a subscription.
30
- add_filter( 'woocommerce_subscription_payment_meta', array( $this, 'add_subscription_payment_meta' ), 10, 2 );
31
- add_filter( 'woocommerce_subscription_validate_payment_meta', array( $this, 'validate_subscription_payment_meta' ), 10, 2 );
32
- add_filter( 'wc_stripe_display_save_payment_method_checkbox', array( $this, 'maybe_hide_save_checkbox' ) );
33
  }
34
  }
35
 
@@ -50,7 +50,8 @@ class WC_Stripe_Sepa_Subs_Compat extends WC_Gateway_Stripe_Sepa {
50
 
51
  /**
52
  * Is $order_id a subscription?
53
- * @param int $order_id
 
54
  * @return boolean
55
  */
56
  public function has_subscription( $order_id ) {
@@ -74,7 +75,7 @@ class WC_Stripe_Sepa_Subs_Compat extends WC_Gateway_Stripe_Sepa {
74
  * @since 4.1.11
75
  */
76
  public function display_update_subs_payment_checkout() {
77
- $subs_statuses = apply_filters( 'wc_stripe_update_subs_payment_method_card_statuses', array( 'active' ) );
78
  if (
79
  apply_filters( 'wc_stripe_display_update_subs_payment_method_card_checkbox', true ) &&
80
  wcs_user_has_subscription( get_current_user_id(), '', $subs_statuses ) &&
@@ -84,11 +85,11 @@ class WC_Stripe_Sepa_Subs_Compat extends WC_Gateway_Stripe_Sepa {
84
  $id = sprintf( 'wc-%1$s-update-subs-payment-method-card', $this->id );
85
  woocommerce_form_field(
86
  $id,
87
- array(
88
  'type' => 'checkbox',
89
  'label' => $label,
90
  'default' => apply_filters( 'wc_stripe_save_to_subs_checked', false ),
91
- )
92
  );
93
  }
94
  }
@@ -103,7 +104,7 @@ class WC_Stripe_Sepa_Subs_Compat extends WC_Gateway_Stripe_Sepa {
103
  public function handle_add_payment_method_success( $source_id, $source_object ) {
104
  if ( isset( $_POST[ 'wc-' . $this->id . '-update-subs-payment-method-card' ] ) ) {
105
  $all_subs = wcs_get_users_subscriptions();
106
- $subs_statuses = apply_filters( 'wc_stripe_update_subs_payment_method_card_statuses', array( 'active' ) );
107
  $stripe_customer = new WC_Stripe_Customer( get_current_user_id() );
108
 
109
  if ( ! empty( $all_subs ) ) {
@@ -112,12 +113,12 @@ class WC_Stripe_Sepa_Subs_Compat extends WC_Gateway_Stripe_Sepa {
112
  WC_Subscriptions_Change_Payment_Gateway::update_payment_method(
113
  $sub,
114
  $this->id,
115
- array(
116
- 'post_meta' => array(
117
- '_stripe_source_id' => array( 'value' => $source_id ),
118
- '_stripe_customer_id' => array( 'value' => $stripe_customer->get_id() ),
119
- ),
120
- )
121
  );
122
  }
123
  }
@@ -142,7 +143,7 @@ class WC_Stripe_Sepa_Subs_Compat extends WC_Gateway_Stripe_Sepa {
142
  } elseif ( function_exists( 'wcs_order_contains_renewal' ) && wcs_order_contains_renewal( $order_id ) ) {
143
  $subscriptions = wcs_get_subscriptions_for_renewal_order( $order_id );
144
  } else {
145
- $subscriptions = array();
146
  }
147
 
148
  foreach ( $subscriptions as $subscription ) {
@@ -154,6 +155,7 @@ class WC_Stripe_Sepa_Subs_Compat extends WC_Gateway_Stripe_Sepa {
154
 
155
  /**
156
  * Process the payment based on type.
 
157
  * @param int $order_id
158
  * @return array
159
  */
@@ -190,10 +192,10 @@ class WC_Stripe_Sepa_Subs_Compat extends WC_Gateway_Stripe_Sepa {
190
 
191
  do_action( 'wc_stripe_change_subs_payment_method_success', $prepared_source->source, $prepared_source );
192
 
193
- return array(
194
  'result' => 'success',
195
  'redirect' => $this->get_return_url( $subscription ),
196
- );
197
  } catch ( WC_Stripe_Exception $e ) {
198
  wc_add_notice( $e->getLocalizedMessage(), 'error' );
199
  WC_Stripe_Logger::log( 'Error: ' . $e->getMessage() );
@@ -216,9 +218,9 @@ class WC_Stripe_Sepa_Subs_Compat extends WC_Gateway_Stripe_Sepa {
216
  * @since 3.0
217
  * @since 4.0.4 Add third parameter flag to retry.
218
  * @since 4.1.0 Add fourth parameter to log previous errors.
219
- * @param float $amount
220
- * @param mixed $renewal_order
221
- * @param bool $retry Should we retry the process?
222
  * @param object $previous_error
223
  */
224
  public function process_subscription_payment( $amount, $renewal_order, $retry = true, $previous_error = false ) {
@@ -249,11 +251,12 @@ class WC_Stripe_Sepa_Subs_Compat extends WC_Gateway_Stripe_Sepa {
249
 
250
  WC_Stripe_Logger::log( "Info: Begin processing subscription payment for order {$order_id} for the amount of {$amount}" );
251
 
252
- /* If we're doing a retry and source is chargeable, we need to pass
 
253
  * a different idempotency key and retry for success.
254
  */
255
  if ( is_object( $source_object ) && empty( $source_object->error ) && $this->need_update_idempotency_key( $source_object, $previous_error ) ) {
256
- add_filter( 'wc_stripe_idempotency_key', array( $this, 'change_idempotency_key' ), 10, 2 );
257
  }
258
 
259
  if ( ( $this->is_no_such_source_error( $previous_error ) || $this->is_no_linked_source_error( $previous_error ) ) && apply_filters( 'wc_stripe_use_default_customer_source', true ) ) {
@@ -315,6 +318,7 @@ class WC_Stripe_Sepa_Subs_Compat extends WC_Gateway_Stripe_Sepa {
315
 
316
  /**
317
  * Don't transfer Stripe customer/token meta to resubscribe orders.
 
318
  * @param int $resubscribe_order The order created for the customer to resubscribe to the old expired/cancelled subscription
319
  */
320
  public function delete_resubscribe_meta( $resubscribe_order ) {
@@ -327,6 +331,7 @@ class WC_Stripe_Sepa_Subs_Compat extends WC_Gateway_Stripe_Sepa {
327
 
328
  /**
329
  * Don't transfer Stripe fee/ID meta to renewal orders.
 
330
  * @param int $resubscribe_order The order created for the customer to resubscribe to the old expired/cancelled subscription
331
  */
332
  public function delete_renewal_meta( $renewal_order ) {
@@ -340,9 +345,8 @@ class WC_Stripe_Sepa_Subs_Compat extends WC_Gateway_Stripe_Sepa {
340
  * Update the customer_id for a subscription after using Stripe to complete a payment to make up for
341
  * an automatic renewal payment which previously failed.
342
  *
343
- * @access public
344
  * @param WC_Subscription $subscription The subscription for which the failing payment method relates.
345
- * @param WC_Order $renewal_order The order which recorded the successful payment (to make up for the failed automatic payment).
346
  * @return void
347
  */
348
  public function update_failing_payment_method( $subscription, $renewal_order ) {
@@ -355,7 +359,7 @@ class WC_Stripe_Sepa_Subs_Compat extends WC_Gateway_Stripe_Sepa {
355
  * manually set up automatic recurring payments for a customer via the Edit Subscriptions screen in 2.0+.
356
  *
357
  * @since 2.5
358
- * @param array $payment_meta associative array of meta data required for automatic payments
359
  * @param WC_Subscription $subscription An instance of a subscription object
360
  * @return array
361
  */
@@ -370,18 +374,18 @@ class WC_Stripe_Sepa_Subs_Compat extends WC_Gateway_Stripe_Sepa {
370
  update_post_meta( $subscription->get_id(), '_stripe_source_id', $source_id );
371
  }
372
 
373
- $payment_meta[ $this->id ] = array(
374
- 'post_meta' => array(
375
- '_stripe_customer_id' => array(
376
  'value' => get_post_meta( $subscription->get_id(), '_stripe_customer_id', true ),
377
  'label' => 'Stripe Customer ID',
378
- ),
379
- '_stripe_source_id' => array(
380
  'value' => $source_id,
381
  'label' => 'Stripe Source ID',
382
- ),
383
- ),
384
- );
385
  return $payment_meta;
386
  }
387
 
@@ -391,7 +395,7 @@ class WC_Stripe_Sepa_Subs_Compat extends WC_Gateway_Stripe_Sepa {
391
  *
392
  * @since 2.5
393
  * @param string $payment_method_id The ID of the payment method to validate
394
- * @param array $payment_meta associative array of meta data required for automatic payments
395
  * @return array
396
  */
397
  public function validate_subscription_payment_meta( $payment_method_id, $payment_meta ) {
@@ -422,7 +426,7 @@ class WC_Stripe_Sepa_Subs_Compat extends WC_Gateway_Stripe_Sepa {
422
  * Render the payment method used for a subscription in the "My Subscriptions" table
423
  *
424
  * @since 1.7.5
425
- * @param string $payment_method_to_display the default payment method text to display
426
  * @param WC_Subscription $subscription the subscription details
427
  * @return string the subscription payment method
428
  */
16
  parent::__construct();
17
 
18
  if ( class_exists( 'WC_Subscriptions_Order' ) ) {
19
+ add_action( 'woocommerce_scheduled_subscription_payment_' . $this->id, [ $this, 'scheduled_subscription_payment' ], 10, 2 );
20
+ add_action( 'wcs_resubscribe_order_created', [ $this, 'delete_resubscribe_meta' ], 10 );
21
+ add_action( 'wcs_renewal_order_created', [ $this, 'delete_renewal_meta' ], 10 );
22
+ add_action( 'woocommerce_subscription_failing_payment_method_updated_stripe', [ $this, 'update_failing_payment_method' ], 10, 2 );
23
+ add_action( 'wc_stripe_sepa_payment_fields', [ $this, 'display_update_subs_payment_checkout' ] );
24
+ add_action( 'wc_stripe_add_payment_method_' . $this->id . '_success', [ $this, 'handle_add_payment_method_success' ], 10, 2 );
25
 
26
  // Display the credit card used for a subscription in the "My Subscriptions" table.
27
+ add_filter( 'woocommerce_my_subscriptions_payment_method', [ $this, 'maybe_render_subscription_payment_method' ], 10, 2 );
28
 
29
  // Allow store managers to manually set Stripe as the payment method on a subscription.
30
+ add_filter( 'woocommerce_subscription_payment_meta', [ $this, 'add_subscription_payment_meta' ], 10, 2 );
31
+ add_filter( 'woocommerce_subscription_validate_payment_meta', [ $this, 'validate_subscription_payment_meta' ], 10, 2 );
32
+ add_filter( 'wc_stripe_display_save_payment_method_checkbox', [ $this, 'maybe_hide_save_checkbox' ] );
33
  }
34
  }
35
 
50
 
51
  /**
52
  * Is $order_id a subscription?
53
+ *
54
+ * @param int $order_id
55
  * @return boolean
56
  */
57
  public function has_subscription( $order_id ) {
75
  * @since 4.1.11
76
  */
77
  public function display_update_subs_payment_checkout() {
78
+ $subs_statuses = apply_filters( 'wc_stripe_update_subs_payment_method_card_statuses', [ 'active' ] );
79
  if (
80
  apply_filters( 'wc_stripe_display_update_subs_payment_method_card_checkbox', true ) &&
81
  wcs_user_has_subscription( get_current_user_id(), '', $subs_statuses ) &&
85
  $id = sprintf( 'wc-%1$s-update-subs-payment-method-card', $this->id );
86
  woocommerce_form_field(
87
  $id,
88
+ [
89
  'type' => 'checkbox',
90
  'label' => $label,
91
  'default' => apply_filters( 'wc_stripe_save_to_subs_checked', false ),
92
+ ]
93
  );
94
  }
95
  }
104
  public function handle_add_payment_method_success( $source_id, $source_object ) {
105
  if ( isset( $_POST[ 'wc-' . $this->id . '-update-subs-payment-method-card' ] ) ) {
106
  $all_subs = wcs_get_users_subscriptions();
107
+ $subs_statuses = apply_filters( 'wc_stripe_update_subs_payment_method_card_statuses', [ 'active' ] );
108
  $stripe_customer = new WC_Stripe_Customer( get_current_user_id() );
109
 
110
  if ( ! empty( $all_subs ) ) {
113
  WC_Subscriptions_Change_Payment_Gateway::update_payment_method(
114
  $sub,
115
  $this->id,
116
+ [
117
+ 'post_meta' => [
118
+ '_stripe_source_id' => [ 'value' => $source_id ],
119
+ '_stripe_customer_id' => [ 'value' => $stripe_customer->get_id() ],
120
+ ],
121
+ ]
122
  );
123
  }
124
  }
143
  } elseif ( function_exists( 'wcs_order_contains_renewal' ) && wcs_order_contains_renewal( $order_id ) ) {
144
  $subscriptions = wcs_get_subscriptions_for_renewal_order( $order_id );
145
  } else {
146
+ $subscriptions = [];
147
  }
148
 
149
  foreach ( $subscriptions as $subscription ) {
155
 
156
  /**
157
  * Process the payment based on type.
158
+ *
159
  * @param int $order_id
160
  * @return array
161
  */
192
 
193
  do_action( 'wc_stripe_change_subs_payment_method_success', $prepared_source->source, $prepared_source );
194
 
195
+ return [
196
  'result' => 'success',
197
  'redirect' => $this->get_return_url( $subscription ),
198
+ ];
199
  } catch ( WC_Stripe_Exception $e ) {
200
  wc_add_notice( $e->getLocalizedMessage(), 'error' );
201
  WC_Stripe_Logger::log( 'Error: ' . $e->getMessage() );
218
  * @since 3.0
219
  * @since 4.0.4 Add third parameter flag to retry.
220
  * @since 4.1.0 Add fourth parameter to log previous errors.
221
+ * @param float $amount
222
+ * @param mixed $renewal_order
223
+ * @param bool $retry Should we retry the process?
224
  * @param object $previous_error
225
  */
226
  public function process_subscription_payment( $amount, $renewal_order, $retry = true, $previous_error = false ) {
251
 
252
  WC_Stripe_Logger::log( "Info: Begin processing subscription payment for order {$order_id} for the amount of {$amount}" );
253
 
254
+ /*
255
+ * If we're doing a retry and source is chargeable, we need to pass
256
  * a different idempotency key and retry for success.
257
  */
258
  if ( is_object( $source_object ) && empty( $source_object->error ) && $this->need_update_idempotency_key( $source_object, $previous_error ) ) {
259
+ add_filter( 'wc_stripe_idempotency_key', [ $this, 'change_idempotency_key' ], 10, 2 );
260
  }
261
 
262
  if ( ( $this->is_no_such_source_error( $previous_error ) || $this->is_no_linked_source_error( $previous_error ) ) && apply_filters( 'wc_stripe_use_default_customer_source', true ) ) {
318
 
319
  /**
320
  * Don't transfer Stripe customer/token meta to resubscribe orders.
321
+ *
322
  * @param int $resubscribe_order The order created for the customer to resubscribe to the old expired/cancelled subscription
323
  */
324
  public function delete_resubscribe_meta( $resubscribe_order ) {
331
 
332
  /**
333
  * Don't transfer Stripe fee/ID meta to renewal orders.
334
+ *
335
  * @param int $resubscribe_order The order created for the customer to resubscribe to the old expired/cancelled subscription
336
  */
337
  public function delete_renewal_meta( $renewal_order ) {
345
  * Update the customer_id for a subscription after using Stripe to complete a payment to make up for
346
  * an automatic renewal payment which previously failed.
347
  *
 
348
  * @param WC_Subscription $subscription The subscription for which the failing payment method relates.
349
+ * @param WC_Order $renewal_order The order which recorded the successful payment (to make up for the failed automatic payment).
350
  * @return void
351
  */
352
  public function update_failing_payment_method( $subscription, $renewal_order ) {
359
  * manually set up automatic recurring payments for a customer via the Edit Subscriptions screen in 2.0+.
360
  *
361
  * @since 2.5
362
+ * @param array $payment_meta associative array of meta data required for automatic payments
363
  * @param WC_Subscription $subscription An instance of a subscription object
364
  * @return array
365
  */
374
  update_post_meta( $subscription->get_id(), '_stripe_source_id', $source_id );
375
  }
376
 
377
+ $payment_meta[ $this->id ] = [
378
+ 'post_meta' => [
379
+ '_stripe_customer_id' => [
380
  'value' => get_post_meta( $subscription->get_id(), '_stripe_customer_id', true ),
381
  'label' => 'Stripe Customer ID',
382
+ ],
383
+ '_stripe_source_id' => [
384
  'value' => $source_id,
385
  'label' => 'Stripe Source ID',
386
+ ],
387
+ ],
388
+ ];
389
  return $payment_meta;
390
  }
391
 
395
  *
396
  * @since 2.5
397
  * @param string $payment_method_id The ID of the payment method to validate
398
+ * @param array $payment_meta associative array of meta data required for automatic payments
399
  * @return array
400
  */
401
  public function validate_subscription_payment_meta( $payment_method_id, $payment_meta ) {
426
  * Render the payment method used for a subscription in the "My Subscriptions" table
427
  *
428
  * @since 1.7.5
429
+ * @param string $payment_method_to_display the default payment method text to display
430
  * @param WC_Subscription $subscription the subscription details
431
  * @return string the subscription payment method
432
  */
includes/compat/class-wc-stripe-subs-compat.php CHANGED
@@ -16,21 +16,21 @@ class WC_Stripe_Subs_Compat extends WC_Gateway_Stripe {
16
  parent::__construct();
17
 
18
  if ( class_exists( 'WC_Subscriptions_Order' ) ) {
19
- add_action( 'woocommerce_scheduled_subscription_payment_' . $this->id, array( $this, 'scheduled_subscription_payment' ), 10, 2 );
20
- add_action( 'wcs_resubscribe_order_created', array( $this, 'delete_resubscribe_meta' ), 10 );
21
- add_action( 'wcs_renewal_order_created', array( $this, 'delete_renewal_meta' ), 10 );
22
- add_action( 'woocommerce_subscription_failing_payment_method_updated_stripe', array( $this, 'update_failing_payment_method' ), 10, 2 );
23
- add_action( 'wc_stripe_cards_payment_fields', array( $this, 'display_update_subs_payment_checkout' ) );
24
- add_action( 'wc_stripe_add_payment_method_' . $this->id . '_success', array( $this, 'handle_add_payment_method_success' ), 10, 2 );
25
- add_action( 'woocommerce_subscriptions_change_payment_before_submit', array( $this, 'differentiate_change_payment_method_form' ) );
26
 
27
  // display the credit card used for a subscription in the "My Subscriptions" table
28
- add_filter( 'woocommerce_my_subscriptions_payment_method', array( $this, 'maybe_render_subscription_payment_method' ), 10, 2 );
29
 
30
  // allow store managers to manually set Stripe as the payment method on a subscription
31
- add_filter( 'woocommerce_subscription_payment_meta', array( $this, 'add_subscription_payment_meta' ), 10, 2 );
32
- add_filter( 'woocommerce_subscription_validate_payment_meta', array( $this, 'validate_subscription_payment_meta' ), 10, 2 );
33
- add_filter( 'wc_stripe_display_save_payment_method_checkbox', array( $this, 'maybe_hide_save_checkbox' ) );
34
 
35
  /*
36
  * WC subscriptions hooks into the "template_redirect" hook with priority 100.
@@ -38,8 +38,8 @@ class WC_Stripe_Subs_Compat extends WC_Gateway_Stripe {
38
  * See: https://github.com/woocommerce/woocommerce-subscriptions/blob/99a75687e109b64cbc07af6e5518458a6305f366/includes/class-wcs-cart-renewal.php#L165
39
  * If we are in the "You just need to authorize SCA" flow, we don't want that redirection to happen.
40
  */
41
- add_action( 'template_redirect', array( $this, 'remove_order_pay_var' ), 99 );
42
- add_action( 'template_redirect', array( $this, 'restore_order_pay_var' ), 101 );
43
  }
44
  }
45
 
@@ -60,7 +60,8 @@ class WC_Stripe_Subs_Compat extends WC_Gateway_Stripe {
60
 
61
  /**
62
  * Is $order_id a subscription?
63
- * @param int $order_id
 
64
  * @return boolean
65
  */
66
  public function has_subscription( $order_id ) {
@@ -84,7 +85,7 @@ class WC_Stripe_Subs_Compat extends WC_Gateway_Stripe {
84
  * @since 4.1.11
85
  */
86
  public function display_update_subs_payment_checkout() {
87
- $subs_statuses = apply_filters( 'wc_stripe_update_subs_payment_method_card_statuses', array( 'active' ) );
88
  if (
89
  apply_filters( 'wc_stripe_display_update_subs_payment_method_card_checkbox', true ) &&
90
  wcs_user_has_subscription( get_current_user_id(), '', $subs_statuses ) &&
@@ -94,11 +95,11 @@ class WC_Stripe_Subs_Compat extends WC_Gateway_Stripe {
94
  $id = sprintf( 'wc-%1$s-update-subs-payment-method-card', $this->id );
95
  woocommerce_form_field(
96
  $id,
97
- array(
98
  'type' => 'checkbox',
99
  'label' => $label,
100
  'default' => apply_filters( 'wc_stripe_save_to_subs_checked', false ),
101
- )
102
  );
103
  }
104
  }
@@ -113,7 +114,7 @@ class WC_Stripe_Subs_Compat extends WC_Gateway_Stripe {
113
  public function handle_add_payment_method_success( $source_id, $source_object ) {
114
  if ( isset( $_POST[ 'wc-' . $this->id . '-update-subs-payment-method-card' ] ) ) {
115
  $all_subs = wcs_get_users_subscriptions();
116
- $subs_statuses = apply_filters( 'wc_stripe_update_subs_payment_method_card_statuses', array( 'active' ) );
117
  $stripe_customer = new WC_Stripe_Customer( get_current_user_id() );
118
 
119
  if ( ! empty( $all_subs ) ) {
@@ -122,12 +123,12 @@ class WC_Stripe_Subs_Compat extends WC_Gateway_Stripe {
122
  WC_Subscriptions_Change_Payment_Gateway::update_payment_method(
123
  $sub,
124
  $this->id,
125
- array(
126
- 'post_meta' => array(
127
- '_stripe_source_id' => array( 'value' => $source_id ),
128
- '_stripe_customer_id' => array( 'value' => $stripe_customer->get_id() ),
129
- ),
130
- )
131
  );
132
  }
133
  }
@@ -163,10 +164,10 @@ class WC_Stripe_Subs_Compat extends WC_Gateway_Stripe {
163
 
164
  do_action( 'wc_stripe_change_subs_payment_method_success', $prepared_source->source, $prepared_source );
165
 
166
- return array(
167
  'result' => 'success',
168
  'redirect' => $this->get_return_url( $subscription ),
169
- );
170
  } catch ( WC_Stripe_Exception $e ) {
171
  wc_add_notice( $e->getLocalizedMessage(), 'error' );
172
  WC_Stripe_Logger::log( 'Error: ' . $e->getMessage() );
@@ -175,6 +176,7 @@ class WC_Stripe_Subs_Compat extends WC_Gateway_Stripe {
175
 
176
  /**
177
  * Process the payment based on type.
 
178
  * @param int $order_id
179
  * @return array
180
  */
@@ -229,9 +231,9 @@ class WC_Stripe_Subs_Compat extends WC_Gateway_Stripe {
229
  * @since 3.0
230
  * @since 4.0.4 Add third parameter flag to retry.
231
  * @since 4.1.0 Add fourth parameter to log previous errors.
232
- * @param float $amount
233
- * @param mixed $renewal_order
234
- * @param bool $retry Should we retry the process?
235
  * @param object $previous_error
236
  */
237
  public function process_subscription_payment( $amount, $renewal_order, $retry = true, $previous_error = false ) {
@@ -253,28 +255,30 @@ class WC_Stripe_Subs_Compat extends WC_Gateway_Stripe {
253
  if ( isset( $_REQUEST['process_early_renewal'] ) ) { // wpcs: csrf ok.
254
  $response = parent::process_payment( $order_id, true, false, $previous_error, true );
255
 
256
- if( 'success' === $response['result'] && isset( $response['payment_intent_secret'] ) ) {
257
  $verification_url = add_query_arg(
258
- array(
259
  'order' => $order_id,
260
  'nonce' => wp_create_nonce( 'wc_stripe_confirm_pi' ),
261
- 'redirect_to' => remove_query_arg( array( 'process_early_renewal', 'subscription_id', 'wcs_nonce' ) ),
262
  'early_renewal' => true,
263
- ),
264
  WC_AJAX::get_endpoint( 'wc_stripe_verify_intent' )
265
  );
266
 
267
- echo wp_json_encode( array(
268
- 'stripe_sca_required' => true,
269
- 'intent_secret' => $response['payment_intent_secret'],
270
- 'redirect_url' => $verification_url,
271
- ) );
 
 
272
 
273
  exit;
274
  }
275
 
276
  // Hijack all other redirects in order to do the redirection in JavaScript.
277
- add_action( 'wp_redirect', array( $this, 'redirect_after_early_renewal' ), 100 );
278
 
279
  return;
280
  }
@@ -297,11 +301,12 @@ class WC_Stripe_Subs_Compat extends WC_Gateway_Stripe {
297
 
298
  WC_Stripe_Logger::log( "Info: Begin processing subscription payment for order {$order_id} for the amount of {$amount}" );
299
 
300
- /* If we're doing a retry and source is chargeable, we need to pass
 
301
  * a different idempotency key and retry for success.
302
  */
303
  if ( is_object( $source_object ) && empty( $source_object->error ) && $this->need_update_idempotency_key( $source_object, $previous_error ) ) {
304
- add_filter( 'wc_stripe_idempotency_key', array( $this, 'change_idempotency_key' ), 10, 2 );
305
  }
306
 
307
  if ( ( $this->is_no_such_source_error( $previous_error ) || $this->is_no_linked_source_error( $previous_error ) ) && apply_filters( 'wc_stripe_use_default_customer_source', true ) ) {
@@ -358,13 +363,14 @@ class WC_Stripe_Subs_Compat extends WC_Gateway_Stripe {
358
  $error_message = __( 'This transaction requires authentication.', 'woocommerce-gateway-stripe' );
359
  $renewal_order->add_order_note( $error_message );
360
 
361
- $charge = end( $response->error->payment_intent->charges->data );
362
- $id = $charge->id;
363
  $order_id = $renewal_order->get_id();
364
 
365
  $renewal_order->set_transaction_id( $id );
 
366
  $renewal_order->update_status( 'failed', sprintf( __( 'Stripe charge awaiting authentication by user: %s.', 'woocommerce-gateway-stripe' ), $id ) );
367
- if ( is_callable( array( $renewal_order, 'save' ) ) ) {
368
  $renewal_order->save();
369
  }
370
  } else {
@@ -402,7 +408,7 @@ class WC_Stripe_Subs_Compat extends WC_Gateway_Stripe {
402
  } elseif ( function_exists( 'wcs_order_contains_renewal' ) && wcs_order_contains_renewal( $order_id ) ) {
403
  $subscriptions = wcs_get_subscriptions_for_renewal_order( $order_id );
404
  } else {
405
- $subscriptions = array();
406
  }
407
 
408
  foreach ( $subscriptions as $subscription ) {
@@ -414,6 +420,7 @@ class WC_Stripe_Subs_Compat extends WC_Gateway_Stripe {
414
 
415
  /**
416
  * Don't transfer Stripe customer/token meta to resubscribe orders.
 
417
  * @param int $resubscribe_order The order created for the customer to resubscribe to the old expired/cancelled subscription
418
  */
419
  public function delete_resubscribe_meta( $resubscribe_order ) {
@@ -428,6 +435,7 @@ class WC_Stripe_Subs_Compat extends WC_Gateway_Stripe {
428
 
429
  /**
430
  * Don't transfer Stripe fee/ID meta to renewal orders.
 
431
  * @param int $resubscribe_order The order created for the customer to resubscribe to the old expired/cancelled subscription
432
  */
433
  public function delete_renewal_meta( $renewal_order ) {
@@ -444,9 +452,8 @@ class WC_Stripe_Subs_Compat extends WC_Gateway_Stripe {
444
  * Update the customer_id for a subscription after using Stripe to complete a payment to make up for
445
  * an automatic renewal payment which previously failed.
446
  *
447
- * @access public
448
  * @param WC_Subscription $subscription The subscription for which the failing payment method relates.
449
- * @param WC_Order $renewal_order The order which recorded the successful payment (to make up for the failed automatic payment).
450
  * @return void
451
  */
452
  public function update_failing_payment_method( $subscription, $renewal_order ) {
@@ -459,7 +466,7 @@ class WC_Stripe_Subs_Compat extends WC_Gateway_Stripe {
459
  * manually set up automatic recurring payments for a customer via the Edit Subscriptions screen in 2.0+.
460
  *
461
  * @since 2.5
462
- * @param array $payment_meta associative array of meta data required for automatic payments
463
  * @param WC_Subscription $subscription An instance of a subscription object
464
  * @return array
465
  */
@@ -476,18 +483,18 @@ class WC_Stripe_Subs_Compat extends WC_Gateway_Stripe {
476
  delete_post_meta( $subscription_id, '_stripe_card_id', $source_id );
477
  }
478
 
479
- $payment_meta[ $this->id ] = array(
480
- 'post_meta' => array(
481
- '_stripe_customer_id' => array(
482
  'value' => get_post_meta( $subscription_id, '_stripe_customer_id', true ),
483
  'label' => 'Stripe Customer ID',
484
- ),
485
- '_stripe_source_id' => array(
486
  'value' => $source_id,
487
  'label' => 'Stripe Source ID',
488
- ),
489
- ),
490
- );
491
 
492
  return $payment_meta;
493
  }
@@ -499,7 +506,7 @@ class WC_Stripe_Subs_Compat extends WC_Gateway_Stripe {
499
  * @since 2.5
500
  * @since 4.0.4 Stripe sourd id field no longer needs to be required.
501
  * @param string $payment_method_id The ID of the payment method to validate
502
- * @param array $payment_meta associative array of meta data required for automatic payments
503
  * @return array
504
  */
505
  public function validate_subscription_payment_meta( $payment_method_id, $payment_meta ) {
@@ -531,7 +538,7 @@ class WC_Stripe_Subs_Compat extends WC_Gateway_Stripe {
531
  * Render the payment method used for a subscription in the "My Subscriptions" table
532
  *
533
  * @since 1.7.5
534
- * @param string $payment_method_to_display the default payment method text to display
535
  * @param WC_Subscription $subscription the subscription details
536
  * @return string the subscription payment method
537
  */
@@ -621,7 +628,7 @@ class WC_Stripe_Subs_Compat extends WC_Gateway_Stripe {
621
  public function remove_order_pay_var() {
622
  global $wp;
623
  if ( isset( $_GET['wc-stripe-confirmation'] ) ) {
624
- $this->order_pay_var = $wp->query_vars['order-pay'];
625
  $wp->query_vars['order-pay'] = null;
626
  }
627
  }
@@ -667,6 +674,7 @@ class WC_Stripe_Subs_Compat extends WC_Gateway_Stripe {
667
  // Fail the payment attempt (order would be currently pending because of retry rules).
668
  $charge = end( $existing_intent->charges->data );
669
  $charge_id = $charge->id;
 
670
  $renewal_order->update_status( 'failed', sprintf( __( 'Stripe charge awaiting authentication by user: %s.', 'woocommerce-gateway-stripe' ), $charge_id ) );
671
 
672
  return true;
@@ -680,10 +688,10 @@ class WC_Stripe_Subs_Compat extends WC_Gateway_Stripe {
680
  */
681
  public function redirect_after_early_renewal( $url ) {
682
  echo wp_json_encode(
683
- array(
684
  'stripe_sca_required' => false,
685
  'redirect_url' => $url,
686
- )
687
  );
688
 
689
  exit;
@@ -715,7 +723,8 @@ class WC_Stripe_Subs_Compat extends WC_Gateway_Stripe {
715
  $order->delete( true );
716
  wc_add_notice( __( 'Payment authorization for the renewal order was unsuccessful, please try again.', 'woocommerce-gateway-stripe' ), 'error' );
717
  $renewal_url = wcs_get_early_renewal_url( wcs_get_subscription( $order->get_meta( '_subscription_renewal' ) ) );
718
- wp_redirect( $renewal_url ); exit;
 
719
  }
720
  }
721
  }
16
  parent::__construct();
17
 
18
  if ( class_exists( 'WC_Subscriptions_Order' ) ) {
19
+ add_action( 'woocommerce_scheduled_subscription_payment_' . $this->id, [ $this, 'scheduled_subscription_payment' ], 10, 2 );
20
+ add_action( 'wcs_resubscribe_order_created', [ $this, 'delete_resubscribe_meta' ], 10 );
21
+ add_action( 'wcs_renewal_order_created', [ $this, 'delete_renewal_meta' ], 10 );
22
+ add_action( 'woocommerce_subscription_failing_payment_method_updated_stripe', [ $this, 'update_failing_payment_method' ], 10, 2 );
23
+ add_action( 'wc_stripe_cards_payment_fields', [ $this, 'display_update_subs_payment_checkout' ] );
24
+ add_action( 'wc_stripe_add_payment_method_' . $this->id . '_success', [ $this, 'handle_add_payment_method_success' ], 10, 2 );
25
+ add_action( 'woocommerce_subscriptions_change_payment_before_submit', [ $this, 'differentiate_change_payment_method_form' ] );
26
 
27
  // display the credit card used for a subscription in the "My Subscriptions" table
28
+ add_filter( 'woocommerce_my_subscriptions_payment_method', [ $this, 'maybe_render_subscription_payment_method' ], 10, 2 );
29
 
30
  // allow store managers to manually set Stripe as the payment method on a subscription
31
+ add_filter( 'woocommerce_subscription_payment_meta', [ $this, 'add_subscription_payment_meta' ], 10, 2 );
32
+ add_filter( 'woocommerce_subscription_validate_payment_meta', [ $this, 'validate_subscription_payment_meta' ], 10, 2 );
33
+ add_filter( 'wc_stripe_display_save_payment_method_checkbox', [ $this, 'maybe_hide_save_checkbox' ] );
34
 
35
  /*
36
  * WC subscriptions hooks into the "template_redirect" hook with priority 100.
38
  * See: https://github.com/woocommerce/woocommerce-subscriptions/blob/99a75687e109b64cbc07af6e5518458a6305f366/includes/class-wcs-cart-renewal.php#L165
39
  * If we are in the "You just need to authorize SCA" flow, we don't want that redirection to happen.
40
  */
41
+ add_action( 'template_redirect', [ $this, 'remove_order_pay_var' ], 99 );
42
+ add_action( 'template_redirect', [ $this, 'restore_order_pay_var' ], 101 );
43
  }
44
  }
45
 
60
 
61
  /**
62
  * Is $order_id a subscription?
63
+ *
64
+ * @param int $order_id
65
  * @return boolean
66
  */
67
  public function has_subscription( $order_id ) {
85
  * @since 4.1.11
86
  */
87
  public function display_update_subs_payment_checkout() {
88
+ $subs_statuses = apply_filters( 'wc_stripe_update_subs_payment_method_card_statuses', [ 'active' ] );
89
  if (
90
  apply_filters( 'wc_stripe_display_update_subs_payment_method_card_checkbox', true ) &&
91
  wcs_user_has_subscription( get_current_user_id(), '', $subs_statuses ) &&
95
  $id = sprintf( 'wc-%1$s-update-subs-payment-method-card', $this->id );
96
  woocommerce_form_field(
97
  $id,
98
+ [
99
  'type' => 'checkbox',
100
  'label' => $label,
101
  'default' => apply_filters( 'wc_stripe_save_to_subs_checked', false ),
102
+ ]
103
  );
104
  }
105
  }
114
  public function handle_add_payment_method_success( $source_id, $source_object ) {
115
  if ( isset( $_POST[ 'wc-' . $this->id . '-update-subs-payment-method-card' ] ) ) {
116
  $all_subs = wcs_get_users_subscriptions();
117
+ $subs_statuses = apply_filters( 'wc_stripe_update_subs_payment_method_card_statuses', [ 'active' ] );
118
  $stripe_customer = new WC_Stripe_Customer( get_current_user_id() );
119
 
120
  if ( ! empty( $all_subs ) ) {
123
  WC_Subscriptions_Change_Payment_Gateway::update_payment_method(
124
  $sub,
125
  $this->id,
126
+ [
127
+ 'post_meta' => [
128
+ '_stripe_source_id' => [ 'value' => $source_id ],
129
+ '_stripe_customer_id' => [ 'value' => $stripe_customer->get_id() ],
130
+ ],
131
+ ]
132
  );
133
  }
134
  }
164
 
165
  do_action( 'wc_stripe_change_subs_payment_method_success', $prepared_source->source, $prepared_source );
166
 
167
+ return [
168
  'result' => 'success',
169
  'redirect' => $this->get_return_url( $subscription ),
170
+ ];
171
  } catch ( WC_Stripe_Exception $e ) {
172
  wc_add_notice( $e->getLocalizedMessage(), 'error' );
173
  WC_Stripe_Logger::log( 'Error: ' . $e->getMessage() );
176
 
177
  /**
178
  * Process the payment based on type.
179
+ *
180
  * @param int $order_id
181
  * @return array
182
  */
231
  * @since 3.0
232
  * @since 4.0.4 Add third parameter flag to retry.
233
  * @since 4.1.0 Add fourth parameter to log previous errors.
234
+ * @param float $amount
235
+ * @param mixed $renewal_order
236
+ * @param bool $retry Should we retry the process?
237
  * @param object $previous_error
238
  */
239
  public function process_subscription_payment( $amount, $renewal_order, $retry = true, $previous_error = false ) {
255
  if ( isset( $_REQUEST['process_early_renewal'] ) ) { // wpcs: csrf ok.
256
  $response = parent::process_payment( $order_id, true, false, $previous_error, true );
257
 
258
+ if ( 'success' === $response['result'] && isset( $response['payment_intent_secret'] ) ) {
259
  $verification_url = add_query_arg(
260
+ [
261
  'order' => $order_id,
262
  'nonce' => wp_create_nonce( 'wc_stripe_confirm_pi' ),
263
+ 'redirect_to' => remove_query_arg( [ 'process_early_renewal', 'subscription_id', 'wcs_nonce' ] ),
264
  'early_renewal' => true,
265
+ ],
266
  WC_AJAX::get_endpoint( 'wc_stripe_verify_intent' )
267
  );
268
 
269
+ echo wp_json_encode(
270
+ [
271
+ 'stripe_sca_required' => true,
272
+ 'intent_secret' => $response['payment_intent_secret'],
273
+ 'redirect_url' => $verification_url,
274
+ ]
275
+ );
276
 
277
  exit;
278
  }
279
 
280
  // Hijack all other redirects in order to do the redirection in JavaScript.
281
+ add_action( 'wp_redirect', [ $this, 'redirect_after_early_renewal' ], 100 );
282
 
283
  return;
284
  }
301
 
302
  WC_Stripe_Logger::log( "Info: Begin processing subscription payment for order {$order_id} for the amount of {$amount}" );
303
 
304
+ /*
305
+ If we're doing a retry and source is chargeable, we need to pass
306
  * a different idempotency key and retry for success.
307
  */
308
  if ( is_object( $source_object ) && empty( $source_object->error ) && $this->need_update_idempotency_key( $source_object, $previous_error ) ) {
309
+ add_filter( 'wc_stripe_idempotency_key', [ $this, 'change_idempotency_key' ], 10, 2 );
310
  }
311
 
312
  if ( ( $this->is_no_such_source_error( $previous_error ) || $this->is_no_linked_source_error( $previous_error ) ) && apply_filters( 'wc_stripe_use_default_customer_source', true ) ) {
363
  $error_message = __( 'This transaction requires authentication.', 'woocommerce-gateway-stripe' );
364
  $renewal_order->add_order_note( $error_message );
365
 
366
+ $charge = end( $response->error->payment_intent->charges->data );
367
+ $id = $charge->id;
368
  $order_id = $renewal_order->get_id();
369
 
370
  $renewal_order->set_transaction_id( $id );
371
+ /* translators: %s is the charge Id */
372
  $renewal_order->update_status( 'failed', sprintf( __( 'Stripe charge awaiting authentication by user: %s.', 'woocommerce-gateway-stripe' ), $id ) );
373
+ if ( is_callable( [ $renewal_order, 'save' ] ) ) {
374
  $renewal_order->save();
375
  }
376
  } else {
408
  } elseif ( function_exists( 'wcs_order_contains_renewal' ) && wcs_order_contains_renewal( $order_id ) ) {
409
  $subscriptions = wcs_get_subscriptions_for_renewal_order( $order_id );
410
  } else {
411
+ $subscriptions = [];
412
  }
413
 
414
  foreach ( $subscriptions as $subscription ) {
420
 
421
  /**
422
  * Don't transfer Stripe customer/token meta to resubscribe orders.
423
+ *
424
  * @param int $resubscribe_order The order created for the customer to resubscribe to the old expired/cancelled subscription
425
  */
426
  public function delete_resubscribe_meta( $resubscribe_order ) {
435
 
436
  /**
437
  * Don't transfer Stripe fee/ID meta to renewal orders.
438
+ *
439
  * @param int $resubscribe_order The order created for the customer to resubscribe to the old expired/cancelled subscription
440
  */
441
  public function delete_renewal_meta( $renewal_order ) {
452
  * Update the customer_id for a subscription after using Stripe to complete a payment to make up for
453
  * an automatic renewal payment which previously failed.
454
  *
 
455
  * @param WC_Subscription $subscription The subscription for which the failing payment method relates.
456
+ * @param WC_Order $renewal_order The order which recorded the successful payment (to make up for the failed automatic payment).
457
  * @return void
458
  */
459
  public function update_failing_payment_method( $subscription, $renewal_order ) {
466
  * manually set up automatic recurring payments for a customer via the Edit Subscriptions screen in 2.0+.
467
  *
468
  * @since 2.5
469
+ * @param array $payment_meta associative array of meta data required for automatic payments
470
  * @param WC_Subscription $subscription An instance of a subscription object
471
  * @return array
472
  */
483
  delete_post_meta( $subscription_id, '_stripe_card_id', $source_id );
484
  }
485
 
486
+ $payment_meta[ $this->id ] = [
487
+ 'post_meta' => [
488
+ '_stripe_customer_id' => [
489
  'value' => get_post_meta( $subscription_id, '_stripe_customer_id', true ),
490
  'label' => 'Stripe Customer ID',
491
+ ],
492
+ '_stripe_source_id' => [
493
  'value' => $source_id,
494
  'label' => 'Stripe Source ID',
495
+ ],
496
+ ],
497
+ ];
498
 
499
  return $payment_meta;
500
  }
506
  * @since 2.5
507
  * @since 4.0.4 Stripe sourd id field no longer needs to be required.
508
  * @param string $payment_method_id The ID of the payment method to validate
509
+ * @param array $payment_meta associative array of meta data required for automatic payments
510
  * @return array
511
  */
512
  public function validate_subscription_payment_meta( $payment_method_id, $payment_meta ) {
538
  * Render the payment method used for a subscription in the "My Subscriptions" table
539
  *
540
  * @since 1.7.5
541
+ * @param string $payment_method_to_display the default payment method text to display
542
  * @param WC_Subscription $subscription the subscription details
543
  * @return string the subscription payment method
544
  */
628
  public function remove_order_pay_var() {
629
  global $wp;
630
  if ( isset( $_GET['wc-stripe-confirmation'] ) ) {
631
+ $this->order_pay_var = $wp->query_vars['order-pay'];
632
  $wp->query_vars['order-pay'] = null;
633
  }
634
  }
674
  // Fail the payment attempt (order would be currently pending because of retry rules).
675
  $charge = end( $existing_intent->charges->data );
676
  $charge_id = $charge->id;
677
+ /* translators: %s is the stripe charge Id */
678
  $renewal_order->update_status( 'failed', sprintf( __( 'Stripe charge awaiting authentication by user: %s.', 'woocommerce-gateway-stripe' ), $charge_id ) );
679
 
680
  return true;
688
  */
689
  public function redirect_after_early_renewal( $url ) {
690
  echo wp_json_encode(
691
+ [
692
  'stripe_sca_required' => false,
693
  'redirect_url' => $url,
694
+ ]
695
  );
696
 
697
  exit;
723
  $order->delete( true );
724
  wc_add_notice( __( 'Payment authorization for the renewal order was unsuccessful, please try again.', 'woocommerce-gateway-stripe' ), 'error' );
725
  $renewal_url = wcs_get_early_renewal_url( wcs_get_subscription( $order->get_meta( '_subscription_renewal' ) ) );
726
+ wp_redirect( $renewal_url );
727
+ exit;
728
  }
729
  }
730
  }
includes/connect/class-wc-stripe-connect-api.php CHANGED
@@ -25,7 +25,7 @@ if ( ! class_exists( 'WC_Stripe_Connect_API' ) ) {
25
  public function get_stripe_oauth_init( $return_url ) {
26
 
27
  $current_user = wp_get_current_user();
28
- $business_data = array();
29
  $business_data['url'] = get_site_url();
30
  $business_data['business_name'] = html_entity_decode( get_bloginfo( 'name' ), ENT_QUOTES );
31
  $business_data['first_name'] = $current_user->user_firstname;
@@ -50,10 +50,10 @@ if ( ! class_exists( 'WC_Stripe_Connect_API' ) ) {
50
  $business_data['zip'] = '';
51
  }
52
 
53
- $request = array(
54
  'returnUrl' => $return_url,
55
  'businessData' => $business_data,
56
- );
57
 
58
  return $this->request( 'POST', '/stripe/oauth-init', $request );
59
  }
@@ -67,7 +67,7 @@ if ( ! class_exists( 'WC_Stripe_Connect_API' ) ) {
67
  */
68
  public function get_stripe_oauth_keys( $code ) {
69
 
70
- $request = array( 'code' => $code );
71
 
72
  return $this->request( 'POST', '/stripe/oauth-keys', $request );
73
  }
@@ -81,7 +81,7 @@ if ( ! class_exists( 'WC_Stripe_Connect_API' ) ) {
81
  *
82
  * @return array|WP_Error
83
  */
84
- protected function request( $method, $path, $body = array() ) {
85
 
86
  if ( ! is_array( $body ) ) {
87
  return new WP_Error(
@@ -95,7 +95,7 @@ if ( ! class_exists( 'WC_Stripe_Connect_API' ) ) {
95
  $url = trailingslashit( $url ) . ltrim( $path, '/' );
96
 
97
  // Add useful system information to requests that contain bodies.
98
- if ( in_array( $method, array( 'POST', 'PUT' ), true ) ) {
99
  $body = $this->request_body( $body );
100
  $body = wp_json_encode( apply_filters( 'wc_connect_api_client_body', $body ) );
101
 
@@ -114,14 +114,14 @@ if ( ! class_exists( 'WC_Stripe_Connect_API' ) ) {
114
 
115
  $http_timeout = 60; // 1 minute
116
  wc_set_time_limit( $http_timeout + 10 );
117
- $args = array(
118
  'headers' => $headers,
119
  'method' => $method,
120
  'body' => $body,
121
  'redirection' => 0,
122
  'compress' => true,
123
  'timeout' => $http_timeout,
124
- );
125
 
126
  $args = apply_filters( 'wc_connect_request_args', $args );
127
  $response = wp_remote_request( $url, $args );
@@ -194,18 +194,18 @@ if ( ! class_exists( 'WC_Stripe_Connect_API' ) ) {
194
  *
195
  * @return array
196
  */
197
- protected function request_body( $initial_body = array() ) {
198
 
199
- $default_body = array(
200
- 'settings' => array(),
201
- );
202
 
203
  $body = array_merge( $default_body, $initial_body );
204
 
205
  // Add interesting fields to the body of each request.
206
  $body['settings'] = wp_parse_args(
207
  $body['settings'],
208
- array(
209
  'base_city' => WC()->countries->get_base_city(),
210
  'base_country' => WC()->countries->get_base_country(),
211
  'base_state' => WC()->countries->get_base_state(),
@@ -214,7 +214,7 @@ if ( ! class_exists( 'WC_Stripe_Connect_API' ) ) {
214
  'stripe_version' => WC_STRIPE_VERSION,
215
  'wc_version' => WC()->version,
216
  'wp_version' => get_bloginfo( 'version' ),
217
- )
218
  );
219
 
220
  return $body;
@@ -227,7 +227,7 @@ if ( ! class_exists( 'WC_Stripe_Connect_API' ) ) {
227
  */
228
  protected function request_headers() {
229
 
230
- $headers = array();
231
  $locale = strtolower( str_replace( '_', '-', get_locale() ) );
232
  $locale_elements = explode( '-', $locale );
233
  $lang = $locale_elements[0];
25
  public function get_stripe_oauth_init( $return_url ) {
26
 
27
  $current_user = wp_get_current_user();
28
+ $business_data = [];
29
  $business_data['url'] = get_site_url();
30
  $business_data['business_name'] = html_entity_decode( get_bloginfo( 'name' ), ENT_QUOTES );
31
  $business_data['first_name'] = $current_user->user_firstname;
50
  $business_data['zip'] = '';
51
  }
52
 
53
+ $request = [
54
  'returnUrl' => $return_url,
55
  'businessData' => $business_data,
56
+ ];
57
 
58
  return $this->request( 'POST', '/stripe/oauth-init', $request );
59
  }
67
  */
68
  public function get_stripe_oauth_keys( $code ) {
69
 
70
+ $request = [ 'code' => $code ];
71
 
72
  return $this->request( 'POST', '/stripe/oauth-keys', $request );
73
  }
81
  *
82
  * @return array|WP_Error
83
  */
84
+ protected function request( $method, $path, $body = [] ) {
85
 
86
  if ( ! is_array( $body ) ) {
87
  return new WP_Error(
95
  $url = trailingslashit( $url ) . ltrim( $path, '/' );
96
 
97
  // Add useful system information to requests that contain bodies.
98
+ if ( in_array( $method, [ 'POST', 'PUT' ], true ) ) {
99
  $body = $this->request_body( $body );
100
  $body = wp_json_encode( apply_filters( 'wc_connect_api_client_body', $body ) );
101
 
114
 
115
  $http_timeout = 60; // 1 minute
116
  wc_set_time_limit( $http_timeout + 10 );
117
+ $args = [
118
  'headers' => $headers,
119
  'method' => $method,
120
  'body' => $body,
121
  'redirection' => 0,
122
  'compress' => true,
123
  'timeout' => $http_timeout,
124
+ ];
125
 
126
  $args = apply_filters( 'wc_connect_request_args', $args );
127
  $response = wp_remote_request( $url, $args );
194
  *
195
  * @return array
196
  */
197
+ protected function request_body( $initial_body = [] ) {
198
 
199
+ $default_body = [
200
+ 'settings' => [],
201
+ ];
202
 
203
  $body = array_merge( $default_body, $initial_body );
204
 
205
  // Add interesting fields to the body of each request.
206
  $body['settings'] = wp_parse_args(
207
  $body['settings'],
208
+ [
209
  'base_city' => WC()->countries->get_base_city(),
210
  'base_country' => WC()->countries->get_base_country(),
211
  'base_state' => WC()->countries->get_base_state(),
214
  'stripe_version' => WC_STRIPE_VERSION,
215
  'wc_version' => WC()->version,
216
  'wp_version' => get_bloginfo( 'version' ),
217
+ ]
218
  );
219
 
220
  return $body;
227
  */
228
  protected function request_headers() {
229
 
230
+ $headers = [];
231
  $locale = strtolower( str_replace( '_', '-', get_locale() ) );
232
  $locale_elements = explode( '-', $locale );
233
  $lang = $locale_elements[0];
includes/connect/class-wc-stripe-connect-rest-oauth-connect-controller.php CHANGED
@@ -56,14 +56,14 @@ if ( ! class_exists( 'WC_Stripe_Connect_REST_Oauth_Connect_Controller' ) ) {
56
  return new WP_Error(
57
  $response->get_error_code(),
58
  $response->get_error_message(),
59
- array( 'status' => 400 )
60
  );
61
  }
62
 
63
- return array(
64
  'success' => true,
65
  'account_id' => $response->accountId, // phpcs:ignore WordPress.NamingConventions.ValidVariableName.UsedPropertyNotSnakeCase
66
- );
67
  }
68
  }
69
  }
56
  return new WP_Error(
57
  $response->get_error_code(),
58
  $response->get_error_message(),
59
+ [ 'status' => 400 ]
60
  );
61
  }
62
 
63
+ return [
64
  'success' => true,
65
  'account_id' => $response->accountId, // phpcs:ignore WordPress.NamingConventions.ValidVariableName.UsedPropertyNotSnakeCase
66
+ ];
67
  }
68
  }
69
  }
includes/connect/class-wc-stripe-connect-rest-oauth-init-controller.php CHANGED
@@ -56,14 +56,14 @@ if ( ! class_exists( 'WC_Stripe_Connect_REST_Oauth_Init_Controller' ) ) {
56
  return new WP_Error(
57
  $response->get_error_code(),
58
  $response->get_error_message(),
59
- array( 'status' => 400 )
60
  );
61
  }
62
 
63
- return array(
64
  'success' => true,
65
  'oauthUrl' => $response,
66
- );
67
  }
68
  }
69
  }
56
  return new WP_Error(
57
  $response->get_error_code(),
58
  $response->get_error_message(),
59
+ [ 'status' => 400 ]
60
  );
61
  }
62
 
63
+ return [
64
  'success' => true,
65
  'oauthUrl' => $response,
66
+ ];
67
  }
68
  }
69
  }
includes/connect/class-wc-stripe-connect.php CHANGED
@@ -27,7 +27,7 @@ if ( ! class_exists( 'WC_Stripe_Connect' ) ) {
27
  public function __construct( WC_Stripe_Connect_API $api ) {
28
  $this->api = $api;
29
 
30
- add_action( 'admin_init', array( $this, 'maybe_handle_redirect' ) );
31
  }
32
 
33
  /**
@@ -86,24 +86,24 @@ if ( ! class_exists( 'WC_Stripe_Connect' ) ) {
86
  // redirect from oauth-init
87
  if ( isset( $_GET['wcs_stripe_code'], $_GET['wcs_stripe_state'] ) ) {
88
 
89
- $response = $this->connect_oauth( $_GET['wcs_stripe_state'], $_GET['wcs_stripe_code'] );
90
- wp_safe_redirect( remove_query_arg( array( 'wcs_stripe_state', 'wcs_stripe_code' ) ) );
91
  exit;
92
 
93
- // redirect from credentials reset
94
  } elseif ( isset( $_GET['reset_stripe_api_credentials'], $_GET['_wpnonce'] ) ) {
95
 
96
- if ( ! wp_verify_nonce( $_GET['_wpnonce'], 'reset_stripe_api_credentials' ) ) {
97
  die( __( 'You are not authorized to clear Stripe account keys.', 'woocommerce-gateway-stripe' ) );
98
  }
99
 
100
  $this->clear_stripe_keys();
101
  wp_safe_redirect(
102
  remove_query_arg(
103
- array(
104
  '_wpnonce',
105
  'reset_stripe_api_credentials',
106
- )
107
  )
108
  );
109
  exit;
@@ -127,7 +127,7 @@ if ( ! class_exists( 'WC_Stripe_Connect' ) ) {
127
  $is_test = false !== strpos( $result->publishableKey, '_test_' ); // phpcs:ignore WordPress.NamingConventions.ValidVariableName.UsedPropertyNotSnakeCase
128
  $prefix = $is_test ? 'test_' : '';
129
  $default_options = $this->get_default_stripe_config();
130
- $options = array_merge( $default_options, get_option( self::SETTINGS_OPTION, array() ) );
131
  $options['enabled'] = 'yes';
132
  $options['testmode'] = $is_test ? 'yes' : 'no';
133
  $options[ $prefix . 'publishable_key' ] = $result->publishableKey; // phpcs:ignore WordPress.NamingConventions.ValidVariableName.UsedPropertyNotSnakeCase
@@ -148,7 +148,7 @@ if ( ! class_exists( 'WC_Stripe_Connect' ) ) {
148
  */
149
  private function clear_stripe_keys() {
150
 
151
- $options = get_option( self::SETTINGS_OPTION, array() );
152
 
153
  if ( 'yes' === $options['testmode'] ) {
154
  $options['test_publishable_key'] = '';
@@ -171,7 +171,7 @@ if ( ! class_exists( 'WC_Stripe_Connect' ) ) {
171
  */
172
  private function get_default_stripe_config() {
173
 
174
- $result = array();
175
  $gateway = new WC_Gateway_Stripe();
176
  foreach ( $gateway->form_fields as $key => $value ) {
177
  if ( isset( $value['default'] ) ) {
@@ -184,7 +184,7 @@ if ( ! class_exists( 'WC_Stripe_Connect' ) ) {
184
 
185
  public function is_connected() {
186
 
187
- $options = get_option( self::SETTINGS_OPTION, array() );
188
 
189
  if ( isset( $options['testmode'] ) && 'yes' === $options['testmode'] ) {
190
  return isset( $options['test_publishable_key'], $options['test_secret_key'] ) && trim( $options['test_publishable_key'] ) && trim( $options['test_secret_key'] );
27
  public function __construct( WC_Stripe_Connect_API $api ) {
28
  $this->api = $api;
29
 
30
+ add_action( 'admin_init', [ $this, 'maybe_handle_redirect' ] );
31
  }
32
 
33
  /**
86
  // redirect from oauth-init
87
  if ( isset( $_GET['wcs_stripe_code'], $_GET['wcs_stripe_state'] ) ) {
88
 
89
+ $response = $this->connect_oauth( wc_clean( wp_unslash( $_GET['wcs_stripe_state'] ) ), wc_clean( wp_unslash( $_GET['wcs_stripe_code'] ) ) );
90
+ wp_safe_redirect( remove_query_arg( [ 'wcs_stripe_state', 'wcs_stripe_code' ] ) );
91
  exit;
92
 
93
+ // redirect from credentials reset
94
  } elseif ( isset( $_GET['reset_stripe_api_credentials'], $_GET['_wpnonce'] ) ) {
95
 
96
+ if ( ! wp_verify_nonce( wc_clean( wp_unslash( $_GET['_wpnonce'] ) ), 'reset_stripe_api_credentials' ) ) {
97
  die( __( 'You are not authorized to clear Stripe account keys.', 'woocommerce-gateway-stripe' ) );
98
  }
99
 
100
  $this->clear_stripe_keys();
101
  wp_safe_redirect(
102
  remove_query_arg(
103
+ [
104
  '_wpnonce',
105
  'reset_stripe_api_credentials',
106
+ ]
107
  )
108
  );
109
  exit;
127
  $is_test = false !== strpos( $result->publishableKey, '_test_' ); // phpcs:ignore WordPress.NamingConventions.ValidVariableName.UsedPropertyNotSnakeCase
128
  $prefix = $is_test ? 'test_' : '';
129
  $default_options = $this->get_default_stripe_config();
130
+ $options = array_merge( $default_options, get_option( self::SETTINGS_OPTION, [] ) );
131
  $options['enabled'] = 'yes';
132
  $options['testmode'] = $is_test ? 'yes' : 'no';
133
  $options[ $prefix . 'publishable_key' ] = $result->publishableKey; // phpcs:ignore WordPress.NamingConventions.ValidVariableName.UsedPropertyNotSnakeCase
148
  */
149
  private function clear_stripe_keys() {
150
 
151
+ $options = get_option( self::SETTINGS_OPTION, [] );
152
 
153
  if ( 'yes' === $options['testmode'] ) {
154
  $options['test_publishable_key'] = '';
171
  */
172
  private function get_default_stripe_config() {
173
 
174
+ $result = [];
175
  $gateway = new WC_Gateway_Stripe();
176
  foreach ( $gateway->form_fields as $key => $value ) {
177
  if ( isset( $value['default'] ) ) {
184
 
185
  public function is_connected() {
186
 
187
+ $options = get_option( self::SETTINGS_OPTION, [] );
188
 
189
  if ( isset( $options['testmode'] ) && 'yes' === $options['testmode'] ) {
190
  return isset( $options['test_publishable_key'], $options['test_secret_key'] ) && trim( $options['test_publishable_key'] ) && trim( $options['test_secret_key'] );
includes/payment-methods/class-wc-gateway-stripe-alipay.php CHANGED
@@ -13,9 +13,10 @@ if ( ! defined( 'ABSPATH' ) ) {
13
  class WC_Gateway_Stripe_Alipay extends WC_Stripe_Payment_Gateway {
14
  /**
15
  * Notices (array)
 
16
  * @var array
17
  */
18
- public $notices = array();
19
 
20
  /**
21
  * Is test mode active?
@@ -60,10 +61,10 @@ class WC_Gateway_Stripe_Alipay extends WC_Stripe_Payment_Gateway {
60
  $this->method_title = __( 'Stripe Alipay', 'woocommerce-gateway-stripe' );
61
  /* translators: link */
62
  $this->method_description = sprintf( __( 'All other general Stripe settings can be adjusted <a href="%s">here</a>.', 'woocommerce-gateway-stripe' ), admin_url( 'admin.php?page=wc-settings&tab=checkout&section=stripe' ) );
63
- $this->supports = array(
64
  'products',
65
  'refunds',
66
- );
67
 
68
  // Load the form fields.
69
  $this->init_form_fields();
@@ -86,8 +87,8 @@ class WC_Gateway_Stripe_Alipay extends WC_Stripe_Payment_Gateway {
86
  $this->secret_key = ! empty( $main_settings['test_secret_key'] ) ? $main_settings['test_secret_key'] : '';
87
  }
88
 
89
- add_action( 'woocommerce_update_options_payment_gateways_' . $this->id, array( $this, 'process_admin_options' ) );
90
- add_action( 'wp_enqueue_scripts', array( $this, 'payment_scripts' ) );
91
  }
92
 
93
  /**
@@ -100,7 +101,7 @@ class WC_Gateway_Stripe_Alipay extends WC_Stripe_Payment_Gateway {
100
  public function get_supported_currency() {
101
  return apply_filters(
102
  'wc_stripe_alipay_supported_currencies',
103
- array(
104
  'EUR',
105
  'AUD',
106
  'CAD',
@@ -111,7 +112,7 @@ class WC_Gateway_Stripe_Alipay extends WC_Stripe_Payment_Gateway {
111
  'NZD',
112
  'SGD',
113
  'USD',
114
- )
115
  );
116
  }
117
 
@@ -166,7 +167,7 @@ class WC_Gateway_Stripe_Alipay extends WC_Stripe_Payment_Gateway {
166
  * Initialize Gateway Settings Form Fields.
167
  */
168
  public function init_form_fields() {
169
- $this->form_fields = require( WC_STRIPE_PLUGIN_PATH . '/includes/admin/stripe-alipay-settings.php' );
170
  }
171
 
172
  /**
@@ -214,12 +215,12 @@ class WC_Gateway_Stripe_Alipay extends WC_Stripe_Payment_Gateway {
214
  public function create_source( $order ) {
215
  $currency = $order->get_currency();
216
  $return_url = $this->get_stripe_return_url( $order );
217
- $post_data = array();
218
  $post_data['amount'] = WC_Stripe_Helper::get_stripe_amount( $order->get_total(), $currency );
219
  $post_data['currency'] = strtolower( $currency );
220
  $post_data['type'] = 'alipay';
221
  $post_data['owner'] = $this->get_owner_details( $order );
222
- $post_data['redirect'] = array( 'return_url' => $return_url );
223
 
224
  if ( ! empty( $this->statement_descriptor ) ) {
225
  $post_data['statement_descriptor'] = WC_Stripe_Helper::clean_statement_descriptor( $this->statement_descriptor );
@@ -270,26 +271,26 @@ class WC_Gateway_Stripe_Alipay extends WC_Stripe_Payment_Gateway {
270
 
271
  WC_Stripe_Logger::log( 'Info: Redirecting to Alipay...' );
272
 
273
- return array(
274
  'result' => 'success',
275
  'redirect' => esc_url_raw( $response->redirect->url ),
276
- );
277
  } catch ( WC_Stripe_Exception $e ) {
278
  wc_add_notice( $e->getLocalizedMessage(), 'error' );
279
  WC_Stripe_Logger::log( 'Error: ' . $e->getMessage() );
280
 
281
  do_action( 'wc_gateway_stripe_process_payment_error', $e, $order );
282
 
283
- $statuses = array( 'pending', 'failed' );
284
 
285
  if ( $order->has_status( $statuses ) ) {
286
  $this->send_failed_order_email( $order_id );
287
  }
288
 
289
- return array(
290
  'result' => 'fail',
291
  'redirect' => '',
292
- );
293
  }
294
  }
295
  }
13
  class WC_Gateway_Stripe_Alipay extends WC_Stripe_Payment_Gateway {
14
  /**
15
  * Notices (array)
16
+ *
17
  * @var array
18
  */
19
+ public $notices = [];
20
 
21
  /**
22
  * Is test mode active?
61
  $this->method_title = __( 'Stripe Alipay', 'woocommerce-gateway-stripe' );
62
  /* translators: link */
63
  $this->method_description = sprintf( __( 'All other general Stripe settings can be adjusted <a href="%s">here</a>.', 'woocommerce-gateway-stripe' ), admin_url( 'admin.php?page=wc-settings&tab=checkout&section=stripe' ) );
64
+ $this->supports = [
65
  'products',
66
  'refunds',
67
+ ];
68
 
69
  // Load the form fields.
70
  $this->init_form_fields();
87
  $this->secret_key = ! empty( $main_settings['test_secret_key'] ) ? $main_settings['test_secret_key'] : '';
88
  }
89
 
90
+ add_action( 'woocommerce_update_options_payment_gateways_' . $this->id, [ $this, 'process_admin_options' ] );
91
+ add_action( 'wp_enqueue_scripts', [ $this, 'payment_scripts' ] );
92
  }
93
 
94
  /**
101
  public function get_supported_currency() {
102
  return apply_filters(
103
  'wc_stripe_alipay_supported_currencies',
104
+ [
105
  'EUR',
106
  'AUD',
107
  'CAD',
112
  'NZD',
113
  'SGD',
114
  'USD',
115
+ ]
116
  );
117
  }
118
 
167
  * Initialize Gateway Settings Form Fields.
168
  */
169
  public function init_form_fields() {
170
+ $this->form_fields = require WC_STRIPE_PLUGIN_PATH . '/includes/admin/stripe-alipay-settings.php';
171
  }
172
 
173
  /**
215
  public function create_source( $order ) {
216
  $currency = $order->get_currency();
217
  $return_url = $this->get_stripe_return_url( $order );
218
+ $post_data = [];
219
  $post_data['amount'] = WC_Stripe_Helper::get_stripe_amount( $order->get_total(), $currency );
220
  $post_data['currency'] = strtolower( $currency );
221
  $post_data['type'] = 'alipay';
222
  $post_data['owner'] = $this->get_owner_details( $order );
223
+ $post_data['redirect'] = [ 'return_url' => $return_url ];
224
 
225
  if ( ! empty( $this->statement_descriptor ) ) {
226
  $post_data['statement_descriptor'] = WC_Stripe_Helper::clean_statement_descriptor( $this->statement_descriptor );
271
 
272
  WC_Stripe_Logger::log( 'Info: Redirecting to Alipay...' );
273
 
274
+ return [
275
  'result' => 'success',
276
  'redirect' => esc_url_raw( $response->redirect->url ),
277
+ ];
278
  } catch ( WC_Stripe_Exception $e ) {
279
  wc_add_notice( $e->getLocalizedMessage(), 'error' );
280
  WC_Stripe_Logger::log( 'Error: ' . $e->getMessage() );
281
 
282
  do_action( 'wc_gateway_stripe_process_payment_error', $e, $order );
283
 
284
+ $statuses = [ 'pending', 'failed' ];
285
 
286
  if ( $order->has_status( $statuses ) ) {
287
  $this->send_failed_order_email( $order_id );
288
  }
289
 
290
+ return [
291
  'result' => 'fail',
292
  'redirect' => '',
293
+ ];
294
  }
295
  }
296
  }
includes/payment-methods/class-wc-gateway-stripe-bancontact.php CHANGED
@@ -13,9 +13,10 @@ if ( ! defined( 'ABSPATH' ) ) {
13
  class WC_Gateway_Stripe_Bancontact extends WC_Stripe_Payment_Gateway {
14
  /**
15
  * Notices (array)
 
16
  * @var array
17
  */
18
- public $notices = array();
19
 
20
  /**
21
  * Is test mode active?
@@ -60,10 +61,10 @@ class WC_Gateway_Stripe_Bancontact extends WC_Stripe_Payment_Gateway {
60
  $this->method_title = __( 'Stripe Bancontact', 'woocommerce-gateway-stripe' );
61
  /* translators: link */
62
  $this->method_description = sprintf( __( 'All other general Stripe settings can be adjusted <a href="%s">here</a>.', 'woocommerce-gateway-stripe' ), admin_url( 'admin.php?page=wc-settings&tab=checkout&section=stripe' ) );
63
- $this->supports = array(
64
  'products',
65
  'refunds',
66
- );
67
 
68
  // Load the form fields.
69
  $this->init_form_fields();
@@ -86,8 +87,8 @@ class WC_Gateway_Stripe_Bancontact extends WC_Stripe_Payment_Gateway {
86
  $this->secret_key = ! empty( $main_settings['test_secret_key'] ) ? $main_settings['test_secret_key'] : '';
87
  }
88
 
89
- add_action( 'woocommerce_update_options_payment_gateways_' . $this->id, array( $this, 'process_admin_options' ) );
90
- add_action( 'wp_enqueue_scripts', array( $this, 'payment_scripts' ) );
91
  }
92
 
93
  /**
@@ -100,9 +101,9 @@ class WC_Gateway_Stripe_Bancontact extends WC_Stripe_Payment_Gateway {
100
  public function get_supported_currency() {
101
  return apply_filters(
102
  'wc_stripe_bancontact_supported_currencies',
103
- array(
104
  'EUR',
105
- )
106
  );
107
  }
108
 
@@ -139,11 +140,7 @@ class WC_Gateway_Stripe_Bancontact extends WC_Stripe_Payment_Gateway {
139
  }
140
 
141
  /**
142
- * payment_scripts function.
143
- *
144
  * Outputs scripts used for stripe payment
145
- *
146
- * @access public
147
  */
148
  public function payment_scripts() {
149
  if ( ! is_cart() && ! is_checkout() && ! isset( $_GET['pay_for_order'] ) && ! is_add_payment_method_page() ) {
@@ -158,7 +155,7 @@ class WC_Gateway_Stripe_Bancontact extends WC_Stripe_Payment_Gateway {
158
  * Initialize Gateway Settings Form Fields.
159
  */
160
  public function init_form_fields() {
161
- $this->form_fields = require( WC_STRIPE_PLUGIN_PATH . '/includes/admin/stripe-bancontact-settings.php' );
162
  }
163
 
164
  /**
@@ -206,13 +203,13 @@ class WC_Gateway_Stripe_Bancontact extends WC_Stripe_Payment_Gateway {
206
  public function create_source( $order ) {
207
  $currency = $order->get_currency();
208
  $return_url = $this->get_stripe_return_url( $order );
209
- $post_data = array();
210
  $post_data['amount'] = WC_Stripe_Helper::get_stripe_amount( $order->get_total(), $currency );
211
  $post_data['currency'] = strtolower( $currency );
212
  $post_data['type'] = 'bancontact';
213
  $post_data['owner'] = $this->get_owner_details( $order );
214
- $post_data['redirect'] = array( 'return_url' => $return_url );
215
- $post_data['bancontact'] = array( 'preferred_language' => $this->get_locale() );
216
 
217
  if ( ! empty( $this->statement_descriptor ) ) {
218
  $post_data['statement_descriptor'] = WC_Stripe_Helper::clean_statement_descriptor( $this->statement_descriptor );
@@ -263,24 +260,24 @@ class WC_Gateway_Stripe_Bancontact extends WC_Stripe_Payment_Gateway {
263
 
264
  WC_Stripe_Logger::log( 'Info: Redirecting to Bancontact...' );
265
 
266
- return array(
267
  'result' => 'success',
268
  'redirect' => esc_url_raw( $response->redirect->url ),
269
- );
270
  } catch ( WC_Stripe_Exception $e ) {
271
  wc_add_notice( $e->getLocalizedMessage(), 'error' );
272
  WC_Stripe_Logger::log( 'Error: ' . $e->getMessage() );
273
 
274
  do_action( 'wc_gateway_stripe_process_payment_error', $e, $order );
275
 
276
- if ( $order->has_status( array( 'pending', 'failed' ) ) ) {
277
  $this->send_failed_order_email( $order_id );
278
  }
279
 
280
- return array(
281
  'result' => 'fail',
282
  'redirect' => '',
283
- );
284
  }
285
  }
286
  }
13
  class WC_Gateway_Stripe_Bancontact extends WC_Stripe_Payment_Gateway {
14
  /**
15
  * Notices (array)
16
+ *
17
  * @var array
18
  */
19
+ public $notices = [];
20
 
21
  /**
22
  * Is test mode active?
61
  $this->method_title = __( 'Stripe Bancontact', 'woocommerce-gateway-stripe' );
62
  /* translators: link */
63
  $this->method_description = sprintf( __( 'All other general Stripe settings can be adjusted <a href="%s">here</a>.', 'woocommerce-gateway-stripe' ), admin_url( 'admin.php?page=wc-settings&tab=checkout&section=stripe' ) );
64
+ $this->supports = [
65
  'products',
66
  'refunds',
67
+ ];
68
 
69
  // Load the form fields.
70
  $this->init_form_fields();
87
  $this->secret_key = ! empty( $main_settings['test_secret_key'] ) ? $main_settings['test_secret_key'] : '';
88
  }
89
 
90
+ add_action( 'woocommerce_update_options_payment_gateways_' . $this->id, [ $this, 'process_admin_options' ] );
91
+ add_action( 'wp_enqueue_scripts', [ $this, 'payment_scripts' ] );
92
  }
93
 
94
  /**
101
  public function get_supported_currency() {
102
  return apply_filters(
103
  'wc_stripe_bancontact_supported_currencies',
104
+ [
105
  'EUR',
106
+ ]
107
  );
108
  }
109
 
140
  }
141
 
142
  /**
 
 
143
  * Outputs scripts used for stripe payment
 
 
144
  */
145
  public function payment_scripts() {
146
  if ( ! is_cart() && ! is_checkout() && ! isset( $_GET['pay_for_order'] ) && ! is_add_payment_method_page() ) {
155
  * Initialize Gateway Settings Form Fields.
156
  */
157
  public function init_form_fields() {
158
+ $this->form_fields = require WC_STRIPE_PLUGIN_PATH . '/includes/admin/stripe-bancontact-settings.php';
159
  }
160
 
161
  /**
203
  public function create_source( $order ) {
204
  $currency = $order->get_currency();
205
  $return_url = $this->get_stripe_return_url( $order );
206
+ $post_data = [];
207
  $post_data['amount'] = WC_Stripe_Helper::get_stripe_amount( $order->get_total(), $currency );
208
  $post_data['currency'] = strtolower( $currency );
209
  $post_data['type'] = 'bancontact';
210
  $post_data['owner'] = $this->get_owner_details( $order );
211
+ $post_data['redirect'] = [ 'return_url' => $return_url ];
212
+ $post_data['bancontact'] = [ 'preferred_language' => $this->get_locale() ];
213
 
214
  if ( ! empty( $this->statement_descriptor ) ) {
215
  $post_data['statement_descriptor'] = WC_Stripe_Helper::clean_statement_descriptor( $this->statement_descriptor );
260
 
261
  WC_Stripe_Logger::log( 'Info: Redirecting to Bancontact...' );
262
 
263
+ return [
264
  'result' => 'success',
265
  'redirect' => esc_url_raw( $response->redirect->url ),
266
+ ];
267
  } catch ( WC_Stripe_Exception $e ) {
268
  wc_add_notice( $e->getLocalizedMessage(), 'error' );
269
  WC_Stripe_Logger::log( 'Error: ' . $e->getMessage() );
270
 
271
  do_action( 'wc_gateway_stripe_process_payment_error', $e, $order );
272
 
273
+ if ( $order->has_status( [ 'pending', 'failed' ] ) ) {
274
  $this->send_failed_order_email( $order_id );
275
  }
276
 
277
+ return [
278
  'result' => 'fail',
279
  'redirect' => '',
280
+ ];
281
  }
282
  }
283
  }
includes/payment-methods/class-wc-gateway-stripe-eps.php CHANGED
@@ -13,9 +13,10 @@ if ( ! defined( 'ABSPATH' ) ) {
13
  class WC_Gateway_Stripe_Eps extends WC_Stripe_Payment_Gateway {
14
  /**
15
  * Notices (array)
 
16
  * @var array
17
  */
18
- public $notices = array();
19
 
20
  /**
21
  * Is test mode active?
@@ -60,10 +61,10 @@ class WC_Gateway_Stripe_Eps extends WC_Stripe_Payment_Gateway {
60
  $this->method_title = __( 'Stripe EPS', 'woocommerce-gateway-stripe' );
61
  /* translators: link */
62
  $this->method_description = sprintf( __( 'All other general Stripe settings can be adjusted <a href="%s">here</a>.', 'woocommerce-gateway-stripe' ), admin_url( 'admin.php?page=wc-settings&tab=checkout&section=stripe' ) );
63
- $this->supports = array(
64
  'products',
65
  'refunds',
66
- );
67
 
68
  // Load the form fields.
69
  $this->init_form_fields();
@@ -86,8 +87,8 @@ class WC_Gateway_Stripe_Eps extends WC_Stripe_Payment_Gateway {
86
  $this->secret_key = ! empty( $main_settings['test_secret_key'] ) ? $main_settings['test_secret_key'] : '';
87
  }
88
 
89
- add_action( 'woocommerce_update_options_payment_gateways_' . $this->id, array( $this, 'process_admin_options' ) );
90
- add_action( 'wp_enqueue_scripts', array( $this, 'payment_scripts' ) );
91
  }
92
 
93
  /**
@@ -100,9 +101,9 @@ class WC_Gateway_Stripe_Eps extends WC_Stripe_Payment_Gateway {
100
  public function get_supported_currency() {
101
  return apply_filters(
102
  'wc_stripe_eps_supported_currencies',
103
- array(
104
  'EUR',
105
- )
106
  );
107
  }
108
 
@@ -139,11 +140,7 @@ class WC_Gateway_Stripe_Eps extends WC_Stripe_Payment_Gateway {
139
  }
140
 
141
  /**
142
- * payment_scripts function.
143
- *
144
  * Outputs scripts used for stripe payment
145
- *
146
- * @access public
147
  */
148
  public function payment_scripts() {
149
  if ( ! is_cart() && ! is_checkout() && ! isset( $_GET['pay_for_order'] ) && ! is_add_payment_method_page() ) {
@@ -158,7 +155,7 @@ class WC_Gateway_Stripe_Eps extends WC_Stripe_Payment_Gateway {
158
  * Initialize Gateway Settings Form Fields.
159
  */
160
  public function init_form_fields() {
161
- $this->form_fields = require( WC_STRIPE_PLUGIN_PATH . '/includes/admin/stripe-eps-settings.php' );
162
  }
163
 
164
  /**
@@ -206,12 +203,12 @@ class WC_Gateway_Stripe_Eps extends WC_Stripe_Payment_Gateway {
206
  public function create_source( $order ) {
207
  $currency = $order->get_currency();
208
  $return_url = $this->get_stripe_return_url( $order );
209
- $post_data = array();
210
  $post_data['amount'] = WC_Stripe_Helper::get_stripe_amount( $order->get_total(), $currency );
211
  $post_data['currency'] = strtolower( $currency );
212
  $post_data['type'] = 'eps';
213
  $post_data['owner'] = $this->get_owner_details( $order );
214
- $post_data['redirect'] = array( 'return_url' => $return_url );
215
 
216
  if ( ! empty( $this->statement_descriptor ) ) {
217
  $post_data['statement_descriptor'] = WC_Stripe_Helper::clean_statement_descriptor( $this->statement_descriptor );
@@ -262,24 +259,24 @@ class WC_Gateway_Stripe_Eps extends WC_Stripe_Payment_Gateway {
262
 
263
  WC_Stripe_Logger::log( 'Info: Redirecting to EPS...' );
264
 
265
- return array(
266
  'result' => 'success',
267
  'redirect' => esc_url_raw( $response->redirect->url ),
268
- );
269
  } catch ( Exception $e ) {
270
  wc_add_notice( $e->getMessage(), 'error' );
271
  WC_Stripe_Logger::log( 'Error: ' . $e->getMessage() );
272
 
273
  do_action( 'wc_gateway_stripe_process_payment_error', $e, $order );
274
 
275
- if ( $order->has_status( array( 'pending', 'failed' ) ) ) {
276
  $this->send_failed_order_email( $order_id );
277
  }
278
 
279
- return array(
280
  'result' => 'fail',
281
  'redirect' => '',
282
- );
283
  }
284
  }
285
  }
13
  class WC_Gateway_Stripe_Eps extends WC_Stripe_Payment_Gateway {
14
  /**
15
  * Notices (array)
16
+ *
17
  * @var array
18
  */
19
+ public $notices = [];
20
 
21
  /**
22
  * Is test mode active?
61
  $this->method_title = __( 'Stripe EPS', 'woocommerce-gateway-stripe' );
62
  /* translators: link */
63
  $this->method_description = sprintf( __( 'All other general Stripe settings can be adjusted <a href="%s">here</a>.', 'woocommerce-gateway-stripe' ), admin_url( 'admin.php?page=wc-settings&tab=checkout&section=stripe' ) );
64
+ $this->supports = [
65
  'products',
66
  'refunds',
67
+ ];
68
 
69
  // Load the form fields.
70
  $this->init_form_fields();
87
  $this->secret_key = ! empty( $main_settings['test_secret_key'] ) ? $main_settings['test_secret_key'] : '';
88
  }
89
 
90
+ add_action( 'woocommerce_update_options_payment_gateways_' . $this->id, [ $this, 'process_admin_options' ] );
91
+ add_action( 'wp_enqueue_scripts', [ $this, 'payment_scripts' ] );
92
  }
93
 
94
  /**
101
  public function get_supported_currency() {
102
  return apply_filters(
103
  'wc_stripe_eps_supported_currencies',
104
+ [
105
  'EUR',
106
+ ]
107
  );
108
  }
109
 
140
  }
141
 
142
  /**
 
 
143
  * Outputs scripts used for stripe payment
 
 
144
  */
145
  public function payment_scripts() {
146
  if ( ! is_cart() && ! is_checkout() && ! isset( $_GET['pay_for_order'] ) && ! is_add_payment_method_page() ) {
155
  * Initialize Gateway Settings Form Fields.
156
  */
157
  public function init_form_fields() {
158
+ $this->form_fields = require WC_STRIPE_PLUGIN_PATH . '/includes/admin/stripe-eps-settings.php';
159
  }
160
 
161
  /**
203
  public function create_source( $order ) {
204
  $currency = $order->get_currency();
205
  $return_url = $this->get_stripe_return_url( $order );
206
+ $post_data = [];
207
  $post_data['amount'] = WC_Stripe_Helper::get_stripe_amount( $order->get_total(), $currency );
208
  $post_data['currency'] = strtolower( $currency );
209
  $post_data['type'] = 'eps';
210
  $post_data['owner'] = $this->get_owner_details( $order );
211
+ $post_data['redirect'] = [ 'return_url' => $return_url ];
212
 
213
  if ( ! empty( $this->statement_descriptor ) ) {
214
  $post_data['statement_descriptor'] = WC_Stripe_Helper::clean_statement_descriptor( $this->statement_descriptor );
259
 
260
  WC_Stripe_Logger::log( 'Info: Redirecting to EPS...' );
261
 
262
+ return [
263
  'result' => 'success',
264
  'redirect' => esc_url_raw( $response->redirect->url ),
265
+ ];
266
  } catch ( Exception $e ) {
267
  wc_add_notice( $e->getMessage(), 'error' );
268
  WC_Stripe_Logger::log( 'Error: ' . $e->getMessage() );
269
 
270
  do_action( 'wc_gateway_stripe_process_payment_error', $e, $order );
271
 
272
+ if ( $order->has_status( [ 'pending', 'failed' ] ) ) {
273
  $this->send_failed_order_email( $order_id );
274
  }
275
 
276
+ return [
277
  'result' => 'fail',
278
  'redirect' => '',
279
+ ];
280
  }
281
  }
282
  }
includes/payment-methods/class-wc-gateway-stripe-giropay.php CHANGED
@@ -13,9 +13,10 @@ if ( ! defined( 'ABSPATH' ) ) {
13
  class WC_Gateway_Stripe_Giropay extends WC_Stripe_Payment_Gateway {
14
  /**
15
  * Notices (array)
 
16
  * @var array
17
  */
18
- public $notices = array();
19
 
20
  /**
21
  * Is test mode active?
@@ -60,10 +61,10 @@ class WC_Gateway_Stripe_Giropay extends WC_Stripe_Payment_Gateway {
60
  $this->method_title = __( 'Stripe Giropay', 'woocommerce-gateway-stripe' );
61
  /* translators: link */
62
  $this->method_description = sprintf( __( 'All other general Stripe settings can be adjusted <a href="%s">here</a>.', 'woocommerce-gateway-stripe' ), admin_url( 'admin.php?page=wc-settings&tab=checkout&section=stripe' ) );
63
- $this->supports = array(
64
  'products',
65
  'refunds',
66
- );
67
 
68
  // Load the form fields.
69
  $this->init_form_fields();
@@ -86,8 +87,8 @@ class WC_Gateway_Stripe_Giropay extends WC_Stripe_Payment_Gateway {
86
  $this->secret_key = ! empty( $main_settings['test_secret_key'] ) ? $main_settings['test_secret_key'] : '';
87
  }
88
 
89
- add_action( 'woocommerce_update_options_payment_gateways_' . $this->id, array( $this, 'process_admin_options' ) );
90
- add_action( 'wp_enqueue_scripts', array( $this, 'payment_scripts' ) );
91
  }
92
 
93
  /**
@@ -100,9 +101,9 @@ class WC_Gateway_Stripe_Giropay extends WC_Stripe_Payment_Gateway {
100
  public function get_supported_currency() {
101
  return apply_filters(
102
  'wc_stripe_giropay_supported_currencies',
103
- array(
104
  'EUR',
105
- )
106
  );
107
  }
108
 
@@ -139,11 +140,7 @@ class WC_Gateway_Stripe_Giropay extends WC_Stripe_Payment_Gateway {
139
  }
140
 
141
  /**
142
- * payment_scripts function.
143
- *
144
  * Outputs scripts used for stripe payment
145
- *
146
- * @access public
147
  */
148
  public function payment_scripts() {
149
  if ( ! is_cart() && ! is_checkout() && ! isset( $_GET['pay_for_order'] ) && ! is_add_payment_method_page() ) {
@@ -158,7 +155,7 @@ class WC_Gateway_Stripe_Giropay extends WC_Stripe_Payment_Gateway {
158
  * Initialize Gateway Settings Form Fields.
159
  */
160
  public function init_form_fields() {
161
- $this->form_fields = require( WC_STRIPE_PLUGIN_PATH . '/includes/admin/stripe-giropay-settings.php' );
162
  }
163
 
164
  /**
@@ -206,12 +203,12 @@ class WC_Gateway_Stripe_Giropay extends WC_Stripe_Payment_Gateway {
206
  public function create_source( $order ) {
207
  $currency = $order->get_currency();
208
  $return_url = $this->get_stripe_return_url( $order );
209
- $post_data = array();
210
  $post_data['amount'] = WC_Stripe_Helper::get_stripe_amount( $order->get_total(), $currency );
211
  $post_data['currency'] = strtolower( $currency );
212
  $post_data['type'] = 'giropay';
213
  $post_data['owner'] = $this->get_owner_details( $order );
214
- $post_data['redirect'] = array( 'return_url' => $return_url );
215
 
216
  if ( ! empty( $this->statement_descriptor ) ) {
217
  $post_data['statement_descriptor'] = WC_Stripe_Helper::clean_statement_descriptor( $this->statement_descriptor );
@@ -262,24 +259,24 @@ class WC_Gateway_Stripe_Giropay extends WC_Stripe_Payment_Gateway {
262
 
263
  WC_Stripe_Logger::log( 'Info: Redirecting to Giropay...' );
264
 
265
- return array(
266
  'result' => 'success',
267
  'redirect' => esc_url_raw( $response->redirect->url ),
268
- );
269
  } catch ( WC_Stripe_Exception $e ) {
270
  wc_add_notice( $e->getLocalizedMessage(), 'error' );
271
  WC_Stripe_Logger::log( 'Error: ' . $e->getMessage() );
272
 
273
  do_action( 'wc_gateway_stripe_process_payment_error', $e, $order );
274
 
275
- if ( $order->has_status( array( 'pending', 'failed' ) ) ) {
276
  $this->send_failed_order_email( $order_id );
277
  }
278
 
279
- return array(
280
  'result' => 'fail',
281
  'redirect' => '',
282
- );
283
  }
284
  }
285
  }
13
  class WC_Gateway_Stripe_Giropay extends WC_Stripe_Payment_Gateway {
14
  /**
15
  * Notices (array)
16
+ *
17
  * @var array
18
  */
19
+ public $notices = [];
20
 
21
  /**
22
  * Is test mode active?
61
  $this->method_title = __( 'Stripe Giropay', 'woocommerce-gateway-stripe' );
62
  /* translators: link */
63
  $this->method_description = sprintf( __( 'All other general Stripe settings can be adjusted <a href="%s">here</a>.', 'woocommerce-gateway-stripe' ), admin_url( 'admin.php?page=wc-settings&tab=checkout&section=stripe' ) );
64
+ $this->supports = [
65
  'products',
66
  'refunds',
67
+ ];
68
 
69
  // Load the form fields.
70
  $this->init_form_fields();
87
  $this->secret_key = ! empty( $main_settings['test_secret_key'] ) ? $main_settings['test_secret_key'] : '';
88
  }
89
 
90
+ add_action( 'woocommerce_update_options_payment_gateways_' . $this->id, [ $this, 'process_admin_options' ] );
91
+ add_action( 'wp_enqueue_scripts', [ $this, 'payment_scripts' ] );
92
  }
93
 
94
  /**
101
  public function get_supported_currency() {
102
  return apply_filters(
103
  'wc_stripe_giropay_supported_currencies',
104
+ [
105
  'EUR',
106
+ ]
107
  );
108
  }
109
 
140
  }
141
 
142
  /**
 
 
143
  * Outputs scripts used for stripe payment
 
 
144
  */
145
  public function payment_scripts() {
146
  if ( ! is_cart() && ! is_checkout() && ! isset( $_GET['pay_for_order'] ) && ! is_add_payment_method_page() ) {
155
  * Initialize Gateway Settings Form Fields.
156
  */
157
  public function init_form_fields() {
158
+ $this->form_fields = require WC_STRIPE_PLUGIN_PATH . '/includes/admin/stripe-giropay-settings.php';
159
  }
160
 
161
  /**
203
  public function create_source( $order ) {
204
  $currency = $order->get_currency();
205
  $return_url = $this->get_stripe_return_url( $order );
206
+ $post_data = [];
207
  $post_data['amount'] = WC_Stripe_Helper::get_stripe_amount( $order->get_total(), $currency );
208
  $post_data['currency'] = strtolower( $currency );
209
  $post_data['type'] = 'giropay';
210
  $post_data['owner'] = $this->get_owner_details( $order );
211
+ $post_data['redirect'] = [ 'return_url' => $return_url ];
212
 
213
  if ( ! empty( $this->statement_descriptor ) ) {
214
  $post_data['statement_descriptor'] = WC_Stripe_Helper::clean_statement_descriptor( $this->statement_descriptor );
259
 
260
  WC_Stripe_Logger::log( 'Info: Redirecting to Giropay...' );
261
 
262
+ return [
263
  'result' => 'success',
264
  'redirect' => esc_url_raw( $response->redirect->url ),
265
+ ];
266
  } catch ( WC_Stripe_Exception $e ) {
267
  wc_add_notice( $e->getLocalizedMessage(), 'error' );
268
  WC_Stripe_Logger::log( 'Error: ' . $e->getMessage() );
269
 
270
  do_action( 'wc_gateway_stripe_process_payment_error', $e, $order );
271
 
272
+ if ( $order->has_status( [ 'pending', 'failed' ] ) ) {
273
  $this->send_failed_order_email( $order_id );
274
  }
275
 
276
+ return [
277
  'result' => 'fail',
278
  'redirect' => '',
279
+ ];
280
  }
281
  }
282
  }
includes/payment-methods/class-wc-gateway-stripe-ideal.php CHANGED
@@ -13,9 +13,10 @@ if ( ! defined( 'ABSPATH' ) ) {
13
  class WC_Gateway_Stripe_Ideal extends WC_Stripe_Payment_Gateway {
14
  /**
15
  * Notices (array)
 
16
  * @var array
17
  */
18
- public $notices = array();
19
 
20
  /**
21
  * Is test mode active?
@@ -60,10 +61,10 @@ class WC_Gateway_Stripe_Ideal extends WC_Stripe_Payment_Gateway {
60
  $this->method_title = __( 'Stripe iDeal', 'woocommerce-gateway-stripe' );
61
  /* translators: link */
62
  $this->method_description = sprintf( __( 'All other general Stripe settings can be adjusted <a href="%s">here</a>.', 'woocommerce-gateway-stripe' ), admin_url( 'admin.php?page=wc-settings&tab=checkout&section=stripe' ) );
63
- $this->supports = array(
64
  'products',
65
  'refunds',
66
- );
67
 
68
  // Load the form fields.
69
  $this->init_form_fields();
@@ -86,8 +87,8 @@ class WC_Gateway_Stripe_Ideal extends WC_Stripe_Payment_Gateway {
86
  $this->secret_key = ! empty( $main_settings['test_secret_key'] ) ? $main_settings['test_secret_key'] : '';
87
  }
88
 
89
- add_action( 'woocommerce_update_options_payment_gateways_' . $this->id, array( $this, 'process_admin_options' ) );
90
- add_action( 'wp_enqueue_scripts', array( $this, 'payment_scripts' ) );
91
  }
92
 
93
  /**
@@ -100,9 +101,9 @@ class WC_Gateway_Stripe_Ideal extends WC_Stripe_Payment_Gateway {
100
  public function get_supported_currency() {
101
  return apply_filters(
102
  'wc_stripe_ideal_supported_currencies',
103
- array(
104
  'EUR',
105
- )
106
  );
107
  }
108
 
@@ -139,11 +140,7 @@ class WC_Gateway_Stripe_Ideal extends WC_Stripe_Payment_Gateway {
139
  }
140
 
141
  /**
142
- * payment_scripts function.
143
- *
144
  * Outputs scripts used for stripe payment
145
- *
146
- * @access public
147
  */
148
  public function payment_scripts() {
149
  if ( ! is_cart() && ! is_checkout() && ! isset( $_GET['pay_for_order'] ) && ! is_add_payment_method_page() ) {
@@ -158,7 +155,7 @@ class WC_Gateway_Stripe_Ideal extends WC_Stripe_Payment_Gateway {
158
  * Initialize Gateway Settings Form Fields.
159
  */
160
  public function init_form_fields() {
161
- $this->form_fields = require( WC_STRIPE_PLUGIN_PATH . '/includes/admin/stripe-ideal-settings.php' );
162
  }
163
 
164
  /**
@@ -206,12 +203,12 @@ class WC_Gateway_Stripe_Ideal extends WC_Stripe_Payment_Gateway {
206
  public function create_source( $order ) {
207
  $currency = $order->get_currency();
208
  $return_url = $this->get_stripe_return_url( $order );
209
- $post_data = array();
210
  $post_data['amount'] = WC_Stripe_Helper::get_stripe_amount( $order->get_total(), $currency );
211
  $post_data['currency'] = strtolower( $currency );
212
  $post_data['type'] = 'ideal';
213
  $post_data['owner'] = $this->get_owner_details( $order );
214
- $post_data['redirect'] = array( 'return_url' => $return_url );
215
 
216
  if ( ! empty( $this->statement_descriptor ) ) {
217
  $post_data['statement_descriptor'] = WC_Stripe_Helper::clean_statement_descriptor( $this->statement_descriptor );
@@ -262,24 +259,24 @@ class WC_Gateway_Stripe_Ideal extends WC_Stripe_Payment_Gateway {
262
 
263
  WC_Stripe_Logger::log( 'Info: Redirecting to iDeal...' );
264
 
265
- return array(
266
  'result' => 'success',
267
  'redirect' => esc_url_raw( $response->redirect->url ),
268
- );
269
  } catch ( WC_Stripe_Exception $e ) {
270
  wc_add_notice( $e->getLocalizedMessage(), 'error' );
271
  WC_Stripe_Logger::log( 'Error: ' . $e->getMessage() );
272
 
273
  do_action( 'wc_gateway_stripe_process_payment_error', $e, $order );
274
 
275
- if ( $order->has_status( array( 'pending', 'failed' ) ) ) {
276
  $this->send_failed_order_email( $order_id );
277
  }
278
 
279
- return array(
280
  'result' => 'fail',
281
  'redirect' => '',
282
- );
283
  }
284
  }
285
  }
13
  class WC_Gateway_Stripe_Ideal extends WC_Stripe_Payment_Gateway {
14
  /**
15
  * Notices (array)
16
+ *
17
  * @var array
18
  */
19
+ public $notices = [];
20
 
21
  /**
22
  * Is test mode active?
61
  $this->method_title = __( 'Stripe iDeal', 'woocommerce-gateway-stripe' );
62
  /* translators: link */
63
  $this->method_description = sprintf( __( 'All other general Stripe settings can be adjusted <a href="%s">here</a>.', 'woocommerce-gateway-stripe' ), admin_url( 'admin.php?page=wc-settings&tab=checkout&section=stripe' ) );
64
+ $this->supports = [
65
  'products',
66
  'refunds',
67
+ ];
68
 
69
  // Load the form fields.
70
  $this->init_form_fields();
87
  $this->secret_key = ! empty( $main_settings['test_secret_key'] ) ? $main_settings['test_secret_key'] : '';
88
  }
89
 
90
+ add_action( 'woocommerce_update_options_payment_gateways_' . $this->id, [ $this, 'process_admin_options' ] );
91
+ add_action( 'wp_enqueue_scripts', [ $this, 'payment_scripts' ] );
92
  }
93
 
94
  /**
101
  public function get_supported_currency() {
102
  return apply_filters(
103
  'wc_stripe_ideal_supported_currencies',
104
+ [
105
  'EUR',
106
+ ]
107
  );
108
  }
109
 
140
  }
141
 
142
  /**
 
 
143
  * Outputs scripts used for stripe payment
 
 
144
  */
145
  public function payment_scripts() {
146
  if ( ! is_cart() && ! is_checkout() && ! isset( $_GET['pay_for_order'] ) && ! is_add_payment_method_page() ) {
155
  * Initialize Gateway Settings Form Fields.
156
  */
157
  public function init_form_fields() {
158
+ $this->form_fields = require WC_STRIPE_PLUGIN_PATH . '/includes/admin/stripe-ideal-settings.php';
159
  }
160
 
161
  /**
203
  public function create_source( $order ) {
204
  $currency = $order->get_currency();
205
  $return_url = $this->get_stripe_return_url( $order );
206
+ $post_data = [];
207
  $post_data['amount'] = WC_Stripe_Helper::get_stripe_amount( $order->get_total(), $currency );
208
  $post_data['currency'] = strtolower( $currency );
209
  $post_data['type'] = 'ideal';
210
  $post_data['owner'] = $this->get_owner_details( $order );
211
+ $post_data['redirect'] = [ 'return_url' => $return_url ];
212
 
213
  if ( ! empty( $this->statement_descriptor ) ) {
214
  $post_data['statement_descriptor'] = WC_Stripe_Helper::clean_statement_descriptor( $this->statement_descriptor );
259
 
260
  WC_Stripe_Logger::log( 'Info: Redirecting to iDeal...' );
261
 
262
+ return [
263
  'result' => 'success',
264
  'redirect' => esc_url_raw( $response->redirect->url ),
265
+ ];
266
  } catch ( WC_Stripe_Exception $e ) {
267
  wc_add_notice( $e->getLocalizedMessage(), 'error' );
268
  WC_Stripe_Logger::log( 'Error: ' . $e->getMessage() );
269
 
270
  do_action( 'wc_gateway_stripe_process_payment_error', $e, $order );
271
 
272
+ if ( $order->has_status( [ 'pending', 'failed' ] ) ) {
273
  $this->send_failed_order_email( $order_id );
274
  }
275
 
276
+ return [
277
  'result' => 'fail',
278
  'redirect' => '',
279
+ ];
280
  }
281
  }
282
  }
includes/payment-methods/class-wc-gateway-stripe-multibanco.php CHANGED
@@ -13,9 +13,10 @@ if ( ! defined( 'ABSPATH' ) ) {
13
  class WC_Gateway_Stripe_Multibanco extends WC_Stripe_Payment_Gateway {
14
  /**
15
  * Notices (array)
 
16
  * @var array
17
  */
18
- public $notices = array();
19
 
20
  /**
21
  * Is test mode active?
@@ -60,10 +61,10 @@ class WC_Gateway_Stripe_Multibanco extends WC_Stripe_Payment_Gateway {
60
  $this->method_title = __( 'Stripe Multibanco', 'woocommerce-gateway-stripe' );
61
  /* translators: link */
62
  $this->method_description = sprintf( __( 'All other general Stripe settings can be adjusted <a href="%s">here</a>.', 'woocommerce-gateway-stripe' ), admin_url( 'admin.php?page=wc-settings&tab=checkout&section=stripe' ) );
63
- $this->supports = array(
64
  'products',
65
  'refunds',
66
- );
67
 
68
  // Load the form fields.
69
  $this->init_form_fields();
@@ -86,12 +87,12 @@ class WC_Gateway_Stripe_Multibanco extends WC_Stripe_Payment_Gateway {
86
  $this->secret_key = ! empty( $main_settings['test_secret_key'] ) ? $main_settings['test_secret_key'] : '';
87
  }
88
 
89
- add_action( 'woocommerce_update_options_payment_gateways_' . $this->id, array( $this, 'process_admin_options' ) );
90
- add_action( 'wp_enqueue_scripts', array( $this, 'payment_scripts' ) );
91
- add_action( 'woocommerce_thankyou_stripe_multibanco', array( $this, 'thankyou_page' ) );
92
 
93
  // Customer Emails
94
- add_action( 'woocommerce_email_before_order_table', array( $this, 'email_instructions' ), 10, 3 );
95
  }
96
 
97
  /**
@@ -104,9 +105,9 @@ class WC_Gateway_Stripe_Multibanco extends WC_Stripe_Payment_Gateway {
104
  public function get_supported_currency() {
105
  return apply_filters(
106
  'wc_stripe_multibanco_supported_currencies',
107
- array(
108
  'EUR',
109
- )
110
  );
111
  }
112
 
@@ -143,11 +144,7 @@ class WC_Gateway_Stripe_Multibanco extends WC_Stripe_Payment_Gateway {
143
  }
144
 
145
  /**
146
- * payment_scripts function.
147
- *
148
  * Outputs scripts used for stripe payment
149
- *
150
- * @access public
151
  */
152
  public function payment_scripts() {
153
  if ( ! is_cart() && ! is_checkout() && ! isset( $_GET['pay_for_order'] ) && ! is_add_payment_method_page() ) {
@@ -162,7 +159,7 @@ class WC_Gateway_Stripe_Multibanco extends WC_Stripe_Payment_Gateway {
162
  * Initialize Gateway Settings Form Fields.
163
  */
164
  public function init_form_fields() {
165
- $this->form_fields = require( WC_STRIPE_PLUGIN_PATH . '/includes/admin/stripe-multibanco-settings.php' );
166
  }
167
 
168
  /**
@@ -214,8 +211,8 @@ class WC_Gateway_Stripe_Multibanco extends WC_Stripe_Payment_Gateway {
214
  * @since 4.1.0
215
  * @version 4.1.0
216
  * @param WC_Order $order
217
- * @param bool $sent_to_admin
218
- * @param bool $plain_text
219
  */
220
  public function email_instructions( $order, $sent_to_admin, $plain_text = false ) {
221
  $order_id = $order->get_id();
@@ -280,11 +277,11 @@ class WC_Gateway_Stripe_Multibanco extends WC_Stripe_Payment_Gateway {
280
  * @param object $source_object
281
  */
282
  public function save_instructions( $order, $source_object ) {
283
- $data = array(
284
  'amount' => $order->get_formatted_order_total(),
285
  'entity' => $source_object->multibanco->entity,
286
  'reference' => $source_object->multibanco->reference,
287
- );
288
 
289
  $order_id = $order->get_id();
290
 
@@ -302,12 +299,12 @@ class WC_Gateway_Stripe_Multibanco extends WC_Stripe_Payment_Gateway {
302
  public function create_source( $order ) {
303
  $currency = $order->get_currency();
304
  $return_url = $this->get_stripe_return_url( $order );
305
- $post_data = array();
306
  $post_data['amount'] = WC_Stripe_Helper::get_stripe_amount( $order->get_total(), $currency );
307
  $post_data['currency'] = strtolower( $currency );
308
  $post_data['type'] = 'multibanco';
309
  $post_data['owner'] = $this->get_owner_details( $order );
310
- $post_data['redirect'] = array( 'return_url' => $return_url );
311
 
312
  if ( ! empty( $this->statement_descriptor ) ) {
313
  $post_data['statement_descriptor'] = WC_Stripe_Helper::clean_statement_descriptor( $this->statement_descriptor );
@@ -369,24 +366,24 @@ class WC_Gateway_Stripe_Multibanco extends WC_Stripe_Payment_Gateway {
369
 
370
  WC_Stripe_Logger::log( 'Info: Redirecting to Multibanco...' );
371
 
372
- return array(
373
  'result' => 'success',
374
  'redirect' => esc_url_raw( $response->redirect->url ),
375
- );
376
  } catch ( Exception $e ) {
377
  wc_add_notice( $e->getMessage(), 'error' );
378
  WC_Stripe_Logger::log( 'Error: ' . $e->getMessage() );
379
 
380
  do_action( 'wc_gateway_stripe_process_payment_error', $e, $order );
381
 
382
- if ( $order->has_status( array( 'pending', 'failed' ) ) ) {
383
  $this->send_failed_order_email( $order_id );
384
  }
385
 
386
- return array(
387
  'result' => 'fail',
388
  'redirect' => '',
389
- );
390
  }
391
  }
392
  }
13
  class WC_Gateway_Stripe_Multibanco extends WC_Stripe_Payment_Gateway {
14
  /**
15
  * Notices (array)
16
+ *
17
  * @var array
18
  */
19
+ public $notices = [];
20
 
21
  /**
22
  * Is test mode active?
61
  $this->method_title = __( 'Stripe Multibanco', 'woocommerce-gateway-stripe' );
62
  /* translators: link */
63
  $this->method_description = sprintf( __( 'All other general Stripe settings can be adjusted <a href="%s">here</a>.', 'woocommerce-gateway-stripe' ), admin_url( 'admin.php?page=wc-settings&tab=checkout&section=stripe' ) );
64
+ $this->supports = [
65
  'products',
66
  'refunds',
67
+ ];
68
 
69
  // Load the form fields.
70
  $this->init_form_fields();
87
  $this->secret_key = ! empty( $main_settings['test_secret_key'] ) ? $main_settings['test_secret_key'] : '';
88
  }
89
 
90
+ add_action( 'woocommerce_update_options_payment_gateways_' . $this->id, [ $this, 'process_admin_options' ] );
91
+ add_action( 'wp_enqueue_scripts', [ $this, 'payment_scripts' ] );
92
+ add_action( 'woocommerce_thankyou_stripe_multibanco', [ $this, 'thankyou_page' ] );
93
 
94
  // Customer Emails
95
+ add_action( 'woocommerce_email_before_order_table', [ $this, 'email_instructions' ], 10, 3 );
96
  }
97
 
98
  /**
105
  public function get_supported_currency() {
106
  return apply_filters(
107
  'wc_stripe_multibanco_supported_currencies',
108
+ [
109
  'EUR',
110
+ ]
111
  );
112
  }
113
 
144
  }
145
 
146
  /**
 
 
147
  * Outputs scripts used for stripe payment
 
 
148
  */
149
  public function payment_scripts() {
150
  if ( ! is_cart() && ! is_checkout() && ! isset( $_GET['pay_for_order'] ) && ! is_add_payment_method_page() ) {
159
  * Initialize Gateway Settings Form Fields.
160
  */
161
  public function init_form_fields() {
162
+ $this->form_fields = require WC_STRIPE_PLUGIN_PATH . '/includes/admin/stripe-multibanco-settings.php';
163
  }
164
 
165
  /**
211
  * @since 4.1.0
212
  * @version 4.1.0
213
  * @param WC_Order $order
214
+ * @param bool $sent_to_admin
215
+ * @param bool $plain_text
216
  */
217
  public function email_instructions( $order, $sent_to_admin, $plain_text = false ) {
218
  $order_id = $order->get_id();
277
  * @param object $source_object
278
  */
279
  public function save_instructions( $order, $source_object ) {
280
+ $data = [
281
  'amount' => $order->get_formatted_order_total(),
282
  'entity' => $source_object->multibanco->entity,
283
  'reference' => $source_object->multibanco->reference,
284
+ ];
285
 
286
  $order_id = $order->get_id();
287
 
299
  public function create_source( $order ) {
300
  $currency = $order->get_currency();
301
  $return_url = $this->get_stripe_return_url( $order );
302
+ $post_data = [];
303
  $post_data['amount'] = WC_Stripe_Helper::get_stripe_amount( $order->get_total(), $currency );
304
  $post_data['currency'] = strtolower( $currency );
305
  $post_data['type'] = 'multibanco';
306
  $post_data['owner'] = $this->get_owner_details( $order );
307
+ $post_data['redirect'] = [ 'return_url' => $return_url ];
308
 
309
  if ( ! empty( $this->statement_descriptor ) ) {
310
  $post_data['statement_descriptor'] = WC_Stripe_Helper::clean_statement_descriptor( $this->statement_descriptor );
366
 
367
  WC_Stripe_Logger::log( 'Info: Redirecting to Multibanco...' );
368
 
369
+ return [
370
  'result' => 'success',
371
  'redirect' => esc_url_raw( $response->redirect->url ),
372
+ ];
373
  } catch ( Exception $e ) {
374
  wc_add_notice( $e->getMessage(), 'error' );
375
  WC_Stripe_Logger::log( 'Error: ' . $e->getMessage() );
376
 
377
  do_action( 'wc_gateway_stripe_process_payment_error', $e, $order );
378
 
379
+ if ( $order->has_status( [ 'pending', 'failed' ] ) ) {
380
  $this->send_failed_order_email( $order_id );
381
  }
382
 
383
+ return [
384
  'result' => 'fail',
385
  'redirect' => '',
386
+ ];
387
  }
388
  }
389
  }
includes/payment-methods/class-wc-gateway-stripe-p24.php CHANGED
@@ -13,9 +13,10 @@ if ( ! defined( 'ABSPATH' ) ) {
13
  class WC_Gateway_Stripe_P24 extends WC_Stripe_Payment_Gateway {
14
  /**
15
  * Notices (array)
 
16
  * @var array
17
  */
18
- public $notices = array();
19
 
20
  /**
21
  * Is test mode active?
@@ -60,10 +61,10 @@ class WC_Gateway_Stripe_P24 extends WC_Stripe_Payment_Gateway {
60
  $this->method_title = __( 'Stripe P24', 'woocommerce-gateway-stripe' );
61
  /* translators: link */
62
  $this->method_description = sprintf( __( 'All other general Stripe settings can be adjusted <a href="%s">here</a>.', 'woocommerce-gateway-stripe' ), admin_url( 'admin.php?page=wc-settings&tab=checkout&section=stripe' ) );
63
- $this->supports = array(
64
  'products',
65
  'refunds',
66
- );
67
 
68
  // Load the form fields.
69
  $this->init_form_fields();
@@ -86,8 +87,8 @@ class WC_Gateway_Stripe_P24 extends WC_Stripe_Payment_Gateway {
86
  $this->secret_key = ! empty( $main_settings['test_secret_key'] ) ? $main_settings['test_secret_key'] : '';
87
  }
88
 
89
- add_action( 'woocommerce_update_options_payment_gateways_' . $this->id, array( $this, 'process_admin_options' ) );
90
- add_action( 'wp_enqueue_scripts', array( $this, 'payment_scripts' ) );
91
  }
92
 
93
  /**
@@ -100,10 +101,10 @@ class WC_Gateway_Stripe_P24 extends WC_Stripe_Payment_Gateway {
100
  public function get_supported_currency() {
101
  return apply_filters(
102
  'wc_stripe_p24_supported_currencies',
103
- array(
104
  'EUR',
105
  'PLN',
106
- )
107
  );
108
  }
109
 
@@ -140,11 +141,7 @@ class WC_Gateway_Stripe_P24 extends WC_Stripe_Payment_Gateway {
140
  }
141
 
142
  /**
143
- * payment_scripts function.
144
- *
145
  * Outputs scripts used for stripe payment
146
- *
147
- * @access public
148
  */
149
  public function payment_scripts() {
150
  if ( ! is_cart() && ! is_checkout() && ! isset( $_GET['pay_for_order'] ) && ! is_add_payment_method_page() ) {
@@ -159,7 +156,7 @@ class WC_Gateway_Stripe_P24 extends WC_Stripe_Payment_Gateway {
159
  * Initialize Gateway Settings Form Fields.
160
  */
161
  public function init_form_fields() {
162
- $this->form_fields = require( WC_STRIPE_PLUGIN_PATH . '/includes/admin/stripe-p24-settings.php' );
163
  }
164
 
165
  /**
@@ -207,12 +204,12 @@ class WC_Gateway_Stripe_P24 extends WC_Stripe_Payment_Gateway {
207
  public function create_source( $order ) {
208
  $currency = $order->get_currency();
209
  $return_url = $this->get_stripe_return_url( $order );
210
- $post_data = array();
211
  $post_data['amount'] = WC_Stripe_Helper::get_stripe_amount( $order->get_total(), $currency );
212
  $post_data['currency'] = strtolower( $currency );
213
  $post_data['type'] = 'p24';
214
  $post_data['owner'] = $this->get_owner_details( $order );
215
- $post_data['redirect'] = array( 'return_url' => $return_url );
216
 
217
  WC_Stripe_Logger::log( 'Info: Begin creating P24 source' );
218
 
@@ -259,24 +256,24 @@ class WC_Gateway_Stripe_P24 extends WC_Stripe_Payment_Gateway {
259
 
260
  WC_Stripe_Logger::log( 'Info: Redirecting to P24...' );
261
 
262
- return array(
263
  'result' => 'success',
264
  'redirect' => esc_url_raw( $response->redirect->url ),
265
- );
266
  } catch ( WC_Stripe_Exception $e ) {
267
  wc_add_notice( $e->getLocalizedMessage(), 'error' );
268
  WC_Stripe_Logger::log( 'Error: ' . $e->getMessage() );
269
 
270
  do_action( 'wc_gateway_stripe_process_payment_error', $e, $order );
271
 
272
- if ( $order->has_status( array( 'pending', 'failed' ) ) ) {
273
  $this->send_failed_order_email( $order_id );
274
  }
275
 
276
- return array(
277
  'result' => 'fail',
278
  'redirect' => '',
279
- );
280
  }
281
  }
282
  }
13
  class WC_Gateway_Stripe_P24 extends WC_Stripe_Payment_Gateway {
14
  /**
15
  * Notices (array)
16
+ *
17
  * @var array
18
  */
19
+ public $notices = [];
20
 
21
  /**
22
  * Is test mode active?
61
  $this->method_title = __( 'Stripe P24', 'woocommerce-gateway-stripe' );
62
  /* translators: link */
63
  $this->method_description = sprintf( __( 'All other general Stripe settings can be adjusted <a href="%s">here</a>.', 'woocommerce-gateway-stripe' ), admin_url( 'admin.php?page=wc-settings&tab=checkout&section=stripe' ) );
64
+ $this->supports = [
65
  'products',
66
  'refunds',
67
+ ];
68
 
69
  // Load the form fields.
70
  $this->init_form_fields();
87
  $this->secret_key = ! empty( $main_settings['test_secret_key'] ) ? $main_settings['test_secret_key'] : '';
88
  }
89
 
90
+ add_action( 'woocommerce_update_options_payment_gateways_' . $this->id, [ $this, 'process_admin_options' ] );
91
+ add_action( 'wp_enqueue_scripts', [ $this, 'payment_scripts' ] );
92
  }
93
 
94
  /**
101
  public function get_supported_currency() {
102
  return apply_filters(
103
  'wc_stripe_p24_supported_currencies',
104
+ [
105
  'EUR',
106
  'PLN',
107
+ ]
108
  );
109
  }
110
 
141
  }
142
 
143
  /**
 
 
144
  * Outputs scripts used for stripe payment
 
 
145
  */
146
  public function payment_scripts() {
147
  if ( ! is_cart() && ! is_checkout() && ! isset( $_GET['pay_for_order'] ) && ! is_add_payment_method_page() ) {
156
  * Initialize Gateway Settings Form Fields.
157
  */
158
  public function init_form_fields() {
159
+ $this->form_fields = require WC_STRIPE_PLUGIN_PATH . '/includes/admin/stripe-p24-settings.php';
160
  }
161
 
162
  /**
204
  public function create_source( $order ) {
205
  $currency = $order->get_currency();
206
  $return_url = $this->get_stripe_return_url( $order );
207
+ $post_data = [];
208
  $post_data['amount'] = WC_Stripe_Helper::get_stripe_amount( $order->get_total(), $currency );
209
  $post_data['currency'] = strtolower( $currency );
210
  $post_data['type'] = 'p24';
211
  $post_data['owner'] = $this->get_owner_details( $order );
212
+ $post_data['redirect'] = [ 'return_url' => $return_url ];
213
 
214
  WC_Stripe_Logger::log( 'Info: Begin creating P24 source' );
215
 
256
 
257
  WC_Stripe_Logger::log( 'Info: Redirecting to P24...' );
258
 
259
+ return [
260
  'result' => 'success',
261
  'redirect' => esc_url_raw( $response->redirect->url ),
262
+ ];
263
  } catch ( WC_Stripe_Exception $e ) {
264
  wc_add_notice( $e->getLocalizedMessage(), 'error' );
265
  WC_Stripe_Logger::log( 'Error: ' . $e->getMessage() );
266
 
267
  do_action( 'wc_gateway_stripe_process_payment_error', $e, $order );
268
 
269
+ if ( $order->has_status( [ 'pending', 'failed' ] ) ) {
270
  $this->send_failed_order_email( $order_id );
271
  }
272
 
273
+ return [
274
  'result' => 'fail',
275
  'redirect' => '',
276
+ ];
277
  }
278
  }
279
  }
includes/payment-methods/class-wc-gateway-stripe-sepa.php CHANGED
@@ -20,9 +20,10 @@ class WC_Gateway_Stripe_Sepa extends WC_Stripe_Payment_Gateway {
20
 
21
  /**
22
  * Notices (array)
 
23
  * @var array
24
  */
25
- public $notices = array();
26
 
27
  /**
28
  * Is test mode active?
@@ -76,7 +77,7 @@ class WC_Gateway_Stripe_Sepa extends WC_Stripe_Payment_Gateway {
76
  /* translators: link */
77
  $this->method_description = sprintf( __( 'All other general Stripe settings can be adjusted <a href="%s">here</a>.', 'woocommerce-gateway-stripe' ), admin_url( 'admin.php?page=wc-settings&tab=checkout&section=stripe' ) );
78
  $this->has_fields = true;
79
- $this->supports = array(
80
  'products',
81
  'refunds',
82
  'tokenization',
@@ -92,7 +93,7 @@ class WC_Gateway_Stripe_Sepa extends WC_Stripe_Payment_Gateway {
92
  'subscription_payment_method_change_admin',
93
  'multiple_subscriptions',
94
  'pre-orders',
95
- );
96
 
97
  // Load the form fields.
98
  $this->init_form_fields();
@@ -115,13 +116,13 @@ class WC_Gateway_Stripe_Sepa extends WC_Stripe_Payment_Gateway {
115
  $this->secret_key = ! empty( $main_settings['test_secret_key'] ) ? $main_settings['test_secret_key'] : '';
116
  }
117
 
118
- add_action( 'woocommerce_update_options_payment_gateways_' . $this->id, array( $this, 'process_admin_options' ) );
119
- add_action( 'wp_enqueue_scripts', array( $this, 'payment_scripts' ) );
120
 
121
  if ( WC_Stripe_Helper::is_pre_orders_exists() ) {
122
  $this->pre_orders = new WC_Stripe_Pre_Orders_Compat();
123
 
124
- add_action( 'wc_pre_orders_process_pre_order_completion_payment_' . $this->id, array( $this->pre_orders, 'process_pre_order_release_payment' ) );
125
  }
126
  }
127
 
@@ -135,9 +136,9 @@ class WC_Gateway_Stripe_Sepa extends WC_Stripe_Payment_Gateway {
135
  public function get_supported_currency() {
136
  return apply_filters(
137
  'wc_stripe_sepa_supported_currencies',
138
- array(
139
  'EUR',
140
- )
141
  );
142
  }
143
 
@@ -178,11 +179,7 @@ class WC_Gateway_Stripe_Sepa extends WC_Stripe_Payment_Gateway {
178
  }
179
 
180
  /**
181
- * payment_scripts function.
182
- *
183
  * Outputs scripts used for stripe payment
184
- *
185
- * @access public
186
  */
187
  public function payment_scripts() {
188
  if ( ! is_cart() && ! is_checkout() && ! isset( $_GET['pay_for_order'] ) && ! is_add_payment_method_page() ) {
@@ -197,7 +194,7 @@ class WC_Gateway_Stripe_Sepa extends WC_Stripe_Payment_Gateway {
197
  * Initialize Gateway Settings Form Fields.
198
  */
199
  public function init_form_fields() {
200
- $this->form_fields = require( WC_STRIPE_PLUGIN_PATH . '/includes/admin/stripe-sepa-settings.php' );
201
  }
202
 
203
  /**
@@ -397,10 +394,10 @@ class WC_Gateway_Stripe_Sepa extends WC_Stripe_Payment_Gateway {
397
  WC()->cart->empty_cart();
398
 
399
  // Return thank you page redirect.
400
- return array(
401
  'result' => 'success',
402
  'redirect' => $this->get_return_url( $order ),
403
- );
404
 
405
  } catch ( WC_Stripe_Exception $e ) {
406
  wc_add_notice( $e->getLocalizedMessage(), 'error' );
@@ -408,14 +405,14 @@ class WC_Gateway_Stripe_Sepa extends WC_Stripe_Payment_Gateway {
408
 
409
  do_action( 'wc_gateway_stripe_process_payment_error', $e, $order );
410
 
411
- if ( $order->has_status( array( 'pending', 'failed' ) ) ) {
412
  $this->send_failed_order_email( $order_id );
413
  }
414
 
415
- return array(
416
  'result' => 'fail',
417
  'redirect' => '',
418
- );
419
  }
420
  }
421
  }
20
 
21
  /**
22
  * Notices (array)
23
+ *
24
  * @var array
25
  */
26
+ public $notices = [];
27
 
28
  /**
29
  * Is test mode active?
77
  /* translators: link */
78
  $this->method_description = sprintf( __( 'All other general Stripe settings can be adjusted <a href="%s">here</a>.', 'woocommerce-gateway-stripe' ), admin_url( 'admin.php?page=wc-settings&tab=checkout&section=stripe' ) );
79
  $this->has_fields = true;
80
+ $this->supports = [
81
  'products',
82
  'refunds',
83
  'tokenization',
93
  'subscription_payment_method_change_admin',
94
  'multiple_subscriptions',
95
  'pre-orders',
96
+ ];
97
 
98
  // Load the form fields.
99
  $this->init_form_fields();
116
  $this->secret_key = ! empty( $main_settings['test_secret_key'] ) ? $main_settings['test_secret_key'] : '';
117
  }
118
 
119
+ add_action( 'woocommerce_update_options_payment_gateways_' . $this->id, [ $this, 'process_admin_options' ] );
120
+ add_action( 'wp_enqueue_scripts', [ $this, 'payment_scripts' ] );
121
 
122
  if ( WC_Stripe_Helper::is_pre_orders_exists() ) {
123
  $this->pre_orders = new WC_Stripe_Pre_Orders_Compat();
124
 
125
+ add_action( 'wc_pre_orders_process_pre_order_completion_payment_' . $this->id, [ $this->pre_orders, 'process_pre_order_release_payment' ] );
126
  }
127
  }
128
 
136
  public function get_supported_currency() {
137
  return apply_filters(
138
  'wc_stripe_sepa_supported_currencies',
139
+ [
140
  'EUR',
141
+ ]
142
  );
143
  }
144
 
179
  }
180
 
181
  /**
 
 
182
  * Outputs scripts used for stripe payment
 
 
183
  */
184
  public function payment_scripts() {
185
  if ( ! is_cart() && ! is_checkout() && ! isset( $_GET['pay_for_order'] ) && ! is_add_payment_method_page() ) {
194
  * Initialize Gateway Settings Form Fields.
195
  */
196
  public function init_form_fields() {
197
+ $this->form_fields = require WC_STRIPE_PLUGIN_PATH . '/includes/admin/stripe-sepa-settings.php';
198
  }
199
 
200
  /**
394
  WC()->cart->empty_cart();
395
 
396
  // Return thank you page redirect.
397
+ return [
398
  'result' => 'success',
399
  'redirect' => $this->get_return_url( $order ),
400
+ ];
401
 
402
  } catch ( WC_Stripe_Exception $e ) {
403
  wc_add_notice( $e->getLocalizedMessage(), 'error' );
405
 
406
  do_action( 'wc_gateway_stripe_process_payment_error', $e, $order );
407
 
408
+ if ( $order->has_status( [ 'pending', 'failed' ] ) ) {
409
  $this->send_failed_order_email( $order_id );
410
  }
411
 
412
+ return [
413
  'result' => 'fail',
414
  'redirect' => '',
415
+ ];
416
  }
417
  }
418
  }
includes/payment-methods/class-wc-gateway-stripe-sofort.php CHANGED
@@ -13,9 +13,10 @@ if ( ! defined( 'ABSPATH' ) ) {
13
  class WC_Gateway_Stripe_Sofort extends WC_Stripe_Payment_Gateway {
14
  /**
15
  * Notices (array)
 
16
  * @var array
17
  */
18
- public $notices = array();
19
 
20
  /**
21
  * Is test mode active?
@@ -60,10 +61,10 @@ class WC_Gateway_Stripe_Sofort extends WC_Stripe_Payment_Gateway {
60
  $this->method_title = __( 'Stripe SOFORT', 'woocommerce-gateway-stripe' );
61
  /* translators: link */
62
  $this->method_description = sprintf( __( 'All other general Stripe settings can be adjusted <a href="%s">here</a>.', 'woocommerce-gateway-stripe' ), admin_url( 'admin.php?page=wc-settings&tab=checkout&section=stripe' ) );
63
- $this->supports = array(
64
  'products',
65
  'refunds',
66
- );
67
 
68
  // Load the form fields.
69
  $this->init_form_fields();
@@ -86,8 +87,8 @@ class WC_Gateway_Stripe_Sofort extends WC_Stripe_Payment_Gateway {
86
  $this->secret_key = ! empty( $main_settings['test_secret_key'] ) ? $main_settings['test_secret_key'] : '';
87
  }
88
 
89
- add_action( 'woocommerce_update_options_payment_gateways_' . $this->id, array( $this, 'process_admin_options' ) );
90
- add_action( 'wp_enqueue_scripts', array( $this, 'payment_scripts' ) );
91
  }
92
 
93
  /**
@@ -100,9 +101,9 @@ class WC_Gateway_Stripe_Sofort extends WC_Stripe_Payment_Gateway {
100
  public function get_supported_currency() {
101
  return apply_filters(
102
  'wc_stripe_sofort_supported_currencies',
103
- array(
104
  'EUR',
105
- )
106
  );
107
  }
108
 
@@ -139,11 +140,7 @@ class WC_Gateway_Stripe_Sofort extends WC_Stripe_Payment_Gateway {
139
  }
140
 
141
  /**
142
- * payment_scripts function.
143
- *
144
  * Outputs scripts used for stripe payment
145
- *
146
- * @access public
147
  */
148
  public function payment_scripts() {
149
  if ( ! is_cart() && ! is_checkout() && ! isset( $_GET['pay_for_order'] ) && ! is_add_payment_method_page() ) {
@@ -158,7 +155,7 @@ class WC_Gateway_Stripe_Sofort extends WC_Stripe_Payment_Gateway {
158
  * Initialize Gateway Settings Form Fields.
159
  */
160
  public function init_form_fields() {
161
- $this->form_fields = require( WC_STRIPE_PLUGIN_PATH . '/includes/admin/stripe-sofort-settings.php' );
162
  }
163
 
164
  /**
@@ -207,16 +204,16 @@ class WC_Gateway_Stripe_Sofort extends WC_Stripe_Payment_Gateway {
207
  $currency = $order->get_currency();
208
  $bank_country = $order->get_billing_country();
209
  $return_url = $this->get_stripe_return_url( $order );
210
- $post_data = array();
211
  $post_data['amount'] = WC_Stripe_Helper::get_stripe_amount( $order->get_total(), $currency );
212
  $post_data['currency'] = strtolower( $currency );
213
  $post_data['type'] = 'sofort';
214
  $post_data['owner'] = $this->get_owner_details( $order );
215
- $post_data['redirect'] = array( 'return_url' => $return_url );
216
- $post_data['sofort'] = array(
217
  'country' => $bank_country,
218
  'preferred_language' => $this->get_locale(),
219
- );
220
 
221
  if ( ! empty( $this->statement_descriptor ) ) {
222
  $post_data['statement_descriptor'] = WC_Stripe_Helper::clean_statement_descriptor( $this->statement_descriptor );
@@ -275,24 +272,24 @@ class WC_Gateway_Stripe_Sofort extends WC_Stripe_Payment_Gateway {
275
 
276
  WC_Stripe_Logger::log( 'Info: Redirecting to SOFORT...' );
277
 
278
- return array(
279
  'result' => 'success',
280
  'redirect' => esc_url_raw( $response->redirect->url ),
281
- );
282
  } catch ( WC_Stripe_Exception $e ) {
283
  wc_add_notice( $e->getLocalizedMessage(), 'error' );
284
  WC_Stripe_Logger::log( 'Error: ' . $e->getMessage() );
285
 
286
  do_action( 'wc_gateway_stripe_process_payment_error', $e, $order );
287
 
288
- if ( $order->has_status( array( 'pending', 'failed' ) ) ) {
289
  $this->send_failed_order_email( $order_id );
290
  }
291
 
292
- return array(
293
  'result' => 'fail',
294
  'redirect' => '',
295
- );
296
  }
297
  }
298
  }
13
  class WC_Gateway_Stripe_Sofort extends WC_Stripe_Payment_Gateway {
14
  /**
15
  * Notices (array)
16
+ *
17
  * @var array
18
  */
19
+ public $notices = [];
20
 
21
  /**
22
  * Is test mode active?
61
  $this->method_title = __( 'Stripe SOFORT', 'woocommerce-gateway-stripe' );
62
  /* translators: link */
63
  $this->method_description = sprintf( __( 'All other general Stripe settings can be adjusted <a href="%s">here</a>.', 'woocommerce-gateway-stripe' ), admin_url( 'admin.php?page=wc-settings&tab=checkout&section=stripe' ) );
64
+ $this->supports = [
65
  'products',
66
  'refunds',
67
+ ];
68
 
69
  // Load the form fields.
70
  $this->init_form_fields();
87
  $this->secret_key = ! empty( $main_settings['test_secret_key'] ) ? $main_settings['test_secret_key'] : '';
88
  }
89
 
90
+ add_action( 'woocommerce_update_options_payment_gateways_' . $this->id, [ $this, 'process_admin_options' ] );
91
+ add_action( 'wp_enqueue_scripts', [ $this, 'payment_scripts' ] );
92
  }
93
 
94
  /**
101
  public function get_supported_currency() {
102
  return apply_filters(
103
  'wc_stripe_sofort_supported_currencies',
104
+ [
105
  'EUR',
106
+ ]
107
  );
108
  }
109
 
140
  }
141
 
142
  /**
 
 
143
  * Outputs scripts used for stripe payment
 
 
144
  */
145
  public function payment_scripts() {
146
  if ( ! is_cart() && ! is_checkout() && ! isset( $_GET['pay_for_order'] ) && ! is_add_payment_method_page() ) {
155
  * Initialize Gateway Settings Form Fields.
156
  */
157
  public function init_form_fields() {
158
+ $this->form_fields = require WC_STRIPE_PLUGIN_PATH . '/includes/admin/stripe-sofort-settings.php';
159
  }
160
 
161
  /**
204
  $currency = $order->get_currency();
205
  $bank_country = $order->get_billing_country();
206
  $return_url = $this->get_stripe_return_url( $order );
207
+ $post_data = [];
208
  $post_data['amount'] = WC_Stripe_Helper::get_stripe_amount( $order->get_total(), $currency );
209
  $post_data['currency'] = strtolower( $currency );
210
  $post_data['type'] = 'sofort';
211
  $post_data['owner'] = $this->get_owner_details( $order );
212
+ $post_data['redirect'] = [ 'return_url' => $return_url ];
213
+ $post_data['sofort'] = [
214
  'country' => $bank_country,
215
  'preferred_language' => $this->get_locale(),
216
+ ];
217
 
218
  if ( ! empty( $this->statement_descriptor ) ) {
219
  $post_data['statement_descriptor'] = WC_Stripe_Helper::clean_statement_descriptor( $this->statement_descriptor );
272
 
273
  WC_Stripe_Logger::log( 'Info: Redirecting to SOFORT...' );
274
 
275
+ return [
276
  'result' => 'success',
277
  'redirect' => esc_url_raw( $response->redirect->url ),
278
+ ];
279
  } catch ( WC_Stripe_Exception $e ) {
280
  wc_add_notice( $e->getLocalizedMessage(), 'error' );
281
  WC_Stripe_Logger::log( 'Error: ' . $e->getMessage() );
282
 
283
  do_action( 'wc_gateway_stripe_process_payment_error', $e, $order );
284
 
285
+ if ( $order->has_status( [ 'pending', 'failed' ] ) ) {
286
  $this->send_failed_order_email( $order_id );
287
  }
288
 
289
+ return [
290
  'result' => 'fail',
291
  'redirect' => '',
292
+ ];
293
  }
294
  }
295
  }
includes/payment-methods/class-wc-stripe-payment-request.php CHANGED
@@ -66,7 +66,7 @@ class WC_Stripe_Payment_Request {
66
  */
67
  public function __construct() {
68
  self::$_this = $this;
69
- $this->stripe_settings = get_option( 'woocommerce_stripe_settings', array() );
70
  $this->testmode = ( ! empty( $this->stripe_settings['testmode'] ) && 'yes' === $this->stripe_settings['testmode'] ) ? true : false;
71
  $this->publishable_key = ! empty( $this->stripe_settings['publishable_key'] ) ? $this->stripe_settings['publishable_key'] : '';
72
  $this->secret_key = ! empty( $this->stripe_settings['secret_key'] ) ? $this->stripe_settings['secret_key'] : '';
@@ -94,7 +94,7 @@ class WC_Stripe_Payment_Request {
94
  return;
95
  }
96
 
97
- add_action( 'template_redirect', array( $this, 'set_session' ) );
98
  $this->init();
99
  }
100
 
@@ -109,10 +109,10 @@ class WC_Stripe_Payment_Request {
109
  // in includes/abstracts/abstract-wc-stripe-payment-gateway.php
110
  if ( $this->testmode ) {
111
  return preg_match( '/^pk_test_/', $this->publishable_key )
112
- && preg_match( '/^[rs]k_test_/', $this->secret_key );
113
  } else {
114
  return preg_match( '/^pk_live_/', $this->publishable_key )
115
- && preg_match( '/^[rs]k_live_/', $this->secret_key );
116
  }
117
  }
118
 
@@ -149,30 +149,30 @@ class WC_Stripe_Payment_Request {
149
  * @return void
150
  */
151
  public function init() {
152
- add_action( 'wp_enqueue_scripts', array( $this, 'scripts' ) );
153
 
154
- add_action( 'woocommerce_after_add_to_cart_quantity', array( $this, 'display_payment_request_button_html' ), 1 );
155
- add_action( 'woocommerce_after_add_to_cart_quantity', array( $this, 'display_payment_request_button_separator_html' ), 2 );
156
 
157
- add_action( 'woocommerce_proceed_to_checkout', array( $this, 'display_payment_request_button_html' ), 1 );
158
- add_action( 'woocommerce_proceed_to_checkout', array( $this, 'display_payment_request_button_separator_html' ), 2 );
159
 
160
- add_action( 'woocommerce_checkout_before_customer_details', array( $this, 'display_payment_request_button_html' ), 1 );
161
- add_action( 'woocommerce_checkout_before_customer_details', array( $this, 'display_payment_request_button_separator_html' ), 2 );
162
 
163
- add_action( 'wc_ajax_wc_stripe_get_cart_details', array( $this, 'ajax_get_cart_details' ) );
164
- add_action( 'wc_ajax_wc_stripe_get_shipping_options', array( $this, 'ajax_get_shipping_options' ) );
165
- add_action( 'wc_ajax_wc_stripe_update_shipping_method', array( $this, 'ajax_update_shipping_method' ) );
166
- add_action( 'wc_ajax_wc_stripe_create_order', array( $this, 'ajax_create_order' ) );
167
- add_action( 'wc_ajax_wc_stripe_add_to_cart', array( $this, 'ajax_add_to_cart' ) );
168
- add_action( 'wc_ajax_wc_stripe_get_selected_product_data', array( $this, 'ajax_get_selected_product_data' ) );
169
- add_action( 'wc_ajax_wc_stripe_clear_cart', array( $this, 'ajax_clear_cart' ) );
170
- add_action( 'wc_ajax_wc_stripe_log_errors', array( $this, 'ajax_log_errors' ) );
171
 
172
- add_filter( 'woocommerce_gateway_title', array( $this, 'filter_gateway_title' ), 10, 2 );
173
- add_filter( 'woocommerce_validate_postcode', array( $this, 'postal_code_validation' ), 10, 3 );
174
 
175
- add_action( 'woocommerce_checkout_order_processed', array( $this, 'add_order_meta' ), 10, 2 );
176
  }
177
 
178
  /**
@@ -290,43 +290,43 @@ class WC_Stripe_Payment_Request {
290
  }
291
  }
292
 
293
- $data = array();
294
- $items = array();
295
 
296
- $items[] = array(
297
  'label' => $product->get_name(),
298
  'amount' => WC_Stripe_Helper::get_stripe_amount( $product->get_price() ),
299
- );
300
 
301
  if ( wc_tax_enabled() ) {
302
- $items[] = array(
303
  'label' => __( 'Tax', 'woocommerce-gateway-stripe' ),
304
  'amount' => 0,
305
  'pending' => true,
306
- );
307
  }
308
 
309
  if ( wc_shipping_enabled() && $product->needs_shipping() ) {
310
- $items[] = array(
311
  'label' => __( 'Shipping', 'woocommerce-gateway-stripe' ),
312
  'amount' => 0,
313
  'pending' => true,
314
- );
315
 
316
- $data['shippingOptions'] = array(
317
  'id' => 'pending',
318
  'label' => __( 'Pending', 'woocommerce-gateway-stripe' ),
319
  'detail' => '',
320
  'amount' => 0,
321
- );
322
  }
323
 
324
  $data['displayItems'] = $items;
325
- $data['total'] = array(
326
  'label' => apply_filters( 'wc_stripe_payment_request_total_label', $this->total_label ),
327
  'amount' => WC_Stripe_Helper::get_stripe_amount( $product->get_price() ),
328
  'pending' => true,
329
- );
330
 
331
  $data['requestShipping'] = ( wc_shipping_enabled() && $product->needs_shipping() );
332
  $data['currency'] = strtolower( get_woocommerce_currency() );
@@ -372,7 +372,7 @@ class WC_Stripe_Payment_Request {
372
  return $valid;
373
  }
374
 
375
- $payment_request_type = isset( $_POST['payment_request_type'] ) ? wc_clean( $_POST['payment_request_type'] ) : '';
376
 
377
  if ( 'apple_pay' !== $payment_request_type ) {
378
  return $valid;
@@ -408,7 +408,7 @@ class WC_Stripe_Payment_Request {
408
 
409
  $order = wc_get_order( $order_id );
410
 
411
- $payment_request_type = wc_clean( $_POST['payment_request_type'] );
412
 
413
  if ( 'apple_pay' === $payment_request_type ) {
414
  $order->set_payment_method_title( 'Apple Pay (Stripe)' );
@@ -431,7 +431,7 @@ class WC_Stripe_Payment_Request {
431
  public function supported_product_types() {
432
  return apply_filters(
433
  'wc_stripe_payment_request_supported_types',
434
- array(
435
  'simple',
436
  'variable',
437
  'variation',
@@ -442,7 +442,7 @@ class WC_Stripe_Payment_Request {
442
  'bundle',
443
  'composite',
444
  'mix-and-match',
445
- )
446
  );
447
  }
448
 
@@ -504,13 +504,13 @@ class WC_Stripe_Payment_Request {
504
 
505
  $suffix = defined( 'SCRIPT_DEBUG' ) && SCRIPT_DEBUG ? '' : '.min';
506
 
507
- $stripe_params = array(
508
  'ajax_url' => WC_AJAX::get_endpoint( '%%endpoint%%' ),
509
- 'stripe' => array(
510
  'key' => $this->publishable_key,
511
  'allow_prepaid_card' => apply_filters( 'wc_stripe_allow_prepaid_card', true ) ? 'yes' : 'no',
512
- ),
513
- 'nonce' => array(
514
  'payment' => wp_create_nonce( 'wc-stripe-payment-request' ),
515
  'shipping' => wp_create_nonce( 'wc-stripe-payment-request-shipping' ),
516
  'update_shipping' => wp_create_nonce( 'wc-stripe-update-shipping-method' ),
@@ -519,21 +519,21 @@ class WC_Stripe_Payment_Request {
519
  'get_selected_product_data' => wp_create_nonce( 'wc-stripe-get-selected-product-data' ),
520
  'log_errors' => wp_create_nonce( 'wc-stripe-log-errors' ),
521
  'clear_cart' => wp_create_nonce( 'wc-stripe-clear-cart' ),
522
- ),
523
- 'i18n' => array(
524
  'no_prepaid_card' => __( 'Sorry, we\'re not accepting prepaid cards at this time.', 'woocommerce-gateway-stripe' ),
525
  /* translators: Do not translate the [option] placeholder */
526
  'unknown_shipping' => __( 'Unknown shipping option "[option]".', 'woocommerce-gateway-stripe' ),
527
- ),
528
- 'checkout' => array(
529
  'url' => wc_get_checkout_url(),
530
  'currency_code' => strtolower( get_woocommerce_currency() ),
531
  'country_code' => substr( get_option( 'woocommerce_default_country' ), 0, 2 ),
532
  'needs_shipping' => WC()->cart->needs_shipping() ? 'yes' : 'no',
533
  // Defaults to 'required' to match how core initializes this option.
534
  'needs_payer_phone' => 'required' === get_option( 'woocommerce_checkout_phone_field', 'required' ),
535
- ),
536
- 'button' => array(
537
  'type' => $this->get_button_type(),
538
  'theme' => $this->get_button_theme(),
539
  'height' => $this->get_button_height(),
@@ -542,13 +542,13 @@ class WC_Stripe_Payment_Request {
542
  'is_branded' => $this->is_branded_button(),
543
  'css_selector' => $this->custom_button_selector(),
544
  'branded_type' => $this->get_button_branded_type(),
545
- ),
546
  'is_product_page' => is_product(),
547
  'product' => $this->get_product_data(),
548
- );
549
 
550
  wp_register_script( 'stripe', 'https://js.stripe.com/v3/', '', '3.0', true );
551
- wp_register_script( 'wc_stripe_payment_request', plugins_url( 'assets/js/stripe-payment-request' . $suffix . '.js', WC_STRIPE_MAIN_FILE ), array( 'jquery', 'stripe' ), WC_STRIPE_VERSION, true );
552
 
553
  wp_localize_script( 'wc_stripe_payment_request', 'wc_stripe_payment_request_params', apply_filters( 'wc_stripe_payment_request_params', $stripe_params ) );
554
 
@@ -585,19 +585,19 @@ class WC_Stripe_Payment_Request {
585
 
586
  if ( is_product() && ! $this->should_show_payment_button_on_product_page() ) {
587
  return;
588
- } else if ( ! $this->should_show_payment_button_on_cart() ) {
589
  return;
590
  }
591
  ?>
592
  <div id="wc-stripe-payment-request-wrapper" style="clear:both;padding-top:1.5em;display:none;">
593
  <div id="wc-stripe-payment-request-button">
594
  <?php
595
- if ( $this->is_custom_button() ) {
596
- $label = esc_html( $this->get_button_label() );
597
- $class_name = esc_attr( 'button ' . $this->get_button_theme() );
598
- $style = esc_attr( 'height:' . $this->get_button_height() . 'px;' );
599
- echo "<button id=\"wc-stripe-custom-button\" class=\"$class_name\" style=\"$style\"> $label </button>";
600
- }
601
  ?>
602
  <!-- A Stripe Element will be inserted here. -->
603
  </div>
@@ -630,7 +630,7 @@ class WC_Stripe_Payment_Request {
630
 
631
  if ( is_product() && ! $this->should_show_payment_button_on_product_page() ) {
632
  return;
633
- } else if ( ! $this->should_show_payment_button_on_cart() ) {
634
  return;
635
  }
636
  ?>
@@ -707,7 +707,7 @@ class WC_Stripe_Payment_Request {
707
  public function ajax_log_errors() {
708
  check_ajax_referer( 'wc-stripe-log-errors', 'security' );
709
 
710
- $errors = wc_clean( stripslashes( $_POST['errors'] ) );
711
 
712
  WC_Stripe_Logger::log( $errors );
713
 
@@ -742,13 +742,13 @@ class WC_Stripe_Payment_Request {
742
  $currency = get_woocommerce_currency();
743
 
744
  // Set mandatory payment details.
745
- $data = array(
746
  'shipping_required' => WC()->cart->needs_shipping(),
747
- 'order_data' => array(
748
  'currency' => strtolower( $currency ),
749
  'country_code' => substr( get_option( 'woocommerce_default_country' ), 0, 2 ),
750
- ),
751
- );
752
 
753
  $data['order_data'] += $this->build_display_items();
754
 
@@ -765,19 +765,19 @@ class WC_Stripe_Payment_Request {
765
  public function ajax_get_shipping_options() {
766
  check_ajax_referer( 'wc-stripe-payment-request-shipping', 'security' );
767
 
768
- $shipping_address = filter_input_array(
769
  INPUT_POST,
770
- array(
771
  'country' => FILTER_SANITIZE_STRING,
772
  'state' => FILTER_SANITIZE_STRING,
773
  'postcode' => FILTER_SANITIZE_STRING,
774
  'city' => FILTER_SANITIZE_STRING,
775
  'address' => FILTER_SANITIZE_STRING,
776
  'address_2' => FILTER_SANITIZE_STRING,
777
- )
778
  );
779
  $product_view_options = filter_input_array( INPUT_POST, [ 'is_product_page' => FILTER_SANITIZE_STRING ] );
780
- $should_show_itemized_view = ! isset( $product_view_options['is_product_page'] ) ?: filter_var( $product_view_options['is_product_page'], FILTER_VALIDATE_BOOLEAN );
781
 
782
  $data = $this->get_shipping_options( $shipping_address, $should_show_itemized_view );
783
  wp_send_json( $data );
@@ -795,7 +795,7 @@ class WC_Stripe_Payment_Request {
795
  public function get_shipping_options( $shipping_address, $itemized_display_items = false ) {
796
  try {
797
  // Set the shipping options.
798
- $data = array();
799
 
800
  // Remember current shipping method before resetting.
801
  $chosen_shipping_methods = WC()->session->get( 'chosen_shipping_methods' );
@@ -810,12 +810,12 @@ class WC_Stripe_Payment_Request {
810
  }
811
 
812
  foreach ( $package['rates'] as $key => $rate ) {
813
- $data['shipping_options'][] = array(
814
  'id' => $rate->id,
815
  'label' => $rate->label,
816
  'detail' => '',
817
  'amount' => WC_Stripe_Helper::get_stripe_amount( $rate->cost ),
818
- );
819
  }
820
  }
821
  } else {
@@ -874,9 +874,9 @@ class WC_Stripe_Payment_Request {
874
  WC()->cart->calculate_totals();
875
 
876
  $product_view_options = filter_input_array( INPUT_POST, [ 'is_product_page' => FILTER_SANITIZE_STRING ] );
877
- $should_show_itemized_view = ! isset( $product_view_options['is_product_page'] ) ?: filter_var( $product_view_options['is_product_page'], FILTER_VALIDATE_BOOLEAN );
878
 
879
- $data = array();
880
  $data += $this->build_display_items( $should_show_itemized_view );
881
  $data['result'] = 'success';
882
 
@@ -911,13 +911,14 @@ class WC_Stripe_Payment_Request {
911
  check_ajax_referer( 'wc-stripe-get-selected-product-data', 'security' );
912
 
913
  try {
914
- $product_id = absint( $_POST['product_id'] );
915
  $qty = ! isset( $_POST['qty'] ) ? 1 : apply_filters( 'woocommerce_add_to_cart_quantity', absint( $_POST['qty'] ), $product_id );
916
  $addon_value = isset( $_POST['addon_value'] ) ? max( floatval( $_POST['addon_value'] ), 0 ) : 0;
917
  $product = wc_get_product( $product_id );
918
  $variation_id = null;
919
 
920
  if ( ! is_a( $product, 'WC_Product' ) ) {
 
921
  throw new Exception( sprintf( __( 'Product with the ID (%d) cannot be found.', 'woocommerce-gateway-stripe' ), $product_id ) );
922
  }
923
 
@@ -946,43 +947,43 @@ class WC_Stripe_Payment_Request {
946
 
947
  $quantity_label = 1 < $qty ? ' (x' . $qty . ')' : '';
948
 
949
- $data = array();
950
- $items = array();
951
 
952
- $items[] = array(
953
  'label' => $product->get_name() . $quantity_label,
954
  'amount' => WC_Stripe_Helper::get_stripe_amount( $total ),
955
- );
956
 
957
  if ( wc_tax_enabled() ) {
958
- $items[] = array(
959
  'label' => __( 'Tax', 'woocommerce-gateway-stripe' ),
960
  'amount' => 0,
961
  'pending' => true,
962
- );
963
  }
964
 
965
  if ( wc_shipping_enabled() && $product->needs_shipping() ) {
966
- $items[] = array(
967
  'label' => __( 'Shipping', 'woocommerce-gateway-stripe' ),
968
  'amount' => 0,
969
  'pending' => true,
970
- );
971
 
972
- $data['shippingOptions'] = array(
973
  'id' => 'pending',
974
  'label' => __( 'Pending', 'woocommerce-gateway-stripe' ),
975
  'detail' => '',
976
  'amount' => 0,
977
- );
978
  }
979
 
980
  $data['displayItems'] = $items;
981
- $data['total'] = array(
982
  'label' => $this->total_label,
983
  'amount' => WC_Stripe_Helper::get_stripe_amount( $total ),
984
  'pending' => true,
985
- );
986
 
987
  $data['requestShipping'] = ( wc_shipping_enabled() && $product->needs_shipping() );
988
  $data['currency'] = strtolower( get_woocommerce_currency() );
@@ -990,7 +991,7 @@ class WC_Stripe_Payment_Request {
990
 
991
  wp_send_json( $data );
992
  } catch ( Exception $e ) {
993
- wp_send_json( array( 'error' => wp_strip_all_tags( $e->getMessage() ) ) );
994
  }
995
  }
996
 
@@ -1010,7 +1011,7 @@ class WC_Stripe_Payment_Request {
1010
 
1011
  WC()->shipping->reset_shipping();
1012
 
1013
- $product_id = absint( $_POST['product_id'] );
1014
  $qty = ! isset( $_POST['qty'] ) ? 1 : absint( $_POST['qty'] );
1015
  $product = wc_get_product( $product_id );
1016
  $product_type = $product->get_type();
@@ -1033,7 +1034,7 @@ class WC_Stripe_Payment_Request {
1033
 
1034
  WC()->cart->calculate_totals();
1035
 
1036
- $data = array();
1037
  $data += $this->build_display_items();
1038
  $data['result'] = 'success';
1039
 
@@ -1041,45 +1042,83 @@ class WC_Stripe_Payment_Request {
1041
  }
1042
 
1043
  /**
1044
- * Normalizes the state/county field because in some
1045
- * cases, the state/county field is formatted differently from
1046
- * what WC is expecting and throws an error. An example
1047
- * for Ireland the county dropdown in Chrome shows "Co. Clare" format
1048
  *
1049
- * @since 4.0.0
1050
- * @version 4.0.0
1051
  */
1052
  public function normalize_state() {
1053
- $billing_country = ! empty( $_POST['billing_country'] ) ? wc_clean( $_POST['billing_country'] ) : '';
1054
- $shipping_country = ! empty( $_POST['shipping_country'] ) ? wc_clean( $_POST['shipping_country'] ) : '';
1055
- $billing_state = ! empty( $_POST['billing_state'] ) ? wc_clean( $_POST['billing_state'] ) : '';
1056
- $shipping_state = ! empty( $_POST['shipping_state'] ) ? wc_clean( $_POST['shipping_state'] ) : '';
1057
 
1058
  if ( $billing_state && $billing_country ) {
1059
- $valid_states = WC()->countries->get_states( $billing_country );
1060
-
1061
- // Valid states found for country.
1062
- if ( ! empty( $valid_states ) && is_array( $valid_states ) && sizeof( $valid_states ) > 0 ) {
1063
- foreach ( $valid_states as $state_abbr => $state ) {
1064
- if ( preg_match( '/' . preg_quote( $state ) . '/i', $billing_state ) ) {
1065
- $_POST['billing_state'] = $state_abbr;
1066
- }
1067
- }
1068
- }
1069
  }
1070
 
1071
  if ( $shipping_state && $shipping_country ) {
1072
- $valid_states = WC()->countries->get_states( $shipping_country );
 
 
1073
 
1074
- // Valid states found for country.
1075
- if ( ! empty( $valid_states ) && is_array( $valid_states ) && sizeof( $valid_states ) > 0 ) {
1076
- foreach ( $valid_states as $state_abbr => $state ) {
1077
- if ( preg_match( '/' . preg_quote( $state ) . '/i', $shipping_state ) ) {
1078
- $_POST['shipping_state'] = $state_abbr;
1079
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1080
  }
1081
  }
1082
  }
 
 
1083
  }
1084
 
1085
  /**
@@ -1097,6 +1136,7 @@ class WC_Stripe_Payment_Request {
1097
  define( 'WOOCOMMERCE_CHECKOUT', true );
1098
  }
1099
 
 
1100
  $this->normalize_state();
1101
 
1102
  WC()->checkout()->process_checkout();
@@ -1110,24 +1150,18 @@ class WC_Stripe_Payment_Request {
1110
  * @param array $address Shipping address.
1111
  *
1112
  * @since 3.1.0
1113
- * @version 4.0.0
1114
  */
1115
- protected function calculate_shipping( $address = array() ) {
1116
  $country = $address['country'];
1117
  $state = $address['state'];
1118
  $postcode = $address['postcode'];
1119
  $city = $address['city'];
1120
  $address_1 = $address['address'];
1121
  $address_2 = $address['address_2'];
1122
- $wc_states = WC()->countries->get_states( $country );
1123
 
1124
- /**
1125
- * In some versions of Chrome, state can be a full name. So we need
1126
- * to convert that to abbreviation as WC is expecting that.
1127
- */
1128
- if ( 2 < strlen( $state ) && ! empty( $wc_states ) && ! isset( $wc_states[ $state ] ) ) {
1129
- $state = array_search( ucwords( strtolower( $state ) ), $wc_states, true );
1130
- }
1131
 
1132
  WC()->shipping->reset_shipping();
1133
 
@@ -1146,7 +1180,7 @@ class WC_Stripe_Payment_Request {
1146
  WC()->customer->set_calculated_shipping( true );
1147
  WC()->customer->save();
1148
 
1149
- $packages = array();
1150
 
1151
  $packages[0]['contents'] = WC()->cart->get_cart();
1152
  $packages[0]['contents_cost'] = 0;
@@ -1180,18 +1214,18 @@ class WC_Stripe_Payment_Request {
1180
  */
1181
  protected function build_shipping_methods( $shipping_methods ) {
1182
  if ( empty( $shipping_methods ) ) {
1183
- return array();
1184
  }
1185
 
1186
- $shipping = array();
1187
 
1188
  foreach ( $shipping_methods as $method ) {
1189
- $shipping[] = array(
1190
  'id' => $method['id'],
1191
  'label' => $method['label'],
1192
  'detail' => '',
1193
  'amount' => WC_Stripe_Helper::get_stripe_amount( $method['amount']['value'] ),
1194
- );
1195
  }
1196
 
1197
  return $shipping;
@@ -1208,7 +1242,7 @@ class WC_Stripe_Payment_Request {
1208
  define( 'WOOCOMMERCE_CART', true );
1209
  }
1210
 
1211
- $items = array();
1212
  $subtotal = 0;
1213
  $discounts = 0;
1214
 
@@ -1221,10 +1255,10 @@ class WC_Stripe_Payment_Request {
1221
 
1222
  $product_name = $cart_item['data']->get_name();
1223
 
1224
- $item = array(
1225
  'label' => $product_name . $quantity_label,
1226
  'amount' => WC_Stripe_Helper::get_stripe_amount( $amount ),
1227
- );
1228
 
1229
  $items[] = $item;
1230
  }
@@ -1247,24 +1281,24 @@ class WC_Stripe_Payment_Request {
1247
  $order_total = version_compare( WC_VERSION, '3.2', '<' ) ? wc_format_decimal( $items_total + $tax + $shipping - $discounts, WC()->cart->dp ) : WC()->cart->get_total( false );
1248
 
1249
  if ( wc_tax_enabled() ) {
1250
- $items[] = array(
1251
  'label' => esc_html( __( 'Tax', 'woocommerce-gateway-stripe' ) ),
1252
  'amount' => WC_Stripe_Helper::get_stripe_amount( $tax ),
1253
- );
1254
  }
1255
 
1256
  if ( WC()->cart->needs_shipping() ) {
1257
- $items[] = array(
1258
  'label' => esc_html( __( 'Shipping', 'woocommerce-gateway-stripe' ) ),
1259
  'amount' => WC_Stripe_Helper::get_stripe_amount( $shipping ),
1260
- );
1261
  }
1262
 
1263
  if ( WC()->cart->has_discount() ) {
1264
- $items[] = array(
1265
  'label' => esc_html( __( 'Discount', 'woocommerce-gateway-stripe' ) ),
1266
  'amount' => WC_Stripe_Helper::get_stripe_amount( $discounts ),
1267
- );
1268
  }
1269
 
1270
  if ( version_compare( WC_VERSION, '3.2', '<' ) ) {
@@ -1275,20 +1309,20 @@ class WC_Stripe_Payment_Request {
1275
 
1276
  // Include fees and taxes as display items.
1277
  foreach ( $cart_fees as $key => $fee ) {
1278
- $items[] = array(
1279
  'label' => $fee->name,
1280
  'amount' => WC_Stripe_Helper::get_stripe_amount( $fee->amount ),
1281
- );
1282
  }
1283
 
1284
- return array(
1285
  'displayItems' => $items,
1286
- 'total' => array(
1287
  'label' => $this->total_label,
1288
  'amount' => max( 0, apply_filters( 'woocommerce_stripe_calculated_total', WC_Stripe_Helper::get_stripe_amount( $order_total ), $order_total, WC()->cart ) ),
1289
  'pending' => false,
1290
- ),
1291
- );
1292
  }
1293
  }
1294
 
66
  */
67
  public function __construct() {
68
  self::$_this = $this;
69
+ $this->stripe_settings = get_option( 'woocommerce_stripe_settings', [] );
70
  $this->testmode = ( ! empty( $this->stripe_settings['testmode'] ) && 'yes' === $this->stripe_settings['testmode'] ) ? true : false;
71
  $this->publishable_key = ! empty( $this->stripe_settings['publishable_key'] ) ? $this->stripe_settings['publishable_key'] : '';
72
  $this->secret_key = ! empty( $this->stripe_settings['secret_key'] ) ? $this->stripe_settings['secret_key'] : '';
94
  return;
95
  }
96
 
97
+ add_action( 'template_redirect', [ $this, 'set_session' ] );
98
  $this->init();
99
  }
100
 
109
  // in includes/abstracts/abstract-wc-stripe-payment-gateway.php
110
  if ( $this->testmode ) {
111
  return preg_match( '/^pk_test_/', $this->publishable_key )
112
+ && preg_match( '/^[rs]k_test_/', $this->secret_key );
113
  } else {
114
  return preg_match( '/^pk_live_/', $this->publishable_key )
115
+ && preg_match( '/^[rs]k_live_/', $this->secret_key );
116
  }
117
  }
118
 
149
  * @return void
150
  */
151
  public function init() {
152
+ add_action( 'wp_enqueue_scripts', [ $this, 'scripts' ] );
153
 
154
+ add_action( 'woocommerce_after_add_to_cart_quantity', [ $this, 'display_payment_request_button_html' ], 1 );
155
+ add_action( 'woocommerce_after_add_to_cart_quantity', [ $this, 'display_payment_request_button_separator_html' ], 2 );
156
 
157
+ add_action( 'woocommerce_proceed_to_checkout', [ $this, 'display_payment_request_button_html' ], 1 );
158
+ add_action( 'woocommerce_proceed_to_checkout', [ $this, 'display_payment_request_button_separator_html' ], 2 );
159
 
160
+ add_action( 'woocommerce_checkout_before_customer_details', [ $this, 'display_payment_request_button_html' ], 1 );
161
+ add_action( 'woocommerce_checkout_before_customer_details', [ $this, 'display_payment_request_button_separator_html' ], 2 );
162
 
163
+ add_action( 'wc_ajax_wc_stripe_get_cart_details', [ $this, 'ajax_get_cart_details' ] );
164
+ add_action( 'wc_ajax_wc_stripe_get_shipping_options', [ $this, 'ajax_get_shipping_options' ] );
165
+ add_action( 'wc_ajax_wc_stripe_update_shipping_method', [ $this, 'ajax_update_shipping_method' ] );
166
+ add_action( 'wc_ajax_wc_stripe_create_order', [ $this, 'ajax_create_order' ] );
167
+ add_action( 'wc_ajax_wc_stripe_add_to_cart', [ $this, 'ajax_add_to_cart' ] );
168
+ add_action( 'wc_ajax_wc_stripe_get_selected_product_data', [ $this, 'ajax_get_selected_product_data' ] );
169
+ add_action( 'wc_ajax_wc_stripe_clear_cart', [ $this, 'ajax_clear_cart' ] );
170
+ add_action( 'wc_ajax_wc_stripe_log_errors', [ $this, 'ajax_log_errors' ] );
171
 
172
+ add_filter( 'woocommerce_gateway_title', [ $this, 'filter_gateway_title' ], 10, 2 );
173
+ add_filter( 'woocommerce_validate_postcode', [ $this, 'postal_code_validation' ], 10, 3 );
174
 
175
+ add_action( 'woocommerce_checkout_order_processed', [ $this, 'add_order_meta' ], 10, 2 );
176
  }
177
 
178
  /**
290
  }
291
  }
292
 
293
+ $data = [];
294
+ $items = [];
295
 
296
+ $items[] = [
297
  'label' => $product->get_name(),
298
  'amount' => WC_Stripe_Helper::get_stripe_amount( $product->get_price() ),
299
+ ];
300
 
301
  if ( wc_tax_enabled() ) {
302
+ $items[] = [
303
  'label' => __( 'Tax', 'woocommerce-gateway-stripe' ),
304
  'amount' => 0,
305
  'pending' => true,
306
+ ];
307
  }
308
 
309
  if ( wc_shipping_enabled() && $product->needs_shipping() ) {
310
+ $items[] = [
311
  'label' => __( 'Shipping', 'woocommerce-gateway-stripe' ),
312
  'amount' => 0,
313
  'pending' => true,
314
+ ];
315
 
316
+ $data['shippingOptions'] = [
317
  'id' => 'pending',
318
  'label' => __( 'Pending', 'woocommerce-gateway-stripe' ),
319
  'detail' => '',
320
  'amount' => 0,
321
+ ];
322
  }
323
 
324
  $data['displayItems'] = $items;
325
+ $data['total'] = [
326
  'label' => apply_filters( 'wc_stripe_payment_request_total_label', $this->total_label ),
327
  'amount' => WC_Stripe_Helper::get_stripe_amount( $product->get_price() ),
328
  'pending' => true,
329
+ ];
330
 
331
  $data['requestShipping'] = ( wc_shipping_enabled() && $product->needs_shipping() );
332
  $data['currency'] = strtolower( get_woocommerce_currency() );
372
  return $valid;
373
  }
374
 
375
+ $payment_request_type = isset( $_POST['payment_request_type'] ) ? wc_clean( wp_unslash( $_POST['payment_request_type'] ) ) : '';
376
 
377
  if ( 'apple_pay' !== $payment_request_type ) {
378
  return $valid;
408
 
409
  $order = wc_get_order( $order_id );
410
 
411
+ $payment_request_type = wc_clean( wp_unslash( $_POST['payment_request_type'] ) );
412
 
413
  if ( 'apple_pay' === $payment_request_type ) {
414
  $order->set_payment_method_title( 'Apple Pay (Stripe)' );
431
  public function supported_product_types() {
432
  return apply_filters(
433
  'wc_stripe_payment_request_supported_types',
434
+ [
435
  'simple',
436
  'variable',
437
  'variation',
442
  'bundle',
443
  'composite',
444
  'mix-and-match',
445
+ ]
446
  );
447
  }
448
 
504
 
505
  $suffix = defined( 'SCRIPT_DEBUG' ) && SCRIPT_DEBUG ? '' : '.min';
506
 
507
+ $stripe_params = [
508
  'ajax_url' => WC_AJAX::get_endpoint( '%%endpoint%%' ),
509
+ 'stripe' => [
510
  'key' => $this->publishable_key,
511
  'allow_prepaid_card' => apply_filters( 'wc_stripe_allow_prepaid_card', true ) ? 'yes' : 'no',
512
+ ],
513
+ 'nonce' => [
514
  'payment' => wp_create_nonce( 'wc-stripe-payment-request' ),
515
  'shipping' => wp_create_nonce( 'wc-stripe-payment-request-shipping' ),
516
  'update_shipping' => wp_create_nonce( 'wc-stripe-update-shipping-method' ),
519
  'get_selected_product_data' => wp_create_nonce( 'wc-stripe-get-selected-product-data' ),
520
  'log_errors' => wp_create_nonce( 'wc-stripe-log-errors' ),
521
  'clear_cart' => wp_create_nonce( 'wc-stripe-clear-cart' ),
522
+ ],
523
+ 'i18n' => [
524
  'no_prepaid_card' => __( 'Sorry, we\'re not accepting prepaid cards at this time.', 'woocommerce-gateway-stripe' ),
525
  /* translators: Do not translate the [option] placeholder */
526
  'unknown_shipping' => __( 'Unknown shipping option "[option]".', 'woocommerce-gateway-stripe' ),
527
+ ],
528
+ 'checkout' => [
529
  'url' => wc_get_checkout_url(),
530
  'currency_code' => strtolower( get_woocommerce_currency() ),
531
  'country_code' => substr( get_option( 'woocommerce_default_country' ), 0, 2 ),
532
  'needs_shipping' => WC()->cart->needs_shipping() ? 'yes' : 'no',
533
  // Defaults to 'required' to match how core initializes this option.
534
  'needs_payer_phone' => 'required' === get_option( 'woocommerce_checkout_phone_field', 'required' ),
535
+ ],
536
+ 'button' => [
537
  'type' => $this->get_button_type(),
538
  'theme' => $this->get_button_theme(),
539
  'height' => $this->get_button_height(),
542
  'is_branded' => $this->is_branded_button(),
543
  'css_selector' => $this->custom_button_selector(),
544
  'branded_type' => $this->get_button_branded_type(),
545
+ ],
546
  'is_product_page' => is_product(),
547
  'product' => $this->get_product_data(),
548
+ ];
549
 
550
  wp_register_script( 'stripe', 'https://js.stripe.com/v3/', '', '3.0', true );
551
+ wp_register_script( 'wc_stripe_payment_request', plugins_url( 'assets/js/stripe-payment-request' . $suffix . '.js', WC_STRIPE_MAIN_FILE ), [ 'jquery', 'stripe' ], WC_STRIPE_VERSION, true );
552
 
553
  wp_localize_script( 'wc_stripe_payment_request', 'wc_stripe_payment_request_params', apply_filters( 'wc_stripe_payment_request_params', $stripe_params ) );
554
 
585
 
586
  if ( is_product() && ! $this->should_show_payment_button_on_product_page() ) {
587
  return;
588
+ } elseif ( ! $this->should_show_payment_button_on_cart() ) {
589
  return;
590
  }
591
  ?>
592
  <div id="wc-stripe-payment-request-wrapper" style="clear:both;padding-top:1.5em;display:none;">
593
  <div id="wc-stripe-payment-request-button">
594
  <?php
595
+ if ( $this->is_custom_button() ) {
596
+ $label = esc_html( $this->get_button_label() );
597
+ $class_name = esc_attr( 'button ' . $this->get_button_theme() );
598
+ $style = esc_attr( 'height:' . $this->get_button_height() . 'px;' );
599
+ echo "<button id=\"wc-stripe-custom-button\" class=\"$class_name\" style=\"$style\"> $label </button>";
600
+ }
601
  ?>
602
  <!-- A Stripe Element will be inserted here. -->
603
  </div>
630
 
631
  if ( is_product() && ! $this->should_show_payment_button_on_product_page() ) {
632
  return;
633
+ } elseif ( ! $this->should_show_payment_button_on_cart() ) {
634
  return;
635
  }
636
  ?>
707
  public function ajax_log_errors() {
708
  check_ajax_referer( 'wc-stripe-log-errors', 'security' );
709
 
710
+ $errors = isset( $_POST['errors'] ) ? wc_clean( wp_unslash( $_POST['errors'] ) ) : '';
711
 
712
  WC_Stripe_Logger::log( $errors );
713
 
742
  $currency = get_woocommerce_currency();
743
 
744
  // Set mandatory payment details.
745
+ $data = [
746
  'shipping_required' => WC()->cart->needs_shipping(),
747
+ 'order_data' => [
748
  'currency' => strtolower( $currency ),
749
  'country_code' => substr( get_option( 'woocommerce_default_country' ), 0, 2 ),
750
+ ],
751
+ ];
752
 
753
  $data['order_data'] += $this->build_display_items();
754
 
765
  public function ajax_get_shipping_options() {
766
  check_ajax_referer( 'wc-stripe-payment-request-shipping', 'security' );
767
 
768
+ $shipping_address = filter_input_array(
769
  INPUT_POST,
770
+ [
771
  'country' => FILTER_SANITIZE_STRING,
772
  'state' => FILTER_SANITIZE_STRING,
773
  'postcode' => FILTER_SANITIZE_STRING,
774
  'city' => FILTER_SANITIZE_STRING,
775
  'address' => FILTER_SANITIZE_STRING,
776
  'address_2' => FILTER_SANITIZE_STRING,
777
+ ]
778
  );
779
  $product_view_options = filter_input_array( INPUT_POST, [ 'is_product_page' => FILTER_SANITIZE_STRING ] );
780
+ $should_show_itemized_view = ! isset( $product_view_options['is_product_page'] ) ? true : filter_var( $product_view_options['is_product_page'], FILTER_VALIDATE_BOOLEAN );
781
 
782
  $data = $this->get_shipping_options( $shipping_address, $should_show_itemized_view );
783
  wp_send_json( $data );
795
  public function get_shipping_options( $shipping_address, $itemized_display_items = false ) {
796
  try {
797
  // Set the shipping options.
798
+ $data = [];
799
 
800
  // Remember current shipping method before resetting.
801
  $chosen_shipping_methods = WC()->session->get( 'chosen_shipping_methods' );
810
  }
811
 
812
  foreach ( $package['rates'] as $key => $rate ) {
813
+ $data['shipping_options'][] = [
814
  'id' => $rate->id,
815
  'label' => $rate->label,
816
  'detail' => '',
817
  'amount' => WC_Stripe_Helper::get_stripe_amount( $rate->cost ),
818
+ ];
819
  }
820
  }
821
  } else {
874
  WC()->cart->calculate_totals();
875
 
876
  $product_view_options = filter_input_array( INPUT_POST, [ 'is_product_page' => FILTER_SANITIZE_STRING ] );
877
+ $should_show_itemized_view = ! isset( $product_view_options['is_product_page'] ) ? true : filter_var( $product_view_options['is_product_page'], FILTER_VALIDATE_BOOLEAN );
878
 
879
+ $data = [];
880
  $data += $this->build_display_items( $should_show_itemized_view );
881
  $data['result'] = 'success';
882
 
911
  check_ajax_referer( 'wc-stripe-get-selected-product-data', 'security' );
912
 
913
  try {
914
+ $product_id = isset( $_POST['product_id'] ) ? absint( $_POST['product_id'] ) : 0;
915
  $qty = ! isset( $_POST['qty'] ) ? 1 : apply_filters( 'woocommerce_add_to_cart_quantity', absint( $_POST['qty'] ), $product_id );
916
  $addon_value = isset( $_POST['addon_value'] ) ? max( floatval( $_POST['addon_value'] ), 0 ) : 0;
917
  $product = wc_get_product( $product_id );
918
  $variation_id = null;
919
 
920
  if ( ! is_a( $product, 'WC_Product' ) ) {
921
+ /* translators: %d is the product Id */
922
  throw new Exception( sprintf( __( 'Product with the ID (%d) cannot be found.', 'woocommerce-gateway-stripe' ), $product_id ) );
923
  }
924
 
947
 
948
  $quantity_label = 1 < $qty ? ' (x' . $qty . ')' : '';
949
 
950
+ $data = [];
951
+ $items = [];
952
 
953
+ $items[] = [
954
  'label' => $product->get_name() . $quantity_label,
955
  'amount' => WC_Stripe_Helper::get_stripe_amount( $total ),
956
+ ];
957
 
958
  if ( wc_tax_enabled() ) {
959
+ $items[] = [
960
  'label' => __( 'Tax', 'woocommerce-gateway-stripe' ),
961
  'amount' => 0,
962
  'pending' => true,
963
+ ];
964
  }
965
 
966
  if ( wc_shipping_enabled() && $product->needs_shipping() ) {
967
+ $items[] = [
968
  'label' => __( 'Shipping', 'woocommerce-gateway-stripe' ),
969
  'amount' => 0,
970
  'pending' => true,
971
+ ];
972
 
973
+ $data['shippingOptions'] = [
974
  'id' => 'pending',
975
  'label' => __( 'Pending', 'woocommerce-gateway-stripe' ),
976
  'detail' => '',
977
  'amount' => 0,
978
+ ];
979
  }
980
 
981
  $data['displayItems'] = $items;
982
+ $data['total'] = [
983
  'label' => $this->total_label,
984
  'amount' => WC_Stripe_Helper::get_stripe_amount( $total ),
985
  'pending' => true,
986
+ ];
987
 
988
  $data['requestShipping'] = ( wc_shipping_enabled() && $product->needs_shipping() );
989
  $data['currency'] = strtolower( get_woocommerce_currency() );
991
 
992
  wp_send_json( $data );
993
  } catch ( Exception $e ) {
994
+ wp_send_json( [ 'error' => wp_strip_all_tags( $e->getMessage() ) ] );
995
  }
996
  }
997
 
1011
 
1012
  WC()->shipping->reset_shipping();
1013
 
1014
+ $product_id = isset( $_POST['product_id'] ) ? absint( $_POST['product_id'] ) : 0;
1015
  $qty = ! isset( $_POST['qty'] ) ? 1 : absint( $_POST['qty'] );
1016
  $product = wc_get_product( $product_id );
1017
  $product_type = $product->get_type();
1034
 
1035
  WC()->cart->calculate_totals();
1036
 
1037
+ $data = [];
1038
  $data += $this->build_display_items();
1039
  $data['result'] = 'success';
1040
 
1042
  }
1043
 
1044
  /**
1045
+ * Normalizes billing and shipping state fields.
 
 
 
1046
  *
1047
+ * @since 4.0.0
1048
+ * @version 5.0.0
1049
  */
1050
  public function normalize_state() {
1051
+ $billing_country = ! empty( $_POST['billing_country'] ) ? wc_clean( wp_unslash( $_POST['billing_country'] ) ) : '';
1052
+ $shipping_country = ! empty( $_POST['shipping_country'] ) ? wc_clean( wp_unslash( $_POST['shipping_country'] ) ) : '';
1053
+ $billing_state = ! empty( $_POST['billing_state'] ) ? wc_clean( wp_unslash( $_POST['billing_state'] ) ) : '';
1054
+ $shipping_state = ! empty( $_POST['shipping_state'] ) ? wc_clean( wp_unslash( $_POST['shipping_state'] ) ) : '';
1055
 
1056
  if ( $billing_state && $billing_country ) {
1057
+ $_POST['billing_state'] = $this->get_normalized_state( $billing_state, $billing_country );
 
 
 
 
 
 
 
 
 
1058
  }
1059
 
1060
  if ( $shipping_state && $shipping_country ) {
1061
+ $_POST['shipping_state'] = $this->get_normalized_state( $shipping_state, $shipping_country );
1062
+ }
1063
+ }
1064
 
1065
+ /**
1066
+ * Gets the normalized state/county field because in some
1067
+ * cases, the state/county field is formatted differently from
1068
+ * what WC is expecting and throws an error. An example
1069
+ * for Ireland the county dropdown in Chrome shows "Co. Clare" format.
1070
+ *
1071
+ * @since 5.0.0
1072
+ *
1073
+ * @param string $state Full state name or an already normalized abbreviation.
1074
+ * @param string $country Two-letter country code.
1075
+ *
1076
+ * @return string Normalized state abbreviation.
1077
+ */
1078
+ public function get_normalized_state( $state, $country ) {
1079
+ $wc_valid_states = $country ? WC()->countries->get_states( $country ) : [];
1080
+
1081
+ if ( $state && $country && is_array( $wc_valid_states ) && count( $wc_valid_states ) > 0 ) {
1082
+
1083
+ // If it's already normalized, skip.
1084
+ if ( in_array( $state, array_keys( $wc_valid_states ) ) ) {
1085
+ return $state;
1086
+ }
1087
+
1088
+ $match_from_state_input = false;
1089
+
1090
+ // China - Adapt dropdown values from Chrome and accept manually typed values like 云南.
1091
+ // WC states: https://github.com/woocommerce/woocommerce/blob/master/i18n/states.php
1092
+ if ( 'CN' === $country ) {
1093
+ $replace_map = [
1094
+ // Rename regions with different spelling.
1095
+ 'Macau' => 'Macao',
1096
+ 'Neimenggu' => 'Inner Mongolia',
1097
+ 'Xizang' => 'Tibet',
1098
+ // Remove suffixes.
1099
+ 'Shi' => '',
1100
+ 'Sheng' => '',
1101
+ 'Zizhiqu' => '',
1102
+ 'Huizuzizhiqu' => '',
1103
+ 'Weiwuerzizhiqu' => '',
1104
+ 'Zhuangzuzizhiqu' => '',
1105
+ ];
1106
+ $state = trim( str_replace( array_keys( $replace_map ), array_values( $replace_map ), $state ) );
1107
+ $match_from_state_input = true;
1108
+ }
1109
+
1110
+ foreach ( $wc_valid_states as $wc_state_abbr => $wc_state_value ) {
1111
+ // Match values either from WC states or from the state input.
1112
+ if (
1113
+ ( ! $match_from_state_input && preg_match( '/' . preg_quote( $wc_state_value, '/' ) . '/i', $state ) ) ||
1114
+ ( $match_from_state_input && preg_match( '/' . preg_quote( $state, '/' ) . '/i', $wc_state_value ) )
1115
+ ) {
1116
+ return $wc_state_abbr;
1117
  }
1118
  }
1119
  }
1120
+
1121
+ return $state;
1122
  }
1123
 
1124
  /**
1136
  define( 'WOOCOMMERCE_CHECKOUT', true );
1137
  }
1138
 
1139
+ // Normalizes billing and shipping state values.
1140
  $this->normalize_state();
1141
 
1142
  WC()->checkout()->process_checkout();
1150
  * @param array $address Shipping address.
1151
  *
1152
  * @since 3.1.0
1153
+ * @version 5.0.0
1154
  */
1155
+ protected function calculate_shipping( $address = [] ) {
1156
  $country = $address['country'];
1157
  $state = $address['state'];
1158
  $postcode = $address['postcode'];
1159
  $city = $address['city'];
1160
  $address_1 = $address['address'];
1161
  $address_2 = $address['address_2'];
 
1162
 
1163
+ // Normalizes state to calculate shipping zones.
1164
+ $state = $this->get_normalized_state( $state, $country );
 
 
 
 
 
1165
 
1166
  WC()->shipping->reset_shipping();
1167
 
1180
  WC()->customer->set_calculated_shipping( true );
1181
  WC()->customer->save();
1182
 
1183
+ $packages = [];
1184
 
1185
  $packages[0]['contents'] = WC()->cart->get_cart();
1186
  $packages[0]['contents_cost'] = 0;
1214
  */
1215
  protected function build_shipping_methods( $shipping_methods ) {
1216
  if ( empty( $shipping_methods ) ) {
1217
+ return [];
1218
  }
1219
 
1220
+ $shipping = [];
1221
 
1222
  foreach ( $shipping_methods as $method ) {
1223
+ $shipping[] = [
1224
  'id' => $method['id'],
1225
  'label' => $method['label'],
1226
  'detail' => '',
1227
  'amount' => WC_Stripe_Helper::get_stripe_amount( $method['amount']['value'] ),
1228
+ ];
1229
  }
1230
 
1231
  return $shipping;
1242
  define( 'WOOCOMMERCE_CART', true );
1243
  }
1244
 
1245
+ $items = [];
1246
  $subtotal = 0;
1247
  $discounts = 0;
1248
 
1255
 
1256
  $product_name = $cart_item['data']->get_name();
1257
 
1258
+ $item = [
1259
  'label' => $product_name . $quantity_label,
1260
  'amount' => WC_Stripe_Helper::get_stripe_amount( $amount ),
1261
+ ];
1262
 
1263
  $items[] = $item;
1264
  }
1281
  $order_total = version_compare( WC_VERSION, '3.2', '<' ) ? wc_format_decimal( $items_total + $tax + $shipping - $discounts, WC()->cart->dp ) : WC()->cart->get_total( false );
1282
 
1283
  if ( wc_tax_enabled() ) {
1284
+ $items[] = [
1285
  'label' => esc_html( __( 'Tax', 'woocommerce-gateway-stripe' ) ),
1286
  'amount' => WC_Stripe_Helper::get_stripe_amount( $tax ),
1287
+ ];
1288
  }
1289
 
1290
  if ( WC()->cart->needs_shipping() ) {
1291
+ $items[] = [
1292
  'label' => esc_html( __( 'Shipping', 'woocommerce-gateway-stripe' ) ),
1293
  'amount' => WC_Stripe_Helper::get_stripe_amount( $shipping ),
1294
+ ];
1295
  }
1296
 
1297
  if ( WC()->cart->has_discount() ) {
1298
+ $items[] = [
1299
  'label' => esc_html( __( 'Discount', 'woocommerce-gateway-stripe' ) ),
1300
  'amount' => WC_Stripe_Helper::get_stripe_amount( $discounts ),
1301
+ ];
1302
  }
1303
 
1304
  if ( version_compare( WC_VERSION, '3.2', '<' ) ) {
1309
 
1310
  // Include fees and taxes as display items.
1311
  foreach ( $cart_fees as $key => $fee ) {
1312
+ $items[] = [
1313
  'label' => $fee->name,
1314
  'amount' => WC_Stripe_Helper::get_stripe_amount( $fee->amount ),
1315
+ ];
1316
  }
1317
 
1318
+ return [
1319
  'displayItems' => $items,
1320
+ 'total' => [
1321
  'label' => $this->total_label,
1322
  'amount' => max( 0, apply_filters( 'woocommerce_stripe_calculated_total', WC_Stripe_Helper::get_stripe_amount( $order_total ), $order_total, WC()->cart ) ),
1323
  'pending' => false,
1324
+ ],
1325
+ ];
1326
  }
1327
  }
1328
 
languages/woocommerce-gateway-stripe.pot CHANGED
@@ -2,10 +2,10 @@
2
  # This file is distributed under the same license as the WooCommerce Stripe Gateway package.
3
  msgid ""
4
  msgstr ""
5
- "Project-Id-Version: WooCommerce Stripe Gateway 4.9.0\n"
6
  "Report-Msgid-Bugs-To: "
7
  "https://wordpress.org/support/plugin/woocommerce-gateway-stripe\n"
8
- "POT-Creation-Date: 2021-02-24 20:47:53+00:00\n"
9
  "MIME-Version: 1.0\n"
10
  "Content-Type: text/plain; charset=utf-8\n"
11
  "Content-Transfer-Encoding: 8bit\n"
@@ -14,61 +14,62 @@ msgstr ""
14
  "Language-Team: LANGUAGE <LL@li.org>\n"
15
  "X-Generator: node-wp-i18n 1.2.3\n"
16
 
17
- #: includes/abstracts/abstract-wc-stripe-payment-gateway.php:24
18
  #. translators: 1) webhook url
19
  msgid ""
20
  "You must add the following webhook endpoint <strong "
21
  "style=\"background-color:#ddd;\">&nbsp;%s&nbsp;</strong> to your <a "
22
  "href=\"https://dashboard.stripe.com/account/webhooks\" "
23
- "target=\"_blank\">Stripe account settings</a>. This will enable you to "
24
- "receive notifications on the charge statuses."
 
25
  msgstr ""
26
 
27
- #: includes/abstracts/abstract-wc-stripe-payment-gateway.php:39
28
  msgid "Save payment information to my account for future purchases."
29
  msgstr ""
30
 
31
- #: includes/abstracts/abstract-wc-stripe-payment-gateway.php:246
32
- #: includes/compat/class-wc-stripe-sepa-subs-compat.php:228
33
- #: includes/compat/class-wc-stripe-subs-compat.php:241
34
  #. translators: 1) amount (including currency symbol)
35
  #. translators: minimum amount
36
  msgid "Sorry, the minimum allowed order total is %1$s to use this payment method."
37
  msgstr ""
38
 
39
- #: includes/abstracts/abstract-wc-stripe-payment-gateway.php:338
40
  #. translators: 1) blog name 2) order number
41
  msgid "%1$s - Order %2$s"
42
  msgstr ""
43
 
44
- #: includes/abstracts/abstract-wc-stripe-payment-gateway.php:379
45
  msgid "customer_name"
46
  msgstr ""
47
 
48
- #: includes/abstracts/abstract-wc-stripe-payment-gateway.php:380
49
  msgid "customer_email"
50
  msgstr ""
51
 
52
- #: includes/abstracts/abstract-wc-stripe-payment-gateway.php:443
53
  #. translators: transaction id
54
  msgid "Stripe charge awaiting payment: %s."
55
  msgstr ""
56
 
57
- #: includes/abstracts/abstract-wc-stripe-payment-gateway.php:450
58
- #: includes/class-wc-stripe-order-handler.php:298
59
- #: includes/class-wc-stripe-webhook-handler.php:384
60
- #: includes/class-wc-stripe-webhook-handler.php:434
61
  #. translators: transaction id
62
  msgid "Stripe charge complete (Charge ID: %s)"
63
  msgstr ""
64
 
65
- #: includes/abstracts/abstract-wc-stripe-payment-gateway.php:455
66
  #: includes/class-wc-gateway-stripe.php:503
67
- #: includes/compat/class-wc-stripe-sepa-subs-compat.php:185
68
  msgid "Payment processing failed. Please retry."
69
  msgstr ""
70
 
71
- #: includes/abstracts/abstract-wc-stripe-payment-gateway.php:467
72
  #. translators: transaction id
73
  msgid ""
74
  "Stripe charge authorized (Charge ID: %s). Process order to take payment, or "
@@ -76,32 +77,32 @@ msgid ""
76
  "part or in full will release the authorization and cancel the payment."
77
  msgstr ""
78
 
79
- #: includes/abstracts/abstract-wc-stripe-payment-gateway.php:645
80
  msgid "Invalid payment method. Please input a new card number."
81
  msgstr ""
82
 
83
- #: includes/abstracts/abstract-wc-stripe-payment-gateway.php:914
84
  #. translators: amount (including currency symbol)
85
  msgid "Pre-Authorization for %s voided."
86
  msgstr ""
87
 
88
- #: includes/abstracts/abstract-wc-stripe-payment-gateway.php:919
89
  msgid ""
90
  "The authorization was voided and the order cancelled. Click okay to "
91
  "continue, then refresh the page."
92
  msgstr ""
93
 
94
- #: includes/abstracts/abstract-wc-stripe-payment-gateway.php:933
95
  #. translators: 1) amount (including currency symbol) 2) transaction id 3)
96
  #. refund message
97
  msgid "Refunded %1$s - Refund ID: %2$s - Reason: %3$s"
98
  msgstr ""
99
 
100
- #: includes/abstracts/abstract-wc-stripe-payment-gateway.php:951
101
  msgid "There was a problem adding the payment method."
102
  msgstr ""
103
 
104
- #: includes/admin/class-wc-stripe-admin-notices.php:125
105
  #. translators: 1) A URL that explains Stripe Radar.
106
  msgid ""
107
  "WooCommerce Stripe - We see that you had the \"Require 3D secure when "
@@ -110,7 +111,7 @@ msgid ""
110
  "href=\"%s\" target=\"_blank\">here</a>."
111
  msgstr ""
112
 
113
- #: includes/admin/class-wc-stripe-admin-notices.php:132
114
  #. translators: 1) int version 2) int version
115
  msgid ""
116
  "WooCommerce Stripe - We recently made changes to Stripe that may impact the "
@@ -120,14 +121,14 @@ msgid ""
120
  "target=\"_blank\">instructions</a> to fix."
121
  msgstr ""
122
 
123
- #: includes/admin/class-wc-stripe-admin-notices.php:142
124
  #. translators: 1) int version 2) int version
125
  msgid ""
126
  "WooCommerce Stripe - The minimum PHP version required for this plugin is "
127
  "%1$s. You are running %2$s."
128
  msgstr ""
129
 
130
- #: includes/admin/class-wc-stripe-admin-notices.php:153
131
  #. translators: 1) int version 2) int version
132
  msgid ""
133
  "WooCommerce Stripe - This is the last version of the plugin compatible with "
@@ -135,18 +136,18 @@ msgid ""
135
  "WooCommerce %2$s or greater."
136
  msgstr ""
137
 
138
- #: includes/admin/class-wc-stripe-admin-notices.php:160
139
  msgid "WooCommerce Stripe - cURL is not installed."
140
  msgstr ""
141
 
142
- #: includes/admin/class-wc-stripe-admin-notices.php:170
143
  #. translators: 1) link
144
  msgid ""
145
  "Stripe is almost ready. To get started, <a href=\"%s\">set your Stripe "
146
  "account keys</a>."
147
  msgstr ""
148
 
149
- #: includes/admin/class-wc-stripe-admin-notices.php:180
150
  #. translators: 1) link
151
  msgid ""
152
  "Stripe is in test mode however your test keys may not be valid. Test keys "
@@ -154,7 +155,7 @@ msgid ""
154
  "<a href=\"%s\">set your Stripe account keys</a>."
155
  msgstr ""
156
 
157
- #: includes/admin/class-wc-stripe-admin-notices.php:188
158
  #. translators: 1) link
159
  msgid ""
160
  "Stripe is in live mode however your live keys may not be valid. Live keys "
@@ -162,7 +163,7 @@ msgid ""
162
  "<a href=\"%s\">set your Stripe account keys</a>."
163
  msgstr ""
164
 
165
- #: includes/admin/class-wc-stripe-admin-notices.php:197
166
  #. translators: 1) link
167
  msgid ""
168
  "Stripe is enabled, but a SSL certificate is not detected. Your checkout may "
@@ -170,13 +171,14 @@ msgid ""
170
  "target=\"_blank\">SSL certificate</a>"
171
  msgstr ""
172
 
173
- #: includes/admin/class-wc-stripe-admin-notices.php:202
 
174
  msgid ""
175
  "Stripe is now ready for Strong Customer Authentication (SCA) and 3D Secure "
176
  "2! <a href=\"%1$s\" target=\"_blank\">Read about SCA</a>"
177
  msgstr ""
178
 
179
- #: includes/admin/class-wc-stripe-admin-notices.php:207
180
  #. translators: %s is a the URL for the link.
181
  msgid ""
182
  "The public and/or secret keys for the Stripe gateway have been changed. "
@@ -184,16 +186,16 @@ msgid ""
184
  "<a href=\"%s\" target=\"_blank\">Click here to learn more</a>."
185
  msgstr ""
186
 
187
- #: includes/admin/class-wc-stripe-admin-notices.php:230
188
  #. translators: %1$s Payment method, %2$s List of supported currencies
189
  msgid "%1$s is enabled - it requires store currency to be set to %2$s"
190
  msgstr ""
191
 
192
- #: includes/admin/class-wc-stripe-admin-notices.php:244
193
  msgid "Action failed. Please refresh the page and retry."
194
  msgstr ""
195
 
196
- #: includes/admin/class-wc-stripe-admin-notices.php:248
197
  msgid "Cheatin&#8217; huh?"
198
  msgstr ""
199
 
@@ -231,44 +233,44 @@ msgstr ""
231
  msgid "Learn more"
232
  msgstr ""
233
 
234
- #: includes/admin/class-wc-stripe-privacy.php:12
235
  #: includes/class-wc-gateway-stripe.php:88
236
  msgid "Stripe"
237
  msgstr ""
238
 
239
- #: includes/admin/class-wc-stripe-privacy.php:14
240
  msgid "WooCommerce Stripe Order Data"
241
  msgstr ""
242
 
243
- #: includes/admin/class-wc-stripe-privacy.php:17
244
  msgid "WooCommerce Stripe Subscriptions Data"
245
  msgstr ""
246
 
247
- #: includes/admin/class-wc-stripe-privacy.php:20
248
- #: includes/admin/class-wc-stripe-privacy.php:22
249
  msgid "WooCommerce Stripe Customer Data"
250
  msgstr ""
251
 
252
- #: includes/admin/class-wc-stripe-privacy.php:23
253
  msgid "WooCommerce Stripe Data"
254
  msgstr ""
255
 
256
- #: includes/admin/class-wc-stripe-privacy.php:37
257
  msgid "Retain Stripe Data"
258
  msgstr ""
259
 
260
- #: includes/admin/class-wc-stripe-privacy.php:38
261
  msgid "Retains any Stripe data such as Stripe customer ID, source ID."
262
  msgstr ""
263
 
264
- #: includes/admin/class-wc-stripe-privacy.php:41
265
- #: includes/compat/class-wc-stripe-sepa-subs-compat.php:482
266
- #: includes/compat/class-wc-stripe-subs-compat.php:591
267
- #: includes/compat/class-wc-stripe-subs-compat.php:606
268
  msgid "N/A"
269
  msgstr ""
270
 
271
- #: includes/admin/class-wc-stripe-privacy.php:95
272
  #. translators: %s URL to docs
273
  msgid ""
274
  "By using this extension, you may be storing personal data or sharing data "
@@ -277,54 +279,54 @@ msgid ""
277
  "policy.</a>"
278
  msgstr ""
279
 
280
- #: includes/admin/class-wc-stripe-privacy.php:118
281
  msgid "Orders"
282
  msgstr ""
283
 
284
- #: includes/admin/class-wc-stripe-privacy.php:122
285
- #: includes/admin/class-wc-stripe-privacy.php:187
286
- #: includes/admin/class-wc-stripe-privacy.php:227
287
  msgid "Stripe payment id"
288
  msgstr ""
289
 
290
- #: includes/admin/class-wc-stripe-privacy.php:126
291
- #: includes/admin/class-wc-stripe-privacy.php:191
292
- #: includes/admin/class-wc-stripe-privacy.php:231
293
  msgid "Stripe customer id"
294
  msgstr ""
295
 
296
- #: includes/admin/class-wc-stripe-privacy.php:183
297
  msgid "Subscriptions"
298
  msgstr ""
299
 
300
- #: includes/admin/class-wc-stripe-privacy.php:223
301
  msgid "Customer Data"
302
  msgstr ""
303
 
304
- #: includes/admin/class-wc-stripe-privacy.php:269
305
  msgid "Stripe User Data Erased."
306
  msgstr ""
307
 
308
- #: includes/admin/class-wc-stripe-privacy.php:345
309
- #: includes/admin/class-wc-stripe-privacy.php:382
310
  #. translators: %d Order ID
311
  msgid ""
312
  "Order ID %d is less than set retention days. Personal data retained. "
313
  "(Stripe)"
314
  msgstr ""
315
 
316
- #: includes/admin/class-wc-stripe-privacy.php:350
317
  #. translators: %d Order ID
318
  msgid ""
319
  "Order ID %d contains an active Subscription. Personal data retained. "
320
  "(Stripe)"
321
  msgstr ""
322
 
323
- #: includes/admin/class-wc-stripe-privacy.php:365
324
  msgid "Stripe Subscription Data Erased."
325
  msgstr ""
326
 
327
- #: includes/admin/class-wc-stripe-privacy.php:393
328
  msgid "Stripe personal data erased."
329
  msgstr ""
330
 
@@ -361,7 +363,7 @@ msgstr ""
361
  #: includes/admin/stripe-multibanco-settings.php:18
362
  #: includes/admin/stripe-p24-settings.php:18
363
  #: includes/admin/stripe-sepa-settings.php:22
364
- #: includes/admin/stripe-settings.php:42
365
  #: includes/admin/stripe-sofort-settings.php:22
366
  msgid "Enable/Disable"
367
  msgstr ""
@@ -378,7 +380,7 @@ msgstr ""
378
  #: includes/admin/stripe-multibanco-settings.php:25
379
  #: includes/admin/stripe-p24-settings.php:25
380
  #: includes/admin/stripe-sepa-settings.php:29
381
- #: includes/admin/stripe-settings.php:49
382
  #: includes/admin/stripe-sofort-settings.php:29
383
  msgid "Title"
384
  msgstr ""
@@ -391,7 +393,7 @@ msgstr ""
391
  #: includes/admin/stripe-multibanco-settings.php:27
392
  #: includes/admin/stripe-p24-settings.php:27
393
  #: includes/admin/stripe-sepa-settings.php:31
394
- #: includes/admin/stripe-settings.php:51
395
  #: includes/admin/stripe-sofort-settings.php:31
396
  msgid "This controls the title which the user sees during checkout."
397
  msgstr ""
@@ -408,7 +410,7 @@ msgstr ""
408
  #: includes/admin/stripe-multibanco-settings.php:32
409
  #: includes/admin/stripe-p24-settings.php:32
410
  #: includes/admin/stripe-sepa-settings.php:36
411
- #: includes/admin/stripe-settings.php:56
412
  #: includes/admin/stripe-sofort-settings.php:36
413
  msgid "Description"
414
  msgstr ""
@@ -421,7 +423,7 @@ msgstr ""
421
  #: includes/admin/stripe-multibanco-settings.php:34
422
  #: includes/admin/stripe-p24-settings.php:34
423
  #: includes/admin/stripe-sepa-settings.php:38
424
- #: includes/admin/stripe-settings.php:58
425
  #: includes/admin/stripe-sofort-settings.php:38
426
  msgid "This controls the description which the user sees during checkout."
427
  msgstr ""
@@ -438,7 +440,7 @@ msgstr ""
438
  #: includes/admin/stripe-multibanco-settings.php:39
439
  #: includes/admin/stripe-p24-settings.php:39
440
  #: includes/admin/stripe-sepa-settings.php:43
441
- #: includes/admin/stripe-settings.php:63
442
  #: includes/admin/stripe-sofort-settings.php:43
443
  msgid "Webhook Endpoints"
444
  msgstr ""
@@ -582,102 +584,104 @@ msgstr ""
582
  msgid "Mandate Information."
583
  msgstr ""
584
 
585
- #: includes/admin/stripe-settings.php:16
 
586
  msgid ""
587
  "%1$sClear all Stripe account keys.%2$s %3$sThis will disable any connection "
588
  "to Stripe.%4$s"
589
  msgstr ""
590
 
591
- #: includes/admin/stripe-settings.php:27
 
592
  msgid ""
593
  "%1$sSetup or link an existing Stripe account.%2$s By clicking this button "
594
  "you agree to the %3$sTerms of Service%2$s. Or, manually enter Stripe "
595
  "account keys below."
596
  msgstr ""
597
 
598
- #: includes/admin/stripe-settings.php:34
599
  msgid "Manually enter Stripe keys below."
600
  msgstr ""
601
 
602
- #: includes/admin/stripe-settings.php:43
603
  msgid "Enable Stripe"
604
  msgstr ""
605
 
606
- #: includes/admin/stripe-settings.php:52
607
  msgid "Credit Card (Stripe)"
608
  msgstr ""
609
 
610
- #: includes/admin/stripe-settings.php:59
611
  msgid "Pay with your credit card via Stripe."
612
  msgstr ""
613
 
614
- #: includes/admin/stripe-settings.php:69
615
- #. translators: webhook URL
616
  msgid "Stripe Account Keys"
617
  msgstr ""
618
 
619
- #: includes/admin/stripe-settings.php:74
620
  msgid "Test mode"
621
  msgstr ""
622
 
623
- #: includes/admin/stripe-settings.php:75
624
  msgid "Enable Test Mode"
625
  msgstr ""
626
 
627
- #: includes/admin/stripe-settings.php:77
628
  msgid "Place the payment gateway in test mode using test API keys."
629
  msgstr ""
630
 
631
- #: includes/admin/stripe-settings.php:82
632
  msgid "Test Publishable Key"
633
  msgstr ""
634
 
635
- #: includes/admin/stripe-settings.php:84
636
  msgid ""
637
  "Get your API keys from your stripe account. Invalid values will be "
638
  "rejected. Only values starting with \"pk_test_\" will be saved."
639
  msgstr ""
640
 
641
- #: includes/admin/stripe-settings.php:89
642
  msgid "Test Secret Key"
643
  msgstr ""
644
 
645
- #: includes/admin/stripe-settings.php:91
646
  msgid ""
647
  "Get your API keys from your stripe account. Invalid values will be "
648
  "rejected. Only values starting with \"sk_test_\" or \"rk_test_\" will be "
649
  "saved."
650
  msgstr ""
651
 
652
- #: includes/admin/stripe-settings.php:96
653
- msgid "Test Webhook Secret"
654
  msgstr ""
655
 
656
- #: includes/admin/stripe-settings.php:98 includes/admin/stripe-settings.php:119
657
  msgid ""
658
- "Get your webhook signing secret from the webhooks section in your stripe "
659
- "account."
660
  msgstr ""
661
 
662
- #: includes/admin/stripe-settings.php:103
663
- msgid "Live Publishable Key"
664
  msgstr ""
665
 
666
- #: includes/admin/stripe-settings.php:105
667
  msgid ""
668
  "Get your API keys from your stripe account. Invalid values will be "
669
- "rejected. Only values starting with \"pk_live_\" will be saved."
 
670
  msgstr ""
671
 
672
  #: includes/admin/stripe-settings.php:110
673
- msgid "Live Secret Key"
674
  msgstr ""
675
 
676
  #: includes/admin/stripe-settings.php:112
 
677
  msgid ""
678
- "Get your API keys from your stripe account. Invalid values will be "
679
- "rejected. Only values starting with \"sk_live_\" or \"rk_live_\" will be "
680
- "saved."
681
  msgstr ""
682
 
683
  #: includes/admin/stripe-settings.php:117
@@ -996,11 +1000,11 @@ msgid "Stripe Payout:"
996
  msgstr ""
997
 
998
  #: includes/class-wc-gateway-stripe.php:832
999
- #: includes/class-wc-stripe-order-handler.php:158
1000
- #: includes/class-wc-stripe-webhook-handler.php:233
1001
- #: includes/compat/class-wc-stripe-sepa-subs-compat.php:284
1002
- #: includes/compat/class-wc-stripe-subs-compat.php:334
1003
- #: includes/payment-methods/class-wc-gateway-stripe-sepa.php:369
1004
  msgid ""
1005
  "Sorry, we are unable to process your payment at this time. Please retry "
1006
  "later."
@@ -1014,42 +1018,47 @@ msgid ""
1014
  "done is for you to authorize the payment with your bank."
1015
  msgstr ""
1016
 
1017
- #: includes/class-wc-gateway-stripe.php:1126
1018
- #: includes/class-wc-stripe-webhook-handler.php:737
1019
- #: includes/class-wc-stripe-webhook-handler.php:782
 
 
 
 
 
1020
  #. translators: 1) The error message that was received from Stripe.
1021
  msgid "Stripe SCA authentication failed. Reason: %s"
1022
  msgstr ""
1023
 
1024
- #: includes/class-wc-gateway-stripe.php:1127
1025
  msgid "Stripe SCA authentication failed."
1026
  msgstr ""
1027
 
1028
- #: includes/class-wc-gateway-stripe.php:1184
1029
  msgid ""
1030
  "The \"Live Publishable Key\" should start with \"pk_live\", enter the "
1031
  "correct key."
1032
  msgstr ""
1033
 
1034
- #: includes/class-wc-gateway-stripe.php:1192
1035
  msgid ""
1036
  "The \"Live Secret Key\" should start with \"sk_live\" or \"rk_live\", enter "
1037
  "the correct key."
1038
  msgstr ""
1039
 
1040
- #: includes/class-wc-gateway-stripe.php:1200
1041
  msgid ""
1042
  "The \"Test Publishable Key\" should start with \"pk_test\", enter the "
1043
  "correct key."
1044
  msgstr ""
1045
 
1046
- #: includes/class-wc-gateway-stripe.php:1208
1047
  msgid ""
1048
  "The \"Test Secret Key\" should start with \"sk_test\" or \"rk_test\", enter "
1049
  "the correct key."
1050
  msgstr ""
1051
 
1052
- #: includes/class-wc-stripe-api.php:140 includes/class-wc-stripe-api.php:174
1053
  msgid "There was a problem connecting to the Stripe API endpoint."
1054
  msgstr ""
1055
 
@@ -1095,21 +1104,21 @@ msgid ""
1095
  "be enabled to see recorded logs."
1096
  msgstr ""
1097
 
1098
- #: includes/class-wc-stripe-customer.php:121
1099
  #. translators: %1$s First name, %2$s Second name, %3$s Username.
1100
- msgid "Name: %1$s %2$s, Username: %s"
1101
  msgstr ""
1102
 
1103
- #: includes/class-wc-stripe-customer.php:137
1104
  #. translators: %1$s First name, %2$s Second name.
1105
  msgid "Name: %1$s %2$s, Guest"
1106
  msgstr ""
1107
 
1108
- #: includes/class-wc-stripe-customer.php:194
1109
  msgid "Attempting to update a Stripe customer without a customer ID."
1110
  msgstr ""
1111
 
1112
- #: includes/class-wc-stripe-customer.php:341
1113
  msgid "Unable to add payment source."
1114
  msgstr ""
1115
 
@@ -1209,29 +1218,29 @@ msgstr ""
1209
  msgid "Unable to verify your request. Please reload the page and try again."
1210
  msgstr ""
1211
 
1212
- #: includes/class-wc-stripe-intent-controller.php:197
1213
  msgid "Your card could not be set up for future usage."
1214
  msgstr ""
1215
 
1216
- #: includes/class-wc-stripe-intent-controller.php:214
1217
  msgid "Failed to save payment method."
1218
  msgstr ""
1219
 
1220
- #: includes/class-wc-stripe-order-handler.php:140
1221
- #: includes/class-wc-stripe-webhook-handler.php:214
1222
- #: includes/payment-methods/class-wc-gateway-stripe-sepa.php:349
1223
  msgid "This card is no longer available and has been removed."
1224
  msgstr ""
1225
 
1226
- #: includes/class-wc-stripe-order-handler.php:190
1227
  #. translators: error message
1228
  msgid "Stripe payment failed: %s"
1229
  msgstr ""
1230
 
1231
- #: includes/class-wc-stripe-order-handler.php:241
1232
- #: includes/class-wc-stripe-order-handler.php:256
1233
- #: includes/class-wc-stripe-order-handler.php:272
1234
- #: includes/class-wc-stripe-order-handler.php:287
1235
  #. translators: error message
1236
  msgid "Unable to capture charge! %s"
1237
  msgstr ""
@@ -1240,12 +1249,12 @@ msgstr ""
1240
  msgid "SEPA IBAN"
1241
  msgstr ""
1242
 
1243
- #: includes/class-wc-stripe-sepa-payment-token.php:41
1244
  #. translators: last 4 digits of IBAN account
1245
  msgid "SEPA IBAN ending in %s"
1246
  msgstr ""
1247
 
1248
- #: includes/class-wc-stripe-webhook-handler.php:293
1249
  #. translators: 1) The URL to the order.
1250
  msgid ""
1251
  "A dispute was created for this order. Response is needed. Please go to your "
@@ -1253,47 +1262,47 @@ msgid ""
1253
  "Dashboard</a> to review this dispute."
1254
  msgstr ""
1255
 
1256
- #: includes/class-wc-stripe-webhook-handler.php:322
1257
  msgid "The dispute was lost or accepted."
1258
  msgstr ""
1259
 
1260
- #: includes/class-wc-stripe-webhook-handler.php:324
1261
  msgid "The dispute was resolved in your favor."
1262
  msgstr ""
1263
 
1264
- #: includes/class-wc-stripe-webhook-handler.php:326
1265
  msgid "The inquiry or retrieval was closed."
1266
  msgstr ""
1267
 
1268
- #: includes/class-wc-stripe-webhook-handler.php:379
1269
  #. translators: partial captured amount
1270
  msgid "This charge was partially captured via Stripe Dashboard in the amount of: %s"
1271
  msgstr ""
1272
 
1273
- #: includes/class-wc-stripe-webhook-handler.php:461
1274
  msgid "This payment failed to clear."
1275
  msgstr ""
1276
 
1277
- #: includes/class-wc-stripe-webhook-handler.php:498
1278
  msgid "This payment was cancelled."
1279
  msgstr ""
1280
 
1281
- #: includes/class-wc-stripe-webhook-handler.php:541
1282
  #. translators: amount (including currency symbol)
1283
  msgid "Pre-Authorization for %s voided from the Stripe Dashboard."
1284
  msgstr ""
1285
 
1286
- #: includes/class-wc-stripe-webhook-handler.php:554
1287
  msgid "Refunded via Stripe Dashboard"
1288
  msgstr ""
1289
 
1290
- #: includes/class-wc-stripe-webhook-handler.php:576
1291
  #. translators: 1) amount (including currency symbol) 2) transaction id 3)
1292
  #. refund message
1293
  msgid "Refunded %1$s - Refund ID: %2$s - %3$s"
1294
  msgstr ""
1295
 
1296
- #: includes/class-wc-stripe-webhook-handler.php:607
1297
  #. translators: 1) The URL to the order. 2) The reason type.
1298
  msgid ""
1299
  "A review has been opened for this order. Action is needed. Please go to "
@@ -1301,11 +1310,109 @@ msgid ""
1301
  "Dashboard</a> to review the issue. Reason: (%2$s)"
1302
  msgstr ""
1303
 
1304
- #: includes/class-wc-stripe-webhook-handler.php:640
1305
  #. translators: 1) The reason type.
1306
  msgid "The opened review for this order is now closed. Reason: (%s)"
1307
  msgstr ""
1308
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1309
  #: includes/compat/class-wc-stripe-email-failed-authentication-retry.php:29
1310
  msgid "Payment Authentication Requested Email"
1311
  msgstr ""
@@ -1369,75 +1476,78 @@ msgstr ""
1369
  msgid "Payment authorization needed for renewal of order {order_number}"
1370
  msgstr ""
1371
 
1372
- #: includes/compat/class-wc-stripe-pre-orders-compat.php:51
1373
  msgid "Unable to store payment details. Please try again."
1374
  msgstr ""
1375
 
1376
- #: includes/compat/class-wc-stripe-pre-orders-compat.php:114
1377
- #: includes/compat/class-wc-stripe-subs-compat.php:366
1378
- #: includes/compat/class-wc-stripe-subs-compat.php:670
 
 
 
1379
  msgid "Stripe charge awaiting authentication by user: %s."
1380
  msgstr ""
1381
 
1382
- #: includes/compat/class-wc-stripe-pre-orders-compat.php:131
1383
  #. translators: error message
1384
  msgid "Stripe Transaction Failed (%s)"
1385
  msgstr ""
1386
 
1387
- #: includes/compat/class-wc-stripe-sepa-subs-compat.php:83
1388
- #: includes/compat/class-wc-stripe-subs-compat.php:93
1389
  msgid "Update the Payment Method used for all of my active subscriptions."
1390
  msgstr ""
1391
 
1392
- #: includes/compat/class-wc-stripe-sepa-subs-compat.php:246
1393
- #: includes/compat/class-wc-stripe-subs-compat.php:294
1394
  msgid "Customer not found"
1395
  msgstr ""
1396
 
1397
- #: includes/compat/class-wc-stripe-sepa-subs-compat.php:404
1398
- #: includes/compat/class-wc-stripe-subs-compat.php:512
1399
  #. translators: error message
1400
  msgid "A \"Stripe Customer ID\" value is required."
1401
  msgstr ""
1402
 
1403
- #: includes/compat/class-wc-stripe-sepa-subs-compat.php:407
1404
- #: includes/compat/class-wc-stripe-subs-compat.php:515
1405
  msgid ""
1406
  "Invalid customer ID. A valid \"Stripe Customer ID\" must begin with "
1407
  "\"cus_\"."
1408
  msgstr ""
1409
 
1410
- #: includes/compat/class-wc-stripe-sepa-subs-compat.php:416
1411
  msgid ""
1412
  "Invalid source ID. A valid source \"Stripe Source ID\" must begin with "
1413
  "\"src_\" or \"card_\"."
1414
  msgstr ""
1415
 
1416
- #: includes/compat/class-wc-stripe-sepa-subs-compat.php:489
1417
  #. translators: 1) last 4 digits of SEPA Direct Debit
1418
  msgid "Via SEPA Direct Debit ending in %1$s"
1419
  msgstr ""
1420
 
1421
- #: includes/compat/class-wc-stripe-subs-compat.php:358
1422
  msgid "This transaction requires authentication."
1423
  msgstr ""
1424
 
1425
- #: includes/compat/class-wc-stripe-subs-compat.php:525
1426
  msgid ""
1427
  "Invalid source ID. A valid source \"Stripe Source ID\" must begin with "
1428
  "\"src_\", \"pm_\", or \"card_\"."
1429
  msgstr ""
1430
 
1431
- #: includes/compat/class-wc-stripe-subs-compat.php:606
1432
  #. translators: 1) card brand 2) last 4 digits
1433
  msgid "Via %1$s card ending in %2$s"
1434
  msgstr ""
1435
 
1436
- #: includes/compat/class-wc-stripe-subs-compat.php:703
1437
  msgid "Your early renewal order was successful."
1438
  msgstr ""
1439
 
1440
- #: includes/compat/class-wc-stripe-subs-compat.php:716
1441
  msgid ""
1442
  "Payment authorization for the renewal order was unsuccessful, please try "
1443
  "again."
@@ -1483,95 +1593,95 @@ msgstr ""
1483
  msgid "You are not authorized to clear Stripe account keys."
1484
  msgstr ""
1485
 
1486
- #: includes/payment-methods/class-wc-gateway-stripe-alipay.php:60
1487
  #: woocommerce-gateway-stripe.php:305
1488
  msgid "Stripe Alipay"
1489
  msgstr ""
1490
 
1491
- #: includes/payment-methods/class-wc-gateway-stripe-alipay.php:62
1492
- #: includes/payment-methods/class-wc-gateway-stripe-bancontact.php:62
1493
- #: includes/payment-methods/class-wc-gateway-stripe-eps.php:62
1494
- #: includes/payment-methods/class-wc-gateway-stripe-giropay.php:62
1495
- #: includes/payment-methods/class-wc-gateway-stripe-ideal.php:62
1496
- #: includes/payment-methods/class-wc-gateway-stripe-multibanco.php:62
1497
- #: includes/payment-methods/class-wc-gateway-stripe-p24.php:62
1498
- #: includes/payment-methods/class-wc-gateway-stripe-sepa.php:77
1499
- #: includes/payment-methods/class-wc-gateway-stripe-sofort.php:62
1500
  #. translators: link
1501
  msgid "All other general Stripe settings can be adjusted <a href=\"%s\">here</a>."
1502
  msgstr ""
1503
 
1504
- #: includes/payment-methods/class-wc-gateway-stripe-alipay.php:188
1505
- #: includes/payment-methods/class-wc-gateway-stripe-bancontact.php:180
1506
- #: includes/payment-methods/class-wc-gateway-stripe-eps.php:180
1507
- #: includes/payment-methods/class-wc-gateway-stripe-giropay.php:180
1508
- #: includes/payment-methods/class-wc-gateway-stripe-ideal.php:180
1509
- #: includes/payment-methods/class-wc-gateway-stripe-multibanco.php:184
1510
- #: includes/payment-methods/class-wc-gateway-stripe-p24.php:181
1511
- #: includes/payment-methods/class-wc-gateway-stripe-sofort.php:180
1512
  msgid "Add Payment"
1513
  msgstr ""
1514
 
1515
- #: includes/payment-methods/class-wc-gateway-stripe-bancontact.php:60
1516
  #: woocommerce-gateway-stripe.php:299
1517
  msgid "Stripe Bancontact"
1518
  msgstr ""
1519
 
1520
- #: includes/payment-methods/class-wc-gateway-stripe-eps.php:60
1521
  #: woocommerce-gateway-stripe.php:302
1522
  msgid "Stripe EPS"
1523
  msgstr ""
1524
 
1525
- #: includes/payment-methods/class-wc-gateway-stripe-giropay.php:60
1526
  #: woocommerce-gateway-stripe.php:301
1527
  msgid "Stripe Giropay"
1528
  msgstr ""
1529
 
1530
- #: includes/payment-methods/class-wc-gateway-stripe-ideal.php:60
1531
  #: woocommerce-gateway-stripe.php:303
1532
  msgid "Stripe iDeal"
1533
  msgstr ""
1534
 
1535
- #: includes/payment-methods/class-wc-gateway-stripe-multibanco.php:60
1536
  #: woocommerce-gateway-stripe.php:307
1537
  msgid "Stripe Multibanco"
1538
  msgstr ""
1539
 
1540
- #: includes/payment-methods/class-wc-gateway-stripe-multibanco.php:243
1541
- #: includes/payment-methods/class-wc-gateway-stripe-multibanco.php:255
1542
  msgid "MULTIBANCO INFORMAÇÕES DE ENCOMENDA:"
1543
  msgstr ""
1544
 
1545
- #: includes/payment-methods/class-wc-gateway-stripe-multibanco.php:245
1546
- #: includes/payment-methods/class-wc-gateway-stripe-multibanco.php:258
1547
  msgid "Montante:"
1548
  msgstr ""
1549
 
1550
- #: includes/payment-methods/class-wc-gateway-stripe-multibanco.php:248
1551
- #: includes/payment-methods/class-wc-gateway-stripe-multibanco.php:262
1552
  msgid "Entidade:"
1553
  msgstr ""
1554
 
1555
- #: includes/payment-methods/class-wc-gateway-stripe-multibanco.php:251
1556
- #: includes/payment-methods/class-wc-gateway-stripe-multibanco.php:266
1557
  msgid "Referencia:"
1558
  msgstr ""
1559
 
1560
- #: includes/payment-methods/class-wc-gateway-stripe-multibanco.php:362
1561
  msgid "Awaiting Multibanco payment"
1562
  msgstr ""
1563
 
1564
- #: includes/payment-methods/class-wc-gateway-stripe-p24.php:60
1565
  #: woocommerce-gateway-stripe.php:304
1566
  msgid "Stripe P24"
1567
  msgstr ""
1568
 
1569
- #: includes/payment-methods/class-wc-gateway-stripe-sepa.php:75
1570
  #: woocommerce-gateway-stripe.php:306
1571
  msgid "Stripe SEPA Direct Debit"
1572
  msgstr ""
1573
 
1574
- #: includes/payment-methods/class-wc-gateway-stripe-sepa.php:212
1575
  #. translators: statement descriptor
1576
  msgid ""
1577
  "By providing your IBAN and confirming this payment, you are authorizing %s "
@@ -1583,35 +1693,35 @@ msgid ""
1583
  "debited."
1584
  msgstr ""
1585
 
1586
- #: includes/payment-methods/class-wc-gateway-stripe-sepa.php:228
1587
  msgid "IBAN."
1588
  msgstr ""
1589
 
1590
- #: includes/payment-methods/class-wc-gateway-stripe-sepa.php:270
1591
  msgid ""
1592
  "TEST MODE ENABLED. In test mode, you can use IBAN number "
1593
  "DE89370400440532013000."
1594
  msgstr ""
1595
 
1596
- #: includes/payment-methods/class-wc-gateway-stripe-sofort.php:60
1597
  #: woocommerce-gateway-stripe.php:300
1598
  msgid "Stripe SOFORT"
1599
  msgstr ""
1600
 
1601
  #: includes/payment-methods/class-wc-stripe-payment-request.php:303
1602
- #: includes/payment-methods/class-wc-stripe-payment-request.php:959
1603
- #: includes/payment-methods/class-wc-stripe-payment-request.php:1251
1604
  msgid "Tax"
1605
  msgstr ""
1606
 
1607
  #: includes/payment-methods/class-wc-stripe-payment-request.php:311
1608
- #: includes/payment-methods/class-wc-stripe-payment-request.php:967
1609
- #: includes/payment-methods/class-wc-stripe-payment-request.php:1258
1610
  msgid "Shipping"
1611
  msgstr ""
1612
 
1613
  #: includes/payment-methods/class-wc-stripe-payment-request.php:318
1614
- #: includes/payment-methods/class-wc-stripe-payment-request.php:974
1615
  msgid "Pending"
1616
  msgstr ""
1617
 
@@ -1633,30 +1743,31 @@ msgstr ""
1633
  msgid "Unable to find shipping method for address."
1634
  msgstr ""
1635
 
1636
- #: includes/payment-methods/class-wc-stripe-payment-request.php:921
 
1637
  msgid "Product with the ID (%d) cannot be found."
1638
  msgstr ""
1639
 
1640
- #: includes/payment-methods/class-wc-stripe-payment-request.php:942
1641
  #. translators: 1: product name 2: quantity in stock
1642
  msgid ""
1643
  "You cannot add that amount of \"%1$s\"; to the cart because there is not "
1644
  "enough stock (%2$s remaining)."
1645
  msgstr ""
1646
 
1647
- #: includes/payment-methods/class-wc-stripe-payment-request.php:1093
1648
  msgid "Empty cart"
1649
  msgstr ""
1650
 
1651
- #: includes/payment-methods/class-wc-stripe-payment-request.php:1265
1652
  msgid "Discount"
1653
  msgstr ""
1654
 
1655
- #: templates/emails/failed-preorder-authentication.php:19
1656
  msgid "Authorize the payment now &raquo;"
1657
  msgstr ""
1658
 
1659
- #: templates/emails/failed-preorder-authentication.php:55
1660
  msgid "Thanks for shopping with us."
1661
  msgstr ""
1662
 
@@ -1669,14 +1780,21 @@ msgstr ""
1669
  msgid "Authorize the payment &raquo;"
1670
  msgstr ""
1671
 
1672
- #: woocommerce-gateway-stripe.php:43
 
 
 
 
 
 
 
1673
  #. translators: 1. URL link.
1674
  msgid ""
1675
  "Stripe requires WooCommerce to be installed and active. You can download %s "
1676
  "here."
1677
  msgstr ""
1678
 
1679
- #: woocommerce-gateway-stripe.php:54
1680
  #. translators: $1. Minimum WooCommerce version. $2. Current WooCommerce
1681
  #. version.
1682
  msgid ""
@@ -1729,7 +1847,7 @@ msgctxt "an email notification"
1729
  msgid "Enable/Disable"
1730
  msgstr ""
1731
 
1732
- #: templates/emails/failed-preorder-authentication.php:18
1733
  #. translators: %s is a link to the payment re-authentication URL.
1734
  msgctxt "In failed SCA authentication for a pre-order."
1735
  msgid ""
@@ -1761,12 +1879,4 @@ msgid ""
1761
  "The automatic payment to renew your subscription with %1$s has failed. To "
1762
  "reactivate the subscription, please login and authorize the renewal from "
1763
  "your account page: %2$s"
1764
- msgstr ""
1765
-
1766
- #: templates/emails/plain/failed-preorder-authentication.php:10
1767
- #. translators: %s is a link to the payment re-authentication URL.
1768
- msgctxt "woocommerce-gateway-stripe"
1769
- msgid ""
1770
- "Your pre-order is now available, but payment cannot be completed "
1771
- "automatically. Please complete the payment now: %s"
1772
  msgstr ""
2
  # This file is distributed under the same license as the WooCommerce Stripe Gateway package.
3
  msgid ""
4
  msgstr ""
5
+ "Project-Id-Version: WooCommerce Stripe Gateway 5.0.0\n"
6
  "Report-Msgid-Bugs-To: "
7
  "https://wordpress.org/support/plugin/woocommerce-gateway-stripe\n"
8
+ "POT-Creation-Date: 2021-03-17 14:10:37+00:00\n"
9
  "MIME-Version: 1.0\n"
10
  "Content-Type: text/plain; charset=utf-8\n"
11
  "Content-Transfer-Encoding: 8bit\n"
14
  "Language-Team: LANGUAGE <LL@li.org>\n"
15
  "X-Generator: node-wp-i18n 1.2.3\n"
16
 
17
+ #: includes/abstracts/abstract-wc-stripe-payment-gateway.php:25
18
  #. translators: 1) webhook url
19
  msgid ""
20
  "You must add the following webhook endpoint <strong "
21
  "style=\"background-color:#ddd;\">&nbsp;%s&nbsp;</strong> to your <a "
22
  "href=\"https://dashboard.stripe.com/account/webhooks\" "
23
+ "target=\"_blank\">Stripe account settings</a> (if there isn't one already "
24
+ "enabled). This will enable you to receive notifications on the charge "
25
+ "statuses."
26
  msgstr ""
27
 
28
+ #: includes/abstracts/abstract-wc-stripe-payment-gateway.php:44
29
  msgid "Save payment information to my account for future purchases."
30
  msgstr ""
31
 
32
+ #: includes/abstracts/abstract-wc-stripe-payment-gateway.php:251
33
+ #: includes/compat/class-wc-stripe-sepa-subs-compat.php:230
34
+ #: includes/compat/class-wc-stripe-subs-compat.php:243
35
  #. translators: 1) amount (including currency symbol)
36
  #. translators: minimum amount
37
  msgid "Sorry, the minimum allowed order total is %1$s to use this payment method."
38
  msgstr ""
39
 
40
+ #: includes/abstracts/abstract-wc-stripe-payment-gateway.php:344
41
  #. translators: 1) blog name 2) order number
42
  msgid "%1$s - Order %2$s"
43
  msgstr ""
44
 
45
+ #: includes/abstracts/abstract-wc-stripe-payment-gateway.php:385
46
  msgid "customer_name"
47
  msgstr ""
48
 
49
+ #: includes/abstracts/abstract-wc-stripe-payment-gateway.php:386
50
  msgid "customer_email"
51
  msgstr ""
52
 
53
+ #: includes/abstracts/abstract-wc-stripe-payment-gateway.php:449
54
  #. translators: transaction id
55
  msgid "Stripe charge awaiting payment: %s."
56
  msgstr ""
57
 
58
+ #: includes/abstracts/abstract-wc-stripe-payment-gateway.php:456
59
+ #: includes/class-wc-stripe-order-handler.php:299
60
+ #: includes/class-wc-stripe-webhook-handler.php:415
61
+ #: includes/class-wc-stripe-webhook-handler.php:465
62
  #. translators: transaction id
63
  msgid "Stripe charge complete (Charge ID: %s)"
64
  msgstr ""
65
 
66
+ #: includes/abstracts/abstract-wc-stripe-payment-gateway.php:461
67
  #: includes/class-wc-gateway-stripe.php:503
68
+ #: includes/compat/class-wc-stripe-sepa-subs-compat.php:187
69
  msgid "Payment processing failed. Please retry."
70
  msgstr ""
71
 
72
+ #: includes/abstracts/abstract-wc-stripe-payment-gateway.php:473
73
  #. translators: transaction id
74
  msgid ""
75
  "Stripe charge authorized (Charge ID: %s). Process order to take payment, or "
77
  "part or in full will release the authorization and cancel the payment."
78
  msgstr ""
79
 
80
+ #: includes/abstracts/abstract-wc-stripe-payment-gateway.php:654
81
  msgid "Invalid payment method. Please input a new card number."
82
  msgstr ""
83
 
84
+ #: includes/abstracts/abstract-wc-stripe-payment-gateway.php:926
85
  #. translators: amount (including currency symbol)
86
  msgid "Pre-Authorization for %s voided."
87
  msgstr ""
88
 
89
+ #: includes/abstracts/abstract-wc-stripe-payment-gateway.php:931
90
  msgid ""
91
  "The authorization was voided and the order cancelled. Click okay to "
92
  "continue, then refresh the page."
93
  msgstr ""
94
 
95
+ #: includes/abstracts/abstract-wc-stripe-payment-gateway.php:945
96
  #. translators: 1) amount (including currency symbol) 2) transaction id 3)
97
  #. refund message
98
  msgid "Refunded %1$s - Refund ID: %2$s - Reason: %3$s"
99
  msgstr ""
100
 
101
+ #: includes/abstracts/abstract-wc-stripe-payment-gateway.php:963
102
  msgid "There was a problem adding the payment method."
103
  msgstr ""
104
 
105
+ #: includes/admin/class-wc-stripe-admin-notices.php:134
106
  #. translators: 1) A URL that explains Stripe Radar.
107
  msgid ""
108
  "WooCommerce Stripe - We see that you had the \"Require 3D secure when "
111
  "href=\"%s\" target=\"_blank\">here</a>."
112
  msgstr ""
113
 
114
+ #: includes/admin/class-wc-stripe-admin-notices.php:141
115
  #. translators: 1) int version 2) int version
116
  msgid ""
117
  "WooCommerce Stripe - We recently made changes to Stripe that may impact the "
121
  "target=\"_blank\">instructions</a> to fix."
122
  msgstr ""
123
 
124
+ #: includes/admin/class-wc-stripe-admin-notices.php:151
125
  #. translators: 1) int version 2) int version
126
  msgid ""
127
  "WooCommerce Stripe - The minimum PHP version required for this plugin is "
128
  "%1$s. You are running %2$s."
129
  msgstr ""
130
 
131
+ #: includes/admin/class-wc-stripe-admin-notices.php:162
132
  #. translators: 1) int version 2) int version
133
  msgid ""
134
  "WooCommerce Stripe - This is the last version of the plugin compatible with "
136
  "WooCommerce %2$s or greater."
137
  msgstr ""
138
 
139
+ #: includes/admin/class-wc-stripe-admin-notices.php:169
140
  msgid "WooCommerce Stripe - cURL is not installed."
141
  msgstr ""
142
 
143
+ #: includes/admin/class-wc-stripe-admin-notices.php:179
144
  #. translators: 1) link
145
  msgid ""
146
  "Stripe is almost ready. To get started, <a href=\"%s\">set your Stripe "
147
  "account keys</a>."
148
  msgstr ""
149
 
150
+ #: includes/admin/class-wc-stripe-admin-notices.php:189
151
  #. translators: 1) link
152
  msgid ""
153
  "Stripe is in test mode however your test keys may not be valid. Test keys "
155
  "<a href=\"%s\">set your Stripe account keys</a>."
156
  msgstr ""
157
 
158
+ #: includes/admin/class-wc-stripe-admin-notices.php:197
159
  #. translators: 1) link
160
  msgid ""
161
  "Stripe is in live mode however your live keys may not be valid. Live keys "
163
  "<a href=\"%s\">set your Stripe account keys</a>."
164
  msgstr ""
165
 
166
+ #: includes/admin/class-wc-stripe-admin-notices.php:206
167
  #. translators: 1) link
168
  msgid ""
169
  "Stripe is enabled, but a SSL certificate is not detected. Your checkout may "
171
  "target=\"_blank\">SSL certificate</a>"
172
  msgstr ""
173
 
174
+ #: includes/admin/class-wc-stripe-admin-notices.php:212
175
+ #. translators: %1 is the URL for the link
176
  msgid ""
177
  "Stripe is now ready for Strong Customer Authentication (SCA) and 3D Secure "
178
  "2! <a href=\"%1$s\" target=\"_blank\">Read about SCA</a>"
179
  msgstr ""
180
 
181
+ #: includes/admin/class-wc-stripe-admin-notices.php:217
182
  #. translators: %s is a the URL for the link.
183
  msgid ""
184
  "The public and/or secret keys for the Stripe gateway have been changed. "
186
  "<a href=\"%s\" target=\"_blank\">Click here to learn more</a>."
187
  msgstr ""
188
 
189
+ #: includes/admin/class-wc-stripe-admin-notices.php:240
190
  #. translators: %1$s Payment method, %2$s List of supported currencies
191
  msgid "%1$s is enabled - it requires store currency to be set to %2$s"
192
  msgstr ""
193
 
194
+ #: includes/admin/class-wc-stripe-admin-notices.php:254
195
  msgid "Action failed. Please refresh the page and retry."
196
  msgstr ""
197
 
198
+ #: includes/admin/class-wc-stripe-admin-notices.php:258
199
  msgid "Cheatin&#8217; huh?"
200
  msgstr ""
201
 
233
  msgid "Learn more"
234
  msgstr ""
235
 
236
+ #: includes/admin/class-wc-stripe-privacy.php:11
237
  #: includes/class-wc-gateway-stripe.php:88
238
  msgid "Stripe"
239
  msgstr ""
240
 
241
+ #: includes/admin/class-wc-stripe-privacy.php:13
242
  msgid "WooCommerce Stripe Order Data"
243
  msgstr ""
244
 
245
+ #: includes/admin/class-wc-stripe-privacy.php:16
246
  msgid "WooCommerce Stripe Subscriptions Data"
247
  msgstr ""
248
 
249
+ #: includes/admin/class-wc-stripe-privacy.php:19
250
+ #: includes/admin/class-wc-stripe-privacy.php:21
251
  msgid "WooCommerce Stripe Customer Data"
252
  msgstr ""
253
 
254
+ #: includes/admin/class-wc-stripe-privacy.php:22
255
  msgid "WooCommerce Stripe Data"
256
  msgstr ""
257
 
258
+ #: includes/admin/class-wc-stripe-privacy.php:36
259
  msgid "Retain Stripe Data"
260
  msgstr ""
261
 
262
+ #: includes/admin/class-wc-stripe-privacy.php:37
263
  msgid "Retains any Stripe data such as Stripe customer ID, source ID."
264
  msgstr ""
265
 
266
+ #: includes/admin/class-wc-stripe-privacy.php:40
267
+ #: includes/compat/class-wc-stripe-sepa-subs-compat.php:486
268
+ #: includes/compat/class-wc-stripe-subs-compat.php:598
269
+ #: includes/compat/class-wc-stripe-subs-compat.php:613
270
  msgid "N/A"
271
  msgstr ""
272
 
273
+ #: includes/admin/class-wc-stripe-privacy.php:93
274
  #. translators: %s URL to docs
275
  msgid ""
276
  "By using this extension, you may be storing personal data or sharing data "
279
  "policy.</a>"
280
  msgstr ""
281
 
282
+ #: includes/admin/class-wc-stripe-privacy.php:116
283
  msgid "Orders"
284
  msgstr ""
285
 
286
+ #: includes/admin/class-wc-stripe-privacy.php:120
287
+ #: includes/admin/class-wc-stripe-privacy.php:185
288
+ #: includes/admin/class-wc-stripe-privacy.php:225
289
  msgid "Stripe payment id"
290
  msgstr ""
291
 
292
+ #: includes/admin/class-wc-stripe-privacy.php:124
293
+ #: includes/admin/class-wc-stripe-privacy.php:189
294
+ #: includes/admin/class-wc-stripe-privacy.php:229
295
  msgid "Stripe customer id"
296
  msgstr ""
297
 
298
+ #: includes/admin/class-wc-stripe-privacy.php:181
299
  msgid "Subscriptions"
300
  msgstr ""
301
 
302
+ #: includes/admin/class-wc-stripe-privacy.php:221
303
  msgid "Customer Data"
304
  msgstr ""
305
 
306
+ #: includes/admin/class-wc-stripe-privacy.php:267
307
  msgid "Stripe User Data Erased."
308
  msgstr ""
309
 
310
+ #: includes/admin/class-wc-stripe-privacy.php:343
311
+ #: includes/admin/class-wc-stripe-privacy.php:380
312
  #. translators: %d Order ID
313
  msgid ""
314
  "Order ID %d is less than set retention days. Personal data retained. "
315
  "(Stripe)"
316
  msgstr ""
317
 
318
+ #: includes/admin/class-wc-stripe-privacy.php:348
319
  #. translators: %d Order ID
320
  msgid ""
321
  "Order ID %d contains an active Subscription. Personal data retained. "
322
  "(Stripe)"
323
  msgstr ""
324
 
325
+ #: includes/admin/class-wc-stripe-privacy.php:363
326
  msgid "Stripe Subscription Data Erased."
327
  msgstr ""
328
 
329
+ #: includes/admin/class-wc-stripe-privacy.php:391
330
  msgid "Stripe personal data erased."
331
  msgstr ""
332
 
363
  #: includes/admin/stripe-multibanco-settings.php:18
364
  #: includes/admin/stripe-p24-settings.php:18
365
  #: includes/admin/stripe-sepa-settings.php:22
366
+ #: includes/admin/stripe-settings.php:43
367
  #: includes/admin/stripe-sofort-settings.php:22
368
  msgid "Enable/Disable"
369
  msgstr ""
380
  #: includes/admin/stripe-multibanco-settings.php:25
381
  #: includes/admin/stripe-p24-settings.php:25
382
  #: includes/admin/stripe-sepa-settings.php:29
383
+ #: includes/admin/stripe-settings.php:50
384
  #: includes/admin/stripe-sofort-settings.php:29
385
  msgid "Title"
386
  msgstr ""
393
  #: includes/admin/stripe-multibanco-settings.php:27
394
  #: includes/admin/stripe-p24-settings.php:27
395
  #: includes/admin/stripe-sepa-settings.php:31
396
+ #: includes/admin/stripe-settings.php:52
397
  #: includes/admin/stripe-sofort-settings.php:31
398
  msgid "This controls the title which the user sees during checkout."
399
  msgstr ""
410
  #: includes/admin/stripe-multibanco-settings.php:32
411
  #: includes/admin/stripe-p24-settings.php:32
412
  #: includes/admin/stripe-sepa-settings.php:36
413
+ #: includes/admin/stripe-settings.php:57
414
  #: includes/admin/stripe-sofort-settings.php:36
415
  msgid "Description"
416
  msgstr ""
423
  #: includes/admin/stripe-multibanco-settings.php:34
424
  #: includes/admin/stripe-p24-settings.php:34
425
  #: includes/admin/stripe-sepa-settings.php:38
426
+ #: includes/admin/stripe-settings.php:59
427
  #: includes/admin/stripe-sofort-settings.php:38
428
  msgid "This controls the description which the user sees during checkout."
429
  msgstr ""
440
  #: includes/admin/stripe-multibanco-settings.php:39
441
  #: includes/admin/stripe-p24-settings.php:39
442
  #: includes/admin/stripe-sepa-settings.php:43
443
+ #: includes/admin/stripe-settings.php:105
444
  #: includes/admin/stripe-sofort-settings.php:43
445
  msgid "Webhook Endpoints"
446
  msgstr ""
584
  msgid "Mandate Information."
585
  msgstr ""
586
 
587
+ #: includes/admin/stripe-settings.php:17
588
+ #. translators: %1, %2, %3, and %4 are all HTML markup tags
589
  msgid ""
590
  "%1$sClear all Stripe account keys.%2$s %3$sThis will disable any connection "
591
  "to Stripe.%4$s"
592
  msgstr ""
593
 
594
+ #: includes/admin/stripe-settings.php:29
595
+ #. translators: %1, %2 and %3 are all HTML markup tags
596
  msgid ""
597
  "%1$sSetup or link an existing Stripe account.%2$s By clicking this button "
598
  "you agree to the %3$sTerms of Service%2$s. Or, manually enter Stripe "
599
  "account keys below."
600
  msgstr ""
601
 
602
+ #: includes/admin/stripe-settings.php:35
603
  msgid "Manually enter Stripe keys below."
604
  msgstr ""
605
 
606
+ #: includes/admin/stripe-settings.php:44
607
  msgid "Enable Stripe"
608
  msgstr ""
609
 
610
+ #: includes/admin/stripe-settings.php:53
611
  msgid "Credit Card (Stripe)"
612
  msgstr ""
613
 
614
+ #: includes/admin/stripe-settings.php:60
615
  msgid "Pay with your credit card via Stripe."
616
  msgstr ""
617
 
618
+ #: includes/admin/stripe-settings.php:64
 
619
  msgid "Stripe Account Keys"
620
  msgstr ""
621
 
622
+ #: includes/admin/stripe-settings.php:69
623
  msgid "Test mode"
624
  msgstr ""
625
 
626
+ #: includes/admin/stripe-settings.php:70
627
  msgid "Enable Test Mode"
628
  msgstr ""
629
 
630
+ #: includes/admin/stripe-settings.php:72
631
  msgid "Place the payment gateway in test mode using test API keys."
632
  msgstr ""
633
 
634
+ #: includes/admin/stripe-settings.php:77
635
  msgid "Test Publishable Key"
636
  msgstr ""
637
 
638
+ #: includes/admin/stripe-settings.php:79
639
  msgid ""
640
  "Get your API keys from your stripe account. Invalid values will be "
641
  "rejected. Only values starting with \"pk_test_\" will be saved."
642
  msgstr ""
643
 
644
+ #: includes/admin/stripe-settings.php:84
645
  msgid "Test Secret Key"
646
  msgstr ""
647
 
648
+ #: includes/admin/stripe-settings.php:86
649
  msgid ""
650
  "Get your API keys from your stripe account. Invalid values will be "
651
  "rejected. Only values starting with \"sk_test_\" or \"rk_test_\" will be "
652
  "saved."
653
  msgstr ""
654
 
655
+ #: includes/admin/stripe-settings.php:91
656
+ msgid "Live Publishable Key"
657
  msgstr ""
658
 
659
+ #: includes/admin/stripe-settings.php:93
660
  msgid ""
661
+ "Get your API keys from your stripe account. Invalid values will be "
662
+ "rejected. Only values starting with \"pk_live_\" will be saved."
663
  msgstr ""
664
 
665
+ #: includes/admin/stripe-settings.php:98
666
+ msgid "Live Secret Key"
667
  msgstr ""
668
 
669
+ #: includes/admin/stripe-settings.php:100
670
  msgid ""
671
  "Get your API keys from your stripe account. Invalid values will be "
672
+ "rejected. Only values starting with \"sk_live_\" or \"rk_live_\" will be "
673
+ "saved."
674
  msgstr ""
675
 
676
  #: includes/admin/stripe-settings.php:110
677
+ msgid "Test Webhook Secret"
678
  msgstr ""
679
 
680
  #: includes/admin/stripe-settings.php:112
681
+ #: includes/admin/stripe-settings.php:119
682
  msgid ""
683
+ "Get your webhook signing secret from the webhooks section in your stripe "
684
+ "account."
 
685
  msgstr ""
686
 
687
  #: includes/admin/stripe-settings.php:117
1000
  msgstr ""
1001
 
1002
  #: includes/class-wc-gateway-stripe.php:832
1003
+ #: includes/class-wc-stripe-order-handler.php:159
1004
+ #: includes/class-wc-stripe-webhook-handler.php:264
1005
+ #: includes/compat/class-wc-stripe-sepa-subs-compat.php:287
1006
+ #: includes/compat/class-wc-stripe-subs-compat.php:339
1007
+ #: includes/payment-methods/class-wc-gateway-stripe-sepa.php:366
1008
  msgid ""
1009
  "Sorry, we are unable to process your payment at this time. Please retry "
1010
  "later."
1018
  "done is for you to authorize the payment with your bank."
1019
  msgstr ""
1020
 
1021
+ #: includes/class-wc-gateway-stripe.php:907
1022
+ #. translators: %s is the order Id
1023
+ msgid "Payment Intent not found for order #%s"
1024
+ msgstr ""
1025
+
1026
+ #: includes/class-wc-gateway-stripe.php:1133
1027
+ #: includes/class-wc-stripe-webhook-handler.php:768
1028
+ #: includes/class-wc-stripe-webhook-handler.php:813
1029
  #. translators: 1) The error message that was received from Stripe.
1030
  msgid "Stripe SCA authentication failed. Reason: %s"
1031
  msgstr ""
1032
 
1033
+ #: includes/class-wc-gateway-stripe.php:1134
1034
  msgid "Stripe SCA authentication failed."
1035
  msgstr ""
1036
 
1037
+ #: includes/class-wc-gateway-stripe.php:1191
1038
  msgid ""
1039
  "The \"Live Publishable Key\" should start with \"pk_live\", enter the "
1040
  "correct key."
1041
  msgstr ""
1042
 
1043
+ #: includes/class-wc-gateway-stripe.php:1199
1044
  msgid ""
1045
  "The \"Live Secret Key\" should start with \"sk_live\" or \"rk_live\", enter "
1046
  "the correct key."
1047
  msgstr ""
1048
 
1049
+ #: includes/class-wc-gateway-stripe.php:1207
1050
  msgid ""
1051
  "The \"Test Publishable Key\" should start with \"pk_test\", enter the "
1052
  "correct key."
1053
  msgstr ""
1054
 
1055
+ #: includes/class-wc-gateway-stripe.php:1215
1056
  msgid ""
1057
  "The \"Test Secret Key\" should start with \"sk_test\" or \"rk_test\", enter "
1058
  "the correct key."
1059
  msgstr ""
1060
 
1061
+ #: includes/class-wc-stripe-api.php:143 includes/class-wc-stripe-api.php:177
1062
  msgid "There was a problem connecting to the Stripe API endpoint."
1063
  msgstr ""
1064
 
1104
  "be enabled to see recorded logs."
1105
  msgstr ""
1106
 
1107
+ #: includes/class-wc-stripe-customer.php:130
1108
  #. translators: %1$s First name, %2$s Second name, %3$s Username.
1109
+ msgid "Name: %1$s %2$s, Username: %3$s"
1110
  msgstr ""
1111
 
1112
+ #: includes/class-wc-stripe-customer.php:146
1113
  #. translators: %1$s First name, %2$s Second name.
1114
  msgid "Name: %1$s %2$s, Guest"
1115
  msgstr ""
1116
 
1117
+ #: includes/class-wc-stripe-customer.php:204
1118
  msgid "Attempting to update a Stripe customer without a customer ID."
1119
  msgstr ""
1120
 
1121
+ #: includes/class-wc-stripe-customer.php:353
1122
  msgid "Unable to add payment source."
1123
  msgstr ""
1124
 
1218
  msgid "Unable to verify your request. Please reload the page and try again."
1219
  msgstr ""
1220
 
1221
+ #: includes/class-wc-stripe-intent-controller.php:200
1222
  msgid "Your card could not be set up for future usage."
1223
  msgstr ""
1224
 
1225
+ #: includes/class-wc-stripe-intent-controller.php:217
1226
  msgid "Failed to save payment method."
1227
  msgstr ""
1228
 
1229
+ #: includes/class-wc-stripe-order-handler.php:141
1230
+ #: includes/class-wc-stripe-webhook-handler.php:245
1231
+ #: includes/payment-methods/class-wc-gateway-stripe-sepa.php:346
1232
  msgid "This card is no longer available and has been removed."
1233
  msgstr ""
1234
 
1235
+ #: includes/class-wc-stripe-order-handler.php:191
1236
  #. translators: error message
1237
  msgid "Stripe payment failed: %s"
1238
  msgstr ""
1239
 
1240
+ #: includes/class-wc-stripe-order-handler.php:242
1241
+ #: includes/class-wc-stripe-order-handler.php:257
1242
+ #: includes/class-wc-stripe-order-handler.php:273
1243
+ #: includes/class-wc-stripe-order-handler.php:288
1244
  #. translators: error message
1245
  msgid "Unable to capture charge! %s"
1246
  msgstr ""
1249
  msgid "SEPA IBAN"
1250
  msgstr ""
1251
 
1252
+ #: includes/class-wc-stripe-sepa-payment-token.php:47
1253
  #. translators: last 4 digits of IBAN account
1254
  msgid "SEPA IBAN ending in %s"
1255
  msgstr ""
1256
 
1257
+ #: includes/class-wc-stripe-webhook-handler.php:324
1258
  #. translators: 1) The URL to the order.
1259
  msgid ""
1260
  "A dispute was created for this order. Response is needed. Please go to your "
1262
  "Dashboard</a> to review this dispute."
1263
  msgstr ""
1264
 
1265
+ #: includes/class-wc-stripe-webhook-handler.php:353
1266
  msgid "The dispute was lost or accepted."
1267
  msgstr ""
1268
 
1269
+ #: includes/class-wc-stripe-webhook-handler.php:355
1270
  msgid "The dispute was resolved in your favor."
1271
  msgstr ""
1272
 
1273
+ #: includes/class-wc-stripe-webhook-handler.php:357
1274
  msgid "The inquiry or retrieval was closed."
1275
  msgstr ""
1276
 
1277
+ #: includes/class-wc-stripe-webhook-handler.php:410
1278
  #. translators: partial captured amount
1279
  msgid "This charge was partially captured via Stripe Dashboard in the amount of: %s"
1280
  msgstr ""
1281
 
1282
+ #: includes/class-wc-stripe-webhook-handler.php:492
1283
  msgid "This payment failed to clear."
1284
  msgstr ""
1285
 
1286
+ #: includes/class-wc-stripe-webhook-handler.php:529
1287
  msgid "This payment was cancelled."
1288
  msgstr ""
1289
 
1290
+ #: includes/class-wc-stripe-webhook-handler.php:572
1291
  #. translators: amount (including currency symbol)
1292
  msgid "Pre-Authorization for %s voided from the Stripe Dashboard."
1293
  msgstr ""
1294
 
1295
+ #: includes/class-wc-stripe-webhook-handler.php:585
1296
  msgid "Refunded via Stripe Dashboard"
1297
  msgstr ""
1298
 
1299
+ #: includes/class-wc-stripe-webhook-handler.php:607
1300
  #. translators: 1) amount (including currency symbol) 2) transaction id 3)
1301
  #. refund message
1302
  msgid "Refunded %1$s - Refund ID: %2$s - %3$s"
1303
  msgstr ""
1304
 
1305
+ #: includes/class-wc-stripe-webhook-handler.php:638
1306
  #. translators: 1) The URL to the order. 2) The reason type.
1307
  msgid ""
1308
  "A review has been opened for this order. Action is needed. Please go to "
1310
  "Dashboard</a> to review the issue. Reason: (%2$s)"
1311
  msgstr ""
1312
 
1313
+ #: includes/class-wc-stripe-webhook-handler.php:671
1314
  #. translators: 1) The reason type.
1315
  msgid "The opened review for this order is now closed. Reason: (%s)"
1316
  msgstr ""
1317
 
1318
+ #: includes/class-wc-stripe-webhook-state.php:135
1319
+ msgid "No error"
1320
+ msgstr ""
1321
+
1322
+ #: includes/class-wc-stripe-webhook-state.php:139
1323
+ msgid "The webhook was missing expected headers"
1324
+ msgstr ""
1325
+
1326
+ #: includes/class-wc-stripe-webhook-state.php:143
1327
+ msgid "The webhook was missing expected body"
1328
+ msgstr ""
1329
+
1330
+ #: includes/class-wc-stripe-webhook-state.php:147
1331
+ msgid "The webhook received did not come from Stripe"
1332
+ msgstr ""
1333
+
1334
+ #: includes/class-wc-stripe-webhook-state.php:151
1335
+ msgid "The webhook signature was missing or was incorrectly formatted"
1336
+ msgstr ""
1337
+
1338
+ #: includes/class-wc-stripe-webhook-state.php:155
1339
+ msgid ""
1340
+ "The timestamp in the webhook differed more than five minutes from the site "
1341
+ "time"
1342
+ msgstr ""
1343
+
1344
+ #: includes/class-wc-stripe-webhook-state.php:159
1345
+ msgid "The webhook was not signed with the expected signing secret"
1346
+ msgstr ""
1347
+
1348
+ #: includes/class-wc-stripe-webhook-state.php:162
1349
+ msgid "Unknown error."
1350
+ msgstr ""
1351
+
1352
+ #: includes/class-wc-stripe-webhook-state.php:185
1353
+ #. translators: 1) date and time of last webhook received, e.g. 2020-06-28
1354
+ #. 10:30:50 UTC
1355
+ msgid "The most recent test webhook, timestamped %s, was processed successfully."
1356
+ msgstr ""
1357
+
1358
+ #: includes/class-wc-stripe-webhook-state.php:187
1359
+ #. translators: 1) date and time of last webhook received, e.g. 2020-06-28
1360
+ #. 10:30:50 UTC
1361
+ msgid "The most recent live webhook, timestamped %s, was processed successfully."
1362
+ msgstr ""
1363
+
1364
+ #: includes/class-wc-stripe-webhook-state.php:198
1365
+ #. translators: 1) date and time webhook monitoring began, e.g. 2020-06-28
1366
+ #. 10:30:50 UTC
1367
+ msgid "No test webhooks have been received since monitoring began at %s."
1368
+ msgstr ""
1369
+
1370
+ #: includes/class-wc-stripe-webhook-state.php:200
1371
+ #. translators: 1) date and time webhook monitoring began, e.g. 2020-06-28
1372
+ #. 10:30:50 UTC
1373
+ msgid "No live webhooks have been received since monitoring began at %s."
1374
+ msgstr ""
1375
+
1376
+ #: includes/class-wc-stripe-webhook-state.php:215
1377
+ #. translators: 1) date and time of last failed webhook e.g. 2020-06-28
1378
+ #. 10:30:50 UTC translators: 2) reason webhook failed translators: 3) date and
1379
+ #. time of last successful webhook e.g. 2020-05-28 10:30:50 UTC
1380
+ msgid ""
1381
+ "Warning: The most recent test webhook, received at %1$s, could not be "
1382
+ "processed. Reason: %2$s. (The last test webhook to process successfully was "
1383
+ "timestamped %3$s.)"
1384
+ msgstr ""
1385
+
1386
+ #: includes/class-wc-stripe-webhook-state.php:221
1387
+ #. translators: 1) date and time of last failed webhook e.g. 2020-06-28
1388
+ #. 10:30:50 UTC translators: 2) reason webhook failed translators: 3) date and
1389
+ #. time of last successful webhook e.g. 2020-05-28 10:30:50 UTC
1390
+ msgid ""
1391
+ "Warning: The most recent live webhook, received at %1$s, could not be "
1392
+ "processed. Reason: %2$s. (The last live webhook to process successfully was "
1393
+ "timestamped %3$s.)"
1394
+ msgstr ""
1395
+
1396
+ #: includes/class-wc-stripe-webhook-state.php:236
1397
+ #. translators: 1) date and time of last failed webhook e.g. 2020-06-28
1398
+ #. 10:30:50 UTC translators: 2) reason webhook failed translators: 3) date and
1399
+ #. time webhook monitoring began e.g. 2020-05-28 10:30:50 UTC
1400
+ msgid ""
1401
+ "Warning: The most recent test webhook, received at %1$s, could not be "
1402
+ "processed. Reason: %2$s. (No test webhooks have been processed successfully "
1403
+ "since monitoring began at %3$s.)"
1404
+ msgstr ""
1405
+
1406
+ #: includes/class-wc-stripe-webhook-state.php:241
1407
+ #. translators: 1) date and time of last failed webhook e.g. 2020-06-28
1408
+ #. 10:30:50 UTC translators: 2) reason webhook failed translators: 3) date and
1409
+ #. time webhook monitoring began e.g. 2020-05-28 10:30:50 UTC
1410
+ msgid ""
1411
+ "Warning: The most recent live webhook, received at %1$s, could not be "
1412
+ "processed. Reason: %2$s. (No live webhooks have been processed successfully "
1413
+ "since monitoring began at %3$s.)"
1414
+ msgstr ""
1415
+
1416
  #: includes/compat/class-wc-stripe-email-failed-authentication-retry.php:29
1417
  msgid "Payment Authentication Requested Email"
1418
  msgstr ""
1476
  msgid "Payment authorization needed for renewal of order {order_number}"
1477
  msgstr ""
1478
 
1479
+ #: includes/compat/class-wc-stripe-pre-orders-compat.php:53
1480
  msgid "Unable to store payment details. Please try again."
1481
  msgstr ""
1482
 
1483
+ #: includes/compat/class-wc-stripe-pre-orders-compat.php:117
1484
+ #: includes/compat/class-wc-stripe-subs-compat.php:372
1485
+ #: includes/compat/class-wc-stripe-subs-compat.php:678
1486
+ #. translators: %s is the charge Id
1487
+ #. translators: %s is the charge Id
1488
+ #. translators: %s is the stripe charge Id
1489
  msgid "Stripe charge awaiting authentication by user: %s."
1490
  msgstr ""
1491
 
1492
+ #: includes/compat/class-wc-stripe-pre-orders-compat.php:134
1493
  #. translators: error message
1494
  msgid "Stripe Transaction Failed (%s)"
1495
  msgstr ""
1496
 
1497
+ #: includes/compat/class-wc-stripe-sepa-subs-compat.php:84
1498
+ #: includes/compat/class-wc-stripe-subs-compat.php:94
1499
  msgid "Update the Payment Method used for all of my active subscriptions."
1500
  msgstr ""
1501
 
1502
+ #: includes/compat/class-wc-stripe-sepa-subs-compat.php:248
1503
+ #: includes/compat/class-wc-stripe-subs-compat.php:298
1504
  msgid "Customer not found"
1505
  msgstr ""
1506
 
1507
+ #: includes/compat/class-wc-stripe-sepa-subs-compat.php:408
1508
+ #: includes/compat/class-wc-stripe-subs-compat.php:519
1509
  #. translators: error message
1510
  msgid "A \"Stripe Customer ID\" value is required."
1511
  msgstr ""
1512
 
1513
+ #: includes/compat/class-wc-stripe-sepa-subs-compat.php:411
1514
+ #: includes/compat/class-wc-stripe-subs-compat.php:522
1515
  msgid ""
1516
  "Invalid customer ID. A valid \"Stripe Customer ID\" must begin with "
1517
  "\"cus_\"."
1518
  msgstr ""
1519
 
1520
+ #: includes/compat/class-wc-stripe-sepa-subs-compat.php:420
1521
  msgid ""
1522
  "Invalid source ID. A valid source \"Stripe Source ID\" must begin with "
1523
  "\"src_\" or \"card_\"."
1524
  msgstr ""
1525
 
1526
+ #: includes/compat/class-wc-stripe-sepa-subs-compat.php:493
1527
  #. translators: 1) last 4 digits of SEPA Direct Debit
1528
  msgid "Via SEPA Direct Debit ending in %1$s"
1529
  msgstr ""
1530
 
1531
+ #: includes/compat/class-wc-stripe-subs-compat.php:363
1532
  msgid "This transaction requires authentication."
1533
  msgstr ""
1534
 
1535
+ #: includes/compat/class-wc-stripe-subs-compat.php:532
1536
  msgid ""
1537
  "Invalid source ID. A valid source \"Stripe Source ID\" must begin with "
1538
  "\"src_\", \"pm_\", or \"card_\"."
1539
  msgstr ""
1540
 
1541
+ #: includes/compat/class-wc-stripe-subs-compat.php:613
1542
  #. translators: 1) card brand 2) last 4 digits
1543
  msgid "Via %1$s card ending in %2$s"
1544
  msgstr ""
1545
 
1546
+ #: includes/compat/class-wc-stripe-subs-compat.php:711
1547
  msgid "Your early renewal order was successful."
1548
  msgstr ""
1549
 
1550
+ #: includes/compat/class-wc-stripe-subs-compat.php:724
1551
  msgid ""
1552
  "Payment authorization for the renewal order was unsuccessful, please try "
1553
  "again."
1593
  msgid "You are not authorized to clear Stripe account keys."
1594
  msgstr ""
1595
 
1596
+ #: includes/payment-methods/class-wc-gateway-stripe-alipay.php:61
1597
  #: woocommerce-gateway-stripe.php:305
1598
  msgid "Stripe Alipay"
1599
  msgstr ""
1600
 
1601
+ #: includes/payment-methods/class-wc-gateway-stripe-alipay.php:63
1602
+ #: includes/payment-methods/class-wc-gateway-stripe-bancontact.php:63
1603
+ #: includes/payment-methods/class-wc-gateway-stripe-eps.php:63
1604
+ #: includes/payment-methods/class-wc-gateway-stripe-giropay.php:63
1605
+ #: includes/payment-methods/class-wc-gateway-stripe-ideal.php:63
1606
+ #: includes/payment-methods/class-wc-gateway-stripe-multibanco.php:63
1607
+ #: includes/payment-methods/class-wc-gateway-stripe-p24.php:63
1608
+ #: includes/payment-methods/class-wc-gateway-stripe-sepa.php:78
1609
+ #: includes/payment-methods/class-wc-gateway-stripe-sofort.php:63
1610
  #. translators: link
1611
  msgid "All other general Stripe settings can be adjusted <a href=\"%s\">here</a>."
1612
  msgstr ""
1613
 
1614
+ #: includes/payment-methods/class-wc-gateway-stripe-alipay.php:189
1615
+ #: includes/payment-methods/class-wc-gateway-stripe-bancontact.php:177
1616
+ #: includes/payment-methods/class-wc-gateway-stripe-eps.php:177
1617
+ #: includes/payment-methods/class-wc-gateway-stripe-giropay.php:177
1618
+ #: includes/payment-methods/class-wc-gateway-stripe-ideal.php:177
1619
+ #: includes/payment-methods/class-wc-gateway-stripe-multibanco.php:181
1620
+ #: includes/payment-methods/class-wc-gateway-stripe-p24.php:178
1621
+ #: includes/payment-methods/class-wc-gateway-stripe-sofort.php:177
1622
  msgid "Add Payment"
1623
  msgstr ""
1624
 
1625
+ #: includes/payment-methods/class-wc-gateway-stripe-bancontact.php:61
1626
  #: woocommerce-gateway-stripe.php:299
1627
  msgid "Stripe Bancontact"
1628
  msgstr ""
1629
 
1630
+ #: includes/payment-methods/class-wc-gateway-stripe-eps.php:61
1631
  #: woocommerce-gateway-stripe.php:302
1632
  msgid "Stripe EPS"
1633
  msgstr ""
1634
 
1635
+ #: includes/payment-methods/class-wc-gateway-stripe-giropay.php:61
1636
  #: woocommerce-gateway-stripe.php:301
1637
  msgid "Stripe Giropay"
1638
  msgstr ""
1639
 
1640
+ #: includes/payment-methods/class-wc-gateway-stripe-ideal.php:61
1641
  #: woocommerce-gateway-stripe.php:303
1642
  msgid "Stripe iDeal"
1643
  msgstr ""
1644
 
1645
+ #: includes/payment-methods/class-wc-gateway-stripe-multibanco.php:61
1646
  #: woocommerce-gateway-stripe.php:307
1647
  msgid "Stripe Multibanco"
1648
  msgstr ""
1649
 
1650
+ #: includes/payment-methods/class-wc-gateway-stripe-multibanco.php:240
1651
+ #: includes/payment-methods/class-wc-gateway-stripe-multibanco.php:252
1652
  msgid "MULTIBANCO INFORMAÇÕES DE ENCOMENDA:"
1653
  msgstr ""
1654
 
1655
+ #: includes/payment-methods/class-wc-gateway-stripe-multibanco.php:242
1656
+ #: includes/payment-methods/class-wc-gateway-stripe-multibanco.php:255
1657
  msgid "Montante:"
1658
  msgstr ""
1659
 
1660
+ #: includes/payment-methods/class-wc-gateway-stripe-multibanco.php:245
1661
+ #: includes/payment-methods/class-wc-gateway-stripe-multibanco.php:259
1662
  msgid "Entidade:"
1663
  msgstr ""
1664
 
1665
+ #: includes/payment-methods/class-wc-gateway-stripe-multibanco.php:248
1666
+ #: includes/payment-methods/class-wc-gateway-stripe-multibanco.php:263
1667
  msgid "Referencia:"
1668
  msgstr ""
1669
 
1670
+ #: includes/payment-methods/class-wc-gateway-stripe-multibanco.php:359
1671
  msgid "Awaiting Multibanco payment"
1672
  msgstr ""
1673
 
1674
+ #: includes/payment-methods/class-wc-gateway-stripe-p24.php:61
1675
  #: woocommerce-gateway-stripe.php:304
1676
  msgid "Stripe P24"
1677
  msgstr ""
1678
 
1679
+ #: includes/payment-methods/class-wc-gateway-stripe-sepa.php:76
1680
  #: woocommerce-gateway-stripe.php:306
1681
  msgid "Stripe SEPA Direct Debit"
1682
  msgstr ""
1683
 
1684
+ #: includes/payment-methods/class-wc-gateway-stripe-sepa.php:209
1685
  #. translators: statement descriptor
1686
  msgid ""
1687
  "By providing your IBAN and confirming this payment, you are authorizing %s "
1693
  "debited."
1694
  msgstr ""
1695
 
1696
+ #: includes/payment-methods/class-wc-gateway-stripe-sepa.php:225
1697
  msgid "IBAN."
1698
  msgstr ""
1699
 
1700
+ #: includes/payment-methods/class-wc-gateway-stripe-sepa.php:267
1701
  msgid ""
1702
  "TEST MODE ENABLED. In test mode, you can use IBAN number "
1703
  "DE89370400440532013000."
1704
  msgstr ""
1705
 
1706
+ #: includes/payment-methods/class-wc-gateway-stripe-sofort.php:61
1707
  #: woocommerce-gateway-stripe.php:300
1708
  msgid "Stripe SOFORT"
1709
  msgstr ""
1710
 
1711
  #: includes/payment-methods/class-wc-stripe-payment-request.php:303
1712
+ #: includes/payment-methods/class-wc-stripe-payment-request.php:960
1713
+ #: includes/payment-methods/class-wc-stripe-payment-request.php:1285
1714
  msgid "Tax"
1715
  msgstr ""
1716
 
1717
  #: includes/payment-methods/class-wc-stripe-payment-request.php:311
1718
+ #: includes/payment-methods/class-wc-stripe-payment-request.php:968
1719
+ #: includes/payment-methods/class-wc-stripe-payment-request.php:1292
1720
  msgid "Shipping"
1721
  msgstr ""
1722
 
1723
  #: includes/payment-methods/class-wc-stripe-payment-request.php:318
1724
+ #: includes/payment-methods/class-wc-stripe-payment-request.php:975
1725
  msgid "Pending"
1726
  msgstr ""
1727
 
1743
  msgid "Unable to find shipping method for address."
1744
  msgstr ""
1745
 
1746
+ #: includes/payment-methods/class-wc-stripe-payment-request.php:922
1747
+ #. translators: %d is the product Id
1748
  msgid "Product with the ID (%d) cannot be found."
1749
  msgstr ""
1750
 
1751
+ #: includes/payment-methods/class-wc-stripe-payment-request.php:943
1752
  #. translators: 1: product name 2: quantity in stock
1753
  msgid ""
1754
  "You cannot add that amount of \"%1$s\"; to the cart because there is not "
1755
  "enough stock (%2$s remaining)."
1756
  msgstr ""
1757
 
1758
+ #: includes/payment-methods/class-wc-stripe-payment-request.php:1132
1759
  msgid "Empty cart"
1760
  msgstr ""
1761
 
1762
+ #: includes/payment-methods/class-wc-stripe-payment-request.php:1299
1763
  msgid "Discount"
1764
  msgstr ""
1765
 
1766
+ #: templates/emails/failed-preorder-authentication.php:20
1767
  msgid "Authorize the payment now &raquo;"
1768
  msgstr ""
1769
 
1770
+ #: templates/emails/failed-preorder-authentication.php:57
1771
  msgid "Thanks for shopping with us."
1772
  msgstr ""
1773
 
1780
  msgid "Authorize the payment &raquo;"
1781
  msgstr ""
1782
 
1783
+ #: templates/emails/plain/failed-preorder-authentication.php:10
1784
+ #. translators: %s is a link to the payment re-authentication URL.
1785
+ msgid ""
1786
+ "Your pre-order is now available, but payment cannot be completed "
1787
+ "automatically. Please complete the payment now: %s"
1788
+ msgstr ""
1789
+
1790
+ #: woocommerce-gateway-stripe.php:41
1791
  #. translators: 1. URL link.
1792
  msgid ""
1793
  "Stripe requires WooCommerce to be installed and active. You can download %s "
1794
  "here."
1795
  msgstr ""
1796
 
1797
+ #: woocommerce-gateway-stripe.php:51
1798
  #. translators: $1. Minimum WooCommerce version. $2. Current WooCommerce
1799
  #. version.
1800
  msgid ""
1847
  msgid "Enable/Disable"
1848
  msgstr ""
1849
 
1850
+ #: templates/emails/failed-preorder-authentication.php:19
1851
  #. translators: %s is a link to the payment re-authentication URL.
1852
  msgctxt "In failed SCA authentication for a pre-order."
1853
  msgid ""
1879
  "The automatic payment to renew your subscription with %1$s has failed. To "
1880
  "reactivate the subscription, please login and authorize the renewal from "
1881
  "your account page: %2$s"
 
 
 
 
 
 
 
 
1882
  msgstr ""
readme.txt CHANGED
@@ -4,7 +4,7 @@ Tags: credit card, stripe, apple pay, payment request, google pay, sepa, sofort,
4
  Requires at least: 4.4
5
  Tested up to: 5.6
6
  Requires PHP: 5.6
7
- Stable tag: 4.9.0
8
  License: GPLv3
9
  License URI: https://www.gnu.org/licenses/gpl-3.0.html
10
  Attributions: thorsten-stripe
@@ -126,14 +126,12 @@ If you get stuck, you can ask for help in the Plugin Forum.
126
 
127
  == Changelog ==
128
 
129
- = 4.9.0 - 2021-02-24 =
130
 
131
- * Fix - Add fees as line items sent to Stripe to prevent Level 3 errors.
132
- * Fix - Adding a SEPA payment method doesn't work.
133
- * Fix - Apple Pay domain verification with live secret key.
134
- * Fix - Display the correct accepted card branding depending on store currency and location.
135
- * Fix - Remove duplicate Apple Pay domain registration Inbox notes.
136
- * Add - Copy Apple Pay domain registration file and trigger domain registration on domain name change.
137
- * Update - Notes and status when refunding order with charge authorization.
138
 
139
  [See changelog for all versions](https://raw.githubusercontent.com/woocommerce/woocommerce-gateway-stripe/trunk/changelog.txt).
4
  Requires at least: 4.4
5
  Tested up to: 5.6
6
  Requires PHP: 5.6
7
+ Stable tag: 5.0.0
8
  License: GPLv3
9
  License URI: https://www.gnu.org/licenses/gpl-3.0.html
10
  Attributions: thorsten-stripe
126
 
127
  == Changelog ==
128
 
129
+ = 5.0.0 - 2021-03-17 =
130
 
131
+ * Add - Display time of last Stripe webhook in settings.
132
+ * Add - wc_stripe_webhook_validate_user_agent filter to customize webhook user-agent validation.
133
+ * Fix - Payment Request Buttons for Chinese provinces in Chrome.
134
+ * Fix - Enable wc_stripe_send_stripe_receipt filter to send Stripe emails.
135
+ * Fix - Check for more errors when attaching sources to customers.
 
 
136
 
137
  [See changelog for all versions](https://raw.githubusercontent.com/woocommerce/woocommerce-gateway-stripe/trunk/changelog.txt).
templates/emails/failed-preorder-authentication.php CHANGED
@@ -11,16 +11,18 @@ $billing_email = $order->get_billing_email();
11
  $billing_phone = $order->get_billing_phone();
12
 
13
  ?>
14
- <p><?php
 
15
  echo wp_kses(
16
  sprintf(
17
  // translators: %s is a link to the payment re-authentication URL.
18
  _x( 'Your pre-order is now available, but payment cannot be completed automatically. %s', 'In failed SCA authentication for a pre-order.', 'woocommerce-gateway-stripe' ),
19
  '<a href="' . esc_url( $authorization_url ) . '">' . esc_html__( 'Authorize the payment now &raquo;', 'woocommerce-gateway-stripe' ) . '</a>'
20
  ),
21
- array( 'a' => array( 'href' => true ) )
22
  );
23
- ?></p>
 
24
 
25
  <?php if ( $email->get_custom_message() ) : ?>
26
  <blockquote><?php echo wpautop( wptexturize( $email->get_custom_message() ) ); ?></blockquote>
11
  $billing_phone = $order->get_billing_phone();
12
 
13
  ?>
14
+ <p>
15
+ <?php
16
  echo wp_kses(
17
  sprintf(
18
  // translators: %s is a link to the payment re-authentication URL.
19
  _x( 'Your pre-order is now available, but payment cannot be completed automatically. %s', 'In failed SCA authentication for a pre-order.', 'woocommerce-gateway-stripe' ),
20
  '<a href="' . esc_url( $authorization_url ) . '">' . esc_html__( 'Authorize the payment now &raquo;', 'woocommerce-gateway-stripe' ) . '</a>'
21
  ),
22
+ [ 'a' => [ 'href' => true ] ]
23
  );
24
+ ?>
25
+ </p>
26
 
27
  <?php if ( $email->get_custom_message() ) : ?>
28
  <blockquote><?php echo wpautop( wptexturize( $email->get_custom_message() ) ); ?></blockquote>
templates/emails/failed-renewal-authentication.php CHANGED
@@ -9,7 +9,8 @@ if ( ! defined( 'ABSPATH' ) ) {
9
  <p>
10
  <?php
11
  // translators: %1$s: name of the blog, %2$s: link to payment re-authentication URL, note: no full stop due to url at the end
12
- echo wp_kses( sprintf( _x( 'The automatic payment to renew your subscription with %1$s has failed. To reactivate the subscription, please login and authorize the renewal from your account page: %2$s', 'In failed renewal authentication email', 'woocommerce-gateway-stripe' ), esc_html( get_bloginfo( 'name' ) ), '<a href="' . esc_url( $authorization_url ) . '">' . esc_html__( 'Authorize the payment &raquo;', 'woocommerce-gateway-stripe' ) . '</a>' ), array( 'a' => array( 'href' => true ) ) ); ?>
 
13
  </p>
14
 
15
  <?php do_action( 'woocommerce_subscriptions_email_order_details', $order, $sent_to_admin, $plain_text, $email ); ?>
9
  <p>
10
  <?php
11
  // translators: %1$s: name of the blog, %2$s: link to payment re-authentication URL, note: no full stop due to url at the end
12
+ echo wp_kses( sprintf( _x( 'The automatic payment to renew your subscription with %1$s has failed. To reactivate the subscription, please login and authorize the renewal from your account page: %2$s', 'In failed renewal authentication email', 'woocommerce-gateway-stripe' ), esc_html( get_bloginfo( 'name' ) ), '<a href="' . esc_url( $authorization_url ) . '">' . esc_html__( 'Authorize the payment &raquo;', 'woocommerce-gateway-stripe' ) . '</a>' ), [ 'a' => [ 'href' => true ] ] );
13
+ ?>
14
  </p>
15
 
16
  <?php do_action( 'woocommerce_subscriptions_email_order_details', $order, $sent_to_admin, $plain_text, $email ); ?>
templates/emails/plain/failed-preorder-authentication.php CHANGED
@@ -7,7 +7,7 @@ echo $email_heading . "\n\n";
7
 
8
  printf(
9
  // translators: %s is a link to the payment re-authentication URL.
10
- _x( 'Your pre-order is now available, but payment cannot be completed automatically. Please complete the payment now: %s', 'woocommerce-gateway-stripe' ),
11
  $authorization_url
12
  );
13
 
7
 
8
  printf(
9
  // translators: %s is a link to the payment re-authentication URL.
10
+ __( 'Your pre-order is now available, but payment cannot be completed automatically. Please complete the payment now: %s', 'woocommerce-gateway-stripe' ),
11
  $authorization_url
12
  );
13
 
uninstall.php CHANGED
@@ -1,9 +1,9 @@
1
  <?php
2
  if ( ! defined( 'ABSPATH' ) ) {
3
- exit; // Exit if accessed directly
4
  }
5
 
6
- // if uninstall not called from WordPress exit
7
  if ( ! defined( 'WP_UNINSTALL_PLUGIN' ) ) {
8
  exit;
9
  }
1
  <?php
2
  if ( ! defined( 'ABSPATH' ) ) {
3
+ exit; // Exit if accessed directly.
4
  }
5
 
6
+ // if uninstall not called from WordPress exit.
7
  if ( ! defined( 'WP_UNINSTALL_PLUGIN' ) ) {
8
  exit;
9
  }
woocommerce-gateway-stripe.php CHANGED
@@ -5,14 +5,13 @@
5
  * Description: Take credit card payments on your store using Stripe.
6
  * Author: WooCommerce
7
  * Author URI: https://woocommerce.com/
8
- * Version: 4.9.0
9
  * Requires at least: 4.4
10
  * Tested up to: 5.6
11
  * WC requires at least: 3.0
12
  * WC tested up to: 5.0
13
  * Text Domain: woocommerce-gateway-stripe
14
  * Domain Path: /languages
15
- *
16
  */
17
 
18
  if ( ! defined( 'ABSPATH' ) ) {
@@ -22,7 +21,7 @@ if ( ! defined( 'ABSPATH' ) ) {
22
  /**
23
  * Required minimums and constants
24
  */
25
- define( 'WC_STRIPE_VERSION', '4.9.0' ); // WRCS: DEFINED_VERSION.
26
  define( 'WC_STRIPE_MIN_PHP_VER', '5.6.0' );
27
  define( 'WC_STRIPE_MIN_WC_VER', '3.0' );
28
  define( 'WC_STRIPE_FUTURE_MIN_WC_VER', '3.3' );
@@ -36,7 +35,6 @@ define( 'WC_STRIPE_PLUGIN_PATH', untrailingslashit( plugin_dir_path( __FILE__ )
36
  * WooCommerce fallback notice.
37
  *
38
  * @since 4.1.2
39
- * @return string
40
  */
41
  function woocommerce_stripe_missing_wc_notice() {
42
  /* translators: 1. URL link. */
@@ -47,7 +45,6 @@ function woocommerce_stripe_missing_wc_notice() {
47
  * WooCommerce not supported fallback notice.
48
  *
49
  * @since 4.4.0
50
- * @return string
51
  */
52
  function woocommerce_stripe_wc_not_supported() {
53
  /* translators: $1. Minimum WooCommerce version. $2. Current WooCommerce version. */
@@ -63,7 +60,9 @@ function woocommerce_gateway_stripe() {
63
  class WC_Stripe {
64
 
65
  /**
66
- * @var Singleton The reference the *Singleton* instance of this class
 
 
67
  */
68
  private static $instance;
69
 
@@ -114,21 +113,21 @@ function woocommerce_gateway_stripe() {
114
  * *Singleton* via the `new` operator from outside of this class.
115
  */
116
  public function __construct() {
117
- add_action( 'admin_init', array( $this, 'install' ) );
118
 
119
  $this->init();
120
 
121
  $this->api = new WC_Stripe_Connect_API();
122
  $this->connect = new WC_Stripe_Connect( $this->api );
123
 
124
- add_action( 'rest_api_init', array( $this, 'register_connect_routes' ) );
125
  }
126
 
127
  /**
128
  * Init the plugin after plugins_loaded so environment variables are set.
129
  *
130
  * @since 1.0.0
131
- * @version 4.0.0
132
  */
133
  public function init() {
134
  if ( is_admin() ) {
@@ -140,6 +139,7 @@ function woocommerce_gateway_stripe() {
140
  require_once dirname( __FILE__ ) . '/includes/class-wc-stripe-helper.php';
141
  include_once dirname( __FILE__ ) . '/includes/class-wc-stripe-api.php';
142
  require_once dirname( __FILE__ ) . '/includes/abstracts/abstract-wc-stripe-payment-gateway.php';
 
143
  require_once dirname( __FILE__ ) . '/includes/class-wc-stripe-webhook-handler.php';
144
  require_once dirname( __FILE__ ) . '/includes/class-wc-stripe-sepa-payment-token.php';
145
  require_once dirname( __FILE__ ) . '/includes/class-wc-stripe-apple-pay-registration.php';
@@ -172,16 +172,16 @@ function woocommerce_gateway_stripe() {
172
  // REMOVE IN THE FUTURE.
173
  require_once dirname( __FILE__ ) . '/includes/deprecated/class-wc-stripe-apple-pay.php';
174
 
175
- add_filter( 'woocommerce_payment_gateways', array( $this, 'add_gateways' ) );
176
- add_filter( 'pre_update_option_woocommerce_stripe_settings', array( $this, 'gateway_settings_update' ), 10, 2 );
177
- add_filter( 'plugin_action_links_' . plugin_basename( __FILE__ ), array( $this, 'plugin_action_links' ) );
178
- add_filter( 'plugin_row_meta', array( $this, 'plugin_row_meta' ), 10, 2 );
179
 
180
  // Modify emails emails.
181
- add_filter( 'woocommerce_email_classes', array( $this, 'add_emails' ), 20 );
182
 
183
  if ( version_compare( WC_VERSION, '3.4', '<' ) ) {
184
- add_filter( 'woocommerce_get_sections_checkout', array( $this, 'filter_gateway_order_admin' ) );
185
  }
186
  }
187
 
@@ -225,9 +225,9 @@ function woocommerce_gateway_stripe() {
225
  * @version 4.0.0
226
  */
227
  public function plugin_action_links( $links ) {
228
- $plugin_links = array(
229
  '<a href="admin.php?page=wc-settings&tab=checkout&section=stripe">' . esc_html__( 'Settings', 'woocommerce-gateway-stripe' ) . '</a>',
230
- );
231
  return array_merge( $plugin_links, $links );
232
  }
233
 
@@ -241,10 +241,10 @@ function woocommerce_gateway_stripe() {
241
  */
242
  public function plugin_row_meta( $links, $file ) {
243
  if ( plugin_basename( __FILE__ ) === $file ) {
244
- $row_meta = array(
245
  'docs' => '<a href="' . esc_url( apply_filters( 'woocommerce_gateway_stripe_docs_url', 'https://docs.woocommerce.com/document/stripe/' ) ) . '" title="' . esc_attr( __( 'View Documentation', 'woocommerce-gateway-stripe' ) ) . '">' . __( 'Docs', 'woocommerce-gateway-stripe' ) . '</a>',
246
  'support' => '<a href="' . esc_url( apply_filters( 'woocommerce_gateway_stripe_support_url', 'https://woocommerce.com/my-account/create-a-ticket?select=18627' ) ) . '" title="' . esc_attr( __( 'Open a support request at WooCommerce.com', 'woocommerce-gateway-stripe' ) ) . '">' . __( 'Support', 'woocommerce-gateway-stripe' ) . '</a>',
247
- );
248
  return array_merge( $links, $row_meta );
249
  }
250
  return (array) $links;
@@ -315,7 +315,7 @@ function woocommerce_gateway_stripe() {
315
  * @since 4.5.4
316
  * @version 4.5.4
317
  *
318
- * @param array $settings New settings to save
319
  * @param array|bool $old_settings Existing settings, if any.
320
  * @return array New value but with defaults initially filled in for missing settings.
321
  */
@@ -344,7 +344,7 @@ function woocommerce_gateway_stripe() {
344
  // Add all emails, generated by the gateway.
345
  $email_classes['WC_Stripe_Email_Failed_Renewal_Authentication'] = new WC_Stripe_Email_Failed_Renewal_Authentication( $email_classes );
346
  $email_classes['WC_Stripe_Email_Failed_Preorder_Authentication'] = new WC_Stripe_Email_Failed_Preorder_Authentication( $email_classes );
347
- $email_classes['WC_Stripe_Email_Failed_Authentication_Retry'] = new WC_Stripe_Email_Failed_Authentication_Retry( $email_classes );
348
 
349
  return $email_classes;
350
  }
5
  * Description: Take credit card payments on your store using Stripe.
6
  * Author: WooCommerce
7
  * Author URI: https://woocommerce.com/
8
+ * Version: 5.0.0
9
  * Requires at least: 4.4
10
  * Tested up to: 5.6
11
  * WC requires at least: 3.0
12
  * WC tested up to: 5.0
13
  * Text Domain: woocommerce-gateway-stripe
14
  * Domain Path: /languages
 
15
  */
16
 
17
  if ( ! defined( 'ABSPATH' ) ) {
21
  /**
22
  * Required minimums and constants
23
  */
24
+ define( 'WC_STRIPE_VERSION', '5.0.0' ); // WRCS: DEFINED_VERSION.
25
  define( 'WC_STRIPE_MIN_PHP_VER', '5.6.0' );
26
  define( 'WC_STRIPE_MIN_WC_VER', '3.0' );
27
  define( 'WC_STRIPE_FUTURE_MIN_WC_VER', '3.3' );
35
  * WooCommerce fallback notice.
36
  *
37
  * @since 4.1.2
 
38
  */
39
  function woocommerce_stripe_missing_wc_notice() {
40
  /* translators: 1. URL link. */
45
  * WooCommerce not supported fallback notice.
46
  *
47
  * @since 4.4.0
 
48
  */
49
  function woocommerce_stripe_wc_not_supported() {
50
  /* translators: $1. Minimum WooCommerce version. $2. Current WooCommerce version. */
60
  class WC_Stripe {
61
 
62
  /**
63
+ * The *Singleton* instance of this class
64
+ *
65
+ * @var Singleton
66
  */
67
  private static $instance;
68
 
113
  * *Singleton* via the `new` operator from outside of this class.
114
  */
115
  public function __construct() {
116
+ add_action( 'admin_init', [ $this, 'install' ] );
117
 
118
  $this->init();
119
 
120
  $this->api = new WC_Stripe_Connect_API();
121
  $this->connect = new WC_Stripe_Connect( $this->api );
122
 
123
+ add_action( 'rest_api_init', [ $this, 'register_connect_routes' ] );
124
  }
125
 
126
  /**
127
  * Init the plugin after plugins_loaded so environment variables are set.
128
  *
129
  * @since 1.0.0
130
+ * @version 5.0.0
131
  */
132
  public function init() {
133
  if ( is_admin() ) {
139
  require_once dirname( __FILE__ ) . '/includes/class-wc-stripe-helper.php';
140
  include_once dirname( __FILE__ ) . '/includes/class-wc-stripe-api.php';
141
  require_once dirname( __FILE__ ) . '/includes/abstracts/abstract-wc-stripe-payment-gateway.php';
142
+ require_once dirname( __FILE__ ) . '/includes/class-wc-stripe-webhook-state.php';
143
  require_once dirname( __FILE__ ) . '/includes/class-wc-stripe-webhook-handler.php';
144
  require_once dirname( __FILE__ ) . '/includes/class-wc-stripe-sepa-payment-token.php';
145
  require_once dirname( __FILE__ ) . '/includes/class-wc-stripe-apple-pay-registration.php';
172
  // REMOVE IN THE FUTURE.
173
  require_once dirname( __FILE__ ) . '/includes/deprecated/class-wc-stripe-apple-pay.php';
174
 
175
+ add_filter( 'woocommerce_payment_gateways', [ $this, 'add_gateways' ] );
176
+ add_filter( 'pre_update_option_woocommerce_stripe_settings', [ $this, 'gateway_settings_update' ], 10, 2 );
177
+ add_filter( 'plugin_action_links_' . plugin_basename( __FILE__ ), [ $this, 'plugin_action_links' ] );
178
+ add_filter( 'plugin_row_meta', [ $this, 'plugin_row_meta' ], 10, 2 );
179
 
180
  // Modify emails emails.
181
+ add_filter( 'woocommerce_email_classes', [ $this, 'add_emails' ], 20 );
182
 
183
  if ( version_compare( WC_VERSION, '3.4', '<' ) ) {
184
+ add_filter( 'woocommerce_get_sections_checkout', [ $this, 'filter_gateway_order_admin' ] );
185
  }
186
  }
187
 
225
  * @version 4.0.0
226
  */
227
  public function plugin_action_links( $links ) {
228
+ $plugin_links = [
229
  '<a href="admin.php?page=wc-settings&tab=checkout&section=stripe">' . esc_html__( 'Settings', 'woocommerce-gateway-stripe' ) . '</a>',
230
+ ];
231
  return array_merge( $plugin_links, $links );
232
  }
233
 
241
  */
242
  public function plugin_row_meta( $links, $file ) {
243
  if ( plugin_basename( __FILE__ ) === $file ) {
244
+ $row_meta = [
245
  'docs' => '<a href="' . esc_url( apply_filters( 'woocommerce_gateway_stripe_docs_url', 'https://docs.woocommerce.com/document/stripe/' ) ) . '" title="' . esc_attr( __( 'View Documentation', 'woocommerce-gateway-stripe' ) ) . '">' . __( 'Docs', 'woocommerce-gateway-stripe' ) . '</a>',
246
  'support' => '<a href="' . esc_url( apply_filters( 'woocommerce_gateway_stripe_support_url', 'https://woocommerce.com/my-account/create-a-ticket?select=18627' ) ) . '" title="' . esc_attr( __( 'Open a support request at WooCommerce.com', 'woocommerce-gateway-stripe' ) ) . '">' . __( 'Support', 'woocommerce-gateway-stripe' ) . '</a>',
247
+ ];
248
  return array_merge( $links, $row_meta );
249
  }
250
  return (array) $links;
315
  * @since 4.5.4
316
  * @version 4.5.4
317
  *
318
+ * @param array $settings New settings to save.
319
  * @param array|bool $old_settings Existing settings, if any.
320
  * @return array New value but with defaults initially filled in for missing settings.
321
  */
344
  // Add all emails, generated by the gateway.
345
  $email_classes['WC_Stripe_Email_Failed_Renewal_Authentication'] = new WC_Stripe_Email_Failed_Renewal_Authentication( $email_classes );
346
  $email_classes['WC_Stripe_Email_Failed_Preorder_Authentication'] = new WC_Stripe_Email_Failed_Preorder_Authentication( $email_classes );
347
+ $email_classes['WC_Stripe_Email_Failed_Authentication_Retry'] = new WC_Stripe_Email_Failed_Authentication_Retry( $email_classes );
348
 
349
  return $email_classes;
350
  }