Completed
Push — master ( 453eba...a7fcb8 )
by Roy
02:23
created

WC_Stripe_Payment_Request   D

Complexity

Total Complexity 192

Size/Duplication

Total Lines 1035
Duplicated Lines 18.16 %

Coupling/Cohesion

Components 1
Dependencies 2

Importance

Changes 0
Metric Value
dl 188
loc 1035
rs 4.4318
c 0
b 0
f 0
wmc 192
lcom 1
cbo 2

26 Methods

Rating   Name   Duplication   Size   Complexity  
F __construct() 0 35 15
B init() 0 38 3
A set_session() 0 9 3
A get_button_type() 0 3 2
A get_button_theme() 0 3 2
A get_button_height() 0 3 2
C get_product_data() 21 53 9
C filter_gateway_title() 0 24 10
B add_order_meta() 16 25 6
A supported_product_types() 0 7 1
B allowed_items_in_cart() 0 16 7
C scripts() 0 67 14
C display_payment_request_button_html() 43 43 15
C display_payment_request_button_separator_html() 39 39 15
A ajax_log_errors() 0 9 1
A ajax_clear_cart() 0 6 1
B ajax_get_cart_details() 0 24 2
B ajax_get_shipping_options() 0 57 8
B ajax_update_shipping_method() 0 26 4
F ajax_get_selected_product_data() 27 73 16
D ajax_add_to_cart() 6 42 9
F normalize_state() 24 32 19
A ajax_create_order() 0 15 3
C calculate_shipping() 0 67 11
A build_shipping_methods() 0 18 3
C build_display_items() 12 76 11

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_Payment_Request 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_Payment_Request, and based on these observations, apply Extract Interface, too.

1
<?php
2
/**
3
 * Stripe Payment Request API
4
 *
5
 * @package WooCommerce_Stripe/Classes/Payment_Request
6
 * @since   3.1.0
7
 */
8
9
if ( ! defined( 'ABSPATH' ) ) {
10
	exit;
11
}
12
13
/**
14
 * WC_Stripe_Payment_Request class.
15
 */
