Handling Timeouts Via API

When using our APIs, and you experience a timeout, rave has built a system for you to handle this gracefully. Please see below on how to do that.

NB: Timeouts happen when a request takes to long to provide response or you get a 5xx error calling the endpoints, typically our window before we return a timeout response is 25 Seconds

Sample responses when there is a timeout:

{
  "status": "error",
  "message": "No Message",
  "data": {
    "code": "FLW_ERR",
    "message": "No Message",
    "err_tx": {
      "id": 60335,
      "chargeResponseCode": "NR",
      "chargeResponseMessage": "No Message",
      "status": "failed",
      "merchantbearsfee": 1,
      "appfee": 96.25,
      "merchantfee": 0,
      "charged_amount": 4500.00
    }
  }
}
{
        "status": "error",
        "data": null,
        "message": "An error occured. Please contact support"
}
<html>
<head><title>503 Service Temporarily Unavailable</title></head>
<body>
<center><h1>503 Service Temporarily Unavailable</h1></center>
<hr><center>nginx/1.16.1</center>
</body>
</html>
{
  "status":"error",
  "data":{
    "responseCode":"R0",
    "responseMessage":"Please requery to confirm the status of the transaction",
    "txref":"74848972"
  },
  "message":"An error occured. Please contact support"
}

🚧

Check transaction status

A general rule of thumb when a timeout happens is to check the status of that transaction before any other action. This is because in some cases, the transaction has gone through successfully from our end during the timeout in which case all you need to do is give value to the customer for their payment.

What happens when the transaction wasn't successful?

You need to ensure you start passing a query string use_polling=1 in your charge and validate/validatecharge endpoint like this:

https://ravesandboxapi.flutterwave.com/flwv3-pug/getpaidx/api/charge?use_polling=1

What happens when you pass the query params ?

You get a response that looks like this:

{
  "status": "success",
  "message": "LONG-REQ",
  "data": {
    "ping_url": "http://localhost:9329/flwv3-pug/getpaidx/api/requests/RCORE_CHREQ_529B140C1A06B38AD413",
    "message": "The request is taking too long. Please poll the ping_url to get response",
    "REQUEST": "RCORE_CHREQ_529B140C1A06B38AD413",
    "wait": 7468
  }
}

Okay I just got that response what does it allow me do ?

The response expects that you POLL the ping_url returned at your own intervals to get a success or failure response.

NB: "wait": 7468, is the advised wait time before you should start polling. Could be used in setTimeout or interval or delay time for cron based systems.

I have started polling what response should I expect ?

Once we have a success or failure response we return a response that looks like this:

{
  "status": "success",
  "message": "REQSPONSE",
  "data": {
    "id": 61,
    "reqid": "RCORE_CHREQ_17F0B216FD488F229EA0",
    "status": "completed",
    "response": "{\"code\":\"FLW_ERR\",\"message\":\"Sorry that account number is invalid. Please check and try again\",\"err_tx\":{\"id\":83146,\"flwRef\":\"ACHG-1511212902957\",\"chargeResponseCode\":\"RR\",\"chargeResponseMessage\":\"Sorry that account number is invalid. Please check and try again\",\"status\":\"failed\",\"merchantbearsfee\":0,\"appfee\":\"10.0736\",\"merchantfee\":\"0\",\"charged_amount\":\"330.07\"},\"is_err\":1}",
    "createdAt": "2017-11-20T21:21:44.000Z",
    "updatedAt": "2017-11-20T21:21:57.000Z",
    "deletedAt": null,
    "response_parsed": {
      "code": "FLW_ERR",
      "message": "Sorry that account number is invalid. Please check and try again",
      "err_tx": {
        "id": 83146,
        "flwRef": "ACHG-1511212902957",
        "chargeResponseCode": "RR",
        "chargeResponseMessage": "Sorry that account number is invalid. Please check and try again",
        "status": "failed",
        "merchantbearsfee": 0,
        "appfee": "10.0736",
        "merchantfee": "0",
        "charged_amount": "330.07"
      },
      "is_err": 1
    }
  }
}
{
    "status": "success",
    "message": "REQSPONSE",
    "data": {
        "id": 13431,
        "reqid": "RCORE_CVALREQ_C705FCFC07D7DCFFD324",
        "status": "completed",
        "response": "{\"id\":118772,\"txRef\":\"flw-2343243dfadsfawe2\",\"orderRef\":\"URF_1522072845096_4553735\",\"flwRef\":\"ACHG-1522072845964\",\"redirectUrl\":\"http://127.0.0\",\"device_fingerprint\":\"N/A\",\"settlement_token\":null,\"cycle\":\"one-time\",\"amount\":5000,\"charged_amount\":5000,\"appfee\":102.5,\"merchantfee\":0,\"merchantbearsfee\":1,\"chargeResponseCode\":\"00\",\"raveRef\":\"RV315220728443604B5F57F3A0\",\"chargeResponseMessage\":\"Pending OTP validation\",\"authModelUsed\":\"AUTH\",\"currency\":\"NGN\",\"IP\":\"::ffff:10.51.175.26\",\"narration\":\"Kongapay\",\"status\":\"successful\",\"vbvrespmessage\":\"N/A\",\"authurl\":\"NO-URL\",\"vbvrespcode\":\"N/A\",\"acctvalrespmsg\":\"Approved Or Completed Successfully\",\"acctvalrespcode\":\"00\",\"paymentType\":\"account\",\"paymentPlan\":null,\"paymentPage\":null,\"paymentId\":\"2\",\"fraud_status\":\"ok\",\"charge_type\":\"normal\",\"is_live\":0,\"createdAt\":\"2018-03-26T14:00:45.000Z\",\"updatedAt\":\"2018-03-26T14:08:00.000Z\",\"deletedAt\":null,\"customerId\":21357,\"AccountId\":1674,\"customer\":{\"id\":21357,\"phone\":\"07069441260\",\"fullName\":\"Oluwapelumi olaoye\",\"customertoken\":null,\"email\":\"[email protected]\",\"createdAt\":\"2018-03-26T08:59:48.000Z\",\"updatedAt\":\"2018-03-26T08:59:48.000Z\",\"deletedAt\":null,\"AccountId\":1674}}",
        "createdAt": "2018-03-26T14:07:51.000Z",
        "updatedAt": "2018-03-26T14:08:11.000Z",
        "deletedAt": null,
        "response_parsed": {
            "id": 118772,
            "txRef": "flw-2343243dfadsfawe2",
            "orderRef": "URF_1522072845096_4553735",
            "flwRef": "ACHG-1522072845964",
            "redirectUrl": "http://127.0.0",
            "device_fingerprint": "N/A",
            "settlement_token": null,
            "cycle": "one-time",
            "amount": 5000,
            "charged_amount": 5000,
            "appfee": 102.5,
            "merchantfee": 0,
            "merchantbearsfee": 1,
            "chargeResponseCode": "00",
            "raveRef": "RV315220728443604B5F57F3A0",
            "chargeResponseMessage": "Pending OTP validation",
            "authModelUsed": "AUTH",
            "currency": "NGN",
            "IP": "::ffff:10.51.175.26",
            "narration": "Kongapay",
            "status": "successful",
            "vbvrespmessage": "N/A",
            "authurl": "NO-URL",
            "vbvrespcode": "N/A",
            "acctvalrespmsg": "Approved Or Completed Successfully",
            "acctvalrespcode": "00",
            "paymentType": "account",
            "paymentPlan": null,
            "paymentPage": null,
            "paymentId": "2",
            "fraud_status": "ok",
            "charge_type": "normal",
            "is_live": 0,
            "createdAt": "2018-03-26T14:00:45.000Z",
            "updatedAt": "2018-03-26T14:08:00.000Z",
            "deletedAt": null,
            "customerId": 21357,
            "AccountId": 1674,
            "customer": {
                "id": 21357,
                "phone": "07069441260",
                "fullName": "Oluwapelumi Olaoye",
                "customertoken": null,
                "email": "[email protected]",
                "createdAt": "2018-03-26T08:59:48.000Z",
                "updatedAt": "2018-03-26T08:59:48.000Z",
                "deletedAt": null,
                "AccountId": 1674
            }
        }
    }
}

If we still don't have a success or failure response we return a response that looks like this, you need to keep polling till you get a failed or successful response:

{
  "status": "success",
  "message": "REQSPONSE",
  "data": {
    "id": 61,
    "reqid": "RCORE_CHREQ_17F0B216FD488F229EA0",
    "status": "pending",
    "response": null,
    "createdAt": "2017-11-20T21:21:44.000Z",
    "updatedAt": "2017-11-20T21:21:44.000Z",
    "deletedAt": null,
    "response_parsed": null
  }
}

Why should I do this

This helps you handle timeouts gracefully. Timeouts happen in payment systems because of the deep level of connections within systems and in some cases dependence on outer systems. Imagine a timeout happens when your customer is trying to pay, we send you the response above and you can do this:

  • Cut the session and inform them you would update the status while you poll at the back.

This would mean you have prevented your customers from experiencing cases where they are debited but value not given because your system did not plan for such cases.

  • And immediately you get the status you can notify your customer, building trust and handling timeouts gracefully.

Do I still need to requery when I get the final response from the ping url ?

Yes you do.