Completed
Push — master ( 86871a...1968f4 )
by Roy
02:10
created

WC_Stripe_Payment_Request::calculate_shipping()   C

Complexity

Conditions 7
Paths 16

Size

Total Lines 49
Code Lines 34

Duplication

Lines 14
Ratio 28.57 %

Importance

Changes 0
Metric Value
dl 14
loc 49
rs 6.7272
c 0
b 0
f 0
cc 7
eloc 34
nc 16
nop 1
1
<?php
2
/**
3
 * Stripe Payment Request API
4
 *
5
 * @package WooCommerce_Stripe/Classes/Payment_Request
6
 * @since   3.1.0
7
 * @version 3.1.0
8
 */
9
10
if ( ! defined( 'ABSPATH' ) ) {
11
	exit;
12
}
13
14
/**
15
 * WC_Stripe_Payment_Request class.
16
 */
17
class WC_Stripe_Payment_Request {
18
19
	/**
20
	 * Initialize class actions.
21
	 */
22
	public function __construct() {
23
		add_action( 'wp_enqueue_scripts', array( $this, 'scripts' ) );
24
25
		add_action( 'wc_ajax_wc_stripe_get_cart_details', array( $this, 'ajax_get_cart_details' ) );
26
		add_action( 'wc_ajax_wc_stripe_get_shipping_options', array( $this, 'ajax_get_shipping_options' ) );
27
		add_action( 'wc_ajax_wc_stripe_update_shipping_method', array( $this, 'ajax_update_shipping_method' ) );
28
		add_action( 'wc_ajax_wc_stripe_create_order', array( $this, 'ajax_create_order' ) );
29
	}
30
31
	/**
32
	 * Check if Stripe gateway is enabled.
33
	 *
34
	 * @return bool
35
	 */
36
	protected function is_activated() {
37
		$options             = get_option( 'woocommerce_stripe_settings', array() );
38
		$enabled             = isset( $options['enabled'] ) && 'yes' === $options['enabled'];
39
		$stripe_checkout     = isset( $options['stripe_checkout'] ) && 'yes' !== $options['stripe_checkout'];
40
		$request_payment_api = isset( $options['request_payment_api'] ) && 'yes' === $options['request_payment_api'];
41
42
		return $enabled && $stripe_checkout && $request_payment_api && is_ssl();
43
	}
44
45
	/**
46
	 * Get publishable key.
47
	 *
48
	 * @return string
49
	 */
50
	protected function get_publishable_key() {
51
		$options = get_option( 'woocommerce_stripe_settings', array() );
52
53
		if ( empty( $options ) ) {
54
			return '';
55
		}
56
57
		return 'yes' === $options['testmode'] ? $options['test_publishable_key'] : $options['publishable_key'];
58
	}
59
60
	/**
61
	 * Load public scripts.
62
	 */
63
	public function scripts() {
64
		// Load PaymentRequest only on cart for now.
65
		if ( ! is_cart() ) {
66
			return;
67
		}
68
69
		if ( ! $this->is_activated() ) {
70
			return;
71
		}
72
73
		$suffix = defined( 'SCRIPT_DEBUG' ) && SCRIPT_DEBUG ? '' : '.min';
74
75
		wp_enqueue_script( 'stripe', 'https://js.stripe.com/v2/', '', '1.0', true );
76
		wp_enqueue_script( 'google-payment-request-shim', 'https://storage.googleapis.com/prshim/v1/payment-shim.js', '', '1.0', false );
77
		wp_enqueue_script( 'wc-stripe-payment-request', plugins_url( 'assets/js/payment-request' . $suffix . '.js', WC_STRIPE_MAIN_FILE ), array( 'jquery', 'stripe' ), WC_STRIPE_VERSION, true );
78
79
		wp_localize_script(
80
			'wc-stripe-payment-request',
81
			'wcStripePaymentRequestParams',
82
			array(
83
				'ajax_url' => WC_AJAX::get_endpoint( '%%endpoint%%' ),
84
				'stripe'   => array(
85
					'key'                => $this->get_publishable_key(),
86
					'allow_prepaid_card' => apply_filters( 'wc_stripe_allow_prepaid_card', true ) ? 'yes' : 'no',
87
				),
88
				'nonce'    => array(
89
					'payment'         => wp_create_nonce( 'wc-stripe-payment-request' ),
90
					'shipping'        => wp_create_nonce( 'wc-stripe-payment-request-shipping' ),
91
					'update_shipping' => wp_create_nonce( 'wc-stripe-update-shipping-method' ),
92
					'checkout'        => wp_create_nonce( 'woocommerce-process_checkout' ),
93
				),
94
				'i18n'     => array(
95
					'no_prepaid_card'  => __( 'Sorry, we\'re not accepting prepaid cards at this time.', 'woocommerce-gateway-stripe' ),
96
					/* translators: Do not translate the [option] placeholder */
97
					'unknown_shipping' => __( 'Unknown shipping option "[option]".', 'woocommerce-gateway-stripe' ),
98
				),
99
			)
100
		);
101
	}
102
103
	/**
104
	 * Get cart details.
105
	 */
106
	public function ajax_get_cart_details() {
107
		check_ajax_referer( 'wc-stripe-payment-request', 'security' );
108
109
		if ( ! defined( 'WOOCOMMERCE_CART' ) ) {
110
			define( 'WOOCOMMERCE_CART', true );
111
		}
112
113
		WC()->cart->calculate_totals();
114
115
		$currency = get_woocommerce_currency();
116
117
		// Set mandatory payment details.
118
		$data = array(
119
			'shipping_required' => WC()->cart->needs_shipping(),
120
			'order_data'        => array(
121
				'total' => array(
122
					'label'  => __( 'Total', 'woocommerce-gateway-stripe' ),
123
					'amount' => array(
124
						'value'    => max( 0, apply_filters( 'woocommerce_calculated_total', round( WC()->cart->cart_contents_total + WC()->cart->fee_total, WC()->cart->dp ), WC()->cart ) ),
125
						'currency' => $currency,
126
					),
127
				),
128
			),
129
		);
130
131
		wp_send_json( $data );
132
	}
133
134
	/**
135
	 * Calculate and set shipping method.
136
	 *
137
	 * @since 3.1.0
138
	 * @version 3.1.0
139
	 * @param array $address
140
	 */
141
	public function calculate_shipping( $address = array() ) {
142
		$country   = $address['country'];
143
		$state     = $address['state'];
144
		$postcode  = $address['postcode'];
145
		$city      = $address['city'];
146
		$address_1 = $address['address'];
147
		$address_2 = $address['address_2'];
148
149
		WC()->shipping->reset_shipping();
150
151
		if ( $postcode && WC_Validation::is_postcode( $postcode, $country ) ) {
152
			$postcode = wc_format_postcode( $postcode, $country );
153
		}
154
155 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...
156
			WC()->customer->set_location( $country, $state, $postcode, $city );
157
			WC()->customer->set_shipping_location( $country, $state, $postcode, $city );
158
		} else {
159
			WC()->customer->set_to_base();
160
			WC()->customer->set_shipping_to_base();
161
		}
162
163
		WC()->customer->calculated_shipping( true );
164
165
		$packages = array();
166
167
		$packages[0]['contents']                 = WC()->cart->get_cart();
168
		$packages[0]['contents_cost']            = 0;
169
		$packages[0]['applied_coupons']          = WC()->cart->applied_coupons;
170
		$packages[0]['user']['ID']               = get_current_user_id();
171
		$packages[0]['destination']['country']   = $country;
172
		$packages[0]['destination']['state']     = $state;
173
		$packages[0]['destination']['postcode']  = $postcode;
174
		$packages[0]['destination']['city']      = $city;
175
		$packages[0]['destination']['address']   = $address_1;
176
		$packages[0]['destination']['address_2'] = $address_2;
177
178 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...
179
			if ( $item['data']->needs_shipping() ) {
180
				if ( isset( $item['line_total'] ) ) {
181
					$packages[0]['contents_cost'] += $item['line_total'];
182
				}
183
			}
184
		}
