npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

node-shopify-api

v1.0.1

Published

OAuth2 Module for Shopify API

Downloads

32

Readme

node-shopify-api Build Status

OAuth2 Module for Shopify API

NPM

Install

npm install -S node-shopify-api

Configure Public App

Public apps are apps intended to appear in the Shopify App Store and require OAuth2 to access shop data.

var shopifyAPI = require('node-shopify-api');

var Shopify = new shopifyAPI({
  shop: 'MYSHOP', // MYSHOP.myshopify.com
  shopify_api_key: '', // Your API key
  shopify_shared_secret: '', // Your Shared Secret
  shopify_scope: 'write_products',
  shopify_version: '2024-01',
  redirect_uri: 'http://localhost:3000/finish_auth',
  nonce: '' // you must provide a randomly selected value unique for each authorization request
});

Configure Private App

Private apps are created for a single shop and do not appear in the shopify app store. More info here.

var shopifyAPI = require('node-shopify-api');

var Shopify = new shopifyAPI({
  shop: 'MYSHOP', // MYSHOP.myshopify.com
  shopify_api_key: '', // Your API key
  access_token: '', // Your API password
   shopify_version: '2024-01' // API version
});

Note: If you are building a private Shopify app, then you don't need to go through the OAuth authentication process. You can skip ahead to the Making Requests section.

CAUTION!!!

If no config object is passed into the module upon initialization, an error will be thrown!

var Shopify = new shopifyAPI(); // No config object passed in

will throw an error like:

> Error: ShopifyAPI module expects a config object
> Please see documentation at: https://github.com/asacarter/node-shopify-api

Usage


// Building the authentication url for a permanent access token
var auth_url = Shopify.buildAuthURL();

// Building the authentication url for an online user access token
var auth_url = Shopify.buildAuthURL('online');

// Assuming you are using the express framework
// you can redirect the user automatically like so
res.redirect(auth_url);

Exchanging the temporary token for a permanent one

After the user visits the authenticaion url they will be redirected to the location you specified in the configuration redirect_url parameter.

Shopify will send along some query parameters including: code (your temporary token), signature, shop, state and timestamp. This module will verify the authenticity of the request from shopify as outlined here in the Shopify OAuth Docs


// Again assuming you are using the express framework

app.get('/finish_auth', function(req, res){

  var Shopify = new shopifyAPI(config), // You need to pass in your config here
    query_params = req.query;

  Shopify.exchange_temporary_token(query_params, function(err, data){
    // This will return successful if the request was authentic from Shopify
    // Otherwise err will be non-null.
    // The module will automatically update your config with the new access token
    // It is also available here as data['access_token']
  });

});

Note:

Once you have initially received your access token you can instantiate a new instance at a later date like so:

var Shopify = new shopifyAPI({
  shop: 'MYSHOP', // MYSHOP.myshopify.com
  shopify_api_key: '', // Your API key
  shopify_shared_secret: '', // Your Shared Secret
  access_token: 'token', //permanent token
});

Making requests

This module supports GET, POST, PUT and DELETE rest verbs. Each request will return any errors, the data in JSON formation and any headers returned by the request.

An important header to take note of is 'http_x_shopify_shop_api_call_limit'. This will let you know if you are getting close to reaching Shopify's API call limit.

API limits

function callback(err, data, headers) {
  var api_limit = headers['http_x_shopify_shop_api_call_limit'];
  console.log( api_limit ); // "1/40"
}

GET

Shopify.get('/admin/products.json', query_data, function(err, data, headers){
  console.log(data); // Data contains product json information
  console.log(headers); // Headers returned from request
});

The argument query_data is optional. If included it will be converted to a querystring and appended to the uri.

POST

var post_data = {
  "product": {
    "title": "Burton Custom Freestlye 151",
    "body_html": "<strong>Good snowboard!</strong>",
    "vendor": "Burton",
    "product_type": "Snowboard",
    "variants": [
      {
        "option1": "First",
        "price": "10.00",
        "sku": 123
      },
      {
        "option1": "Second",
        "price": "20.00",
        "sku": "123"
      }
    ]
  }
}

