Skip to content

Commit

Permalink
initial commit
Browse files Browse the repository at this point in the history
  • Loading branch information
Sam Ban committed Aug 19, 2022
0 parents commit 4d495a6
Show file tree
Hide file tree
Showing 9 changed files with 238 additions and 0 deletions.
5 changes: 5 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
node_modules
.env
*.csv

yarn.lock
41 changes: 41 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
# Commercetools SheerID discount codes

This is a quick overview of how to integrate [SheerID verification](https://www.sheerid.com/) to your commercetools (https://www.commercetools.com/) site without automatic processes.

## Requirements
- a commercetools website, access to Merchant Center with a user that has access to the Settings > Developer settings > API keys
- a SheerID account
- computer with nodejs v16 or not much higher (should work from v10 and with recent versions but no guarantees)

## Installation

Preparation, this process does not install anything outside of the cloned folder.

- clone the repository to your local machine
- run `yarn` or `npm install` to install the dependencies

## The process

How to use:
- Create a cart discount on your system (e.g. 20% off for students)
- Create a commercetools API client in Merchant Center > Settings > Developer settings > API clients
- Scope can be "Admin client" (not recommended) or "Manage" Cart discounts and Discount codes
- Download the created API client's "Environment variables (.env)" file before closing the popup
- Add the .env file to the project root
- Run `node get-cart-discounts.js`, copy the desired ID (UUID format, like `f9c4718e-0792-4f08-a802-70f81ef9d46d`)
- Run `node generate-discount-codes.js STUD20- f9c4718e-0792-4f08-a802-70f81ef9d46d 20 > newcodes.csv`
- Check `newcodes.csv` for the generated discount codes
- Sanity check the generated discount codes in Merchant Center > Discounts > Discount code list
- Test code behaviours in the cart without using them, or by removing the used up codes from the csv
- On https://my.sheerid.com/
- Create a SheerID program, e.g. "Student discount"
- Upload `newcodes.csv` to the Codes step "Single-Use Codes" card
- Copy the Web URL from Publish step "New Page"

- Add the copied Web URL to your website as a banner link or button
- Test linked banner on your website, fill the form, copy the code and test cart and checkout (the code will be invalidated in SheerID system immediately after successful verification)
- Don't forget to switch the program to Live mode on https://my.sheerid.com/

## This repository

This is spike code. Feel free to copy-paste from it, if you like playing with razors blindfolded.
67 changes: 67 additions & 0 deletions generate-discount-codes.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
var request = require('request');
var config = require('dotenv').config().parsed;

const auth = require('./src/auth');
const nano = require('./src/nano');
const getCartDiscount = require('./src/discount');

function makeid(length) {
var result = '';
var characters = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
var charactersLength = characters.length;
for (var i = 0; i < length; i++) {
result += characters.charAt(Math.floor(Math.random() * charactersLength));
}

return (result.substring(0, length / 2) + nano() + result.substring(length / 2, length)).toUpperCase();
}

async function main() {
if (process.argv.length < 5) {
console.log('Usage: node generate-discount-codes.js <prefix> <cart discount id (UUID)> <number of codes>');
return;
}
const token = await auth();
if (token.error) {
console.log(token.error);
return;
}

const prefix = process.argv[2];
const cartDiscountId = process.argv[3];
const numberOfCodes = process.argv[4];

const discount = await getCartDiscount(cartDiscountId, token.access_token);
const name = discount.name.en;
console.log('Discount Codes');

for (let i = 0; i < numberOfCodes; i++) {
request({
'method': 'POST',
'url': `${config.CTP_API_URL}/${config.CTP_PROJECT_KEY}/discount-codes`,
'headers': {
'Authorization': 'Bearer ' + token.access_token,
'Content-Type': 'application/json'
},
body: JSON.stringify({
"code": prefix + makeid(6),
"name": discount.name,
"cartDiscounts": [
{
"typeId": "cart-discount",
"id": cartDiscountId
}
],
"isActive": true,
"cartPredicate": "1=1"
})
}, function (error, response) {
if (error) throw new Error(error);
const res = JSON.parse(response.body);
console.log(res.code);
});
}
}

main();

29 changes: 29 additions & 0 deletions get-cart-discounts.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
var request = require('request');
var config = require('dotenv').config().parsed;

const auth = require('./src/auth');

async function main() {
const token = await auth();
if (token.error) {
console.log(token.error);
return;
}

request({
'method': 'GET',
'url': `${config.CTP_API_URL}/${config.CTP_PROJECT_KEY}/cart-discounts`,
'headers': {
'Authorization': 'Bearer '+token.access_token,
}
}, function (error, response) {
if (error) throw new Error(error);
const res = JSON.parse(response.body);
res.results.forEach(element => {
console.log(`${element.key}: ${element.id} - ${element.name.en}`);
});
});
}

main();

30 changes: 30 additions & 0 deletions get-discount-codes.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
var request = require('request');
var config = require('dotenv').config().parsed;

const auth = require('./src/auth');

async function main() {
const token = await auth();
if (token.error) {
console.log(token.error);
return;
}

request({
'method': 'GET',
'url': `${config.CTP_API_URL}/${config.CTP_PROJECT_KEY}/discount-codes`,
'headers': {
'Authorization': 'Bearer '+token.access_token,
}
}, function (error, response) {
if (error) throw new Error(error);
const res = JSON.parse(response.body);
res.results.forEach(element => {
// console.log(element)
console.log(`${element.code}: ${element.id} - ${element.name.en} (${element.cartDiscounts[0].id})`);
});
});
}

main();

10 changes: 10 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
{
"name": "commercetools-sheerid",
"version": "0.1.0",
"main": "index.js",
"license": "MIT",
"dependencies": {
"dotenv": "^16.0.1",
"request": "^2.88.2"
}
}
28 changes: 28 additions & 0 deletions src/auth.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
var config = require('dotenv').config().parsed;
var request = require('request');

const auth = async () => {
var auth = 'Basic ' + Buffer.from(config.CTP_CLIENT_ID + ':' + config.CTP_CLIENT_SECRET).toString('base64');
return new Promise(function (resolve, reject) {
request({
'method': 'POST',
'url': `${config.CTP_AUTH_URL}/oauth/token`,
'headers': {
'Authorization': auth,
'Content-Type': 'application/x-www-form-urlencoded'
},
form: {
'grant_type': 'client_credentials',
'scope': config.CTP_SCOPES
}
}, function (error, res, body) {
if (!error && res.statusCode == 200) {
resolve(JSON.parse(body));
} else {
reject(error);
}
});
});
}

module.exports = auth;
22 changes: 22 additions & 0 deletions src/discount.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
var config = require('dotenv').config().parsed;
var request = require('request');

const getCartDiscount = async (code, token) => {
return new Promise(function (resolve, reject) {
request({
'method': 'GET',
'url': `${config.CTP_API_URL}/${config.CTP_PROJECT_KEY}/cart-discounts/${code}`,
'headers': {
'Authorization': 'Bearer '+token,
},
}, function (error, res, body) {
if (!error && res.statusCode == 200) {
resolve(JSON.parse(body));
} else {
reject(error);
}
});
});
}

module.exports = getCartDiscount;
6 changes: 6 additions & 0 deletions src/nano.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
function nano() {
var hrTime = process.hrtime()
return (hrTime[0] * 1000000000 + hrTime[1]).toString(36)
}

module.exports = nano;

0 comments on commit 4d495a6

Please sign in to comment.