Completed
Push — master ( e94018...c62a31 )
by Roy
02:10
created

WC_Stripe_Payment_Request::set_session()   A

Complexity

Conditions 4
Paths 5

Size

Total Lines 13
Code Lines 7

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 4
eloc 7
nc 5
nop 0
dl 0
loc 13
rs 9.2
c 0
b 0
f 0
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
		add_action( 'woocommerce_init', array( $this, 'set_session' ) );
92
		$this->init();
93
	}
94
95
	/**
96
	 * Sets the WC customer session if one is not set.
97
	 * This is needed so nonces can be verified by AJAX Request.
98
	 *
99
	 * @since 4.0.0
100
	 */
101
	public function set_session() {
102
		if ( ! is_user_logged_in() ) {
103
			$wc_session = new WC_Session_Handler();
104
105
			if ( version_compare( WC_VERSION, '3.3', '>=' ) ) {
106
				$wc_session->init();
107
			}
108
109
			if ( ! $wc_session->has_session() ) {
110
				$wc_session->set_customer_session_cookie( true );
111
			}
112
		}
113
	}
114
115
	/**
116
	 * Initialize hooks.
117
	 *
118
	 * @since 4.0.0
119
	 * @version 4.0.0
120
	 */
121
	public function init() {
122
		add_action( 'wp_enqueue_scripts', array( $this, 'scripts' ) );
123
124
		/*
125
		 * In order to display the Payment Request button in the correct position,
126
		 * a new hook was added to WooCommerce 3.0. In older versions of WooCommerce,
127
		 * CSS is used to position the button.
128
		 */
129
		if ( WC_Stripe_Helper::is_pre_30() ) {
130
			add_action( 'woocommerce_after_add_to_cart_button', array( $this, 'display_payment_request_button_html' ), 1 );
131
			add_action( 'woocommerce_after_add_to_cart_button', array( $this, 'display_payment_request_button_separator_html' ), 2 );
132
		} else {
133
			add_action( 'woocommerce_after_add_to_cart_quantity', array( $this, 'display_payment_request_button_html' ), 1 );
134
			add_action( 'woocommerce_after_add_to_cart_quantity', array( $this, 'display_payment_request_button_separator_html' ), 2 );
135
		}
136
137
		add_action( 'woocommerce_proceed_to_checkout', array( $this, 'display_payment_request_button_html' ), 1 );
138
		add_action( 'woocommerce_proceed_to_checkout', array( $this, 'display_payment_request_button_separator_html' ), 2 );
139
140
		add_action( 'woocommerce_checkout_before_customer_details', array( $this, 'display_payment_request_button_html' ), 1 );
141
		add_action( 'woocommerce_checkout_before_customer_details', array( $this, 'display_payment_request_button_separator_html' ), 2 );
142
143
		add_action( 'wc_ajax_wc_stripe_get_cart_details', array( $this, 'ajax_get_cart_details' ) );
144
		add_action( 'wc_ajax_wc_stripe_get_shipping_options', array( $this, 'ajax_get_shipping_options' ) );
145
		add_action( 'wc_ajax_wc_stripe_update_shipping_method', array( $this, 'ajax_update_shipping_method' ) );
146
		add_action( 'wc_ajax_wc_stripe_create_order', array( $this, 'ajax_create_order' ) );
147
		add_action( 'wc_ajax_wc_stripe_add_to_cart', array( $this, 'ajax_add_to_cart' ) );
148
		add_action( 'wc_ajax_wc_stripe_get_selected_product_data', array( $this, 'ajax_get_selected_product_data' ) );
149
		add_action( 'wc_ajax_wc_stripe_clear_cart', array( $this, 'ajax_clear_cart' ) );
150
		add_action( 'wc_ajax_wc_stripe_log_errors', array( $this, 'ajax_log_errors' ) );
151
152
		add_filter( 'woocommerce_gateway_title', array( $this, 'filter_gateway_title' ), 10, 2 );
153
		add_filter( 'woocommerce_validate_postcode', array( $this, 'postal_code_validation' ), 10, 3 );
154
155
		add_action( 'woocommerce_checkout_order_processed', array( $this, 'add_order_meta' ), 10, 2 );
156
	}
157
158
	/**
159
	 * Gets the button type.
160
	 *
161
	 * @since 4.0.0
162
	 * @version 4.0.0
163
	 * @return string
164
	 */
165
	public function get_button_type() {
166
		return isset( $this->stripe_settings['payment_request_button_type'] ) ? $this->stripe_settings['payment_request_button_type'] : 'default';
167
	}
168
169
	/**
170
	 * Gets the button theme.
171
	 *
172
	 * @since 4.0.0
173
	 * @version 4.0.0
174
	 * @return string
175
	 */
176
	public function get_button_theme() {
177
		return isset( $this->stripe_settings['payment_request_button_theme'] ) ? $this->stripe_settings['payment_request_button_theme'] : 'dark';
178
	}
179
180
	/**
181
	 * Gets the button height.
182
	 *
183
	 * @since 4.0.0
184
	 * @version 4.0.0
185
	 * @return string
186
	 */
