Completed
Push — master ( c1ff6b...717fdd )
by Roy
02:07
created

WC_Stripe_Payment_Request::set_session()   B

Complexity

Conditions 5
Paths 6

Size

Total Lines 17
Code Lines 9

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 5
eloc 9
nc 6
nop 0
dl 0
loc 17
rs 8.8571
c 0
b 0
f 0
1
<?php
2
/**
3
 * Stripe Payment Request API
4
 *
5
 * @package WooCommerce_Stripe/Classes/Payment_Request
6
 * @since   4.0.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
	 * Key
47
	 *
48
	 * @var
49
	 */
50
	public $secret_key;
51
52
	/**
53
	 * Is test mode active?
54
	 *
55
	 * @var bool
56
	 */
57
	public $testmode;
58
59
	/**
60
	 * This Instance.
61
	 *
62
	 * @var
63
	 */
64
	private static $_this;
65
66
	/**
67
	 * Initialize class actions.
68
	 *
69
	 * @since 3.0.0
70
	 * @version 4.0.0
71
	 */
72
	public function __construct() {
73
		self::$_this                   = $this;
74
		$this->stripe_settings         = get_option( 'woocommerce_stripe_settings', array() );
75
		$this->testmode                = ( ! empty( $this->stripe_settings['testmode'] ) && 'yes' === $this->stripe_settings['testmode'] ) ? true : false;
76
		$this->publishable_key         = ! empty( $this->stripe_settings['publishable_key'] ) ? $this->stripe_settings['publishable_key'] : '';
77
		$this->secret_key              = ! empty( $this->stripe_settings['secret_key'] ) ? $this->stripe_settings['secret_key'] : '';
78
		$this->stripe_checkout_enabled = isset( $this->stripe_settings['stripe_checkout'] ) && 'yes' === $this->stripe_settings['stripe_checkout'];
79
		$this->total_label             = ! empty( $this->stripe_settings['statement_descriptor'] ) ? WC_Stripe_Helper::clean_statement_descriptor( $this->stripe_settings['statement_descriptor'] ) : '';
80
81
		if ( $this->testmode ) {
82
			$this->publishable_key = ! empty( $this->stripe_settings['test_publishable_key'] ) ? $this->stripe_settings['test_publishable_key'] : '';
83
			$this->secret_key      = ! empty( $this->stripe_settings['test_secret_key'] ) ? $this->stripe_settings['test_secret_key'] : '';
84
		}
85
86
		$this->total_label = str_replace( "'", '', $this->total_label ) . apply_filters( 'wc_stripe_payment_request_total_label_suffix', ' (via WooCommerce)' );
87
88
		// Checks if Stripe Gateway is enabled.
89
		if ( empty( $this->stripe_settings ) || ( isset( $this->stripe_settings['enabled'] ) && 'yes' !== $this->stripe_settings['enabled'] ) ) {
90
			return;
91
		}
92
93
		// Checks if Payment Request is enabled.
94
		if ( ! isset( $this->stripe_settings['payment_request'] ) || 'yes' !== $this->stripe_settings['payment_request'] ) {
95
			return;
96
		}
97
98
		// Don't load for change payment method page.
99
		if ( isset( $_GET['change_payment_method'] ) ) {
100
			return;
101
		}
102
103
		add_action( 'template_redirect', array( $this, 'set_session' ) );
104
		$this->init();
105
	}
106
107
	/**
108
	 * Checks if keys are set.
109
	 *
110
	 * @since 4.0.6
111
	 * @return bool
112
	 */
113
	public function are_keys_set() {
114
		if ( empty( $this->secret_key ) || empty( $this->publishable_key ) ) {
115
			return false;
116
		}
117
118
		return true;
119
	}
120
121
	/**
122
	 * Get this instance.
123
	 *
124
	 * @since 4.0.6
125
	 * @return class
126
	 */
127
	public static function instance() {
128
		return self::$_this;
129
	}
130
131
	/**
132
	 * Sets the WC customer session if one is not set.
133
	 * This is needed so nonces can be verified by AJAX Request.
134
	 *
135
	 * @since 4.0.0
136
	 */
137
	public function set_session() {
138
		if ( ! is_product() ) {
139
			return;
140
		}
141
142
		if ( ! is_user_logged_in() ) {
143
			$wc_session = new WC_Session_Handler();
144
145
			if ( version_compare( WC_VERSION, '3.3', '>=' ) ) {
146
				$wc_session->init();
147
			}
148
149
			if ( ! $wc_session->has_session() ) {
150
				$wc_session->set_customer_session_cookie( true );
151
			}
152
		}
153
	}
154
155
	/**
156
	 * Initialize hooks.
157
	 *
158
	 * @since 4.0.0
159
	 * @version 4.0.0
160
	 */
