WC_Stripe_Helper   F
last analyzed

Complexity

Total Complexity 62

Size/Duplication

Total Lines 461
Duplicated Lines 22.99 %

Coupling/Cohesion

Components 0
Dependencies 0

Importance

Changes 0
Metric Value
dl 106
loc 461
rs 3.44
c 0
b 0
f 0
wmc 62
lcom 0
cbo 0

22 Methods

Rating   Name   Duplication   Size   Complexity  
A get_stripe_currency() 0 7 2
A update_stripe_currency() 0 7 2
A get_stripe_fee() 19 19 4
A update_stripe_fee() 0 7 2
A delete_stripe_fee() 10 10 2
A get_stripe_net() 19 19 4
A update_stripe_net() 0 7 2
A delete_stripe_net() 10 10 2
A get_stripe_amount() 0 11 3
A get_localized_messages() 0 27 2
A no_decimal_currencies() 0 20 1
A format_balance_fee() 0 19 5
C get_minimum_amount() 0 37 14
A get_settings() 0 9 4
A is_pre_orders_exists() 0 3 1
A is_wc_lt() 0 3 1
A get_webhook_url() 0 3 1
A get_order_by_source_id() 11 11 2
A get_order_by_charge_id() 15 15 3
A get_order_by_intent_id() 11 11 2
A get_order_by_setup_intent_id() 11 11 2
A clean_statement_descriptor() 0 10 1

How to fix   Duplicated Code    Complexity   

Duplicated Code

Duplicate code is one of the most pungent code smells. A rule that is often used is to re-structure code once it is duplicated in three or more places.

Common duplication problems, and corresponding solutions are:

Complex Class

 Tip:   Before tackling complexity, make sure that you eliminate any duplication first. This often can reduce the size of classes significantly.

Complex classes like WC_Stripe_Helper often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes. You can also have a look at the cohesion graph to spot any un-connected, or weakly-connected components.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

While breaking up the class, it is a good idea to analyze how other classes use WC_Stripe_Helper, and based on these observations, apply Extract Interface, too.

1
<?php
2
if ( ! defined( 'ABSPATH' ) ) {
3
	exit;
4
}
5
6
/**
7
 * Provides static methods as helpers.
8
 *
9
 * @since 4.0.0
10
 */
