WooCommerce Stripe Payment Gateway - Version 4.9.0

Version Description

  • 2021-02-24 =

  • Fix - Add fees as line items sent to Stripe to prevent Level 3 errors.

  • Fix - Adding a SEPA payment method doesn't work.

  • Fix - Apple Pay domain verification with live secret key.

  • Fix - Display the correct accepted card branding depending on store currency and location.

  • Fix - Remove duplicate Apple Pay domain registration Inbox notes.

  • Add - Copy Apple Pay domain registration file and trigger domain registration on domain name change.

  • Update - Notes and status when refunding order with charge authorization.

See changelog for all versions.

Download this release

Release Info

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

Code changes from version 4.8.0 to 4.9.0

changelog.txt CHANGED
@@ -1,4 +1,12 @@
1
  *** Changelog ***
 
 
 
 
 
 
 
 
2
 
3
  = 4.8.0 - 2021-01-28 =
4
  * Fix - Filter more disallowed characters from statement descriptors.
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.
5
+ * Fix - Apple Pay domain verification with live secret key.
6
+ * Fix - Display the correct accepted card branding depending on store currency and location.
7
+ * Fix - Remove duplicate Apple Pay domain registration Inbox notes.
8
+ * Add - Copy Apple Pay domain registration file and trigger domain registration on domain name change.
9
+ * Update - Notes and status when refunding order with charge authorization.
10
 
11
  = 4.8.0 - 2021-01-28 =
12
  * Fix - Filter more disallowed characters from statement descriptors.
includes/abstracts/abstract-wc-stripe-payment-gateway.php CHANGED
@@ -242,7 +242,7 @@ abstract class WC_Stripe_Payment_Gateway extends WC_Payment_Gateway_CC {
242
  */
243
  public function validate_minimum_order_amount( $order ) {
244
  if ( $order->get_total() * 100 < WC_Stripe_Helper::get_minimum_amount() ) {
245
- /* translators: 1) dollar amount */
246
  throw new WC_Stripe_Exception( 'Did not meet minimum amount', sprintf( __( 'Sorry, the minimum allowed order total is %1$s to use this payment method.', 'woocommerce-gateway-stripe' ), wc_price( WC_Stripe_Helper::get_minimum_amount() / 100 ) ) );
247
  }
248
  }
@@ -464,7 +464,7 @@ abstract class WC_Stripe_Payment_Gateway extends WC_Payment_Gateway_CC {
464
  }
465
 
466
  /* translators: transaction id */
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.', 'woocommerce-gateway-stripe' ), $response->id ) );
468
  }
469
 
