import { NextRequest, NextResponse } from 'next/server' import crypto from 'crypto' interface PayUBalanceResponse { status: string txnid: string amount: string productinfo: string firstname: string email: string hash: string key: string [key: string]: string } /** * Balance Addition Success Handler * Processes successful "Add Balance" payments 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 in balance success') return NextResponse.redirect(new URL('/payment/failed?error=invalid-response', request.url)) } // Verify payment status if (status !== 'success') { console.log(`Balance payment failed for transaction: ${txnid}, status: ${status}`) return NextResponse.redirect(new URL('/payment/failed?txn=' + txnid + '&type=balance', 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 balance transaction: ${txnid}`) return NextResponse.redirect(new URL('/payment/failed?error=hash-mismatch&type=balance', request.url)) } try { // TODO: Update database with successful balance addition // In real implementation: // const siliconId = await getSiliconIdFromTransaction(txnid) // await updateAddBalanceStatus(txnid, 'success') // await incrementUserBalance(siliconId, parseFloat(amount)) console.log(`Balance addition successful for transaction: ${txnid}, amount: ₹${amount}`) // Mock database update for demo const updateResult = await mockUpdateBalanceSuccess(txnid as string, parseFloat(amount as string)) // Redirect to profile page with success message const successUrl = new URL('/profile', request.url) successUrl.searchParams.set('payment', 'success') successUrl.searchParams.set('type', 'balance') successUrl.searchParams.set('amount', amount as string) successUrl.searchParams.set('txn', txnid as string) return NextResponse.redirect(successUrl) } catch (dbError) { console.error('Database update error during balance success:', dbError) // Log for manual reconciliation - payment was successful at gateway console.error(`CRITICAL: Balance payment ${txnid} succeeded at PayU but DB update failed`) // Still redirect to success but with warning const successUrl = new URL('/profile', request.url) successUrl.searchParams.set('payment', 'success') successUrl.searchParams.set('type', 'balance') successUrl.searchParams.set('amount', amount as string) successUrl.searchParams.set('txn', txnid as string) successUrl.searchParams.set('warning', 'db-update-failed') return NextResponse.redirect(successUrl) } } catch (error) { console.error('Balance success handler error:', error) return NextResponse.redirect(new URL('/payment/failed?error=processing-error&type=balance', request.url)) } } // Mock function for demonstration async function mockUpdateBalanceSuccess(txnid: string, amount: number) { console.log(`Mock DB Update: Balance Transaction ${txnid} successful`) // Mock: Get user Silicon ID from transaction const mockSiliconId = 'USR_12345' // In real implementation, fetch from add_balance_history table // Mock: Update add_balance_history status const historyUpdate = { transaction_id: txnid, status: 'success', updated_at: new Date(), payment_gateway_response: { amount: amount, currency: 'INR', payment_date: new Date() } } // Mock: Update user balance const balanceUpdate = { silicon_id: mockSiliconId, balance_increment: amount, previous_balance: 5000, // Mock previous balance new_balance: 5000 + amount, updated_at: new Date() } console.log(`Mock: User ${mockSiliconId} balance increased by ₹${amount}`) console.log(`Mock: New balance: ₹${balanceUpdate.new_balance}`) // Mock delay await new Promise(resolve => setTimeout(resolve, 150)) return { historyUpdate, balanceUpdate } }