IPN Validation

IPN VALIDATION (ALL INITIATED PAYMENTS & CHARGES)

This section applies to all successful payments or charges initiated through the UMVA platform that send a callback to your server, including:

  • Server API Fiat charges (/initiate-fiat).
  • Server API Crypto charges (/initiate-crypto).
  • Hosted web checkout (POST /payment/initiate with ipn_url).
  • Any other internal flows that ultimately send an IPN to your configured ipn_url.

Signature Algorithm (All IPNs): UMVA signs every IPN using HMAC-SHA256:

signature = HMAC-SHA256(amount + identifier, merchant_secret_api_key)

You must recompute this signature on your server using the amount and identifier in the IPN payload and your Secret API Key, then compare it to the provided signature field.

Generic IPN Payload Structure:

{
  "status": "success",
  "identifier": "YOUR-ORDER-ID",
  "signature": "HMAC-SHA256(amount + identifier, secret_api_key)",
  "data": {
    "payment_trx": "UMV-TRX-XXXXXX",
    "amount": 100.50,
    "net_amount": 98.00,
    "charge": 2.50,
    "payment_type": "api" | "api_crypto" | "hosted",
    "currency": "USD"
  }
}

Recommended IPN Validation Steps (Server-Side):

  1. Read the raw JSON body from the IPN request.
  2. Extract status, identifier, signature and the data object (including amount, currency, payment_type, payment_trx).
  3. Recompute expected_signature = HMAC-SHA256(amount + identifier, your_secret_api_key).
  4. Compare expected_signature to the signature field from the IPN (constant‑time comparison where possible).
  5. Verify that status is "success", that amount, currency, and identifier match what you expect for this order in your database, and that payment_type is one of the expected values for this flow (api, api_crypto, hosted).
  6. Ensure idempotency: if this payment_trx or identifier has already been processed as paid, do not credit it again.
  7. Only after all checks pass, mark the order as paid in your system and return HTTP 200 from your IPN endpoint.