Moneybag

Verify API

Check the status of payment transactions

Verify API

The Verify endpoint allows you to check the status of a payment transaction after the customer has completed or attempted payment. This is essential for confirming payment success before fulfilling orders.


Endpoint Details

Endpoint: GET /payments/verify/{transaction_id}

Base URLs:

  • Sandbox: https://sandbox.api.moneybag.com.bd/api/v2
  • Production: https://api.moneybag.com.bd/api/v2

Authentication

All requests require authentication via API key in the header:

X-Merchant-API-Key: <your_merchant_api_key>

Request

Headers

HeaderValueRequired
X-Merchant-API-KeyYour merchant API keyYes

Path Parameters

ParameterTypeRequiredDescription
transaction_idstringYesThe unique transaction ID received from Moneybag after payment processing

Request Example

GET /payments/verify/txn1234567899
X-Merchant-API-Key: your_merchant_api_key

Response

Success Response

HTTP Status: 200 OK

{
  "success": true,
  "data": {
    "transaction_id": "txn1234567899",
    "order_id": "order123321",
    "verified": true,
    "status": "SUCCESS",
    "amount": "1280.00",
    "currency": "BDT",
    "payment_method": "bkash",
    "payment_reference_id": "REF_987654321",
    "customer": {
      "name": "John Doe",
      "email": "john.doe@example.com",
      "phone": "+8801700000000"
    },
    "paid_at": "2025-01-18T10:45:30Z",
    "metadata": {
      "source": "web",
      "session_id": "SESSION12345"
    }
  },
  "message": "Payment verification details retrieved"
}

Response Fields

FieldTypeDescription
transaction_idstringUnique transaction ID
order_idstringMerchant's order ID
verifiedbooleanWhether the payment is verified
statusstringPayment status (SUCCESS, FAILED, PENDING, CANCELLED)
amountdecimalPaid amount
currencystringCurrency code
payment_methodstringPayment method used (card, bkash, nagad, etc.)
payment_reference_idstringReference ID from payment provider
customerobjectCustomer information
paid_atdatetimePayment completion timestamp (ISO format)
metadataobjectAdditional transaction data

Payment Status Values

StatusDescription
SUCCESSPayment completed successfully
FAILEDPayment failed
PENDINGPayment is being processed
CANCELLEDPayment was cancelled by user
EXPIREDPayment session expired
REFUNDEDPayment has been refunded

Error Response

HTTP Status: 404/401/500

{
  "success": false,
  "error": {
    "code": "TRANSACTION_NOT_FOUND",
    "message": "Transaction with ID txn1234567899 not found"
  }
}

Code Examples

cURL

curl -X GET \
  "https://sandbox.api.moneybag.com.bd/api/v2/payments/verify/txn1234567899" \
  -H "X-Merchant-API-Key: your_merchant_api_key"

JavaScript (Node.js)

const axios = require('axios');

async function verifyPayment(transactionId) {
  try {
    const response = await axios.get(
      `https://sandbox.api.moneybag.com.bd/api/v2/payments/verify/${transactionId}`,
      {
        headers: {
          'X-Merchant-API-Key': 'your_merchant_api_key'
        }
      }
    );
    
    const data = response.data.data;
    
    if (data.verified && data.status === 'SUCCESS') {
      console.log('Payment verified successfully');
      console.log('Amount:', data.amount);
      console.log('Payment Method:', data.payment_method);
      // Process the successful payment
    } else {
      console.log('Payment not successful:', data.status);
    }
  } catch (error) {
    console.error('Verification failed:', error.response.data);
  }
}

// Example usage
verifyPayment('txn1234567899');

Python

import requests

def verify_payment(transaction_id):
    url = f'https://sandbox.api.moneybag.com.bd/api/v2/payments/verify/{transaction_id}'
    
    headers = {
        'X-Merchant-API-Key': 'your_merchant_api_key'
    }
    
    response = requests.get(url, headers=headers)
    result = response.json()
    
    if result['success']:
        data = result['data']
        if data['verified'] and data['status'] == 'SUCCESS':
            print('Payment verified successfully')
            print(f"Amount: {data['amount']}")
            print(f"Payment Method: {data['payment_method']}")
            # Process the successful payment
        else:
            print(f"Payment not successful: {data['status']}")
    else:
        print(f"Verification error: {result['error']['message']}")

# Example usage
verify_payment('txn1234567899')

PHP

