WooCommerce Subscriptions: How to Bulk Update Next Payment Date

If you run a WooCommerce Subscriptions site for long enough you will experience a situation where you need to change the Next Payment date for subscriptions. Knowing how to bulk update the next payment date in WooCommerce Subscriptions is a vital tool for developers and shop managers.

In this article I’ll explain how to change the Next Payment date on one or thousands of subscriptions at one time in a few steps:

  1. Why would I need to bulk update next payment date on a subscription?
  2. How to update Next Payment date on a WooCommerce subscription
  3. How to bulk update Next Payment Date in many WooCommerce subscriptions

Let’s get started!

Why would I need to bulk update next payment date on a subscription?

While supporting Grow Development clients there have been many business reasons where a few hundred to tens of thousands of subscriptions needed to have their next payment date changed. These reasons include:

  • The company is switching to a new 3PL and it is taking some time to get it online
  • The accounting department needs subscriptions to renew in the next calendar month
  • A supplier has a delay in providing items that will be part of a monthly subscription box
  • The company is migrating to a new payment provider
  • A subscriber contacts customer support and requests their payment be moved out one week. This is an easy change that keeps an existing customer happy and make sure they don’t cancel.
  • Subscribers who went through dunning sequence need to be moved to next billing month

Each of these reasons adds a heap of work to a store manager’s day. If there are 10,000 subscriptions that need updates, or even 10 subscriptions – it’s time to automate!

How to update Next Payment date on a Single WooCommerce Subscription

To begin here’s an example of updating the next payment date on a single subscription. This subscription is set to renew on June 18, 2021:

WooCommerce Edit Subscription page

Notice under the subscription details in the Scheduled Actions meta box there is a corresponding scheduled action that will fire the woocommerce_scheduled-subscription_payment hook. To see the scheduled actions tied to a subscription I’m using the Scheduled Actions Meta Box plugin by Shop Plugins.

To push that payment out seven days, click on the Next Payment date in the Schedule meta box and change it to June 25, 2021.

woocommerce subscriptions update next payment date

Then press Update.

WooCommerce Subscriptions Edit Subscription page new next payment date.

The Next Payment date and the time of the Scheduled Action are now updated.

This process is suitable for updating one or two subscriptions, but thousands would take too much time and would incur some human error. Next, let’s see how to do this programmatically.

How to bulk update Next Payment Date for many WooCommerce Subscriptions Programmatically

Most managed WordPress hosts allow ssh connections and the target audience of this how to are developers, so we’re going to tackle this task by writing a PHP script. One of my favorite tools for running batch scripts is the WP CLI eval-file command. With this command you can execute a PHP file from the command line on a server.

The benefit of using WP CLI to run a script is that the WordPress environment loaded and available from inside the script. This means we can take advantage of WooCommerce Subscriptions helper functions to update subscriptions.

How to organize the bulk update script

The script will need to do three things:

  1. Identify the subscriptions to be updated
  2. Loop through the subscriptions and handle restart
  3. Update the next payment date

Get Subscriptions

The easiest way to get subscriptions that need to be updated is to use a reporting tool to get the ID of each subscription. Most of our clients use Metorik for reporting and with that tool they can identify a segment of active subscriptions and export the subscription ID to a CSV.

The IDs can be added to an array() and used in the next step.

$subscription_ids = ['10001','100033','22233','44425'];

Another alternative is to run a custom SQL command to pull subscriptions that meet certain criteria. To do this you’ll need to JOIN the posts and postmeta tables. This example pulls all subscriptions with Active status that have a next payment in the month of June, 2021:

$subscription_ids = $wpdb->get_results(
		$wpdb->prepare( "
			SELECT wp_postmeta.post_id
			FROM wp_postmeta
			INNER JOIN wp_posts ON wp_postmeta.post_id = wp_posts.ID
			AND wp_posts.post_status IN ( 'wc-active' )
			AND wp_postmeta.meta_key = '_schedule_next_payment'
			AND wp_postmeta.meta_value != 0
			AND wp_postmeta.meta_value > '2021-06-01 00:00:00'
			AND wp_postmeta.meta_value < '2021-06-30 23:59:59'
			",
		),
		ARRAY_A
	);

Setup your loop

The array from the previous step can be used in a simple foreach() loop to work on each subscription individually.

foreach ( $subscription_ids as $sub_id ) {

Update next payment date

If the new date will be the same for all subscriptions you can add the date to a variable and be done.

$new_date = '2021-08-01 00:09:00';

If the new date needs to change based on the subscription you will need to query the current date. Next let’s get the subscription object using the WooCommerce Subscription helper function:

$subscription = wcs_get_subscription( $sub_id );

It the subscription is not valid the helper function will return false. Finally use another helper function to update the next payment date:

try {
	$subscription->update_dates( array( 'next_payment' => gmdate( 'Y-m-d H:i:s', $new_date ) )
);
	$subscription->save();
	WP_CLI::log( "Updated {$sub_id}." );
} catch ( \Exception $e ) {
	WP_CLI::log( 'Error: ' . $e->getMessage() );
}

It’s important to use the helper function to update the date so that the old scheduled action is cancelled and a new action with the new date is created. The helper function will throw an exception if there is a problem updating the subscription so the code is wrapped in a try/catch block.

Run the script

Here’s the entire update script:

<?php
/**
 * Update next payment date for selected subscriptions to future date.
 *
 * Run `wp eval-file update-subscriptions.php`
 */

// array holding the IDs of subscriptions to be updated
$subscription_ids = ['10001','100033','22233','44425'];
// date to update Next Payment
$new_date = '2021-08-01 00:09:00';

foreach ( $subscription_ids as $sub_id ) {
   $subscription = wcs_get_subscription( $sub_id );
   try {
      $subscription->update_dates( array( 'next_payment' => gmdate( 'Y-m-d H:i:s', $new_date ) )
      );
      $subscription->save();
      WP_CLI::log( "Updated subscription $sub_id." );
   } catch ( \Exception $e ) {
      WP_CLI::log( 'Error: ' . $e->getMessage() );
   }
}
WP_CLI::log( 'Finished!' );

I named the script update-subscriptions.php so that file can be uploaded to the store in the root directory. It’s a good practice to remove these scripts after they are used, or to store them in a locked down sub folder.

I can use this command to execute the script:

$ wp eval-file update-subscriptions.php

If you use WP CLI output there will be nice log showing the output of the script:

$ wp eval-file update-subscriptions.php
Updated subscription 10001.
Updated subscription 100033.
Updated subscription 22233.
Updated subscription 44425.
Finished!
$

You can now be assured that these subscriptions will renew on the new date correctly.

Final thoughts

Bulk updating the next payment date is a skill to keep in your toolbox if you’re managing a large WooCommerce site. This script can be expanded to be re-run in ssh environments with a timeout (Example: WPEngine). The subscription also needs to use a payment gateway that allows payment date changes.

If you have any questions ask them below, Get in Touch, or ping Grow Development on Twitter!

Daniel Espinoza

Daniel has been building ecommerce plugins and sites since 2007. He built the first commercial plugin for WooCommerce in 2011 and has built dozens of plugins and sites since.

Have a question? Ask it below and we will try to help!

Important:
  • Write all questions in English.
  • Please wrap any code with [php] [/php]
  • Be kind!