Step 5 - Handle the Payment Response
This manual is designed to guide you through handling the direct payment response sent from PayTabs after a transaction. Properly managing this response will enable you to ensure a seamless user experience based on the payment status and update the order status in your database accordingly. It is important to note that after a payment, you can expect three types of responses:
- The response on the return page (explained in this step)
- The callback (explained in the next step)
- The IPN (explained in the next step)
To get the best out of this manual, make sure you have a full understanding of the following manuals:
As it relies on the Hosted Payment Page integration type, so after redirecting the cardholder/customer to the payment page to fill in the payment page requirements and card authentication, the customer will be redirected to the return URL (ONLY if the return parameter has been set) along with an HTTP POST response to the same URL with the brief transaction information.
The Payment Flow
- You would normally follow theInvoices | Initiate the paymentmanual to initiate the payment.
- Then, you will receive a response that includes link URL. This means you have initiated the payment successfully.
"invoice_link": "https://secure-egypt.paytabs.com/payment/request/invoice/31***37/6A52*****************A92337E0A2D",
- Next, you should redirect your customer to this URL so the payment process can be finalized.
- The customer/cardholder will be redirected to the issuer 3DSecure page to authenticate the card.
- Finally, the customer will be redirected to the return URL (ONLY if the
return
parameter has been set with HTTPs link) along with an HTTP POST response including a brief transaction information. - By this time, you will be able to see his transaction on your merchant dashboard, whether it's accepted/authorized or not.
Requirements
- The return parameter MUST be set.
- The return URL MUST be HTTPS.
- The handle return URL action/function MUST handle POST requests otherwise you will receive an error.
- The handle return URL action/function MUST be developed that the response received will be within the request's body.
Handle the Response via The Return URL Response
According to the used integration type flow clarified inHosted Payment Page | Payment Workflowof this manual, you will receive the below response payload. However, it is worth mentioning that the main reason for this type of response on the return page is to customize the return page your customer will be redirected to whether it's a successful or failed payment route.
acquirerMessage=
&acquirerRRN=
&cartId=CART%231001
&customerEmail=demo%40paytabs.com
&respCode=G10046
&respMessage=Authorised
&respStatus=A
&signature=3701705571119d23923a8677db0d5ae90869f80d84954d2f9a
&token=
&tranRef=TST2231101374414
parameter | Sample Response | Represents | Nullable |
---|---|---|---|
| 00:Approved | 00:Approved | ✔ |
Message as received from the acquirer bank. To know more details about this parameter, check our [Return Page Response | Acquirer Message [acquirerMessage]] | |||
| 234115208294 | 234115208294 | ✔ |
Indicates the reference number of this transaction on the acquirer bank side. To know more details about this parameter, check our [Return Page Response | Acquirer Retrieval Reference Number [acquirerRRN]] | |||
| CART%231001 | CART#1001 | ❌ |
Indicates the Cart ID as received from the Merchant side while creating this payment. To know more details about this parameter, check our [Return Page Response | Cart ID [cartId]] | |||
| demo%40paytabs.com | [email protected] | ❌ |
Indicates the customer email used to perform such transaction. To know more details about this parameter, check our [Return Page Response | Customer Email [customerEmail]] | |||
| 03656D | 03656D | ❌ |
Indicates the response code of this transaction, which will be one of PayTabs response codes. You may need to check:What is: Response_code vs the Response_status?. To know more details about this parameter, check our [Return Page Response | Response Code [respCode]] | |||
| Authorised | Authorised | ❌ |
Indicates the response message of the above response code. To know more details about this parameter, check our [Return Page Response | Response Message [respMessage]] | |||
| A | A | ❌ |
Indicates the response status of this transaction, which will be one of PayTabs response statuses. You may need to check:What is: Response_code vs the Response_status?. This status can be used from your system side to decide the transaction status. Only (A) can be considered a successful transaction. To know more details about this parameter, check our [Return Page Response | Response Status [respStatus]] | |||
| 370170557...54f80d84980d8454d2f9a | 370170557...54f80d84980d8454d2f9a | ✔ |
This signature can be used to validate whether the response is genuine or not. This will assure you that it's coming from PayTabs side. To know more details about this, check the section | |||
| 2C4658B652...FC658B658B75B1 | 2C4658B652...FC658B658B75B1 | ✔ |
Only if the card has been tokenized per the merchant's request, the card token would be returned within the response. To know more details about this parameter, check our [Return Page Response | Response Status [respStatus]] | |||
| TST2231101374414 | TST2231101374414 | ❌ |
Indicates the Transaction Reference on PayTabs dashboard. To know more details about this parameter, check our [Return Page Response | Transaction Reference [tranRef]] |
Verify the Return Response
It's highly recommended to verify the Return response first. Verifying the received object is a mandatory step to ensure that the request source is PayTabs itself. To validate and verify the response received when the customer is redirected back to the provided return URL after the payment, unlike IPN/Callback, the response received on the return page should be run through a longer validation process. To validate and verify the Signature locally kindly follow the below steps:
- Get you main server key which will be used in signing your requests. To know more you may check the How to get my Authentication/Integration/API Keys? solution article
For the sake of this tutorial we would assume that server key is "SGJNZ96JLG-JDMKHGRWT9-RWRK2KJNRJ", and this is the raw content you received with the POST return URL redirection:acquirerMessage=&acquirerRRN=&cartId=cart_11111&customerEmail=email%40domain.com&respCode=G84718&respMessage=Authorised&respStatus=A&signature=7a181a32c768621eb6966107752ee70205a01f1c4403a3d13c0ff604f591f988&token=&tranRef=TST2215201242166
- After that, remove any empty parameters as well sent you in this response. You are expected to have a result like the one shown below:
cartId=cart_11111&[email protected]&respCode=G84718&respStatus=A&tranRef=TST2215201242166&respMessage=Authorised
- Then, sort the response by the keys of the sent parameters. You will have a result like the one shown below:
cartId=cart_11111&[email protected]&respCode=G84718&respMessage=Authorised&respStatus=A&tranRef=TST2215201242166
- Next, perform a url_encoding to the parameters (key and values), so that you can have a result like the one shown below:
cartId=cart_11111&customerEmail=email%40domain.com&respCode=G84718&respMessage=Authorised&respStatus=A&tranRef=TST2215201242166
- Then, has the final result you have (as shown in the previous step) using the "sha256" scheme along with your ServerKey as a key. You will have a result like the one shown below:
7a181a32c768621eb6966107752ee70205a01f1c4403a3d13c0ff604f591f988
- Finally, compare this result with the signature payload received.
Sample Code in PHP
function is_valid_redirect($post_values)
{
if (empty($post_values) || !array_key_exists('signature', $post_values)) {
return false;
}
$serverKey = $this->server_key;
// Request body include a signature post Form URL encoded field
// 'signature' (hexadecimal encoding for hmac of sorted post form fields)
$requestSignature = $post_values["signature"];
unset($post_values["signature"]);
$fields = array_filter($post_values);
// Sort form fields
ksort($fields);
// Generate URL-encoded query string of Post fields except signature field.
$query = http_build_query($fields);
return $this->is_genuine($query, $requestSignature, $serverKey);
}
private function is_genuine($data, $requestSignature, $serverKey)
{
$signature = hash_hmac('sha256', $data, $serverKey);
if (hash_equals($signature, $requestSignature) === TRUE) {
// VALID Redirect
return true;
} else {
// INVALID Redirect
return false;
}
}