So, once you have posted a transaction to PesaPal, how do you find if the payment has competed? Or failed?
PesaPal can send you a notification every time a status change has happened on one of your transactions following which you can query for the status. This is referred to as IPN or Instant Payment Notifications.
Let's take a look at how this works in detail.
To enable IPN, you need to set the URL at which you will be listening to the PesaPal notifications. To do this, log in to your PesaPal Merchant account, click on the "IPN Settings" menu, and enter the URL.
Note: use https://demo.pesapal.com for testing
PesaPal will call the URL you entered above with the following query parameters:
You must respond to the HTTP request with the same data that you received from PesaPal. For example:
pesapal_notification_type=CHANGE&pesapal_transaction_tracking_id=XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXX&pesapal_merchant_reference=12345
PesaPal will retry a number of times, if we don't receive the correct response (for example due to network failure).
At this point you may be wondering why PesaPal didn't send you the status of the transaction? We only send you the
pesapal_transaction_tracking_id and the pesapal_merchant_reference for security reasons.
Once you have these two values, you can query PesaPal over a secure SSL connection (that's the https in https://www.pesapal.com) for the status of the transaction using the QueryPaymentStatus API method.
To call the QueryPaymentStatus API method, you need to package the request using OAuth, similar to when you posted a transaction to PesaPal.
<?php include_once('oauth.php'); $consumer_key="xxxxxxxxxxxxxxxxxx";//Register a merchant account on //demo.pesapal.com and use the merchant key for testing. //When you are ready to go live make sure you change the key to the live account //registered on www.pesapal.com! $consumer_secret="xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx";// Use the secret from your test //account on demo.pesapal.com. When you are ready to go live make sure you //change the secret to the live account registered on www.pesapal.com! $statusrequestAPI = 'https://demo.pesapal.com/api/querypaymentstatus';//change to //https://www.pesapal.com/api/querypaymentstatus' when you are ready to go live! // Parameters sent to you by PesaPal IPN $pesapalNotification=$_GET['pesapal_notification_type']; $pesapalTrackingId=$_GET['pesapal_transaction_tracking_id']; $pesapal_merchant_reference=$_GET['pesapal_merchant_reference']; if($pesapalNotification=="CHANGE" && $pesapalTrackingId!='') { $token = $params = NULL; $consumer = new OAuthConsumer($consumer_key, $consumer_secret); $signature_method = new OAuthSignatureMethod_HMAC_SHA1(); //get transaction status $request_status = OAuthRequest::from_consumer_and_token($consumer, $token, "GET", $statusrequestAPI, $params); $request_status->set_parameter("pesapal_merchant_reference", $pesapal_merchant_reference); $request_status->set_parameter("pesapal_transaction_tracking_id",$pesapalTrackingId); $request_status->sign_request($signature_method, $consumer, $token); $ch = curl_init(); curl_setopt($ch, CURLOPT_URL, $request_status); curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); curl_setopt($ch, CURLOPT_HEADER, 1); curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, 0); if(defined('CURL_PROXY_REQUIRED')) if (CURL_PROXY_REQUIRED == 'True') { $proxy_tunnel_flag = (defined('CURL_PROXY_TUNNEL_FLAG') && strtoupper(CURL_PROXY_TUNNEL_FLAG) == 'FALSE') ? false : true; curl_setopt ($ch, CURLOPT_HTTPPROXYTUNNEL, $proxy_tunnel_flag); curl_setopt ($ch, CURLOPT_PROXYTYPE, CURLPROXY_HTTP); curl_setopt ($ch, CURLOPT_PROXY, CURL_PROXY_SERVER_DETAILS); } $response = curl_exec($ch); $header_size = curl_getinfo($ch, CURLINFO_HEADER_SIZE); $raw_header = substr($response, 0, $header_size - 4); $headerArray = explode("\r\n\r\n", $raw_header); $header = $headerArray[count($headerArray) - 1]; //transaction status $elements = preg_split("/=/",substr($response, $header_size)); $status = $elements[1]; curl_close ($ch); //UPDATE YOUR DB TABLE WITH NEW STATUS FOR TRANSACTION WITH pesapal_transaction_tracking_id $pesapalTrackingId if(DB_UPDATE_IS_SUCCESSFUL && $status != "PENDING") { $resp="pesapal_notification_type=$pesapalNotification&pesapal_transaction_tracking_id=$pesapalTrackingId&pesapal_merchant_reference=$pesapal_merchant_reference"; ob_start(); echo $resp; ob_flush(); exit; } } ?>
try { var ipnType = Request["pesapal_notification_type"]; var transactionTrackingId = Request["pesapal_transaction_tracking_id"]; var merchantRef = Request["pesapal_merchant_reference"]; if (UpdateIpnTransactionStatus(ipnType , transactionTrackingId , merchantRef )) { Response.ClearContent(); Response.Write(string.Format( "pesapal_notification_type={0}&pesapal_transaction_tracking_id={1}&pesapal_merchant_reference={2}", ipnType, transactionTrackingId, merchantRef)); } } catch (Exception ex) { // Handle error } public static bool UpdateIpnTransactionStatus(string ipnType, string transactionTrackingId, string merchantRef) { string consumerKey = "xxxxxxxxxxxxxxxxxx";//Register a merchant account on //demo.pesapal.com and use the merchant key for testing. //When you are ready to go live make sure you change the key to the live account //registered on www.pesapal.com! string consumerSecret =" xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx";// Use the secret from your test //account on demo.pesapal.com. When you are ready to go live make sure you //change the secret to the live account registered on www.pesapal.com! Uri pesapalQueryPaymentStatusUri = "https://demo.pesapal.com/api/querypaymentstatus";//change to //https://www.pesapal.com/api/querypaymentstatus' when you are ready to go live! IBuilder builder = new APIPostParametersBuilder() .ConsumerKey(consumerKey) .ConsumerSecret(consumerSecret) .OAuthVersion(EOAuthVersion.VERSION1) .SignatureMethod(ESignatureMethod.HMACSHA1) .SimplePostHttpMethod(EHttpMethod.GET) .SimplePostBaseUri(pesapalQueryPaymentStatusUri ); // Initialize API helper var helper = new APIHelper(builder); if (ipnType == "CHANGE") { // query pesapal for status >> format of the result is pesapal_response_data=<status> string result = helper.PostGetQueryPaymentStatus(pesapal_tracking_id, reference); string[] resultParts = result.Split(new char[] { '=' }); string paymentStatus = resultParts[1]; /* Possible values: PENDING, COMPLETED, FAILED or INVALID*/ // UPDATE YOUR DATABASE: SET THE STATUS OF THIS TRANSACTION TO paymentStatus //IF DATABASE WAS NOT UPDATED OR STATUS == PENDING, RETURN FALSE TO AVOID SENDING AN ACKNOWLEDGEMENT TO PESAPAL if(DB_UPDATE_IS_NOT_SUCCESSFUL){ return false; } } else { return false; } return true; }