Completed
Pull Request — master (#314)
by Akeda
01:56
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.2
9
 * Requires at least: 4.4
10
 * Tested up to: 4.8
11
 * Text Domain: woocommerce-gateway-stripe
12
 * Domain Path: /languages
13
 *
14
 * Copyright (c) 2017 WooCommerce
15
 *
16
 * This program is free software: you can redistribute it and/or modify
17
 * it under the terms of the GNU General Public License as published by
18
 * the Free Software Foundation, either version 3 of the License, or
19
 * (at your option) any later version.
20
 *
21
 * This program is distributed in the hope that it will be useful,
22
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
23
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
24
 * GNU General Public License for more details.
25
 *
26
 * You should have received a copy of the GNU General Public License
27
 * along with this program. If not, see <http://www.gnu.org/licenses/>.
28
*/
29
30
if ( ! defined( 'ABSPATH' ) ) {
31
	exit;
32
}
33
34
/**
35
 * Required minimums and constants
36
 */
37
define( 'WC_STRIPE_VERSION', '3.2.2' );
38
define( 'WC_STRIPE_MIN_PHP_VER', '5.6.0' );
39
define( 'WC_STRIPE_MIN_WC_VER', '2.5.0' );
40
define( 'WC_STRIPE_MAIN_FILE', __FILE__ );
41
define( 'WC_STRIPE_PLUGIN_URL', untrailingslashit( plugins_url( basename( plugin_dir_path( __FILE__ ) ), basename( __FILE__ ) ) ) );
42
define( 'WC_STRIPE_PLUGIN_PATH', untrailingslashit( plugin_dir_path( __FILE__ ) ) );
43
44
if ( ! class_exists( 'WC_Stripe' ) ) :
45
46
	class WC_Stripe {
47
48
		/**
49
		 * @var Singleton The reference the *Singleton* instance of this class
50
		 */
51
		private static $instance;
52
53
		/**
54
		 * @var Reference to logging class.
55
		 */
56
		private static $log;
57
58
		/**
59
		 * Returns the *Singleton* instance of this class.
60
		 *
61
		 * @return Singleton The *Singleton* instance.
62
		 */
63
		public static function get_instance() {
64
			if ( null === self::$instance ) {
65
				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...
66
			}
67
			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 67 which is incompatible with the return type documented by WC_Stripe::get_instance of type Singleton.
Loading history...
68
		}
69
70
		/**
71
		 * Private clone method to prevent cloning of the instance of the
72
		 * *Singleton* instance.
73
		 *
74
		 * @return void
75
		 */
76
		private function __clone() {}
77
78
		/**
79
		 * Private unserialize method to prevent unserializing of the *Singleton*
80
		 * instance.
81
		 *
82
		 * @return void
83
		 */
84
		private function __wakeup() {}
85
86
		/**
87
		 * Flag to indicate whether or not we need to load code for / support subscriptions.
88
		 *
89
		 * @var bool
90
		 */
91
		private $subscription_support_enabled = false;
92
93
		/**
94
		 * Flag to indicate whether or not we need to load support for pre-orders.
95
		 *
96
		 * @since 3.0.3
97
		 *
98
		 * @var bool
99
		 */
100
		private $pre_order_enabled = false;
101
102
		/**
103
		 * Notices (array)
104
		 * @var array
105
		 */
106
		public $notices = array();
107
108
		/**
109
		 * Protected constructor to prevent creating a new instance of the
110
		 * *Singleton* via the `new` operator from outside of this class.
111
		 */
112
		protected function __construct() {
113
			add_action( 'admin_init', array( $this, 'check_environment' ) );
114
			add_action( 'admin_notices', array( $this, 'admin_notices' ), 15 );
115
			add_action( 'plugins_loaded', array( $this, 'init' ) );
116
		}
117
118
		/**
119
		 * Init the plugin after plugins_loaded so environment variables are set.
120
		 */
121
		public function init() {
122
			// Don't hook anything else in the plugin if we're in an incompatible environment
123
			if ( self::get_environment_warning() ) {
124
				return;
125
			}
126
127
			include_once( dirname( __FILE__ ) . '/includes/class-wc-stripe-api.php' );
128
			include_once( dirname( __FILE__ ) . '/includes/class-wc-stripe-customer.php' );
129
130
			// Init the gateway itself
131
			$this->init_gateways();
132
133
			add_filter( 'plugin_action_links_' . plugin_basename( __FILE__ ), array( $this, 'plugin_action_links' ) );
134
			add_action( 'woocommerce_order_status_on-hold_to_processing', array( $this, 'capture_payment' ) );
135
			add_action( 'woocommerce_order_status_on-hold_to_completed', array( $this, 'capture_payment' ) );
136
			add_action( 'woocommerce_order_status_on-hold_to_cancelled', array( $this, 'cancel_payment' ) );
137
			add_action( 'woocommerce_order_status_on-hold_to_refunded', array( $this, 'cancel_payment' ) );
138
			add_filter( 'woocommerce_get_customer_payment_tokens', array( $this, 'woocommerce_get_customer_payment_tokens' ), 10, 3 );
139
			add_action( 'woocommerce_payment_token_deleted', array( $this, 'woocommerce_payment_token_deleted' ), 10, 2 );
140
			add_action( 'woocommerce_payment_token_set_default', array( $this, 'woocommerce_payment_token_set_default' ) );
141
			add_action( 'wp_ajax_stripe_dismiss_request_api_notice', array( $this, 'dismiss_request_api_notice' ) );
142
			add_action( 'wp_ajax_stripe_dismiss_apple_pay_notice', array( $this, 'dismiss_apple_pay_notice' ) );
143
144
			include_once( dirname( __FILE__ ) . '/includes/class-wc-stripe-payment-request.php' );
145
		}
146
147
		/**
148
		 * Allow this class and other classes to add slug keyed notices (to avoid duplication)
149
		 */
150
		public function add_admin_notice( $slug, $class, $message ) {
151
			$this->notices[ $slug ] = array(
152
				'class'   => $class,
153
				'message' => $message,
154
			);
155
		}
156
157
		/**
158
		 * The backup sanity check, in case the plugin is activated in a weird way,
159
		 * or the environment changes after activation. Also handles upgrade routines.
160
		 */
161
		public function check_environment() {
162
			if ( ! defined( 'IFRAME_REQUEST' ) && ( WC_STRIPE_VERSION !== get_option( 'wc_stripe_version' ) ) ) {
163
				$this->install();
164
165
				do_action( 'woocommerce_stripe_updated' );
166
			}
167
168
			$environment_warning = self::get_environment_warning();
169
170
			if ( $environment_warning && is_plugin_active( plugin_basename( __FILE__ ) ) ) {
171
				$this->add_admin_notice( 'bad_environment', 'error', $environment_warning );
172
			}
173
174
			// Check if secret key present. Otherwise prompt, via notice, to go to
175
			// setting.
176
			if ( ! class_exists( 'WC_Stripe_API' ) ) {
177
				include_once( dirname( __FILE__ ) . '/includes/class-wc-stripe-api.php' );
178
			}
179
180
			$secret = WC_Stripe_API::get_secret_key();
181
182
			if ( empty( $secret ) && ! ( isset( $_GET['page'], $_GET['section'] ) && 'wc-settings' === $_GET['page'] && 'stripe' === $_GET['section'] ) ) {
183
				$setting_link = $this->get_setting_link();
184
				$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 ) );
185
			}
186
		}