187
	public function get_button_height() {
188
		return isset( $this->stripe_settings['payment_request_button_height'] ) ? str_replace( 'px', '', $this->stripe_settings['payment_request_button_height'] ) : '64';
189
	}
190
191
	/**
192
	 * Gets the product data for the currently viewed page
193
	 *
194
	 * @since 4.0.0
195
	 * @version 4.0.0
196
	 */
197
	public function get_product_data() {
198
		if ( ! is_product() ) {
199
			return false;
200
		}
201
202
		global $post;
203
204
		$product = wc_get_product( $post->ID );
205
206
		$data  = array();
207
		$items = array();
208
209
		$items[] = array(
210
			'label'  => WC_Stripe_Helper::is_pre_30() ? $product->name : $product->get_name(),
211
			'amount' => WC_Stripe_Helper::get_stripe_amount( WC_Stripe_Helper::is_pre_30() ? $product->price : $product->get_price() ),
212
		);
213
214 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...
215
			$items[] = array(
216
				'label'   => __( 'Tax', 'woocommerce-gateway-stripe' ),
217
				'amount'  => 0,
218
				'pending' => true,
219
			);
220
		}
221
222 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...
223
			$items[] = array(
224
				'label'   => __( 'Shipping', 'woocommerce-gateway-stripe' ),
225
				'amount'  => 0,
226
				'pending' => true,
227
			);
228
229
			$data['shippingOptions']  = array(
230
				'id'     => 'pending',
231
				'label'  => __( 'Pending', 'woocommerce-gateway-stripe' ),
232
				'detail' => '',
233
				'amount' => 0,
234
			);
235
		}
236
237
		$data['displayItems'] = $items;
238
		$data['total'] = array(
239
			'label'   => apply_filters( 'wc_stripe_payment_request_total_label', $this->total_label ),
240
			'amount'  => WC_Stripe_Helper::get_stripe_amount( WC_Stripe_Helper::is_pre_30() ? $product->price : $product->get_price() ),
241
			'pending' => true,
242
		);
243
244
		$data['requestShipping'] = ( wc_shipping_enabled() && $product->needs_shipping() );
245
		$data['currency']        = strtolower( get_woocommerce_currency() );
246
		$data['country_code']    = substr( get_option( 'woocommerce_default_country' ), 0, 2 );
247
248
		return apply_filters( 'wc_stripe_payment_request_product_data', $data, $product );
249
	}
250
251
	/**
252
	 * Filters the gateway title to reflect Payment Request type
253
	 *
254
	 */
255
	public function filter_gateway_title( $title, $id ) {
256
		global $post;
257
258
		if ( ! is_object( $post ) ) {
259
			return $title;
260
		}
261
262
		if ( WC_Stripe_Helper::is_pre_30() ) {
263
			$method_title = get_post_meta( $post->ID, '_payment_method_title', true );
264
		} else {
265
			$order        = wc_get_order( $post->ID );
266
			$method_title = is_object( $order ) ? $order->get_payment_method_title() : '';
267
		}
268
269
		if ( 'stripe' === $id && ! empty( $method_title ) && 'Apple Pay (Stripe)' === $method_title ) {
270
			return $method_title;
271
		}
272
273
		if ( 'stripe' === $id && ! empty( $method_title ) && 'Chrome Payment Request (Stripe)' === $method_title ) {
274
			return $method_title;
275
		}
276
277
		return $title;
278
	}
279
280
	/**
281
	 * Removes postal code validation from WC.
282
	 *
283
	 * @since 3.1.4
284
	 * @version 4.0.0
285
	 */
286
	public function postal_code_validation( $valid, $postcode, $country ) {
287
		$gateways = WC()->payment_gateways->get_available_payment_gateways();
288
289
		if ( ! isset( $gateways['stripe'] ) ) {
290
			return $valid;
291
		}
292
293
		$payment_request_type = wc_clean( $_POST['payment_request_type'] );
294
295
		if ( 'apple_pay' !== $payment_request_type ) {
296
			return $valid;
297
		}
298
299
		/**
300
		 * Currently Apple Pay truncates postal codes from UK and Canada to first 3 characters
301
		 * when passing it back from the shippingcontactselected object. This causes WC to invalidate
302
		 * the order and not let it go through. The remedy for now is just to remove this validation.
303
		 * Note that this only works with shipping providers that don't validate full postal codes.
304
		 */
305
		if ( 'GB' === $country || 'CA' === $country ) {
306
			return true;
307
		}
308
309
		return $valid;
310
	}
311
312
	/**
313
	 * Add needed order meta
314
	 *
315
	 * @since 4.0.0
316
	 * @version 4.0.0
317
	 * @param int $order_id
318
	 * @param array $posted_data The posted data from checkout form.
319
	 */
320
	public function add_order_meta( $order_id, $posted_data ) {
0 ignored issues
show
Unused Code introduced by
The parameter $posted_data is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
321
		if ( empty( $_POST['payment_request_type'] ) ) {
322
			return;
323
		}
324
325
		$order = wc_get_order( $order_id );
326
327
		$payment_request_type = wc_clean( $_POST['payment_request_type'] );
328
329 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...
330
			if ( WC_Stripe_Helper::is_pre_30() ) {
331
				update_post_meta( $order_id, '_payment_method_title', 'Apple Pay (Stripe)' );
332
			} else {
333
				$order->set_payment_method_title( 'Apple Pay (Stripe)' );
334
				$order->save();
335
			}
336
		}
337
338 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...
339
			if ( WC_Stripe_Helper::is_pre_30() ) {
340
				update_post_meta( $order_id, '_payment_method_title', 'Chrome Payment Request (Stripe)' );
341
			} else {
342
				$order->set_payment_method_title( 'Chrome Payment Request (Stripe)' );
343
				$order->save();
344
			}
345
		}
346
	}
347
348
	/**
349
	 * Checks to make sure product type is supported.
350
	 *
351
	 * @since 3.1.0
352
	 * @version 4.0.0
353
	 * @return array
354
	 */
355
	public function supported_product_types() {
356
		return apply_filters( 'wc_stripe_payment_request_supported_types', array(
357
			'simple',
358
			'variable',
359
			'variation',
360
		) );
361
	}
362
363
	/**
364
	 * Checks the cart to see if all items are allowed to used.
365
	 *
366
	 * @since 3.1.4
367
	 * @version 4.0.0
368
	 * @return bool
369
	 */
370
	public function allowed_items_in_cart() {
371
		foreach ( WC()->cart->get_cart() as $cart_item_key => $cart_item ) {
372
			$_product = apply_filters( 'woocommerce_cart_item_product', $cart_item['data'], $cart_item, $cart_item_key );
373
374
			if ( ! in_array( ( WC_Stripe_Helper::is_pre_30() ? $_product->product_type : $_product->get_type() ), $this->supported_product_types() ) ) {
375
				return false;
376
			}
377
378
			// Pre Orders compatbility where we don't support charge upon release.
379
			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() ) ) {
380
				return false;
381
			}
382
		}
383
384
		return true;
385
	}
386
387
	/**
388
	 * Load public scripts and styles.
389
	 *
390
	 * @since 3.1.0
391
	 * @version 4.0.0
392
	 */
393
	public function scripts() {
394
		if ( ! is_product() && ! is_cart() && ! is_checkout() && ! isset( $_GET['pay_for_order'] ) ) {
395
			return;
396
		}
397
398
		if ( is_product() ) {
399
			global $post;
400
401
			$product = wc_get_product( $post->ID );
402
403
			if ( ! is_object( $product ) || ! in_array( ( WC_Stripe_Helper::is_pre_30() ? $product->product_type : $product->get_type() ), $this->supported_product_types() ) ) {
404
				return;
405
			}
406
407
			if ( apply_filters( 'wc_stripe_hide_payment_request_on_product_page', false ) ) {
408
				return;
409
			}
410
		}
411
412
		$suffix = defined( 'SCRIPT_DEBUG' ) && SCRIPT_DEBUG ? '' : '.min';
413
414
		wp_register_script( 'stripe', 'https://js.stripe.com/v3/', '', '3.0', true );
415
		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 );
416
417
		wp_localize_script(
418
			'wc_stripe_payment_request',
419
			'wc_stripe_payment_request_params',
420
			array(
421
				'ajax_url' => WC_AJAX::get_endpoint( '%%endpoint%%' ),
422
				'stripe'   => array(
423
					'key'                => $this->publishable_key,
424
					'allow_prepaid_card' => apply_filters( 'wc_stripe_allow_prepaid_card', true ) ? 'yes' : 'no',
425
				),
426
				'nonce'    => array(
427
					'payment'                        => wp_create_nonce( 'wc-stripe-payment-request' ),
428
					'shipping'                       => wp_create_nonce( 'wc-stripe-payment-request-shipping' ),
429
					'update_shipping'                => wp_create_nonce( 'wc-stripe-update-shipping-method' ),
430
					'checkout'                       => wp_create_nonce( 'woocommerce-process_checkout' ),
431
					'add_to_cart'                    => wp_create_nonce( 'wc-stripe-add-to-cart' ),
432
					'get_selected_product_data'      => wp_create_nonce( 'wc-stripe-get-selected-product-data' ),
433
					'log_errors'                     => wp_create_nonce( 'wc-stripe-log-errors' ),
434
					'clear_cart'                     => wp_create_nonce( 'wc-stripe-clear-cart' ),
435
				),
436
				'i18n'     => array(
437
					'no_prepaid_card'  => __( 'Sorry, we\'re not accepting prepaid cards at this time.', 'woocommerce-gateway-stripe' ),
438
					/* translators: Do not translate the [option] placeholder */
439
					'unknown_shipping' => __( 'Unknown shipping option "[option]".', 'woocommerce-gateway-stripe' ),
440
				),
441
				'checkout' => array(
442
					'url'            => wc_get_checkout_url(),
443
					'currency_code'  => strtolower( get_woocommerce_currency() ),
444
					'country_code'   => substr( get_option( 'woocommerce_default_country' ), 0, 2 ),
445
					'needs_shipping' => WC()->cart->needs_shipping() ? 'yes' : 'no',
446
				),
447
				'button' => array(
448
					'type'   => $this->get_button_type(),
449
					'theme'  => $this->get_button_theme(),
450
					'height' => $this->get_button_height(),
451
					'locale' => substr( get_locale(), 0, 2 ), // Default format is en_US.
452
				),
453
				'is_product_page' => is_product(),
454
				'product'         => $this->get_product_data(),
455
			)
456
		);
457
458
		wp_enqueue_script( 'wc_stripe_payment_request' );
459
	}
460
461
	/**
462
	 * Display the payment request button.
463
	 *
464
	 * @since 4.0.0
465
	 * @version 4.0.0
466
	 */
467 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...
468
		$gateways = WC()->payment_gateways->get_available_payment_gateways();
469
470
		if ( ! isset( $gateways['stripe'] ) ) {
471
			return;
472
		}
473
474
		if ( ! is_cart() && ! is_checkout() && ! is_product() && ! isset( $_GET['pay_for_order'] ) ) {
475
			return;
476
		}
477
478
		if ( is_product() && apply_filters( 'wc_stripe_hide_payment_request_on_product_page', false ) ) {
479
			return;
480
		}
481
482
		if ( is_checkout() && ! apply_filters( 'wc_stripe_show_payment_request_on_checkout', false ) ) {
483
			return;
484
		}
485
486
		if ( is_product() ) {
487
			global $post;
488
489
			$product = wc_get_product( $post->ID );
490
491
			if ( ! is_object( $product ) || ! in_array( ( WC_Stripe_Helper::is_pre_30() ? $product->product_type : $product->get_type() ), $this->supported_product_types() ) ) {
492
				return;
493
			}
494
495
			// Pre Orders charge upon release not supported.
496
			if ( class_exists( 'WC_Pre_Orders_Order' ) && WC_Pre_Orders_Product::product_is_charged_upon_release( $product ) ) {
497
				WC_Stripe_Logger::log( 'Pre Order charge upon release is not supported. ( Payment Request button disabled )' );
498
				return;
499
			}
500
		} else {
501
			if ( ! $this->allowed_items_in_cart() ) {
502
				WC_Stripe_Logger::log( 'Items in the cart has unsupported product type ( Payment Request button disabled )' );
503
				return;
504
			}
505
		}
506
		?>
507
		<div id="wc-stripe-payment-request-wrapper" style="clear:both;padding-top:1.5em;">
508
			<div id="wc-stripe-payment-request-button">
509
				<!-- A Stripe Element will be inserted here. -->
510
			</div>
511
		</div>
512
		<?php
513
	}
514
515
	/**
516
	 * Display payment request button separator.
517
	 *
518
	 * @since 4.0.0
519
	 * @version 4.0.0
520
	 */
521 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...
522
		$gateways = WC()->payment_gateways->get_available_payment_gateways();
523
524
		if ( ! isset( $gateways['stripe'] ) ) {
525
			return;
526
		}
527
528
		if ( ! is_cart() && ! is_checkout() && ! is_product() && ! isset( $_GET['pay_for_order'] ) ) {
529
			return;
530
		}
531
532
		if ( is_product() && apply_filters( 'wc_stripe_hide_payment_request_on_product_page', false ) ) {
533
			return;
534
		}
535
536
		if ( is_checkout() && ! apply_filters( 'wc_stripe_show_payment_request_on_checkout', false ) ) {
537
			return;
538
		}
539
540
		if ( is_product() ) {
541
			global $post;
542
543
			$product = wc_get_product( $post->ID );
544
545
			if ( ! is_object( $product ) || ! in_array( ( WC_Stripe_Helper::is_pre_30() ? $product->product_type : $product->get_type() ), $this->supported_product_types() ) ) {
546
				return;
547
			}
548
549
			// Pre Orders charge upon release not supported.
550
			if ( class_exists( 'WC_Pre_Orders_Order' ) && WC_Pre_Orders_Product::product_is_charged_upon_release( $product ) ) {
551
				WC_Stripe_Logger::log( 'Pre Order charge upon release is not supported. ( Payment Request button disabled )' );
552
				return;
553
			}
554
		} else {
555
			if ( ! $this->allowed_items_in_cart() ) {
556
				WC_Stripe_Logger::log( 'Items in the cart has unsupported product type ( Payment Request button disabled )' );
557
				return;
558
			}
559
		}
560
		?>
561
		<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>
562
		<?php
563
	}
564
565
	/**
566
	 * Log errors coming from Payment Request
567
	 *
568
	 * @since 3.1.4
569
	 * @version 4.0.0
570
	 */
571
	public function ajax_log_errors() {
572
		check_ajax_referer( 'wc-stripe-log-errors', 'security' );
573
574
		$errors = wc_clean( stripslashes( $_POST['errors'] ) );
575
576
		WC_Stripe_Logger::log( $errors );
577
578
		exit;
579
	}
580
581
	/**
582
	 * Clears cart.
583
	 *
584
	 * @since 3.1.4
585
	 * @version 4.0.0
586
	 */
587
	public function ajax_clear_cart() {
588
		check_ajax_referer( 'wc-stripe-clear-cart', 'security' );
589
590
		WC()->cart->empty_cart();
591
		exit;
592
	}
593
594
	/**
595
	 * Get cart details.
596
	 */
597
	public function ajax_get_cart_details() {
598
		check_ajax_referer( 'wc-stripe-payment-request', 'security' );
599
600
		if ( ! defined( 'WOOCOMMERCE_CART' ) ) {
601
			define( 'WOOCOMMERCE_CART', true );
602
		}
603
604
		WC()->cart->calculate_totals();
605
606
		$currency = get_woocommerce_currency();
607
608
		// Set mandatory payment details.
609
		$data = array(
610
			'shipping_required' => WC()->cart->needs_shipping(),
611
			'order_data'        => array(
612
				'currency'        => strtolower( $currency ),
613
				'country_code'    => substr( get_option( 'woocommerce_default_country' ), 0, 2 ),
614
			),
615
		);
616
617
		$data['order_data'] += $this->build_display_items();
618
619
		wp_send_json( $data );
620
	}
621
622
	/**
623
	 * Get shipping options.
624
	 *
625
	 * @see WC_Cart::get_shipping_packages().
626
	 * @see WC_Shipping::calculate_shipping().
627
	 * @see WC_Shipping::get_packages().
628
	 */
629
	public function ajax_get_shipping_options() {
630
		check_ajax_referer( 'wc-stripe-payment-request-shipping', 'security' );
631
632
		try {
633
			// Set the shipping package.
634
			$posted = filter_input_array( INPUT_POST, array(
635
				'country'   => FILTER_SANITIZE_STRING,
636
				'state'     => FILTER_SANITIZE_STRING,
637
				'postcode'  => FILTER_SANITIZE_STRING,
638
				'city'      => FILTER_SANITIZE_STRING,
639
				'address'   => FILTER_SANITIZE_STRING,
640
				'address_2' => FILTER_SANITIZE_STRING,
641
			) );
642
643
			$this->calculate_shipping( $posted );
644
645
			// Set the shipping options.
646
			$data     = array();
647
			$packages = WC()->shipping->get_packages();
648
649
			if ( ! empty( $packages ) && WC()->customer->has_calculated_shipping() ) {
650
				foreach ( $packages as $package_key => $package ) {
651
					if ( empty( $package['rates'] ) ) {
652
						throw new Exception( __( 'Unable to find shipping method for address.', 'woocommerce-gateway-stripe' ) );
653
					}
654
655
					foreach ( $package['rates'] as $key => $rate ) {
656
						$data['shipping_options'][] = array(
657
							'id'       => $rate->id,
658
							'label'    => $rate->label,
659
							'detail'   => '',
660
							'amount'   => WC_Stripe_Helper::get_stripe_amount( $rate->cost ),
661
						);
662
					}
663
				}
664
			} else {
665
				throw new Exception( __( 'Unable to find shipping method for address.', 'woocommerce-gateway-stripe' ) );
666
			}
667
668
			if ( isset( $data[0] ) ) {
669
				// Auto select the first shipping method.
670
				WC()->session->set( 'chosen_shipping_methods', array( $data[0]['id'] ) );
671
			}
672
673
			WC()->cart->calculate_totals();
674
675
			$data += $this->build_display_items();
676
			$data['result'] = 'success';
677
678
			wp_send_json( $data );
679
		} catch ( Exception $e ) {
680
			$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...
681
			$data['result'] = 'invalid_shipping_address';
682
683
			wp_send_json( $data );
684
		}
685
	}
686
687
	/**
688
	 * Update shipping method.
689
	 */
690
	public function ajax_update_shipping_method() {
691
		check_ajax_referer( 'wc-stripe-update-shipping-method', 'security' );
692
693
		if ( ! defined( 'WOOCOMMERCE_CART' ) ) {
694
			define( 'WOOCOMMERCE_CART', true );
695
		}
696
697
		$chosen_shipping_methods = WC()->session->get( 'chosen_shipping_methods' );
698
		$shipping_method         = filter_input( INPUT_POST, 'shipping_method', FILTER_DEFAULT, FILTER_REQUIRE_ARRAY );
699
700
		if ( is_array( $shipping_method ) ) {
701
			foreach ( $shipping_method as $i => $value ) {
702
				$chosen_shipping_methods[ $i ] = wc_clean( $value );
703
			}
704
		}
705
706
		WC()->session->set( 'chosen_shipping_methods', $chosen_shipping_methods );
707
708
		WC()->cart->calculate_totals();
709
710
		$data = array();
711
		$data += $this->build_display_items();
712
		$data['result'] = 'success';
713
714
		wp_send_json( $data );
715
	}
716
717
	/**
718
	 * Gets the selected product data.
719
	 *
720
	 * @since 4.0.0
721
	 * @version 4.0.0
722
	 * @return array $data
723
	 */
