phonepe #61
@ -131,8 +131,173 @@ export const phonePeWebhook = onRequest({
|
||||
if (paymentUpdateSuccess) {
|
||||
const orderData = orderDoc.data();
|
||||
const membershipId = orderData.metaInfo?.membershipId;
|
||||
const bookingId = orderData.metaInfo?.bookingId;
|
||||
if (bookingId) {
|
||||
await processDayPassBooking(payload, orderData, bookingId);
|
||||
} else if (membershipId) {
|
||||
await processMembershipPayment(payload, orderData, membershipId);
|
||||
}
|
||||
}
|
||||
|
||||
logger.info(`Processing invoice for completed payment`, {
|
||||
logger.info(`Payment data updated for completed payment: ${payload.merchantOrderId}`);
|
||||
} catch (paymentUpdateError) {
|
||||
logger.error('Error updating payment data:', paymentUpdateError);
|
||||
}
|
||||
}
|
||||
|
||||
response.status(200).json({ success: true });
|
||||
|
||||
} catch (error: any) {
|
||||
logger.error('PhonePe webhook processing error:', error);
|
||||
response.status(500).json({
|
||||
success: false,
|
||||
error: 'Failed to process webhook',
|
||||
details: error.message
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
async function processDayPassBooking(payload: any, orderData: any, bookingId: string) {
|
||||
try {
|
||||
logger.info(`Processing day pass booking for bookingId: ${bookingId}`);
|
||||
|
||||
const bookingRef = admin.firestore().collection('day_pass_bookings').doc(bookingId);
|
||||
const bookingDoc = await bookingRef.get();
|
||||
|
||||
if (!bookingDoc.exists) {
|
||||
logger.error(`Day pass booking not found for bookingId: ${bookingId}`);
|
||||
return;
|
||||
}
|
||||
|
||||
await bookingRef.update({
|
||||
status: 'ACCEPTED',
|
||||
paymentDetails: {
|
||||
transactionId: payload.orderId,
|
||||
merchantOrderId: payload.merchantOrderId,
|
||||
amount: orderData.amount,
|
||||
paymentDate: new Date(),
|
||||
paymentMethod: 'PhonePe'
|
||||
},
|
||||
updatedAt: admin.firestore.FieldValue.serverTimestamp()
|
||||
});
|
||||
|
||||
logger.info(`Updated day pass booking status to 'Accepted' for bookingId: ${bookingId}`);
|
||||
|
||||
const bookingData = bookingDoc.data();
|
||||
const gymId = orderData.metaInfo?.gymId || bookingData?.gymId;
|
||||
|
||||
if (gymId) {
|
||||
try {
|
||||
const gymDoc = await admin.firestore().collection('gyms').doc(gymId).get();
|
||||
let gymName = 'Fitlien';
|
||||
let gymAddress = '';
|
||||
let gymOwnerEmail = '';
|
||||
|
||||
if (gymDoc.exists) {
|
||||
const gymData = gymDoc.data();
|
||||
gymName = gymData?.name || 'Fitlien';
|
||||
gymAddress = gymData?.address || '';
|
||||
|
||||
if (gymData?.userId) {
|
||||
const gymOwnerDoc = await admin.firestore()
|
||||
.collection('users')
|
||||
.doc(gymData.userId)
|
||||
.get();
|
||||
|
||||
if (gymOwnerDoc.exists) {
|
||||
const gymOwnerData = gymOwnerDoc.data();
|
||||
gymOwnerEmail = gymOwnerData?.email || '';
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const invoiceNumber = `INV-${payload.merchantOrderId.substring(0, 8)}`;
|
||||
|
||||
logger.info(`Generated invoice number for day pass: ${invoiceNumber}`);
|
||||
|
||||
const invoiceData = {
|
||||
invoiceNumber,
|
||||
businessName: gymName,
|
||||
address: gymAddress,
|
||||
gstNumber: orderData.metaInfo?.gstNumber,
|
||||
customerName: orderData.metaInfo?.customerName || bookingData?.customerName || '',
|
||||
phoneNumber: orderData.metaInfo?.customerPhone || bookingData?.phoneNumber || '',
|
||||
email: orderData.metaInfo?.customerEmail || bookingData?.email || '',
|
||||
planName: 'Day Pass',
|
||||
amount: orderData.amount,
|
||||
transactionId: payload.orderId,
|
||||
paymentDate: new Date(),
|
||||
paymentMethod: 'Online'
|
||||
};
|
||||
|
||||
const invoicePath = await invoiceService.generateInvoice(invoiceData);
|
||||
logger.info(`Day pass invoice generated successfully at path: ${invoicePath}`);
|
||||
|
||||
await bookingRef.update({
|
||||
invoicePath: invoicePath,
|
||||
invoiceNumber: invoiceNumber
|
||||
});
|
||||
|
||||
logger.info(`Updated day pass booking with invoice path: ${invoicePath}`);
|
||||
|
||||
const downloadUrl = await invoiceService.getInvoiceDownloadUrl(invoicePath);
|
||||
const formattedDate = format(new Date(), 'dd/MM/yyyy');
|
||||
|
||||
if (gymOwnerEmail) {
|
||||
logger.info(`Preparing to send day pass invoice email to gym owner: ${gymOwnerEmail}`);
|
||||
try {
|
||||
const ownerEmailSubject = `New Day Pass Payment - ${gymName}`;
|
||||
|
||||
const gymOwnerEmailHtml = `
|
||||
<html>
|
||||
<body>
|
||||
<h2>New Day Pass Payment Received</h2>
|
||||
<p>Dear Gym Owner,</p>
|
||||
<p>A new day pass payment has been received for your gym.</p>
|
||||
<p>Customer Details:</p>
|
||||
<ul>
|
||||
<li>Name: ${invoiceData.customerName}</li>
|
||||
<li>Phone: ${invoiceData.phoneNumber}</li>
|
||||
</ul>
|
||||
<p>Day Pass Details:</p>
|
||||
<ul>
|
||||
<li>Service: Day Pass</li>
|
||||
<li>Amount: ₹${orderData.amount.toFixed(2)}</li>
|
||||
<li>Transaction ID: ${payload.merchantOrderId}</li>
|
||||
<li>Date: ${formattedDate}</li>
|
||||
</ul>
|
||||
<p>Please find the invoice attached.</p>
|
||||
<p>Regards,<br>Fitlien Team</p>
|
||||
</body>
|
||||
</html>
|
||||
`;
|
||||
|
||||
await sendEmailWithAttachmentUtil(
|
||||
gymOwnerEmail,
|
||||
ownerEmailSubject,
|
||||
gymOwnerEmailHtml,
|
||||
downloadUrl,
|
||||
`Invoice_${path.basename(invoicePath)}`
|
||||
);
|
||||
|
||||
logger.info(`Day pass invoice email sent to gym owner (${gymOwnerEmail}) for payment: ${payload.merchantOrderId}`);
|
||||
} catch (ownerEmailError) {
|
||||
logger.error('Error sending gym owner day pass invoice email:', ownerEmailError);
|
||||
}
|
||||
}
|
||||
|
||||
} catch (invoiceError) {
|
||||
logger.error('Error generating day pass invoice:', invoiceError);
|
||||
}
|
||||
}
|
||||
|
||||
} catch (error) {
|
||||
logger.error('Error processing day pass booking:', error);
|
||||
}
|
||||
}
|
||||
|
||||
async function processMembershipPayment(payload: any, orderData: any, membershipId: string) {
|
||||
logger.info(`Processing membership for completed payment`, {
|
||||
merchantOrderId: payload.merchantOrderId,
|
||||
orderId: payload.orderId,
|
||||
membershipId: membershipId || 'not-provided'
|
||||
@ -455,21 +620,3 @@ export const phonePeWebhook = onRequest({
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
logger.info(`Payment data updated for completed payment: ${payload.merchantOrderId}`);
|
||||
} catch (paymentUpdateError) {
|
||||
logger.error('Error updating payment data:', paymentUpdateError);
|
||||
}
|
||||
}
|
||||
|
||||
response.status(200).json({ success: true });
|
||||
|
||||
} catch (error: any) {
|
||||
logger.error('PhonePe webhook processing error:', error);
|
||||
response.status(500).json({
|
||||
success: false,
|
||||
error: 'Failed to process webhook',
|
||||
details: error.message
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
Loading…
Reference in New Issue
Block a user