187
188
		/**
189
		 * Updates the plugin version in db
190
		 *
191
		 * @since 3.1.0
192
		 * @version 3.1.0
193
		 * @return bool
194
		 */
195
		private static function _update_plugin_version() {
196
			delete_option( 'wc_stripe_version' );
197
			update_option( 'wc_stripe_version', WC_STRIPE_VERSION );
198
199
			return true;
200
		}
201
202
		/**
203
		 * Dismiss the Google Payment Request API Feature notice.
204
		 *
205
		 * @since 3.1.0
206
		 * @version 3.1.0
207
		 */
208
		public function dismiss_request_api_notice() {
209
			update_option( 'wc_stripe_show_request_api_notice', 'no' );
210
		}
211
212
		/**
213
		 * Dismiss the Apple Pay Feature notice.
214
		 *
215
		 * @since 3.1.0
216
		 * @version 3.1.0
217
		 */
218
		public function dismiss_apple_pay_notice() {
219
			update_option( 'wc_stripe_show_apple_pay_notice', 'no' );
220
		}
221
222
		/**
223
		 * Handles upgrade routines.
224
		 *
225
		 * @since 3.1.0
226
		 * @version 3.1.0
227
		 */
228
		public function install() {
229
			if ( ! defined( 'WC_STRIPE_INSTALLING' ) ) {
230
				define( 'WC_STRIPE_INSTALLING', true );
231
			}
232
233
			$this->_update_plugin_version();
234
		}
