> ## Documentation Index
> Fetch the complete documentation index at: https://docs.fossapay.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Collections Guide

> Complete guide to accepting payments with FossaPay

## Overview

This guide walks you through accepting payments using FossaPay's Fiat Wallet API. You'll learn how to create fiat wallets, receive payments, handle webhooks, and reconcile transactions.

## Quick Start

<Steps>
  <Step title="Create a Fiat Wallet">
    Generate a unique account number for your customer
  </Step>

  <Step title="Share Account Details">
    Provide the account number to your customer
  </Step>

  <Step title="Receive Payment">
    Customer transfers money to the wallet account
  </Step>

  <Step title="Get Notified">
    Receive instant webhook notification
  </Step>

  <Step title="Credit Customer">
    Update your customer's balance or fulfill their order
  </Step>
</Steps>

## Creating Fiat Wallets

### For Wallet Top-ups

```bash theme={null}
curl -X POST https://api-production.fossapay.com/api/v1/wallets/fiat/create \
  -H "x-api-key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "customerId": "cus_123",
    "walletName": "Main Wallet",
    "walletReference": "wallet_ref_001"
  }'
```

**Response:**

```json theme={null}
{
  "success": true,
  "message": "Fiat wallet created successfully",
  "data": {
    "walletId": "wal_abc123xyz",
    "bankName": "Wema Bank",
    "bankCode": "035",
    "accountNumber": "1234567890"
  }
}
```

### For Invoice Payments

```bash theme={null}
# Create fiat wallet for customer if not exists
curl -X POST https://api-production.fossapay.com/api/v1/wallets/fiat/create \
  -H "x-api-key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "customerId": "cus_456",
    "walletName": "Invoice Wallet",
    "walletReference": "invoice_INV-001"
  }'
```

**Response:**

```json theme={null}
{
  "success": true,
  "message": "Fiat wallet created successfully",
  "data": {
    "walletId": "wal_xyz789",
    "bankName": "Wema Bank",
    "bankCode": "035",
    "accountNumber": "0987654321"
  }
}
```

Share the account details with the customer for payment.

## Displaying Account Details

### Email Template

```html theme={null}
<div style="font-family: Arial, sans-serif;">
  <h2>Payment Instructions</h2>
  <p>Please transfer <strong>₦50,000</strong> to the account below:</p>

  <div style="background: #f5f5f5; padding: 20px; border-radius: 8px;">
    <p><strong>Bank:</strong> Wema Bank</p>
    <p><strong>Account Number:</strong> 1234567890</p>
    <p><strong>Account Name:</strong> ACME Corp - Jane Smith</p>
    <p><strong>Amount:</strong> ₦50,000</p>
  </div>

  <p><small>This account is unique to your transaction and expires on Jan 31, 2024</small></p>
</div>
```

### In-App Display (React)

```jsx theme={null}
function PaymentInstructions({ account, amount }) {
  const [copied, setCopied] = useState(false);

  const copyAccountNumber = () => {
    navigator.clipboard.writeText(account.account_number);
    setCopied(true);
    setTimeout(() => setCopied(false), 2000);
  };

  return (
    <div className="payment-card">
      <h3>Transfer {formatCurrency(amount)} to:</h3>

      <div className="account-details">
        <div className="detail-row">
          <span>Bank:</span>
          <strong>{account.bank_name}</strong>
        </div>

        <div className="detail-row">
          <span>Account Number:</span>
          <div>
            <strong>{account.account_number}</strong>
            <button onClick={copyAccountNumber}>
              {copied ? 'Copied!' : 'Copy'}
            </button>
          </div>
        </div>

        <div className="detail-row">
          <span>Account Name:</span>
          <strong>{account.account_name}</strong>
        </div>
      </div>

      <p className="note">
        Payments are confirmed instantly
      </p>
    </div>
  );
}
```

## Handling Webhook Notifications

### Set Up Webhook Endpoint

```javascript theme={null}
const express = require('express');
const crypto = require('crypto');
const app = express();

app.use(express.json());

app.post('/webhooks/fossapay', async (req, res) => {
  // 1. Verify signature
  if (!verifySignature(req.body, req.headers['x-fossapay-signature'])) {
    return res.status(401).json({ error: 'Invalid signature' });
  }

  // 2. Respond immediately
  res.status(200).json({ received: true });

  // 3. Process asynchronously
  const { event, data } = req.body;

  if (event === 'deposit.completed') {
    await handlePaymentReceived(data);
  }
});

async function handlePaymentReceived(payment) {
  console.log('Payment received:', payment);

  // Get customer from metadata
const customerId = payment.metadata.customer_id;

  // Create transaction record
  await db.transactions.create({
    id: payment.transaction_id,
    customer_id: customerId,
    amount: payment.amount,
    type: 'credit',
    status: 'completed',
    reference: payment.reference,
    created_at: payment.created_at
  });

  // Credit customer wallet
  await db.wallets.increment({
    customer_id: customerId,
    amount: payment.amount
  });

  // Send notification
  await sendNotification(customerId, {
    title: 'Payment Received!',
    message: `Your wallet has been credited with ₦${payment.amount.toLocaleString()}`
  });

  // Send confirmation email
  await sendEmail(payment.metadata.customer_email, {
    subject: 'Payment Confirmation',
    template: 'payment-received',
    data: {
      amount: payment.amount,
      reference: payment.reference,
      date: payment.created_at
    }
  });
}

function verifySignature(payload, signature) {
  const secret = process.env.FOSSAPAY_WEBHOOK_SECRET;
  const hash = crypto
    .createHmac('sha256', secret)
    .update(JSON.stringify(payload))
    .digest('hex');

  return hash === signature;
}
```