470
  if ( is_callable( array( $order, 'save' ) ) ) {
@@ -819,10 +819,12 @@ abstract class WC_Stripe_Payment_Gateway extends WC_Payment_Gateway_CC {
819
  * Refund a charge.
820
  *
821
  * @since 3.1.0
822
- * @version 4.8.0
823
  * @param int $order_id
824
  * @param float $amount
 
825
  * @return bool
 
826
  */
827
  public function process_refund( $order_id, $amount = null, $reason = '' ) {
828
  $order = wc_get_order( $order_id );
@@ -857,7 +859,7 @@ abstract class WC_Stripe_Payment_Gateway extends WC_Payment_Gateway_CC {
857
  // Add some explainer text indicating where to find the full refund reason.
858
  $reason = $reason . '... [See WooCommerce order page for full text.]';
859
  }
860
-
861
  $request['metadata'] = array(
862
  'reason' => $reason,
863
  );
@@ -871,7 +873,7 @@ abstract class WC_Stripe_Payment_Gateway extends WC_Payment_Gateway_CC {
871
  $intent = $this->get_intent_from_order( $order );
872
  $intent_cancelled = false;
873
  if ( $intent ) {
874
- // If the order has a Payment Intent pending capture, then the Intent itself must be refunded (cancelled), not the Charge
875
  if ( ! empty( $intent->error ) ) {
876
  $response = $intent;
877
  $intent_cancelled = true;
@@ -891,7 +893,7 @@ abstract class WC_Stripe_Payment_Gateway extends WC_Payment_Gateway_CC {
891
  }
892
  }
893
 
894
- if ( ! $intent_cancelled ) {
895
  $response = WC_Stripe_API::request( $request, 'refunds' );
896
  }
897
 
@@ -901,20 +903,34 @@ abstract class WC_Stripe_Payment_Gateway extends WC_Payment_Gateway_CC {
901
  return $response;
902
 
903
  } elseif ( ! empty( $response->id ) ) {
904
- $order->update_meta_data( '_stripe_refund_id', $response->id );
905
-
906
- $amount = wc_price( $response->amount / 100 );
907
-
908
  if ( in_array( strtolower( $order->get_currency() ), WC_Stripe_Helper::no_decimal_currencies() ) ) {
909
- $amount = wc_price( $response->amount );
910
  }
911
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
912
  if ( isset( $response->balance_transaction ) ) {
913
  $this->update_fees( $order, $response->balance_transaction );
914
  }
915
 
916
- /* translators: 1) dollar amount 2) transaction id 3) refund message */
917
- $refund_message = ( isset( $captured ) && 'yes' === $captured ) ? sprintf( __( 'Refunded %1$s - Refund ID: %2$s - Reason: %3$s', 'woocommerce-gateway-stripe' ), $amount, $response->id, $reason ) : __( 'Pre-Authorization Released', 'woocommerce-gateway-stripe' );
918
 
919
  $order->add_order_note( $refund_message );
920
  WC_Stripe_Logger::log( 'Success: ' . html_entity_decode( wp_strip_all_tags( $refund_message ) ) );
@@ -1084,18 +1100,24 @@ abstract class WC_Stripe_Payment_Gateway extends WC_Payment_Gateway_CC {
1084
  public function get_level3_data_from_order( $order ) {
1085
  // Get the order items. Don't need their keys, only their values.
1086
  // Order item IDs are used as keys in the original order items array.
1087
- $order_items = array_values( $order->get_items() );
1088
  $currency = $order->get_currency();
1089
 
1090
- $stripe_line_items = array_map(function( $item ) use ( $currency ) {
1091
- $product_id = $item->get_variation_id()
1092
- ? $item->get_variation_id()
1093
- : $item->get_product_id();
 
 
 
 
 
 
1094
  $product_description = substr( $item->get_name(), 0, 26 );
1095
  $quantity = $item->get_quantity();
1096
- $unit_cost = WC_Stripe_Helper::get_stripe_amount( ( $item->get_subtotal() / $quantity ), $currency );
1097
  $tax_amount = WC_Stripe_Helper::get_stripe_amount( $item->get_total_tax(), $currency );
1098
- $discount_amount = WC_Stripe_Helper::get_stripe_amount( $item->get_subtotal() - $item->get_total(), $currency );
1099
 
1100
  return (object) array(
1101
  'product_code' => (string) $product_id, // Up to 12 characters that uniquely identify the product.
242
  */
243
  public function validate_minimum_order_amount( $order ) {
244
  if ( $order->get_total() * 100 < WC_Stripe_Helper::get_minimum_amount() ) {
245
+ /* translators: 1) amount (including currency symbol) */
246
  throw new WC_Stripe_Exception( 'Did not meet minimum amount', sprintf( __( 'Sorry, the minimum allowed order total is %1$s to use this payment method.', 'woocommerce-gateway-stripe' ), wc_price( WC_Stripe_Helper::get_minimum_amount() / 100 ) ) );
247
  }
248
  }
464
  }
465
 
466
  /* translators: transaction id */
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' ) ) ) {
819
  * Refund a charge.
820
  *
821
  * @since 3.1.0
822
+ * @version 4.9.0
823
  * @param int $order_id
824
  * @param float $amount
825
+ *
826
  * @return bool
827
+ * @throws Exception Throws exception when charge wasn't captured.
828
  */
829
  public function process_refund( $order_id, $amount = null, $reason = '' ) {
830
  $order = wc_get_order( $order_id );
859
  // Add some explainer text indicating where to find the full refund reason.
860
  $reason = $reason . '... [See WooCommerce order page for full text.]';
861
  }
862
+
863
  $request['metadata'] = array(
864
  'reason' => $reason,
865
  );
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;
893
  }
894
  }
895
 
896
+ if ( ! $intent_cancelled && 'yes' === $captured ) {
897
  $response = WC_Stripe_API::request( $request, 'refunds' );
898
  }
899
 
903
  return $response;
904
 
905
  } elseif ( ! empty( $response->id ) ) {
906
+ $formatted_amount = wc_price( $response->amount / 100 );
 
 
 
907
  if ( in_array( strtolower( $order->get_currency() ), WC_Stripe_Helper::no_decimal_currencies() ) ) {
908
+ $formatted_amount = wc_price( $response->amount );
909
  }
910
 
911
+ // If charge wasn't captured, skip creating a refund and cancel order.
912
+ if ( 'yes' !== $captured ) {
913
+ /* translators: amount (including currency symbol) */
914
+ $order->add_order_note( sprintf( __( 'Pre-Authorization for %s voided.', 'woocommerce-gateway-stripe' ), $formatted_amount ) );
915
+ $order->update_status( 'cancelled' );
916
+ // If amount is set, that means this function was called from the manual refund form.
917
+ if ( ! is_null( $amount ) ) {
918
+ // Throw an exception to provide a custom message on why the refund failed.
919
+ throw new Exception( __( 'The authorization was voided and the order cancelled. Click okay to continue, then refresh the page.', 'woocommerce-gateway-stripe' ) );
920
+ } else {
921
+ // If refund was initiaded by changing order status, prevent refund without errors.
922
+ return false;
923
+ }
924
+ }
925
+
926
+ $order->update_meta_data( '_stripe_refund_id', $response->id );
927
+
928
  if ( isset( $response->balance_transaction ) ) {
929
  $this->update_fees( $order, $response->balance_transaction );
930
  }
931
 
932
+ /* translators: 1) amount (including currency symbol) 2) transaction id 3) refund message */
933
+ $refund_message = sprintf( __( 'Refunded %1$s - Refund ID: %2$s - Reason: %3$s', 'woocommerce-gateway-stripe' ), $formatted_amount, $response->id, $reason );
934
 
935
  $order->add_order_note( $refund_message );
936
  WC_Stripe_Logger::log( 'Success: ' . html_entity_decode( wp_strip_all_tags( $refund_message ) ) );
1100
  public function get_level3_data_from_order( $order ) {
1101
  // Get the order items. Don't need their keys, only their values.
1102
  // Order item IDs are used as keys in the original order items array.
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.
includes/admin/class-wc-stripe-inbox-notes.php CHANGED
@@ -57,28 +57,24 @@ class WC_Stripe_Inbox_Notes {
57
  return;
58
  }
59
 
 
 
 
 
 
 
 
 
 
 
 
60
  if ( $verification_complete ) {
61
  if ( self::should_show_marketing_note() && ! wp_next_scheduled( self::POST_SETUP_SUCCESS_ACTION ) ) {
62
  wp_schedule_single_event( time() + DAY_IN_SECONDS, self::POST_SETUP_SUCCESS_ACTION );
63
  }
64
-
65
- // If the domain verification completed after failure note was created, make sure it's marked as actioned.
66
- try {
67
- $data_store = WC_Data_Store::load( 'admin-note' );
68
- $failure_note_ids = $data_store->get_notes_with_name( self::FAILURE_NOTE_NAME );
69
- if ( ! empty( $failure_note_ids ) ) {
70
- $note_id = array_pop( $failure_note_ids );
71
- $note = WC_Admin_Notes::get_note( $note_id );
72
- if ( false !== $note && WC_Admin_Note::E_WC_ADMIN_NOTE_ACTIONED !== $note->get_status() ) {
73
- $note->set_status( WC_Admin_Note::E_WC_ADMIN_NOTE_ACTIONED );
74
- $note->save();
75
- }
76
- }
77
- } catch ( Exception $e ) {} // @codingStandardsIgnoreLine.
78
  } else {
79
- if ( empty( $failure_note_ids ) ) {
80
- self::create_failure_note();
81
- }
82
  }
83
  }
84
 
57
  return;
58
  }
59
 
60
+ try {
61
+ $data_store = WC_Data_Store::load( 'admin-note' );
62
+ $failure_note_ids = $data_store->get_notes_with_name( self::FAILURE_NOTE_NAME );
63
+ // Delete all previously created, soft deleted and unactioned failure notes (Legacy).
64
+ while ( ! empty( $failure_note_ids ) ) {
65
+ $note_id = array_pop( $failure_note_ids );
66
+ $note = WC_Admin_Notes::get_note( $note_id );
67
+ $note->delete();
68
+ }
69
+ } catch ( Exception $e ) {} // @codingStandardsIgnoreLine
70
+
71
  if ( $verification_complete ) {
72
  if ( self::should_show_marketing_note() && ! wp_next_scheduled( self::POST_SETUP_SUCCESS_ACTION ) ) {
73
  wp_schedule_single_event( time() + DAY_IN_SECONDS, self::POST_SETUP_SUCCESS_ACTION );
74
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
75
  } else {
76
+ // Create new note if verification failed.
77
+ self::create_failure_note();
 
78
  }
79
  }
80
 
includes/admin/stripe-settings.php CHANGED
@@ -146,7 +146,7 @@ return apply_filters(
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 */
149
- __( 'Enable Payment Request Buttons. (Apple Pay/Google Pay) %1$sBy using Apple Pay, you agree to %2$s and %3$s\'s terms of service. (Apple Pay domain verification is performed automatically; configuration can be found on the %4$sStripe dashboard%5$s.)', 'woocommerce-gateway-stripe' ),
150
  '<br />',
151
  '<a href="https://stripe.com/apple-pay/legal" target="_blank">Stripe</a>',
152
  '<a href="https://developer.apple.com/apple-pay/acceptable-use-guidelines-for-websites/" target="_blank">Apple</a>',
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 */
149
+ __( 'Enable Payment Request Buttons. (Apple Pay/Google Pay) %1$sBy using Apple Pay, you agree to %2$s and %3$s\'s terms of service. (Apple Pay domain verification is performed automatically in live mode; configuration can be found on the %4$sStripe dashboard%5$s.)', 'woocommerce-gateway-stripe' ),
150
  '<br />',
151
  '<a href="https://stripe.com/apple-pay/legal" target="_blank">Stripe</a>',
152
  '<a href="https://developer.apple.com/apple-pay/acceptable-use-guidelines-for-websites/" target="_blank">Apple</a>',
includes/class-wc-gateway-stripe.php CHANGED
@@ -185,22 +185,17 @@ class WC_Gateway_Stripe extends WC_Stripe_Payment_Gateway {
185
  * Get_icon function.
186
  *
187
  * @since 1.0.0
188
- * @version 4.0.0
189
  * @return string
190
  */
191
  public function get_icon() {
192
  $icons = $this->payment_icons();
 
193
 
194
  $icons_str = '';
195
 
196
- $icons_str .= isset( $icons['visa'] ) ? $icons['visa'] : '';
197
- $icons_str .= isset( $icons['amex'] ) ? $icons['amex'] : '';
198
- $icons_str .= isset( $icons['mastercard'] ) ? $icons['mastercard'] : '';
199
-
200
- if ( 'USD' === get_woocommerce_currency() ) {
201
- $icons_str .= isset( $icons['discover'] ) ? $icons['discover'] : '';
202
- $icons_str .= isset( $icons['jcb'] ) ? $icons['jcb'] : '';
203
- $icons_str .= isset( $icons['diners'] ) ? $icons['diners'] : '';
204
  }
205
 
206
  return apply_filters( 'woocommerce_gateway_icon', $icons_str, $this->id );
@@ -738,7 +733,7 @@ class WC_Gateway_Stripe extends WC_Stripe_Payment_Gateway {
738
  </td>
739
  <td width="1%"></td>
740
  <td class="total">
741
- -&nbsp;<?php echo wc_price( $fee, array( 'currency' => $currency ) ); // wpcs: xss ok. ?>
742
  </td>
743
  </tr>
744
 
185
  * Get_icon function.
186
  *
187
  * @since 1.0.0
188
+ * @version 4.9.0
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 );
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
 
includes/class-wc-stripe-apple-pay-registration.php CHANGED
@@ -10,6 +10,10 @@ if ( ! defined( 'ABSPATH' ) ) {
10
  }
11
 
12
  class WC_Stripe_Apple_Pay_Registration {
 
 
 
 
13
  /**
14
  * Enabled.
15
  *
@@ -24,6 +28,13 @@ class WC_Stripe_Apple_Pay_Registration {
24
  */
25
  public $apple_pay_domain_set;
26
 
 
 
 
 
 
 
 
27
  /**
28
  * Stores Apple Pay domain verification issues.
29
  *
@@ -33,15 +44,17 @@ class WC_Stripe_Apple_Pay_Registration {
33
 
34
  public function __construct() {
35
  add_action( 'init', array( $this, 'add_domain_association_rewrite_rule' ) );
 
 
36
  add_filter( 'query_vars', array( $this, 'whitelist_domain_association_query_param' ), 10, 1 );
37
  add_action( 'parse_request', array( $this, 'parse_domain_association_request' ), 10, 1 );
38
 
39
  add_action( 'woocommerce_stripe_updated', array( $this, 'verify_domain_if_configured' ) );
40
  add_action( 'add_option_woocommerce_stripe_settings', array( $this, 'verify_domain_on_new_settings' ), 10, 2 );
41
  add_action( 'update_option_woocommerce_stripe_settings', array( $this, 'verify_domain_on_updated_settings' ), 10, 2 );
42
- add_action( 'admin_notices', array( $this, 'admin_notices' ) );
43
 
44
  $this->stripe_settings = get_option( 'woocommerce_stripe_settings', array() );
 
45
  $this->apple_pay_domain_set = 'yes' === $this->get_option( 'apple_pay_domain_set', 'no' );
46
  $this->apple_pay_verify_notice = '';
47
  }
@@ -83,19 +96,96 @@ class WC_Stripe_Apple_Pay_Registration {
83
  * Gets the Stripe secret key for the current mode.
84
  *
85
  * @since 4.5.3
 
86
  * @return string Secret key.
87
  */
88
  private function get_secret_key() {
89
- $testmode = 'yes' === $this->get_option( 'testmode', 'no' );
90
- return $testmode ? $this->get_option( 'test_secret_key' ) : $this->get_option( 'secret_key' );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
91
  }
92
 
93
  /**
94
  * Adds a rewrite rule for serving the domain association file from the proper location.
95
  */
96
  public function add_domain_association_rewrite_rule() {
97
- $regex = '^\.well-known\/apple-developer-merchantid-domain-association$';
98
- $redirect = 'index.php?apple-developer-merchantid-domain-association=1';
99
 
100
  add_rewrite_rule( $regex, $redirect, 'top' );
101
  }
@@ -107,7 +197,7 @@ class WC_Stripe_Apple_Pay_Registration {
107
  * @return array Updated public query vars.
108
  */
109
  public function whitelist_domain_association_query_param( $query_vars ) {
110
- $query_vars[] = 'apple-developer-merchantid-domain-association';
111
  return $query_vars;
112
  }
113
 
@@ -118,14 +208,14 @@ class WC_Stripe_Apple_Pay_Registration {
118
  */
119
  public function parse_domain_association_request( $wp ) {
120
  if (
121
- ! isset( $wp->query_vars['apple-developer-merchantid-domain-association'] ) ||
122
- '1' !== $wp->query_vars['apple-developer-merchantid-domain-association']
123
  ) {
124
  return;
125
  }
126
 
127
- $path = WC_STRIPE_PLUGIN_PATH . '/apple-developer-merchantid-domain-association';
128
- header( 'Content-Type: application/octet-stream' );
129
  echo esc_html( file_get_contents( $path ) );
130
  exit;
131
  }
@@ -134,7 +224,7 @@ class WC_Stripe_Apple_Pay_Registration {
134
  * Makes request to register the domain with Stripe/Apple Pay.
135
  *
136
  * @since 3.1.0
137
- * @version 4.5.4
138
  * @param string $secret_key
139
  */
140
  private function make_domain_registration_request( $secret_key ) {
@@ -145,7 +235,7 @@ class WC_Stripe_Apple_Pay_Registration {
145
  $endpoint = 'https://api.stripe.com/v1/apple_pay/domains';
146
 
147
  $data = array(
148
- 'domain_name' => $_SERVER['HTTP_HOST'],
149
  );
150
 
151
  $headers = array(
@@ -158,6 +248,7 @@ class WC_Stripe_Apple_Pay_Registration {
158
  array(
159
  'headers' => $headers,
160
  'body' => http_build_query( $data ),
 
161
  )
162
  );
163
 
@@ -191,8 +282,9 @@ class WC_Stripe_Apple_Pay_Registration {
191
  $this->make_domain_registration_request( $secret_key );
192
 
193
  // No errors to this point, verification success!
194
- $this->stripe_settings['apple_pay_domain_set'] = 'yes';
195
- $this->apple_pay_domain_set = true;
 
196
 
197
  update_option( 'woocommerce_stripe_settings', $this->stripe_settings );
198
 
@@ -201,8 +293,9 @@ class WC_Stripe_Apple_Pay_Registration {
201
  return true;
202
 
203
  } catch ( Exception $e ) {
204
- $this->stripe_settings['apple_pay_domain_set'] = 'no';
205
- $this->apple_pay_domain_set = false;
 
206
 
207
  update_option( 'woocommerce_stripe_settings', $this->stripe_settings );
208
 
@@ -216,7 +309,7 @@ class WC_Stripe_Apple_Pay_Registration {
216
  * Process the Apple Pay domain verification if proper settings are configured.
217
  *
218
  * @since 4.5.4
219
- * @version 4.5.4
220
  */
221
  public function verify_domain_if_configured() {
222
  $secret_key = $this->get_secret_key();
@@ -228,6 +321,10 @@ class WC_Stripe_Apple_Pay_Registration {
228
  // Ensure that domain association file will be served.
229
  flush_rewrite_rules();
230
 
 
 
 
 
231
  // Register the domain with Apple Pay.
232
  $verification_complete = $this->register_domain_with_apple( $secret_key );
233
 
10
  }
11
 
12
  class WC_Stripe_Apple_Pay_Registration {
13
+
14
+ const DOMAIN_ASSOCIATION_FILE_NAME = 'apple-developer-merchantid-domain-association';
15
+ const DOMAIN_ASSOCIATION_FILE_DIR = '.well-known';
16
+
17
  /**
18
  * Enabled.
19
  *
28
  */
29
  public $apple_pay_domain_set;
30
 
31
+ /**
32
+ * Current domain name.
33
+ *
34
+ * @var bool
35
+ */
36
+ private $domain_name;
37
+
38
  /**
39
  * Stores Apple Pay domain verification issues.
40
  *
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 = '';
60
  }
96
  * Gets the Stripe secret key for the current mode.
97
  *
98
  * @since 4.5.3
99
+ * @version 4.9.0
100
  * @return string Secret key.
101
  */
102
  private function get_secret_key() {
103
+ return $this->get_option( 'secret_key' );
104
+ }
105
+
106
+ /**
107
+ * Trigger Apple Pay registration upon domain name change.
108
+ *
109
+ * @since 4.9.0
110
+ */
111
+ public function verify_domain_on_domain_name_change() {
112
+ if ( $this->domain_name !== $this->get_option( 'apple_pay_verified_domain' ) ) {
113
+ $this->verify_domain_if_configured();
114
+ }
115
+ }
116
+
117
+ /**
118
+ * Vefifies if hosted domain association file is up to date
119
+ * with the file from the plugin directory.
120
+ *
121
+ * @since 4.9.0
122
+ * @return bool Wether file is up to date or not.
123
+ */
124
+ private function verify_hosted_domain_association_file_is_up_to_date() {
125
+ // Contents of domain association file from plugin dir.
126
+ $new_contents = @file_get_contents( WC_STRIPE_PLUGIN_PATH . '/' . self::DOMAIN_ASSOCIATION_FILE_NAME ); // @codingStandardsIgnoreLine
127
+ // Get file contents from local path and remote URL and check if either of which matches.
128
+ $fullpath = untrailingslashit( ABSPATH ) . '/' . self::DOMAIN_ASSOCIATION_FILE_DIR . '/' . self::DOMAIN_ASSOCIATION_FILE_NAME;
129
+ $local_contents = @file_get_contents( $fullpath ); // @codingStandardsIgnoreLine
130
+ $url = get_site_url() . '/' . self::DOMAIN_ASSOCIATION_FILE_DIR . '/' . self::DOMAIN_ASSOCIATION_FILE_NAME;
131
+ $response = @wp_remote_get( $url ); // @codingStandardsIgnoreLine
132
+ $remote_contents = @wp_remote_retrieve_body( $response ); // @codingStandardsIgnoreLine
133
+
134
+ return $local_contents === $new_contents || $remote_contents === $new_contents;
135
+ }
136
+
137
+ /**
138
+ * Copies and overwrites domain association file.
139
+ *
140
+ * @since 4.9.0
141
+ * @return null|string Error message.
142
+ */
143
+ private function copy_and_overwrite_domain_association_file() {
144
+ $well_known_dir = untrailingslashit( ABSPATH ) . '/' . self::DOMAIN_ASSOCIATION_FILE_DIR;
145
+ $fullpath = $well_known_dir . '/' . self::DOMAIN_ASSOCIATION_FILE_NAME;
146
+
147
+ if ( ! file_exists( $well_known_dir ) ) {
148
+ if ( ! @mkdir( $well_known_dir, 0755 ) ) { // @codingStandardsIgnoreLine
149
+ return __( 'Unable to create domain association folder to domain root.', 'woocommerce-gateway-stripe' );
150
+ }
151
+ }
152
+
153
+ if ( ! @copy( WC_STRIPE_PLUGIN_PATH . '/' . self::DOMAIN_ASSOCIATION_FILE_NAME, $fullpath ) ) { // @codingStandardsIgnoreLine
154
+ return __( 'Unable to copy domain association file to domain root.', 'woocommerce-gateway-stripe' );
155
+ }
156
+ }
157
+
158
+ /**
159
+ * Updates the Apple Pay domain association file.
160
+ * Reports failure only if file isn't already being served properly.
161
+ *
162
+ * @since 4.9.0
163
+ */
164
+ public function update_domain_association_file() {
165
+ if ( $this->verify_hosted_domain_association_file_is_up_to_date() ) {
166
+ return;
167
+ }
168
+
169
+ $error_message = $this->copy_and_overwrite_domain_association_file();
170
+
171
+ if ( isset( $error_message ) ) {
172
+ $url = get_site_url() . '/' . self::DOMAIN_ASSOCIATION_FILE_DIR . '/' . self::DOMAIN_ASSOCIATION_FILE_NAME;
173
+ WC_Stripe_Logger::log(
174
+ 'Error: ' . $error_message . ' ' .
175
+ /* translators: expected domain association file URL */
176
+ sprintf( __( 'To enable Apple Pay, domain association file must be hosted at %s.', 'woocommerce-gateway-stripe' ), $url )
177
+ );
178
+ } else {
179
+ WC_Stripe_Logger::log( __( 'Domain association file updated.', 'woocommerce-gateway-stripe' ) );
180
+ }
181
  }
182
 
183
  /**
184
  * Adds a rewrite rule for serving the domain association file from the proper location.
185
  */
186
  public function add_domain_association_rewrite_rule() {
187
+ $regex = '^\\' . self::DOMAIN_ASSOCIATION_FILE_DIR . '\/' . self::DOMAIN_ASSOCIATION_FILE_NAME . '$';
188
+ $redirect = 'index.php?' . self::DOMAIN_ASSOCIATION_FILE_NAME . '=1';
189
 
190
  add_rewrite_rule( $regex, $redirect, 'top' );
191
  }
197
  * @return array Updated public query vars.
198
  */
199
  public function whitelist_domain_association_query_param( $query_vars ) {
200
+ $query_vars[] = self::DOMAIN_ASSOCIATION_FILE_NAME;
201
  return $query_vars;
202
  }
203
 
208
  */
209
  public function parse_domain_association_request( $wp ) {
210
  if (
211
+ ! isset( $wp->query_vars[ self::DOMAIN_ASSOCIATION_FILE_NAME ] ) ||
212
+ '1' !== $wp->query_vars[ self::DOMAIN_ASSOCIATION_FILE_NAME ]
213
  ) {
214
  return;
215
  }
216
 
217
+ $path = WC_STRIPE_PLUGIN_PATH . '/' . self::DOMAIN_ASSOCIATION_FILE_NAME;
218
+ header( 'Content-Type: text/plain;charset=utf-8' );
219
  echo esc_html( file_get_contents( $path ) );
220
  exit;
221
  }
224
  * Makes request to register the domain with Stripe/Apple Pay.
225
  *
226
  * @since 3.1.0
227
+ * @version 4.9.0
228
  * @param string $secret_key
229
  */
230
  private function make_domain_registration_request( $secret_key ) {
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(
248
  array(
249
  'headers' => $headers,
250
  'body' => http_build_query( $data ),
251
+ 'timeout' => 30,
252
  )
253
  );
254
 
282
  $this->make_domain_registration_request( $secret_key );
283
 
284
  // No errors to this point, verification success!
285
+ $this->stripe_settings['apple_pay_verified_domain'] = $this->domain_name;
286
+ $this->stripe_settings['apple_pay_domain_set'] = 'yes';
287
+ $this->apple_pay_domain_set = true;
288
 
289
  update_option( 'woocommerce_stripe_settings', $this->stripe_settings );
290
 
293
  return true;
294
 
295
  } catch ( Exception $e ) {
296
+ $this->stripe_settings['apple_pay_verified_domain'] = $this->domain_name;
297
+ $this->stripe_settings['apple_pay_domain_set'] = 'no';
298
+ $this->apple_pay_domain_set = false;
299
 
300
  update_option( 'woocommerce_stripe_settings', $this->stripe_settings );
301
 
309
  * Process the Apple Pay domain verification if proper settings are configured.
310
  *
311
  * @since 4.5.4
312
+ * @version 4.9.0
313
  */
314
  public function verify_domain_if_configured() {
315
  $secret_key = $this->get_secret_key();
321
  // Ensure that domain association file will be served.
322
  flush_rewrite_rules();
323
 
324
+ // The rewrite rule method doesn't work if permalinks are set to Plain.
325
+ // Create/update domain association file by copying it from the plugin folder as a fallback.
326
+ $this->update_domain_association_file();
327
+
328
  // Register the domain with Apple Pay.
329
  $verification_complete = $this->register_domain_with_apple( $secret_key );
330
 
includes/class-wc-stripe-helper.php CHANGED
@@ -315,6 +315,41 @@ class WC_Stripe_Helper {
315
  return $minimum_amount;
316
  }
317
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
318
  /**
319
  * Gets all the saved setting options from a specific method.
320
  * If specific setting is passed, only return that.
315
  return $minimum_amount;
316
  }
317
 
318
+ /**
319
+ * Gets the supported card brands, taking the store's base country and currency into account.
320
+ * For more information, please see: https://stripe.com/docs/payments/cards/supported-card-brands.
321
+ *
322
+ * @since 4.9.0
323
+ * @version 4.9.0
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
+ }
341
+
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
+ }
349
+
350
+ return $supported_card_brands;
351
+ }
352
+
353
  /**
354
  * Gets all the saved setting options from a specific method.
355
  * If specific setting is passed, only return that.
includes/class-wc-stripe-intent-controller.php CHANGED
@@ -170,6 +170,16 @@ class WC_Stripe_Intent_Controller {
170
  throw new Exception( $source_object->get_error_message() );
171
  }
172
 
 
 
 
 
 
 
 
 
 
 
173
  // 4. Generate the setup intent
174
  $setup_intent = WC_Stripe_API::request(
175
  [
@@ -180,7 +190,7 @@ class WC_Stripe_Intent_Controller {
180
  'setup_intents'
181
  );
182
 
183
- if ( $setup_intent->error ) {
184
  $error_response_message = print_r( $setup_intent, true );
185
  WC_Stripe_Logger::log("Failed create Setup Intent while saving a card.");
186
  WC_Stripe_Logger::log("Response: $error_response_message");
170
  throw new Exception( $source_object->get_error_message() );
171
  }
172
 
173
+ // SEPA Direct Debit payments do not require any customer action after the source has been created.
174
+ // Once the customer has provided their IBAN details and accepted the mandate, no further action is needed and the resulting source is directly chargeable.
175
+ if ( 'sepa_debit' === $source_object->type ) {
176
+ $response = [
177
+ 'status' => 'success',
178
+ ];
179
+ echo wp_json_encode( $response );
180
+ return;
181
+ }
182
+
183
  // 4. Generate the setup intent
184
  $setup_intent = WC_Stripe_API::request(
185
  [
190
  'setup_intents'
191
  );
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");
includes/class-wc-stripe-webhook-handler.php CHANGED
@@ -272,8 +272,8 @@ class WC_Stripe_Webhook_Handler extends WC_Stripe_Payment_Gateway {
272
  }
273
 
274
  /**
275
- * Process webhook disputes that is created.
276
- * This is trigger when a fraud is detected or customer processes chargeback.
277
  * We want to put the order into on-hold and add an order note.
278
  *
279
  * @since 4.0.0
@@ -287,8 +287,15 @@ class WC_Stripe_Webhook_Handler extends WC_Stripe_Payment_Gateway {
287
  return;
288
  }
289
 
 
 
290
  /* translators: 1) The URL to the order. */
291
- $order->update_status( 'on-hold', sprintf( __( 'A dispute was created for this order. Response is needed. Please go to your <a href="%s" title="Stripe Dashboard" target="_blank">Stripe Dashboard</a> to review this dispute.', 'woocommerce-gateway-stripe' ), $this->get_transaction_url( $order ) ) );
 
 
 
 
 
292
 
293
  do_action( 'wc_gateway_stripe_process_webhook_payment_error', $order, $notification );
294
 
@@ -296,6 +303,43 @@ class WC_Stripe_Webhook_Handler extends WC_Stripe_Payment_Gateway {
296
  $this->send_failed_order_email( $order_id );
297
  }
298
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
299
  /**
300
  * Process webhook capture. This is used for an authorized only
301
  * transaction that is later captured via Stripe not WC.
@@ -414,7 +458,12 @@ class WC_Stripe_Webhook_Handler extends WC_Stripe_Payment_Gateway {
414
  return;
415
  }
416
 
417
- $order->update_status( 'failed', __( 'This payment failed to clear.', 'woocommerce-gateway-stripe' ) );
 
 
 
 
 
418
 
419
  do_action( 'wc_gateway_stripe_process_webhook_payment_error', $order, $notification );
420
  }
@@ -446,8 +495,11 @@ class WC_Stripe_Webhook_Handler extends WC_Stripe_Payment_Gateway {
446
  return;
447
  }
448
 
449
- if ( ! $order->has_status( 'cancelled' ) ) {
450
- $order->update_status( 'cancelled', __( 'This payment has cancelled.', 'woocommerce-gateway-stripe' ) );
 
 
 
451
  }
452
 
453
  do_action( 'wc_gateway_stripe_process_webhook_payment_error', $order, $notification );
@@ -457,7 +509,7 @@ class WC_Stripe_Webhook_Handler extends WC_Stripe_Payment_Gateway {
457
  * Process webhook refund.
458
  *
459
  * @since 4.0.0
460
- * @version 4.0.0
461
  * @param object $notification
462
  */
463
  public function process_webhook_refund( $notification ) {
@@ -475,14 +527,31 @@ class WC_Stripe_Webhook_Handler extends WC_Stripe_Payment_Gateway {
475
  $captured = $order->get_meta( '_stripe_charge_captured', true );
476
  $refund_id = $order->get_meta( '_stripe_refund_id', true );
477
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
478
  // If the refund ID matches, don't continue to prevent double refunding.
479
  if ( $notification->data->object->refunds->data[0]->id === $refund_id ) {
480
  return;
481
  }
482
 
483
- // Only refund captured charge.
484
  if ( $charge ) {
485
- $reason = ( isset( $captured ) && 'yes' === $captured ) ? __( 'Refunded via Stripe Dashboard', 'woocommerce-gateway-stripe' ) : __( 'Pre-Authorization Released via Stripe Dashboard', 'woocommerce-gateway-stripe' );
486
 
487
  // Create the refund.
488
  $refund = wc_create_refund(
@@ -499,20 +568,12 @@ class WC_Stripe_Webhook_Handler extends WC_Stripe_Payment_Gateway {
499
 
500
  $order->update_meta_data( '_stripe_refund_id', $notification->data->object->refunds->data[0]->id );
501
 
502
- $amount = wc_price( $notification->data->object->refunds->data[0]->amount / 100 );
503
-
504
- if ( in_array( strtolower( $order->get_currency() ), WC_Stripe_Helper::no_decimal_currencies() ) ) {
505
- $amount = wc_price( $notification->data->object->refunds->data[0]->amount );
506
- }
507
-
508
  if ( isset( $notification->data->object->refunds->data[0]->balance_transaction ) ) {
509
  $this->update_fees( $order, $notification->data->object->refunds->data[0]->balance_transaction );
510
  }
511
 
512
- /* translators: 1) dollar amount 2) transaction id 3) refund message */
513
- $refund_message = ( isset( $captured ) && 'yes' === $captured ) ? sprintf( __( 'Refunded %1$s - Refund ID: %2$s - %3$s', 'woocommerce-gateway-stripe' ), $amount, $notification->data->object->refunds->data[0]->id, $reason ) : __( 'Pre-Authorization Released via Stripe Dashboard', 'woocommerce-gateway-stripe' );
514
-
515
- $order->add_order_note( $refund_message );
516
  }
517
  }
518
  }
@@ -540,10 +601,12 @@ class WC_Stripe_Webhook_Handler extends WC_Stripe_Payment_Gateway {
540
  }
541
  }
542
 
 
 
543
  /* translators: 1) The URL to the order. 2) The reason type. */
544
  $message = sprintf( __( 'A review has been opened for this order. Action is needed. Please go to your <a href="%1$s" title="Stripe Dashboard" target="_blank">Stripe Dashboard</a> to review the issue. Reason: (%2$s)', 'woocommerce-gateway-stripe' ), $this->get_transaction_url( $order ), $notification->data->object->reason );
545
 
546
- if ( apply_filters( 'wc_stripe_webhook_review_change_order_status', true, $order, $notification ) ) {
547
  $order->update_status( 'on-hold', $message );
548
  } else {
549
  $order->add_order_note( $message );
@@ -576,12 +639,12 @@ class WC_Stripe_Webhook_Handler extends WC_Stripe_Payment_Gateway {
576
  /* translators: 1) The reason type. */
577
  $message = sprintf( __( 'The opened review for this order is now closed. Reason: (%s)', 'woocommerce-gateway-stripe' ), $notification->data->object->reason );
578
 
579
- if ( $order->has_status( 'on-hold' ) ) {
580
- if ( apply_filters( 'wc_stripe_webhook_review_change_order_status', true, $order, $notification ) ) {
581
- $order->update_status( 'processing', $message );
582
- } else {
583
- $order->add_order_note( $message );
584
- }
585
  } else {
586
  $order->add_order_note( $message );
587
  }
@@ -671,7 +734,13 @@ class WC_Stripe_Webhook_Handler extends WC_Stripe_Payment_Gateway {
671
  $error_message = $intent->last_payment_error ? $intent->last_payment_error->message : "";
672
 
673
  /* translators: 1) The error message that was received from Stripe. */
674
- $order->update_status( 'failed', sprintf( __( 'Stripe SCA authentication failed. Reason: %s', 'woocommerce-gateway-stripe' ), $error_message ) );
 
 
 
 
 
 
675
 
676
  do_action( 'wc_gateway_stripe_process_webhook_payment_error', $order, $notification );
677
 
@@ -710,7 +779,13 @@ class WC_Stripe_Webhook_Handler extends WC_Stripe_Payment_Gateway {
710
  $error_message = $intent->last_setup_error ? $intent->last_setup_error->message : "";
711
 
712
  /* translators: 1) The error message that was received from Stripe. */
713
- $order->update_status( 'failed', sprintf( __( 'Stripe SCA authentication failed. Reason: %s', 'woocommerce-gateway-stripe' ), $error_message ) );
 
 
 
 
 
 
714
 
715
  $this->send_failed_order_email( $order_id );
716
  }
@@ -753,6 +828,10 @@ class WC_Stripe_Webhook_Handler extends WC_Stripe_Payment_Gateway {
753
  $this->process_webhook_dispute( $notification );
754
  break;
755
 
 
 
 
 
756
  case 'charge.refunded':
757
  $this->process_webhook_refund( $notification );
758
  break;
272
  }
273
 
274
  /**
275
+ * Process webhook dispute that is created.
276
+ * This is triggered when fraud is detected or customer processes chargeback.
277
  * We want to put the order into on-hold and add an order note.
278
  *
279
  * @since 4.0.0
287
  return;
288
  }
289
 
290
+ $order->update_meta_data( '_stripe_status_before_hold', $order->get_status() );
291
+
292
  /* translators: 1) The URL to the order. */
293
+ $message = sprintf( __( 'A dispute was created for this order. Response is needed. Please go to your <a href="%s" title="Stripe Dashboard" target="_blank">Stripe Dashboard</a> to review this dispute.', 'woocommerce-gateway-stripe' ), $this->get_transaction_url( $order ) );
294
+ if ( ! $order->get_meta( '_stripe_status_final', false ) ) {
295
+ $order->update_status( 'on-hold', $message );
296
+ } else {
297
+ $order->add_order_note( $message );
298
+ }
299
 
300
  do_action( 'wc_gateway_stripe_process_webhook_payment_error', $order, $notification );
301
 
303
  $this->send_failed_order_email( $order_id );
304
  }
305
 
306
+ /**
307
+ * Process webhook dispute that is closed.
308
+ *
309
+ * @since 4.4.1
310
+ * @param object $notification
311
+ */
312
+ public function process_webhook_dispute_closed( $notification ) {
313
+ $order = WC_Stripe_Helper::get_order_by_charge_id( $notification->data->object->charge );
314
+ $status = $notification->data->object->status;
315
+
316
+ if ( ! $order ) {
317
+ WC_Stripe_Logger::log( 'Could not find order via charge ID: ' . $notification->data->object->charge );
318
+ return;
319
+ }
320
+
321
+ if ( 'lost' === $status ) {
322
+ $message = __( 'The dispute was lost or accepted.', 'woocommerce-gateway-stripe' );
323
+ } elseif ( 'won' === $status ) {
324
+ $message = __( 'The dispute was resolved in your favor.', 'woocommerce-gateway-stripe' );
325
+ } elseif ( 'warning_closed' === $status ) {
326
+ $message = __( 'The inquiry or retrieval was closed.', 'woocommerce-gateway-stripe' );
327
+ } else {
328
+ return;
329
+ }
330
+
331
+ if ( apply_filters( 'wc_stripe_webhook_dispute_change_order_status', true, $order, $notification ) ) {
332
+ // Mark final so that order status is not overridden by out-of-sequence events.
333
+ $order->update_meta_data( '_stripe_status_final', true );
334
+
335
+ // Fail order if dispute is lost, or else revert to pre-dispute status.
336
+ $order_status = 'lost' === $status ? 'failed' : $order->get_meta( '_stripe_status_before_hold', 'processing' );
337
+ $order->update_status( $order_status, $message );
338
+ } else {
339
+ $order->add_order_note( $message );
340
+ }
341
+ }
342
+
343
  /**
344
  * Process webhook capture. This is used for an authorized only
345
  * transaction that is later captured via Stripe not WC.
458
  return;
459
  }
460
 
461
+ $message = __( 'This payment failed to clear.', 'woocommerce-gateway-stripe' );
462
+ if ( ! $order->get_meta( '_stripe_status_final', false ) ) {
463
+ $order->update_status( 'failed', $message );
464
+ } else {
465
+ $order->add_order_note( $message );
466
+ }
467
 
468
  do_action( 'wc_gateway_stripe_process_webhook_payment_error', $order, $notification );
469
  }
495
  return;
496
  }
497
 
498
+ $message = __( 'This payment was cancelled.', 'woocommerce-gateway-stripe' );
499
+ if ( ! $order->has_status( 'cancelled' ) && ! $order->get_meta( '_stripe_status_final', false ) ) {
500
+ $order->update_status( 'cancelled', $message );
501
+ } else {
502
+ $order->add_order_note( $message );
503
  }
504
 
505
  do_action( 'wc_gateway_stripe_process_webhook_payment_error', $order, $notification );
509
  * Process webhook refund.
510
  *
511
  * @since 4.0.0
512
+ * @version 4.9.0
513
  * @param object $notification
514
  */
515
  public function process_webhook_refund( $notification ) {
527
  $captured = $order->get_meta( '_stripe_charge_captured', true );
528
  $refund_id = $order->get_meta( '_stripe_refund_id', true );
529
 
530
+ $amount = wc_price( $notification->data->object->refunds->data[0]->amount / 100 );
531
+ if ( in_array( strtolower( $order->get_currency() ), WC_Stripe_Helper::no_decimal_currencies() ) ) {
532
+ $amount = wc_price( $notification->data->object->refunds->data[0]->amount );
533
+ }
534
+
535
+ // If charge wasn't captured, skip creating a refund.
536
+ if ( 'yes' !== $captured ) {
537
+ // If the process was initiated from wp-admin,
538
+ // the order was already cancelled, so we don't need a new note.
539
+ if ( 'cancelled' !== $order->get_status() ) {
540
+ /* translators: amount (including currency symbol) */
541
+ $order->add_order_note( sprintf( __( 'Pre-Authorization for %s voided from the Stripe Dashboard.', 'woocommerce-gateway-stripe' ), $amount ) );
542
+ $order->update_status( 'cancelled' );
543
+ }
544
+
545
+ return;
546
+ }
547
+
548
  // If the refund ID matches, don't continue to prevent double refunding.
549
  if ( $notification->data->object->refunds->data[0]->id === $refund_id ) {
550
  return;
551
  }
552
 
 
553
  if ( $charge ) {
554
+ $reason = __( 'Refunded via Stripe Dashboard', 'woocommerce-gateway-stripe' );
555
 
556
  // Create the refund.
557
  $refund = wc_create_refund(
568
 
569
  $order->update_meta_data( '_stripe_refund_id', $notification->data->object->refunds->data[0]->id );
570
 
 
 
 
 
 
 
571
  if ( isset( $notification->data->object->refunds->data[0]->balance_transaction ) ) {
572
  $this->update_fees( $order, $notification->data->object->refunds->data[0]->balance_transaction );
573
  }
574
 
575
+ /* translators: 1) amount (including currency symbol) 2) transaction id 3) refund message */
576
+ $order->add_order_note( sprintf( __( 'Refunded %1$s - Refund ID: %2$s - %3$s', 'woocommerce-gateway-stripe' ), $amount, $notification->data->object->refunds->data[0]->id, $reason ) );
 
 
577
  }
578
  }
579
  }
601
  }
602
  }
603
 
604
+ $order->update_meta_data( '_stripe_status_before_hold', $order->get_status() );
605
+
606
  /* translators: 1) The URL to the order. 2) The reason type. */
607
  $message = sprintf( __( 'A review has been opened for this order. Action is needed. Please go to your <a href="%1$s" title="Stripe Dashboard" target="_blank">Stripe Dashboard</a> to review the issue. Reason: (%2$s)', 'woocommerce-gateway-stripe' ), $this->get_transaction_url( $order ), $notification->data->object->reason );
608
 
609
+ if ( apply_filters( 'wc_stripe_webhook_review_change_order_status', true, $order, $notification ) && ! $order->get_meta( '_stripe_status_final', false ) ) {
610
  $order->update_status( 'on-hold', $message );
611
  } else {
612
  $order->add_order_note( $message );
639
  /* translators: 1) The reason type. */
640
  $message = sprintf( __( 'The opened review for this order is now closed. Reason: (%s)', 'woocommerce-gateway-stripe' ), $notification->data->object->reason );
641
 
642
+ if (
643
+ $order->has_status( 'on-hold' ) &&
644
+ apply_filters( 'wc_stripe_webhook_review_change_order_status', true, $order, $notification ) &&
645
+ ! $order->get_meta( '_stripe_status_final', false )
646
+ ) {
647
+ $order->update_status( $order->get_meta( '_stripe_status_before_hold', 'processing' ), $message );
648
  } else {
649
  $order->add_order_note( $message );
650
  }
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 );
738
+
739
+ if ( ! $order->get_meta( '_stripe_status_final', false ) ) {
740
+ $order->update_status( 'failed', $message );
741
+ } else {
742
+ $order->add_order_note( $message );
743
+ }
744
 
745
  do_action( 'wc_gateway_stripe_process_webhook_payment_error', $order, $notification );
746
 
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 );
783
+
784
+ if ( ! $order->get_meta( '_stripe_status_final', false ) ) {
785
+ $order->update_status( 'failed', $message );
786
+ } else {
787
+ $order->add_order_note( $message );
788
+ }
789
 
790
  $this->send_failed_order_email( $order_id );
791
  }
828
  $this->process_webhook_dispute( $notification );
829
  break;
830
 
831
+ case 'charge.dispute.closed':
832
+ $this->process_webhook_dispute_closed( $notification );
833
+ break;
834
+
835
  case 'charge.refunded':
836
  $this->process_webhook_refund( $notification );
837
  break;
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.8.0\n"
6
  "Report-Msgid-Bugs-To: "
7
  "https://wordpress.org/support/plugin/woocommerce-gateway-stripe\n"
8
- "POT-Creation-Date: 2021-01-28 19:54:35+00:00\n"
9
  "MIME-Version: 1.0\n"
10
  "Content-Type: text/plain; charset=utf-8\n"
11
  "Content-Transfer-Encoding: 8bit\n"
@@ -31,7 +31,7 @@ msgstr ""
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) dollar amount
35
  #. translators: minimum amount
36
  msgid "Sorry, the minimum allowed order total is %1$s to use this payment method."
37
  msgstr ""
@@ -56,14 +56,14 @@ 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:340
60
- #: includes/class-wc-stripe-webhook-handler.php:390
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:508
67
  #: includes/compat/class-wc-stripe-sepa-subs-compat.php:185
68
  msgid "Payment processing failed. Please retry."
69
  msgstr ""
@@ -72,23 +72,32 @@ msgstr ""
72
  #. translators: transaction id
73
  msgid ""
74
  "Stripe charge authorized (Charge ID: %s). Process order to take payment, or "
75
- "cancel to remove the pre-authorization."
 
76
  msgstr ""
77
 
78
  #: includes/abstracts/abstract-wc-stripe-payment-gateway.php:645
79
  msgid "Invalid payment method. Please input a new card number."
80
  msgstr ""
81
 
82
- #: includes/abstracts/abstract-wc-stripe-payment-gateway.php:917
83
- #. translators: 1) dollar amount 2) transaction id 3) refund message
84
- msgid "Refunded %1$s - Refund ID: %2$s - Reason: %3$s"
 
 
 
 
 
 
85
  msgstr ""
86
 
87
- #: includes/abstracts/abstract-wc-stripe-payment-gateway.php:917
88
- msgid "Pre-Authorization Released"
 
 
89
  msgstr ""
90
 
91
- #: includes/abstracts/abstract-wc-stripe-payment-gateway.php:935
92
  msgid "There was a problem adding the payment method."
93
  msgstr ""
94
 
@@ -196,29 +205,29 @@ msgstr ""
196
  msgid "Boost sales with Apple Pay!"
197
  msgstr ""
198
 
199
- #: includes/admin/class-wc-stripe-inbox-notes.php:130
200
  msgid ""
201
  "Now that you accept Apple Pay® with Stripe, you can increase conversion "
202
  "rates by letting your customers know that Apple Pay is available. Here’s a "
203
  "marketing guide to help you get started."
204
  msgstr ""
205
 
206
- #: includes/admin/class-wc-stripe-inbox-notes.php:136
207
  msgid "See marketing guide"
208
  msgstr ""
209
 
210
- #: includes/admin/class-wc-stripe-inbox-notes.php:149
211
  msgid "Apple Pay domain verification needed"
212
  msgstr ""
213
 
214
- #: includes/admin/class-wc-stripe-inbox-notes.php:150
215
  msgid ""
216
  "The WooCommerce Stripe Gateway extension attempted to perform domain "
217
  "verification on behalf of your store, but was unable to do so. This must be "
218
  "resolved before Apple Pay can be offered to your customers."
219
  msgstr ""
220
 
221
- #: includes/admin/class-wc-stripe-inbox-notes.php:156
222
  msgid "Learn more"
223
  msgstr ""
224
 
@@ -723,8 +732,8 @@ msgstr ""
723
  msgid ""
724
  "Enable Payment Request Buttons. (Apple Pay/Google Pay) %1$sBy using Apple "
725
  "Pay, you agree to %2$s and %3$s's terms of service. (Apple Pay domain "
726
- "verification is performed automatically; configuration can be found on the "
727
- "%4$sStripe dashboard%5$s.)"
728
  msgstr ""
729
 
730
  #: includes/admin/stripe-settings.php:157
@@ -901,7 +910,7 @@ msgid ""
901
  "to remove any %1$ssaved payment methods%2$s on file and re-add them."
902
  msgstr ""
903
 
904
- #: includes/class-wc-gateway-stripe.php:258
905
  #. translators: link to Stripe testing page
906
  msgid ""
907
  "TEST MODE ENABLED. In test mode, you can use the card number "
@@ -910,23 +919,23 @@ msgid ""
910
  "card numbers."
911
  msgstr ""
912
 
913
- #: includes/class-wc-gateway-stripe.php:297
914
  msgid "Credit or debit card"
915
  msgstr ""
916
 
917
- #: includes/class-wc-gateway-stripe.php:305
918
  msgid "Card Number"
919
  msgstr ""
920
 
921
- #: includes/class-wc-gateway-stripe.php:316
922
  msgid "Expiry Date"
923
  msgstr ""
924
 
925
- #: includes/class-wc-gateway-stripe.php:324
926
  msgid "Card Code (CVC)"
927
  msgstr ""
928
 
929
- #: includes/class-wc-gateway-stripe.php:359
930
  msgid ""
931
  "<strong>Warning:</strong> your site's time does not match the time on your "
932
  "browser and may be incorrect. Some payment methods depend on webhook "
@@ -936,57 +945,57 @@ msgid ""
936
  "correct the site's time."
937
  msgstr ""
938
 
939
- #: includes/class-wc-gateway-stripe.php:420
940
  msgid "Please accept the terms and conditions first"
941
  msgstr ""
942
 
943
- #: includes/class-wc-gateway-stripe.php:421
944
  msgid "Please fill in required checkout fields first"
945
  msgstr ""
946
 
947
- #: includes/class-wc-gateway-stripe.php:450
948
- #: includes/class-wc-gateway-stripe.php:495
949
  msgid ""
950
  "Sorry, we're not accepting prepaid cards at this time. Your credit card has "
951
  "not been charged. Please try with alternative payment method."
952
  msgstr ""
953
 
954
- #: includes/class-wc-gateway-stripe.php:451
955
  msgid "Please enter your IBAN account name."
956
  msgstr ""
957
 
958
- #: includes/class-wc-gateway-stripe.php:452
959
  msgid "Please enter your IBAN account number."
960
  msgstr ""
961
 
962
- #: includes/class-wc-gateway-stripe.php:453
963
  msgid "We couldn't initiate the payment. Please try again."
964
  msgstr ""
965
 
966
- #: includes/class-wc-gateway-stripe.php:464
967
  msgid "Billing First Name and Last Name are required."
968
  msgstr ""
969
 
970
- #: includes/class-wc-gateway-stripe.php:736
971
  #. translators: error message
972
  msgid "This represents the fee Stripe collects for the transaction."
973
  msgstr ""
974
 
975
- #: includes/class-wc-gateway-stripe.php:737
976
  msgid "Stripe Fee:"
977
  msgstr ""
978
 
979
- #: includes/class-wc-gateway-stripe.php:773
980
  msgid ""
981
  "This represents the net total that will be credited to your Stripe bank "
982
  "account. This may be in the currency that is set in your Stripe account."
983
  msgstr ""
984
 
985
- #: includes/class-wc-gateway-stripe.php:774
986
  msgid "Stripe Payout:"
987
  msgstr ""
988
 
989
- #: includes/class-wc-gateway-stripe.php:837
990
  #: includes/class-wc-stripe-order-handler.php:158
991
  #: includes/class-wc-stripe-webhook-handler.php:233
992
  #: includes/compat/class-wc-stripe-sepa-subs-compat.php:284
@@ -997,7 +1006,7 @@ msgid ""
997
  "later."
998
  msgstr ""
999
 
1000
- #: includes/class-wc-gateway-stripe.php:890
1001
  msgid ""
1002
  "Almost there!\n"
1003
  "\n"
@@ -1005,36 +1014,36 @@ msgid ""
1005
  "done is for you to authorize the payment with your bank."
1006
  msgstr ""
1007
 
1008
- #: includes/class-wc-gateway-stripe.php:1131
1009
- #: includes/class-wc-stripe-webhook-handler.php:674
1010
- #: includes/class-wc-stripe-webhook-handler.php:713
1011
  #. translators: 1) The error message that was received from Stripe.
1012
  msgid "Stripe SCA authentication failed. Reason: %s"
1013
  msgstr ""
1014
 
1015
- #: includes/class-wc-gateway-stripe.php:1132
1016
  msgid "Stripe SCA authentication failed."
1017
  msgstr ""
1018
 
1019
- #: includes/class-wc-gateway-stripe.php:1189
1020
  msgid ""
1021
  "The \"Live Publishable Key\" should start with \"pk_live\", enter the "
1022
  "correct key."
1023
  msgstr ""
1024
 
1025
- #: includes/class-wc-gateway-stripe.php:1197
1026
  msgid ""
1027
  "The \"Live Secret Key\" should start with \"sk_live\" or \"rk_live\", enter "
1028
  "the correct key."
1029
  msgstr ""
1030
 
1031
- #: includes/class-wc-gateway-stripe.php:1205
1032
  msgid ""
1033
  "The \"Test Publishable Key\" should start with \"pk_test\", enter the "
1034
  "correct key."
1035
  msgstr ""
1036
 
1037
- #: includes/class-wc-gateway-stripe.php:1213
1038
  msgid ""
1039
  "The \"Test Secret Key\" should start with \"sk_test\" or \"rk_test\", enter "
1040
  "the correct key."
@@ -1044,25 +1053,42 @@ msgstr ""
1044
  msgid "There was a problem connecting to the Stripe API endpoint."
1045
  msgstr ""
1046
 
1047
- #: includes/class-wc-stripe-apple-pay-registration.php:142
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1048
  msgid "Unable to verify domain - missing secret key."
1049
  msgstr ""
1050
 
1051
- #: includes/class-wc-stripe-apple-pay-registration.php:166
1052
- #: includes/class-wc-stripe-apple-pay-registration.php:175
1053
  #. translators: error message
1054
  msgid "Unable to verify domain - %s"
1055
  msgstr ""
1056
 
1057
- #: includes/class-wc-stripe-apple-pay-registration.php:297
1058
  msgid "Apple Pay domain verification failed."
1059
  msgstr ""
1060
 
1061
- #: includes/class-wc-stripe-apple-pay-registration.php:298
1062
  msgid "Apple Pay domain verification failed with the following error:"
1063
  msgstr ""
1064
 
1065
- #: includes/class-wc-stripe-apple-pay-registration.php:301
1066
  #. translators: 1) HTML anchor open tag 2) HTML anchor closing tag
1067
  msgid ""
1068
  "Please check the %1$slogs%2$s for more details on this issue. Logging must "
@@ -1183,11 +1209,11 @@ msgstr ""
1183
  msgid "Unable to verify your request. Please reload the page and try again."
1184
  msgstr ""
1185
 
1186
- #: includes/class-wc-stripe-intent-controller.php:187
1187
  msgid "Your card could not be set up for future usage."
1188
  msgstr ""
1189
 
1190
- #: includes/class-wc-stripe-intent-controller.php:204
1191
  msgid "Failed to save payment method."
1192
  msgstr ""
1193
 
@@ -1219,7 +1245,7 @@ msgstr ""
1219
  msgid "SEPA IBAN ending in %s"
1220
  msgstr ""
1221
 
1222
- #: includes/class-wc-stripe-webhook-handler.php:291
1223
  #. translators: 1) The URL to the order.
1224
  msgid ""
1225
  "A dispute was created for this order. Response is needed. Please go to your "
@@ -1227,34 +1253,47 @@ msgid ""
1227
  "Dashboard</a> to review this dispute."
1228
  msgstr ""
1229
 
1230
- #: includes/class-wc-stripe-webhook-handler.php:335
 
 
 
 
 
 
 
 
 
 
 
 
1231
  #. translators: partial captured amount
1232
  msgid "This charge was partially captured via Stripe Dashboard in the amount of: %s"
1233
  msgstr ""
1234
 
1235
- #: includes/class-wc-stripe-webhook-handler.php:417
1236
  msgid "This payment failed to clear."
1237
  msgstr ""
1238
 
1239
- #: includes/class-wc-stripe-webhook-handler.php:450
1240
- msgid "This payment has cancelled."
1241
  msgstr ""
1242
 
1243
- #: includes/class-wc-stripe-webhook-handler.php:485
1244
- msgid "Refunded via Stripe Dashboard"
 
1245
  msgstr ""
1246
 
1247
- #: includes/class-wc-stripe-webhook-handler.php:485
1248
- #: includes/class-wc-stripe-webhook-handler.php:513
1249
- msgid "Pre-Authorization Released via Stripe Dashboard"
1250
  msgstr ""
1251
 
1252
- #: includes/class-wc-stripe-webhook-handler.php:513
1253
- #. translators: 1) dollar amount 2) transaction id 3) refund message
 
1254
  msgid "Refunded %1$s - Refund ID: %2$s - %3$s"
1255
  msgstr ""
1256
 
1257
- #: includes/class-wc-stripe-webhook-handler.php:544
1258
  #. translators: 1) The URL to the order. 2) The reason type.
1259
  msgid ""
1260
  "A review has been opened for this order. Action is needed. Please go to "
@@ -1262,7 +1301,7 @@ msgid ""
1262
  "Dashboard</a> to review the issue. Reason: (%2$s)"
1263
  msgstr ""
1264
 
1265
- #: includes/class-wc-stripe-webhook-handler.php:577
1266
  #. translators: 1) The reason type.
1267
  msgid "The opened review for this order is now closed. Reason: (%s)"
1268
  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 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"
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 ""
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 ""
72
  #. translators: transaction id
73
  msgid ""
74
  "Stripe charge authorized (Charge ID: %s). Process order to take payment, or "
75
+ "cancel to remove the pre-authorization. Attempting to refund the order in "
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
 
205
  msgid "Boost sales with Apple Pay!"
206
  msgstr ""
207
 
208
+ #: includes/admin/class-wc-stripe-inbox-notes.php:126
209
  msgid ""
210
  "Now that you accept Apple Pay® with Stripe, you can increase conversion "
211
  "rates by letting your customers know that Apple Pay is available. Here’s a "
212
  "marketing guide to help you get started."
213
  msgstr ""
214
 
215
+ #: includes/admin/class-wc-stripe-inbox-notes.php:132
216
  msgid "See marketing guide"
217
  msgstr ""
218
 
219
+ #: includes/admin/class-wc-stripe-inbox-notes.php:145
220
  msgid "Apple Pay domain verification needed"
221
  msgstr ""
222
 
223
+ #: includes/admin/class-wc-stripe-inbox-notes.php:146
224
  msgid ""
225
  "The WooCommerce Stripe Gateway extension attempted to perform domain "
226
  "verification on behalf of your store, but was unable to do so. This must be "
227
  "resolved before Apple Pay can be offered to your customers."
228
  msgstr ""
229
 
230
+ #: includes/admin/class-wc-stripe-inbox-notes.php:152
231
  msgid "Learn more"
232
  msgstr ""
233
 
732
  msgid ""
733
  "Enable Payment Request Buttons. (Apple Pay/Google Pay) %1$sBy using Apple "
734
  "Pay, you agree to %2$s and %3$s's terms of service. (Apple Pay domain "
735
+ "verification is performed automatically in live mode; configuration can be "
736
+ "found on the %4$sStripe dashboard%5$s.)"
737
  msgstr ""
738
 
739
  #: includes/admin/stripe-settings.php:157
910
  "to remove any %1$ssaved payment methods%2$s on file and re-add them."
911
  msgstr ""
912
 
913
+ #: includes/class-wc-gateway-stripe.php:253
914
  #. translators: link to Stripe testing page
915
  msgid ""
916
  "TEST MODE ENABLED. In test mode, you can use the card number "
919
  "card numbers."
920
  msgstr ""
921
 
922
+ #: includes/class-wc-gateway-stripe.php:292
923
  msgid "Credit or debit card"
924
  msgstr ""
925
 
926
+ #: includes/class-wc-gateway-stripe.php:300
927
  msgid "Card Number"
928
  msgstr ""
929
 
930
+ #: includes/class-wc-gateway-stripe.php:311
931
  msgid "Expiry Date"
932
  msgstr ""
933
 
934
+ #: includes/class-wc-gateway-stripe.php:319
935
  msgid "Card Code (CVC)"
936
  msgstr ""
937
 
938
+ #: includes/class-wc-gateway-stripe.php:354
939
  msgid ""
940
  "<strong>Warning:</strong> your site's time does not match the time on your "
941
  "browser and may be incorrect. Some payment methods depend on webhook "
945
  "correct the site's time."
946
  msgstr ""
947
 
948
+ #: includes/class-wc-gateway-stripe.php:415
949
  msgid "Please accept the terms and conditions first"
950
  msgstr ""
951
 
952
+ #: includes/class-wc-gateway-stripe.php:416
953
  msgid "Please fill in required checkout fields first"
954
  msgstr ""
955
 
956
+ #: includes/class-wc-gateway-stripe.php:445
957
+ #: includes/class-wc-gateway-stripe.php:490
958
  msgid ""
959
  "Sorry, we're not accepting prepaid cards at this time. Your credit card has "
960
  "not been charged. Please try with alternative payment method."
961
  msgstr ""
962
 
963
+ #: includes/class-wc-gateway-stripe.php:446
964
  msgid "Please enter your IBAN account name."
965
  msgstr ""
966
 
967
+ #: includes/class-wc-gateway-stripe.php:447
968
  msgid "Please enter your IBAN account number."
969
  msgstr ""
970
 
971
+ #: includes/class-wc-gateway-stripe.php:448
972
  msgid "We couldn't initiate the payment. Please try again."
973
  msgstr ""
974
 
975
+ #: includes/class-wc-gateway-stripe.php:459
976
  msgid "Billing First Name and Last Name are required."
977
  msgstr ""
978
 
979
+ #: includes/class-wc-gateway-stripe.php:731
980
  #. translators: error message
981
  msgid "This represents the fee Stripe collects for the transaction."
982
  msgstr ""
983
 
984
+ #: includes/class-wc-gateway-stripe.php:732
985
  msgid "Stripe Fee:"
986
  msgstr ""
987
 
988
+ #: includes/class-wc-gateway-stripe.php:768
989
  msgid ""
990
  "This represents the net total that will be credited to your Stripe bank "
991
  "account. This may be in the currency that is set in your Stripe account."
992
  msgstr ""
993
 
994
+ #: includes/class-wc-gateway-stripe.php:769
995
  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
1006
  "later."
1007
  msgstr ""
1008
 
1009
+ #: includes/class-wc-gateway-stripe.php:885
1010
  msgid ""
1011
  "Almost there!\n"
1012
  "\n"
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."
1053
  msgid "There was a problem connecting to the Stripe API endpoint."
1054
  msgstr ""
1055
 
1056
+ #: includes/class-wc-stripe-apple-pay-registration.php:149
1057
+ msgid "Unable to create domain association folder to domain root."
1058
+ msgstr ""
1059
+
1060
+ #: includes/class-wc-stripe-apple-pay-registration.php:154
1061
+ msgid "Unable to copy domain association file to domain root."
1062
+ msgstr ""
1063
+
1064
+ #: includes/class-wc-stripe-apple-pay-registration.php:176
1065
+ #. translators: expected domain association file URL
1066
+ msgid "To enable Apple Pay, domain association file must be hosted at %s."
1067
+ msgstr ""
1068
+
1069
+ #: includes/class-wc-stripe-apple-pay-registration.php:179
1070
+ msgid "Domain association file updated."
1071
+ msgstr ""
1072
+
1073
+ #: includes/class-wc-stripe-apple-pay-registration.php:232
1074
  msgid "Unable to verify domain - missing secret key."
1075
  msgstr ""
1076
 
1077
+ #: includes/class-wc-stripe-apple-pay-registration.php:257
1078
+ #: includes/class-wc-stripe-apple-pay-registration.php:266
1079
  #. translators: error message
1080
  msgid "Unable to verify domain - %s"
1081
  msgstr ""
1082
 
1083
+ #: includes/class-wc-stripe-apple-pay-registration.php:394
1084
  msgid "Apple Pay domain verification failed."
1085
  msgstr ""
1086
 
1087
+ #: includes/class-wc-stripe-apple-pay-registration.php:395
1088
  msgid "Apple Pay domain verification failed with the following error:"
1089
  msgstr ""
1090
 
1091
+ #: includes/class-wc-stripe-apple-pay-registration.php:398
1092
  #. translators: 1) HTML anchor open tag 2) HTML anchor closing tag
1093
  msgid ""
1094
  "Please check the %1$slogs%2$s for more details on this issue. Logging must "
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
 
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
  "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
  "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 ""
readme.txt CHANGED
@@ -2,9 +2,9 @@
2
  Contributors: woocommerce, automattic, royho, akeda, mattyza, bor0, woothemes
3
  Tags: credit card, stripe, apple pay, payment request, google pay, sepa, sofort, bancontact, alipay, giropay, ideal, p24, woocommerce, automattic
4
  Requires at least: 4.4
5
- Tested up to: 5.5
6
  Requires PHP: 5.6
7
- Stable tag: 4.8.0
8
  License: GPLv3
9
  License URI: https://www.gnu.org/licenses/gpl-3.0.html
10
  Attributions: thorsten-stripe
@@ -126,8 +126,14 @@ If you get stuck, you can ask for help in the Plugin Forum.
126
 
127
  == Changelog ==
128
 
129
- = 4.8.0 - 2021-01-28 =
130
- * Fix - Filter more disallowed characters from statement descriptors.
131
 
132
- [See changelog for all versions](https://raw.githubusercontent.com/woocommerce/woocommerce-gateway-stripe/trunk/changelog.txt).
 
 
 
 
 
 
133
 
 
2
  Contributors: woocommerce, automattic, royho, akeda, mattyza, bor0, woothemes
3
  Tags: credit card, stripe, apple pay, payment request, google pay, sepa, sofort, bancontact, alipay, giropay, ideal, p24, woocommerce, automattic
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
 
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).
woocommerce-gateway-stripe.php CHANGED
@@ -5,11 +5,11 @@
5
  * Description: Take credit card payments on your store using Stripe.
6
  * Author: WooCommerce
7
  * Author URI: https://woocommerce.com/
8
- * Version: 4.8.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: 4.9
13
  * Text Domain: woocommerce-gateway-stripe
14
  * Domain Path: /languages
15
  *
@@ -22,7 +22,7 @@ if ( ! defined( 'ABSPATH' ) ) {
22
  /**
23
  * Required minimums and constants
24
  */
25
- define( 'WC_STRIPE_VERSION', '4.8.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' );
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
  *
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' );