161
	public function init() {
162
		add_action( 'wp_enqueue_scripts', array( $this, 'scripts' ) );
163
164
		/*
165
		 * In order to display the Payment Request button in the correct position,
166
		 * a new hook was added to WooCommerce 3.0. In older versions of WooCommerce,
167
		 * CSS is used to position the button.
168
		 */
169
		if ( WC_Stripe_Helper::is_pre_30() ) {
170
			add_action( 'woocommerce_after_add_to_cart_button', array( $this, 'display_payment_request_button_html' ), 1 );
171
			add_action( 'woocommerce_after_add_to_cart_button', array( $this, 'display_payment_request_button_separator_html' ), 2 );
172
		} else {
173
			add_action( 'woocommerce_after_add_to_cart_quantity', array( $this, 'display_payment_request_button_html' ), 1 );
174
			add_action( 'woocommerce_after_add_to_cart_quantity', array( $this, 'display_payment_request_button_separator_html' ), 2 );
175
		}
176
177
		add_action( 'woocommerce_proceed_to_checkout', array( $this, 'display_payment_request_button_html' ), 1 );
178
		add_action( 'woocommerce_proceed_to_checkout', array( $this, 'display_payment_request_button_separator_html' ), 2 );
179
180
		add_action( 'woocommerce_checkout_before_customer_details', array( $this, 'display_payment_request_button_html' ), 1 );
181
		add_action( 'woocommerce_checkout_before_customer_details', array( $this, 'display_payment_request_button_separator_html' ), 2 );
182
183
		add_action( 'wc_ajax_wc_stripe_get_cart_details', array( $this, 'ajax_get_cart_details' ) );
184
		add_action( 'wc_ajax_wc_stripe_get_shipping_options', array( $this, 'ajax_get_shipping_options' ) );
185
		add_action( 'wc_ajax_wc_stripe_update_shipping_method', array( $this, 'ajax_update_shipping_method' ) );
186
		add_action( 'wc_ajax_wc_stripe_create_order', array( $this, 'ajax_create_order' ) );
187
		add_action( 'wc_ajax_wc_stripe_add_to_cart', array( $this, 'ajax_add_to_cart' ) );
188
		add_action( 'wc_ajax_wc_stripe_get_selected_product_data', array( $this, 'ajax_get_selected_product_data' ) );
189
		add_action( 'wc_ajax_wc_stripe_clear_cart', array( $this, 'ajax_clear_cart' ) );
190
		add_action( 'wc_ajax_wc_stripe_log_errors', array( $this, 'ajax_log_errors' ) );
191
192
		add_filter( 'woocommerce_gateway_title', array( $this, 'filter_gateway_title' ), 10, 2 );
193
		add_filter( 'woocommerce_validate_postcode', array( $this, 'postal_code_validation' ), 10, 3 );
194
195
		add_action( 'woocommerce_checkout_order_processed', array( $this, 'add_order_meta' ), 10, 2 );
196
	}
197
198
	/**
199
	 * Gets the button type.
200
	 *
201
	 * @since 4.0.0
202
	 * @version 4.0.0
203
	 * @return string
204
	 */
205
	public function get_button_type() {
206
		return isset( $this->stripe_settings['payment_request_button_type'] ) ? $this->stripe_settings['payment_request_button_type'] : 'default';
207
	}
208
209
	/**
210
	 * Gets the button theme.
211
	 *
212
	 * @since 4.0.0
213
	 * @version 4.0.0
214
	 * @return string
215
	 */
216
	public function get_button_theme() {
217
		return isset( $this->stripe_settings['payment_request_button_theme'] ) ? $this->stripe_settings['payment_request_button_theme'] : 'dark';
218
	}
219
220
	/**
221
	 * Gets the button height.
222
	 *
223
	 * @since 4.0.0
224
	 * @version 4.0.0
225
	 * @return string
226
	 */
227
	public function get_button_height() {
228
		return isset( $this->stripe_settings['payment_request_button_height'] ) ? str_replace( 'px', '', $this->stripe_settings['payment_request_button_height'] ) : '64';
229
	}
230
231
	/**
232
	 * Gets the product data for the currently viewed page
233
	 *
234
	 * @since 4.0.0
235
	 * @version 4.0.0
236
	 */
237
	public function get_product_data() {
238
		if ( ! is_product() ) {
239
			return false;
240
		}
241
242
		global $post;
243
244
		$product = wc_get_product( $post->ID );
245
246
		$data  = array();
247
		$items = array();
248
249
		$items[] = array(
250
			'label'  => WC_Stripe_Helper::is_pre_30() ? $product->name : $product->get_name(),
251
			'amount' => WC_Stripe_Helper::get_stripe_amount( WC_Stripe_Helper::is_pre_30() ? $product->price : $product->get_price() ),
252
		);
253
254 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...
255
			$items[] = array(
256
				'label'   => __( 'Tax', 'woocommerce-gateway-stripe' ),
257
				'amount'  => 0,
258
				'pending' => true,
259
			);
260
		}
261
262 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...
263
			$items[] = array(
264
				'label'   => __( 'Shipping', 'woocommerce-gateway-stripe' ),
265
				'amount'  => 0,
266
				'pending' => true,
267
			);
268
269
			$data['shippingOptions']  = array(
270
				'id'     => 'pending',
271
				'label'  => __( 'Pending', 'woocommerce-gateway-stripe' ),
272
				'detail' => '',
273
				'amount' => 0,
274
			);
275
		}
276
277
		$data['displayItems'] = $items;
278
		$data['total'] = array(
279
			'label'   => apply_filters( 'wc_stripe_payment_request_total_label', $this->total_label ),
280
			'amount'  => WC_Stripe_Helper::get_stripe_amount( WC_Stripe_Helper::is_pre_30() ? $product->price : $product->get_price() ),
281
			'pending' => true,
282
		);
283
284
		$data['requestShipping'] = ( wc_shipping_enabled() && $product->needs_shipping() );
285
		$data['currency']        = strtolower( get_woocommerce_currency() );
286
		$data['country_code']    = substr( get_option( 'woocommerce_default_country' ), 0, 2 );
287
288
		return apply_filters( 'wc_stripe_payment_request_product_data', $data, $product );
289
	}
290
291
	/**
292
	 * Filters the gateway title to reflect Payment Request type
293
	 *
294
	 */
295
	public function filter_gateway_title( $title, $id ) {
296
		global $post;
297
298
		if ( ! is_object( $post ) ) {
299
			return $title;
300
		}
301
302
		if ( WC_Stripe_Helper::is_pre_30() ) {
303
			$method_title = get_post_meta( $post->ID, '_payment_method_title', true );
304
		} else {
305
			$order        = wc_get_order( $post->ID );
306
			$method_title = is_object( $order ) ? $order->get_payment_method_title() : '';
307
		}
308
309
		if ( 'stripe' === $id && ! empty( $method_title ) && 'Apple Pay (Stripe)' === $method_title ) {
310
			return $method_title;
311
		}
312
313
		if ( 'stripe' === $id && ! empty( $method_title ) && 'Chrome Payment Request (Stripe)' === $method_title ) {
314
			return $method_title;
315
		}
316
317
		return $title;
318
	}
319
320
	/**
321
	 * Removes postal code validation from WC.
322
	 *
323
	 * @since 3.1.4
324
	 * @version 4.0.0
325
	 */
326
	public function postal_code_validation( $valid, $postcode, $country ) {
327
		$gateways = WC()->payment_gateways->get_available_payment_gateways();
328
329
		if ( ! isset( $gateways['stripe'] ) ) {
330
			return $valid;
331
		}
332
333
		$payment_request_type = isset( $_POST['payment_request_type'] ) ? wc_clean( $_POST['payment_request_type'] ) : '';
334
335
		if ( 'apple_pay' !== $payment_request_type ) {
336
			return $valid;
337
		}
338
339
		/**
340
		 * Currently Apple Pay truncates postal codes from UK and Canada to first 3 characters
341
		 * when passing it back from the shippingcontactselected object. This causes WC to invalidate
342
		 * the order and not let it go through. The remedy for now is just to remove this validation.
343
		 * Note that this only works with shipping providers that don't validate full postal codes.
344
		 */
345
		if ( 'GB' === $country || 'CA' === $country ) {
346
			return true;
347
		}
348
349
		return $valid;
350
	}
351
352
	/**
353
	 * Add needed order meta
354
	 *
355
	 * @since 4.0.0
356
	 * @version 4.0.0
357
	 * @param int $order_id
358
	 * @param array $posted_data The posted data from checkout form.
359
	 */
360
	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...
361
		if ( empty( $_POST['payment_request_type'] ) ) {
362
			return;
363
		}
364
365
		$order = wc_get_order( $order_id );
366
367
		$payment_request_type = wc_clean( $_POST['payment_request_type'] );
368
369 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...
370
			if ( WC_Stripe_Helper::is_pre_30() ) {
371
				update_post_meta( $order_id, '_payment_method_title', 'Apple Pay (Stripe)' );
372
			} else {
373
				$order->set_payment_method_title( 'Apple Pay (Stripe)' );
374
				$order->save();
375
			}
376
		}
377
378 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...
379
			if ( WC_Stripe_Helper::is_pre_30() ) {
380
				update_post_meta( $order_id, '_payment_method_title', 'Chrome Payment Request (Stripe)' );
381
			} else {
382
				$order->set_payment_method_title( 'Chrome Payment Request (Stripe)' );
383
				$order->save();
384
			}
385
		}
386
	}
387
388
	/**
389
	 * Checks to make sure product type is supported.
390
	 *
391
	 * @since 3.1.0
392
	 * @version 4.0.0
393
	 * @return array
394
	 */
395
	public function supported_product_types() {
396
		return apply_filters( 'wc_stripe_payment_request_supported_types', array(
397
			'simple',
398
			'variable',
399
			'variation',
400
		) );
401
	}
402
403
	/**
404
	 * Checks the cart to see if all items are allowed to used.
405
	 *
406
	 * @since 3.1.4
407
	 * @version 4.0.0
408
	 * @return bool
409
	 */
410
	public function allowed_items_in_cart() {
411
		foreach ( WC()->cart->get_cart() as $cart_item_key => $cart_item ) {
412
			$_product = apply_filters( 'woocommerce_cart_item_product', $cart_item['data'], $cart_item, $cart_item_key );
413
414
			if ( ! in_array( ( WC_Stripe_Helper::is_pre_30() ? $_product->product_type : $_product->get_type() ), $this->supported_product_types() ) ) {
415
				return false;
416
			}
417
418
			// Pre Orders compatbility where we don't support charge upon release.
419
			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() ) ) {
420
				return false;
421
			}
422
		}
423
424
		return true;
425
	}
426
427
	/**
428
	 * Load public scripts and styles.
429
	 *
430
	 * @since 3.1.0
431
	 * @version 4.0.0
432
	 */
433
	public function scripts() {
434
		// If keys are not set bail.
435
		if ( ! $this->are_keys_set() ) {
436
			WC_Stripe_Logger::log( 'Keys are not set correctly.' );
437
			return;
438
		}
439
440
		// If no SSL bail.
441
		if ( ! $this->testmode && ! is_ssl() ) {
442
			WC_Stripe_Logger::log( 'Stripe requires SSL.' );
443
			return;
444
		}
445
446
		if ( ! is_product() && ! is_cart() && ! is_checkout() && ! isset( $_GET['pay_for_order'] ) ) {
447
			return;
448
		}
449
450
		if ( is_product() ) {
451
			global $post;
452
453
			$product = wc_get_product( $post->ID );
454
455
			if ( ! is_object( $product ) || ! in_array( ( WC_Stripe_Helper::is_pre_30() ? $product->product_type : $product->get_type() ), $this->supported_product_types() ) ) {
456
				return;
457
			}
458
459
			if ( apply_filters( 'wc_stripe_hide_payment_request_on_product_page', false ) ) {
460
				return;
461
			}
462
		}
463
464
		$suffix = defined( 'SCRIPT_DEBUG' ) && SCRIPT_DEBUG ? '' : '.min';
465
466
		wp_register_script( 'stripe', 'https://js.stripe.com/v3/', '', '3.0', true );
467
		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 );
468
469
		wp_localize_script(
470
			'wc_stripe_payment_request',
471
			'wc_stripe_payment_request_params',
472
			array(
473
				'ajax_url' => WC_AJAX::get_endpoint( '%%endpoint%%' ),
474
				'stripe'   => array(
475
					'key'                => $this->publishable_key,
476
					'allow_prepaid_card' => apply_filters( 'wc_stripe_allow_prepaid_card', true ) ? 'yes' : 'no',
477
				),
478
				'nonce'    => array(
479
					'payment'                        => wp_create_nonce( 'wc-stripe-payment-request' ),
480
					'shipping'                       => wp_create_nonce( 'wc-stripe-payment-request-shipping' ),
481
					'update_shipping'                => wp_create_nonce( 'wc-stripe-update-shipping-method' ),
482
					'checkout'                       => wp_create_nonce( 'woocommerce-process_checkout' ),
483
					'add_to_cart'                    => wp_create_nonce( 'wc-stripe-add-to-cart' ),
484
					'get_selected_product_data'      => wp_create_nonce( 'wc-stripe-get-selected-product-data' ),
485
					'log_errors'                     => wp_create_nonce( 'wc-stripe-log-errors' ),
486
					'clear_cart'                     => wp_create_nonce( 'wc-stripe-clear-cart' ),
487
				),
488
				'i18n'     => array(
489
					'no_prepaid_card'  => __( 'Sorry, we\'re not accepting prepaid cards at this time.', 'woocommerce-gateway-stripe' ),
490
					/* translators: Do not translate the [option] placeholder */
491
					'unknown_shipping' => __( 'Unknown shipping option "[option]".', 'woocommerce-gateway-stripe' ),
492
				),
493
				'checkout' => array(
494
					'url'            => wc_get_checkout_url(),
495
					'currency_code'  => strtolower( get_woocommerce_currency() ),
496
					'country_code'   => substr( get_option( 'woocommerce_default_country' ), 0, 2 ),
497
					'needs_shipping' => WC()->cart->needs_shipping() ? 'yes' : 'no',
498
				),
499
				'button' => array(
500
					'type'   => $this->get_button_type(),
501
					'theme'  => $this->get_button_theme(),
502
					'height' => $this->get_button_height(),
503
					'locale' => substr( get_locale(), 0, 2 ), // Default format is en_US.
504
				),
505
				'is_product_page' => is_product(),
506
				'product'         => $this->get_product_data(),
507
			)
508
		);
509
510
		wp_enqueue_script( 'wc_stripe_payment_request' );
511
	}
512
513
	/**
514
	 * Display the payment request button.
515
	 *
516
	 * @since 4.0.0
517
	 * @version 4.0.0
518
	 */
519 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...
520
		$gateways = WC()->payment_gateways->get_available_payment_gateways();
521
522
		if ( ! isset( $gateways['stripe'] ) ) {
523
			return;
524
		}
525
526
		if ( ! is_cart() && ! is_checkout() && ! is_product() && ! isset( $_GET['pay_for_order'] ) ) {
527
			return;
528
		}
529
530
		if ( is_product() && apply_filters( 'wc_stripe_hide_payment_request_on_product_page', false ) ) {
531
			return;
532
		}
533
534
		if ( is_checkout() && ! apply_filters( 'wc_stripe_show_payment_request_on_checkout', false ) ) {
535
			return;
536
		}
537
538
		if ( is_product() ) {
539
			global $post;
540
541
			$product = wc_get_product( $post->ID );
542
543
			if ( ! is_object( $product ) || ! in_array( ( WC_Stripe_Helper::is_pre_30() ? $product->product_type : $product->get_type() ), $this->supported_product_types() ) ) {
544
				return;
545
			}
546
547
			// Pre Orders charge upon release not supported.
548
			if ( class_exists( 'WC_Pre_Orders_Order' ) && WC_Pre_Orders_Product::product_is_charged_upon_release( $product ) ) {
549
				WC_Stripe_Logger::log( 'Pre Order charge upon release is not supported. ( Payment Request button disabled )' );
550
				return;
551
			}
552
		} else {
553
			if ( ! $this->allowed_items_in_cart() ) {
554
				WC_Stripe_Logger::log( 'Items in the cart has unsupported product type ( Payment Request button disabled )' );
555
				return;
556
			}
557
		}
558
		?>
559
		<div id="wc-stripe-payment-request-wrapper" style="clear:both;padding-top:1.5em;">
560
			<div id="wc-stripe-payment-request-button">
561
				<!-- A Stripe Element will be inserted here. -->
562
			</div>
563
		</div>
564
		<?php
565
	}
566
567
	/**
568
	 * Display payment request button separator.
569
	 *
570
	 * @since 4.0.0
571
	 * @version 4.0.0
572
	 */
573 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...
574
		$gateways = WC()->payment_gateways->get_available_payment_gateways();
575
576
		if ( ! isset( $gateways['stripe'] ) ) {
577
			return;
578
		}
579
580
		if ( ! is_cart() && ! is_checkout() && ! is_product() && ! isset( $_GET['pay_for_order'] ) ) {
581
			return;
582
		}
583
584
		if ( is_product() && apply_filters( 'wc_stripe_hide_payment_request_on_product_page', false ) ) {
585
			return;
586
		}