235
236
		/**
237
		 * Checks the environment for compatibility problems.  Returns a string with the first incompatibility
238
		 * found or false if the environment has no problems.
239
		 */
240
		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...
241 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...
242
				$message = __( 'WooCommerce Stripe - The minimum PHP version required for this plugin is %1$s. You are running %2$s.', 'woocommerce-gateway-stripe' );
243
244
				return sprintf( $message, WC_STRIPE_MIN_PHP_VER, phpversion() );
245
			}
246
247
			if ( ! defined( 'WC_VERSION' ) ) {
248
				return __( 'WooCommerce Stripe requires WooCommerce to be activated to work.', 'woocommerce-gateway-stripe' );
249
			}
250
251 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...
252
				$message = __( 'WooCommerce Stripe - The minimum WooCommerce version required for this plugin is %1$s. You are running %2$s.', 'woocommerce-gateway-stripe' );
253
254
				return sprintf( $message, WC_STRIPE_MIN_WC_VER, WC_VERSION );
255
			}
256
257
			if ( ! function_exists( 'curl_init' ) ) {
258
				return __( 'WooCommerce Stripe - cURL is not installed.', 'woocommerce-gateway-stripe' );
259
			}
260
261
			return false;
262
		}
263
264
		/**
265
		 * Adds plugin action links
266
		 *
267
		 * @since 1.0.0
268
		 */
269
		public function plugin_action_links( $links ) {
270
			$setting_link = $this->get_setting_link();
271
272
			$plugin_links = array(
273
				'<a href="' . $setting_link . '">' . __( 'Settings', 'woocommerce-gateway-stripe' ) . '</a>',
274
				'<a href="https://docs.woocommerce.com/document/stripe/">' . __( 'Docs', 'woocommerce-gateway-stripe' ) . '</a>',
275
				'<a href="https://woocommerce.com/contact-us/">' . __( 'Support', 'woocommerce-gateway-stripe' ) . '</a>',
276
			);
277
			return array_merge( $plugin_links, $links );
278
		}
279
280
		/**
281
		 * Get setting link.
282
		 *
283
		 * @since 1.0.0
284
		 *
285
		 * @return string Setting link
286
		 */
287
		public function get_setting_link() {
288
			$use_id_as_section = function_exists( 'WC' ) ? version_compare( WC()->version, '2.6', '>=' ) : false;
289
290
			$section_slug = $use_id_as_section ? 'stripe' : strtolower( 'WC_Gateway_Stripe' );
291
292
			return admin_url( 'admin.php?page=wc-settings&tab=checkout&section=' . $section_slug );
293
		}
294
295
		/**
296
		 * Display any notices we've collected thus far (e.g. for connection, disconnection)
297
		 */
