103 lines
3.6 KiB
TypeScript
103 lines
3.6 KiB
TypeScript
import 'reflect-metadata';
|
||
import axios from 'axios';
|
||
import serverless from 'serverless-http';
|
||
import express from 'express';
|
||
|
||
import { OrderEngineDBSchema } from '@services/module-payments/functions/orders/schemas/order.schema';
|
||
import { SettingsCache } from '@lib/seed/graphql/Settings';
|
||
|
||
import StripeService from '@services/module-payments/services/stripe/StripeService';
|
||
import { OrderStatusEnum } from '@services/module-payments/components/components.orders';
|
||
import { PaymentStatusEnum } from '@services/module-payments/components/components.payments';
|
||
import DB from '@seed/services/database/DBService';
|
||
|
||
import {afterPaymentSuccess, afterPaymentFailed } from '@src/orders/services/order.service'
|
||
|
||
|
||
const app = express();
|
||
|
||
app.use(require('body-parser').text({ type: '*/*' }));
|
||
app.post('/payments/webhook', async function (request, response) {
|
||
const settingsI = SettingsCache.getInstance();
|
||
await settingsI.refreshCache();
|
||
|
||
|
||
const body = request.body;
|
||
const signature = request.headers['stripe-signature'];
|
||
|
||
const endpointSecret = process.env.STRIPE_HOOK_SECRET || '';
|
||
|
||
let event;
|
||
|
||
const stripeInstance = await StripeService.getInstance();
|
||
|
||
try {
|
||
event = stripeInstance.stripe.webhooks.constructEvent(body, signature as any, endpointSecret);
|
||
} catch (err) {
|
||
console.error('[STRIPE] Hooks - ERROR', err);
|
||
response.status(400).end();
|
||
return;
|
||
}
|
||
|
||
const intent = event.data.object;
|
||
console.log('[STRIPE] Hooks - event', event['type'], 'intent', intent.id);
|
||
|
||
const orderData = await (await DB.getInstance()).db
|
||
.collection('shop.orders')
|
||
.findOne({ 'paymentIntent.stripePaymentIntentData.id': intent.id });
|
||
|
||
if (!orderData) {
|
||
console.error('[STRIPE] Hooks - ERROR', 'no order found')
|
||
return;
|
||
}
|
||
|
||
switch (event['type']) {
|
||
case 'payment_intent.succeeded':
|
||
// Get the order
|
||
try {
|
||
// Update the payment Intent and it's status
|
||
const dataToSave: Partial<OrderEngineDBSchema> = {
|
||
paymentStatus: PaymentStatusEnum.paid,
|
||
orderStatus: OrderStatusEnum.processing,
|
||
};
|
||
|
||
// check if organisations ids on product
|
||
// const providersData: ProviderSchema[] = [];
|
||
// await setProviderData(orderData, await createApolloContext(), providersData);
|
||
|
||
// if (providersData.length > 0) dataToSave.providerOrderItems = providersData;
|
||
|
||
await (await DB.getInstance()).db.collection('shop.orders').updateOne({ _id: orderData._id }, { $set: dataToSave });
|
||
|
||
await afterPaymentSuccess(orderData);
|
||
} catch (error) {
|
||
console.error(error);
|
||
}
|
||
break;
|
||
case 'payment_intent.payment_failed':
|
||
const message = intent?.last_payment_error && intent?.last_payment_error.message;
|
||
console.log('Failed:', intent.id, message);
|
||
|
||
// // Get the order
|
||
try {
|
||
// Update the payment Intent and it's status
|
||
const dataToSave: Partial<OrderEngineDBSchema> = {
|
||
paymentStatus: undefined,
|
||
orderStatus: OrderStatusEnum.draft,
|
||
};
|
||
await (await DB.getInstance()).db.collection('shop.orders').updateOne({ _id: orderData._id }, { $set: dataToSave });
|
||
|
||
await afterPaymentFailed(orderData);
|
||
} catch (error) {
|
||
console.error(error);
|
||
}
|
||
break;
|
||
}
|
||
|
||
response.sendStatus(200);
|
||
});
|
||
|
||
module.exports.handler = serverless(app);
|
||
|
||
|