76 lines
2.2 KiB
JavaScript
76 lines
2.2 KiB
JavaScript
'use strict'
|
|
require('dotenv').config()
|
|
const fs = require('fs').promises
|
|
const express = require('express')
|
|
const app = express()
|
|
|
|
const ORDERS_DIR = `${__dirname}/orders`
|
|
const SHOP_DIR = `${__dirname}/_src/shop`
|
|
const SOLD_DIR = `${__dirname}/sold`
|
|
|
|
// Run a command
|
|
const run = (cmd) => {
|
|
require('child_process').exec(cmd, (err, stdout, stderr) => {
|
|
if (err) console.error(err.message)
|
|
if (stderr) console.log(stderr)
|
|
console.log(stdout)
|
|
})
|
|
}
|
|
|
|
// Format float to USD string
|
|
const formatUSD = (v) => v.toLocaleString(undefined, {
|
|
style: 'currency', currency: 'USD' })
|
|
|
|
// Start webhook forwarder so we don't need a public endpoint
|
|
run(`stripe listen --api-key '${process.env.STRIPE_SEC}' --forward-to 'http://localhost:${process.env.HOOK_PORT}/' --format 'JSON'`)
|
|
|
|
// Receive that webhook
|
|
app.listen(process.env.HOOK_PORT)
|
|
|
|
app.post('/', express.json(), async (req) => {
|
|
|
|
if (req.body.data.object.object==='charge') {
|
|
|
|
// Check if paid
|
|
if (!req.body.data.object.paid)
|
|
return console.log(`[${req.body.id}] Charge unpaid!`)
|
|
|
|
// Get order ID
|
|
const orderId = req.body.data.object.metadata.id
|
|
if (orderId == null)
|
|
return console.error(`[${req.body.id}] Charge has no metadata.id!`)
|
|
else
|
|
console.log(`[${req.body.id}] Charge paid for order ${orderId}`)
|
|
|
|
// Get order file
|
|
const orderFile = `${ORDERS_DIR}/${orderId}.json`
|
|
let order; try {
|
|
order = await JSON.parse(await fs.readFile(orderFile))
|
|
} catch (err) {
|
|
return console.error(`[${req.body.id}] Failed to retrieve order from ${orderFile}:\n${err}`)
|
|
}
|
|
|
|
// Save paidDate to order
|
|
try { order.paidDate = new Date()
|
|
fs.writeFile(orderFile, JSON.stringify(order,null,2))
|
|
} catch (err) {
|
|
console.error(`[${req.body.id}] Failed to write paidDate to ${orderFile}:\n${err}`)
|
|
}
|
|
|
|
// Email customer
|
|
run(`./hooks/email-customer ${order.id} ${order.contact.email} ${formatUSD(order.total)}`)
|
|
|
|
// Notify sales team
|
|
run(`./hooks/ntfy ${order.id} ${order.items.length} ${formatUSD(order.total)}`)
|
|
run(`./hooks/email-sales '${JSON.stringify(order)}'`)
|
|
|
|
// Remove single products from store
|
|
order.items.forEach((item) => {
|
|
if (item.sid)
|
|
run(`./hooks/remove_sid ${item.sid} ${SHOP_DIR} ${SOLD_DIR} ${__dirname}`)
|
|
})
|
|
|
|
}
|
|
|
|
})
|