587
588
		if ( is_checkout() && ! apply_filters( 'wc_stripe_show_payment_request_on_checkout', false ) ) {
589
			return;
590
		}
591
592
		if ( is_product() ) {
593
			global $post;
594
595
			$product = wc_get_product( $post->ID );
596
597
			if ( ! is_object( $product ) || ! in_array( ( WC_Stripe_Helper::is_pre_30() ? $product->product_type : $product->get_type() ), $this->supported_product_types() ) ) {
598
				return;
599
			}
600
601
			// Pre Orders charge upon release not supported.
602
			if ( class_exists( 'WC_Pre_Orders_Order' ) && WC_Pre_Orders_Product::product_is_charged_upon_release( $product ) ) {
603
				WC_Stripe_Logger::log( 'Pre Order charge upon release is not supported. ( Payment Request button disabled )' );
604
				return;
605
			}
606
		} else {
607
			if ( ! $this->allowed_items_in_cart() ) {
608
				WC_Stripe_Logger::log( 'Items in the cart has unsupported product type ( Payment Request button disabled )' );
609
				return;
610
			}
611
		}
612
		?>
613
		<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>
614
		<?php
615
	}
616
617
	/**
618
	 * Log errors coming from Payment Request
619
	 *
620
	 * @since 3.1.4
621
	 * @version 4.0.0
622
	 */
623
	public function ajax_log_errors() {
624
		check_ajax_referer( 'wc-stripe-log-errors', 'security' );
625
626
		$errors = wc_clean( stripslashes( $_POST['errors'] ) );
627
628
		WC_Stripe_Logger::log( $errors );
629
630
		exit;
631
	}
632
633
	/**
634
	 * Clears cart.
635
	 *
636
	 * @since 3.1.4
637
	 * @version 4.0.0
638
	 */
639
	public function ajax_clear_cart() {
640
		check_ajax_referer( 'wc-stripe-clear-cart', 'security' );
641
642
		WC()->cart->empty_cart();
643
		exit;
644
	}
645
646
	/**
647
	 * Get cart details.
648
	 */
649
	public function ajax_get_cart_details() {
650
		check_ajax_referer( 'wc-stripe-payment-request', 'security' );
651
652
		if ( ! defined( 'WOOCOMMERCE_CART' ) ) {
653
			define( 'WOOCOMMERCE_CART', true );
654
		}
655
656
		WC()->cart->calculate_totals();
657
658
		$currency = get_woocommerce_currency();
659
660
		// Set mandatory payment details.
661
		$data = array(
662
			'shipping_required' => WC()->cart->needs_shipping(),
663
			'order_data'        => array(
664
				'currency'        => strtolower( $currency ),
665
				'country_code'    => substr( get_option( 'woocommerce_default_country' ), 0, 2 ),
666
			),
667
		);
668
669
		$data['order_data'] += $this->build_display_items();
670
671
		wp_send_json( $data );
672
	}
673
674
	/**
675
	 * Get shipping options.
676
	 *
677
	 * @see WC_Cart::get_shipping_packages().
678
	 * @see WC_Shipping::calculate_shipping().
679
	 * @see WC_Shipping::get_packages().
680
	 */
681
	public function ajax_get_shipping_options() {
682
		check_ajax_referer( 'wc-stripe-payment-request-shipping', 'security' );
683
684
		try {
685
			// Set the shipping package.
686
			$posted = filter_input_array( INPUT_POST, array(
687
				'country'   => FILTER_SANITIZE_STRING,
688
				'state'     => FILTER_SANITIZE_STRING,
689
				'postcode'  => FILTER_SANITIZE_STRING,
690
				'city'      => FILTER_SANITIZE_STRING,
691
				'address'   => FILTER_SANITIZE_STRING,
692
				'address_2' => FILTER_SANITIZE_STRING,
693
			) );
694
695
			$this->calculate_shipping( $posted );
696
697
			// Set the shipping options.
698
			$data     = array();
699
			$packages = WC()->shipping->get_packages();
700
701
			if ( ! empty( $packages ) && WC()->customer->has_calculated_shipping() ) {
702
				foreach ( $packages as $package_key => $package ) {
703
					if ( empty( $package['rates'] ) ) {
704
						throw new Exception( __( 'Unable to find shipping method for address.', 'woocommerce-gateway-stripe' ) );
705
					}
706
707
					foreach ( $package['rates'] as $key => $rate ) {
708
						$data['shipping_options'][] = array(
709
							'id'       => $rate->id,
710
							'label'    => $rate->label,
711
							'detail'   => '',
712
							'amount'   => WC_Stripe_Helper::get_stripe_amount( $rate->cost ),
713
						);
714
					}
715
				}
716
			} else {
717
				throw new Exception( __( 'Unable to find shipping method for address.', 'woocommerce-gateway-stripe' ) );
718
			}
719
720
			if ( isset( $data[0] ) ) {
721
				// Auto select the first shipping method.
722
				WC()->session->set( 'chosen_shipping_methods', array( $data[0]['id'] ) );
723
			}
724
725
			WC()->cart->calculate_totals();
726
727
			$data += $this->build_display_items();
728
			$data['result'] = 'success';
729
730
			wp_send_json( $data );
731
		} catch ( Exception $e ) {
732
			$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...
733
			$data['result'] = 'invalid_shipping_address';
734
735
			wp_send_json( $data );
736
		}
737
	}
738
739
	/**
740
	 * Update shipping method.
741
	 */
