Skip to content

Commit

Permalink
apply discount (case b)
Browse files Browse the repository at this point in the history
  • Loading branch information
Sam Ban committed Sep 16, 2022
1 parent acb251b commit e4e94b2
Show file tree
Hide file tree
Showing 3 changed files with 190 additions and 51 deletions.
3 changes: 2 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,8 @@
"dependencies": {
"dotenv": "^16.0.2",
"node-fetch": "^3.2.10",
"redis": "^4.3.1"
"redis": "^4.3.1",
"request": "^2.88.2"
},
"imports": {
"@/*": "./src/*"
Expand Down
98 changes: 88 additions & 10 deletions server.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,26 +4,52 @@ import { auth } from './src/auth.js';
import url from 'url';
import { createClient } from 'redis';
import { createWebhook, getVerification } from './src/sheerid.js';
import { nano } from './src/nano.js';
import { getCartDiscounts, createCartDiscount, createDiscountCode, applyDiscount, getCart, getCarts } from './src/discount.js';
import fetch from 'node-fetch';

const redis = createClient();
redis.on('error', (err) => console.log('Redis Client Error', err));
const token = await auth();

console.log('connecting to Redis...');
await redis.connect();
const 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();
}

const verificationStatus = async (verificationId) => {
return await getVerification(verificationId);
}

const onSuccess = async (cartId, verificationData) => {
// create new discount code
// add directDiscount to cart
return await redis.set(`cart-${cartId}`, JSON.stringify(verificationData));
}

import { getCartDiscounts, createCartDiscount, createDiscountCode } from './src/discount.js';
const updateCart = async (sessionId, cartId) => {
const existing = await redis.get(`cartid-${sessionId}`);
if (existing) {
return;
}
const code = "ST"+makeid(6)
console.log('updating cart', cartId, code);
const cart = await getCart(token, cartId);
const res = await createDiscountCode(token, "Student Discount", config.CART_DISCOUNT_ID, code);
if (res) {
console.log(res);
const res2 = await applyDiscount(token, cartId, cart.version, code);
console.log(res2);
await redis.set(`cartid-${sessionId}`, cartId);
}
}

const token = await auth();
const redis = createClient();
redis.on('error', (err) => console.log('Redis Client Error', err));

console.log('connecting to Redis...');
await redis.connect();