<?php
function verifyPayment($transactionId) {
    $curl = curl_init();
    
    curl_setopt_array($curl, [
        CURLOPT_URL => "https://sandbox.api.moneybag.com.bd/api/v2/payments/verify/{$transactionId}",
        CURLOPT_RETURNTRANSFER => true,
        CURLOPT_HTTPHEADER => [
            'X-Merchant-API-Key: your_merchant_api_key'
        ]
    ]);
    
    $response = curl_exec($curl);
    $result = json_decode($response, true);
    curl_close($curl);
    
    if ($result['success']) {
        $data = $result['data'];
        if ($data['verified'] && $data['status'] === 'SUCCESS') {
            echo 'Payment verified successfully' . PHP_EOL;
            echo 'Amount: ' . $data['amount'] . PHP_EOL;
            echo 'Payment Method: ' . $data['payment_method'] . PHP_EOL;
            // Process the successful payment
            return true;
        } else {
            echo 'Payment not successful: ' . $data['status'] . PHP_EOL;
            return false;
        }
    } else {
        echo 'Verification error: ' . $result['error']['message'] . PHP_EOL;
        return false;
    }
}

// Example usage
verifyPayment('txn1234567899');
?>

Try in Playground


When to Verify

Immediate Verification

Verify payment immediately after customer returns to your site:

// In your success callback handler
app.get('/payment/success', async (req, res) => {
  const { transaction_id } = req.query;
  
  // Verify immediately
  const verification = await verifyPayment(transaction_id);
  
  if (verification.success && verification.data.status === 'SUCCESS') {
    // Process order fulfillment
    await fulfillOrder(verification.data.order_id);
  }
});

Webhook + Verification

Best practice: Use webhooks with verification for reliability:

// In your webhook handler
app.post('/webhook', async (req, res) => {
  const { transaction_id, event_type } = req.body;
  
  if (event_type === 'payment.success') {
    // Always verify before processing
    const verification = await verifyPayment(transaction_id);
    
    if (verification.data.verified) {
      await processPayment(verification.data);
    }
  }
  
  res.status(200).send('OK');
});

Periodic Verification

For pending payments, verify periodically:

async function checkPendingPayments() {
  const pendingTransactions = await getPendingTransactions();
  
  for (const txn of pendingTransactions) {
    const verification = await verifyPayment(txn.id);
    
    if (verification.data.status !== 'PENDING') {
      // Update transaction status
      await updateTransactionStatus(txn.id, verification.data.status);
    }
  }
}

// Run every 5 minutes
setInterval(checkPendingPayments, 5 * 60 * 1000);

Best Practices

1. Always Verify Before Fulfillment

Never fulfill orders based solely on redirect URLs:

// ❌ Bad - Don't do this
app.get('/payment/success', (req, res) => {
  fulfillOrder(req.query.order_id); // Unsafe!
});

// ✅ Good - Always verify first
app.get('/payment/success', async (req, res) => {
  const verification = await verifyPayment(req.query.transaction_id);
  if (verification.data.verified && verification.data.status === 'SUCCESS') {
    fulfillOrder(verification.data.order_id);
  }
});

2. Handle All Status Types

switch(verification.data.status) {
  case 'SUCCESS':
    await fulfillOrder(orderId);
    break;
  case 'PENDING':
    await markOrderPending(orderId);
    break;
  case 'FAILED':
    await cancelOrder(orderId);
    break;
  case 'CANCELLED':
    await handleCancellation(orderId);
    break;
  default:
    await logUnknownStatus(orderId, status);
}

3. Implement Idempotency

Prevent duplicate order processing:

async function processPayment(verification) {
  // Check if already processed
  const existing = await getProcessedTransaction(verification.transaction_id);
  if (existing) {
    return existing; // Already processed
  }
  
  // Process and mark as completed
  await markTransactionProcessed(verification.transaction_id);
  await fulfillOrder(verification.order_id);
}

4. Store Verification Results

Keep audit trail of all verifications:

async function verifyAndStore(transactionId) {
  const verification = await verifyPayment(transactionId);
  
  // Store verification result
  await storeVerification({
    transaction_id: transactionId,
    verification_result: verification,
    verified_at: new Date(),
    ip_address: req.ip
  });
  
  return verification;
}

Testing

Use sandbox test transactions to verify different scenarios:

Transaction IDReturns Status
txn_test_successSUCCESS
txn_test_failedFAILED
txn_test_pendingPENDING
txn_test_cancelledCANCELLED
txn_test_expiredEXPIRED

Common Issues

Transaction Not Found

  • Ensure transaction ID is correct
  • Check if using correct environment (sandbox vs production)
  • Wait a few seconds after payment before verifying

Verification Timeout

  • Implement retry logic with exponential backoff
  • Check network connectivity
  • Verify API endpoint status

Status Mismatch

  • Always use latest verification result
  • Don't cache verification results for extended periods
  • Implement webhook handlers for status updates