oauth_problem=signature_invalid , Auoth 1.0 PUT request

Viewed 713

Im trying to make an api call using ETSY api to update listing inventory.

I'm getting this error : oauth_problem=signature_invalid&debug_sbs=PUT

My code is :

const request = require('request')
const OAuth = require('oauth-1.0a')
const crypto = require('crypto')

let data ='produts data';


// Initialize
const oauth = OAuth({
    consumer: {
        key: api_key,
        secret: secret
    },
    signature_method: 'HMAC-SHA1',
    hash_function(base_string, key) {
        return crypto
            .createHmac('sha1', key)
            .update(base_string)
            .digest('base64')
    },
})
const request_data = {
    url: url,
    method: 'PUT',
    data: {
        products: data.products,
        price_on_property: [513],
        quantity_on_property: [513],
        sku_on_property: [513]
    },
}

// Note: The token is optional for some requests
const token = {
    key: access_token,
    secret: access_token_secret,
}
request({
    url: request_data.url,
    method: request_data.method,
    form: request_data.data,
    headers: oauth.toHeader(oauth.authorize(request_data, token)),
},
    function (error, response, body) {
        console.log(response.body)
    });

Is there anything missing in my code?

1 Answers

The Etsy API requires the oauth parameters to be included in the post body and not the headers. The documentation is not very clear on that but sort of implies it (https://www.etsy.com/developers/documentation/getting_started/oauth#section_authorized_put_post_requests)

So your request call should look like this:

request({
    url: request_data.url,
    method: request_data.method,
    form: oauth.authorize(request_data, token)
},
function (error, response, body) {
    console.log(response.body)
});

A good tool for debugging these sort of issues is Postman (https://www.postman.com/). It's how I was able to track down this issue.

Edit:

If the request is working in Postman but you still can't get it to work in your code then you can break the process down a bit. Build the oauth paramaters manually by calling the nonce, timestamp and signature methods on the oauth object.

let oauth_data = {
    oauth_consumer_key: api_key,
    oauth_nonce: oauth.getNonce(),
    oauth_signature_method: "HMAC-SHA1",
    oauth_timestamp: oauth.getTimeStamp(),
    oauth_version: "1.0",
    oauth_token: access_token
 };
 //now generate the signature using the request data and the oauth object
 //you've just created above
 let signature = oauth.getSignature(request_data,token_secret,oauth_data);
 //now add the signature to the oauth_data paramater object
 oauth_data.oauth_signature = signature;


 //merge two objects into one
 let formData = Object.assign({},oauth_data,request_data.params);

 request({
    url: request_data.url,
    method: request_data.method,
    form: formData
 },
 function (error, response, body) {
    console.log(response.body)
 });

I found in my code that I had misnamed the consumer.secret variable when initiating the oauth object. So the consumer secret was null and therefore the signature was coming out wrong.

Also, try out a more simpler PUT call just to test that your basic PUT request works. I was doing updateShop to update the shop title (and you could actually update it to the existing title, thus not changing anything), which only needs your shop id and title string.

Related