Skip to content
Advertisement

WooCommerce Subscriptions – Automatically complete renewal orders and Subscription status

I am working on a site which uses WooCommerce Subscriptions and WooCommerce Memberships. It sells subscriptions which renew annually.

The only payment gateway being used is Cheque (renamed to Pay via Invoice), so all renewals are manual renewals. An invoice is sent to the customer (outside of WooCommerce) and the store owners mark the order as Completed in admin when payment has been made.

The Subscription status is tied to the latest order status:

  • if the order is completed, the sub is Active.

  • if the order is pending, processing, on hold etc, the sub is On Hold.

As invoices are being sent and processed via an external accounting system, the client wants to have renewal orders automatically complete so that there is no break in membership access for users.

I’ve looked at similar questions such as here and I’m running into similar issues.

Change subscription status to active based on order id WooCommerce

I’ve tested the hook woocommerce_new_order and can see it’s firing for all orders, including renewals.

Using wcs_get_subscriptions_for_order(), it’s possible to pass 'renewal' as an order_type to test if the given order is a renewal or a new customer.

I have a very small bit of code to check the new order, update it if applicable, and update the subscription status afterwards. However, it seems that my first if block is being skipped over – it always runs to the code in the else block.

Additionally, if I move the lines to update the order and sub status to the else block (so it does update all orders), the order status updates but the sub stays as On Hold.

I’m guessing there must be some trigger that is usually called if updating the order from admin or via payment that isn’t firing, but I can’t see from the docs what it would be.

Can anyone advise where I’m going wrong here, please?

<?php

/**
 * Autocomplete Renewal Orders
 */

function ctz_autocomplete_renewal_order($order_id) {
  
  /**
   * Check if the order is associated with a subscription 
   * 
   * WC Subscriptions gives us a function to obtain the related orders for a subscription in an array. The second parameter allows us to retrieve only renewal orders.
   * 
   * We can use this function to check if the given order ID is for a new customer order or an existing customer's renewal. 
   * 
   * If this array returns blank, it's a first order, and should be skipped over.
   */
  
  // Get related Subscriptions 
  
  $subscriptions = wcs_get_subscriptions_for_order($order_id, array('order_type' => 'renewal'));
  
  if(is_array($subscriptions) && !empty($subscriptions) ) :                                 
    
    // This is a renewal order - change the status 
  
    $order = wc_get_order($order_id);
    
    $order->update_status( 'completed');
    
    $order->save();
    
    // Check and update the subscription status
    
    activate_subscriptions_for_order($order);
    
    // Log the change
    
    $message = $order_id . " Renewal automatically completed.";
  
    ctz_custom_logs('autorenewals', $message);
  
  else :
    
  // This is a new order - leave unchanged 
  
    $message = $order_id . " Initial order - status unchanged.";
  
    ctz_custom_logs('autorenewals', $message);
  
  endif;
 
}

add_action('woocommerce_new_order', 'ctz_autocomplete_renewal_order', 11, 1);

?>

FYI the logging function I’m using is just for debugging and records the given message to a file.

Thanks in advance.

Advertisement

Answer

add_filter('wcs_renewal_order_created', 'wcs_after_create_renewal_order', 10, 2);

function wcs_after_create_renewal_order($renewal_order, $subscription) {

    // Set the current renewal order as completed.
    $renewal_order->update_status('completed');
    $renewal_order->add_order_note( __( 'Renewal automatically processed' ) );

    // Set the corresponding subscription as active.
    $subscription->update_status('active');
    return $renewal_order;
}

The hook wcs_renewal_order_created is fired only after a renewal order is created. Simply add the code snippet above into your active theme functions.php file.

User contributions licensed under: CC BY-SA
7 People found this is helpful
Advertisement