Completed
Pull Request — master (#379)
by Brandon
03:53
created

woocommerce-gateway-stripe.php (7 issues)

Upgrade to new PHP Analysis Engine

These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more

1
<?php
2
/*
3
 * Plugin Name: WooCommerce Stripe Gateway
4
 * Plugin URI: https://wordpress.org/plugins/woocommerce-gateway-stripe/
5
 * Description: Take credit card payments on your store using Stripe.
6
 * Author: WooCommerce
7
 * Author URI: https://woocommerce.com/
8
 * Version: 3.2.3
9
 * Requires at least: 4.4
10
 * Tested up to: 4.8
11
 * WC requires at least: 2.5
12
 * WC tested up to: 3.1
13
 * Text Domain: woocommerce-gateway-stripe
14
 * Domain Path: /languages
15
 *
16
 * Copyright (c) 2017 WooCommerce
17
 *
18
 * This program is free software: you can redistribute it and/or modify
19
 * it under the terms of the GNU General Public License as published by
20
 * the Free Software Foundation, either version 3 of the License, or
21
 * (at your option) any later version.
22
 *
23
 * This program is distributed in the hope that it will be useful,
24
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
25
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
26
 * GNU General Public License for more details.
27
 *
28
 * You should have received a copy of the GNU General Public License
29
 * along with this program. If not, see <http://www.gnu.org/licenses/>.
30
*/
31
32
if ( ! defined( 'ABSPATH' ) ) {
33
	exit;
34
}
35
36
/**
37
 * Required minimums and constants
38
 */
39
define( 'WC_STRIPE_VERSION', '3.2.3' );
40
define( 'WC_STRIPE_MIN_PHP_VER', '5.6.0' );
41
define( 'WC_STRIPE_MIN_WC_VER', '2.5.0' );
42
define( 'WC_STRIPE_MAIN_FILE', __FILE__ );
43
define( 'WC_STRIPE_PLUGIN_URL', untrailingslashit( plugins_url( basename( plugin_dir_path( __FILE__ ) ), basename( __FILE__ ) ) ) );
44
define( 'WC_STRIPE_PLUGIN_PATH', untrailingslashit( plugin_dir_path( __FILE__ ) ) );
45
46
if ( ! class_exists( 'WC_Stripe' ) ) :
47
48
	class WC_Stripe {
49
50
		/**
51
		 * @var Singleton The reference the *Singleton* instance of this class
52
		 */
53
		private static $instance;
54
55
		/**
56
		 * @var Reference to logging class.
57
		 */
58
		private static $log;
59
60
		/**
61
		 * Returns the *Singleton* instance of this class.
62
		 *
63
		 * @return Singleton The *Singleton* instance.
64
		 */
65
		public static function get_instance() {
66
			if ( null === self::$instance ) {
67
				self::$instance = new self();
0 ignored issues
show
Documentation Bug introduced by
It seems like new self() of type object<WC_Stripe> is incompatible with the declared type object<Singleton> of property $instance.

Our type inference engine has found an assignment to a property that is incompatible with the declared type of that property.

Either this assignment is in error or the assigned type should be added to the documentation/type hint for that property..

Loading history...
68
			}
69
			return self::$instance;
0 ignored issues
show
Bug Compatibility introduced by
The expression self::$instance; of type WC_Stripe|Singleton adds the type WC_Stripe to the return on line 69 which is incompatible with the return type documented by WC_Stripe::get_instance of type Singleton.
Loading history...
70
		}
71
72
		/**
73
		 * Private clone method to prevent cloning of the instance of the
74
		 * *Singleton* instance.
75
		 *
76
		 * @return void
77
		 */
78
		private function __clone() {}
79
80
		/**
81
		 * Private unserialize method to prevent unserializing of the *Singleton*
82
		 * instance.
83
		 *
84
		 * @return void
85
		 */
86
		private function __wakeup() {}
87
88
		/**
89
		 * Flag to indicate whether or not we need to load code for / support subscriptions.
90
		 *
91
		 * @var bool
92
		 */
93
		private $subscription_support_enabled = false;
94
95
		/**
96
		 * Flag to indicate whether or not we need to load support for pre-orders.
97
		 *
98
		 * @since 3.0.3
99
		 *
100
		 * @var bool
101
		 */
102
		private $pre_order_enabled = false;
103
104
		/**
105
		 * Notices (array)
106
		 * @var array
107
		 */
108
		public $notices = array();
109
110
		/**
111
		 * Protected constructor to prevent creating a new instance of the
112
		 * *Singleton* via the `new` operator from outside of this class.
113
		 */
114
		protected function __construct() {
115
			add_action( 'admin_init', array( $this, 'check_environment' ) );
116
			add_action( 'admin_notices', array( $this, 'admin_notices' ), 15 );
117
			add_action( 'plugins_loaded', array( $this, 'init' ) );
118
		}
119
120
		/**
121
		 * Init the plugin after plugins_loaded so environment variables are set.
122
		 */
123
		public function init() {
124
			// Don't hook anything else in the plugin if we're in an incompatible environment
125
			if ( self::get_environment_warning() ) {
126
				return;
127
			}
128
129
			include_once( dirname( __FILE__ ) . '/includes/class-wc-stripe-api.php' );
130
			include_once( dirname( __FILE__ ) . '/includes/class-wc-stripe-customer.php' );
131
132
			// Init the gateway itself
133
			$this->init_gateways();
134
135
			add_filter( 'plugin_action_links_' . plugin_basename( __FILE__ ), array( $this, 'plugin_action_links' ) );
136
			add_action( 'woocommerce_order_status_on-hold_to_processing', array( $this, 'capture_payment' ) );
137
			add_action( 'woocommerce_order_status_on-hold_to_completed', array( $this, 'capture_payment' ) );
138
			add_action( 'woocommerce_order_status_on-hold_to_cancelled', array( $this, 'cancel_payment' ) );
139
			add_action( 'woocommerce_order_status_on-hold_to_refunded', array( $this, 'cancel_payment' ) );
140
			add_filter( 'woocommerce_get_customer_payment_tokens', array( $this, 'woocommerce_get_customer_payment_tokens' ), 10, 3 );
141
			add_action( 'woocommerce_payment_token_deleted', array( $this, 'woocommerce_payment_token_deleted' ), 10, 2 );
142
			add_action( 'woocommerce_payment_token_set_default', array( $this, 'woocommerce_payment_token_set_default' ) );
143
			add_action( 'wp_ajax_stripe_dismiss_request_api_notice', array( $this, 'dismiss_request_api_notice' ) );
144
			add_action( 'wp_ajax_stripe_dismiss_apple_pay_notice', array( $this, 'dismiss_apple_pay_notice' ) );
145
146
			include_once( dirname( __FILE__ ) . '/includes/class-wc-stripe-payment-request.php' );
147
		}
148
149
		/**
150
		 * Allow this class and other classes to add slug keyed notices (to avoid duplication)
151
		 */
152
		public function add_admin_notice( $slug, $class, $message ) {
153
			$this->notices[ $slug ] = array(
154
				'class'   => $class,
155
				'message' => $message,
156
			);
157
		}
158
159
		/**
160
		 * The backup sanity check, in case the plugin is activated in a weird way,
161
		 * or the environment changes after activation. Also handles upgrade routines.
162
		 */
163
		public function check_environment() {
164
			if ( ! defined( 'IFRAME_REQUEST' ) && ( WC_STRIPE_VERSION !== get_option( 'wc_stripe_version' ) ) ) {
165
				$this->install();
166
167
				do_action( 'woocommerce_stripe_updated' );
168
			}
169
170
			$environment_warning = self::get_environment_warning();
171
172
			if ( $environment_warning && is_plugin_active( plugin_basename( __FILE__ ) ) ) {
173
				$this->add_admin_notice( 'bad_environment', 'error', $environment_warning );
174
			}
175
176
			// Check if secret key present. Otherwise prompt, via notice, to go to
177
			// setting.
178
			if ( ! class_exists( 'WC_Stripe_API' ) ) {
179
				include_once( dirname( __FILE__ ) . '/includes/class-wc-stripe-api.php' );
180
			}
181
182
			$secret = WC_Stripe_API::get_secret_key();
183
184
			if ( empty( $secret ) && ! ( isset( $_GET['page'], $_GET['section'] ) && 'wc-settings' === $_GET['page'] && 'stripe' === $_GET['section'] ) ) {
185
				$setting_link = $this->get_setting_link();
186
				$this->add_admin_notice( 'prompt_connect', 'notice notice-warning', sprintf( __( 'Stripe is almost ready. To get started, <a href="%s">set your Stripe account keys</a>.', 'woocommerce-gateway-stripe' ), $setting_link ) );
187
			}
188
		}
189
190
		/**
191
		 * Updates the plugin version in db
192
		 *
193
		 * @since 3.1.0
194
		 * @version 3.1.0
195
		 * @return bool
196
		 */
197
		private static function _update_plugin_version() {
198
			delete_option( 'wc_stripe_version' );
199
			update_option( 'wc_stripe_version', WC_STRIPE_VERSION );
200
201
			return true;
202
		}
203
204
		/**
205
		 * Dismiss the Google Payment Request API Feature notice.
206
		 *
207
		 * @since 3.1.0
208
		 * @version 3.1.0
209
		 */
210
		public function dismiss_request_api_notice() {
211
			update_option( 'wc_stripe_show_request_api_notice', 'no' );
212
		}
213
214
		/**
215
		 * Dismiss the Apple Pay Feature notice.
216
		 *
217
		 * @since 3.1.0
218
		 * @version 3.1.0
219
		 */
220
		public function dismiss_apple_pay_notice() {
221
			update_option( 'wc_stripe_show_apple_pay_notice', 'no' );
222
		}
223
224
		/**
225
		 * Handles upgrade routines.
226
		 *
227
		 * @since 3.1.0
228
		 * @version 3.1.0
229
		 */
230
		public function install() {
231
			if ( ! defined( 'WC_STRIPE_INSTALLING' ) ) {
232
				define( 'WC_STRIPE_INSTALLING', true );
233
			}
234
235
			$this->_update_plugin_version();
236
		}
237
238
		/**
239
		 * Checks the environment for compatibility problems.  Returns a string with the first incompatibility
240
		 * found or false if the environment has no problems.
241
		 */
242
		static function get_environment_warning() {
0 ignored issues
show
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
243 View Code Duplication
			if ( version_compare( phpversion(), WC_STRIPE_MIN_PHP_VER, '<' ) ) {
0 ignored issues
show
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...
244
				$message = __( 'WooCommerce Stripe - The minimum PHP version required for this plugin is %1$s. You are running %2$s.', 'woocommerce-gateway-stripe' );
245
246
				return sprintf( $message, WC_STRIPE_MIN_PHP_VER, phpversion() );
247
			}
248
249
			if ( ! defined( 'WC_VERSION' ) ) {
250
				return __( 'WooCommerce Stripe requires WooCommerce to be activated to work.', 'woocommerce-gateway-stripe' );
251
			}
252
253 View Code Duplication
			if ( version_compare( WC_VERSION, WC_STRIPE_MIN_WC_VER, '<' ) ) {
0 ignored issues
show
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...
254
				$message = __( 'WooCommerce Stripe - The minimum WooCommerce version required for this plugin is %1$s. You are running %2$s.', 'woocommerce-gateway-stripe' );
255
256
				return sprintf( $message, WC_STRIPE_MIN_WC_VER, WC_VERSION );
257
			}
258
259
			if ( ! function_exists( 'curl_init' ) ) {
260
				return __( 'WooCommerce Stripe - cURL is not installed.', 'woocommerce-gateway-stripe' );
261
			}
262
263
			return false;
264
		}
265
266
		/**
267
		 * Adds plugin action links
268
		 *
269
		 * @since 1.0.0
270
		 */
271
		public function plugin_action_links( $links ) {
272
			$setting_link = $this->get_setting_link();
273
274
			$plugin_links = array(
275
				'<a href="' . $setting_link . '">' . __( 'Settings', 'woocommerce-gateway-stripe' ) . '</a>',
276
				'<a href="https://docs.woocommerce.com/document/stripe/">' . __( 'Docs', 'woocommerce-gateway-stripe' ) . '</a>',
277
				'<a href="https://woocommerce.com/contact-us/">' . __( 'Support', 'woocommerce-gateway-stripe' ) . '</a>',
278
			);
279
			return array_merge( $plugin_links, $links );
280
		}
281
282
		/**
283
		 * Get setting link.
284
		 *
285
		 * @since 1.0.0
286
		 *
287
		 * @return string Setting link
288
		 */
289
		public function get_setting_link() {
290
			$use_id_as_section = function_exists( 'WC' ) ? version_compare( WC()->version, '2.6', '>=' ) : false;
291
292
			$section_slug = $use_id_as_section ? 'stripe' : strtolower( 'WC_Gateway_Stripe' );
293
294
			return admin_url( 'admin.php?page=wc-settings&tab=checkout&section=' . $section_slug );
295
		}
296
297
		/**
298
		 * Display any notices we've collected thus far (e.g. for connection, disconnection)
299
		 */
300
		public function admin_notices() {
301
			$show_request_api_notice = get_option( 'wc_stripe_show_request_api_notice' );
302
			$show_apple_pay_notice   = get_option( 'wc_stripe_show_apple_pay_notice' );
303
304
			if ( empty( $show_apple_pay_notice ) ) {
305
				// @TODO remove this notice in the future.
306
				?>
307
				<div class="notice notice-warning wc-stripe-apple-pay-notice is-dismissible"><p><?php echo sprintf( esc_html__( 'New Feature! Stripe now supports %s. Your customers can now purchase your products even faster. Apple Pay has been enabled by default.', 'woocommerce-gateway-stripe' ), '<a href="https://woocommerce.com/apple-pay/">Apple Pay</a>'); ?></p></div>
308
309
				<script type="application/javascript">
310
					jQuery( '.wc-stripe-apple-pay-notice' ).on( 'click', '.notice-dismiss', function() {
311
						var data = {
312
							action: 'stripe_dismiss_apple_pay_notice'
313
						};
314
315
						jQuery.post( '<?php echo admin_url( 'admin-ajax.php' ); ?>', data );
316
					});
317
				</script>
318
319
				<?php
320
			}
321
322
			if ( empty( $show_request_api_notice ) ) {
323
				// @TODO remove this notice in the future.
324
				?>
325
				<div class="notice notice-warning wc-stripe-request-api-notice is-dismissible"><p><?php esc_html_e( 'New Feature! Stripe now supports Google Payment Request. Your customers can now use mobile phones with supported browsers such as Chrome to make purchases easier and faster.', 'woocommerce-gateway-stripe' ); ?></p></div>
326
327
				<script type="application/javascript">
328
					jQuery( '.wc-stripe-request-api-notice' ).on( 'click', '.notice-dismiss', function() {
329
						var data = {
330
							action: 'stripe_dismiss_request_api_notice'
331
						};
332
333
						jQuery.post( '<?php echo admin_url( 'admin-ajax.php' ); ?>', data );
334
					});
335
				</script>
336
337
				<?php
338
			}
339
340
			foreach ( (array) $this->notices as $notice_key => $notice ) {
341
				echo "<div class='" . esc_attr( $notice['class'] ) . "'><p>";
342
				echo wp_kses( $notice['message'], array( 'a' => array( 'href' => array() ) ) );
343
				echo '</p></div>';
344
			}
345
		}
346
347
		/**
348
		 * Initialize the gateway. Called very early - in the context of the plugins_loaded action
349
		 *
350
		 * @since 1.0.0
351
		 */
352
		public function init_gateways() {
353
			if ( class_exists( 'WC_Subscriptions_Order' ) && function_exists( 'wcs_create_renewal_order' ) ) {
354
				$this->subscription_support_enabled = true;
355
			}
356
357
			if ( class_exists( 'WC_Pre_Orders_Order' ) ) {
358
				$this->pre_order_enabled = true;
359
			}
360
361
			if ( ! class_exists( 'WC_Payment_Gateway' ) ) {
362
				return;
363
			}
364
365
			if ( class_exists( 'WC_Payment_Gateway_CC' ) ) {
366
				include_once( dirname( __FILE__ ) . '/includes/class-wc-gateway-stripe.php' );
367
				include_once( dirname( __FILE__ ) . '/includes/class-wc-stripe-apple-pay.php' );
368
			} else {
369
				include_once( dirname( __FILE__ ) . '/includes/legacy/class-wc-gateway-stripe.php' );
370
				include_once( dirname( __FILE__ ) . '/includes/legacy/class-wc-gateway-stripe-saved-cards.php' );
371
			}
372
373
			load_plugin_textdomain( 'woocommerce-gateway-stripe', false, plugin_basename( dirname( __FILE__ ) ) . '/languages' );
374
			add_filter( 'woocommerce_payment_gateways', array( $this, 'add_gateways' ) );
375
376
			$load_addons = (
377
				$this->subscription_support_enabled
378
				||
379
				$this->pre_order_enabled
380
			);
381
382
			if ( $load_addons ) {
383
				require_once( dirname( __FILE__ ) . '/includes/class-wc-gateway-stripe-addons.php' );
384
			}
385
		}
386
387
		/**
388
		 * Add the gateways to WooCommerce
389
		 *
390
		 * @since 1.0.0
391
		 */
392
		public function add_gateways( $methods ) {
393
			if ( $this->subscription_support_enabled || $this->pre_order_enabled ) {
394
				$methods[] = 'WC_Gateway_Stripe_Addons';
395
			} else {
396
				$methods[] = 'WC_Gateway_Stripe';
397
			}
398
			return $methods;
399
		}
400
401
		/**
402
		 * List of currencies supported by Stripe that has no decimals.
403
		 *
404
		 * @return array $currencies
405
		 */
406
		public static function no_decimal_currencies() {
407
			return array(
408
				'bif', // Burundian Franc
409
				'djf', // Djiboutian Franc
410
				'jpy', // Japanese Yen
411
				'krw', // South Korean Won
412
				'pyg', // Paraguayan Guaraní
413
				'vnd', // Vietnamese Đồng
414
				'xaf', // Central African Cfa Franc
415
				'xpf', // Cfp Franc
416
				'clp', // Chilean Peso
417
				'gnf', // Guinean Franc
418
				'kmf', // Comorian Franc
419
				'mga', // Malagasy Ariary
420
				'rwf', // Rwandan Franc
421
				'vuv', // Vanuatu Vatu
422
				'xof', // West African Cfa Franc
423
			);
424
		}
425
426
		/**
427
		 * Stripe uses smallest denomination in currencies such as cents.
428
		 * We need to format the returned currency from Stripe into human readable form.
429
		 *
430
		 * @param object $balance_transaction
431
		 * @param string $type Type of number to format
432
		 */
433
		public static function format_number( $balance_transaction, $type = 'fee' ) {
434
			if ( ! is_object( $balance_transaction ) ) {
435
				return;
436
			}
437
438
			if ( in_array( strtolower( $balance_transaction->currency ), self::no_decimal_currencies() ) ) {
439
				if ( 'fee' === $type ) {
440
					return $balance_transaction->fee;
441
				}
442
443
				return $balance_transaction->net;
444
			}
445
446
			if ( 'fee' === $type ) {
447
				return number_format( $balance_transaction->fee / 100, 2, '.', '' );
448
			}
449
450
			return number_format( $balance_transaction->net / 100, 2, '.', '' );
451
		}
452
453
		/**
454
		 * Capture payment when the order is changed from on-hold to complete or processing
455
		 *
456
		 * @param  int $order_id
457
		 */
458
		public function capture_payment( $order_id ) {
459
			$order = wc_get_order( $order_id );
460
461
			if ( 'stripe' === ( version_compare( WC_VERSION, '3.0.0', '<' ) ? $order->payment_method : $order->get_payment_method() ) ) {
462
				$charge   = get_post_meta( $order_id, '_stripe_charge_id', true );
463
				$captured = get_post_meta( $order_id, '_stripe_charge_captured', true );
464
465
				if ( $charge && 'no' === $captured ) {
466
					$result = WC_Stripe_API::request( array(
467
						'amount'   => $order->get_total() * 100,
468
						'expand[]' => 'balance_transaction',
469
					), 'charges/' . $charge . '/capture' );
470
471
					if ( is_wp_error( $result ) ) {
472
						$order->add_order_note( __( 'Unable to capture charge!', 'woocommerce-gateway-stripe' ) . ' ' . $result->get_error_message() );
473
					} else {
474
						$order->add_order_note( sprintf( __( 'Stripe charge complete (Charge ID: %s)', 'woocommerce-gateway-stripe' ), $result->id ) );
475
						update_post_meta( $order_id, '_stripe_charge_captured', 'yes' );
476
477
						// Store other data such as fees
478
						update_post_meta( $order_id, 'Stripe Payment ID', $result->id );
479
						update_post_meta( $order_id, '_transaction_id', $result->id );
480
481 View Code Duplication
						if ( isset( $result->balance_transaction ) && isset( $result->balance_transaction->fee ) ) {
0 ignored issues
show
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...
482
							// Fees and Net needs to both come from Stripe to be accurate as the returned
483
							// values are in the local currency of the Stripe account, not from WC.
484
							$fee = ! empty( $result->balance_transaction->fee ) ? self::format_number( $result->balance_transaction, 'fee' ) : 0;
485
							$net = ! empty( $result->balance_transaction->net ) ? self::format_number( $result->balance_transaction, 'net' ) : 0;
486
							update_post_meta( $order_id, 'Stripe Fee', $fee );
487
							update_post_meta( $order_id, 'Net Revenue From Stripe', $net );
488
						}
489
					}
490
				}
491
			}
492
		}
493
494
		/**
495
		 * Cancel pre-auth on refund/cancellation
496
		 *
497
		 * @param  int $order_id
498
		 */
499
		public function cancel_payment( $order_id ) {
500
			$order = wc_get_order( $order_id );
501
502
			if ( 'stripe' === ( version_compare( WC_VERSION, '3.0.0', '<' ) ? $order->payment_method : $order->get_payment_method() ) ) {
503
				$charge   = get_post_meta( $order_id, '_stripe_charge_id', true );
504
505
				if ( $charge ) {
506
					$result = WC_Stripe_API::request( array(
507
						'amount' => $order->get_total() * 100,
508
					), 'charges/' . $charge . '/refund' );
509
510
					if ( is_wp_error( $result ) ) {
511
						$order->add_order_note( __( 'Unable to refund charge!', 'woocommerce-gateway-stripe' ) . ' ' . $result->get_error_message() );
512
					} else {
513
						$order->add_order_note( sprintf( __( 'Stripe charge refunded (Charge ID: %s)', 'woocommerce-gateway-stripe' ), $result->id ) );
514
						delete_post_meta( $order_id, '_stripe_charge_captured' );
515
						delete_post_meta( $order_id, '_stripe_charge_id' );
516
					}
517
				}
518
			}
519
		}
520
521
		/**
522
		 * Gets saved tokens from API if they don't already exist in WooCommerce.
523
		 * @param array $tokens
524
		 * @return array
525
		 */
526
		public function woocommerce_get_customer_payment_tokens( $tokens, $customer_id, $gateway_id ) {
527
			if ( is_user_logged_in() && 'stripe' === $gateway_id && class_exists( 'WC_Payment_Token_CC' ) ) {
528
				$stripe_customer = new WC_Stripe_Customer( $customer_id );
529
				$stripe_cards    = $stripe_customer->get_cards();
530
				$stored_tokens   = array();
531
532
				foreach ( $tokens as $token ) {
533
					$stored_tokens[] = $token->get_token();
534
				}
535
536
				foreach ( $stripe_cards as $card ) {
537
					if ( ! in_array( $card->id, $stored_tokens ) ) {
538
						$token = new WC_Payment_Token_CC();
539
						$token->set_token( $card->id );
540
						$token->set_gateway_id( 'stripe' );
541
						$token->set_card_type( strtolower( $card->brand ) );
542
						$token->set_last4( $card->last4 );
543
						$token->set_expiry_month( $card->exp_month );
544
						$token->set_expiry_year( $card->exp_year );
545
						$token->set_user_id( $customer_id );
546
						$token->save();
547
						$tokens[ $token->get_id() ] = $token;
548
					}
549
				}
550
			}
551
			return $tokens;
552
		}
553
554
		/**
555
		 * Delete token from Stripe
556
		 */
557
		public function woocommerce_payment_token_deleted( $token_id, $token ) {
558
			if ( 'stripe' === $token->get_gateway_id() ) {
559
				$stripe_customer = new WC_Stripe_Customer( get_current_user_id() );
560
				$stripe_customer->delete_card( $token->get_token() );
561
			}
562
		}
563
564
		/**
565
		 * Set as default in Stripe
566
		 */
567
		public function woocommerce_payment_token_set_default( $token_id ) {
568
			$token = WC_Payment_Tokens::get( $token_id );
569
			if ( 'stripe' === $token->get_gateway_id() ) {
570
				$stripe_customer = new WC_Stripe_Customer( get_current_user_id() );
571
				$stripe_customer->set_default_card( $token->get_token() );
572
			}
573
		}
574
575
		/**
576
		 * Checks Stripe minimum order value authorized per currency
577
		 */
578
		public static function get_minimum_amount() {
579
			// Check order amount
580
			switch ( get_woocommerce_currency() ) {
581
				case 'USD':
582
				case 'CAD':
583
				case 'EUR':
584
				case 'CHF':
585
				case 'AUD':
586
				case 'SGD':
587
					$minimum_amount = 50;
588
					break;
589
				case 'GBP':
590
					$minimum_amount = 30;
591
					break;
592
				case 'DKK':
593
					$minimum_amount = 250;
594
					break;
595
				case 'NOK':
596
				case 'SEK':
597
					$minimum_amount = 300;
598
					break;
599
				case 'JPY':
600
					$minimum_amount = 5000;
601
					break;
602
				case 'MXN':
603
					$minimum_amount = 1000;
604
					break;
605
				case 'HKD':
606
					$minimum_amount = 400;
607
					break;
608
				default:
609
					$minimum_amount = 50;
610
					break;
611
			}
612
613
			return $minimum_amount;
614
		}
615
616
		/**
617
		 * What rolls down stairs
618
		 * alone or in pairs,
619
		 * and over your neighbor's dog?
620
		 * What's great for a snack,
621
		 * And fits on your back?
622
		 * It's log, log, log
623
		 */
624
		public static function log( $message ) {
625
			if ( empty( self::$log ) ) {
626
				self::$log = new WC_Logger();
0 ignored issues
show
Documentation Bug introduced by
It seems like new \WC_Logger() of type object<WC_Logger> is incompatible with the declared type object<Reference> of property $log.

Our type inference engine has found an assignment to a property that is incompatible with the declared type of that property.

Either this assignment is in error or the assigned type should be added to the documentation/type hint for that property..

Loading history...
627
			}
628
629
			self::$log->add( 'woocommerce-gateway-stripe', $message );
630
		}
631
	}
632
633
	$GLOBALS['wc_stripe'] = WC_Stripe::get_instance();
634
635
endif;
636