import { NextRequest, NextResponse } from 'next/server' import crypto from 'crypto' interface PayUResponse { status: string txnid: string amount: string productinfo: string firstname: string email: string hash: string key: string [key: string]: string } /** * PayU Payment Success Handler * Processes successful payment responses from PayU gateway */ export async function POST(request: NextRequest) { try { const formData = await request.formData() const payuResponse: Partial = {} // Extract all PayU response parameters for (const [key, value] of formData.entries()) { payuResponse[key] = value.toString() } const { status, txnid, amount, productinfo, firstname, email, hash, key: merchantKey } = payuResponse // Validate required parameters if (!status || !txnid || !amount || !hash) { console.error('Missing required PayU parameters') return NextResponse.redirect(new URL('/payment/failed?error=invalid-response', request.url)) } // Verify payment status if (status !== 'success') { console.log(`Payment failed for transaction: ${txnid}, status: ${status}`) return NextResponse.redirect(new URL('/payment/failed?txn=' + txnid, request.url)) } // Verify PayU hash for security const merchantSalt = process.env.PAYU_MERCHANT_SALT || 'test-salt' const expectedHashString = `${merchantSalt}|${status}|||||||||||${email}|${firstname}|${productinfo}|${amount}|${txnid}|${merchantKey}` const expectedHash = crypto.createHash('sha512').update(expectedHashString).digest('hex').toLowerCase() if (hash?.toLowerCase() !== expectedHash) { console.error(`Hash mismatch for transaction: ${txnid}`) // Log potential fraud attempt console.error('Expected hash:', expectedHash) console.error('Received hash:', hash?.toLowerCase()) return NextResponse.redirect(new URL('/payment/failed?error=hash-mismatch', request.url)) } try { // TODO: Update database with successful payment // In a real implementation: // await updateBillingStatus(txnid, 'success') // await updateUserBalance(userSiliconId, parseFloat(amount)) console.log(`Payment successful for transaction: ${txnid}, amount: ₹${amount}`) // Mock database update for demo await mockUpdatePaymentStatus(txnid as string, 'success', parseFloat(amount as string)) // Redirect to success page with transaction details const successUrl = new URL('/payment/success', request.url) successUrl.searchParams.set('txn', txnid as string) successUrl.searchParams.set('amount', amount as string) return NextResponse.redirect(successUrl) } catch (dbError) { console.error('Database update error:', dbError) // Even if DB update fails, payment was successful at gateway // Log for manual reconciliation return NextResponse.redirect(new URL('/payment/success?warning=db-update-failed&txn=' + txnid, request.url)) } } catch (error) { console.error('Payment success handler error:', error) return NextResponse.redirect(new URL('/payment/failed?error=processing-error', request.url)) } } // Mock function for demonstration async function mockUpdatePaymentStatus(txnid: string, status: string, amount: number) { // In real implementation, this would update MongoDB/database console.log(`Mock DB Update: Transaction ${txnid} marked as ${status}, amount: ₹${amount}`) // Simulate database operations const billingUpdate = { billing_id: txnid, payment_status: status, payment_date: new Date(), amount: amount } const userBalanceUpdate = { // This would update user's account balance for "add_balance" transactions increment: status === 'success' && txnid.includes('balance') ? amount : 0 } // Mock delay await new Promise(resolve => setTimeout(resolve, 100)) return { billingUpdate, userBalanceUpdate } }