16
class WC_Stripe_Payment_Request {
17
	/**
18
	 * Enabled.
19
	 *
20
	 * @var
21
	 */
22
	public $stripe_settings;
23
24
	/**
25
	 * Stripe Checkout enabled.
26
	 *
27
	 * @var
28
	 */
29
	public $stripe_checkout_enabled;
30
31
	/**
32
	 * Total label
33
	 *
34
	 * @var
35
	 */
36
	public $total_label;
37
38
	/**
39
	 * Key
40
	 *
41
	 * @var
42
	 */
43
	public $publishable_key;
44
45
	/**
46
	 * Is test mode active?
47
	 *
48
	 * @var bool
49
	 */
50
	public $testmode;
51
52
	/**
53
	 * Initialize class actions.
54
	 *
55
	 * @since 3.0.0
56
	 * @version 4.0.0
57
	 */
58
	public function __construct() {
59
		$this->stripe_settings         = get_option( 'woocommerce_stripe_settings', array() );
60
		$this->testmode                = ( ! empty( $this->stripe_settings['testmode'] ) && 'yes' === $this->stripe_settings['testmode'] ) ? true : false;
61
		$this->publishable_key         = ! empty( $this->stripe_settings['publishable_key'] ) ? $this->stripe_settings['publishable_key'] : '';
62
		$this->stripe_checkout_enabled = isset( $this->stripe_settings['stripe_checkout'] ) && 'yes' === $this->stripe_settings['stripe_checkout'];
63
		$this->total_label             = ! empty( $this->stripe_settings['statement_descriptor'] ) ? WC_Stripe_Helper::clean_statement_descriptor( $this->stripe_settings['statement_descriptor'] ) : '';
64
65
		if ( $this->testmode ) {
66
			$this->publishable_key = ! empty( $this->stripe_settings['test_publishable_key'] ) ? $this->stripe_settings['test_publishable_key'] : '';
67
		}
68
69
		// If both site title and statement descriptor is not set. Fallback.
70
		if ( empty( $this->total_label ) ) {
71
			$this->total_label = $_SERVER['SERVER_NAME'];
72
		}
73
74
		$this->total_label = str_replace( "'", '', $this->total_label ) . apply_filters( 'wc_stripe_payment_request_total_label_suffix', ' (via WooCommerce)' );
75
76
		// Checks if Stripe Gateway is enabled.
77
		if ( empty( $this->stripe_settings ) || ( isset( $this->stripe_settings['enabled'] ) && 'yes' !== $this->stripe_settings['enabled'] ) ) {
78
			return;
79
		}
80
81
		// Checks if Payment Request is enabled.
82
		if ( ! isset( $this->stripe_settings['payment_request'] ) || 'yes' !== $this->stripe_settings['payment_request'] ) {
83
			return;
84
		}
85
86
		// Don't load for change payment method page.
87
		if ( isset( $_GET['change_payment_method'] ) ) {
88
			return;
89
		}
90
91
		$this->init();
92
	}
93
94
	/**
95
	 * Initialize hooks.
96
	 *
97
	 * @since 4.0.0
98
	 * @version 4.0.0
99
	 */
100
	protected function init() {
101
		add_action( 'wp_enqueue_scripts', array( $this, 'scripts' ) );
102
		add_action( 'wp', array( $this, 'set_session' ) );
103
104
		/*
105
		 * In order to display the Payment Request button in the correct position,
106
		 * a new hook was added to WooCommerce 3.0. In older versions of WooCommerce,
107
		 * CSS is used to position the button.
108
		 */
109
		if ( WC_Stripe_Helper::is_pre_30() ) {
110
			add_action( 'woocommerce_after_add_to_cart_button', array( $this, 'display_payment_request_button_html' ), 1 );
111
			add_action( 'woocommerce_after_add_to_cart_button', array( $this, 'display_payment_request_button_separator_html' ), 2 );
112
		} else {
113
			add_action( 'woocommerce_after_add_to_cart_quantity', array( $this, 'display_payment_request_button_html' ), 1 );
114
			add_action( 'woocommerce_after_add_to_cart_quantity', array( $this, 'display_payment_request_button_separator_html' ), 2 );
115
		}
116
117
		add_action( 'woocommerce_proceed_to_checkout', array( $this, 'display_payment_request_button_html' ), 1 );
118
		add_action( 'woocommerce_proceed_to_checkout', array( $this, 'display_payment_request_button_separator_html' ), 2 );
119
120
		if ( apply_filters( 'wc_stripe_show_payment_request_on_checkout', false ) ) {
121
			add_action( 'woocommerce_checkout_before_customer_details', array( $this, 'display_payment_request_button_html' ), 1 );
122
			add_action( 'woocommerce_checkout_before_customer_details', array( $this, 'display_payment_request_button_separator_html' ), 2 );
123
		}
124
125
		add_action( 'wc_ajax_wc_stripe_get_cart_details', array( $this, 'ajax_get_cart_details' ) );
126
		add_action( 'wc_ajax_wc_stripe_get_shipping_options', array( $this, 'ajax_get_shipping_options' ) );
127
		add_action( 'wc_ajax_wc_stripe_update_shipping_method', array( $this, 'ajax_update_shipping_method' ) );
128
		add_action( 'wc_ajax_wc_stripe_create_order', array( $this, 'ajax_create_order' ) );
129
		add_action( 'wc_ajax_wc_stripe_add_to_cart', array( $this, 'ajax_add_to_cart' ) );
130
		add_action( 'wc_ajax_wc_stripe_get_selected_product_data', array( $this, 'ajax_get_selected_product_data' ) );
131
		add_action( 'wc_ajax_wc_stripe_clear_cart', array( $this, 'ajax_clear_cart' ) );
132
		add_action( 'wc_ajax_wc_stripe_log_errors', array( $this, 'ajax_log_errors' ) );
133
134
		add_filter( 'woocommerce_gateway_title', array( $this, 'filter_gateway_title' ), 10, 2 );
135
136
		add_action( 'woocommerce_checkout_order_processed', array( $this, 'add_order_meta' ), 10, 3 );
137
	}
138
139
	/**
140
	 * Sets the WC customer session if one is not set.
141
	 * This is needed so nonces can be verified.
142
	 *
143
	 * @since 4.0.0
144
	 */
145
	public function set_session() {
146
		if ( ! is_user_logged_in() ) {
147
			$wc_session = new WC_Session_Handler();
148
149
			if ( ! $wc_session->has_session() ) {
150
				$wc_session->set_customer_session_cookie( true );
151
			}
152
		}
153
	}
154
155
	/**
156
	 * Gets the button type.
157
	 *
158
	 * @since 4.0.0
159
	 * @version 4.0.0
160
	 * @return string
161
	 */
162
	public function get_button_type() {
163
		return isset( $this->stripe_settings['payment_request_button_type'] ) ? $this->stripe_settings['payment_request_button_type'] : 'default';
164
	}
165
166
	/**
167
	 * Gets the button theme.
168
	 *
169
	 * @since 4.0.0
170
	 * @version 4.0.0
171
	 * @return string
172
	 */
173
	public function get_button_theme() {
174
		return isset( $this->stripe_settings['payment_request_button_theme'] ) ? $this->stripe_settings['payment_request_button_theme'] : 'dark';
175
	}
176
177
	/**
178
	 * Gets the button height.
179
	 *
180
	 * @since 4.0.0
181
	 * @version 4.0.0
182
	 * @return string
183
	 */
184
	public function get_button_height() {
185
		return isset( $this->stripe_settings['payment_request_button_height'] ) ? str_replace( 'px', '', $this->stripe_settings['payment_request_button_height'] ) : '64';
186
	}
187
188
	/**
189
	 * Gets the product data for the currently viewed page
190
	 *
191
	 * @since 4.0.0
192
	 * @version 4.0.0
193
	 */
194
	public function get_product_data() {
195
		if ( ! is_product() ) {
196
			return false;
197
		}
198
199
		global $post;
200
201
		$product = wc_get_product( $post->ID );
202
203
		$data  = array();
204
		$items = array();
205
206
		$items[] = array(
207
			'label'  => WC_Stripe_Helper::is_pre_30() ? $product->name : $product->get_name(),
208
			'amount' => WC_Stripe_Helper::get_stripe_amount( WC_Stripe_Helper::is_pre_30() ? $product->price : $product->get_price() ),
209
		);
210
211 View Code Duplication
		if ( wc_tax_enabled() ) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across 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...
212
			$items[] = array(
213
				'label'   => __( 'Tax', 'woocommerce-gateway-stripe' ),
214
				'amount'  => 0,
215
				'pending' => true,
216
			);
217
		}
218
219 View Code Duplication
		if ( wc_shipping_enabled() && $product->needs_shipping() ) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across 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...
220
			$items[] = array(
221
				'label'   => __( 'Shipping', 'woocommerce-gateway-stripe' ),
222
				'amount'  => 0,
223
				'pending' => true,
224
			);
225
226
			$data['shippingOptions']  = array(
227
				'id'     => 'pending',
228
				'label'  => __( 'Pending', 'woocommerce-gateway-stripe' ),
229
				'detail' => '',
230
				'amount' => 0,
231
			);
232
		}
233
234
		$data['displayItems'] = $items;
235
		$data['total'] = array(
236
			'label'   => $this->total_label,
237
			'amount'  => WC_Stripe_Helper::get_stripe_amount( WC_Stripe_Helper::is_pre_30() ? $product->price : $product->get_price() ),
238
			'pending' => true,
239
		);