298
		public function admin_notices() {
299
			$show_request_api_notice = get_option( 'wc_stripe_show_request_api_notice' );
300
			$show_apple_pay_notice   = get_option( 'wc_stripe_show_apple_pay_notice' );
301
302
			if ( empty( $show_apple_pay_notice ) ) {
303
				// @TODO remove this notice in the future.
304
				?>
305
				<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>
306
307
				<script type="application/javascript">
308
					jQuery( '.wc-stripe-apple-pay-notice' ).on( 'click', '.notice-dismiss', function() {
309
						var data = {
310
							action: 'stripe_dismiss_apple_pay_notice'
311
						};
312
313
						jQuery.post( '<?php echo admin_url( 'admin-ajax.php' ); ?>', data );
314
					});
315
				</script>
316
317
				<?php
318
			}
319
320
			if ( empty( $show_request_api_notice ) ) {
321
				// @TODO remove this notice in the future.
322
				?>
323
				<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>
324
325
				<script type="application/javascript">
326
					jQuery( '.wc-stripe-request-api-notice' ).on( 'click', '.notice-dismiss', function() {
327
						var data = {
328
							action: 'stripe_dismiss_request_api_notice'
329
						};
330
331
						jQuery.post( '<?php echo admin_url( 'admin-ajax.php' ); ?>', data );
332
					});
333
				</script>
334
335
				<?php
336
			}
337
338
			foreach ( (array) $this->notices as $notice_key => $notice ) {
339
				echo "<div class='" . esc_attr( $notice['class'] ) . "'><p>";
340
				echo wp_kses( $notice['message'], array( 'a' => array( 'href' => array() ) ) );
341
				echo '</p></div>';
342
			}
343
		}
344
345
		/**
346
		 * Initialize the gateway. Called very early - in the context of the plugins_loaded action
347
		 *
348
		 * @since 1.0.0
349
		 */
350
		public function init_gateways() {
351
			if ( class_exists( 'WC_Subscriptions_Order' ) && function_exists( 'wcs_create_renewal_order' ) ) {
352
				$this->subscription_support_enabled = true;
353
			}
354
355
			if ( class_exists( 'WC_Pre_Orders_Order' ) ) {
356
				$this->pre_order_enabled = true;
357
			}
358
359
			if ( ! class_exists( 'WC_Payment_Gateway' ) ) {
360
				return;
361
			}
362
363
			if ( class_exists( 'WC_Payment_Gateway_CC' ) ) {
364
				include_once( dirname( __FILE__ ) . '/includes/class-wc-gateway-stripe.php' );
365
				include_once( dirname( __FILE__ ) . '/includes/class-wc-stripe-apple-pay.php' );
366
			} else {
367
				include_once( dirname( __FILE__ ) . '/includes/legacy/class-wc-gateway-stripe.php' );
368
				include_once( dirname( __FILE__ ) . '/includes/legacy/class-wc-gateway-stripe-saved-cards.php' );
369
			}
370
371
			load_plugin_textdomain( 'woocommerce-gateway-stripe', false, plugin_basename( dirname( __FILE__ ) ) . '/languages' );
372
			add_filter( 'woocommerce_payment_gateways', array( $this, 'add_gateways' ) );
373
374
			$load_addons = (
375
				$this->subscription_support_enabled
376
				||
377
				$this->pre_order_enabled
378
			);
379
380
			if ( $load_addons ) {
381
				require_once( dirname( __FILE__ ) . '/includes/class-wc-gateway-stripe-addons.php' );
382
			}
383
		}
384
385
		/**
386
		 * Add the gateways to WooCommerce
387
		 *
388
		 * @since 1.0.0
389
		 */
390
		public function add_gateways( $methods ) {
391
			if ( $this->subscription_support_enabled || $this->pre_order_enabled ) {
392
				$methods[] = 'WC_Gateway_Stripe_Addons';
393
			} else {
394
				$methods[] = 'WC_Gateway_Stripe';
395
			}
396
			return $methods;
397
		}
398
399
		/**
400
		 * List of currencies supported by Stripe that has no decimals.
401
		 *
402
		 * @return array $currencies
403
		 */
404
		public static function no_decimal_currencies() {
405
			return array(
406
				'bif', // Burundian Franc
407
				'djf', // Djiboutian Franc
408
				'jpy', // Japanese Yen
409
				'krw', // South Korean Won
410
				'pyg', // Paraguayan Guaraní
411
				'vnd', // Vietnamese Đồng
412
				'xaf', // Central African Cfa Franc
413
				'xpf', // Cfp Franc
414
				'clp', // Chilean Peso
415
				'gnf', // Guinean Franc
416
				'kmf', // Comorian Franc
417
				'mga', // Malagasy Ariary
418
				'rwf', // Rwandan Franc
419
				'vuv', // Vanuatu Vatu
420
				'xof', // West African Cfa Franc
421
			);
422
		}
