Paytm gateway integration in PHP
Paytm is a very popular way to make payments these days. To integrate Paytm in our site we need to follow the given steps –
Step 1. First, we need to create an account at https://business.paytm.com/ and get our merchant ID and Secret Key.
Now we can start coding in our site to use the Paytm. First, we will configure the Paytm with test credentials to test our code.
Step 2. (filename – config.php)
define('PAYTM_ENVIRONMENT', 'TEST'); // PROD for live payment define('PAYTM_MERCHANT_KEY', 'xxxxxxxxxxxxxxx'); define('PAYTM_MERCHANT_MID', xxxxxxxxxxxxxxxx); define('PAYTM_MERCHANT_WEBSITE', "WEBSTAGING"); define('PAYTM_REDIRECT_URL', "http://localhost/paytm/Response.php"); $PAYTM_TXN_URL='https://securegw-stage.paytm.in/theia/processTransaction'; if (PAYTM_ENVIRONMENT == 'PROD') { $PAYTM_TXN_URL='https://securegw.paytm.in/theia/processTransaction'; } define('PAYTM_TXN_URL', $PAYTM_TXN_URL);
Step 3. Now we will create a new file(index.php) to create the payment form which will have the amount to be paid and other needed information –
<?php require_once("config.php"); ?> <html> <head> <title>Merchant Check Out Page</title> <meta name="GENERATOR" content="Evrsoft First Page"> </head> <body> <h1>Merchant Check Out Page</h1> <pre> </pre> <form method="post" action="Redirect.php"> <table border="1"> <tbody> <tr> <th>S.No</th> <th>Label</th> <th>Value</th> </tr> <tr> <td>1</td> <td><label>ORDER_ID::*</label></td> <td><input id="ORDER_ID" tabindex="1" maxlength="20" size="20" name="ORDER_ID" autocomplete="off" value="<?php echo "ORDS" . rand(10000,99999999)?>"> </td> </tr> <tr> <td>2</td> <td><label>CUSTID ::*</label></td> <td><input id="CUST_ID" tabindex="2" maxlength="12" size="12" name="CUST_ID" autocomplete="off" value="CUST001"></td> </tr> <tr> <td>3</td> <td><label>INDUSTRY_TYPE_ID ::*</label></td> <td><input id="INDUSTRY_TYPE_ID" tabindex="4" maxlength="12" size="12" name="INDUSTRY_TYPE_ID" autocomplete="off" value="Retail"></td> </tr> <tr> <td>4</td> <td><label>Channel ::*</label></td> <td><input id="CHANNEL_ID" tabindex="4" maxlength="12" size="12" name="CHANNEL_ID" autocomplete="off" value="WEB"> </td> </tr> <tr> <td>5</td> <td><label>txnAmount*</label></td> <td><input title="TXN_AMOUNT" tabindex="10" type="text" name="TXN_AMOUNT" value="1"> </td> </tr> <tr> <td></td> <td></td> <input type="hidden" name="CALLBACK_URL" value="<?php echo PAYTM_REDIRECT_URL; ?>" /> <td><input value="CheckOut" type="submit" onclick=""></td> </tr> </tbody> </table> * - Mandatory Fields </form> </body> </html>
Step 4. Here in form, we have set the action=”Redirect.php”, so we will create a new file with this name –
<?php require_once("config.php"); require_once("encdec_paytm.php"); // this is a php file that has predefined functions for encryption and decryption of paytm data $checkSum = ""; $paramList = array(); $ORDER_ID = $_POST["ORDER_ID"]; $CUST_ID = $_POST["CUST_ID"]; $INDUSTRY_TYPE_ID = $_POST["INDUSTRY_TYPE_ID"]; $CHANNEL_ID = $_POST["CHANNEL_ID"]; $TXN_AMOUNT = $_POST["TXN_AMOUNT"]; $CALLBACK_URL=$_POST['CALLBACK_URL']; // Create an array having all required parameters for creating checksum. $paramList["MID"] = PAYTM_MERCHANT_MID; $paramList["ORDER_ID"] = $ORDER_ID; $paramList["CUST_ID"] = $CUST_ID; $paramList["INDUSTRY_TYPE_ID"] = $INDUSTRY_TYPE_ID; $paramList["CHANNEL_ID"] = $CHANNEL_ID; $paramList["TXN_AMOUNT"] = $TXN_AMOUNT; $paramList["WEBSITE"] = PAYTM_MERCHANT_WEBSITE; $paramList['CALLBACK_URL']=$CALLBACK_URL; //Here checksum string will return by getChecksumFromArray() function. $checkSum = getChecksumFromArray($paramList,PAYTM_MERCHANT_KEY); ?> <html> <head> <title>Merchant Check Out Page</title> </head> <body> <center><h1>Please do not refresh this page...</h1></center> <form method="post" action="<?php echo PAYTM_TXN_URL ?>" name="f1"> <table border="1"> <tbody> <?php foreach($paramList as $name => $value) { echo '<input type="hidden" name="' . $name .'" value="' . $value . '">'; } ?> <input type="hidden" name="CHECKSUMHASH" value="<?php echo $checkSum ?>"> </tbody> </table> <script type="text/javascript"> document.f1.submit(); </script> </form> </body> </html>
To handle the response of return call from paytm we need another file(Response.php) –
<?php require_once("config.php"); require_once("encdec_paytm.php"); $paytmChecksum = ""; $paramList = array(); $isValidChecksum = "FALSE"; $paramList = $_POST; $paytmChecksum = isset($_POST["CHECKSUMHASH"]) ? $_POST["CHECKSUMHASH"] : ""; //Sent by Paytm pg
//Verify all parameters received from Paytm pg to your application. Like MID received from paytm pg is same as your application’s MID, TXN_AMOUNT and ORDER_ID are same as what was sent by you to Paytm PG for initiating transaction etc.
$isValidChecksum = verifychecksum_e($paramList, PAYTM_MERCHANT_KEY, $paytmChecksum); //will return TRUE or FALSE string. if($isValidChecksum == "TRUE") { echo "<b>Checksum matched and following are the transaction details:</b>" . "<br/>"; if ($_POST["STATUS"] == "TXN_SUCCESS") { echo "<b>Transaction status is success</b>" . "<br/>"; //Process your transaction here as success transaction. //Verify amount & order id received from Payment gateway with your application's order id and amount. } else { echo "<b>Transaction status is failure</b>" . "<br/>"; } if (isset($_POST) && count($_POST)>0 ) { foreach($_POST as $paramName => $paramValue) { echo "<br/>" . $paramName . " = " . $paramValue; } } } else { echo "<b>Checksum mismatched.</b>"; //Process transaction as suspicious. } ?>
Some Important Notes –
1. When we create an account for paytm payment it asks us for a redirect URL where paytm will send the response. By default it will redirect to that URL, we can not change that.
If we want to pass the dynamic URL then we will need to contact support and ask them to enable the dynamic URL for our MERCHANT_ID.
2. We can also pass some additional data while making a call to paytm payment API and paytm will return that data in the response. But the name of that parameter can only be “MERC_UNQ_REF”. We can not pass user-defined parameter name.
3. Login credentials for test payment –
Mobile number – 7777777777
Password – 489871
All the functions of the (encdec_paytm.php) file are below –
<?php function encrypt_e($input, $ky) { $key = html_entity_decode($ky); $iv = "@@@@&&&###$$$$"; $data = openssl_encrypt ( $input , "AES-128-CBC" , $key, 0, $iv ); return $data; } function decrypt_e($crypt, $ky) { $key = html_entity_decode($ky); $iv = "@@@@&&&###$$$$"; $data = openssl_decrypt ( $crypt , "AES-128-CBC" , $key, 0, $iv ); return $data; } function generateSalt_e($length) { $random = ""; srand((double) microtime() * 1000000); $data = "AbcDE123IJKLMN67QRSTUVWXYZ"; $data .= "aBCdefghijklmn123opq45rs67tuv89wxyz"; $data .= "0FGH45OP89"; for ($i = 0; $i < $length; $i++) { $random .= substr($data, (rand() % (strlen($data))), 1); } return $random; } function checkString_e($value) { if ($value == 'null') $value = ''; return $value; } function getChecksumFromArray($arrayList, $key, $sort=1) { if ($sort != 0) { ksort($arrayList); } $str = getArray2Str($arrayList); $salt = generateSalt_e(4); $finalString = $str . "|" . $salt; $hash = hash("sha256", $finalString); $hashString = $hash . $salt; $checksum = encrypt_e($hashString, $key); return $checksum; } function getChecksumFromString($str, $key) { $salt = generateSalt_e(4); $finalString = $str . "|" . $salt; $hash = hash("sha256", $finalString); $hashString = $hash . $salt; $checksum = encrypt_e($hashString, $key); return $checksum; } function verifychecksum_e($arrayList, $key, $checksumvalue) { $arrayList = removeCheckSumParam($arrayList); ksort($arrayList); $str = getArray2StrForVerify($arrayList); $paytm_hash = decrypt_e($checksumvalue, $key); $salt = substr($paytm_hash, -4); $finalString = $str . "|" . $salt; $website_hash = hash("sha256", $finalString); $website_hash .= $salt; $validFlag = "FALSE"; if ($website_hash == $paytm_hash) { $validFlag = "TRUE"; } else { $validFlag = "FALSE"; } return $validFlag; } function verifychecksum_eFromStr($str, $key, $checksumvalue) { $paytm_hash = decrypt_e($checksumvalue, $key); $salt = substr($paytm_hash, -4); $finalString = $str . "|" . $salt; $website_hash = hash("sha256", $finalString); $website_hash .= $salt; $validFlag = "FALSE"; if ($website_hash == $paytm_hash) { $validFlag = "TRUE"; } else { $validFlag = "FALSE"; } return $validFlag; } function getArray2Str($arrayList) { $findme = 'REFUND'; $findmepipe = '|'; $paramStr = ""; $flag = 1; foreach ($arrayList as $key => $value) { $pos = strpos($value, $findme); $pospipe = strpos($value, $findmepipe); if ($pos !== false || $pospipe !== false) { continue; } if ($flag) { $paramStr .= checkString_e($value); $flag = 0; } else { $paramStr .= "|" . checkString_e($value); } } return $paramStr; } function getArray2StrForVerify($arrayList) { $paramStr = ""; $flag = 1; foreach ($arrayList as $key => $value) { if ($flag) { $paramStr .= checkString_e($value); $flag = 0; } else { $paramStr .= "|" . checkString_e($value); } } return $paramStr; } function redirect2PG($paramList, $key) { $hashString = getchecksumFromArray($paramList); $checksum = encrypt_e($hashString, $key); } function removeCheckSumParam($arrayList) { if (isset($arrayList["CHECKSUMHASH"])) { unset($arrayList["CHECKSUMHASH"]); } return $arrayList; } function getTxnStatus($requestParamList) { return callAPI(PAYTM_STATUS_QUERY_URL, $requestParamList); } function getTxnStatusNew($requestParamList) { return callNewAPI(PAYTM_STATUS_QUERY_NEW_URL, $requestParamList); } function initiateTxnRefund($requestParamList) { $CHECKSUM = getRefundChecksumFromArray($requestParamList,PAYTM_MERCHANT_KEY,0); $requestParamList["CHECKSUM"] = $CHECKSUM; return callAPI(PAYTM_REFUND_URL, $requestParamList); } function callAPI($apiURL, $requestParamList) { $jsonResponse = ""; $responseParamList = array(); $JsonData =json_encode($requestParamList); $postData = 'JsonData='.urlencode($JsonData); $ch = curl_init($apiURL); curl_setopt($ch, CURLOPT_CUSTOMREQUEST, "POST"); curl_setopt($ch, CURLOPT_POSTFIELDS, $postData); curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); curl_setopt ($ch, CURLOPT_SSL_VERIFYHOST, 0); curl_setopt ($ch, CURLOPT_SSL_VERIFYPEER, 0); curl_setopt($ch, CURLOPT_HTTPHEADER, array( 'Content-Type: application/json', 'Content-Length: ' . strlen($postData)) ); $jsonResponse = curl_exec($ch); $responseParamList = json_decode($jsonResponse,true); return $responseParamList; } function callNewAPI($apiURL, $requestParamList) { $jsonResponse = ""; $responseParamList = array(); $JsonData =json_encode($requestParamList); $postData = 'JsonData='.urlencode($JsonData); $ch = curl_init($apiURL); curl_setopt($ch, CURLOPT_CUSTOMREQUEST, "POST"); curl_setopt($ch, CURLOPT_POSTFIELDS, $postData); curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); curl_setopt ($ch, CURLOPT_SSL_VERIFYHOST, 0); curl_setopt ($ch, CURLOPT_SSL_VERIFYPEER, 0); curl_setopt($ch, CURLOPT_HTTPHEADER, array( 'Content-Type: application/json', 'Content-Length: ' . strlen($postData)) ); $jsonResponse = curl_exec($ch); $responseParamList = json_decode($jsonResponse,true); return $responseParamList; } function getRefundChecksumFromArray($arrayList, $key, $sort=1) { if ($sort != 0) { ksort($arrayList); } $str = getRefundArray2Str($arrayList); $salt = generateSalt_e(4); $finalString = $str . "|" . $salt; $hash = hash("sha256", $finalString); $hashString = $hash . $salt; $checksum = encrypt_e($hashString, $key); return $checksum; } function getRefundArray2Str($arrayList) { $findmepipe = '|'; $paramStr = ""; $flag = 1; foreach ($arrayList as $key => $value) { $pospipe = strpos($value, $findmepipe); if ($pospipe !== false) { continue; } if ($flag) { $paramStr .= checkString_e($value); $flag = 0; } else { $paramStr .= "|" . checkString_e($value); } } return $paramStr; } function callRefundAPI($refundApiURL, $requestParamList) { $jsonResponse = ""; $responseParamList = array(); $JsonData =json_encode($requestParamList); $postData = 'JsonData='.urlencode($JsonData); $ch = curl_init($apiURL); curl_setopt ($ch, CURLOPT_SSL_VERIFYHOST, 0); curl_setopt ($ch, CURLOPT_SSL_VERIFYPEER, 0); curl_setopt($ch, CURLOPT_URL, $refundApiURL); curl_setopt($ch, CURLOPT_POST, true); curl_setopt($ch, CURLOPT_POSTFIELDS, $postData); curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); $headers = array(); $headers[] = 'Content-Type: application/json'; curl_setopt($ch, CURLOPT_HTTPHEADER, $headers); $jsonResponse = curl_exec($ch); $responseParamList = json_decode($jsonResponse,true); return $responseParamList; }
Nice Man