724
	public function ajax_get_selected_product_data() {
725
		check_ajax_referer( 'wc-stripe-get-selected-product-data', 'security' );
726
727
		$product_id = absint( $_POST['product_id'] );
728
		$qty = ! isset( $_POST['qty'] ) ? 1 : absint( $_POST['qty'] );
729
730
		$product = wc_get_product( $product_id );
731
732
		if ( 'variable' === ( WC_Stripe_Helper::is_pre_30() ? $product->product_type : $product->get_type() ) && isset( $_POST['attributes'] ) ) {
733
			$attributes = array_map( 'wc_clean', $_POST['attributes'] );
734
735 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...
736
				$variation_id = $product->get_matching_variation( $attributes );
737
			} else {
738
				$data_store = WC_Data_Store::load( 'product' );
739
				$variation_id = $data_store->find_matching_product_variation( $product, $attributes );
740
			}
741
742
			if ( ! empty( $variation_id ) ) {
743
				$product = wc_get_product( $variation_id );
744
			}
745
		} elseif ( 'simple' === ( WC_Stripe_Helper::is_pre_30() ? $product->product_type : $product->get_type() ) ) {
746
			$product = wc_get_product( $product_id );
747
		}
748
749
		$total = $qty * ( WC_Stripe_Helper::is_pre_30() ? $product->price : $product->get_price() );
750
751
		$quantity_label = 1 < $qty ? ' (x' . $qty . ')' : '';
752
753
		$data  = array();
754
		$items = array();
755
756
		$items[] = array(
757
			'label'  => ( WC_Stripe_Helper::is_pre_30() ? $product->name : $product->get_name() ) . $quantity_label,
758
			'amount' => WC_Stripe_Helper::get_stripe_amount( $total ),
759
		);
760
761 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...
762
			$items[] = array(
763
				'label'   => __( 'Tax', 'woocommerce-gateway-stripe' ),
764
				'amount'  => 0,
765
				'pending' => true,
766
			);
767
		}
768
769 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...
770
			$items[] = array(
771
				'label'   => __( 'Shipping', 'woocommerce-gateway-stripe' ),
772
				'amount'  => 0,
773
				'pending' => true,
774
			);
775
776
			$data['shippingOptions']  = array(
777
				'id'     => 'pending',
778
				'label'  => __( 'Pending', 'woocommerce-gateway-stripe' ),
779
				'detail' => '',
780
				'amount' => 0,
781
			);
782
		}
783
784
		$data['displayItems'] = $items;
785
		$data['total'] = array(
786
			'label'   => $this->total_label,
787
			'amount'  => WC_Stripe_Helper::get_stripe_amount( $total ),
788
			'pending' => true,
789
		);
790
791
		$data['requestShipping'] = ( wc_shipping_enabled() && $product->needs_shipping() );
792
		$data['currency']        = strtolower( get_woocommerce_currency() );
793
		$data['country_code']    = substr( get_option( 'woocommerce_default_country' ), 0, 2 );
794
795
		wp_send_json( $data );
796
	}
797
798
	/**
799
	 * Adds the current product to the cart. Used on product detail page.
800
	 *
801
	 * @since 4.0.0
802
	 * @version 4.0.0
803
	 * @return array $data
804
	 */
805
	public function ajax_add_to_cart() {
806
		check_ajax_referer( 'wc-stripe-add-to-cart', 'security' );
807
808
		if ( ! defined( 'WOOCOMMERCE_CART' ) ) {
809
			define( 'WOOCOMMERCE_CART', true );
810
		}
811
812
		WC()->shipping->reset_shipping();
813
814
		$product_id = absint( $_POST['product_id'] );
815
		$qty = ! isset( $_POST['qty'] ) ? 1 : absint( $_POST['qty'] );
816
817
		$product = wc_get_product( $product_id );
818
819
		// First empty the cart to prevent wrong calculation.
820
		WC()->cart->empty_cart();
821
822
		if ( 'variable' === ( WC_Stripe_Helper::is_pre_30() ? $product->product_type : $product->get_type() ) && isset( $_POST['attributes'] ) ) {
823
			$attributes = array_map( 'wc_clean', $_POST['attributes'] );
824
825 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...
826
				$variation_id = $product->get_matching_variation( $attributes );
827
			} else {
828
				$data_store = WC_Data_Store::load( 'product' );
829
				$variation_id = $data_store->find_matching_product_variation( $product, $attributes );
830
			}
831
832
			WC()->cart->add_to_cart( $product->get_id(), $qty, $variation_id, $attributes );
833
		}
834
835
		if ( 'simple' === ( WC_Stripe_Helper::is_pre_30() ? $product->product_type : $product->get_type() ) ) {
836
			WC()->cart->add_to_cart( $product->get_id(), $qty );
837
		}
838
839
		WC()->cart->calculate_totals();
840
841
		$data = array();
842
		$data += $this->build_display_items();
843
		$data['result'] = 'success';
844
845
		wp_send_json( $data );
846
	}
847
848
	/**
849
	 * Normalizes the state/county field because in some
850
	 * cases, the state/county field is formatted differently from
851
	 * what WC is expecting and throws an error. An example
852
	 * for Ireland the county dropdown in Chrome shows "Co. Clare" format
853
	 *
854
	 * @since 4.0.0
855
	 * @version 4.0.0
856
	 */
