@unchainedshop/plugins
Version:
Official plugin collection for the Unchained Engine with payment, delivery, and pricing adapters
73 lines (72 loc) • 3.15 kB
JavaScript
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);
}
}