240
241
		$data['requestShipping'] = ( wc_shipping_enabled() && $product->needs_shipping() );
242
		$data['currency']        = strtolower( get_woocommerce_currency() );
243
		$data['country_code']    = substr( get_option( 'woocommerce_default_country' ), 0, 2 );
244
245
		return $data;
246
	}
247
248
	/**
249
	 * Filters the gateway title to reflect Payment Request type
250
	 *
251
	 */
252
	public function filter_gateway_title( $title, $id ) {
253
		global $post;
254
255
		if ( ! is_object( $post ) ) {
256
			return $title;
257
		}
258
259
		if ( WC_Stripe_Helper::is_pre_30() ) {
260
			$method_title = get_post_meta( $post->ID, '_payment_method_title', true );
261
		} else {
262
			$order        = wc_get_order( $post->ID );
263
			$method_title = is_object( $order ) ? $order->get_payment_method_title() : '';
264
		}
265
266
		if ( 'stripe' === $id && ! empty( $method_title ) && 'Apple Pay (Stripe)' === $method_title ) {
267
			return $method_title;
268
		}
269
270
		if ( 'stripe' === $id && ! empty( $method_title ) && 'Chrome Payment Request (Stripe)' === $method_title ) {
271
			return $method_title;
272
		}
273
274
		return $title;
275
	}
276
277
	/**
278
	 * Add needed order meta
279
	 *
280
	 * @since 4.0.0
281
	 * @version 4.0.0
282
	 * @param int $order_id
283
	 * @param array $posted_data The posted data from checkout form.
284
	 * @param object $order
285
	 */
286
	public function add_order_meta( $order_id, $posted_data, $order ) {
287
		if ( empty( $_POST['payment_request_type'] ) ) {
288
			return;
289
		}
290
291
		$payment_request_type = wc_clean( $_POST['payment_request_type'] );
292
293 View Code Duplication
		if ( 'apple_pay' === $payment_request_type ) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across 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...
294
			if ( WC_Stripe_Helper::is_pre_30() ) {
295
				update_post_meta( $order_id, '_payment_method_title', 'Apple Pay (Stripe)' );
296
			} else {
297
				$order->set_payment_method_title( 'Apple Pay (Stripe)' );
298
				$order->save();
299
			}
300
		}
301
302 View Code Duplication
		if ( 'payment_request_api' === $payment_request_type ) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across 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...
303
			if ( WC_Stripe_Helper::is_pre_30() ) {
304
				update_post_meta( $order_id, '_payment_method_title', 'Chrome Payment Request (Stripe)' );
305
			} else {
306
				$order->set_payment_method_title( 'Chrome Payment Request (Stripe)' );
307
				$order->save();
308
			}
309
		}
310
	}
311
312
	/**
313
	 * Checks to make sure product type is supported.
314
	 *
315
	 * @since 3.1.0
316
	 * @version 4.0.0
317
	 * @return array
318
	 */
319
	public function supported_product_types() {
320
		return apply_filters( 'wc_stripe_payment_request_supported_types', array(
321
			'simple',
322
			'variable',
323
			'variation',
324
		) );
325
	}
326
327
	/**
328
	 * Checks the cart to see if all items are allowed to used.
329
	 *
330
	 * @since 3.1.4
331
	 * @version 4.0.0
332
	 * @return bool
333
	 */
334
	public function allowed_items_in_cart() {
335
		foreach ( WC()->cart->get_cart() as $cart_item_key => $cart_item ) {
336
			$_product = apply_filters( 'woocommerce_cart_item_product', $cart_item['data'], $cart_item, $cart_item_key );
337
338
			if ( ! in_array( ( WC_Stripe_Helper::is_pre_30() ? $_product->product_type : $_product->get_type() ), $this->supported_product_types() ) ) {
339
				return false;
340
			}
341
342
			// Pre Orders compatbility where we don't support charge upon release.
343
			if ( class_exists( 'WC_Pre_Orders_Order' ) && WC_Pre_Orders_Cart::cart_contains_pre_order() && WC_Pre_Orders_Product::product_is_charged_upon_release( WC_Pre_Orders_Cart::get_pre_order_product() ) ) {
344
				return false;
345
			}
346
		}
347
348
		return true;
349
	}
350
351
	/**
352
	 * Load public scripts and styles.
353
	 *
354
	 * @since 3.1.0
355
	 * @version 4.0.0
356
	 */