857
	public function normalize_state() {
858
		$billing_country  = ! empty( $_POST['billing_country'] ) ? wc_clean( $_POST['billing_country'] ) : '';
859
		$shipping_country = ! empty( $_POST['shipping_country'] ) ? wc_clean( $_POST['shipping_country'] ) : '';
860
		$billing_state    = ! empty( $_POST['billing_state'] ) ? wc_clean( $_POST['billing_state'] ) : '';
861
		$shipping_state   = ! empty( $_POST['shipping_state'] ) ? wc_clean( $_POST['shipping_state'] ) : '';
862
863 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...
864
			$valid_states = WC()->countries->get_states( $billing_country );
865
866
			// Valid states found for country.
867
			if ( ! empty( $valid_states ) && is_array( $valid_states ) && sizeof( $valid_states ) > 0 ) {
868
				foreach ( $valid_states as $state_abbr => $state ) {
869
					if ( preg_match( '/' . preg_quote( $state ) . '/i', $billing_state ) ) {
870
						$_POST['billing_state'] = $state_abbr;
871
					}
872
				}
873
			}
874
		}
875
876 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...
877
			$valid_states = WC()->countries->get_states( $shipping_country );
878
879
			// Valid states found for country.
880
			if ( ! empty( $valid_states ) && is_array( $valid_states ) && sizeof( $valid_states ) > 0 ) {
881
				foreach ( $valid_states as $state_abbr => $state ) {
882
					if ( preg_match( '/' . preg_quote( $state ) . '/i', $shipping_state ) ) {
883
						$_POST['shipping_state'] = $state_abbr;
884
					}
885
				}
886
			}
887
		}
888
	}
889
890
	/**
891
	 * Create order. Security is handled by WC.
892
	 *
893
	 * @since 3.1.0
894
	 * @version 4.0.0
895
	 */
896
	public function ajax_create_order() {
897
		if ( WC()->cart->is_empty() ) {
898
			wp_send_json_error( __( 'Empty cart', 'woocommerce-gateway-stripe' ) );
899
		}
900
901
		if ( ! defined( 'WOOCOMMERCE_CHECKOUT' ) ) {
902
			define( 'WOOCOMMERCE_CHECKOUT', true );
903
		}
904
905
		$this->normalize_state();
906
907
		WC()->checkout()->process_checkout();
908
909
		die( 0 );
910
	}
911
912
	/**
913
	 * Calculate and set shipping method.
914
	 *
915
	 * @since 3.1.0
916
	 * @version 4.0.0
917
	 * @param array $address
918
	 */
919
	protected function calculate_shipping( $address = array() ) {
920
		global $states;
921
922
		$country   = $address['country'];
923
		$state     = $address['state'];
924
		$postcode  = $address['postcode'];
925
		$city      = $address['city'];
926
		$address_1 = $address['address'];
927
		$address_2 = $address['address_2'];
928
929
		$country_class = new WC_Countries();
930
		$country_class->load_country_states();
931
932
		/**
933
		 * In some versions of Chrome, state can be a full name. So we need
934
		 * to convert that to abbreviation as WC is expecting that.
935
		 */
936
		if ( 2 < strlen( $state ) ) {
937
			$state = array_search( ucfirst( strtolower( $state ) ), $states[ $country ] );
938
		}
939
940
		WC()->shipping->reset_shipping();
941
942
		if ( $postcode && WC_Validation::is_postcode( $postcode, $country ) ) {
943
			$postcode = wc_format_postcode( $postcode, $country );
944
		}
945
946
		if ( $country ) {
947
			WC()->customer->set_location( $country, $state, $postcode, $city );
948
			WC()->customer->set_shipping_location( $country, $state, $postcode, $city );
949
		} else {
950
			WC_Stripe_Helper::is_pre_30() ? WC()->customer->set_to_base() : WC()->customer->set_billing_address_to_base();
951
			WC_Stripe_Helper::is_pre_30() ? WC()->customer->set_shipping_to_base() : WC()->customer->set_shipping_address_to_base();
952
		}
953
954
		if ( WC_Stripe_Helper::is_pre_30() ) {
955
			WC()->customer->calculated_shipping( true );
956
		} else {
957
			WC()->customer->set_calculated_shipping( true );
958
			WC()->customer->save();
959
		}
960
961
		$packages = array();
962
963
		$packages[0]['contents']                 = WC()->cart->get_cart();
964
		$packages[0]['contents_cost']            = 0;
965
		$packages[0]['applied_coupons']          = WC()->cart->applied_coupons;
966
		$packages[0]['user']['ID']               = get_current_user_id();
967
		$packages[0]['destination']['country']   = $country;
968
		$packages[0]['destination']['state']     = $state;
969
		$packages[0]['destination']['postcode']  = $postcode;
970
		$packages[0]['destination']['city']      = $city;
971
		$packages[0]['destination']['address']   = $address_1;
972
		$packages[0]['destination']['address_2'] = $address_2;
973
974
		foreach ( WC()->cart->get_cart() as $item ) {
975
			if ( $item['data']->needs_shipping() ) {
976
				if ( isset( $item['line_total'] ) ) {
977
					$packages[0]['contents_cost'] += $item['line_total'];
978
				}
979
			}
980
		}
981
982
		$packages = apply_filters( 'woocommerce_cart_shipping_packages', $packages );
983
984
		WC()->shipping->calculate_shipping( $packages );
985
	}
