Completed
Push — master ( 6d8164...bf7249 )
by Roy
03:26
created

WC_Stripe_Payment_Request   D

Complexity

Total Complexity 195

Size/Duplication

Total Lines 1061
Duplicated Lines 17.72 %

Coupling/Cohesion

Components 1
Dependencies 2

Importance

Changes 0
Metric Value
dl 188
loc 1061
rs 4.4229
c 0
b 0
f 0
wmc 195
lcom 1
cbo 2

28 Methods

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

How to fix   Duplicated Code    Complexity   

Duplicated Code

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

Common duplication problems, and corresponding solutions are:

Complex Class

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

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

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

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

1
<?php
2
/**
3
 * Stripe Payment Request API
4
 *
5
 * @package WooCommerce_Stripe/Classes/Payment_Request
6
 * @since   3.1.0
7
 */
8
9
if ( ! defined( 'ABSPATH' ) ) {
10
	exit;
11
}
12
13
/**
14
 * WC_Stripe_Payment_Request class.
15
 */
16
class WC_Stripe_Payment_Request {
17
	/**
18
	 * Enabled.
19
	 *
20
	 * @var
21
	 */
22
	public $stripe_settings;
23
24
	/**
25
	 * Stripe Checkout enabled.
26
	 *
27
	 * @var
28
	 */
29
	public $stripe_checkout_enabled;
30
31
	/**
32
	 * Total label
33
	 *
34
	 * @var
35
	 */
36
	public $total_label;
37
38
	/**
39
	 * Initialize class actions.
40
	 *
41
	 * @since 3.0.0
42
	 * @version 4.0.0
43
	 */
44
	public function __construct() {
45
		$this->stripe_settings         = get_option( 'woocommerce_stripe_settings', array() );
46
		$this->publishable_key         = $this->get_publishable_key();
0 ignored issues
show
Bug introduced by
The property publishable_key does not exist. Did you maybe forget to declare it?

In PHP it is possible to write to properties without declaring them. For example, the following is perfectly valid PHP code:

class MyClass { }

$x = new MyClass();
$x->foo = true;

Generally, it is a good practice to explictly declare properties to avoid accidental typos and provide IDE auto-completion:

class MyClass {
    public $foo;
}

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

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

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