Now that we have introduced methods that we can use to check for payments, this guide will show you how you can check for Paynow payments using polling. It will give you the detailed steps on how that can be accomplished.
Use Cases
The Polling Method is useful in these cases:
- Mobile Apps
- Systems that are not exposed line
- Confirming payments just in case your webhook fails for some reason
Steps
The polling method will involve the following steps
- Send payment to Paynow
- Sleep for 15 seconds
- Check the Payment Status
- If the payment successful update the database, notify the user and exit
- If user cancelled payment update database and exit
- 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:
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:
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:
$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.
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 Back-off 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 back-off algorithm retries requests exponentially, increasing the waiting time between retries up to a maximum back-off time.
So instead of trying shouting at Pay-now 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
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)
...
}
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
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