357
	public function scripts() {
358
		if ( ! is_product() && ! is_cart() && ! is_checkout() && ! isset( $_GET['pay_for_order'] ) ) {
359
			return;
360
		}
361
362
		if ( is_product() ) {
363
			global $post;
364
365
			$product = wc_get_product( $post->ID );
366
367
			if ( ! is_object( $product ) || ! in_array( ( WC_Stripe_Helper::is_pre_30() ? $product->product_type : $product->get_type() ), $this->supported_product_types() ) ) {
368
				return;
369
			}
370
371
			if ( apply_filters( 'wc_stripe_hide_payment_request_on_product_page', false ) ) {
372
				return;
373
			}
374
		}
375
376
		$suffix = defined( 'SCRIPT_DEBUG' ) && SCRIPT_DEBUG ? '' : '.min';
377
378
		wp_register_script( 'stripe', 'https://js.stripe.com/v3/', '', '3.0', true );
379
		wp_register_script( 'wc_stripe_payment_request', plugins_url( 'assets/js/stripe-payment-request' . $suffix . '.js', WC_STRIPE_MAIN_FILE ), array( 'jquery', 'stripe' ), WC_STRIPE_VERSION, true );
380
381
		wp_localize_script(
382
			'wc_stripe_payment_request',
383
			'wc_stripe_payment_request_params',
384
			array(
385
				'ajax_url' => WC_AJAX::get_endpoint( '%%endpoint%%' ),
386
				'stripe'   => array(
387
					'key'                => $this->publishable_key,
388
					'allow_prepaid_card' => apply_filters( 'wc_stripe_allow_prepaid_card', true ) ? 'yes' : 'no',
389
				),
390
				'nonce'    => array(
391
					'payment'                        => wp_create_nonce( 'wc-stripe-payment-request' ),
392
					'shipping'                       => wp_create_nonce( 'wc-stripe-payment-request-shipping' ),
393
					'update_shipping'                => wp_create_nonce( 'wc-stripe-update-shipping-method' ),
394
					'checkout'                       => wp_create_nonce( 'woocommerce-process_checkout' ),
395
					'add_to_cart'                    => wp_create_nonce( 'wc-stripe-add-to-cart' ),
396
					'get_selected_product_data'      => wp_create_nonce( 'wc-stripe-get-selected-product-data' ),
397
					'log_errors'                     => wp_create_nonce( 'wc-stripe-log-errors' ),
398
					'clear_cart'                     => wp_create_nonce( 'wc-stripe-clear-cart' ),
399
				),
400
				'i18n'     => array(
401
					'no_prepaid_card'  => __( 'Sorry, we\'re not accepting prepaid cards at this time.', 'woocommerce-gateway-stripe' ),
402
					/* translators: Do not translate the [option] placeholder */
403
					'unknown_shipping' => __( 'Unknown shipping option "[option]".', 'woocommerce-gateway-stripe' ),
404
				),
405
				'checkout' => array(
406
					'url'            => wc_get_checkout_url(),
407
					'currency_code'  => strtolower( get_woocommerce_currency() ),
408
					'country_code'   => substr( get_option( 'woocommerce_default_country' ), 0, 2 ),
409
					'needs_shipping' => WC()->cart->needs_shipping() ? 'yes' : 'no',
410
				),
411
				'button' => array(
412
					'type'   => $this->get_button_type(),
413
					'theme'  => $this->get_button_theme(),
414
					'height' => $this->get_button_height(),
415
					'locale' => substr( get_locale(), 0, 2 ), // Default format is en_US.
416
				),
417
				'is_product_page' => is_product(),
418
				'product'         => $this->get_product_data(),
419
			)
420
		);
421
422
		wp_enqueue_script( 'wc_stripe_payment_request' );
423
	}
424
425
	/**
426
	 * Display the payment request button.
427
	 *
428
	 * @since 4.0.0
429
	 * @version 4.0.0
430
	 */
431 View Code Duplication
	public function display_payment_request_button_html() {
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...
432
		$gateways = WC()->payment_gateways->get_available_payment_gateways();
433
434
		if ( ! isset( $gateways['stripe'] ) ) {
435
			return;
436
		}
437
438
		if ( ! is_cart() && ! is_checkout() && ! is_product() && ! isset( $_GET['pay_for_order'] ) ) {
439
			return;
440
		}
441
442
		if ( is_product() && apply_filters( 'wc_stripe_hide_payment_request_on_product_page', false ) ) {
443
			return;
444
		}
445
446
		if ( is_product() ) {
447
			global $post;
448
449
			$product = wc_get_product( $post->ID );
450
451
			if ( ! is_object( $product ) || ! in_array( ( WC_Stripe_Helper::is_pre_30() ? $product->product_type : $product->get_type() ), $this->supported_product_types() ) ) {
452
				return;
453
			}
454
455
			// Pre Orders charge upon release not supported.
456
			if ( class_exists( 'WC_Pre_Orders_Order' ) && WC_Pre_Orders_Product::product_is_charged_upon_release( $product ) ) {
457
				WC_Stripe_Logger::log( 'Pre Order charge upon release is not supported. ( Payment Request button disabled )' );
458
				return;
459
			}
460
		} else {
461
			if ( ! $this->allowed_items_in_cart() ) {
462
				WC_Stripe_Logger::log( 'Items in the cart has unsupported product type ( Payment Request button disabled )' );
463
				return;
464
			}
465
		}
466
		?>
467
		<div id="wc-stripe-payment-request-wrapper" style="clear:both;padding-top:1.5em;">
468
			<div id="wc-stripe-payment-request-button">
469
				<!-- A Stripe Element will be inserted here. -->
470
			</div>
471
		</div>
472
		<?php
473
	}
474
475
	/**
476
	 * Display payment request button separator.
477
	 *
478
	 * @since 4.0.0
479
	 * @version 4.0.0
480
	 */
481 View Code Duplication
	public function display_payment_request_button_separator_html() {
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...
482
		$gateways = WC()->payment_gateways->get_available_payment_gateways();
483
484
		if ( ! isset( $gateways['stripe'] ) ) {
485
			return;
486
		}
487
488
		if ( ! is_cart() && ! is_checkout() && ! is_product() && ! isset( $_GET['pay_for_order'] ) ) {
489
			return;
490
		}
491
492
		if ( is_product() && apply_filters( 'wc_stripe_hide_payment_request_on_product_page', false ) ) {
493
			return;
494
		}
495
496
		if ( is_product() ) {
497
			global $post;
498
499
			$product = wc_get_product( $post->ID );
500
501
			if ( ! is_object( $product ) || ! in_array( ( WC_Stripe_Helper::is_pre_30() ? $product->product_type : $product->get_type() ), $this->supported_product_types() ) ) {
502
				return;
503
			}
504
505
			// Pre Orders charge upon release not supported.
506
			if ( class_exists( 'WC_Pre_Orders_Order' ) && WC_Pre_Orders_Product::product_is_charged_upon_release( $product ) ) {
507
				WC_Stripe_Logger::log( 'Pre Order charge upon release is not supported. ( Payment Request button disabled )' );
508
				return;
509
			}
510
		} else {
511
			if ( ! $this->allowed_items_in_cart() ) {
512
				WC_Stripe_Logger::log( 'Items in the cart has unsupported product type ( Payment Request button disabled )' );
513
				return;
514
			}
515
		}
516
		?>
517
		<p id="wc-stripe-payment-request-button-separator" style="margin-top:1.5em;text-align:center;display:none;">- <?php esc_html_e( 'OR', 'woocommerce-gateway-stripe' ); ?> -</p>
518
		<?php
519
	}
520
521
	/**
522
	 * Log errors coming from Payment Request
523
	 *
524
	 * @since 3.1.4
525
	 * @version 4.0.0
526
	 */
527
	public function ajax_log_errors() {
528
		check_ajax_referer( 'wc-stripe-log-errors', 'security' );
529
530
		$errors = wc_clean( stripslashes( $_POST['errors'] ) );
531
532
		WC_Stripe_Logger::log( $errors );
533
534
		exit;
535
	}
536
537
	/**
538
	 * Clears cart.
539
	 *
540
	 * @since 3.1.4
541
	 * @version 4.0.0
542
	 */
543
	public function ajax_clear_cart() {
544
		check_ajax_referer( 'wc-stripe-clear-cart', 'security' );
545
546
		WC()->cart->empty_cart();
547
		exit;
548
	}
549
550
	/**
551
	 * Get cart details.
552
	 */
553
	public function ajax_get_cart_details() {
554
		check_ajax_referer( 'wc-stripe-payment-request', 'security' );
555
556
		if ( ! defined( 'WOOCOMMERCE_CART' ) ) {
557
			define( 'WOOCOMMERCE_CART', true );
558
		}
559
560
		WC()->cart->calculate_totals();
561
562
		$currency = get_woocommerce_currency();
563
564
		// Set mandatory payment details.
565
		$data = array(
566
			'shipping_required' => WC()->cart->needs_shipping(),
567
			'order_data'        => array(
568
				'currency'        => strtolower( $currency ),
569
				'country_code'    => substr( get_option( 'woocommerce_default_country' ), 0, 2 ),
570
			),
571
		);
572
573
		$data['order_data'] += $this->build_display_items();
574
575
		wp_send_json( $data );
576
	}
577
578
	/**
579
	 * Get shipping options.
580
	 *
581
	 * @see WC_Cart::get_shipping_packages().
582
	 * @see WC_Shipping::calculate_shipping().
583
	 * @see WC_Shipping::get_packages().
584
	 */
585
	public function ajax_get_shipping_options() {
586
		check_ajax_referer( 'wc-stripe-payment-request-shipping', 'security' );
587
588
		try {
589
			// Set the shipping package.
590
			$posted = filter_input_array( INPUT_POST, array(
591
				'country'   => FILTER_SANITIZE_STRING,
592
				'state'     => FILTER_SANITIZE_STRING,
593
				'postcode'  => FILTER_SANITIZE_STRING,
594
				'city'      => FILTER_SANITIZE_STRING,
595
				'address'   => FILTER_SANITIZE_STRING,
596
				'address_2' => FILTER_SANITIZE_STRING,
597
			) );
598
599
			$this->calculate_shipping( $posted );
600
601
			// Set the shipping options.
602
			$data     = array();
603
			$packages = WC()->shipping->get_packages();
604
605
			if ( ! empty( $packages ) && WC()->customer->has_calculated_shipping() ) {
606
				foreach ( $packages as $package_key => $package ) {
607
					if ( empty( $package['rates'] ) ) {
608
						throw new Exception( __( 'Unable to find shipping method for address.', 'woocommerce-gateway-stripe' ) );
609
					}
610
611
					foreach ( $package['rates'] as $key => $rate ) {
612
						$data['shipping_options'][] = array(
613
							'id'       => $rate->id,
614
							'label'    => $rate->label,
615
							'detail'   => '',
616
							'amount'   => WC_Stripe_Helper::get_stripe_amount( $rate->cost ),
617
						);
618
					}
619
				}
620
			} else {
621
				throw new Exception( __( 'Unable to find shipping method for address.', 'woocommerce-gateway-stripe' ) );
622
			}
623
624
			if ( isset( $data[0] ) ) {
625
				// Auto select the first shipping method.
626
				WC()->session->set( 'chosen_shipping_methods', array( $data[0]['id'] ) );
627
			}
628
629
			WC()->cart->calculate_totals();
630
631
			$data += $this->build_display_items();
632
			$data['result'] = 'success';
633
634
			wp_send_json( $data );
635
		} catch ( Exception $e ) {
636
			$data += $this->build_display_items();
0 ignored issues
show
Bug introduced by
The variable $data does not seem to be defined for all execution paths leading up to this point.

If you define a variable conditionally, it can happen that it is not defined for all execution paths.

Let’s take a look at an example:

function myFunction($a) {
    switch ($a) {
        case 'foo':
            $x = 1;
            break;

        case 'bar':
            $x = 2;
            break;
    }

    // $x is potentially undefined here.
    echo $x;
}

In the above example, the variable $x is defined if you pass “foo” or “bar” as argument for $a. However, since the switch statement has no default case statement, if you pass any other value, the variable $x would be undefined.

Available Fixes

  1. Check for existence of the variable explicitly:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        if (isset($x)) { // Make sure it's always set.
            echo $x;
        }
    }
    
  2. Define a default value for the variable:

    function myFunction($a) {
        $x = ''; // Set a default which gets overridden for certain paths.
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        echo $x;
    }
    
  3. Add a value for the missing path:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
    
            // We add support for the missing case.
            default:
                $x = '';
                break;
        }
    
        echo $x;
    }
    
Loading history...
637
			$data['result'] = 'invalid_shipping_address';
