Created
December 2, 2020 07:52
-
-
Save hnestmann/1996ef390f21b444595637f88e5c1112 to your computer and use it in GitHub Desktop.
add-to-cart.js
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
const { appendFile } = require("fs"); | |
const fetch = require("node-fetch"); | |
const fs = require('fs'); | |
const params = JSON.parse(fs.readFileSync('./config.json')); | |
/* Example | |
{ | |
"accountManager": { | |
"scope": "SALESFORCE_COMMERCE_API:xxxx_xxx sfcc.yy", | |
"clientId": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx", | |
"secret": "xXxXxxx" | |
}, | |
"shopperProductSearchApi": { | |
"siteId": "xxx", | |
"searchTerm": "shoe", | |
"shortCode": "xxxx", | |
"organizationId": "f_ecom_xxx" | |
} | |
} | |
*/ | |
const startTimeStamp = (new Date()).toISOString().replace(/[^a-zA-Z0-9]/g, ""); | |
/** | |
* Logs a message to a file and optionally to console | |
*/ | |
function log(message) { | |
if (!fs.existsSync('./logs/')) { | |
fs.mkdirSync('./logs/', 0744); | |
} | |
const logFileName = `./logs/${startTimeStamp}.log` | |
fs.appendFileSync(logFileName, message + '\n'); | |
if (params.execution.verbose) { | |
console.info((new Date()).toISOString() + ': ' + message) | |
} | |
} | |
async function searchProducts(searchTerm, start, limit) { | |
log(`searching ${limit} products from point ${start}`); | |
const url = `https://${params.shopperProductSearchApi.shortCode}.api.commercecloud.salesforce.com/search/shopper-search/v1/organizations/${params.shopperProductSearchApi.organizationId}/product-search?q=${searchTerm}&siteId=${params.shopperProductSearchApi.siteId}`; | |
var token = await getAuthenticationToken(); | |
const response = await fetch(url, { | |
method: 'get', | |
headers: { | |
'Content-Type': 'application/json', | |
'Authorization': `Bearer ${token}` | |
} | |
}); | |
const searchResponseDocument = await response.json(); | |
return searchResponseDocument; | |
} | |
async function createCart() { | |
const url = `https://${params.shopperProductSearchApi.shortCode}.api.commercecloud.salesforce.com/checkout/shopper-baskets/v1/organizations/${params.shopperProductSearchApi.organizationId}/baskets?siteId=${params.shopperProductSearchApi.siteId}`; | |
var token = await getAuthenticationToken(); | |
const response = await fetch(url, { | |
method: 'post', | |
body: '{}', | |
headers: { | |
'Content-Type': 'application/json', | |
'Authorization': `Bearer ${token}` | |
} | |
}); | |
const basketResponse = await response.json(); | |
return basketResponse; | |
} | |
async function addToCart(basketId, pid) { | |
const url = `https://${params.shopperProductSearchApi.shortCode}.api.commercecloud.salesforce.com/checkout/shopper-baskets/v1/organizations/${params.shopperProductSearchApi.organizationId}/baskets/${basketId}/items?siteId=${params.shopperProductSearchApi.siteId}`; | |
var request = [ | |
{ | |
"productId": pid, | |
"quantity": 1 | |
} | |
] | |
var token = await getAuthenticationToken(); | |
const response = await fetch(url, { | |
method: 'post', | |
body: JSON.stringify(request), | |
headers: { | |
'Content-Type': 'application/json', | |
'Authorization': `Bearer ${token}` | |
} | |
}); | |
const basketResponse = await response.json(); | |
return basketResponse; | |
} | |
async function changePidInCart(basketId, itemId, pid) { | |
const url = `https://${params.shopperProductSearchApi.shortCode}.api.commercecloud.salesforce.com/checkout/shopper-baskets/v1/organizations/${params.shopperProductSearchApi.organizationId}/baskets/${basketId}/items/${itemId}?siteId=${params.shopperProductSearchApi.siteId}`; | |
var request = { | |
"productId": pid, | |
"quantity": 1 | |
} | |
var token = await getAuthenticationToken(); | |
const response = await fetch(url, { | |
method: 'patch', | |
body: JSON.stringify(request), | |
headers: { | |
'Content-Type': 'application/json', | |
'Authorization': `Bearer ${token}` | |
} | |
}); | |
const basketResponse = await response.json(); | |
return basketResponse; | |
} | |
var expiration = new Date(0); | |
var token; | |
/** | |
* Gets the authentication token and generates a new one if timed out | |
*/ | |
async function getAuthenticationToken() { | |
const url = `https://${params.shopperProductSearchApi.shortCode}.api.commercecloud.salesforce.com/customer/shopper-customers/v1/organizations/${params.shopperProductSearchApi.organizationId}/customers/actions/login?siteId=${params.shopperProductSearchApi.siteId}&clientId=${params.accountManager.clientId}`; | |
if (expiration.getTime() < Date.now() || !token) { | |
log('fetching new jwt') | |
const searchParams = JSON.stringify({ | |
"type": "guest" | |
}) | |
const authString = `${params.accountManager.clientId}:${params.accountManager.secret}`; | |
const buff = Buffer.from(authString, 'utf-8'); | |
const b64AuthString = buff.toString('base64'); | |
const response = await fetch(url, { | |
method: 'post', | |
body: searchParams, | |
headers: { | |
'Content-Type': 'application/json', | |
'Authorization': `Basic ${b64AuthString}` | |
}, | |
}); | |
const json = await response.json(); | |
// the locally held token will expire a minute before the actual | |
expiration = new Date(Date.now() + ((30 * 60) - 60) * 1000); | |
token = response.headers.get('authorization').replace('Bearer ', ''); | |
} | |
return token; | |
}; | |
/** | |
* The main 'controller' - externalized as async function | |
*/ | |
async function mainAsync() { | |
var productsInitial = await searchProducts(params.shopperProductSearchApi.searchTerm, 0, 2); | |
log(`found ${JSON.stringify(productsInitial.total)} products`); | |
var pages = Math.ceil(productsInitial.total / 25); | |
var pid1 = productsInitial.hits[0].representedProducts[0].id; | |
var pid2 = productsInitial.hits[1].representedProducts[0].id; | |
var basketResponse = await createCart(); | |
var basketId = basketResponse.basketId; | |
var addToCartResponse = await addToCart(basketId, pid1); | |
log(`added ${pid1} - basketTotal ${addToCartResponse.productTotal}`) | |
var itemId = addToCartResponse.productItems.pop().itemId; | |
var changePidResonse = await changePidInCart(basketId, itemId, pid2) | |
log(`changed to ${changePidResonse.productItems.pop().productId} - basketTotal ${changePidResonse.productTotal}`) | |
} | |
mainAsync(); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment