UNPKG

@unchainedshop/plugins

Version:

Official plugin collection for the Unchained Engine with payment, delivery, and pricing adapters

73 lines (72 loc) 3.15 kB
import { createLogger } from '@unchainedshop/logger'; import {} from '@unchainedshop/api'; import { OrderStatus } from '@unchainedshop/core-orders'; import { timingSafeStringEqual } from '@unchainedshop/utils'; import {} from "./module.js"; import {} from '@unchainedshop/core-products'; const { CRYPTOPAY_SECRET, CRYPTOPAY_MAX_RATE_AGE = '360' } = process.env; const logger = createLogger('unchained:cryptopay:handler'); export default async function handleWebhook({ secret, wallet, price, ping, }, context) { const { modules, services } = context; if (!CRYPTOPAY_SECRET || !(await timingSafeStringEqual(secret, CRYPTOPAY_SECRET))) { logger.warn(`webhook called with invalid secret`); throw new Error('Secret invalid'); } if (wallet) { const { address, blockHeight, amount, contract, decimals, currencyCode } = wallet; logger.debug('webhook received wallet data', wallet); const { orderPaymentId } = await modules.cryptopay.updateWalletAddress({ address, blockHeight, amount, contract, decimals: decimals ?? 0, currencyCode, }); const orderPayment = orderPaymentId && (await modules.orders.payments.findOrderPayment({ orderPaymentId, })); if (orderPayment) { const order = await modules.orders.findOrder({ orderId: orderPayment.orderId }); if (!order) { logger.error('Order not found for payment', { orderPaymentId, orderId: orderPayment.orderId }); throw new Error('Order not found'); } if (order.status === null) { logger.info('Initiating checkout for new order', { orderId: order._id }); await services.orders.checkoutOrder(order._id, {}); } else if (order.status === OrderStatus.PENDING) { logger.info('Processing pending order after payment update', { orderId: order._id }); await services.orders.processOrder(order, {}); } else { logger.warn('Order already processed, ignoring webhook', { orderId: order._id, status: order.status, }); throw new Error('Already processed'); } } } if (price) { logger.debug('webhook received price data', price); const { baseCurrency, token, rate, timestamp } = price; const timestampDate = new Date(timestamp); const expiresAt = new Date(new Date().getTime() + parseInt(CRYPTOPAY_MAX_RATE_AGE, 10) * 1000); const rateData = { baseCurrency, quoteCurrency: token, rate, expiresAt, timestamp: timestampDate, }; await modules.products.prices.rates.updateRates([rateData]); } if (ping) { logger.debug('webhook received ping data', ping); const { blockHeight, currencyCode } = ping; await modules.cryptopay.updateMostRecentBlock(currencyCode, blockHeight); } }