638
639
			wp_send_json( $data );
640
		}
641
	}
642
643
	/**
644
	 * Update shipping method.
645
	 */
646
	public function ajax_update_shipping_method() {
647
		check_ajax_referer( 'wc-stripe-update-shipping-method', 'security' );
648
649
		if ( ! defined( 'WOOCOMMERCE_CART' ) ) {
650
			define( 'WOOCOMMERCE_CART', true );
651
		}
652
653
		$chosen_shipping_methods = WC()->session->get( 'chosen_shipping_methods' );
654
		$shipping_method         = filter_input( INPUT_POST, 'shipping_method', FILTER_DEFAULT, FILTER_REQUIRE_ARRAY );
655
656
		if ( is_array( $shipping_method ) ) {
657
			foreach ( $shipping_method as $i => $value ) {
658
				$chosen_shipping_methods[ $i ] = wc_clean( $value );
659
			}
660
		}
661
662
		WC()->session->set( 'chosen_shipping_methods', $chosen_shipping_methods );
663
664
		WC()->cart->calculate_totals();
665
666
		$data = array();
667
		$data += $this->build_display_items();
668
		$data['result'] = 'success';
669
670
		wp_send_json( $data );
671
	}
672
673
	/**
674
	 * Gets the selected product data.
675
	 *
676
	 * @since 4.0.0
677
	 * @version 4.0.0
678
	 * @return array $data
679
	 */
680
	public function ajax_get_selected_product_data() {
681
		check_ajax_referer( 'wc-stripe-get-selected-product-data', 'security' );
682
683
		$product_id = absint( $_POST['product_id'] );
684
		$qty = ! isset( $_POST['qty'] ) ? 1 : absint( $_POST['qty'] );
685
686
		$product = wc_get_product( $product_id );
687
688
		if ( 'variable' === ( WC_Stripe_Helper::is_pre_30() ? $product->product_type : $product->get_type() ) && isset( $_POST['attributes'] ) ) {
689
			$attributes = array_map( 'wc_clean', $_POST['attributes'] );
690
691 View Code Duplication
			if ( WC_Stripe_Helper::is_pre_30() ) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across 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...
692
				$variation_id = $product->get_matching_variation( $attributes );
693
			} else {
694
				$data_store = WC_Data_Store::load( 'product' );
695
				$variation_id = $data_store->find_matching_product_variation( $product, $attributes );
696
			}
697
698
			if ( ! empty( $variation_id ) ) {
699
				$product = wc_get_product( $variation_id );
700
			}
701
		} elseif ( 'simple' === ( WC_Stripe_Helper::is_pre_30() ? $product->product_type : $product->get_type() ) ) {
702
			$product = wc_get_product( $product_id );
703
		}
704
705
		$total = $qty * ( WC_Stripe_Helper::is_pre_30() ? $product->price : $product->get_price() );
706
707
		$quantity_label = 1 < $qty ? ' (x' . $qty . ')' : '';
708
709
		$data  = array();
710
		$items = array();
711
712
		$items[] = array(
713
			'label'  => ( WC_Stripe_Helper::is_pre_30() ? $product->name : $product->get_name() ) . $quantity_label,
714
			'amount' => WC_Stripe_Helper::get_stripe_amount( $total ),
715
		);
716
717 View Code Duplication
		if ( wc_tax_enabled() ) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across 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...
718
			$items[] = array(
719
				'label'   => __( 'Tax', 'woocommerce-gateway-stripe' ),
720
				'amount'  => 0,
721
				'pending' => true,
722
			);
723
		}
724
725 View Code Duplication
		if ( wc_shipping_enabled() && $product->needs_shipping() ) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across 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...
726
			$items[] = array(
727
				'label'   => __( 'Shipping', 'woocommerce-gateway-stripe' ),
728
				'amount'  => 0,
729
				'pending' => true,
730
			);
731
732
			$data['shippingOptions']  = array(
733
				'id'     => 'pending',
734
				'label'  => __( 'Pending', 'woocommerce-gateway-stripe' ),
735
				'detail' => '',
736
				'amount' => 0,
737
			);
738
		}
739
740
		$data['displayItems'] = $items;
741
		$data['total'] = array(
742
			'label'   => $this->total_label,
743
			'amount'  => WC_Stripe_Helper::get_stripe_amount( $total ),
744
			'pending' => true,
745
		);
746
747
		$data['requestShipping'] = ( wc_shipping_enabled() && $product->needs_shipping() );
748
		$data['currency']        = strtolower( get_woocommerce_currency() );
749
		$data['country_code']    = substr( get_option( 'woocommerce_default_country' ), 0, 2 );
750
751
		wp_send_json( $data );
752
	}
753
754
	/**
755
	 * Adds the current product to the cart. Used on product detail page.
756
	 *
757
	 * @since 4.0.0
758
	 * @version 4.0.0
759
	 * @return array $data
760
	 */
761
	public function ajax_add_to_cart() {
762
		check_ajax_referer( 'wc-stripe-add-to-cart', 'security' );
763
764
		if ( ! defined( 'WOOCOMMERCE_CART' ) ) {
765
			define( 'WOOCOMMERCE_CART', true );
766
		}
767
768
		WC()->shipping->reset_shipping();
769
770
		$product_id = absint( $_POST['product_id'] );
771
		$qty = ! isset( $_POST['qty'] ) ? 1 : absint( $_POST['qty'] );
772
773
		$product = wc_get_product( $product_id );
774
775
		// First empty the cart to prevent wrong calculation.
776
		WC()->cart->empty_cart();
777
778
		if ( 'variable' === ( WC_Stripe_Helper::is_pre_30() ? $product->product_type : $product->get_type() ) && isset( $_POST['attributes'] ) ) {
779
			$attributes = array_map( 'wc_clean', $_POST['attributes'] );
780
781 View Code Duplication
			if ( WC_Stripe_Helper::is_pre_30() ) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across 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...
782
				$variation_id = $product->get_matching_variation( $attributes );
783
			} else {
784
				$data_store = WC_Data_Store::load( 'product' );
785
				$variation_id = $data_store->find_matching_product_variation( $product, $attributes );
786
			}
787
788
			WC()->cart->add_to_cart( $product->get_id(), $qty, $variation_id, $attributes );
789
		}