423
424
		/**
425
		 * Stripe uses smallest denomination in currencies such as cents.
426
		 * We need to format the returned currency from Stripe into human readable form.
427
		 *
428
		 * @param object $balance_transaction
429
		 * @param string $type Type of number to format
430
		 */
431
		public static function format_number( $balance_transaction, $type = 'fee' ) {
432
			if ( ! is_object( $balance_transaction ) ) {
433
				return;
434
			}
435
436
			if ( in_array( strtolower( $balance_transaction->currency ), self::no_decimal_currencies() ) ) {
437
				if ( 'fee' === $type ) {
438
					return $balance_transaction->fee;
439
				}
440
441
				return $balance_transaction->net;
442
			}
443
444
			if ( 'fee' === $type ) {
445
				return number_format( $balance_transaction->fee / 100, 2, '.', '' );
446
			}
447
448
			return number_format( $balance_transaction->net / 100, 2, '.', '' );
449
		}
450
451
		/**
452
		 * Capture payment when the order is changed from on-hold to complete or processing
453
		 *
454
		 * @param  int $order_id
455
		 */
456
		public function capture_payment( $order_id ) {
457
			$order = wc_get_order( $order_id );
458
459
			if ( 'stripe' === ( version_compare( WC_VERSION, '3.0.0', '<' ) ? $order->payment_method : $order->get_payment_method() ) ) {
460
				$charge   = get_post_meta( $order_id, '_stripe_charge_id', true );
461
				$captured = get_post_meta( $order_id, '_stripe_charge_captured', true );
462
463
				if ( $charge && 'no' === $captured ) {
464
					$result = WC_Stripe_API::request( array(
465
						'amount'   => $order->get_total() * 100,
466
						'expand[]' => 'balance_transaction',
467
					), 'charges/' . $charge . '/capture' );
468
469
					if ( is_wp_error( $result ) ) {
470
						$order->add_order_note( __( 'Unable to capture charge!', 'woocommerce-gateway-stripe' ) . ' ' . $result->get_error_message() );
471
					} else {
472
						$order->add_order_note( sprintf( __( 'Stripe charge complete (Charge ID: %s)', 'woocommerce-gateway-stripe' ), $result->id ) );
473
						update_post_meta( $order_id, '_stripe_charge_captured', 'yes' );
474
475
						// Store other data such as fees
476
						update_post_meta( $order_id, 'Stripe Payment ID', $result->id );
477
						update_post_meta( $order_id, '_transaction_id', $result->id );
478
479 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...
480
							// Fees and Net needs to both come from Stripe to be accurate as the returned
481
							// values are in the local currency of the Stripe account, not from WC.
482
							$fee = ! empty( $result->balance_transaction->fee ) ? self::format_number( $result->balance_transaction, 'fee' ) : 0;
483
							$net = ! empty( $result->balance_transaction->net ) ? self::format_number( $result->balance_transaction, 'net' ) : 0;
484
							update_post_meta( $order_id, 'Stripe Fee', $fee );
485
							update_post_meta( $order_id, 'Net Revenue From Stripe', $net );
486
						}
487
					}
488
				}
489
			}
490
		}
491
492
		/**
493
		 * Cancel pre-auth on refund/cancellation
494
		 *
495
		 * @param  int $order_id
496
		 */
497
		public function cancel_payment( $order_id ) {
498
			$order = wc_get_order( $order_id );
499
500
			if ( 'stripe' === ( version_compare( WC_VERSION, '3.0.0', '<' ) ? $order->payment_method : $order->get_payment_method() ) ) {
501
				$charge   = get_post_meta( $order_id, '_stripe_charge_id', true );
502
503
				if ( $charge ) {
504
					$result = WC_Stripe_API::request( array(
505
						'amount' => $order->get_total() * 100,
506
					), 'charges/' . $charge . '/refund' );
507
508
					if ( is_wp_error( $result ) ) {
509
						$order->add_order_note( __( 'Unable to refund charge!', 'woocommerce-gateway-stripe' ) . ' ' . $result->get_error_message() );
510
					} else {
511
						$order->add_order_note( sprintf( __( 'Stripe charge refunded (Charge ID: %s)', 'woocommerce-gateway-stripe' ), $result->id ) );
512
						delete_post_meta( $order_id, '_stripe_charge_captured' );
513
						delete_post_meta( $order_id, '_stripe_charge_id' );
514
					}
515
				}
516
			}
517
		}
