require('dotenv').config({ override: true }); const express = require('express'); const crypto = require('crypto'); const { generateInvoicePDF } = require('./pdfGenerator'); const { sendEmailWithAttachment } = require('./mailer'); const app = express(); const PORT = process.env.PORT || 3000; // Middleware to capture raw body for Shopify webhook HMAC verification app.use(express.json({ verify: (req, res, buf) => { req.rawBody = buf; } })); // Function to verify Shopify Webhook const verifyShopifyWebhook = (req, res, next) => { const hmacHeader = req.get('X-Shopify-Hmac-Sha256'); const body = req.rawBody; const secret = process.env.SHOPIFY_WEBHOOK_SECRET; if (!hmacHeader || !body || !secret) { return res.status(401).send('Webhook verification failed: Missing headers or secret.'); } const generatedHash = crypto .createHmac('sha256', secret) .update(body, 'utf8') .digest('base64'); if (generatedHash !== hmacHeader) { return res.status(401).send('Webhook verification failed: Invalid HMAC.'); } next(); }; // Webhook endpoint for Order Creation app.post('/webhooks/orders/create', verifyShopifyWebhook, async (req, res) => { const fs = require('fs'); const logMessage = `[${new Date().toISOString()}] Received webhook request\n`; fs.appendFileSync('webhook.log', logMessage); // Acknowledge receipt of the webhook immediately res.status(200).send('Webhook received'); try { const orderData = req.body; const processMessage = `[${new Date().toISOString()}] Processing Order ${orderData.order_number}\n`; fs.appendFileSync('webhook.log', processMessage); // 1. Generate the PDF invoice const pdfBuffer = await generateInvoicePDF(orderData); // 2. Send the email with the attached PDF const customerEmail = orderData.email || orderData.contact_email; if (!customerEmail) { const errorMsg = `[${new Date().toISOString()}] Order ${orderData.order_number} has no email address associated.\n`; fs.appendFileSync('webhook.log', errorMsg); return; } await sendEmailWithAttachment( customerEmail, orderData.order_number, pdfBuffer ); const successMsg = `[${new Date().toISOString()}] Successfully processed and sent email for Order ${orderData.order_number}\n`; fs.appendFileSync('webhook.log', successMsg); } catch (error) { const errorMsg = `[${new Date().toISOString()}] Error processing order webhook: ${error.stack}\n`; fs.appendFileSync('webhook.log', errorMsg); console.error('Error processing order webhook:', error); } }); app.listen(PORT, () => { console.log(`Shopify Invoice Email Plugin running on port ${PORT}`); });