PluginProbe
Subscriptions for WooCommerce with Stripe Recurring Payments / 2.2.0
Subscriptions for WooCommerce with Stripe Recurring Payments v2.2.0
2.4.0 2.3.0 2.2.0 2.1.0 2.0.0 1.11.2 1.11.1 1.11.0 1.10.9 1.10.8 1.10.7 1.10.6 1.10.5 1.10.4 1.10.3 1.10.2 1.10.1 1.10.0 1.9.6 1.9.5 trunk 1.3.0 1.3.1 1.3.2 1.4.0 All 65 releases
← All changes | includes/Illuminate/GuestCheckout.php +229 -1 1.10.4 → 2.2.0 View file →
@@ -30,8 +30,13 @@
30 30
31 31 // Enforce Login/Registration in checkout
32 32 add_action( 'woocommerce_checkout_process', [ $this, 'require_account_creation' ] );
33 33 add_filter( 'woocommerce_store_api_checkout_update_order_from_request', [ $this,'require_account_creation_store_api' ], 10, 2 );
34 +
35 + // Guest account creation.
36 + add_action( 'woocommerce_store_api_checkout_update_customer_from_request', [ $this, 'maybe_create_user_from_customer' ], 10, 1 );
37 + add_action( 'woocommerce_store_api_checkout_update_order_from_request', [ $this, 'maybe_assign_user_to_order' ], 5, 1 );
38 + add_action( 'woocommerce_checkout_create_order', [ $this, 'maybe_assign_user_to_order' ], 10, 1 );
34 39 }
35 40
36 41 /**
37 42 * Add Guest Checkout Settings Fields
@@ -43,9 +48,9 @@
43 48 $guest_checkout_fields = [
44 49 [
45 50 'type' => 'heading',
46 51 'group' => 'guest_checkout',
47 - 'priority' => 1,
52 + 'priority' => 2,
48 53 'field_data' => [
49 54 'title' => __( 'Guest Checkout', 'subscription' ),
50 55 'description' => __( 'Manage guest checkout settings for subscriptions.', 'subscription' ),
51 56 ],
@@ -277,7 +282,230 @@
277 282 __( 'You are ordering a subscription product. You must be either <strong>logged in</strong> or check the "<strong>Create an account</strong>" option to continue the checkout.', 'subscription' )
278 283 ),
279 284 400
280 285 );
286 + }
287 + }
288 +
289 + /**
290 + * Build user info from order or customer object.
291 + *
292 + * @param \WC_Order|\WC_Customer $order_or_customer Order or Customer object.
293 + */
294 + public function build_user_info( $order_or_customer ): array {
295 + $user_info = [];
296 +
297 + // Billing info.
298 + $user_info['billing_first_name'] = $order_or_customer->get_billing_first_name();
299 + $user_info['billing_last_name'] = $order_or_customer->get_billing_last_name();
300 + $user_info['billing_company'] = $order_or_customer->get_billing_company();
301 + $user_info['billing_address_1'] = $order_or_customer->get_billing_address_1();
302 + $user_info['billing_address_2'] = $order_or_customer->get_billing_address_2();
303 + $user_info['billing_city'] = $order_or_customer->get_billing_city();
304 + $user_info['billing_postcode'] = $order_or_customer->get_billing_postcode();
305 + $user_info['billing_country'] = $order_or_customer->get_billing_country();
306 + $user_info['billing_state'] = $order_or_customer->get_billing_state();
307 + $user_info['billing_email'] = $order_or_customer->get_billing_email();
308 + $user_info['billing_phone'] = $order_or_customer->get_billing_phone();
309 +
310 + // Shipping info.
311 + $user_info['shipping_first_name'] = ! empty( $order_or_customer->get_shipping_first_name() ) ? $order_or_customer->get_shipping_first_name() : $user_info['billing_first_name'];
312 + $user_info['shipping_last_name'] = ! empty( $order_or_customer->get_shipping_last_name() ) ? $order_or_customer->get_shipping_last_name() : $user_info['billing_last_name'];
313 + $user_info['shipping_company'] = ! empty( $order_or_customer->get_shipping_company() ) ? $order_or_customer->get_shipping_company() : $user_info['billing_company'];
314 + $user_info['shipping_address_1'] = ! empty( $order_or_customer->get_shipping_address_1() ) ? $order_or_customer->get_shipping_address_1() : $user_info['billing_address_1'];
315 + $user_info['shipping_address_2'] = ! empty( $order_or_customer->get_shipping_address_2() ) ? $order_or_customer->get_shipping_address_2() : $user_info['billing_address_2'];
316 + $user_info['shipping_city'] = ! empty( $order_or_customer->get_shipping_city() ) ? $order_or_customer->get_shipping_city() : $user_info['billing_city'];
317 + $user_info['shipping_postcode'] = ! empty( $order_or_customer->get_shipping_postcode() ) ? $order_or_customer->get_shipping_postcode() : $user_info['billing_postcode'];
318 + $user_info['shipping_country'] = ! empty( $order_or_customer->get_shipping_country() ) ? $order_or_customer->get_shipping_country() : $user_info['billing_country'];
319 + $user_info['shipping_state'] = ! empty( $order_or_customer->get_shipping_state() ) ? $order_or_customer->get_shipping_state() : $user_info['billing_state'];
320 + $user_info['shipping_phone'] = ! empty( $order_or_customer->get_shipping_phone() ) ? $order_or_customer->get_shipping_phone() : $user_info['billing_phone'];
321 +
322 + return $user_info;
323 + }
324 +
325 + /**
326 + * Maybe create user from user info.
327 + *
328 + * @param array $user_info User info array.
329 + */
330 + public function maybe_create_user( $user_info ): ?int {
331 + // Don't proceed if guest checkout is not allowed.
332 + $is_guest_checkout_allowed = in_array( get_option( 'wp_subscription_allow_guest_checkout', '0' ), [ 1, '1', 'yes', 'on' ], true );
333 + if ( ! $is_guest_checkout_allowed ) {
334 + return null;
335 + }
336 +
337 + $is_new_customer = false;
338 +
339 + // Check if user exists with email.
340 + $user = get_user_by( 'email', $user_info['billing_email'] );
341 + $user_id = $user ? $user->ID : 0;
342 +
343 + if ( ! $user_id ) {
344 + $is_new_customer = true;
345 +
346 + // Not wp_insert_user(): without a `user_pass` it stores wp_hash_password( '' ).
347 + $user_id = wc_create_new_customer(
348 + $user_info['billing_email'],
349 + '',
350 + '',
351 + [
352 + 'first_name' => $user_info['billing_first_name'],
353 + 'last_name' => $user_info['billing_last_name'],
354 + 'source' => 'subscrpt-guest-checkout',
355 + ]
356 + );
357 +
358 + if ( is_wp_error( $user_id ) ) {
359 + subscrpt_write_log( 'Failed to auto-create user during checkout. Error: ' . $user_id->get_error_message() );
360 + return null;
361 + }
362 +
363 + // Set billing info.
364 + update_user_meta( $user_id, 'billing_first_name', $user_info['billing_first_name'] );
365 + update_user_meta( $user_id, 'billing_last_name', $user_info['billing_last_name'] );
366 + update_user_meta( $user_id, 'billing_company', $user_info['billing_company'] );
367 + update_user_meta( $user_id, 'billing_address_1', $user_info['billing_address_1'] );
368 + update_user_meta( $user_id, 'billing_address_2', $user_info['billing_address_2'] );
369 + update_user_meta( $user_id, 'billing_city', $user_info['billing_city'] );
370 + update_user_meta( $user_id, 'billing_postcode', $user_info['billing_postcode'] );
371 + update_user_meta( $user_id, 'billing_country', $user_info['billing_country'] );
372 + update_user_meta( $user_id, 'billing_state', $user_info['billing_state'] );
373 + update_user_meta( $user_id, 'billing_email', $user_info['billing_email'] );
374 + update_user_meta( $user_id, 'billing_phone', $user_info['billing_phone'] );
375 +
376 + // Set shipping info.
377 + update_user_meta( $user_id, 'shipping_first_name', $user_info['shipping_first_name'] );
378 + update_user_meta( $user_id, 'shipping_last_name', $user_info['shipping_last_name'] );
379 + update_user_meta( $user_id, 'shipping_company', $user_info['shipping_company'] );
380 + update_user_meta( $user_id, 'shipping_address_1', $user_info['shipping_address_1'] );
381 + update_user_meta( $user_id, 'shipping_address_2', $user_info['shipping_address_2'] );
382 + update_user_meta( $user_id, 'shipping_city', $user_info['shipping_city'] );
383 + update_user_meta( $user_id, 'shipping_postcode', $user_info['shipping_postcode'] );
384 + update_user_meta( $user_id, 'shipping_country', $user_info['shipping_country'] );
385 + update_user_meta( $user_id, 'shipping_state', $user_info['shipping_state'] );
386 + update_user_meta( $user_id, 'shipping_phone', $user_info['shipping_phone'] );
387 + }
388 +
389 + // Auto-login the newly created account so the subscription can be associated with the user.
390 + // This ONLY runs when $is_new_customer is true — i.e. when wp_insert_user() succeeded
391 + // just above in this same request. It never fires for returning/existing users.
392 + // wc_set_customer_auth_cookie() is the WooCommerce-sanctioned way to log a customer in
393 + // during checkout; wp_set_auth_cookie() is the WP fallback if WC is not available.
394 + if ( ! is_user_logged_in() && $is_new_customer && $user_id ) {
395 + wp_set_current_user( $user_id );
396 + if ( function_exists( 'wc_set_customer_auth_cookie' ) ) {
397 + wc_set_customer_auth_cookie( $user_id );
398 + } else {
399 + wp_set_auth_cookie( $user_id );
400 + }
401 +
402 + subscrpt_write_debug_log( 'Auto-logged in newly created user ID: ' . $user_id . ' after checkout.' );
403 + }
404 +
405 + return $user_id;
406 + }
407 +
408 + /**
409 + * Auto-create a guest account only while login is not enforced.
410 + *
411 + * @return bool
412 + */
413 + protected function should_auto_create_account() {
414 + return self::is_guest_checkout_allowed() && ! self::is_guest_login_enforced();
415 + }
416 +
417 + /**
418 + * Does the current cart contain a subscription product.
419 + *
420 + * @return bool
421 + */
422 + protected function cart_has_subscription() {
423 + if ( ! function_exists( 'WC' ) || ! WC()->cart ) {
424 + return false;
425 + }
426 +
427 + return count( Helper::get_recurrs_from_cart( WC()->cart->get_cart() ) ) > 0;
428 + }
429 +
430 + /**
431 + * Create the guest account before the order exists, for gateway customer binding.
432 + *
433 + * @param \WC_Customer $customer Customer object.
434 + *
435 + * @return void
436 + */
437 + public function maybe_create_user_from_customer( $customer ) {
438 + if ( is_user_logged_in() || ! $this->should_auto_create_account() ) {
439 + return;
440 + }
441 +
442 + // Already backed by a real user.
443 + if ( $customer->get_id() ) {
444 + return;
445 + }
446 +
447 + if ( ! $this->cart_has_subscription() ) {
448 + return;
449 + }
450 +
451 + $billing_email = $customer->get_billing_email();
452 +
453 + // Cannot create an account without an email.
454 + if ( empty( $billing_email ) ) {
455 + return;
456 + }
457 +
458 + // Never $customer->set_id() + save() here: it blanks user_email.
459 + $this->maybe_create_user( $this->build_user_info( $customer ) );
460 + }
461 +
462 + /**
463 + * Assign a user to a guest subscription order, creating one if needed.
464 + *
465 + * @param \WC_Order $order Order object.
466 + *
467 + * @return void
468 + */
469 + public function maybe_assign_user_to_order( $order ) {
470 + if ( ! $this->should_auto_create_account() ) {
471 + return;
472 + }
473 +
474 + if ( ! $order instanceof \WC_Order ) {
475 + return;
476 + }
477 +
478 + // Don't proceed if the order already has a user.
479 + if ( $order->get_customer_id() ) {
480 + return;
481 + }
482 +
483 + if ( ! $this->cart_has_subscription() ) {
484 + return;
485 + }
486 +
487 + // Reuse the user created earlier in this request when there is one.
488 + $user_id = get_current_user_id();
489 +
490 + if ( ! $user_id ) {
491 + $user_info = $this->build_user_info( $order );
492 +
493 + if ( empty( $user_info['billing_email'] ) ) {
494 + return;
495 + }
496 +
497 + $user_id = $this->maybe_create_user( $user_info );
498 + }
499 +
500 + if ( ! $user_id ) {
501 + return;
502 + }
503 +
504 + $order->set_customer_id( $user_id );
505 +
506 + // The classic checkout hands over an unsaved order and persists it itself.
507 + if ( $order->get_id() ) {
508 + $order->save();
281 509 }
282 510 }
283 511 }