Fixed monero payments and hooks

This commit is contained in:
Keith Irwin 2023-04-05 21:34:12 -06:00
parent b46c202a13
commit d601a107b2
Signed by: ki9
GPG Key ID: DF773B3F4A88DA86
8 changed files with 38 additions and 33 deletions

View File

@ -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(),

View File

@ -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'),

View File

@ -89,7 +89,7 @@ title: Order
<h2><span data-bind="visible:paymentMethod()==='USD'">💳 </span><span data-bind="visible:paymentMethod()==='XMR'"><img src="/assets/img/monero.svg" style="width:1em;height:1em"> </span>Payment</h2>
{# XMR Payment form #}
<div data-bind="hidden:(paymentMethod()!='XMR'||isPaid())">
<div data-bind="hidden:(paymentMethod()!='XMR'||isSubmitted())">
<p>Please send <code data-bind="text:unsubmitted"></code> XMR to this address: </p>
<pre><code data-bind="text:xmr_address"></code></pre>
<p>You can also click, tap, or scan this qr code:</p>
@ -102,7 +102,7 @@ title: Order
<button data-bind="click:submitStripePayment(), text:stripeSubmitButtonText(),disable:isPlacingStripeOrder()" style="margin:2em 0 1em;height:4em"></button>
</div>
<hr data-bind="hidden:(isPaid()||paymentMethod()==='USD')">
<hr data-bind="hidden:(isSubmitted()||paymentMethod()==='USD')">
{# Stripe payment status #}
<p data-bind="text:stripeText"></p>
@ -115,7 +115,7 @@ title: Order
</p>
<div data-bind="hidden:isPaid">
<p>Transactions you send will appear on this page when they are accepted into a block. <b><i>THIS COULD TAKE TEN MINUTES OR MORE</i></b>. Transactions "unlock" after receiving 10 confirmations on the blockchain, each taking a few minutes each. Once the full <span data-bind="text:totalxmr_pretty"></span> are unlocked, we'll ship your order.
<p>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.</p>
<p>You don't have to wait for the payment to unlock. After sumbitting it in your wallet app<span data-bind="visible:isSubmitted()"> (which you've done already)</span>, 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.</p>
</div><div data-bind="visible:isPaid">
<p>Your payment has been confirmed! We will ship your order as soon as possible and send an email with the tracking info.</p>
</div>

View File

@ -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),

View File

@ -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"

View File

@ -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) }

View File

@ -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) }

View File

@ -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)