Merge branch 'dev' into qa

This commit is contained in:
Benoy Bose 2025-04-14 15:02:28 +05:30
commit e8ca80df48
2 changed files with 140 additions and 1 deletions

View File

@ -10,3 +10,4 @@ CASHFREE_CLIENT_SECRET=#{CASHFREE_CLIENT_SECRET}#
GOOGLE_MAPS_API_KEY=#{GOOGLE_MAPS_API_KEY}# GOOGLE_MAPS_API_KEY=#{GOOGLE_MAPS_API_KEY}#
FITLIENHOST=#{FITLIENHOST}# FITLIENHOST=#{FITLIENHOST}#
CASHFREE_URL=#{CASHFREE_URL}# CASHFREE_URL=#{CASHFREE_URL}#
CASHFREE_LINK_URL=#{CASHFREE_LINK_URL}#

View File

@ -15,7 +15,7 @@ const formData = require('form-data');
const Mailgun = require('mailgun.js'); const Mailgun = require('mailgun.js');
const { convert } = require('html-to-text'); const { convert } = require('html-to-text');
const twilio = require('twilio'); const twilio = require('twilio');
const { v4: uuidv4 } = require('uuid');
if (!admin.apps.length) { if (!admin.apps.length) {
admin.initializeApp(); admin.initializeApp();
@ -486,6 +486,144 @@ export const createCashfreeOrder = onRequest({
}); });
}); });
export const createCashfreeLink = onRequest({
region: '#{SERVICES_RGN}#'
}, async (request: Request, response: express.Response) => {
return corsHandler(request, response, async () => {
try {
const authHeader = request.headers.authorization;
if (!authHeader || !authHeader.startsWith('Bearer ')) {
response.status(401).json({ error: 'Unauthorized' });
return;
}
const idToken = authHeader.split('Bearer ')[1];
try {
const decodedToken = await admin.auth().verifyIdToken(idToken);
const uid = decodedToken.uid;
const {
amount,
customerName,
customerEmail,
customerPhone,
productInfo,
userId,
gymId,
orderId
} = request.body;
if (!amount || !customerEmail || !customerPhone) {
response.status(400).json({ error: 'Missing required fields' });
return;
}
const expirationDate = new Date(Date.now() + 24 * 60 * 60 * 1000);
const expirationString = expirationDate.toISOString();
const clientId = process.env.CASHFREE_CLIENT_ID;
const clientSecret = process.env.CASHFREE_CLIENT_SECRET;
let apiUrl = process.env.CASHFREE_LINK_URL;
if (!clientId || !clientSecret) {
logger.error('Cashfree credentials not configured');
response.status(500).json({ error: 'Payment gateway configuration error' });
return;
}
const linkId = uuidv4();
try {
const options = {
method: 'POST',
headers: {
'x-api-version': '2025-01-01',
'x-client-id': `${process.env.CASHFREE_CLIENT_ID}`,
'x-client-secret': `${process.env.CASHFREE_CLIENT_SECRET}`,
'Content-Type': 'application/json'
},
body: `{
"customer_details": {
"customer_email": "${customerEmail}",
"customer_name": "${customerName}",
"customer_phone": "${customerPhone}"
},
"link_amount": ${amount},
"link_auto_reminders": true,
"link_currency": "INR",
"link_expiry_time": "${expirationString}",
"link_id": "${linkId}",
"link_meta": {
"notify_url": "https://ee08e626ecd88c61c85f5c69c0418cb5.m.pipedream.net",
"return_url": "https://www.cashfree.com/devstudio/thankyou",
"upi_intent": false
},
"link_notes": {
"userId": "${userId}",
"gymId": "${gymId}",
"orderId": "${orderId}",
"requestUserId": "${uid}"
},
"link_notify": {
"send_email": true,
"send_sms": true
},
"link_partial_payments": false,
"link_purpose": "${productInfo}",
"order_splits": []
}`
};
const cashfreeResponse = await axios.post(apiUrl!, options);
try {
await admin.firestore().collection('payment_links').doc(orderId).set({
requestUserId: uid,
amount: amount,
customerEmail: customerEmail,
customerPhone: customerPhone,
userId: userId,
gymId: gymId,
orderId: orderId,
...cashfreeResponse.data,
createdAt: new Date(),
});
} catch (firestoreError) {
logger.error('Error storing order in Firestore:', firestoreError);
}
response.json({
success: true,
linkId: linkId,
linkUrl: cashfreeResponse.data.link_url,
linkExpiryTime: cashfreeResponse.data.link_expiry_time,
linkStatus: cashfreeResponse.data.link_status
});
} catch (axiosError: any) {
logger.error('Cashfree API error:', axiosError);
response.status(axiosError.response?.status || 500).json({
success: false,
error: 'Payment gateway error',
details: axiosError.response?.data || axiosError.message,
code: axiosError.code
});
}
} catch (authError) {
logger.error('Authentication error:', authError);
response.status(401).json({
success: false,
error: 'Invalid authentication token'
});
}
} catch (error: any) {
logger.error('Cashfree order creation error:', error);
response.status(500).json({
success: false,
error: 'Failed to create payment order',
details: error.message
});
}
});
});
export const verifyCashfreePayment = onRequest({ export const verifyCashfreePayment = onRequest({
region: '#{SERVICES_RGN}#' region: '#{SERVICES_RGN}#'