http.createServer(async (req, res) => {
if (req.url === '/' && req.method === 'GET') {
Expand Down Expand Up @@ -54,12 +80,65 @@ http.createServer(async (req, res) => {
}
res.writeHead(200, {'Content-Type': 'application/json'});
res.end(cartJson);
} else if (req.url.startsWith('/api/getcarts') && req.method === 'GET') {
const q = url.parse(req.url, true).query;
res.writeHead(200, {'Content-Type': 'application/json'});
res.end(JSON.stringify(await getCarts(token)));
} else if (req.url.startsWith('/api/update') && req.method === 'GET') {
const q = url.parse(req.url, true).query;
console.log('get /api/update', q.cid);
redis.set(`cartid-${q.cid}`, q.cart);
res.writeHead(200, {'Content-Type': 'application/json'});
res.end(`{}`);
try {
updateCart(q.cid, q.cart);
} catch (e) {
console.log(e);
}
// return;
// const storedCart = await redis.get(`cart-${q.cid}`);
// if (!storedCart) {
// return;
// }
// const rb = await fetch("https://api.europe-west1.gcp.commercetools.com/sunrise-spa/graphql", {
// "headers": {
// "authorization": "Bearer "+q.t,
// "content-type": "application/json",
// },
// "method": "POST",
// "body": "{\"operationName\":\"myCart\",\"variables\":{\"locale\":\"en\"},\"query\":\"query myCart($locale: Locale!) {\\n myCart: me {\\n activeCart {\\n cartId: id\\n version\\n lineItems {\\n lineId: id\\n name(locale: $locale)\\n productSlug(locale: $locale)\\n quantity\\n price {\\n value {\\n centAmount\\n currencyCode\\n fractionDigits\\n __typename\\n }\\n discounted {\\n value {\\n centAmount\\n currencyCode\\n fractionDigits\\n __typename\\n }\\n discount {\\n name(locale: $locale)\\n __typename\\n }\\n __typename\\n }\\n __typename\\n }\\n totalPrice {\\n centAmount\\n currencyCode\\n fractionDigits\\n __typename\\n }\\n variant {\\n sku\\n images {\\n url\\n __typename\\n }\\n attributesRaw {\\n name\\n value\\n attributeDefinition {\\n type {\\n name\\n __typename\\n }\\n name\\n label(locale: $locale)\\n __typename\\n }\\n __typename\\n }\\n __typename\\n }\\n __typename\\n }\\n totalPrice {\\n centAmount\\n currencyCode\\n fractionDigits\\n __typename\\n }\\n shippingInfo {\\n shippingMethod {\\n methodId: id\\n name\\n localizedDescription(locale: $locale)\\n __typename\\n }\\n price {\\n centAmount\\n currencyCode\\n fractionDigits\\n __typename\\n }\\n __typename\\n }\\n taxedPrice {\\n totalGross {\\n centAmount\\n currencyCode\\n fractionDigits\\n __typename\\n }\\n totalNet {\\n centAmount\\n currencyCode\\n fractionDigits\\n __typename\\n }\\n __typename\\n }\\n discountCodes {\\n discountCode {\\n codeId: id\\n code\\n name(locale: $locale)\\n __typename\\n }\\n __typename\\n }\\n shippingAddress {\\n firstName\\n lastName\\n streetName\\n additionalStreetInfo\\n postalCode\\n city\\n country\\n phone\\n email\\n __typename\\n }\\n billingAddress {\\n firstName\\n lastName\\n streetName\\n additionalStreetInfo\\n postalCode\\n city\\n country\\n phone\\n email\\n __typename\\n }\\n __typename\\n }\\n __typename\\n }\\n}\"}",
// });
// const r = await rb.json();
// const activeCart = await r.data.myCart.activeCart;
// console.log('cart version:', JSON.stringify(activeCart.version));

// const code = "ST"+makeid(6)
// console.log('updating cart', activeCart.cartId, code);
// const dc = await createDiscountCode(token, "Student Discount", config.CART_DISCOUNT_ID, code);
// console.log('discountcode:', dc);
// if (dc) {
// const qi = JSON.stringify({
// "operationName":"mutateCart",
// "variables":{
// "actions":[{"addDiscountCode":{"code": dc.code }}],
// "version":activeCart.version,
// "id":activeCart.cartId,
// },
// "query":"mutation mutateCart($actions: [MyCartUpdateAction!]!, $version: Long!, $id: String!) {\n updateMyCart(actions: $actions, version: $version, id: $id) {\n id\n version\n lineItems {\nlineId: id\nquantity\n__typename\n}\n__typename\n}\n}",
// })
// console.log('q', qi);
// fetch("https://api.europe-west1.gcp.commercetools.com/sunrise-spa/graphql", {
// "headers": {
// "authorization": "Bearer "+q.t,
// "content-type": "application/json",
// },
// "method": "POST",
// "body": qi,
// }).then(async(res)=>{
// const r = await res.json();
// console.log(r)
// });
// }

} else if (req.url === '/api/success-webhook' && req.method === 'POST') {
console.log('post /api/success-webhook');
let body = [];
Expand All @@ -76,7 +155,6 @@ http.createServer(async (req, res) => {
const cartId = r.personInfo.metadata.cartid;
console.log(`saving ${cartId} cart id`);
onSuccess(cartId, r);
updateStatus(cartId, r);
} else {
console.log('no metadata', r);
}
Expand Down
140 changes: 100 additions & 40 deletions src/discount.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,31 @@ import { config } from './config.js';

const getCartDiscount = async (token, code) => {
const res = await fetch(`${config.CTP_API_URL}/${config.CTP_PROJECT_KEY}/cart-discounts/${code}`, {
'method': 'GET',
'headers': {
'Authorization': 'Bearer ' + token,
method: 'GET',
headers: {
Authorization: 'Bearer ' + token.access_token,
},
});
return await res.json();
}

const getCart = async (token, cartId) => {
console.log("getting",cartId, token.access_token);
const res = await fetch(`${config.CTP_API_URL}/${config.CTP_PROJECT_KEY}/carts/${cartId}`, {
method: 'GET',
headers: {
Authorization: 'Bearer ' + token.access_token,
},
});
return await res.json();
}

const getCarts = async (token) => {
console.log("getting ", token.access_token);
const res = await fetch(`${config.CTP_API_URL}/${config.CTP_PROJECT_KEY}/carts`, {
method: 'GET',
headers: {
Authorization: 'Bearer ' + token.access_token,
},
});
return await res.json();
Expand All @@ -14,9 +36,9 @@ const getCartDiscount = async (token, code) => {
const getCartDiscounts = async (token) => {
const res = await fetch(
`${config.CTP_API_URL}/${config.CTP_PROJECT_KEY}/cart-discounts`, {
'method': 'GET',
'headers': {
'Authorization': 'Bearer ' + token,
method: 'GET',
headers: {
Authorization: 'Bearer ' + token.access_token,
},
});
return await res.json();
Expand All @@ -26,54 +48,92 @@ const createCartDiscount = async (token, discount) => {
const res = await fetch(
`${config.CTP_API_URL}/${config.CTP_PROJECT_KEY}/cart-discounts`,
{
'method': 'POST',
'headers': {
method: 'POST',
headers: {
'Authorization': 'Bearer ' + token.access_token,
'Content-Type': 'application/json'
},
body: JSON.stringify({
"name": {
"en": r.name,
name: {
en: r.name,
},
"value": {
"type": "relative",
"permyriad": 1000
value: {
type: "relative",
permyriad: 1000
},
"cartPredicate": "1=1",
"target": {
"type": "lineItems",
"predicate": "1=1"
cartPredicate: "1=1",
target: {
type: "lineItems",
predicate: "1=1"
},
"sortOrder": Math.random().toString(),
"isActive": true,
"requiresDiscountCode": false
sortOrder: Math.random().toString(),
isActive: true,
requiresDiscountCode: false
})
});
if (res.status != 200) {
console.log(res.status, res.body);
return false;
}
return await res.json();
}

const createDiscountCode = (prefix, name, cartDiscountId) => {
fetch(
const createDiscountCode = async (token, name, cartDiscountId, cartDiscountCode) => {
const sjson = JSON.stringify({
code: cartDiscountCode,
name: { en: name},
cartDiscounts: [
{
typeId: 'cart-discount',
id: cartDiscountId
}
],
maxApplications: 1,
isActive: true,
cartPredicate: '1=1'
})
const res = await fetch(
`${config.CTP_API_URL}/${config.CTP_PROJECT_KEY}/discount-codes`,
{
'method': 'POST',
'headers': {
'Authorization': 'Bearer ' + token.access_token,
method: 'POST',
headers: {
Authorization: 'Bearer ' + token.access_token,
'Content-Type': 'application/json'
},
body: JSON.stringify({
"code": prefix + makeid(6),
"name": name,
"cartDiscounts": [
{
"typeId": "cart-discount",
"id": cartDiscountId
}
],
"isActive": true,
"cartPredicate": "1=1"
})
})
}
body: sjson,
});
// const rr = await res;
// if (res.status < 300) {
// console.log(sjson, res.status, await res.json());
// return false;
// }
return await res.json();
}

const applyDiscount = async (token, cartId, version, discountCode) => {
console.log('applying discount to',cartId, version, discountCode);
const reqj = JSON.stringify({
version: version,
actions: [{"action": "addDiscountCode", "code": discountCode}],
});
const res = await fetch(`${config.CTP_API_URL}/${config.CTP_PROJECT_KEY}/carts/${cartId}`,
{
method: 'POST',
headers: {
Authorization: 'Bearer ' + token.access_token,
'Content-Type': 'application/json'
},
body: reqj,
});
if (res.status > 299) {
try {
console.log(reqj, res, await res.json());
} catch (e) {
console.log(e);
}
return false;
}
return await res.json();
}

export { getCartDiscount, getCartDiscounts, createCartDiscount, createDiscountCode };
export { getCartDiscount, getCartDiscounts, createCartDiscount, createDiscountCode, applyDiscount, getCart, getCarts };

0 comments on commit e4e94b2

Please sign in to comment.