134 lines
4.9 KiB
TypeScript
134 lines
4.9 KiB
TypeScript
import { onRequest } from "firebase-functions/v2/https";
|
|
import { Request } from "firebase-functions/v2/https";
|
|
import { getCorsHandler } from "../../shared/middleware";
|
|
import { getAdmin, getLogger } from "../../shared/config";
|
|
import axios from "axios";
|
|
const { v4: uuidv4 } = require('uuid');
|
|
|
|
const corsHandler = getCorsHandler();
|
|
const admin = getAdmin();
|
|
const logger = getLogger();
|
|
|
|
interface CashfreeLinkRequest {
|
|
amount: number;
|
|
customerName?: string;
|
|
customerEmail: string;
|
|
customerPhone: string;
|
|
productInfo?: string;
|
|
userId?: string;
|
|
gymId?: string;
|
|
orderId: string;
|
|
}
|
|
|
|
interface CashfreeLinkResponse {
|
|
link_id: string;
|
|
link_url: string;
|
|
link_expiry_time: string;
|
|
link_status: string;
|
|
link_qrcode: string;
|
|
[key: string]: any;
|
|
}
|
|
|
|
export const createCashfreeLink = onRequest({
|
|
region: '#{SERVICES_RGN}#'
|
|
}, async (request: Request, 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];
|
|
const decodedToken = await admin.auth().verifyIdToken(idToken);
|
|
const uid = decodedToken.uid;
|
|
|
|
const linkRequest = request.body as CashfreeLinkRequest;
|
|
if (!linkRequest.amount || !linkRequest.customerEmail || !linkRequest.customerPhone) {
|
|
response.status(400).json({ error: 'Missing required fields' });
|
|
return;
|
|
}
|
|
|
|
const clientId = process.env.CASHFREE_CLIENT_ID;
|
|
const clientSecret = process.env.CASHFREE_CLIENT_SECRET;
|
|
if (!clientId || !clientSecret) {
|
|
logger.error('Cashfree credentials not configured');
|
|
response.status(500).json({ error: 'Payment gateway configuration error' });
|
|
return;
|
|
}
|
|
|
|
const expirationDate = new Date(Date.now() + 24 * 60 * 60 * 1000);
|
|
const expirationString = expirationDate.toISOString();
|
|
const apiUrl = process.env.CASHFREE_LINK_URL;
|
|
const linkId = uuidv4();
|
|
|
|
const requestHeaders = {
|
|
'x-client-id': clientId,
|
|
'x-client-secret': clientSecret,
|
|
'x-api-version': '2025-01-01',
|
|
'Content-Type': 'application/json'
|
|
};
|
|
|
|
const requestBody = {
|
|
link_id: linkId,
|
|
link_amount: linkRequest.amount,
|
|
link_currency: "INR",
|
|
link_purpose: linkRequest.productInfo,
|
|
customer_details: {
|
|
customer_phone: linkRequest.customerPhone,
|
|
customer_email: linkRequest.customerEmail,
|
|
customer_name: linkRequest.customerName,
|
|
},
|
|
link_partial_payments: false,
|
|
link_notify: {
|
|
send_sms: true,
|
|
send_email: true
|
|
},
|
|
link_expiry_time: expirationString,
|
|
link_notes: {
|
|
order_id: linkRequest.orderId,
|
|
gym_id: linkRequest.gymId,
|
|
user_id: linkRequest.userId
|
|
}
|
|
};
|
|
|
|
const cashfreeResponse = await axios.post<CashfreeLinkResponse>(
|
|
apiUrl!,
|
|
requestBody,
|
|
{ headers: requestHeaders }
|
|
);
|
|
|
|
await admin.firestore().collection('payment_links').doc(linkRequest.orderId).set({
|
|
requestUserId: uid,
|
|
amount: linkRequest.amount,
|
|
customerEmail: linkRequest.customerEmail,
|
|
customerPhone: linkRequest.customerPhone,
|
|
userId: linkRequest.userId,
|
|
gymId: linkRequest.gymId,
|
|
orderId: linkRequest.orderId,
|
|
...cashfreeResponse.data,
|
|
createdAt: admin.firestore.FieldValue.serverTimestamp(),
|
|
});
|
|
|
|
response.json({
|
|
success: true,
|
|
linkId: linkId,
|
|
linkUrl: cashfreeResponse.data.link_url,
|
|
linkExpiryTime: cashfreeResponse.data.link_expiry_time,
|
|
linkStatus: cashfreeResponse.data.link_status,
|
|
linkQRCode: cashfreeResponse.data.link_qrcode
|
|
});
|
|
|
|
} catch (error: any) {
|
|
logger.error('Cashfree link creation error:', error);
|
|
const statusCode = error.response?.status || 500;
|
|
response.status(statusCode).json({
|
|
success: false,
|
|
error: error.response?.data?.message || 'Failed to create payment link',
|
|
details: error.response?.data || error.message
|
|
});
|
|
}
|
|
});
|
|
});
|