Custom WooCommerce Webhook Topic

I need to send WooCommerce webhook requests only when an order is completed. But WooCommerce does not have any webhook topic for order completion. I created the custom topic ‘Custom Order Completed‘. Here is my code below.

Custom WC Webhook Manager
Add new webhook topic only for WC order completed.
Developed by Md Jahidul Islam ( oneTarek )
//Don't allow direct access
if( ! defined( 'ABSPATH' ) ) exit;
if( ! class_exists( 'Custom_WC_Webhook_Manager' ) ) :
class Custom_WC_Webhook_Manager {
public function __construct() {
add_filter('woocommerce_webhook_topics', array( $this, 'add_custom_webhook_topics' ), 10, 1 );
add_action('woocommerce_order_status_completed', array( $this, 'on_woocommerce_order_status_completed' ), 10, 2 );
add_filter('woocommerce_webhook_payload', array( $this, 'add_custom_webhook_payload' ), 10, 4 );
Custom topics must start with 'action.woocommerce_' or 'action.wc_'
described in the function wc_is_webhook_valid_topic
If the topic name starts with 'action' then there must has a wp hook named with the string used after dot(.)
So for this Topic we must have a wp hook 'wc_custom_order_completed'.
Adding custom topic hooks using filter 'woocommerce_webhook_topic_hooks' does not work here.
public function add_custom_webhook_topics( $topics ){
$topics['action.wc_custom_order_completed'] = 'Custom Order completed';
return $topics;
//Trigger wc_custom_order_completed hook on woocommerce_order_status_completed hook.
public function on_woocommerce_order_status_completed( $order_id, $order ){
//We could use 'woocommerce_order_status_completed' hook name directly with the topic name.
//But we are not using that direclty because , if in future WC pluign add new topic using that hook.
do_action('wc_custom_order_completed', $order_id, $order );
* Set payload for our custom topic.
public function add_custom_webhook_payload( $payload, $resource, $resource_id, $webhook_id ) {
if( isset( $payload['action'] ) && $payload['action'] == 'wc_custom_order_completed' && !empty( $payload['arg'] ) ) {
$webhook = wc_get_webhook( $webhook_id );
// Build the payload with the same user context as the user who created
// the webhook — this avoids permission errors as background processing
// runs with no user context.
//See build_payload() in woocommerce/includes/class-wc-webhook.php
$current_user = get_current_user_id();
wp_set_current_user( $webhook->get_user_id() );
$version = str_replace( 'wp_api_', '', $webhook->get_api_version() );
$resource = 'order';
$payload = wc()->api->get_endpoint_data( "/wc/{$version}/{$resource}s/{$resource_id}" );
// Restore the current user.
wp_set_current_user( $current_user );
return $payload;
}//end class
$Custom_WC_Webhook_Manager = new Custom_WC_Webhook_Manager();

Leave a Reply

Your email address will not be published. Required fields are marked *


This site uses Akismet to reduce spam. Learn how your comment data is processed.