Call a PHP Function after WooCommerce Order Completed

WooCommerce is an extendable WordPress plugin used to develop eCommerce websites. It’s pretty much the go-to eCommerce plugin for WordPress. So important is it, that Automattic purchased it outright in 2015.

WooCommerce is dominating global e-commerce platforms, powering roughly 30% of all online stores. It’s used to sell everything, from your standard physical products, to event tickets, digital downloads and subscriptions. In this post, WooCommerce is being used to sell support tickets for solving WooCommerce problems! 🙂

Let’s say you purchase a support ticket from a WordPress website using WooCommerce. When purchasing the ticket, you are asked to supply your login details – this functionality has been set up using the WooCommerce Checkout Field Editor. Upon placing the order and making payment, the support staff begin work on your task.

This works fine, but the problem is that the login details are now stored in plaintext in the database. The staff then need to be relied on to manually purge those details once the work on your task is completed.

What we wanted to do was implement an automated way to delete the login details once an order status is changed to completed.

WooCommerce contains a number of hooks so that developers can extend the features and functionality of the plugin programmatically. And sure enough, there is an action hook available for WooCommerce so that we can call a function when an order status is changed to “completed”.

The action hook is called woocommerce_order_status_completed and this is how you use it:

add_action( 'woocommerce_order_status_completed', 'your_custom_function_call', 10, 1);

What we are doing here is telling WordPress to run the yet-to-be-defined function your_custom_function_call whenever a WooCommerce order status is changed to “completed”.

The number 10 is the priority – if more than one function needs to run when a status is changed, the lower the number, the earlier the execution. 10 is the default.

The number 1 is the number or arguments that the yet-to-be-defined function will accept. Again, 1 is the default.

Now, let’s define the function:

// define woocommerce_order_status_completed callback function
function your_custom_function_call( $int ) {
// Write your code here
}

This function receives a single argument, $int, and currently does nothing. Now, we need to write our custom code:

function your_custom_function_call( $order_id ) { 
delete_post_meta( $order_id, 'customer_username' );
delete_post_meta( $order_id, 'customer_password' );
delete_post_meta( $order_id, 'customer_website' );
}

In this example, the customer_username, customer_password and customer_website are the additional fields set by the Checkout Field Editor plugin. In this example, the function will run every time an order is set to completed. Now, let’s modify it so that it only runs when a specific product is purchased:

function your_custom_function_call( $order_id ) { 
$order = wc_get_order( $order_id );
foreach( $order->get_items() as $item ) {
if ( $item['product_id'] == 123 ) {
delete_post_meta( $order_id, 'customer_username' );
delete_post_meta( $order_id, 'customer_password' );
delete_post_meta( $order_id, 'customer_website' );
}
}
}

Finally, if you want to trigger an action when an order moves from one specific status to another, we can use the woocommerce_order_status_changed hook like so:

add_action( 'woocommerce_order_status_changed', 'your_custom_function_call', 10, 3 );
function your_custom_function_call( $order_id, $old_status, $new_status ) {
if ( $new_status == "completed" ) {
delete_post_meta( $order_id, 'customer_username' );
delete_post_meta( $order_id, 'customer_password' );
delete_post_meta( $order_id, 'customer_website' );
}
}

If you are just tweaking an existing website, this code can be added to your functions.php file. However, if you are developing a tool which you aim to use across multiple websites (or even sell), then you will need to add it to a custom plugin.

Finally, we want to check that all orders that have already been closed have had this information purged from the Order in WooCommerce. Rather than writing more PHP code to do this, it’s easier to just delete directly from the database. This is simply because, once run, the new PHP code will no longer be necessary because the function above will purge all new orders as they are completed.

Before we do anything to the database, we take a backup.

Then, to delete the customer_password record from the database on all orders that are already completed, we do this:

DELETE FROM wp_postmeta WHERE meta_key='customer_password' AND post_id IN (SELECT ID FROM wp_posts WHERE post_status='wc-completed' AND post_type='shop_order');

The SELECT statement gets the post ID of every order (post_type='shop_order') that has already been completed (post_status='wc-completed').

Then, the DELETE statement deletes the postmeta field we want deleted (meta_key='customer_password') but only on any post_id that is IN the results of the SELECT statement; that is, orders that are already completed.

Leave a Comment