790
791
		if ( 'simple' === ( WC_Stripe_Helper::is_pre_30() ? $product->product_type : $product->get_type() ) ) {
792
			WC()->cart->add_to_cart( $product->get_id(), $qty );
793
		}
794
795
		WC()->cart->calculate_totals();
796
797
		$data = array();
798
		$data += $this->build_display_items();
799
		$data['result'] = 'success';
800
801
		wp_send_json( $data );
802
	}
803
804
	/**
805
	 * Normalizes the state/county field because in some
806
	 * cases, the state/county field is formatted differently from
807
	 * what WC is expecting and throws an error. An example
808
	 * for Ireland the county dropdown in Chrome shows "Co. Clare" format
809
	 *
810
	 * @since 4.0.0
811
	 * @version 4.0.0
812
	 */
813
	public function normalize_state() {
814
		$billing_country  = ! empty( $_POST['billing_country'] ) ? wc_clean( $_POST['billing_country'] ) : '';
815
		$shipping_country = ! empty( $_POST['shipping_country'] ) ? wc_clean( $_POST['shipping_country'] ) : '';
816
		$billing_state    = ! empty( $_POST['billing_state'] ) ? wc_clean( $_POST['billing_state'] ) : '';
817
		$shipping_state   = ! empty( $_POST['shipping_state'] ) ? wc_clean( $_POST['shipping_state'] ) : '';
818
819 View Code Duplication
		if ( $billing_state && $billing_country ) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across 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...
820
			$valid_states = WC()->countries->get_states( $billing_country );
821
822
			// Valid states found for country.
823
			if ( ! empty( $valid_states ) && is_array( $valid_states ) && sizeof( $valid_states ) > 0 ) {
824
				foreach ( $valid_states as $state_abbr => $state ) {
825
					if ( preg_match( '/' . preg_quote( $state ) . '/i', $billing_state ) ) {
826
						$_POST['billing_state'] = $state_abbr;
827
					}
828
				}
829
			}
830
		}
831
832 View Code Duplication
		if ( $shipping_state && $shipping_country ) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across 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...
833
			$valid_states = WC()->countries->get_states( $shipping_country );
834
835
			// Valid states found for country.
836
			if ( ! empty( $valid_states ) && is_array( $valid_states ) && sizeof( $valid_states ) > 0 ) {
837
				foreach ( $valid_states as $state_abbr => $state ) {
838
					if ( preg_match( '/' . preg_quote( $state ) . '/i', $shipping_state ) ) {
839
						$_POST['shipping_state'] = $state_abbr;
840
					}
841
				}
842
			}
843
		}
844
	}
845
846
	/**
847
	 * Create order. Security is handled by WC.
848
	 *
849
	 * @since 3.1.0
850
	 * @version 4.0.0
851
	 */
852
	public function ajax_create_order() {
853
		if ( WC()->cart->is_empty() ) {
854
			wp_send_json_error( __( 'Empty cart', 'woocommerce-gateway-stripe' ) );
855
		}
856
857
		if ( ! defined( 'WOOCOMMERCE_CHECKOUT' ) ) {
858
			define( 'WOOCOMMERCE_CHECKOUT', true );
859
		}
860
861
		$this->normalize_state();
862
863
		WC()->checkout()->process_checkout();
864
865
		die( 0 );
866
	}
867
868
	/**
869
	 * Calculate and set shipping method.
870
	 *
871
	 * @since 3.1.0
872
	 * @version 4.0.0
873
	 * @param array $address
874
	 */
875
	protected function calculate_shipping( $address = array() ) {
876
		global $states;
877
878
		$country   = $address['country'];
879
		$state     = $address['state'];
880
		$postcode  = $address['postcode'];
881
		$city      = $address['city'];
882
		$address_1 = $address['address'];
883
		$address_2 = $address['address_2'];
884
885
		$country_class = new WC_Countries();
886
		$country_class->load_country_states();
887
888
		/**
889
		 * In some versions of Chrome, state can be a full name. So we need
890
		 * to convert that to abbreviation as WC is expecting that.
891
		 */
892
		if ( 2 < strlen( $state ) ) {
893
			$state = array_search( ucfirst( strtolower( $state ) ), $states[ $country ] );
894
		}
895
896
		WC()->shipping->reset_shipping();
897
898
		if ( $postcode && WC_Validation::is_postcode( $postcode, $country ) ) {
899
			$postcode = wc_format_postcode( $postcode, $country );
900
		}
901
902
		if ( $country ) {
903
			WC()->customer->set_location( $country, $state, $postcode, $city );
904
			WC()->customer->set_shipping_location( $country, $state, $postcode, $city );
905
		} else {
906
			WC_Stripe_Helper::is_pre_30() ? WC()->customer->set_to_base() : WC()->customer->set_billing_address_to_base();
907
			WC_Stripe_Helper::is_pre_30() ? WC()->customer->set_shipping_to_base() : WC()->customer->set_shipping_address_to_base();
908
		}
909
910
		if ( WC_Stripe_Helper::is_pre_30() ) {
911
			WC()->customer->calculated_shipping( true );
912
		} else {
913
			WC()->customer->set_calculated_shipping( true );
914
			WC()->customer->save();
915
		}
916
917
		$packages = array();
918
919
		$packages[0]['contents']                 = WC()->cart->get_cart();
920
		$packages[0]['contents_cost']            = 0;
921
		$packages[0]['applied_coupons']          = WC()->cart->applied_coupons;
922
		$packages[0]['user']['ID']               = get_current_user_id();
923
		$packages[0]['destination']['country']   = $country;
924
		$packages[0]['destination']['state']     = $state;
925
		$packages[0]['destination']['postcode']  = $postcode;
926
		$packages[0]['destination']['city']      = $city;
927
		$packages[0]['destination']['address']   = $address_1;
928
		$packages[0]['destination']['address_2'] = $address_2;
929
930
		foreach ( WC()->cart->get_cart() as $item ) {
931
			if ( $item['data']->needs_shipping() ) {
932
				if ( isset( $item['line_total'] ) ) {
933
					$packages[0]['contents_cost'] += $item['line_total'];
934
				}
935
			}
936
		}
937
938
		$packages = apply_filters( 'woocommerce_cart_shipping_packages', $packages );
939
940
		WC()->shipping->calculate_shipping( $packages );
941
	}
