0

I need to implement vuejs to load the categories of my store. I've read that the woocoomerce rest api need authenticate requets to work, so I'm trying to get the categories using oauth on localhost with https enabled:

// This is in my functions file to pass the parameters
// wp_localize_script( 'main', 'woo', 
    //   array(
    //     'ajaxurl' => 'wp-ajax.php',
    //     'timestamp' => time(),
    //     'hash' => hash_hmac(),
    //     'nonce'
    //   )
    // );

AJAX

// This is the JS part
//$.ajax({
        //method: 'GET',
        //url: 'wp-json/wc/v3/products/categories&oauth_consumer_key="+woo.consumer_key+"&oauth_signature_method="HMAC-SHA1&oauth_timestamp="+woo.timestamp+"&oauth_nonce="+woo.nonce+"&oauth_signature=+woo.hash',
        // beforeSend: function (xhr) {
        //   xhr.setRequestHeader ("Authorization", "OAuth " + btoa(username + ":" + password));
        // },

I get always a 401 response code, I'm not able to authenticate using ajax. I want to use the wp_localize_script to pass the needed timestamp and auth, but I'm not able to find how to do it correctly. Any example will be appreciated.

UPDATE:

I rewrite the che code using sally suggestion but I still get the 401 error response code. Here is the updated code

PHP

wp_register_script('main', get_template_directory_uri().'/assets/js/main.js', array('jquery'), null );
    $localize = array(
       'ajaxurl' => admin_url('admin-ajax.php'),
       // Securing your WordPress plugin AJAX calls using nonces
       'auth' => base64_encode('ck_32a46b36d90680e574e9de6456746a11cf07945:cs_0a6bd199a45c0b96e848a1401a14b18444fa46d8'),
    );
    wp_localize_script('main', 'wp', $localize);
    wp_enqueue_script('main');

JS

    const app = new Vue({
      el: '#app',
      data: {},
      created: function(){
        $.ajax({
          method: 'GET',
          url: 'wp-json/wc/v3/products/categories',
          headers: {
             'Authorization': "Basic "+ wp.auth
          },
          success: function(response){
            console.log(response);
          }
        });
      },
      destroyed: {},
      mounted: {},
    });

I'm on localhost with a self signed cert to have the https, maybe this can be the problem?

0

First off, the WooCommerce REST API documentation is available here and you should check it out.

Secondly, the examples below are using the /wc/v3/products/categories ("List all product categories") endpoint.

And here's a proper way to authenticate your request using OAuth — it always works when authenticating over HTTPS and it is the only accepted option for authenticating over HTTP:

  • It's up to you how to make the relevant variables available in JavaScript via wp_localize_script(). Or to implement the PHP code below in JavaScript.

  • You can generate your WooCommerce REST API keys via the WordPress admin interface — WooCommerce → Settings → "Advanced" tab → REST API.

// Define the request method.
$method = 'GET';
// Just set the second parameter to the proper endpoint, without /wp-json.
$url = get_rest_url( null, '/wc/v3/products/categories' );
// Define your keys.
$ck = '<put key here>'; // consumer key
$cs = '<put key here>'; // consumer secret

$params = [
    // Required parameters:
    'oauth_consumer_key'     => $ck,
    'oauth_timestamp'        => time(),
    'oauth_nonce'            => wp_create_nonce( time() ),
    'oauth_signature_method' => 'HMAC-SHA1',

    // Parameters specific to the endpoint:
    'per_page' => 2,
];

// Sort the parameters and encode them into a single string.
uksort( $params, 'strcmp' );
$params2 = '';
foreach ( $params as $key => $value ) {
    $params2 .= ( $params2 ? '%26' : '' ) .
        rawurlencode( $key ) . '%3D' . rawurlencode( $value );
}

// Create the signature base string.
$sig_base = $method . '&' . rawurlencode( $url ) . '&' . $params2;
// And generate the signature base.
$sig = base64_encode( hash_hmac( 'sha1', $sig_base, $cs . '&', true ) );

// Add the required oauth_signature parameter.
$params['oauth_signature'] = $sig;
// And build the query string.
$query = http_build_query( $params );

// Then make request to this URL:
//$req_url = $url . '?' . $query;

And here are other options you can use, but only when authenticating over HTTPS, and you should know that these will expose your consumer secret key:

  1. Use HTTP Basic Auth — set the HTTP Authorization header; i.e. Authorization: Basic <base64 encoding of <consumer key>:<consumer secret>>:

    jQuery.ajax( {
        url: '/wp-json/wc/v3/products/categories',
        headers: {
            'Authorization': 'Basic <base64-encoded value here>'
        },
        ...
    } );
    

    In PHP, you can do base64_encode( '<consumer key>:<consumer secret>' ); to get the base64-encoded value.

    And make sure the Authorization header is enabled on the server.

  2. Or provide the consumer key/secret as query string parameters — e.g. https://example.com/wp-json/wc/v3/products/categories?consumer_key=<KEY>&consumer_secret=<KEY>:

    jQuery.ajax( {
        url: '/wp-json/wc/v3/products/categories?consumer_key=<key>&consumer_secret=<key>',
        ...
    } );
    

Another option when authenticating over HTTPS, is by using the standard cookie authentication as explained here:

// This example provides the nonce as a query string parameter.
jQuery.ajax( {
    url: '/wp-json/wc/v3/products/categories?_wpnonce=<nonce>',
    ...
} );

You may also use authentication plugins, but you will need to test them on your own.

| improve this answer | |
  • I'm encoding the credentials in php using base64_encode and I'm passing the result string using the localize script, but I still get the 401 response from categories endpoint. I'm passing the headers in this way in ajax headers: { 'Authorization': "Basic "+ wp.auth }, – sialfa Feb 23 at 12:40
  • Can you update the question with your current code, both PHP & JS? That way, I can give you better suggestions/ideas. – Sally CJ Feb 23 at 13:10
  • question updated – sialfa Feb 23 at 13:22
  • Have you checked if the server actually allows the Authorization header? Also, in your $.ajax() call, your url should start with /wp-json/ and not wp-json/ even if the script is linked to from the homepage. Even better, add a localized var that points to the root REST API URL and use the var in your scripts. (e.g. add 'root' => esc_url_raw( rest_url() ), to the wp_localize_script() array) – Sally CJ Feb 23 at 13:46
  • No, I didn't checked if the server allow auth, I think it's enabled by default, I need to check apache settings right? I will consider to add the url as a variable like you suggested – sialfa Feb 23 at 14:41

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.