11
class WC_Stripe_Helper {
12
	const LEGACY_META_NAME_FEE      = 'Stripe Fee';
13
	const LEGACY_META_NAME_NET      = 'Net Revenue From Stripe';
14
	const META_NAME_FEE             = '_stripe_fee';
15
	const META_NAME_NET             = '_stripe_net';
16
	const META_NAME_STRIPE_CURRENCY = '_stripe_currency';
17
18
	/**
19
	 * Gets the Stripe currency for order.
20
	 *
21
	 * @since 4.1.0
22
	 * @param object $order
23
	 * @return string $currency
24
	 */
25
	public static function get_stripe_currency( $order = null ) {
26
		if ( is_null( $order ) ) {
27
			return false;
0 ignored issues
show
Bug Best Practice introduced by
The return type of return false; (false) is incompatible with the return type documented by WC_Stripe_Helper::get_stripe_currency of type string.

If you return a value from a function or method, it should be a sub-type of the type that is given by the parent type f.e. an interface, or abstract method. This is more formally defined by the Lizkov substitution principle, and guarantees that classes that depend on the parent type can use any instance of a child type interchangably. This principle also belongs to the SOLID principles for object oriented design.

Let’s take a look at an example:

class Author {
    private $name;

    public function __construct($name) {
        $this->name = $name;
    }

    public function getName() {
        return $this->name;
    }
}

abstract class Post {
    public function getAuthor() {
        return 'Johannes';
    }
}

class BlogPost extends Post {
    public function getAuthor() {
        return new Author('Johannes');
    }
}

class ForumPost extends Post { /* ... */ }

function my_function(Post $post) {
    echo strtoupper($post->getAuthor());
}

Our function my_function expects a Post object, and outputs the author of the post. The base class Post returns a simple string and outputting a simple string will work just fine. However, the child class BlogPost which is a sub-type of Post instead decided to return an object, and is therefore violating the SOLID principles. If a BlogPost were passed to my_function, PHP would not complain, but ultimately fail when executing the strtoupper call in its body.

Loading history...
28
		}
29
30
		return $order->get_meta( self::META_NAME_STRIPE_CURRENCY, true );
31
	}
32
33
	/**
34
	 * Updates the Stripe currency for order.
35
	 *
36
	 * @since 4.1.0
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
		}
44
45
		$order->update_meta_data( self::META_NAME_STRIPE_CURRENCY, $currency );
46
	}
47
48
	/**
49
	 * Gets the Stripe fee for order. With legacy check.
50
	 *
51
	 * @since 4.1.0
52
	 * @param object $order
53
	 * @return string $amount
54
	 */
55 View Code Duplication
	public static function get_stripe_fee( $order = null ) {
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
56
		if ( is_null( $order ) ) {
57
			return false;
0 ignored issues
show
Bug Best Practice introduced by
The return type of return false; (false) is incompatible with the return type documented by WC_Stripe_Helper::get_stripe_fee of type string.

If you return a value from a function or method, it should be a sub-type of the type that is given by the parent type f.e. an interface, or abstract method. This is more formally defined by the Lizkov substitution principle, and guarantees that classes that depend on the parent type can use any instance of a child type interchangably. This principle also belongs to the SOLID principles for object oriented design.

Let’s take a look at an example:

class Author {
    private $name;

    public function __construct($name) {
        $this->name = $name;
    }

    public function getName() {
        return $this->name;
    }
}

abstract class Post {
    public function getAuthor() {
        return 'Johannes';
    }
}

class BlogPost extends Post {
    public function getAuthor() {
        return new Author('Johannes');
    }
}

class ForumPost extends Post { /* ... */ }

function my_function(Post $post) {
    echo strtoupper($post->getAuthor());
}

Our function my_function expects a Post object, and outputs the author of the post. The base class Post returns a simple string and outputting a simple string will work just fine. However, the child class BlogPost which is a sub-type of Post instead decided to return an object, and is therefore violating the SOLID principles. If a BlogPost were passed to my_function, PHP would not complain, but ultimately fail when executing the strtoupper call in its body.

Loading history...
58
		}
59
60
		$amount = $order->get_meta( self::META_NAME_FEE, true );
61
62
		// If not found let's check for legacy name.
63
		if ( empty( $amount ) ) {
64
			$amount = $order->get_meta( self::LEGACY_META_NAME_FEE, true );
65
66
			// If found update to new name.
67
			if ( $amount ) {
68
				self::update_stripe_fee( $order, $amount );
69
			}
70
		}
71
72
		return $amount;
73
	}
74
75
	/**
76
	 * Updates the Stripe fee for order.
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 ) ) {
84
			return false;
85
		}
86
87
		$order->update_meta_data( self::META_NAME_FEE, $amount );
88
	}
89
90
	/**
91
	 * Deletes the Stripe fee for order.
92
	 *
93
	 * @since 4.1.0
94
	 * @param object $order
95
	 */
96 View Code Duplication
	public static function delete_stripe_fee( $order = null ) {
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
97
		if ( is_null( $order ) ) {
98
			return false;
99
		}
100
101
		$order_id = $order->get_id();
102
103
		delete_post_meta( $order_id, self::META_NAME_FEE );
104
		delete_post_meta( $order_id, self::LEGACY_META_NAME_FEE );
105
	}
106
107
	/**
108
	 * Gets the Stripe net for order. With legacy check.
109
	 *
110
	 * @since 4.1.0
111
	 * @param object $order
112
	 * @return string $amount
113
	 */
114 View Code Duplication
	public static function get_stripe_net( $order = null ) {
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
115
		if ( is_null( $order ) ) {
116
			return false;
0 ignored issues
show
Bug Best Practice introduced by
The return type of return false; (false) is incompatible with the return type documented by WC_Stripe_Helper::get_stripe_net of type string.

If you return a value from a function or method, it should be a sub-type of the type that is given by the parent type f.e. an interface, or abstract method. This is more formally defined by the Lizkov substitution principle, and guarantees that classes that depend on the parent type can use any instance of a child type interchangably. This principle also belongs to the SOLID principles for object oriented design.

Let’s take a look at an example:

class Author {
    private $name;

    public function __construct($name) {
        $this->name = $name;
    }

    public function getName() {
        return $this->name;
    }
}

abstract class Post {
    public function getAuthor() {
        return 'Johannes';
    }
}

class BlogPost extends Post {
    public function getAuthor() {
        return new Author('Johannes');
    }
}

class ForumPost extends Post { /* ... */ }

function my_function(Post $post) {
    echo strtoupper($post->getAuthor());
}

Our function my_function expects a Post object, and outputs the author of the post. The base class Post returns a simple string and outputting a simple string will work just fine. However, the child class BlogPost which is a sub-type of Post instead decided to return an object, and is therefore violating the SOLID principles. If a BlogPost were passed to my_function, PHP would not complain, but ultimately fail when executing the strtoupper call in its body.

Loading history...
117
		}
118
119
		$amount = $order->get_meta( self::META_NAME_NET, true );
120
121
		// If not found let's check for legacy name.
122
		if ( empty( $amount ) ) {
123
			$amount = $order->get_meta( self::LEGACY_META_NAME_NET, true );
124
125
			// If found update to new name.
126
			if ( $amount ) {
127
				self::update_stripe_net( $order, $amount );
128
			}
129
		}
130
131
		return $amount;
132
	}
133
134
	/**
135
	 * Updates the Stripe net for 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 ) ) {
143
			return false;
144
		}
145
146
		$order->update_meta_data( self::META_NAME_NET, $amount );
147
	}
148
149
	/**
150
	 * Deletes the Stripe net for order.
151
	 *
152
	 * @since 4.1.0
153
	 * @param object $order
154
	 */
155 View Code Duplication
	public static function delete_stripe_net( $order = null ) {
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
156
		if ( is_null( $order ) ) {
157
			return false;
158
		}
159
160
		$order_id = $order->get_id();
161
162
		delete_post_meta( $order_id, self::META_NAME_NET );
163
		delete_post_meta( $order_id, self::LEGACY_META_NAME_NET );
164
	}
165
166
	/**
167
	 * Get Stripe amount to pay
168
	 *
169
	 * @param float  $total Amount due.
170
	 * @param string $currency Accepted currency.
171
	 *
172
	 * @return float|int
173
	 */
174
	public static function get_stripe_amount( $total, $currency = '' ) {
175
		if ( ! $currency ) {
176
			$currency = get_woocommerce_currency();
177
		}
178
179
		if ( in_array( strtolower( $currency ), self::no_decimal_currencies() ) ) {
180
			return absint( $total );
181
		} else {
182
			return absint( wc_format_decimal( ( (float) $total * 100 ), wc_get_price_decimals() ) ); // In cents.
183
		}
184
	}
185
186
	/**
187
	 * Localize Stripe messages based on code
188
	 *
189
	 * @since 3.0.6
190
	 * @version 3.0.6
191
	 * @return array
192
	 */
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' ),
200
				'invalid_cvc'              => __( 'The card\'s security code is invalid.', 'woocommerce-gateway-stripe' ),
201
				'incorrect_number'         => __( 'The card number is incorrect.', 'woocommerce-gateway-stripe' ),
202
				'incomplete_number'        => __( 'The card number is incomplete.', 'woocommerce-gateway-stripe' ),
203
				'incomplete_cvc'           => __( 'The card\'s security code is incomplete.', 'woocommerce-gateway-stripe' ),
204
				'incomplete_expiry'        => __( 'The card\'s expiration date is incomplete.', 'woocommerce-gateway-stripe' ),
205
				'expired_card'             => __( 'The card has expired.', 'woocommerce-gateway-stripe' ),
206
				'incorrect_cvc'            => __( 'The card\'s security code is incorrect.', 'woocommerce-gateway-stripe' ),
207
				'incorrect_zip'            => __( 'The card\'s zip code failed validation.', 'woocommerce-gateway-stripe' ),
208
				'invalid_expiry_year_past' => __( 'The card\'s expiration year is in the past', 'woocommerce-gateway-stripe' ),
209
				'card_declined'            => __( 'The card was declined.', 'woocommerce-gateway-stripe' ),
210
				'missing'                  => __( 'There is no card on a customer that is being charged.', 'woocommerce-gateway-stripe' ),
211
				'processing_error'         => __( 'An error occurred while processing the card.', 'woocommerce-gateway-stripe' ),
212
				'invalid_sofort_country'   => __( 'The billing country is not accepted by SOFORT. Please try another country.', 'woocommerce-gateway-stripe' ),
213
				'email_invalid'            => __( 'Invalid email address, please correct and try again.', '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
221
	/**
222
	 * List of currencies supported by Stripe that has no decimals
223
	 * https://stripe.com/docs/currencies#zero-decimal from https://stripe.com/docs/currencies#presentment-currencies
224
	 *
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
232
			'gnf', // Guinean Franc
233
			'jpy', // Japanese Yen
234
			'kmf', // Comorian Franc
235
			'krw', // South Korean Won
236
			'mga', // Malagasy Ariary
237
			'pyg', // Paraguayan Guaraní
238
			'rwf', // Rwandan Franc
239
			'ugx', // Ugandan Shilling
240
			'vnd', // Vietnamese Đồng
241
			'vuv', // Vanuatu Vatu
242
			'xaf', // Central African Cfa Franc
243
			'xof', // West African Cfa Franc
244
			'xpf', // Cfp Franc
245
		);
246
	}
247
248
	/**
249
	 * Stripe uses smallest denomination in currencies such as cents.
250
	 * We need to format the returned currency from Stripe into human readable form.
251
	 * The amount is not used in any calculations so returning string is sufficient.
252
	 *
253
	 * @param object $balance_transaction
254
	 * @param string $type Type of number to format
255
	 * @return string
256
	 */
257
	public static function format_balance_fee( $balance_transaction, $type = 'fee' ) {
258
		if ( ! is_object( $balance_transaction ) ) {
259
			return;
260
		}
261
262
		if ( in_array( strtolower( $balance_transaction->currency ), self::no_decimal_currencies() ) ) {
263
			if ( 'fee' === $type ) {
264
				return $balance_transaction->fee;
265
			}
266
267
			return $balance_transaction->net;
268
		}
269
270
		if ( 'fee' === $type ) {
271
			return number_format( $balance_transaction->fee / 100, 2, '.', '' );
272
		}
273
274
		return number_format( $balance_transaction->net / 100, 2, '.', '' );
275
	}
276
277
	/**
278
	 * Checks Stripe minimum order value authorized per currency
279
	 */
280
	public static function get_minimum_amount() {
281
		// Check order amount
282
		switch ( get_woocommerce_currency() ) {
283
			case 'USD':
284
			case 'CAD':
285
			case 'EUR':
286
			case 'CHF':
287
			case 'AUD':
288
			case 'SGD':
289
				$minimum_amount = 50;
290
				break;
291
			case 'GBP':
292
				$minimum_amount = 30;
293
				break;
294
			case 'DKK':
295
				$minimum_amount = 250;
296
				break;
297
			case 'NOK':
298
			case 'SEK':
299
				$minimum_amount = 300;
300
				break;
301
			case 'JPY':
302
				$minimum_amount = 5000;
303
				break;
304
			case 'MXN':
305
				$minimum_amount = 1000;
306
				break;
307
			case 'HKD':
308
				$minimum_amount = 400;
309
				break;
310
			default:
311
				$minimum_amount = 50;
312
				break;
313
		}
314
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.
321
	 *
322
	 * @since 4.0.0
323
	 * @version 4.0.0
324
	 * @param string $method The payment method to get the settings from.
325
	 * @param string $setting The name of the setting to get.
326
	 */
327
	public static function get_settings( $method = null, $setting = null ) {
328
		$all_settings = null === $method ? get_option( 'woocommerce_stripe_settings', array() ) : get_option( 'woocommerce_stripe_' . $method . '_settings', array() );
329
330
		if ( null === $setting ) {
331
			return $all_settings;
332
		}
333
334
		return isset( $all_settings[ $setting ] ) ? $all_settings[ $setting ] : '';
335
	}
336
337
	/**
338
	 * Checks if Pre Orders is available.
339
	 *
340
	 * @since 4.1.0
341
	 * @return bool
342
	 */
343
	public static function is_pre_orders_exists() {
344
		return class_exists( 'WC_Pre_Orders_Order' );
345
	}
346
347
	/**
348
	 * Checks if WC version is less than passed in version.
349
	 *
350
	 * @since 4.1.11
351
	 * @param string $version Version to check against.
352
	 * @return bool
353
	 */
354
	public static function is_wc_lt( $version ) {
355
		return version_compare( WC_VERSION, $version, '<' );
356
	}
357
358
	/**
359
	 * Gets the webhook URL for Stripe triggers. Used mainly for
360
	 * asyncronous redirect payment methods in which statuses are
361
	 * not immediately chargeable.
362
	 *
363
	 * @since 4.0.0
364
	 * @version 4.0.0
365
	 * @return string
366
	 */
367
	public static function get_webhook_url() {
368
		return add_query_arg( 'wc-api', 'wc_stripe', trailingslashit( get_home_url() ) );
369
	}
370
371
	/**
372
	 * Gets the order by Stripe source ID.
373
	 *
374
	 * @since 4.0.0
375
	 * @version 4.0.0
376
	 * @param string $source_id
377
	 */
378 View Code Duplication
	public static function get_order_by_source_id( $source_id ) {
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
379
		global $wpdb;
380
381
		$order_id = $wpdb->get_var( $wpdb->prepare( "SELECT DISTINCT ID FROM $wpdb->posts as posts LEFT JOIN $wpdb->postmeta as meta ON posts.ID = meta.post_id WHERE meta.meta_value = %s AND meta.meta_key = %s", $source_id, '_stripe_source_id' ) );
382
383
		if ( ! empty( $order_id ) ) {
384
			return wc_get_order( $order_id );
385
		}
386
387
		return false;
388
	}
389
390
	/**
391
	 * Gets the order by Stripe charge ID.
392
	 *
393
	 * @since 4.0.0
394
	 * @since 4.1.16 Return false if charge_id is empty.
395
	 * @param string $charge_id
396
	 */
397 View Code Duplication
	public static function get_order_by_charge_id( $charge_id ) {
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
398
		global $wpdb;
399
400
		if ( empty( $charge_id ) ) {
401
			return false;
402
		}
403
404
		$order_id = $wpdb->get_var( $wpdb->prepare( "SELECT DISTINCT ID FROM $wpdb->posts as posts LEFT JOIN $wpdb->postmeta as meta ON posts.ID = meta.post_id WHERE meta.meta_value = %s AND meta.meta_key = %s", $charge_id, '_transaction_id' ) );
405
406
		if ( ! empty( $order_id ) ) {
407
			return wc_get_order( $order_id );
408
		}
409
410
		return false;
411
	}
412
413
	/**
414
	 * Gets the order by Stripe PaymentIntent ID.
415
	 *
416
	 * @since 4.2
417
	 * @param string $intent_id The ID of the intent.
418
	 * @return WC_Order|bool Either an order or false when not found.
419
	 */
420 View Code Duplication
	public static function get_order_by_intent_id( $intent_id ) {
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
421
		global $wpdb;
422
423
		$order_id = $wpdb->get_var( $wpdb->prepare( "SELECT DISTINCT ID FROM $wpdb->posts as posts LEFT JOIN $wpdb->postmeta as meta ON posts.ID = meta.post_id WHERE meta.meta_value = %s AND meta.meta_key = %s", $intent_id, '_stripe_intent_id' ) );
424
425
		if ( ! empty( $order_id ) ) {
426
			return wc_get_order( $order_id );
427
		}
428
429
		return false;
430
	}
431
432
	/**
433
	 * Gets the order by Stripe SetupIntent ID.
434
	 *
435
	 * @since 4.3
436
	 * @param string $intent_id The ID of the intent.
437
	 * @return WC_Order|bool Either an order or false when not found.
438
	 */
439 View Code Duplication
	public static function get_order_by_setup_intent_id( $intent_id ) {
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
440
		global $wpdb;
441
442
		$order_id = $wpdb->get_var( $wpdb->prepare( "SELECT DISTINCT ID FROM $wpdb->posts as posts LEFT JOIN $wpdb->postmeta as meta ON posts.ID = meta.post_id WHERE meta.meta_value = %s AND meta.meta_key = %s", $intent_id, '_stripe_setup_intent' ) );
443
444
		if ( ! empty( $order_id ) ) {
445
			return wc_get_order( $order_id );
446
		}
447
448
		return false;
449
	}
450
451
	/**
452
	 * Sanitize statement descriptor text.
453
	 *
454
	 * Stripe requires max of 22 characters and no
455
	 * special characters with ><"'.
456
	 *
457
	 * @since 4.0.0
458
	 * @param string $statement_descriptor
459
	 * @return string $statement_descriptor Sanitized statement descriptor
460
	 */
461
	public static function clean_statement_descriptor( $statement_descriptor = '' ) {
462
		$disallowed_characters = array( '<', '>', '"', "'" );
463
464
		// Remove special characters.
465
		$statement_descriptor = str_replace( $disallowed_characters, '', $statement_descriptor );
466
467
		$statement_descriptor = substr( trim( $statement_descriptor ), 0, 22 );
468
469
		return $statement_descriptor;
470
	}
471
}
472