942
943
	/**
944
	 * Builds the shippings methods to pass to Payment Request
945
	 *
946
	 * @since 3.1.0
947
	 * @version 4.0.0
948
	 */
949
	protected function build_shipping_methods( $shipping_methods ) {
950
		if ( empty( $shipping_methods ) ) {
951
			return array();
952
		}
953
954
		$shipping = array();
955
956
		foreach ( $shipping_methods as $method ) {
957
			$shipping[] = array(
958
				'id'         => $method['id'],
959
				'label'      => $method['label'],
960
				'detail'     => '',
961
				'amount'     => WC_Stripe_Helper::get_stripe_amount( $method['amount']['value'] ),
962
			);
963
		}
964
965
		return $shipping;
966
	}
967
968
	/**
969
	 * Builds the line items to pass to Payment Request
970
	 *
971
	 * @since 3.1.0
972
	 * @version 4.0.0
973
	 */
974
	protected function build_display_items() {
975
		if ( ! defined( 'WOOCOMMERCE_CART' ) ) {
976
			define( 'WOOCOMMERCE_CART', true );
977
		}
978
979
		$items    = array();
980
		$subtotal = 0;
981
982
		// Default show only subtotal instead of itemization.
983
		if ( ! apply_filters( 'wc_stripe_payment_request_hide_itemization', true ) ) {
984
			foreach ( WC()->cart->get_cart() as $cart_item_key => $cart_item ) {
985
				$amount         = $cart_item['line_subtotal'];
986
				$subtotal       += $cart_item['line_subtotal'];
987
				$quantity_label = 1 < $cart_item['quantity'] ? ' (x' . $cart_item['quantity'] . ')' : '';
988
989
				$product_name = WC_Stripe_Helper::is_pre_30() ? $cart_item['data']->post->post_title : $cart_item['data']->get_name();
990
991
				$item = array(
992
					'label'  => $product_name . $quantity_label,
993
					'amount' => WC_Stripe_Helper::get_stripe_amount( $amount ),
994
				);
995
996
				$items[] = $item;
997
			}
998
		}
999
1000
		$discounts   = wc_format_decimal( WC()->cart->get_cart_discount_total(), WC()->cart->dp );
1001
		$tax         = wc_format_decimal( WC()->cart->tax_total + WC()->cart->shipping_tax_total, WC()->cart->dp );
1002
		$shipping    = wc_format_decimal( WC()->cart->shipping_total, WC()->cart->dp );
1003
		$items_total = wc_format_decimal( WC()->cart->cart_contents_total, WC()->cart->dp ) + $discounts;
1004
		$order_total = wc_format_decimal( $items_total + $tax + $shipping - $discounts, WC()->cart->dp );
1005
1006
		if ( wc_tax_enabled() ) {
1007
			$items[] = array(
1008
				'label'  => esc_html( __( 'Tax', 'woocommerce-gateway-stripe' ) ),
1009
				'amount' => WC_Stripe_Helper::get_stripe_amount( $tax ),
1010
			);
1011
		}
1012
1013 View Code Duplication
		if ( WC()->cart->needs_shipping() ) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across 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...
1014
			$items[] = array(
1015
				'label'  => esc_html( __( 'Shipping', 'woocommerce-gateway-stripe' ) ),
1016
				'amount' => WC_Stripe_Helper::get_stripe_amount( $shipping ),
1017
			);
1018
		}
1019
1020 View Code Duplication
		if ( WC()->cart->has_discount() ) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across 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...
1021
			$items[] = array(
1022
				'label'  => esc_html( __( 'Discount', 'woocommerce-gateway-stripe' ) ),
1023
				'amount' => WC_Stripe_Helper::get_stripe_amount( $discounts ),
1024
			);
1025
		}
1026
1027
		if ( version_compare( WC_VERSION, '3.2', '<' ) ) {
1028
			$cart_fees = WC()->cart->fees;
1029
		} else {
1030
			$cart_fees = WC()->cart->get_fees();
1031
		}
1032
1033
		// Include fees and taxes as display items.
1034
		foreach ( $cart_fees as $key => $fee ) {
1035
			$items[] = array(
1036
				'label'  => $fee->name,
1037
				'amount' => WC_Stripe_Helper::get_stripe_amount( $fee->amount ),
1038
			);
1039
		}
1040
1041
		return array(
1042
			'displayItems' => $items,
1043
			'total'      => array(
1044
				'label'   => $this->total_label,
1045
				'amount'  => max( 0, apply_filters( 'woocommerce_stripe_calculated_total', WC_Stripe_Helper::get_stripe_amount( $order_total ), $order_total, WC()->cart ) ),
1046
				'pending' => false,
1047
			),
1048
		);
1049
	}
1050
}
1051
1052
new WC_Stripe_Payment_Request();
1053