518
519
		/**
520
		 * Gets saved tokens from API if they don't already exist in WooCommerce.
521
		 * @param array $tokens
522
		 * @return array
523
		 */
524
		public function woocommerce_get_customer_payment_tokens( $tokens, $customer_id, $gateway_id ) {
525
			if ( is_user_logged_in() && 'stripe' === $gateway_id && class_exists( 'WC_Payment_Token_CC' ) ) {
526
				$stripe_customer = new WC_Stripe_Customer( $customer_id );
527
				$stripe_cards    = $stripe_customer->get_cards();
528
				$stored_tokens   = array();
529
530
				foreach ( $tokens as $token ) {
531
					$stored_tokens[] = $token->get_token();
532
				}
533
534
				foreach ( $stripe_cards as $card ) {
535
					if ( ! in_array( $card->id, $stored_tokens ) ) {
536
						$token = new WC_Payment_Token_CC();
537
						$token->set_token( $card->id );
538
						$token->set_gateway_id( 'stripe' );
539
						$token->set_card_type( strtolower( $card->brand ) );
540
						$token->set_last4( $card->last4 );
541
						$token->set_expiry_month( $card->exp_month );
542
						$token->set_expiry_year( $card->exp_year );
543
						$token->set_user_id( $customer_id );
544
						$token->save();
545
						$tokens[ $token->get_id() ] = $token;
546
					}
547
				}
548
			}
549
			return $tokens;
550
		}
551
552
		/**
553
		 * Delete token from Stripe
554
		 */
555
		public function woocommerce_payment_token_deleted( $token_id, $token ) {
556
			if ( 'stripe' === $token->get_gateway_id() ) {
557
				$stripe_customer = new WC_Stripe_Customer( get_current_user_id() );
558
				$stripe_customer->delete_card( $token->get_token() );
559
			}
560
		}
561
562
		/**
563
		 * Set as default in Stripe
564
		 */
565
		public function woocommerce_payment_token_set_default( $token_id ) {
566
			$token = WC_Payment_Tokens::get( $token_id );
567
			if ( 'stripe' === $token->get_gateway_id() ) {
568
				$stripe_customer = new WC_Stripe_Customer( get_current_user_id() );
569
				$stripe_customer->set_default_card( $token->get_token() );
570
			}
571
		}
572
573
		/**
574
		 * Checks Stripe minimum order value authorized per currency
575
		 */
576
		public static function get_minimum_amount() {
577
			// Check order amount
578
			switch ( get_woocommerce_currency() ) {
579
				case 'USD':
580
				case 'CAD':
581
				case 'EUR':
582
				case 'CHF':
583
				case 'AUD':
584
				case 'SGD':
585
					$minimum_amount = 50;
586
					break;
587
				case 'GBP':
588
					$minimum_amount = 30;
589
					break;
590
				case 'DKK':
591
					$minimum_amount = 250;
592
					break;
593
				case 'NOK':
594
				case 'SEK':
595
					$minimum_amount = 300;
596
					break;
597
				case 'JPY':
598
					$minimum_amount = 5000;
599
					break;
600
				case 'MXN':
601
					$minimum_amount = 1000;
602
					break;
603
				case 'HKD':
604
					$minimum_amount = 400;
605
					break;
606
				default:
607
					$minimum_amount = 50;
608
					break;
609
			}
610
611
			return $minimum_amount;
612
		}
613
614
		/**
615
		 * What rolls down stairs
616
		 * alone or in pairs,
617
		 * and over your neighbor's dog?
618
		 * What's great for a snack,
619
		 * And fits on your back?
620
		 * It's log, log, log
621
		 */
622
		public static function log( $message ) {
623
			if ( empty( self::$log ) ) {
624
				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...
625
			}
626
627
			self::$log->add( 'woocommerce-gateway-stripe', $message );
628
		}
629
	}
630
631
	$GLOBALS['wc_stripe'] = WC_Stripe::get_instance();
632
633
endif;
634