### Webhook Payload Example

```json theme={null}
{
  "event": "deposit.completed",
  "eventId": "evt_abc123",
  "timestamp": "2024-01-15T10:30:45Z",
  "data": {
    "transactionId": "txn_001",
    "walletId": "wal_abc123",
    "accountNumber": "1234567890",
    "amount": 50000,
    "currency": "NGN",
    "senderName": "John Doe",
    "senderAccount": "0987654321",
    "senderBank": "GTBank",
    "senderBankCode": "058",
    "reference": "FP-20240115-001",
    "narration": "Payment from John Doe",
    "customerId": "cus_123",
    "createdAt": "2024-01-15T10:30:40Z"
  }
}
```

## Querying Transaction Status

### Get Transaction by ID

```javascript theme={null}
const transaction = await client.transactions.get('txn_001');

console.log(transaction);
// {
//   "status": "success",
//   "data": {
//     "transaction_id": "txn_001",
//     "amount": 50000,
//     "status": "successful",
//     "sender_name": "John Doe",
//     "created_at": "2024-01-15T10:30:40Z"
//   }
// }
```

### List Virtual Account Transactions

```javascript theme={null}
const response = await fetch('https://api-production.fossapay.com/api/v1/wallets/fiat/va_abc123/transactions?startDate=2024-01-01&endDate=2024-01-31&limit=50', {
  headers: {
    'x-api-key': 'YOUR_API_KEY'
  }
});

const data = await response.json();
const transactions = data.transactions;
```

### Overpayment

```javascript theme={null}
async function handlePaymentReceived(payment) {
  const expectedAmount = await getExpectedAmount(payment.metadata.invoice_id);

  if (payment.amount > expectedAmount) {
    // Overpayment detected
    const excess = payment.amount - expectedAmount;

    // Credit invoice amount
    await creditInvoice(payment.metadata.invoice_id, expectedAmount);

    // Credit excess to wallet
    await creditWallet(payment.metadata.customer_id, excess);

    // Notify customer
    await sendNotification(payment.metadata.customer_id, {
      title: 'Overpayment Detected',
      message: `You paid ₦${excess.toLocaleString()} extra. We've added it to your wallet.`
    });
  } else {
    // Normal payment
    await creditInvoice(payment.metadata.invoice_id, payment.amount);
  }
}
```

### Underpayment

```javascript theme={null}
if (payment.amount < expectedAmount) {
  const shortfall = expectedAmount - payment.amount;

  // Mark invoice as partially paid
  await db.invoices.update(payment.metadata.invoice_id, {
    status: 'partially_paid',
    amount_paid: payment.amount,
    amount_remaining: shortfall
  });

  // Notify customer
  await sendNotification(payment.metadata.customer_id, {
    title: 'Partial Payment Received',
    message: `You paid ₦${payment.amount.toLocaleString()}. ₦${shortfall.toLocaleString()} remaining.`
  });
}
```

### Duplicate Payments

```javascript theme={null}
async function handlePaymentReceived(payment) {
  // Check if already processed
  const existing = await db.transactions.findOne({
    id: payment.transaction_id
  });

  if (existing) {
    console.log('Duplicate webhook, skipping');
    return;
  }

  // Process payment
  // ...
}
```

## Best Practices

<AccordionGroup>
  <Accordion title="Always Use Metadata">
    Store relevant information in metadata for easy tracking:

    ```javascript theme={null}
    metadata: {
      customer_id: 'cus_123',
      order_id: 'ord_456',
      campaign: 'q1-promo',
      source: 'mobile_app'
    }
    ```
  </Accordion>

  <Accordion title="Set Expiry for Temporary Accounts">
    Always set expiry dates for invoice payments:

    ```javascript theme={null}
    expires_at: new Date(Date.now() + 7 * 24 * 60 * 60 * 1000) // 7 days
    ```
  </Accordion>

  <Accordion title="Verify Webhook Signatures">
    Never process webhooks without signature verification.
  </Accordion>

  <Accordion title="Handle Webhooks Idempotently">
    Always check for duplicates using transaction\_id or event\_id.
  </Accordion>

  <Accordion title="Send Confirmations">
    Always notify customers when payments are received.
  </Accordion>
</AccordionGroup>

## Testing

### Simulate Payment in Sandbox

```bash theme={null}
curl -X POST https://api-production.fossapay.com/api/v1/sandbox/simulate-payment \
  -H "x-api-key: fp_test_sk_xxxxxxxx" \
  -H "Content-Type: application/json" \
  -d '{
    "virtual_account_number": "1234567890",
    "amount": 50000,
    "sender_name": "Test Customer",
    "sender_account": "0000000001",
    "sender_bank": "058"
  }'
```

## Next Steps

<CardGroup cols={2}>
  <Card color="#0080FF" title="Create Fiat Wallet API" icon="code" href="/api-reference/virtual-account/create-wallet">
    API reference for creating fiat wallets
  </Card>

  <Card color="#0080FF" title="Webhooks Guide" icon="webhook" href="/concepts/webhooks">
    Learn more about handling webhooks
  </Card>

  <Card color="#0080FF" title="Reconciliation Guide" icon="book" href="/guides/reconciliation">
    Best practices for reconciliation
  </Card>

  <Card color="#0080FF" title="Wallets Concept" icon="building-columns" href="/concepts/wallets">
    Understand wallets in depth
  </Card>
</CardGroup>