986
987
	/**
988
	 * Builds the shippings methods to pass to Payment Request
989
	 *
990
	 * @since 3.1.0
991
	 * @version 4.0.0
992
	 */
993
	protected function build_shipping_methods( $shipping_methods ) {
994
		if ( empty( $shipping_methods ) ) {
995
			return array();
996
		}
997
998
		$shipping = array();
999
1000
		foreach ( $shipping_methods as $method ) {
1001
			$shipping[] = array(
1002
				'id'         => $method['id'],
1003
				'label'      => $method['label'],
1004
				'detail'     => '',
1005
				'amount'     => WC_Stripe_Helper::get_stripe_amount( $method['amount']['value'] ),
1006
			);
1007
		}
1008
1009
		return $shipping;
1010
	}
1011
1012
	/**
1013
	 * Builds the line items to pass to Payment Request
1014
	 *
1015
	 * @since 3.1.0
1016
	 * @version 4.0.0
1017
	 */
1018
	protected function build_display_items() {
1019
		if ( ! defined( 'WOOCOMMERCE_CART' ) ) {
1020
			define( 'WOOCOMMERCE_CART', true );
1021
		}
1022
1023
		$items    = array();
1024
		$subtotal = 0;
1025
1026
		// Default show only subtotal instead of itemization.
1027
		if ( ! apply_filters( 'wc_stripe_payment_request_hide_itemization', true ) ) {
1028
			foreach ( WC()->cart->get_cart() as $cart_item_key => $cart_item ) {
1029
				$amount         = $cart_item['line_subtotal'];
1030
				$subtotal       += $cart_item['line_subtotal'];
1031
				$quantity_label = 1 < $cart_item['quantity'] ? ' (x' . $cart_item['quantity'] . ')' : '';
1032
1033
				$product_name = WC_Stripe_Helper::is_pre_30() ? $cart_item['data']->post->post_title : $cart_item['data']->get_name();
1034
1035
				$item = array(
1036
					'label'  => $product_name . $quantity_label,
1037
					'amount' => WC_Stripe_Helper::get_stripe_amount( $amount ),
1038
				);
1039
1040
				$items[] = $item;
1041
			}
1042
		}
1043
1044
		$discounts   = wc_format_decimal( WC()->cart->get_cart_discount_total(), WC()->cart->dp );
1045
		$tax         = wc_format_decimal( WC()->cart->tax_total + WC()->cart->shipping_tax_total, WC()->cart->dp );
1046
		$shipping    = wc_format_decimal( WC()->cart->shipping_total, WC()->cart->dp );
1047
		$items_total = wc_format_decimal( WC()->cart->cart_contents_total, WC()->cart->dp ) + $discounts;
1048
		$order_total = wc_format_decimal( $items_total + $tax + $shipping - $discounts, WC()->cart->dp );
1049
1050
		if ( wc_tax_enabled() ) {
1051
			$items[] = array(
1052
				'label'  => esc_html( __( 'Tax', 'woocommerce-gateway-stripe' ) ),
1053
				'amount' => WC_Stripe_Helper::get_stripe_amount( $tax ),
1054
			);
1055
		}
1056
1057 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...
1058
			$items[] = array(
1059
				'label'  => esc_html( __( 'Shipping', 'woocommerce-gateway-stripe' ) ),
1060
				'amount' => WC_Stripe_Helper::get_stripe_amount( $shipping ),
1061
			);
1062
		}
1063
1064 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...
1065
			$items[] = array(
1066
				'label'  => esc_html( __( 'Discount', 'woocommerce-gateway-stripe' ) ),
1067
				'amount' => WC_Stripe_Helper::get_stripe_amount( $discounts ),
1068
			);
1069
		}
1070
1071
		if ( version_compare( WC_VERSION, '3.2', '<' ) ) {
1072
			$cart_fees = WC()->cart->fees;
1073
		} else {
1074
			$cart_fees = WC()->cart->get_fees();
1075
		}
1076
1077
		// Include fees and taxes as display items.
1078
		foreach ( $cart_fees as $key => $fee ) {
1079
			$items[] = array(
1080
				'label'  => $fee->name,
1081
				'amount' => WC_Stripe_Helper::get_stripe_amount( $fee->amount ),
1082
			);
1083
		}
1084
1085
		return array(
1086
			'displayItems' => $items,
1087
			'total'      => array(
1088
				'label'   => $this->total_label,
1089
				'amount'  => max( 0, apply_filters( 'woocommerce_stripe_calculated_total', WC_Stripe_Helper::get_stripe_amount( $order_total ), $order_total, WC()->cart ) ),
1090
				'pending' => false,
1091
			),
1092
		);
1093
	}
1094
}
1095
1096
new WC_Stripe_Payment_Request();
1097