Completed
Push — master ( 1097c7...2c7ec5 )
by Roy
02:23
created

WC_Stripe_Apple_Pay::__construct()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 9
Code Lines 5

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 9
rs 9.6666
c 0
b 0
f 0
cc 2
eloc 5
nc 2
nop 0
1
<?php
2
if ( ! defined( 'ABSPATH' ) ) {
3
	exit;
4
}
5
6
/**
7
 * WC_Stripe_Apple_Pay class.
8
 *
9
 * @extends WC_Gateway_Stripe
10
 */
11
class WC_Stripe_Apple_Pay extends WC_Gateway_Stripe {
12
	/**
13
	 * This Instance.
14
	 *
15
	 * @var
16
	 */
17
	private static $_this;
18
19
	/**
20
	 * Gateway.
21
	 *
22
	 * @var
23
	 */
24
	private $_gateway;
0 ignored issues
show
Unused Code introduced by
The property $_gateway is not used and could be removed.

This check marks private properties in classes that are never used. Those properties can be removed.

Loading history...
25
26
	/**
27
	 * Statement Description
28
	 *
29
	 * @var
30
	 */
31
	public $statement_descriptor;
32
33
	/**
34
	 * Gateway settings.
35
	 *
36
	 * @var
37
	 */
38
	private $_gateway_settings;
39
40
	/**
41
	 * Constructor.
42
	 *
43
	 * @access public
44
	 * @since 3.1.0
45
	 * @version 3.1.0
46
	 */
47
	public function __construct() {
48
		self::$_this = $this;
49
50
		$this->_gateway_settings = get_option( 'woocommerce_stripe_settings', '' );
51
52
		$this->statement_descriptor = ! empty( $this->_gateway_settings['statement_descriptor'] ) ? $this->_gateway_settings['statement_descriptor'] : wp_specialchars_decode( get_bloginfo( 'name' ), ENT_QUOTES );
53
54
		$this->init();
55
	}
56
57
	public function instance() {
58
		return self::$_this;
59
	}
60
61
	/**
62
	 * Initialize.
63
	 *
64
	 * @access public
65
	 * @since 3.1.0
66
	 * @version 3.1.4
67
	 */
68
	public function init() {
69
		// If Apple Pay is not enabled no need to proceed further.
70
		if ( 'yes' !== $this->_gateway_settings['apple_pay'] ) {
71
			return;
72
		}
73
74
		add_action( 'wp_enqueue_scripts', array( $this, 'cart_scripts' ) );
75
		add_action( 'wp_enqueue_scripts', array( $this, 'single_scripts' ) );
76
77
		/**
78
		 * In order to display the Apple Pay button in the correct position,
79
		 * a new hook was added to WooCommerce 3.0. In older versions of WooCommerce,
80
		 * CSS is used to position the button.
81
		 */
82
		if ( version_compare( WC_VERSION, '3.0.0', '<' ) ) {
83
			add_action( 'woocommerce_after_add_to_cart_button', array( $this, 'display_apple_pay_button' ), 1 );
84
		} else {
85
			add_action( 'woocommerce_after_add_to_cart_quantity', array( $this, 'display_apple_pay_button' ), 1 );
86
		}
87
88
		add_action( 'woocommerce_proceed_to_checkout', array( $this, 'display_apple_pay_button' ), 1 );
89
		add_action( 'woocommerce_proceed_to_checkout', array( $this, 'display_apple_pay_separator_html' ), 2 );
90
		add_action( 'woocommerce_checkout_before_customer_details', array( $this, 'display_apple_pay_button' ), 1 );
91
		add_action( 'woocommerce_checkout_before_customer_details', array( $this, 'display_apple_pay_separator_html' ), 2 );
92
		add_action( 'wc_ajax_wc_stripe_apple_pay', array( $this, 'process_apple_pay' ) );
93
		add_action( 'wc_ajax_wc_stripe_generate_apple_pay_cart', array( $this, 'generate_apple_pay_cart' ) );
94
		add_action( 'wc_ajax_wc_stripe_apple_pay_clear_cart', array( $this, 'clear_cart' ) );
95
		add_action( 'wc_ajax_wc_stripe_generate_apple_pay_single', array( $this, 'generate_apple_pay_single' ) );
96
		add_action( 'wc_ajax_wc_stripe_apple_pay_get_shipping_methods', array( $this, 'get_shipping_methods' ) );
97
		add_action( 'wc_ajax_wc_stripe_apple_pay_update_shipping_method', array( $this, 'update_shipping_method' ) );
98
		add_filter( 'woocommerce_gateway_title', array( $this, 'filter_gateway_title' ), 10, 2 );
99
	}
100
101
	/**
102
	 * Filters the gateway title to reflect Apple Pay.
103
	 *
104
	 */
105
	public function filter_gateway_title( $title, $id ) {
106
		global $post;
107
108
		if ( ! is_object( $post ) ) {
109
			return $title;
110
		}
111
112
		$method_title = get_post_meta( $post->ID, '_payment_method_title', true );
113
114
		if ( 'stripe' === $id && ! empty( $method_title ) ) {
115
			return $method_title;
116
		}
117
118
		return $title;
119
	}
120
121
	/**
122
	 * Enqueue JS scripts and styles for single product page.
123
	 *
124
	 * @since 3.1.0
125
	 * @version 3.1.4
126
	 */
127
	public function single_scripts() {
128
		if ( ! is_single() ) {
129
			return;
130
		}
131
132
		global $post;
133
134
		$product = wc_get_product( $post->ID );
135
136
		if ( ! is_object( $product ) || ! in_array( ( version_compare( WC_VERSION, '3.0.0', '<' ) ? $product->product_type : $product->get_type() ), $this->supported_product_types() ) ) {
137
			return;
138
		}
139
140
		$suffix = defined( 'SCRIPT_DEBUG' ) && SCRIPT_DEBUG ? '' : '.min';
141
142
		wp_enqueue_style( 'stripe_apple_pay', plugins_url( 'assets/css/stripe-apple-pay.css', WC_STRIPE_MAIN_FILE ), array(), WC_STRIPE_VERSION );
143
144
		wp_enqueue_script( 'stripe', 'https://js.stripe.com/v2/', '', '1.0', true );
145
		wp_enqueue_script( 'woocommerce_stripe_apple_pay_single', plugins_url( 'assets/js/stripe-apple-pay-single' . $suffix . '.js', WC_STRIPE_MAIN_FILE ), array( 'stripe' ), WC_STRIPE_VERSION, true );
146
147
		$publishable_key = 'yes' === $this->_gateway_settings['testmode'] ? $this->_gateway_settings['test_publishable_key'] : $this->_gateway_settings['publishable_key'];
148
149
		$stripe_params = array(
150
			'key'                                           => $publishable_key,
151
			'currency_code'                                 => get_woocommerce_currency(),
152
			'country_code'                                  => substr( get_option( 'woocommerce_default_country' ), 0, 2 ),
153
			'label'                                         => $this->statement_descriptor,
154
			'ajaxurl'                                       => WC_AJAX::get_endpoint( '%%endpoint%%' ),
155
			'stripe_apple_pay_nonce'                        => wp_create_nonce( '_wc_stripe_apple_pay_nonce' ),
156
			'stripe_apple_pay_cart_nonce'                   => wp_create_nonce( '_wc_stripe_apple_pay_cart_nonce' ),
157
			'stripe_apple_pay_get_shipping_methods_nonce'   => wp_create_nonce( '_wc_stripe_apple_pay_get_shipping_methods_nonce' ),
158
			'stripe_apple_pay_update_shipping_method_nonce' => wp_create_nonce( '_wc_stripe_apple_pay_update_shipping_method_nonce' ),
159
			'needs_shipping'                                => $product->needs_shipping() ? 'yes' : 'no',
160
			'i18n'                                          => array(
161
				'sub_total' => __( 'Sub-Total', 'woocommerce-gateway-stripe' ),
162
			),
163
		);
164
165
		wp_localize_script( 'woocommerce_stripe_apple_pay_single', 'wc_stripe_apple_pay_single_params', apply_filters( 'wc_stripe_apple_pay_single_params', $stripe_params ) );
166
	}
167
168
	/**
169
	 * Enqueue JS scripts and styles for the cart/checkout.
170
	 *
171
	 * @since 3.1.0
172
	 * @version 3.1.0
173
	 */
174
	public function cart_scripts() {
175
		if ( ! is_cart() && ! is_checkout() && ! isset( $_GET['pay_for_order'] ) ) {
176
			return;
177
		}
178
179
		$suffix = defined( 'SCRIPT_DEBUG' ) && SCRIPT_DEBUG ? '' : '.min';
180
181
		wp_enqueue_style( 'stripe_apple_pay', plugins_url( 'assets/css/stripe-apple-pay.css', WC_STRIPE_MAIN_FILE ), array(), WC_STRIPE_VERSION );
182
183
		wp_enqueue_script( 'stripe', 'https://js.stripe.com/v2/', '', '1.0', true );
184
		wp_enqueue_script( 'woocommerce_stripe_apple_pay', plugins_url( 'assets/js/stripe-apple-pay' . $suffix . '.js', WC_STRIPE_MAIN_FILE ), array( 'stripe' ), WC_STRIPE_VERSION, true );
185
186
		$publishable_key = 'yes' === $this->_gateway_settings['testmode'] ? $this->_gateway_settings['test_publishable_key'] : $this->_gateway_settings['publishable_key'];
187
188
		$stripe_params = array(
189
			'key'                                           => $publishable_key,
190
			'currency_code'                                 => get_woocommerce_currency(),
191
			'country_code'                                  => substr( get_option( 'woocommerce_default_country' ), 0, 2 ),
192
			'label'                                         => $this->statement_descriptor,
193
			'ajaxurl'                                       => WC_AJAX::get_endpoint( '%%endpoint%%' ),
194
			'stripe_apple_pay_nonce'                        => wp_create_nonce( '_wc_stripe_apple_pay_nonce' ),
195
			'stripe_apple_pay_cart_nonce'                   => wp_create_nonce( '_wc_stripe_apple_pay_cart_nonce' ),
196
			'stripe_apple_pay_get_shipping_methods_nonce'   => wp_create_nonce( '_wc_stripe_apple_pay_get_shipping_methods_nonce' ),
197
			'stripe_apple_pay_update_shipping_method_nonce' => wp_create_nonce( '_wc_stripe_apple_pay_update_shipping_method_nonce' ),
198
			'needs_shipping'                                => WC()->cart->needs_shipping() ? 'yes' : 'no',
199
			'is_cart_page'                                  => is_cart() ? 'yes' : 'no',
200
		);
201
202
		wp_localize_script( 'woocommerce_stripe_apple_pay', 'wc_stripe_apple_pay_params', apply_filters( 'wc_stripe_apple_pay_params', $stripe_params ) );
203
	}
204
205
	/**
206
	 * Checks to make sure product type is supported by Apple Pay.
207
	 *
208
	 */
209
	public function supported_product_types() {
210
		return array(
211
			'simple',
212
			'variable',
213
		);
214
	}
215
216
	/**
217
	 * Display Apple Pay button on the cart page
218
	 *
219
	 * @since 3.1.0
220
	 * @version 3.1.0
221
	 */
222
	public function display_apple_pay_button() {
223
		$gateways = WC()->payment_gateways->get_available_payment_gateways();
224
225
		/**
226
		 * In order for the Apple Pay button to show on product detail page,
227
		 * Apple Pay must be enabled and Stripe gateway must be enabled.
228
		 */
229
		if (
230
			'yes' !== $this->_gateway_settings['apple_pay']
231
			|| ! isset( $gateways['stripe'] )
232
		) {
233
			return;
234
		}
235
236 View Code Duplication
		if ( is_single() ) {
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...
237
			global $post;
238
239
			$product = wc_get_product( $post->ID );
240
241
			if ( ! is_object( $product ) || ! in_array( ( version_compare( WC_VERSION, '3.0.0', '<' ) ? $product->product_type : $product->get_type() ), $this->supported_product_types() ) ) {
242
				return;
243
			}
244
		}
245
246
		$apple_pay_button = ! empty( $this->_gateway_settings['apple_pay_button'] ) ? $this->_gateway_settings['apple_pay_button'] : 'black';
247
		$button_lang      = ! empty( $this->_gateway_settings['apple_pay_button_lang'] ) ? strtolower( $this->_gateway_settings['apple_pay_button_lang'] ) : 'en';
248
		?>
249
		<div class="apple-pay-button-wrapper">
250
			<button class="apple-pay-button" lang="<?php echo esc_attr( $button_lang ); ?>" style="-webkit-appearance: -apple-pay-button; -apple-pay-button-type: buy; -apple-pay-button-style: <?php echo esc_attr( $apple_pay_button ); ?>;"></button>
251
		</div>
252
		<?php
253
	}
254
255
	/**
256
	 * Display Apple Pay button on the cart page
257
	 *
258
	 * @since 3.1.0
259
	 * @version 3.1.0
260
	 */
261
	public function display_apple_pay_separator_html() {
262
		$gateways = WC()->payment_gateways->get_available_payment_gateways();
263
264
		/**
265
		 * In order for the Apple Pay button to show on cart page,
266
		 * Apple Pay must be enabled and Stripe gateway must be enabled.
267
		 */
268
		if (
269
			'yes' !== $this->_gateway_settings['apple_pay']
270
			|| ! isset( $gateways['stripe'] )
271
		) {
272
			return;
273
		}
274
275 View Code Duplication
		if ( is_single() ) {
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...
276
			global $post;
277
278
			$product = wc_get_product( $post->ID );
279
280
			if ( ! in_array( ( version_compare( WC_VERSION, '3.0.0', '<' ) ? $product->product_type : $product->get_type() ), $this->supported_product_types() ) ) {
281
				return;
282
			}
283
		}
284
		?>
285
		<p class="apple-pay-button-checkout-separator">- <?php esc_html_e( 'Or', 'woocommerce-gateway-stripe' ); ?> -</p>
286
		<?php
287
	}
288
289
	/**
290
	 * Generates the Apple Pay single cart.
291
	 *
292
	 * @since 3.1.0
293
	 * @version 3.1.0
294
	 */
295
	public function generate_apple_pay_single() {
296
		if ( ! wp_verify_nonce( $_POST['nonce'], '_wc_stripe_apple_pay_cart_nonce' ) ) {
297
			wp_die( __( 'Cheatin&#8217; huh?', 'woocommerce-gateway-stripe' ) );
298
		}
299
300
		if ( ! defined( 'WOOCOMMERCE_CART' ) ) {
301
			define( 'WOOCOMMERCE_CART', true );
302
		}
303
304
		WC()->shipping->reset_shipping();
305
306
		global $post;
307
308
		$product = wc_get_product( $post->ID );
309
		$qty     = ! isset( $_POST['qty'] ) ? 1 : absint( $_POST['qty'] );
310
311
		/**
312
		 * If this page is single product page, we need to simulate
313
		 * adding the product to the cart taken account if it is a
314
		 * simple or variable product.
315
		 */
316
		if ( is_single() ) {
317
			// First empty the cart to prevent wrong calculation.
318
			WC()->cart->empty_cart();
319
320
			if ( 'variable' === ( version_compare( WC_VERSION, '3.0.0', '<' ) ? $product->product_type : $product->get_type() ) && isset( $_POST['attributes'] ) ) {
321
				$attributes = array_map( 'wc_clean', $_POST['attributes'] );
322
323
				if ( version_compare( WC_VERSION, '3.0.0', '<' ) ) {
324
					$variation_id = $product->get_matching_variation( $attributes );
325
				} else {
326
					$data_store = WC_Data_Store::load( 'product' );
327
					$variation_id = $data_store->find_matching_product_variation( $product, $attributes );
328
				}
329
330
				WC()->cart->add_to_cart( $product->get_id(), $qty, $variation_id, $attributes );
331
			}
332
333
			if ( 'simple' === ( version_compare( WC_VERSION, '3.0.0', '<' ) ? $product->product_type : $product->get_type() ) ) {
334
				WC()->cart->add_to_cart( $product->get_id(), $qty );
335
			}
336
		}
337
338
		WC()->cart->calculate_totals();
339
340
		wp_send_json( array( 'line_items' => $this->build_line_items(), 'total' => WC()->cart->total ) );
341
	}
342
343
	/**
344
	 * Generates the Apple Pay cart.
345
	 *
346
	 * @since 3.1.0
347
	 * @version 3.1.0
348
	 */
349
	public function generate_apple_pay_cart() {
350
		if ( ! wp_verify_nonce( $_POST['nonce'], '_wc_stripe_apple_pay_cart_nonce' ) ) {
351
			wp_die( __( 'Cheatin&#8217; huh?', 'woocommerce-gateway-stripe' ) );
352
		}
353
354
		wp_send_json( array( 'line_items' => $this->build_line_items(), 'total' => WC()->cart->total ) );
355
	}
356
357
	/**
358
	 * Clears Apple Pay cart.
359
	 *
360
	 * @since 3.1.4
361
	 * @version 3.1.4
362
	 */
363
	public function clear_cart() {
364
		WC()->cart->empty_cart();
365
		exit;
366
	}
367
368
	/**
369
	 * Calculate and set shipping method.
370
	 *
371
	 * @since 3.1.0
372
	 * @version 3.1.0
373
	 * @param array $address
374
	 */
375
	public function calculate_shipping( $address = array() ) {
376
		$country  = strtoupper( $address['countryCode'] );
377
		$state    = strtoupper( $address['administrativeArea'] );
378
		$postcode = $address['postalCode'];
379
		$city     = $address['locality'];
380
381
		WC()->shipping->reset_shipping();
382
383
		if ( $postcode && ! WC_Validation::is_postcode( $postcode, $country ) ) {
384
			throw new Exception( __( 'Please enter a valid postcode/ZIP.', 'woocommerce-gateway-stripe' ) );
385
		} elseif ( $postcode ) {
386
			$postcode = wc_format_postcode( $postcode, $country );
387
		}
388
389 View Code Duplication
		if ( $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...
390
			WC()->customer->set_location( $country, $state, $postcode, $city );
391
			WC()->customer->set_shipping_location( $country, $state, $postcode, $city );
392
		} else {
393
			WC()->customer->set_to_base();
394
			WC()->customer->set_shipping_to_base();
395
		}
396
397
		WC()->customer->calculated_shipping( true );
398
399
		/**
400
		 * Set the shipping package.
401
		 *
402
		 * Note that address lines are not provided at this point
403
		 * because Apple Pay does not supply that until after
404
		 * authentication via passcode or Touch ID. We will need to
405
		 * capture this information when we process the payment.
406
		 */
407
408
		$packages = array();
409
410
		$packages[0]['contents']                 = WC()->cart->get_cart();
411
		$packages[0]['contents_cost']            = 0;
412
		$packages[0]['applied_coupons']          = WC()->cart->applied_coupons;
413
		$packages[0]['user']['ID']               = get_current_user_id();
414
		$packages[0]['destination']['country']   = $country;
415
		$packages[0]['destination']['state']     = $state;
416
		$packages[0]['destination']['postcode']  = $postcode;
417
		$packages[0]['destination']['city']      = $city;
418
419 View Code Duplication
		foreach ( WC()->cart->get_cart() as $item ) {
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...
420
			if ( $item['data']->needs_shipping() ) {
421
				if ( isset( $item['line_total'] ) ) {
422
					$packages[0]['contents_cost'] += $item['line_total'];
423
				}
424
			}
425
		}
426
427
		$packages = apply_filters( 'woocommerce_cart_shipping_packages', $packages );
428
429
		WC()->shipping->calculate_shipping( $packages );
430
	}
431
432
	/**
433
	 * Gets shipping for Apple Pay Payment sheet.
434
	 *
435
	 * @since 3.1.0
436
	 * @version 3.1.0
437
	 */
438
	public function get_shipping_methods() {
439
		if ( ! wp_verify_nonce( $_POST['nonce'], '_wc_stripe_apple_pay_get_shipping_methods_nonce' ) ) {
440
			wp_die( __( 'Cheatin&#8217; huh?', 'woocommerce-gateway-stripe' ) );
441
		}
442
443
		if ( ! defined( 'WOOCOMMERCE_CART' ) ) {
444
			define( 'WOOCOMMERCE_CART', true );
445
		}
446
447
		try {
448
			$address = array_map( 'wc_clean', $_POST['address'] );
449
450
			$this->calculate_shipping( $address );
451
452
			// Set the shipping options.
453
			$currency = get_woocommerce_currency();
454
			$data     = array();
455
456
			$packages = WC()->shipping->get_packages();
457
458
			if ( ! empty( $packages ) && WC()->customer->has_calculated_shipping() ) {
459
				foreach ( $packages as $package_key => $package ) {
460
					if ( empty( $package['rates'] ) ) {
461
						throw new Exception( __( 'Unable to find shipping method for address.', 'woocommerce-gateway-stripe' ) );
462
					}
463
464
					foreach ( $package['rates'] as $key => $rate ) {
465
						$data[] = array(
466
							'id'       => $rate->id,
467
							'label'    => $rate->label,
468
							'amount'   => array(
469
								'currency' => $currency,
470
								'value'    => $rate->cost,
471
							),
472
							'selected' => false,
473
						);
474
					}
475
				}
476
477
				// Auto select the first shipping method.
478
				WC()->session->set( 'chosen_shipping_methods', array( $data[0]['id'] ) );
479
480
				WC()->cart->calculate_totals();
481
482
				wp_send_json( array( 'success' => 'true', 'shipping_methods' => $this->build_shipping_methods( $data ), 'line_items' => $this->build_line_items(), 'total' => WC()->cart->total ) );
483
			} else {
484
				throw new Exception( __( 'Unable to find shipping method for address.', 'woocommerce-gateway-stripe' ) );
485
			}
486
		} catch ( Exception $e ) {
487
			wp_send_json( array( 'success' => 'false', 'shipping_methods' => array(), 'line_items' => $this->build_line_items(), 'total' => WC()->cart->total ) );
488
		}
489
	}
490
491
	/**
492
	 * Updates shipping method on cart session.
493
	 *
494
	 * @since 3.1.0
495
	 * @version 3.1.0
496
	 */
497
	public function update_shipping_method() {
498
		if ( ! defined( 'WOOCOMMERCE_CART' ) ) {
499
			define( 'WOOCOMMERCE_CART', true );
500
		}
501
502
		if ( ! wp_verify_nonce( $_POST['nonce'], '_wc_stripe_apple_pay_update_shipping_method_nonce' ) ) {
503
			wp_die( __( 'Cheatin&#8217; huh?', 'woocommerce-gateway-stripe' ) );
504
		}
505
506
		$selected_shipping_method = array_map( 'wc_clean', $_POST['selected_shipping_method'] );
507
508
		WC()->session->set( 'chosen_shipping_methods', array( $selected_shipping_method['identifier'] ) );
509
510
		WC()->cart->calculate_totals();
511
512
		// Send back the new cart total.
513
		$currency  = get_woocommerce_currency();
514
		$tax_total = max( 0, round( WC()->cart->tax_total + WC()->cart->shipping_tax_total, WC()->cart->dp ) );
515
		$data      = array(
516
			'total' => WC()->cart->total,
517
		);
518
519
		// Include fees and taxes as displayItems.
520 View Code Duplication
		foreach ( WC()->cart->fees as $key => $fee ) {
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...
521
			$data['items'][] = array(
522
				'label'  => $fee->name,
523
				'amount' => array(
524
					'currency' => $currency,
525
					'value'    => $fee->amount,
526
				),
527
			);
528
		}
529 View Code Duplication
		if ( 0 < $tax_total ) {
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...
530
			$data['items'][] = array(
531
				'label'  => __( 'Tax', 'woocommerce-gateway-stripe' ),
532
				'amount' => array(
533
					'currency' => $currency,
534
					'value'    => $tax_total,
535
				),
536
			);
537
		}
538
539
		wp_send_json( array( 'success' => 'true', 'line_items' => $this->build_line_items(), 'total' => WC()->cart->total ) );
540
	}
541
542
	/**
543
	 * Handles the Apple Pay processing via AJAX
544
	 *
545
	 * @access public
546
	 * @since 3.1.0
547
	 * @version 3.1.0
548
	 */
549
	public function process_apple_pay() {
550
		if ( ! wp_verify_nonce( $_POST['nonce'], '_wc_stripe_apple_pay_nonce' ) ) {
551
			wp_die( __( 'Cheatin&#8217; huh?', 'woocommerce-gateway-stripe' ) );
552
		}
553
554
		try {
555
			$result = array_map( 'wc_clean', $_POST['result'] );
556
557
			$order = $this->create_order( $result );
558
559
			$order_id = version_compare( WC_VERSION, '3.0.0', '<' ) ? $order->id : $order->get_id();
560
561
			// Handle payment.
562
			if ( $order->get_total() > 0 ) {
563
564 View Code Duplication
				if ( $order->get_total() * 100 < WC_Stripe::get_minimum_amount() ) {
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...
565
					return new WP_Error( 'stripe_error', sprintf( __( 'Sorry, the minimum allowed order total is %1$s to use this payment method.', 'woocommerce-gateway-stripe' ), wc_price( WC_Stripe::get_minimum_amount() / 100 ) ) );
566
				}
567
568
				WC_Stripe::log( "Info: Begin processing payment for order {$order_id} for the amount of {$order->get_total()}" );
569
570
				// Make the request.
571
				$response = WC_Stripe_API::request( $this->generate_payment_request( $order, $result['token']['id'] ) );
572
573
				if ( is_wp_error( $response ) ) {
574
					$localized_messages = $this->get_localized_messages();
575
576
					throw new Exception( ( isset( $localized_messages[ $response->get_error_code() ] ) ? $localized_messages[ $response->get_error_code() ] : $response->get_error_message() ) );
577
				}
578
579
				// Process valid response.
580
				$this->process_response( $response, $order );
581
			} else {
582
				$order->payment_complete();
583
			}
584
585
			// Remove cart.
586
			WC()->cart->empty_cart();
587
588
			update_post_meta( $order_id, '_customer_user', get_current_user_id() );
589
			update_post_meta( $order_id, '_payment_method_title', __( 'Apple Pay (Stripe)', 'woocommerce-gateway-stripe' ) );
590
591
			// Return thank you page redirect.
592
			wp_send_json( array(
593
				'success'  => 'true',
594
				'redirect' => $this->get_return_url( $order ),
595
			) );
596
597
		} catch ( Exception $e ) {
598
			WC()->session->set( 'refresh_totals', true );
599
			WC_Stripe::log( sprintf( __( 'Error: %s', 'woocommerce-gateway-stripe' ), $e->getMessage() ) );
600
601
			if ( is_object( $order ) && isset( $order_id ) && $order->has_status( array( 'pending', 'failed' ) ) ) {
0 ignored issues
show
Bug introduced by
The variable $order 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...
602
				$this->send_failed_order_email( $order_id );
603
			}
604
605
			wp_send_json( array( 'success' => 'false', 'msg' => $e->getMessage() ) );
606
		}
607
	}
608
609
	/**
610
	 * Generate the request for the payment.
611
	 * @param  WC_Order $order
612
	 * @param string $source token
613
	 * @return array()
0 ignored issues
show
Documentation introduced by
The doc-type array() could not be parsed: Expected "|" or "end of type", but got "(" at position 5. (view supported doc-types)

This check marks PHPDoc comments that could not be parsed by our parser. To see which comment annotations we can parse, please refer to our documentation on supported doc-types.

Loading history...
614
	 */
615
	protected function generate_payment_request( $order, $source ) {
616
		$post_data                = array();
617
		$post_data['currency']    = strtolower( version_compare( WC_VERSION, '3.0.0', '<' ) ? $order->get_order_currency() : $order->get_currency() );
618
		$post_data['amount']      = $this->get_stripe_amount( $order->get_total(), $post_data['currency'] );
619
		$post_data['description'] = sprintf( __( '%1$s - Order %2$s', 'woocommerce-gateway-stripe' ), $this->statement_descriptor, $order->get_order_number() );
620
		$post_data['capture']     = 'yes' === $this->_gateway_settings['capture'] ? 'true' : 'false';
621
622
		$billing_email      = version_compare( WC_VERSION, '3.0.0', '<' ) ? $order->billing_email : $order->get_billing_email();
623
624
		if ( ! empty( $billing_email ) && apply_filters( 'wc_stripe_send_stripe_receipt', false ) ) {
625
			$post_data['receipt_email'] = $billing_email;
626
		}
627
628
		$post_data['expand[]']    = 'balance_transaction';
629
		$post_data['source']      = $source;
630
631
		/**
632
		 * Filter the return value of the WC_Payment_Gateway_CC::generate_payment_request.
633
		 *
634
		 * @since 3.1.0
635
		 * @param array $post_data
636
		 * @param WC_Order $order
637
		 * @param object $source
638
		 */
639
		return apply_filters( 'wc_stripe_generate_payment_request', $post_data, $order );
640
	}
641
642
	/**
643
	 * Builds the shippings methods to pass to Apple Pay.
644
	 *
645
	 * @since 3.1.0
646
	 * @version 3.1.0
647
	 */
648
	public function build_shipping_methods( $shipping_methods ) {
649
		if ( empty( $shipping_methods ) ) {
650
			return array();
651
		}
652
653
		$shipping = array();
654
655
		foreach ( $shipping_methods as $method ) {
656
			$shipping[] = array(
657
				'label'      => $method['label'],
658
				'detail'     => '',
659
				'amount'     => $method['amount']['value'],
660
				'identifier' => $method['id'],
661
			);
662
		}
663
664
		return $shipping;
665
	}
666
667
	/**
668
	 * Builds the line items to pass to Apple Pay.
669
	 *
670
	 * @since 3.1.0
671
	 * @version 3.1.0
672
	 */
673
	public function build_line_items() {
674
		if ( ! defined( 'WOOCOMMERCE_CART' ) ) {
675
			define( 'WOOCOMMERCE_CART', true );
676
		}
677
678
		$decimals = apply_filters( 'wc_stripe_apple_pay_decimals', 2 );
679
		
680
		$items    = array();
681
		$subtotal = 0;
682
683
		foreach ( WC()->cart->get_cart() as $cart_item_key => $values ) {
684
			$amount         = wc_format_decimal( $values['line_subtotal'], $decimals );
685
			$subtotal       += $values['line_subtotal'];
686
			$quantity_label = 1 < $values['quantity'] ? ' (x' . $values['quantity'] . ')' : '';
687
688
			$item = array(
689
				'type'   => 'final',
690
				'label'  => $values['data']->post->post_title . $quantity_label,
691
				'amount' => wc_format_decimal( $amount, $decimals ),
692
			);
693
694
			$items[] = $item;
695
		}
696
697
		// Default show only subtotal instead of itemization.
698
		if ( apply_filters( 'wc_stripe_apple_pay_disable_itemization', true ) ) {
699
			$items = array();
700
			$items[] = array(
701
				'type'   => 'final',
702
				'label'  => __( 'Sub-Total', 'woocommerce-gateway-stripe' ),
703
				'amount' => wc_format_decimal( $subtotal, $decimals ),
704
			);
705
		}
706
707
		$discounts   = wc_format_decimal( WC()->cart->get_cart_discount_total(), $decimals );
708
		$tax         = wc_format_decimal( WC()->cart->tax_total + WC()->cart->shipping_tax_total, $decimals );
709
		$shipping    = wc_format_decimal( WC()->cart->shipping_total, $decimals );
710
		$item_total  = wc_format_decimal( WC()->cart->cart_contents_total, $decimals ) + $discounts;
711
		$order_total = wc_format_decimal( $item_total + $tax + $shipping, $decimals );
0 ignored issues
show
Unused Code introduced by
$order_total 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...
712
713
		if ( wc_tax_enabled() ) {
714
			$items[] = array(
715
				'type'   => 'final',
716
				'label'  => __( 'Tax', 'woocommerce-gateway-stripe' ),
717
				'amount' => $tax,
718
			);
719
		}
720
721 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...
722
			$items[] = array(
723
				'type'   => 'final',
724
				'label'  => __( 'Shipping', 'woocommerce-gateway-stripe' ),
725
				'amount' => $shipping,
726
			);
727
		}
728
729 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...
730
			$items[] = array(
731
				'type'   => 'final',
732
				'label'  => __( 'Discount', 'woocommerce-gateway-stripe' ),
733
				'amount' => '-' . $discounts,
734
			);
735
		}
736
737
		return $items;
738
	}
739
740
	/**
741
	 * Create order programatically.
742
	 *
743
	 * @since 3.1.0
744
	 * @version 3.1.0
745
	 * @param array $data
746
	 * @return object $order
747
	 */
748
	public function create_order( $data = array() ) {
749
		if ( empty( $data ) ) {
750
			throw new Exception( sprintf( __( 'Error %d: Unable to create order. Please try again.', 'woocommerce-gateway-stripe' ), 520 ) );
751
		}
752
753
		$order = wc_create_order();
754
		$order_id = version_compare( WC_VERSION, '3.0.0', '<' ) ? $order->id : $order->get_id();
755
756
		if ( is_wp_error( $order ) ) {
757
			throw new Exception( sprintf( __( 'Error %d: Unable to create order. Please try again.', 'woocommerce-gateway-stripe' ), 520 ) );
758
		} elseif ( false === $order ) {
759
			throw new Exception( sprintf( __( 'Error %d: Unable to create order. Please try again.', 'woocommerce-gateway-stripe' ), 521 ) );
760
		} else {
761
			do_action( 'woocommerce_new_order', $order_id );
762
		}
763
764
		// Store the line items to the new/resumed order
765
		foreach ( WC()->cart->get_cart() as $cart_item_key => $values ) {
766
			$item_id = $order->add_product(
767
				$values['data'],
768
				$values['quantity'],
769
				array(
770
					'variation' => $values['variation'],
771
					'totals'    => array(
772
						'subtotal'     => $values['line_subtotal'],
773
						'subtotal_tax' => $values['line_subtotal_tax'],
774
						'total'        => $values['line_total'],
775
						'tax'          => $values['line_tax'],
776
						'tax_data'     => $values['line_tax_data'], // Since 2.2
777
					),
778
				)
779
			);
780
781
			if ( ! $item_id ) {
782
				throw new Exception( sprintf( __( 'Error %d: Unable to create order. Please try again.', 'woocommerce-gateway-stripe' ), 525 ) );
783
			}
784
785
			// Allow plugins to add order item meta
786 View Code Duplication
			if ( version_compare( WC_VERSION, '3.0', '<' ) ) {
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...
787
				do_action( 'woocommerce_add_order_item_meta', $item_id, $values, $cart_item_key );
788
			} else {
789
				do_action( 'woocommerce_new_order_item', $item_id, wc_get_product( $item_id ), $order->get_id() );
790
			}
791
		}
792
793
		// Store fees
794
		foreach ( WC()->cart->get_fees() as $fee_key => $fee ) {
795
			if ( version_compare( WC_VERSION, '3.0', '<' ) ) {
796
				$item_id = $order->add_fee( $fee );
797
			} else {
798
				$item = new WC_Order_Item_Fee();
799
				$item->set_props( array(
800
					'name'      => $fee->name,
801
					'tax_class' => $fee->taxable ? $fee->tax_class : 0,
802
					'total'     => $fee->amount,
803
					'total_tax' => $fee->tax,
804
					'taxes'     => array(
805
						'total' => $fee->tax_data,
806
					),
807
					'order_id'  => $order->get_id(),
808
				) );
809
				$item_id = $item->save();
810
				$order->add_item( $item );
811
			}
812
813
			if ( ! $item_id ) {
814
				throw new Exception( sprintf( __( 'Error %d: Unable to create order. Please try again.', 'woocommerce-gateway-stripe' ), 526 ) );
815
			}
816
817
			// Allow plugins to add order item meta to fees
818 View Code Duplication
			if ( version_compare( WC_VERSION, '3.0', '<' ) ) {
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...
819
				do_action( 'woocommerce_add_order_fee_meta', $order_id, $item_id, $fee, $fee_key );
820
			} else {
821
				do_action( 'woocommerce_new_order_item', $item_id, $fee, $order->get_id() );
822
			}
823
		}
824
825
		// Store tax rows
826
		foreach ( array_keys( WC()->cart->taxes + WC()->cart->shipping_taxes ) as $tax_rate_id ) {
827
			$tax_amount = WC()->cart->get_tax_amount( $tax_rate_id );
828
			$shipping_tax_amount = WC()->cart->get_shipping_tax_amount( $tax_rate_id );
829
830
			if ( version_compare( WC_VERSION, '3.0', '<' ) ) {
831
				$item_id = $order->add_tax( $tax_rate_id, $tax_amount, $shipping_tax_amount );
832
			} else {
833
				$item = new WC_Order_Item_Tax();
834
				$item->set_props( array(
835
					'rate_id'            => $tax_rate_id,
836
					'tax_total'          => $tax_amount,
837
					'shipping_tax_total' => $shipping_tax_amount,
838
				) );
839
				$item->set_rate( $tax_rate_id );
840
				$item->set_order_id( $order->get_id() );
841
				$item_id = $item->save();
842
				$order->add_item( $item );
843
			}
844
845
			if ( $tax_rate_id && ! $item_id && apply_filters( 'woocommerce_cart_remove_taxes_zero_rate_id', 'zero-rated' ) !== $tax_rate_id ) {
846
				throw new Exception( sprintf( __( 'Error %d: Unable to create order. Please try again.', 'woocommerce-gateway-stripe' ), 528 ) );
847
			}
848
		}
849
850
		// Store coupons
851
		$discount = WC()->cart->get_coupon_discount_amount( $code );
0 ignored issues
show
Bug introduced by
The variable $code seems only to be defined at a later point. Did you maybe move this code here without moving the variable definition?

This error can happen if you refactor code and forget to move the variable initialization.

Let’s take a look at a simple example:

function someFunction() {
    $x = 5;
    echo $x;
}

The above code is perfectly fine. Now imagine that we re-order the statements:

function someFunction() {
    echo $x;
    $x = 5;
}

In that case, $x would be read before it is initialized. This was a very basic example, however the principle is the same for the found issue.

Loading history...
852
		$discount_tax = WC()->cart->get_coupon_discount_tax_amount( $code );
0 ignored issues
show
Bug introduced by
The variable $code seems only to be defined at a later point. Did you maybe move this code here without moving the variable definition?

This error can happen if you refactor code and forget to move the variable initialization.

Let’s take a look at a simple example:

function someFunction() {
    $x = 5;
    echo $x;
}

The above code is perfectly fine. Now imagine that we re-order the statements:

function someFunction() {
    echo $x;
    $x = 5;
}

In that case, $x would be read before it is initialized. This was a very basic example, however the principle is the same for the found issue.

Loading history...
853
854
		foreach ( WC()->cart->get_coupons() as $code => $coupon ) {
855
			if ( version_compare( WC_VERSION, '3.0', '<' ) ) {
856
				$coupon_id = $order->add_coupon( $code, $discount, $discount_tax );
857
			} else {
858
				$item = new WC_Order_Item_Coupon();
859
				$item->set_props( array(
860
					'code'         => $code,
861
					'discount'     => $discount,
862
					'discount_tax' => $discount_tax,
863
					'order_id'     => $order->get_id(),
864
				) );
865
				$coupon_id = $item->save();
866
				$order->add_item( $item );
867
			}
868
869
			if ( ! $coupon_id ) {
870
				throw new Exception( sprintf( __( 'Error %d: Unable to create order. Please try again.', 'woocommerce-gateway-stripe' ), 529 ) );
871
			}
872
		}
873
874
		// Billing address
875
		$billing_address = array();
876
		if ( ! empty( $data['token']['card'] ) ) {
877
			// Name from Stripe is a full name string.
878
			$name                          = explode( ' ', $data['token']['card']['name'] );
879
			$lastname                      = array_pop( $name );
880
			$firstname                     = implode( ' ', $name );
881
			$billing_address['first_name'] = $firstname;
882
			$billing_address['last_name']  = $lastname;
883
			$billing_address['email']      = $data['shippingContact']['emailAddress'];
884
			$billing_address['phone']      = $data['shippingContact']['phoneNumber'];
885
			$billing_address['country']    = $data['token']['card']['country'];
886
			$billing_address['address_1']  = $data['token']['card']['address_line1'];
887
			$billing_address['address_2']  = $data['token']['card']['address_line2'];
888
			$billing_address['city']       = $data['token']['card']['address_city'];
889
			$billing_address['state']      = $data['token']['card']['address_state'];
890
			$billing_address['postcode']   = $data['token']['card']['address_zip'];
891
		}
892
893
		// Shipping address.
894
		$shipping_address = array();
895
		if ( WC()->cart->needs_shipping() && ! empty( $data['shippingContact'] ) ) {
896
			$shipping_address['first_name'] = $data['shippingContact']['givenName'];
897
			$shipping_address['last_name']  = $data['shippingContact']['familyName'];
898
			$shipping_address['email']      = $data['shippingContact']['emailAddress'];
899
			$shipping_address['phone']      = $data['shippingContact']['phoneNumber'];
900
			$shipping_address['country']    = $data['shippingContact']['countryCode'];
901
			$shipping_address['address_1']  = $data['shippingContact']['addressLines'][0];
902
			$shipping_address['address_2']  = $data['shippingContact']['addressLines'][1];
903
			$shipping_address['city']       = $data['shippingContact']['locality'];
904
			$shipping_address['state']      = $data['shippingContact']['administrativeArea'];
905
			$shipping_address['postcode']   = $data['shippingContact']['postalCode'];
906
		} elseif ( ! empty( $data['shippingContact'] ) ) {
907
			$shipping_address['first_name'] = $firstname;
0 ignored issues
show
Bug introduced by
The variable $firstname 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...
908
			$shipping_address['last_name']  = $lastname;
0 ignored issues
show
Bug introduced by
The variable $lastname 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...
909
			$shipping_address['email']      = $data['shippingContact']['emailAddress'];
910
			$shipping_address['phone']      = $data['shippingContact']['phoneNumber'];
911
			$shipping_address['country']    = $data['token']['card']['country'];
912
			$shipping_address['address_1']  = $data['token']['card']['address_line1'];
913
			$shipping_address['address_2']  = $data['token']['card']['address_line2'];
914
			$shipping_address['city']       = $data['token']['card']['address_city'];
915
			$shipping_address['state']      = $data['token']['card']['address_state'];
916
			$shipping_address['postcode']   = $data['token']['card']['address_zip'];
917
		}
918
919
		$order->set_address( $billing_address, 'billing' );
920
		$order->set_address( $shipping_address, 'shipping' );
921
922
		WC()->shipping->calculate_shipping( WC()->cart->get_shipping_packages() );
923
924
		// Get the rate object selected by user.
925
		foreach ( WC()->shipping->get_packages() as $package_key => $package ) {
926
			foreach ( $package['rates'] as $key => $rate ) {
927
				// Loop through user chosen shipping methods.
928
				foreach ( WC()->session->get( 'chosen_shipping_methods' ) as $method ) {
929
					if ( $method === $key ) {
930
						if ( version_compare( WC_VERSION, '3.0', '<' ) ) {
931
							$order->add_shipping( $rate );
932
						} else {
933
							$item = new WC_Order_Item_Shipping();
934
							$item->set_props( array(
935
								'method_title' => $rate->label,
936
								'method_id'    => $rate->id,
937
								'total'        => wc_format_decimal( $rate->cost ),
938
								'taxes'        => $rate->taxes,
939
								'order_id'     => $order->get_id(),
940
							) );
941
							foreach ( $rate->get_meta_data() as $key => $value ) {
942
								$item->add_meta_data( $key, $value, true );
943
							}
944
							$item->save();
945
							$order->add_item( $item );
946
						}
947
					}
948
				}
949
			}
950
		}
951
952
		$available_gateways = WC()->payment_gateways->get_available_payment_gateways();
953
		$order->set_payment_method( $available_gateways['stripe'] );
954
		$order->set_total( WC()->cart->shipping_total, 'shipping' );
955
		$order->set_total( WC()->cart->get_cart_discount_total(), 'cart_discount' );
956
		$order->set_total( WC()->cart->get_cart_discount_tax_total(), 'cart_discount_tax' );
957
		$order->set_total( WC()->cart->tax_total, 'tax' );
958
		$order->set_total( WC()->cart->shipping_tax_total, 'shipping_tax' );
959
		$order->set_total( WC()->cart->total );
960
961
		// If we got here, the order was created without problems!
962
		wc_transaction_query( 'commit' );
963
964
		return $order;
965
	}
966
}
967
968
new WC_Stripe_Apple_Pay();
969