742
	public function ajax_update_shipping_method() {
743
		check_ajax_referer( 'wc-stripe-update-shipping-method', 'security' );
744
745
		if ( ! defined( 'WOOCOMMERCE_CART' ) ) {
746
			define( 'WOOCOMMERCE_CART', true );
747
		}
748
749
		$chosen_shipping_methods = WC()->session->get( 'chosen_shipping_methods' );
750
		$shipping_method         = filter_input( INPUT_POST, 'shipping_method', FILTER_DEFAULT, FILTER_REQUIRE_ARRAY );
751
752
		if ( is_array( $shipping_method ) ) {
753
			foreach ( $shipping_method as $i => $value ) {
754
				$chosen_shipping_methods[ $i ] = wc_clean( $value );
755
			}
756
		}
757
758
		WC()->session->set( 'chosen_shipping_methods', $chosen_shipping_methods );
759
760
		WC()->cart->calculate_totals();
761
762
		$data = array();
763
		$data += $this->build_display_items();
764
		$data['result'] = 'success';
765
766
		wp_send_json( $data );
767
	}
768
769
	/**
770
	 * Gets the selected product data.
771
	 *
772
	 * @since 4.0.0
773
	 * @version 4.0.0
774
	 * @return array $data
775
	 */
776
	public function ajax_get_selected_product_data() {
777
		check_ajax_referer( 'wc-stripe-get-selected-product-data', 'security' );
778
779
		$product_id = absint( $_POST['product_id'] );
780
		$qty = ! isset( $_POST['qty'] ) ? 1 : absint( $_POST['qty'] );
781
782
		$product = wc_get_product( $product_id );
783
784
		if ( 'variable' === ( WC_Stripe_Helper::is_pre_30() ? $product->product_type : $product->get_type() ) && isset( $_POST['attributes'] ) ) {
785
			$attributes = array_map( 'wc_clean', $_POST['attributes'] );
786
787 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...
788
				$variation_id = $product->get_matching_variation( $attributes );
789
			} else {
790
				$data_store = WC_Data_Store::load( 'product' );
791
				$variation_id = $data_store->find_matching_product_variation( $product, $attributes );
792
			}
793
794
			if ( ! empty( $variation_id ) ) {
795
				$product = wc_get_product( $variation_id );
796
			}
797
		} elseif ( 'simple' === ( WC_Stripe_Helper::is_pre_30() ? $product->product_type : $product->get_type() ) ) {
798
			$product = wc_get_product( $product_id );
799
		}
800
801
		$total = $qty * ( WC_Stripe_Helper::is_pre_30() ? $product->price : $product->get_price() );
802
803
		$quantity_label = 1 < $qty ? ' (x' . $qty . ')' : '';
804
805
		$data  = array();
806
		$items = array();
807
808
		$items[] = array(
809
			'label'  => ( WC_Stripe_Helper::is_pre_30() ? $product->name : $product->get_name() ) . $quantity_label,
810
			'amount' => WC_Stripe_Helper::get_stripe_amount( $total ),
811
		);
812
813 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...
814
			$items[] = array(
815
				'label'   => __( 'Tax', 'woocommerce-gateway-stripe' ),
816
				'amount'  => 0,
817
				'pending' => true,
818
			);
819
		}
820
821 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...
822
			$items[] = array(
823
				'label'   => __( 'Shipping', 'woocommerce-gateway-stripe' ),
824
				'amount'  => 0,
825
				'pending' => true,
826
			);
827
828
			$data['shippingOptions']  = array(
829
				'id'     => 'pending',
830
				'label'  => __( 'Pending', 'woocommerce-gateway-stripe' ),
831
				'detail' => '',
832
				'amount' => 0,
833
			);
834
		}
835
836
		$data['displayItems'] = $items;
837
		$data['total'] = array(
838
			'label'   => $this->total_label,
839
			'amount'  => WC_Stripe_Helper::get_stripe_amount( $total ),
840
			'pending' => true,
841
		);
842
843
		$data['requestShipping'] = ( wc_shipping_enabled() && $product->needs_shipping() );
844
		$data['currency']        = strtolower( get_woocommerce_currency() );
845
		$data['country_code']    = substr( get_option( 'woocommerce_default_country' ), 0, 2 );
846
847
		wp_send_json( $data );
848
	}
849
850
	/**
851
	 * Adds the current product to the cart. Used on product detail page.
852
	 *
853
	 * @since 4.0.0
854
	 * @version 4.0.0
855
	 * @return array $data
856
	 */
857
	public function ajax_add_to_cart() {
858
		check_ajax_referer( 'wc-stripe-add-to-cart', 'security' );
859
860
		if ( ! defined( 'WOOCOMMERCE_CART' ) ) {
861
			define( 'WOOCOMMERCE_CART', true );
862
		}
863
864
		WC()->shipping->reset_shipping();
865
866
		$product_id = absint( $_POST['product_id'] );
867
		$qty = ! isset( $_POST['qty'] ) ? 1 : absint( $_POST['qty'] );
868
869
		$product = wc_get_product( $product_id );
870
871
		// First empty the cart to prevent wrong calculation.
872
		WC()->cart->empty_cart();
873
874
		if ( 'variable' === ( WC_Stripe_Helper::is_pre_30() ? $product->product_type : $product->get_type() ) && isset( $_POST['attributes'] ) ) {
875
			$attributes = array_map( 'wc_clean', $_POST['attributes'] );
876
877 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...
878
				$variation_id = $product->get_matching_variation( $attributes );
879
			} else {
880
				$data_store = WC_Data_Store::load( 'product' );
881
				$variation_id = $data_store->find_matching_product_variation( $product, $attributes );
882
			}
883
884
			WC()->cart->add_to_cart( $product->get_id(), $qty, $variation_id, $attributes );
885
		}
