|
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->tax_total, WC()->cart->dp ), WC()->cart ) ), |
|
125
|
|
|
'currency' => $currency, |
|
126
|
|
|
), |
|
127
|
|
|
), |
|
128
|
|
|
// Include line items such as subtotal, fees and taxes. No shipping option is provided here because it is not chosen yet. |
|
129
|
|
|
'displayItems' => $this->compute_display_items( null ), |
|
130
|
|
|
), |
|
131
|
|
|
); |
|
132
|
|
|
|
|
133
|
|
|
wp_send_json( $data ); |
|
134
|
|
|
} |
|
135
|
|
|
|
|
136
|
|
|
/** |
|
137
|
|
|
* Calculate and set shipping method. |
|
138
|
|
|
* |
|
139
|
|
|
* @since 3.1.0 |
|
140
|
|
|
* @version 3.1.0 |
|
141
|
|
|
* @param array $address |
|
142
|
|
|
*/ |
|
143
|
|
|
public function calculate_shipping( $address = array() ) { |
|
144
|
|
|
$country = $address['country']; |
|
145
|
|
|
$state = $address['state']; |
|
146
|
|
|
$postcode = $address['postcode']; |
|
147
|
|
|
$city = $address['city']; |
|
148
|
|
|
$address_1 = $address['address']; |
|
149
|
|
|
$address_2 = $address['address_2']; |
|
150
|
|
|
|
|
151
|
|
|
WC()->shipping->reset_shipping(); |
|
152
|
|
|
|
|
153
|
|
|
if ( $postcode && WC_Validation::is_postcode( $postcode, $country ) ) { |
|
154
|
|
|
$postcode = wc_format_postcode( $postcode, $country ); |
|
155
|
|
|
} |
|
156
|
|
|
|
|
157
|
|
View Code Duplication |
if ( $country ) { |
|
|
|
|
|
|
158
|
|
|
WC()->customer->set_location( $country, $state, $postcode, $city ); |
|
159
|
|
|
WC()->customer->set_shipping_location( $country, $state, $postcode, $city ); |
|
160
|
|
|
} else { |
|
161
|
|
|
WC()->customer->set_to_base(); |
|
162
|
|
|
WC()->customer->set_shipping_to_base(); |
|
163
|
|
|
} |
|
164
|
|
|
|
|
165
|
|
|
if ( version_compare( WC_VERSION, '3.0', '<' ) ) { |
|
166
|
|
|
WC()->customer->calculated_shipping( true ); |
|
167
|
|
|
} else { |
|
168
|
|
|
WC()->customer->set_calculated_shipping( true ); |
|
169
|
|
|
WC()->customer->save(); |
|
170
|
|
|
} |
|
171
|
|
|
|
|
172
|
|
|
$packages = array(); |
|
173
|
|
|
|
|
174
|
|
|
$packages[0]['contents'] = WC()->cart->get_cart(); |
|
175
|
|
|
$packages[0]['contents_cost'] = 0; |
|
176
|
|
|
$packages[0]['applied_coupons'] = WC()->cart->applied_coupons; |
|
177
|
|
|
$packages[0]['user']['ID'] = get_current_user_id(); |
|
178
|
|
|
$packages[0]['destination']['country'] = $country; |
|
179
|
|
|
$packages[0]['destination']['state'] = $state; |
|
180
|
|
|
$packages[0]['destination']['postcode'] = $postcode; |
|
181
|
|
|
$packages[0]['destination']['city'] = $city; |
|
182
|
|
|
$packages[0]['destination']['address'] = $address_1; |
|
183
|
|
|
$packages[0]['destination']['address_2'] = $address_2; |
|
184
|
|
|
|
|
185
|
|
View Code Duplication |
foreach ( WC()->cart->get_cart() as $item ) { |
|
|
|
|
|
|
186
|
|
|
if ( $item['data']->needs_shipping() ) { |
|
187
|
|
|
if ( isset( $item['line_total'] ) ) { |
|
188
|
|
|
$packages[0]['contents_cost'] += $item['line_total']; |
|
189
|
|
|
} |
|
190
|
|
|
} |
|
191
|
|
|
} |
|
192
|
|
|
|
|
193
|
|
|
$packages = apply_filters( 'woocommerce_cart_shipping_packages', $packages ); |
|
194
|
|
|
|
|
195
|
|
|
WC()->shipping->calculate_shipping( $packages ); |
|
196
|
|
|
} |
|
197
|
|
|
|
|
198
|
|
|
/** |
|
199
|
|
|
* Get shipping options. |
|
200
|
|
|
* |
|
201
|
|
|
* @see WC_Cart::get_shipping_packages(). |
|
202
|
|
|
* @see WC_Shipping::calculate_shipping(). |
|
203
|
|
|
* @see WC_Shipping::get_packages(). |
|
204
|
|
|
*/ |
|
205
|
|
|
public function ajax_get_shipping_options() { |
|
206
|
|
|
check_ajax_referer( 'wc-stripe-payment-request-shipping', 'security' ); |
|
207
|
|
|
|
|
208
|
|
|
// Set the shipping package. |
|
209
|
|
|
$posted = filter_input_array( INPUT_POST, array( |
|
210
|
|
|
'country' => FILTER_SANITIZE_STRING, |
|
211
|
|
|
'state' => FILTER_SANITIZE_STRING, |
|
212
|
|
|
'postcode' => FILTER_SANITIZE_STRING, |
|
213
|
|
|
'city' => FILTER_SANITIZE_STRING, |
|
214
|
|
|
'address' => FILTER_SANITIZE_STRING, |
|
215
|
|
|
'address_2' => FILTER_SANITIZE_STRING, |
|
216
|
|
|
) ); |
|
217
|
|
|
|
|
218
|
|
|
$this->calculate_shipping( $posted ); |
|
219
|
|
|
|
|
220
|
|
|
// Set the shipping options. |
|
221
|
|
|
$currency = get_woocommerce_currency(); |
|
222
|
|
|
$data = array(); |
|
223
|
|
|
|
|
224
|
|
|
$packages = WC()->shipping->get_packages(); |
|
225
|
|
|
|
|
226
|
|
|
if ( ! empty( $packages ) && WC()->customer->has_calculated_shipping() ) { |
|
227
|
|
|
foreach ( $packages as $package_key => $package ) { |
|
228
|
|
|
if ( empty( $package['rates'] ) ) { |
|
229
|
|
|
break; |
|
230
|
|
|
} |
|
231
|
|
|
|
|
232
|
|
View Code Duplication |
foreach ( $package['rates'] as $key => $rate ) { |
|
|
|
|
|
|
233
|
|
|
$data[] = array( |
|
234
|
|
|
'id' => $rate->id, |
|
235
|
|
|
'label' => $rate->label, |
|
236
|
|
|
'amount' => array( |
|
237
|
|
|
'currency' => $currency, |
|
238
|
|
|
'value' => $rate->cost, |
|
239
|
|
|
), |
|
240
|
|
|
'selected' => false, |
|
241
|
|
|
); |
|
242
|
|
|
} |
|
243
|
|
|
} |
|
244
|
|
|
} |
|
245
|
|
|
|
|
246
|
|
|
// Auto select when have only one shipping method available. |
|
247
|
|
|
if ( 1 === count( $data ) ) { |
|
248
|
|
|
$data[0]['selected'] = true; |
|
249
|
|
|
} |
|
250
|
|
|
|
|
251
|
|
|
wp_send_json( $data ); |
|
252
|
|
|
} |
|
253
|
|
|
|
|
254
|
|
|
/** |
|
255
|
|
|
* Update shipping method. |
|
256
|
|
|
*/ |
|
257
|
|
|
public function ajax_update_shipping_method() { |
|
258
|
|
|
check_ajax_referer( 'wc-stripe-update-shipping-method', 'security' ); |
|
259
|
|
|
|
|
260
|
|
|
if ( ! defined( 'WOOCOMMERCE_CART' ) ) { |
|
261
|
|
|
define( 'WOOCOMMERCE_CART', true ); |
|
262
|
|
|
} |
|
263
|
|
|
|
|
264
|
|
|
$chosen_shipping_methods = WC()->session->get( 'chosen_shipping_methods' ); |
|
265
|
|
|
$shipping_method = filter_input( INPUT_POST, 'shipping_method', FILTER_DEFAULT, FILTER_REQUIRE_ARRAY ); |
|
266
|
|
|
|
|
267
|
|
|
if ( is_array( $shipping_method ) ) { |
|
268
|
|
|
foreach ( $shipping_method as $i => $value ) { |
|
269
|
|
|
$chosen_shipping_methods[ $i ] = wc_clean( $value ); |
|
270
|
|
|
} |
|
271
|
|
|
} |
|
272
|
|
|
|
|
273
|
|
|
WC()->session->set( 'chosen_shipping_methods', $chosen_shipping_methods ); |
|
274
|
|
|
|
|
275
|
|
|
WC()->cart->calculate_totals(); |
|
276
|
|
|
|
|
277
|
|
|
// Send back the new cart total and line items to be displayed, such as subtotal, shipping rate(s), fees and taxes. |
|
278
|
|
|
$data = array( |
|
279
|
|
|
'total' => WC()->cart->total, |
|
280
|
|
|
'items' => $this->compute_display_items( $shipping_method[0] ), |
|
281
|
|
|
); |
|
282
|
|
|
|
|
283
|
|
|
wp_send_json( $data ); |
|
284
|
|
|
} |
|
285
|
|
|
|
|
286
|
|
|
/** |
|
287
|
|
|
* Create order. |
|
288
|
|
|
*/ |
|
289
|
|
|
public function ajax_create_order() { |
|
290
|
|
|
if ( WC()->cart->is_empty() ) { |
|
291
|
|
|
wp_send_json_error( __( 'Empty cart', 'woocommerce-gateway-stripe' ) ); |
|
292
|
|
|
} |
|
293
|
|
|
|
|
294
|
|
|
if ( ! defined( 'WOOCOMMERCE_CHECKOUT' ) ) { |
|
295
|
|
|
define( 'WOOCOMMERCE_CHECKOUT', true ); |
|
296
|
|
|
} |
|
297
|
|
|
|
|
298
|
|
|
$_POST['terms'] = 1; |
|
299
|
|
|
|
|
300
|
|
|
WC()->checkout()->process_checkout(); |
|
301
|
|
|
|
|
302
|
|
|
die( 0 ); |
|
303
|
|
|
} |
|
304
|
|
|
|
|
305
|
|
|
/** |
|
306
|
|
|
* Compute display items to be included in the 'displayItems' key of the PaymentDetails. |
|
307
|
|
|
* |
|
308
|
|
|
* @param string shipping_method_id If shipping method ID is provided, will include display items about shipping. |
|
309
|
|
|
*/ |
|
310
|
|
|
protected function compute_display_items( $shipping_method_id ) { |
|
311
|
|
|
$currency = get_woocommerce_currency(); |
|
312
|
|
|
$items = array( |
|
313
|
|
|
// Subtotal excluding tax, because taxes is a separate item, below. |
|
314
|
|
|
array( |
|
315
|
|
|
'label' => __( 'Subtotal', 'woocommerce-gateway-stripe' ), |
|
316
|
|
|
'amount' => array( |
|
317
|
|
|
'value' => max( 0, round( WC()->cart->subtotal_ex_tax, WC()->cart->dp ) ), |
|
318
|
|
|
'currency' => $currency, |
|
319
|
|
|
), |
|
320
|
|
|
), |
|
321
|
|
|
); |
|
322
|
|
|
// If a chosen shipping option was provided, add line item(s) for it and include the shipping tax. |
|
323
|
|
|
$tax_total = max( 0, round( WC()->cart->tax_total, WC()->cart->dp ) ); |
|
324
|
|
|
if ( $shipping_method_id ) { |
|
325
|
|
|
$tax_total = max( 0, round( WC()->cart->tax_total + WC()->cart->shipping_tax_total, WC()->cart->dp ) ); |
|
326
|
|
|
// Look through the package rates for $shipping_method_id, and when found, add a line item. |
|
327
|
|
|
foreach ( WC()->shipping->get_packages() as $package_key => $package ) { |
|
328
|
|
|
foreach ( $package['rates'] as $key => $rate ) { |
|
329
|
|
|
if ( $rate->id == $shipping_method_id ) { |
|
330
|
|
|
$items[] = array( |
|
331
|
|
|
'label' => $rate->label, |
|
332
|
|
|
'amount' => array( |
|
333
|
|
|
'value' => $rate->cost, |
|
334
|
|
|
'currency' => $currency, |
|
335
|
|
|
), |
|
336
|
|
|
); |
|
337
|
|
|
break; |
|
338
|
|
|
} |
|
339
|
|
|
} |
|
340
|
|
|
} |
|
341
|
|
|
} |
|
342
|
|
|
// Include fees and taxes as display items. |
|
343
|
|
View Code Duplication |
foreach ( WC()->cart->fees as $key => $fee ) { |
|
|
|
|
|
|
344
|
|
|
$items[] = array( |
|
345
|
|
|
'label' => $fee->name, |
|
346
|
|
|
'amount' => array( |
|
347
|
|
|
'currency' => $currency, |
|
348
|
|
|
'value' => $fee->amount, |
|
349
|
|
|
), |
|
350
|
|
|
); |
|
351
|
|
|
} |
|
352
|
|
|
// The tax total may include the shipping taxes if a shipping option is provided. |
|
353
|
|
View Code Duplication |
if ( 0 < $tax_total ) { |
|
|
|
|
|
|
354
|
|
|
$items[] = array( |
|
355
|
|
|
'label' => __( 'Tax', 'woocommerce-gateway-stripe' ), |
|
356
|
|
|
'amount' => array( |
|
357
|
|
|
'currency' => $currency, |
|
358
|
|
|
'value' => $tax_total, |
|
359
|
|
|
), |
|
360
|
|
|
); |
|
361
|
|
|
} |
|
362
|
|
|
return $items; |
|
363
|
|
|
} |
|
364
|
|
|
} |
|
365
|
|
|
|
|
366
|
|
|
new WC_Stripe_Payment_Request(); |
|
367
|
|
|
|
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.