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