886
887
		if ( 'simple' === ( WC_Stripe_Helper::is_pre_30() ? $product->product_type : $product->get_type() ) ) {
888
			WC()->cart->add_to_cart( $product->get_id(), $qty );
889
		}
890
891
		WC()->cart->calculate_totals();
892
893
		$data = array();
894
		$data += $this->build_display_items();
895
		$data['result'] = 'success';
896
897
		wp_send_json( $data );
898
	}
899
900
	/**
901
	 * Normalizes the state/county field because in some
902
	 * cases, the state/county field is formatted differently from
903
	 * what WC is expecting and throws an error. An example
904
	 * for Ireland the county dropdown in Chrome shows "Co. Clare" format
905
	 *
906
	 * @since 4.0.0
907
	 * @version 4.0.0
908
	 */
909
	public function normalize_state() {
910
		$billing_country  = ! empty( $_POST['billing_country'] ) ? wc_clean( $_POST['billing_country'] ) : '';
911
		$shipping_country = ! empty( $_POST['shipping_country'] ) ? wc_clean( $_POST['shipping_country'] ) : '';
912
		$billing_state    = ! empty( $_POST['billing_state'] ) ? wc_clean( $_POST['billing_state'] ) : '';
913
		$shipping_state   = ! empty( $_POST['shipping_state'] ) ? wc_clean( $_POST['shipping_state'] ) : '';
914
915 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...
916
			$valid_states = WC()->countries->get_states( $billing_country );
917
918
			// Valid states found for country.
919
			if ( ! empty( $valid_states ) && is_array( $valid_states ) && sizeof( $valid_states ) > 0 ) {
920
				foreach ( $valid_states as $state_abbr => $state ) {
921
					if ( preg_match( '/' . preg_quote( $state ) . '/i', $billing_state ) ) {
922
						$_POST['billing_state'] = $state_abbr;
923
					}
924
				}
925
			}
926
		}
927
928 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...
929
			$valid_states = WC()->countries->get_states( $shipping_country );
930
931
			// Valid states found for country.
932
			if ( ! empty( $valid_states ) && is_array( $valid_states ) && sizeof( $valid_states ) > 0 ) {
933
				foreach ( $valid_states as $state_abbr => $state ) {
934
					if ( preg_match( '/' . preg_quote( $state ) . '/i', $shipping_state ) ) {
935
						$_POST['shipping_state'] = $state_abbr;
936
					}
937
				}
938
			}
939
		}
940
	}
941
942
	/**
943
	 * Create order. Security is handled by WC.
944
	 *
945
	 * @since 3.1.0
946
	 * @version 4.0.0
947
	 */
948
	public function ajax_create_order() {
949
		if ( WC()->cart->is_empty() ) {
950
			wp_send_json_error( __( 'Empty cart', 'woocommerce-gateway-stripe' ) );
951
		}
952
953
		if ( ! defined( 'WOOCOMMERCE_CHECKOUT' ) ) {
954
			define( 'WOOCOMMERCE_CHECKOUT', true );
955
		}
956
957
		$this->normalize_state();
958
959
		WC()->checkout()->process_checkout();
960
961
		die( 0 );
962
	}
963
964
	/**
965
	 * Calculate and set shipping method.
966
	 *
967
	 * @since 3.1.0
968
	 * @version 4.0.0
969
	 * @param array $address
970
	 */
971
	protected function calculate_shipping( $address = array() ) {
972
		global $states;
973
974
		$country   = $address['country'];
975
		$state     = $address['state'];
976
		$postcode  = $address['postcode'];
977
		$city      = $address['city'];
978
		$address_1 = $address['address'];
979
		$address_2 = $address['address_2'];
980
981
		$country_class = new WC_Countries();
982
		$country_class->load_country_states();
983
984
		/**
985
		 * In some versions of Chrome, state can be a full name. So we need
986
		 * to convert that to abbreviation as WC is expecting that.
987
		 */
988
		if ( 2 < strlen( $state ) ) {
989
			$state = array_search( ucfirst( strtolower( $state ) ), $states[ $country ] );
990
		}
991
992
		WC()->shipping->reset_shipping();
993
994
		if ( $postcode && WC_Validation::is_postcode( $postcode, $country ) ) {
995
			$postcode = wc_format_postcode( $postcode, $country );
996
		}
997
998
		if ( $country ) {
999
			WC()->customer->set_location( $country, $state, $postcode, $city );
1000
			WC()->customer->set_shipping_location( $country, $state, $postcode, $city );
1001
		} else {
1002
			WC_Stripe_Helper::is_pre_30() ? WC()->customer->set_to_base() : WC()->customer->set_billing_address_to_base();
1003
			WC_Stripe_Helper::is_pre_30() ? WC()->customer->set_shipping_to_base() : WC()->customer->set_shipping_address_to_base();
1004
		}
1005
1006
		if ( WC_Stripe_Helper::is_pre_30() ) {
1007
			WC()->customer->calculated_shipping( true );
1008
		} else {
1009
			WC()->customer->set_calculated_shipping( true );
1010
			WC()->customer->save();
1011
		}
1012
1013
		$packages = array();
1014
1015
		$packages[0]['contents']                 = WC()->cart->get_cart();
1016
		$packages[0]['contents_cost']            = 0;
1017
		$packages[0]['applied_coupons']          = WC()->cart->applied_coupons;
1018
		$packages[0]['user']['ID']               = get_current_user_id();
1019
		$packages[0]['destination']['country']   = $country;
1020
		$packages[0]['destination']['state']     = $state;
1021
		$packages[0]['destination']['postcode']  = $postcode;
1022
		$packages[0]['destination']['city']      = $city;
1023
		$packages[0]['destination']['address']   = $address_1;
1024
		$packages[0]['destination']['address_2'] = $address_2;
1025
1026
		foreach ( WC()->cart->get_cart() as $item ) {
1027
			if ( $item['data']->needs_shipping() ) {
1028
				if ( isset( $item['line_total'] ) ) {
1029
					$packages[0]['contents_cost'] += $item['line_total'];
1030
				}
1031
			}
1032
		}
1033
1034
		$packages = apply_filters( 'woocommerce_cart_shipping_packages', $packages );
1035
1036
		WC()->shipping->calculate_shipping( $packages );
1037
	}
1038
1039
	/**
1040
	 * Builds the shippings methods to pass to Payment Request
1041
	 *
1042
	 * @since 3.1.0
1043
	 * @version 4.0.0
1044
	 */
1045
	protected function build_shipping_methods( $shipping_methods ) {
1046
		if ( empty( $shipping_methods ) ) {
1047
			return array();
1048
		}
1049
1050
		$shipping = array();
1051
1052
		foreach ( $shipping_methods as $method ) {
1053
			$shipping[] = array(
1054
				'id'         => $method['id'],
1055
				'label'      => $method['label'],
1056
				'detail'     => '',
1057
				'amount'     => WC_Stripe_Helper::get_stripe_amount( $method['amount']['value'] ),
1058
			);
1059
		}
1060
1061
		return $shipping;
1062
	}
1063
1064
	/**
1065
	 * Builds the line items to pass to Payment Request
1066
	 *
1067
	 * @since 3.1.0
1068
	 * @version 4.0.0
1069
	 */
1070
	protected function build_display_items() {
1071
		if ( ! defined( 'WOOCOMMERCE_CART' ) ) {
1072
			define( 'WOOCOMMERCE_CART', true );
1073
		}
1074
1075
		$items    = array();
1076
		$subtotal = 0;
1077
1078
		// Default show only subtotal instead of itemization.
1079
		if ( ! apply_filters( 'wc_stripe_payment_request_hide_itemization', true ) ) {
1080
			foreach ( WC()->cart->get_cart() as $cart_item_key => $cart_item ) {
1081
				$amount         = $cart_item['line_subtotal'];
1082
				$subtotal       += $cart_item['line_subtotal'];
1083
				$quantity_label = 1 < $cart_item['quantity'] ? ' (x' . $cart_item['quantity'] . ')' : '';
1084
1085
				$product_name = WC_Stripe_Helper::is_pre_30() ? $cart_item['data']->post->post_title : $cart_item['data']->get_name();
1086
1087
				$item = array(
1088
					'label'  => $product_name . $quantity_label,
1089
					'amount' => WC_Stripe_Helper::get_stripe_amount( $amount ),
1090
				);
1091
1092
				$items[] = $item;
1093
			}
1094
		}
1095
1096
		$discounts   = wc_format_decimal( WC()->cart->get_cart_discount_total(), WC()->cart->dp );
1097
		$tax         = wc_format_decimal( WC()->cart->tax_total + WC()->cart->shipping_tax_total, WC()->cart->dp );
1098
		$shipping    = wc_format_decimal( WC()->cart->shipping_total, WC()->cart->dp );
1099
		$items_total = wc_format_decimal( WC()->cart->cart_contents_total, WC()->cart->dp ) + $discounts;
1100
		$order_total = wc_format_decimal( $items_total + $tax + $shipping - $discounts, WC()->cart->dp );
1101
1102
		if ( wc_tax_enabled() ) {
1103
			$items[] = array(
1104
				'label'  => esc_html( __( 'Tax', 'woocommerce-gateway-stripe' ) ),
1105
				'amount' => WC_Stripe_Helper::get_stripe_amount( $tax ),
1106
			);
1107
		}
1108
1109 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...
1110
			$items[] = array(
1111
				'label'  => esc_html( __( 'Shipping', 'woocommerce-gateway-stripe' ) ),
1112
				'amount' => WC_Stripe_Helper::get_stripe_amount( $shipping ),
1113
			);
1114
		}
1115
1116 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...
1117
			$items[] = array(
1118
				'label'  => esc_html( __( 'Discount', 'woocommerce-gateway-stripe' ) ),
1119
				'amount' => WC_Stripe_Helper::get_stripe_amount( $discounts ),
1120
			);
1121
		}
1122
1123
		if ( version_compare( WC_VERSION, '3.2', '<' ) ) {
1124
			$cart_fees = WC()->cart->fees;
1125
		} else {
1126
			$cart_fees = WC()->cart->get_fees();
1127
		}
1128
1129
		// Include fees and taxes as display items.
1130
		foreach ( $cart_fees as $key => $fee ) {
1131
			$items[] = array(
1132
				'label'  => $fee->name,
1133
				'amount' => WC_Stripe_Helper::get_stripe_amount( $fee->amount ),
1134
			);
1135
		}
1136
1137
		return array(
1138
			'displayItems' => $items,
1139
			'total'      => array(
1140
				'label'   => $this->total_label,
1141
				'amount'  => max( 0, apply_filters( 'woocommerce_stripe_calculated_total', WC_Stripe_Helper::get_stripe_amount( $order_total ), $order_total, WC()->cart ) ),
1142
				'pending' => false,
1143
			),
1144
		);
1145
	}
1146
}
1147
1148
new WC_Stripe_Payment_Request();
1149