Skip to main content

Refund Flow

Process INR refunds -- full refunds, partial refunds, and batch operations. Refunds are paid out to the customer's bank account via IMPS.

import { ZenPays } from '@zenxdigitalholdings/zenpays'

const zenpays = new ZenPays({ apiKey: process.env.ZENPAYS_API_KEY! })

// ---------------------------------------------------------------------------
// 1. Full refund
// ---------------------------------------------------------------------------
async function fullRefund(transactionId: string) {
const refund = await zenpays.refunds.create({
transactionId,
reason: 'Customer requested full refund',
beneficiaryEmail: 'priya@example.com',
beneficiaryAccount: '50100012345678',
beneficiaryIfsc: 'HDFC0001234',
})

console.log('Refund created:', refund.refundId)
console.log('Amount:', refund.amount, refund.currency)
console.log('Status:', refund.status) // pending_approval
}

// ---------------------------------------------------------------------------
// 2. Partial refund
// ---------------------------------------------------------------------------
async function partialRefund(transactionId: string) {
const refund = await zenpays.refunds.create({
transactionId,
amount: 500, // Refund 500 INR out of the total
reason: 'Partial item return',
beneficiaryEmail: 'priya@example.com',
beneficiaryAccount: '50100012345678',
beneficiaryIfsc: 'HDFC0001234',
})

console.log('Partial refund:', refund.refundId)
console.log('Refund amount:', refund.amount) // 500
console.log('Original amount:', refund.originalAmount) // e.g. 2000
console.log('Type:', refund.refundType) // partial
}

// ---------------------------------------------------------------------------
// 3. Refund with beneficiary name
// ---------------------------------------------------------------------------
async function refundViaBankAccount(transactionId: string) {
const refund = await zenpays.refunds.create({
transactionId,
amount: 750,
reason: 'Order cancelled',
beneficiaryEmail: 'rahul@example.com',
beneficiaryAccount: '50100012345678',
beneficiaryIfsc: 'HDFC0001234',
beneficiaryName: 'Rahul Sharma',
})

console.log('Bank refund:', refund.refundId)
console.log('Status:', refund.status)
}

// ---------------------------------------------------------------------------
// 4. Multiple partial refunds on the same transaction
// ---------------------------------------------------------------------------
async function progressivePartialRefunds(transactionId: string) {
// Original transaction: 1000 INR

// First partial refund: 300 INR
const refund1 = await zenpays.refunds.create({
transactionId,
amount: 300,
reason: 'Damaged item',
beneficiaryEmail: 'customer@example.com',
beneficiaryAccount: '91020034567890',
beneficiaryIfsc: 'SBIN0001234',
})
console.log(`Refund 1: ${refund1.refundId}, amount: 300`)
// Transaction: refundedAmount = 300, status = "partial_refund"

// Second partial refund: 200 INR
const refund2 = await zenpays.refunds.create({
transactionId,
amount: 200,
reason: 'Shipping overcharge',
beneficiaryEmail: 'customer@example.com',
beneficiaryAccount: '91020034567890',
beneficiaryIfsc: 'SBIN0001234',
})
console.log(`Refund 2: ${refund2.refundId}, amount: 200`)
// Transaction: refundedAmount = 500, status = "partial_refund"

// Final refund: remaining 500 INR
const refund3 = await zenpays.refunds.create({
transactionId,
amount: 500,
reason: 'Remaining balance',
beneficiaryEmail: 'customer@example.com',
beneficiaryAccount: '91020034567890',
beneficiaryIfsc: 'SBIN0001234',
})
console.log(`Refund 3: ${refund3.refundId}, amount: 500`)
// Transaction: refundedAmount = 1000, status = "refunded"

// This would fail -- already fully refunded:
// await zenpays.refunds.create({ transactionId, amount: 1, ... })
// Error: "Transaction has already been fully refunded"
}

// ---------------------------------------------------------------------------
// 5. Batch refund
// ---------------------------------------------------------------------------
async function batchRefund() {
const result = await zenpays.refunds.bulkUpload({
refunds: [
{
transactionId: 'txn_aaa',
reason: 'Customer request',
beneficiaryEmail: 'john@example.com',
beneficiaryAccount: '30200045678901',
beneficiaryIfsc: 'ICIC0001234',
},
{
transactionId: 'txn_bbb',
amount: 500,
reason: 'Partial refund',
beneficiaryEmail: 'jane@example.com',
beneficiaryAccount: '1234567890',
beneficiaryIfsc: 'HDFC0001234',
},
],
})

console.log('Total:', result.total)
console.log('Succeeded:', result.succeeded)
console.log('Failed:', result.failed)

result.results.forEach((r) => {
if (r.status === 'success') {
console.log(` ${r.transactionId}: Refund ${r.refundId}`)
} else {
console.log(` ${r.transactionId}: Failed - ${r.error}`)
}
})
}

// ---------------------------------------------------------------------------
// 6. Poll for refund status
// ---------------------------------------------------------------------------
async function waitForRefund(refundId: string): Promise<string> {
const refund = await zenpays.refunds.get(refundId)

switch (refund.status) {
case 'completed':
console.log('Refund completed successfully')
return 'completed'

case 'failed':
console.log('Refund failed:', refund.failureReason)
return 'failed'

case 'rejected':
console.log('Refund rejected')
return 'rejected'

case 'cancelled':
console.log('Refund cancelled')
return 'cancelled'

default:
// pending_approval, approved, processing -- keep polling
console.log('Refund status:', refund.status)
await new Promise(resolve => setTimeout(resolve, 5000))
return waitForRefund(refundId)
}
}

// ---------------------------------------------------------------------------
// 7. Get refund statistics
// ---------------------------------------------------------------------------
async function getRefundStats() {
const stats = await zenpays.refunds.getStats('2026-01-01', '2026-12-31', 'INR')

console.log('Refund Statistics:')
console.log(' Total refunds:', stats.totalCount)
console.log(' Total amount:', stats.totalAmount, 'INR')
console.log(' Pending:', stats.pendingCount)
console.log(' Completed:', stats.completedCount)
console.log(' Failed:', stats.failedCount)
}