Skip to content

Instantly share code, notes, and snippets.

@ndvo
Last active April 9, 2021 14:59
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save ndvo/01eeea43fe9a811ad965eaf24e9ab48b to your computer and use it in GitHub Desktop.
Save ndvo/01eeea43fe9a811ad965eaf24e9ab48b to your computer and use it in GitHub Desktop.
Example Foxy.io JSON webhook written in Node
const crypto = require('crypto');
const foxyEncryptionKey = 'YOUR_ENCRYPTION_KEY_HERE';
const foxyStoreId = 'YOUR_STORE_ID_HERE';
const foxyStoreDomain = 'YOUR_STORE_DOMAIN_HERE';
const http = require('http');
const server = http.createServer(handleRequest);
const routes = {
'transaction/created': handleTransactionCreated,
}
function handleRequest(request, response) {
if (!validFoxyRequest(request)) {
response.statusCode = 403; // Forbidden
response.write('Forbidden');
return response.end();
}
const bodyChunks = [];
request.on('data', (chunk) => bodyChunks.push(chunk));
request.on('end', () => {
let body = Buffer.concat(bodyChunks).toString()
if (!validFoxySignature(request.headers['foxy-webhook-signature'], body)){
response.statusCode = 403; // Forbidden
response.write('Forbidden');
return response.end();
}
try {
body = JSON.parse(body);
} catch(e) {
response.statusCode = 400; // Bad Request
response.write('Bad Request');
return response.end();
}
const foxyEvent = request.headers['foxy-webhook-event'];
const responseData = routes[foxyEvent](request.headers, body);
console.log(responseData);
if (responseData) {
response.statusCode = 200;
response.write(JSON.stringify(responseData));
return response.end();
}
response.statusCode = 500;
response.end();
});
}
function validFoxyRequest(request) {
const postMethod = request.method === 'POST';
const headers = request.headers;
const routeForEventExists = Object.keys(routes).includes(headers['foxy-webhook-event']);
const foxySignatureExists = !!headers['foxy-webhook-signature'];
const foxyStoreIdIsCorrect = headers['foxy-store-id'] === foxyStoreId;
const foxyStoreDomainIsCorrect = headers['foxy-store-domain'] === foxyStoreDomain;
return postMethod && routeForEventExists && foxySignatureExists && foxyStoreIdIsCorrect && foxyStoreDomainIsCorrect;
}
function validFoxySignature(signature, payload) {
const referenceSignature = crypto.createHmac('sha256', foxyEncryptionKey).update(payload).digest('hex');
console.log(referenceSignature);
return signature === referenceSignature;
}
function handleTransactionCreated(headers, body) {
const emailAddress = body['customer_email'];
const billingCountry = body['_embedded']['fx:billing_addresses']['country'];
const shippingCountry = body['_embedded']['fx:shipments'][0]['country'];
// Check if there is a Product A and its size
let hasSmallA = false;;
let hasLargeA = false;;
for (let item of body['_embedded']['fx:items']) {
const name = item['name'];
const quantity = item['quantity'];
const category = item['_embedded']['fx:item_category']['code'];
if(item['name'] === "Product A") {
for (let itemOption of item['_embedded']['fx:item_options']) {
if (itemOption['name'] == 'size') {
if (itemOption['value'] === 'small') {
hasSmallA = true;
return {
ok: true,
details: "has small A"
}
} else if (itemOption['value'] === 'large') {
hasLargeA = true;
return {
ok: true,
details: "has large A"
}
}
}
}
}
}
}
server.listen(80);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment