Skip to content

Instantly share code, notes, and snippets.

@nilsnolde
Created April 28, 2020 10:50
Show Gist options
  • Save nilsnolde/1be4fa6155c2770d0657c244c371987a to your computer and use it in GitHub Desktop.
Save nilsnolde/1be4fa6155c2770d0657c244c371987a to your computer and use it in GitHub Desktop.
/* eslint-disable camelcase */
import axios from 'axios'
import OAuth from 'oauth-1.0a'
import crypto from 'crypto-browserify'
import * as R from 'ramda'
import queryString from 'query-string'
/**
* WooCommerce REST API wrappercat
*
* @param {String} consumerKey
* @param {String} consumerSecret
* @param {Number} timeout
*/
class WooCommerceAPI {
constructor(consumerKey, consumerSecret, timeout = 60000) {
this.consumerKey = consumerKey
this.consumerSecret = consumerSecret
this.timeout = timeout
this._request = axios.create({
//baseURL: process.env.REACT_APP_WC_API_URL + '/wp-json/wc/v3',
baseURL : 'http://localhost:8080/wp-json/wc/v3',
timeout: this.timeout
})
}
/**
* Check for object
*
* @param {object} param
* @return {bool}
*/
static _isObject(obj) {
return obj === Object(obj)
}
/**
* Normalize query string for oAuth
*
* @param {object} params
* @return {string}
*/
static _normalizeQueryString(params) {
if (!params) {
return ''
}
const params_list = []
for (const p in params) {
params_list.push(p)
}
params_list.sort()
const urlQueryString = {}
for (const idx in params_list) {
/** we can't use POST with oauth which is why we have to make sure
our POST payload (may be nested, objects or arrays) is added correctly
as GET parameters which woocommerce can read **/
if (
Object.prototype.toString.call(params[params_list[idx]]) ===
'[object Object]'
) {
const prepNestedParam = (paramValue, paramKey) => {
urlQueryString[params_list[idx] + '[' + paramKey + ']'] = paramValue
}
R.forEachObjIndexed(prepNestedParam, params[params_list[idx]])
} else if (
Object.prototype.toString.call(params[params_list[idx]]) ===
'[object Array]'
) {
let cnt = 0
for (const item of params[params_list[idx]]) {
if (Object.prototype.toString.call(item) === '[object Object]') {
for (const k in item) {
urlQueryString[
params_list[idx] + '[' + cnt + ']' + '[' + k + ']'
] = item[k]
}
cnt += 1
} else {
urlQueryString[params_list[idx] + '[' + cnt + ']'] = item
}
}
} else {
const paramKey = encodeURIComponent(params_list[idx])
.replace('%5B', '[')
.replace('%5D', ']')
const paramValue = encodeURIComponent(params[params_list[idx]])
urlQueryString[paramKey] = paramValue
}
}
return '?' + queryString.stringify(urlQueryString, { encode: false })
}
/**
* Get OAuth
*
* @return {OAuth}
*/
_getOAuth() {
const data = {
consumer: {
key: this.consumerKey,
secret: this.consumerSecret
},
signature_method: 'HMAC-SHA1',
hash_function: (base_string, key) => {
return crypto
.createHmac('sha1', key)
.update(base_string)
.digest('base64')
}
}
return new OAuth(data)
}
/**
* GET requests
*
* @param {String} endpoint
* @param {Object} params
*
* @return {Object}
*/
get(endpoint, params = null) {
const method = 'GET'
const urlString = WooCommerceAPI._normalizeQueryString(params)
const oauth_params = this._getOAuth().authorize({
url:
'http://localhost:8080' +
//process.env.REACT_APP_WC_API_URL +
'/wp-json/wc/v3' +
endpoint +
urlString,
method: method
})
return this._request.get(endpoint, {
params: { ...params, ...oauth_params }
})
}
post(endpoint, data_params) {
// This is a hack. Problem is WC has some limitations for browser-side OAuth and POST
// Problem: OPTIONS preflights are not supported by WC for POST queries with body and headers
// Solution: put all parameters into querystring, incl OAuth params and don't set headers
// https://github.com/woocommerce/woocommerce/issues/14987#issuecomment-300581467
// https://github.com/woocommerce/woocommerce/issues/15395#issuecomment-305471553
const method = 'POST'
const oauth_params = this._getOAuth().authorize({
url:
//process.env.REACT_APP_WC_API_URL +
'http://localhost:8080' +
'/wp-json/wc/v3' +
endpoint +
WooCommerceAPI._normalizeQueryString(data_params),
method: method
})
return this._request.post(endpoint, null, {
params: oauth_params
})
}
put(endpoint, data_params) {
// This is a hack. Problem is WC has some limitations for browser-side OAuth and PUT
// Problem: OPTIONS preflights are not supported by WC for POST queries with body and headers
// Solution: WP introduced the _method parameter for GET to describe what should be done on the backend
// https://github.com/woocommerce/woocommerce/issues/14987#issuecomment-300581467
const _method = 'PUT'
return this.post(endpoint, { ...data_params, _method })
}
}
export default new WooCommerceAPI(
// process.env.REACT_APP_WC_CONSUMER_KEY,
// process.env.REACT_APP_WC_CONSUMER_SECRET
'ck_305da442a35475f60b32701261c72766e7597e8a',
'cs_87f87684c81e6a6df6cc5f4d393c9221047a423a'
)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment