Skip to content

Paynow Integration – Checking for payments using Polling

Now that we have introduced methods that we can use to check for payments, lets dive into deep detail of each………..Starting with polling

Use Cases

The Polling Method is useful in these cases:

  1. Mobile Apps
  2. Systems that are not exposed line
  3. Confirming payments just in case your webhook fails for some reason

Steps

The polling method will involve the following steps

  1. Send payment to Paynow
  2. Sleep for 15 seconds
  3. Check the Payment Status
  4. If the payment successful update the database, notify the user and exit
  5. If user cancelled payment update database and exit
  6. If the payment is not successful go back to Step 2

Of course these steps will execute under a timeout so that they don’t execute forever and consume our precious resources

Demonstration

To demonstrate the Polling method I will use Node JS, PHP and Python

JS Gang:

JavaScript
const response = await this.paynow.sendMobile(
  this.payment,
  data.phone,
  paymentMethod
);

console.log("Response: ", response);

if (response.success) {
  const pollUrl = response.pollUrl;

  let transaction = await this.paynow.pollTransaction(pollUrl);
  let retries = 0;

  while (retries <= 3) {
    await sleep(4000);

    transaction = await this.paynow.pollTransaction(pollUrl);

    if (transaction.status == "Paid" || transaction.status == "Cancelled")
      break;
      
    retries++;
  }

  if (transaction.status == "Paid") {
    // Paid
  } else {
    // Not paid
  }
}

Python Gang:

Python
import time

...

response = self.paynow.send_mobile(self.payment, data['phone'], payment_method)

print("Response: ", response)

if response['success']:
    poll_url = response.poll_url
    
    transaction = self.paynow.check_transaction_status(poll_url)
    retries = 0
    
    while retries <= 3:
        time.sleep(4)  # sleep for 4 seconds
        
        transaction = self.paynow.check_transaction_status(poll_url)
        
        if transaction.paid or transaction.cancelled:
            break
        
        retries += 1
    
    if transaction.paid:
        # Paid
    else:
        # Not paid
# Some code here

PHP Gang:

PHP
$response = $this->paynow->sendMobile($this->payment, $data['phone'], $paymentMethod);


if ($response->success()) {
    $pollUrl = $response->pollUrl();
    
    $transaction = $this->paynow->pollTransaction($pollUrl);
    $retries = 0;
    
    while ($retries <= 3) {
        usleep(4000 * 1000); // sleep for 4 seconds
        
        $transaction = $this->paynow->pollTransaction($pollUrl);
        
        if ($transaction->status == "Paid" || $transaction->status == "Cancelled") {
            break;
        }
        
        $retries++;
    }
    
    if ($transaction['status'] == "Paid") {
        // Paid
    } else {
        // Not paid
    }
}

In all examples we send payment then check the response, if the response successful we retrieve this poll URL then poll the transaction. In our case its generous we check for about 3 times and pausing for about 4 seconds before each poll

For Javascript the Status object looks like that, for Python and PHP it might be different, so be sure to check it.

JSON
StatusResponse {
    reference: "Invoice%201714568296370",
    amount: "0.50",
    paynowReference: "17877213",
    pollUrl: "https://www.paynow.co.zw/Interface/CheckPayment/?guid=2712da83-b1e5-4b65-894e-24a9be5b03d2",
    status: "Paid"
}

Exponential Backoff Algorithm

Just checking for payment status every 15 seconds or so for 7 times is a good and an acceptable solution for someone who is starting out but for a seasoned developer more is expected.

Enter Exponential Back Off Algorithm!!!

According to Google Cloud, An exponential backoff algorithm retries requests exponentially, increasing the waiting time between retries up to a maximum backoff time

So instead of trying shouting at Paynow every 15 seconds we increase the wait time between each request as shown below:

That was a fail scenario, a success scenario would look something like that:

Demonstation

To demonstrate the use of this algorithm i will use Node JS, PHP and Python

JavaScript
function backoff(retries, maxDelay) {
    return Math.min(1000 * Math.pow(2, retries), maxDelay);
}

let maxDelay = 60000 // 60 seconds
let maxRetries = 10
let retries = 0

...
while (retries <= maxRetries){
  ...
  
  let delay = backoff(1, maxDelay)
  await sleep(delay)
  ...
}
Python
import time

def backoff(retries, max_delay):
    return min(1000 * 2 ** retries, max_delay)

# Example usage:
max_retries = 10
max_delay = 60000  # 60 seconds
retries = 0

...
while retries <= max_retries:
  ...
  delay = backoff(retries, max_delay)
  time.sleep(delay / 1000)
  ...
PHP
<?php

function backoff($retries, $maxDelay) {
    return min(1000 * pow(2, $retries), $maxDelay);
}

// Example usage:
$maxRetries = 10;
$maxDelay = 60000; // 60 seconds
$retries = 0;


while($retries <= $maxRetries){
  ...
  $delay = backoff($retries, $maxDelay);
  usleep($delay * 1000);
  ...
}      

?>

In this example, the backoff function calculates the delay based on the number of retries and a maximum delay. The delay increases exponentially with each retry but is capped at the maximum delay specified.

So this brings us to the end of the tutorial

Additional Resources

Exponential Backoff

Leave a Reply

Your email address will not be published. Required fields are marked *