Shopify.post('/admin/products.json', post_data, function(err, data, headers){
  console.log(data);
});

PUT

var put_data = {
  "product": {
    "body_html": "<strong>Updated!</strong>"
  }
}

Shopify.put('/admin/products/1234567.json', put_data, function(err, data, headers){
  console.log(data);
});

DELETE

Shopify.delete('/admin/products/1234567.json', function(err, data, headers){
  console.log(data);
});

Errors

Every response from Shopify's API is parsed and checked if it looks like an error. Three keys are used to determine an error response: 'error_description', 'error', and 'errors'. If any of these keys are found in the response, an error object will be made with the first found key's value as the error message and the response's status code as the error's code. This error object will be passed as the first parameter in the callback, along with the response JSON and response headers.

If an error occurs while making a request, the callback will be passed an error object provided from https as the only parameter.

OPTIONS

Verbose Mode

By default, node-shopify-api will automatically console.log all headers and responses. To suppress these messages, simply set verbose to false.

var config = {
  ...
  verbose: false
}
Additional Verbose Options

If only a particular message type(s) is desired it may be specifically requested to override the standard verbose console logging.

Available logging options: * verbose_status * verbose_headers * verbose_api_limit * verbose_body

var config = {
  ...
  verbose_headers: true,
  verbose_api_limit: true
}

The above config results in only messages beginning as type HEADER: and API_LIMIT: to be logged.

This is a more ideal use case for a production server, where excessive body content logging may obstruct developers from isolating meaningful server data.

Verify Shopify Request

Note: This module has been updated to use HMAC parameter instead of the deprecated "signature".

From the shopify docs:

"Every request or redirect from Shopify to the client server includes a signature and hmac parameters that can be used to ensure that it came from Shopify. The signature attribute is deprecated due to vulnerabilities in how the signature is generated."

The module utilizes the is_valid_signature function to verify that requests coming from shopify are authentic. You can use this method in your code to verify requests from Shopify. Here is an example of its use in the this module:

ShopifyAPI.prototype.exchange_temporary_token = function(query_params, callback) {

  // Return an error if signature is not valid
  if (!self.is_valid_signature(query_params)) {
    return callback(new Error("Signature is not authentic!"));
  }

  // do more things...
}

You can call it from an initialized Shopify object like so

Shopify.is_valid_signature(query_params);

To verify a Shopify signature that does not contain a state parameter, just pass true as the second argument of is_valid_signature:

Shopify.is_valid_signature(query_params, true);

This is required when checking a non-authorization query string, for example the query string passed when the app is clicked in the user's app store

API Call Limit Options

By default, node-shopify-api will automatically wait if you approach Shopify's API call limit. The default setting for backoff delay time is 1 second if you reach 35 out of 40 calls. If you hit the limit, Shopify will return a 429 error, and by default, this module will have a rate limit delay time of 10 seconds. You can modify these options using the following parameters:

var config = {
  //...
  rate_limit_delay: 10000, // 10 seconds (in ms) => if Shopify returns 429 response code
  backoff: 35, // limit X of 40 API calls => default is 35 of 40 API calls
  backoff_delay: 1000 // 1 second (in ms) => wait 1 second if backoff option is exceeded
}

Alternatively if you are working on a Shopify Plus or Gold project or if you get increased API limits from your Shopify rep you can use 'backoff_level' to specify at what fraction of bucket capacity your app should start backing off.

var config = {
  //...
  rate_limit_delay: 10000, // 10 seconds (in ms) => if Shopify returns 429 response code
  backoff_level: 0.85, // limit X/bucket size API calls => no default since 'backoff' is the default behaviour
  backoff_delay: 1000 // 1 second (in ms) => wait 1 second if backoff option is exceeded
}

Become a Shopify App Developer

Join the Shopify Partner Program

Testing

npm install
npm test

Contributing

I will continue to make updates as often as possible but we are more than happy to review any feature requests and will be accepting pull requests as well.