diff --git a/_src/assets/scripts/cart.js b/_src/assets/scripts/cart.js index c367133..df5b2b0 100644 --- a/_src/assets/scripts/cart.js +++ b/_src/assets/scripts/cart.js @@ -251,19 +251,21 @@ class Cart { constructor() { phone: self.phone(), email: self.email(), }, - shippingAddress: { + shipping: { name: self.shipname(), - addr1: self.addr1(), - addr2: self.addr2(), - city: self.city(), - state: self.state(), - zip: self.zip(), + address: { + addr1: self.addr1(), + addr2: self.addr2(), + city: self.city(), + state: self.state(), + zip: self.zip(), + }, + amount: Math.round(self.shipping()*100)/100, }, subtotal: Math.round(self.subtotal()*100)/100, tax: self.tax(), taxAmount: Math.round(self.tax() * self.subtotal() * 100)/100, processing: Math.round(self.processing()*100)/100, - shippingAmount: Math.round(self.shipping()*100)/100, paymentMethod: self.payment_method(), total: self.total(), totalxmr: self.totalxmr(), diff --git a/_src/assets/scripts/order.js b/_src/assets/scripts/order.js index 2e02680..3ebeeb5 100644 --- a/_src/assets/scripts/order.js +++ b/_src/assets/scripts/order.js @@ -145,7 +145,7 @@ class Checkout { constructor(data) { ) self.transactions = ko.observableArray([]) self.xmr_uri = ko.pureComputed(() => - `monero:${self.xmr_address()}?tx_amount=${self.unsubmitted()}&tx_description=sales@slvit.us order ${self.orderId()}` + `monero:${self.xmr_address()}?tx_amount=${self.unsubmitted()}&tx_description=sales@slvit.us%20order%20${self.orderId()}` ) let xmr_qr = new QRCode( document.getElementById('xmr_qr'), diff --git a/_src/shop/order.njk b/_src/shop/order.njk index 018cc80..7bf6cc6 100644 --- a/_src/shop/order.njk +++ b/_src/shop/order.njk @@ -89,7 +89,7 @@ title: Order

💳 Payment

{# XMR Payment form #} -
+

Please send XMR to this address:

You can also click, tap, or scan this qr code:

@@ -102,7 +102,7 @@ title: Order
-
+
{# Stripe payment status #}

@@ -115,7 +115,7 @@ title: Order

Transactions you send will appear on this page when they are accepted into a block. THIS COULD TAKE TEN MINUTES OR MORE. Transactions "unlock" after receiving 10 confirmations on the blockchain, each taking a few minutes each. Once the full are unlocked, we'll ship your order. -

You don't have to wait for the payment to unlock. After sumbitting it in your wallet app, you can close this window. We sent a link to this page to the email specified, if you ever want to come back and check on the order.

+

You don't have to wait for the payment to unlock. After sumbitting it in your wallet app (which you've done already), you can close this window. When the payment confirms, we'll send a link to this page to the email specified, if you ever want to come back and check on the order.

Your payment has been confirmed! We will ship your order as soon as possible and send an email with the tracking info.

diff --git a/api/order-add.js b/api/order-add.js index 428ac32..46f8cf8 100644 --- a/api/order-add.js +++ b/api/order-add.js @@ -108,9 +108,9 @@ module.exports = async (req, res) => { }) const taxesPromise = new Promise((resolve, reject) => { - if (!order.shippingAddress.state) reject(`order.shippingAddress.state not provided!`) + if (!order.shipping.address.state) reject(`order.shipping.address.state not provided!`) let tax = 0 - if (order.shippingAddress.state==='CO') tax = 0.049 + if (order.shipping.address.state==='CO') tax = 0.049 else tax = 0 if (tax===order.tax) resolve(tax) else reject(`Taxes calculated as ${tax} didn't match what was sent by the client (${order.tax})`) @@ -118,12 +118,12 @@ module.exports = async (req, res) => { const shippingPromise = new Promise(async (resolve, reject) => { if (!order.items.length) reject('order.items is untrue!') - if (!order.shippingAddress.zip) reject('order.shippingAddress.zip is unset!') - let shipping = Math.round( getUspsRates(order.shippingAddress.zip, + if (!order.shipping.address.zip) reject('order.shipping.address.zip is unset!') + let shipping = Math.round( getUspsRates(order.shipping.address.zip, await weightPromise, await volumePromise ) * 100 )/100 - if (shipping===order.shippingAmount) resolve(shipping) + if (shipping===order.shipping.amount) resolve(shipping) else reject(`Shipping calculation of ${shipping} didn't match what the client sent (${order.shipping})`) }) @@ -164,13 +164,13 @@ module.exports = async (req, res) => { key: order.key, }, shipping: { - name: order.shippingAddress.name, + name: order.shipping.name, address: { - line1: order.shippingAddress.addr1, - line2: order.shippingAddress.addr2, - city: order.shippingAddress.city, - postal_code: order.shippingAddress.zip, - state: order.shippingAddress.state, + line1: order.shipping.address.addr1, + line2: order.shipping.address.addr2, + city: order.shipping.address.city, + postal_code: order.shipping.address.zip, + state: order.shipping.address.state, country: 'US', }, } @@ -273,10 +273,10 @@ module.exports = async (req, res) => { contact: processedOrder.contact, shipping: { date: null, - address: processedOrder.shippingAddress, + address: processedOrder.shipping.address, carrier: '', tracking: [], - amount: parseFloat(processedOrder.shippingAmount), + amount: parseFloat(processedOrder.shipping.amount), }, subtotal: parseFloat(processedOrder.subtotal), tax: parseFloat(processedOrder.tax), diff --git a/docker-compose.yml.sample b/docker-compose.yml.sample index 10d9702..4135c7a 100644 --- a/docker-compose.yml.sample +++ b/docker-compose.yml.sample @@ -61,6 +61,7 @@ services: - "./_site:/app/_site:ro" - "./orders:/app/orders" - "./sold:/app/sold" + - "./hooks:/app/hooks:ro" - "./listeners:/app/listeners:ro" - "./api:/app/api:ro" - "./lib:/app/lib:ro" diff --git a/hooks/email-customer.js b/hooks/email-customer.js index 2144b64..c9c2e12 100644 --- a/hooks/email-customer.js +++ b/hooks/email-customer.js @@ -14,7 +14,7 @@ module.exports = async (order) => { to: order.contact.email, replyTo: process.env.SALES_EMAIL, subject: `Order ${order.id} for ${amt} has been processed`, - text: `Dear ${order.contact.name},\n\nThank you for your payment. We will ship your order as soon as possible and send the tracking info to this email address. For now, keep this copy of your order details as proof of your payment. \n\n---\n\nITEMS: \n${customer_mail_items_string}\nTOTALS: \nSubtotal: ${formatUSD(order.subtotal)}\nTax: ${formatUSD(order.taxAmount)}\nShipping: ${formatUSD(order.shipping.amount)}\nProcessing: ${formatUSD(order.processing)}\nTOTAL: ${formatUSD(order.total)}${(order.paymentMethod==='XMR')?'\nMONERO TOTAL: '+amt:''}\n\nCONTACT: \n${order.contact.name}\n${order.contact.phone}\n${order.contact.email}\n\nSHIPPING ADDRESS:\n${order.shipping.address.name}\n${order.shipping.address.addr1}${(order.shipping.address.addr2)?'\n'+order.shipping.address.addr2:''}\n${order.shipping.address.city}, ${order.shipping.address.state} ${order.shipping.address.zip}\n\n---\n\nTo view your order info anytime, visit this page: ${process.env.SITE_DOMAIN}/shop/order/stripe/?order=${order.id}&key=${order.key}\n\nFor questions, comments, or to cancel this order, reply to this email or call 719-936-7778 x1. \n\nThank you!\n`, + text: `Dear ${order.contact.name},\n\nThank you for your payment. We will ship your order as soon as possible and send the tracking info to this email address. For now, keep this copy of your order details as proof of your payment. \n\n---\n\nITEMS: \n${customer_mail_items_string}\nTOTALS: \nSubtotal: ${formatUSD(order.subtotal)}\nTax: ${formatUSD(order.taxAmount)}\nShipping: ${formatUSD(order.shipping.amount)}\nProcessing: ${formatUSD(order.processing)}\nTOTAL: ${formatUSD(order.total)}${(order.paymentMethod==='XMR')?'\nMONERO TOTAL: '+amt:''}\n\nCONTACT: \n${order.contact.name}\n${order.contact.phone}\n${order.contact.email}\n\nSHIPPING ADDRESS:\n${order.shipping.name}\n${order.shipping.address.addr1}${(order.shipping.address.addr2)?'\n'+order.shipping.address.addr2:''}\n${order.shipping.address.city}, ${order.shipping.address.state} ${order.shipping.address.zip}\n\n---\n\nTo view your order info anytime, visit this page: ${process.env.SITE_DOMAIN}/shop/order/stripe/?order=${order.id}&key=${order.key}\n\nFor questions, comments, or to cancel this order, reply to this email or call 719-936-7778 x1. \n\nThank you!\n`, }) console.log(`Sent email ${customer_mail_res.messageId} to customer for order ${order.id}`) } catch (err) { console.error(err) } diff --git a/hooks/email-sales.js b/hooks/email-sales.js index 7ae580f..f05e802 100644 --- a/hooks/email-sales.js +++ b/hooks/email-sales.js @@ -13,7 +13,7 @@ module.exports = async (order) => { from: process.env.SALES_MAIL_FROM, to: process.env.SALES_EMAIL, subject: `Order for ${amt} processed`, - text: `Order ${order.id} needs ${order.items.length} items shipped: \n\n${sales_mail_items_string}\nSHIP TO:\n${order.shipping.address.name}\n${order.shipping.address.addr1}${(order.shipping.address.addr2)?'\n'+order.shipping.address.addr2:''}\n${order.shipping.address.city}, ${order.shipping.address.state} ${order.shipping.address.zip}\n\nCONTACT:\n${order.contact.name}\n${order.contact.phone}\n${order.contact.email}\n\n---\n\nOrder page: ${process.env.SITE_DOMAIN}/shop/order/stripe/?order=${order.id}&key=${order.key}\n`, + text: `Order ${order.id} needs ${order.items.length} items shipped: \n\n${sales_mail_items_string}\nSHIP TO:\n${order.shipping.name}\n${order.shipping.address.addr1}${(order.shipping.address.addr2)?'\n'+order.shipping.address.addr2:''}\n${order.shipping.address.city}, ${order.shipping.address.state} ${order.shipping.address.zip}\n\nCONTACT:\n${order.contact.name}\n${order.contact.phone}\n${order.contact.email}\n\n---\n\nOrder page: ${process.env.SITE_DOMAIN}/shop/order/stripe/?order=${order.id}&key=${order.key}\n`, }) console.log(`Sent email ${sales_mail_res.messageId} to sales team for order ${order.id}`) } catch (err) { console.error(err) } diff --git a/listeners/monero.js b/listeners/monero.js index c651cc1..3899078 100644 --- a/listeners/monero.js +++ b/listeners/monero.js @@ -4,6 +4,7 @@ const formatUSD = (v) => v.toLocaleString(undefined, { style: 'currency', currency: 'USD' }) const fs = require('fs').promises const axios = require('axios') +const ORDERS_DIR = `${__dirname}/../orders` // Monero price let XMR_PRICE @@ -30,19 +31,20 @@ const xmrPaidCheck = async (order) => { } catch (err) { return console.error(`Failed to get update about xmr address ${order.xmr_address}\n${err}`) } - + // Throw hook if paid - if (res.amount!=null) if (res.amount.expected<=res.amount.covered.unlocked && order.paidDate==null) { - console.log(`Order ${order.id} has been paid with ${res.amount.expected/1000000000000} XMR`) + if (res.data.amount!=null) if (res.data.amount.expected<=res.data.amount.covered.unlocked && order.paidDate==null) { + console.log(`Order ${order.id} has been paid with ${res.data.amount.expected/1000000000000} XMR`) // Save payment data to order order.paidDate = new Date() - order.xmr_txs = res.transactions.map((tx) => { + order.xmr_txs = res.data.transactions.map((tx) => { tx.fee_usd = xmrToUsd(tx.fee) }) - const orderFile = `${ORDERS_DIR}/${orderId}.json` + const orderFile = `${ORDERS_DIR}/${order.id}.json` try { - fs.writeFile(orderFile, JSON.stringify(order,null,2)) + console.log(JSON.stringify(order,null,2)) + await fs.writeFile(orderFile, JSON.stringify(order,null,2)) } catch (err) { console.error(`Failed to write paidDate to ${orderFile}:\n${err}`) } @@ -57,7 +59,7 @@ const xmrPaidCheck = async (order) => { require('../hooks/email-sales')(order) // Remove single products from store - require('./remove-sid')(order) + require('../hooks/remove-sid')(order) // Remove this listener clearInterval(interval)