185
186
		$packages = apply_filters( 'woocommerce_cart_shipping_packages', $packages );
187
188
		WC()->shipping->calculate_shipping( $packages );
189
	}
190
191
	/**
192
	 * Get shipping options.
193
	 *
194
	 * @see WC_Cart::get_shipping_packages().
195
	 * @see WC_Shipping::calculate_shipping().
196
	 * @see WC_Shipping::get_packages().
197
	 */
198
	public function ajax_get_shipping_options() {
199
		check_ajax_referer( 'wc-stripe-payment-request-shipping', 'security' );
200
201
		// Set the shipping package.
202
		$posted   = filter_input_array( INPUT_POST, array(
203
			'country'   => FILTER_SANITIZE_ENCODED,
204
			'state'     => FILTER_SANITIZE_STRING,
205
			'postcode'  => FILTER_SANITIZE_ENCODED,
206
			'city'      => FILTER_SANITIZE_STRING,
207
			'address'   => FILTER_SANITIZE_STRING,
208
			'address_2' => FILTER_SANITIZE_STRING,
209
		) );
210
211
		$this->calculate_shipping( $posted );
212
213
		// Set the shipping options.
214
		$currency = get_woocommerce_currency();
215
		$data     = array();
216
217
		$packages = WC()->shipping->get_packages();
218
219
		if ( ! empty( $packages ) && WC()->customer->has_calculated_shipping() ) {
220
			foreach ( $packages as $package_key => $package ) {
221
				if ( empty( $package['rates'] ) ) {
222
					break;
223
				}
224
225
				foreach ( $package['rates'] as $key => $rate ) {
226
					$data[] = array(
227
						'id'       => $rate->id,
228
						'label'    => $rate->label,
229
						'amount'   => array(
230
							'currency' => $currency,
231
							'value'    => $rate->cost,
232
						),
233
						'selected' => false,
234
					);
235
				}
236
			}
237
		}
238
239
		// Auto select when have only one shipping method available.
240
		if ( 1 === count( $data ) ) {
241
			$data[0]['selected'] = true;
242
		}
243
244
		wp_send_json( $data );
245
	}
