Search code examples
woocommercehook-woocommercewordpress-rest-apiwoocommerce-rest-api

Is it possible to add a new API endpoint that uses WooCommerce's authorization?


I need to add an API endpoint in my WordPress plugin that will write to the database, etc. I want it to be triggered by a remote system that will call this new API.

However, I'd like to use the built-in WooCommerce REST authentication, the auth set up here:

enter image description here

(And no, those credentials don't work, anymore).

Is there a way to do this? To add a custom HTTP endpoint that will use the auth from WooCommerce and then run some arbitrary code that I want to run?

Or is there a way to add a hook on an existing WooCommerce API endpoint to run before that endpoint executes? I just need a way to use the existing WooCommerce REST API auth to trigger some updates I need to run in my plugin.


Solution

  • You can add a route under the Woocommerce endpoint to use this key/secret authentication system.

    Here's a working example:

    add_action('rest_api_init', function () {
        register_rest_route('wc', '/test', [
            'methods'  => 'GET',
            'callback' => 'my_awesome_func',
        ]);
    });
    
    function my_awesome_func(WP_REST_Request $request)
    {
    
        if (is_user_logged_in() && (int)wp_get_current_user()->ID === 123) {
            //your stuff only for legged in user 123
            return new WP_REST_Response('ok', 200);
        }
    
        return new WP_Error('unauthorized', __('You shall not pass'), [ 'status' => 401 ]); //can also use WP_REST_Response
    
     }
    

    This will:

    • add a new GET route under the "wc" endpoint (woocommerce one), so https://example.com/wp-json/wc/test
    • you then use "HTTP Basic auth" to pass your key and secret as per Woocommerce documentation
    • the results of is_user_logged_in() and wp_get_current_user() will depend on the correct combination of key/secret. If correct, a the associated user will be "authentified" as for Wordpress.
    • if correct combination you'll get [true, WP_user_object], if incorrect key [false, Empty_user_object].
    • If correct key and incorrect secret, a 401 will be thrown (not the one in my example, another 401 by woocommerce. my_awesome_func() is not reached in this case. I believe it's like wp-login, custom error message when correct login (key), nice ^^')

    You then need to secure your route by your rules:

    • Checking if user is logged in like if(!is_user_logged_in()) return false
    • Checking user ID wp_get_current_user()->ID
    • Checking by your role/permission system
    • now that you have user ID, you do what you want with it
    • use the WP_REST_Request $request parameter to handle GET or POST HTTP parameters.

    So it could look like:

    add_action('rest_api_init', function () {
        register_rest_route('wc', '/test', [
            'methods'  => 'GET',
            'callback' => 'my_awesome_func',
        ]);
    });
    
    function my_awesome_func(WP_REST_Request $request)
    {
    
        if (is_user_logged_in() && (int)wp_get_current_user()->ID === 123) {
            //your stuff only for legged in user 123
            return new WP_REST_Response('ok', 200);
        }
    
        return new WP_Error('unauthorized', __('You shall not pass'), [ 'status' => 401 ]); //can also use WP_REST_Response
    }
    

    It seems there may be proper ways to add a Woocommerce REST API endpoint (couldn't find proper documentation about it...). But I tested this and it worked, at least to use the Woocommerce key/Secret authentication system, which I believe is applied under the /wc/ endpoint.

    Note: careful adding routes to the wc endpoints, as you may override an existing route endpoint. Eg: adding /product/mytest could conflict with an official Woocommerce route that handles /product/[product_id].

    Note 2: I first tested with a custom WordPress REST API route, and passing Woocommerce key/secret to see if WordPress could see me correctly authenticated and identified. But it didn't work (WP uses the core API auth system). So I moved to the Woocommerce API endpoint.

    Note 3: You could achieve the same using the Wordpress REST API with a custom route, and a "machine to machine" authentication plugins like Oauth, application password, JWT... like described on WP REST API authentication documentation page.