246
247
	/**
248
	 * Update shipping method.
249
	 */
250
	public function ajax_update_shipping_method() {
251
		check_ajax_referer( 'wc-stripe-update-shipping-method', 'security' );
252
253
		if ( ! defined( 'WOOCOMMERCE_CART' ) ) {
254
			define( 'WOOCOMMERCE_CART', true );
255
		}
256
257
		$chosen_shipping_methods = WC()->session->get( 'chosen_shipping_methods' );
258
		$shipping_method         = filter_input( INPUT_POST, 'shipping_method', FILTER_DEFAULT, FILTER_REQUIRE_ARRAY );
259
260
		if ( is_array( $shipping_method ) ) {
261
			foreach ( $shipping_method as $i => $value ) {
262
				$chosen_shipping_methods[ $i ] = wc_clean( $value );
263
			}
264
		}
265
266
		WC()->session->set( 'chosen_shipping_methods', $chosen_shipping_methods );
267
268
		WC()->cart->calculate_totals();
269
270
		// Send back the new cart total.
271
		$currency  = get_woocommerce_currency();
272
		$tax_total = max( 0, round( WC()->cart->tax_total + WC()->cart->shipping_tax_total, WC()->cart->dp ) );
273
		$data      = array(
274
			'total' => WC()->cart->total,
275
		);
276
277
		// Include fees and taxes as displayItems.
278 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...
279
			$data['items'][] = array(
280
				'label'  => $fee->name,
281
				'amount' => array(
282
					'currency' => $currency,
283
					'value'    => $fee->amount,
284
				),
285
			);
286
		}
287 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...
288
			$data['items'][] = array(
289
				'label'  => __( 'Tax', 'woocommerce-gateway-stripe' ),
290
				'amount' => array(
291
					'currency' => $currency,
292
					'value'    => $tax_total,
293
				),
294
			);
295
		}
296
297
		wp_send_json( $data );
298
	}
299
300
	/**
301
	 * Create order.
302
	 */
303
	public function ajax_create_order() {
304
		if ( WC()->cart->is_empty() ) {
305
			wp_send_json_error( __( 'Empty cart', 'woocommerce-gateway-stripe' ) );
306
		}
307
308
		if ( ! defined( 'WOOCOMMERCE_CHECKOUT' ) ) {
309
			define( 'WOOCOMMERCE_CHECKOUT', true );
310
		}
311
312
		WC()->checkout()->process_checkout();
313
314
		die( 0 );
315
	}
316
}
317
318
new WC_Stripe_Payment_Request();
319