paytm / payment
Paytm JS Checkout for cakephp
Package info
github.com/paytm/paytm-cakephp-js-checkout
Type:cakephp-plugin
pkg:composer/paytm/payment
Requires
- php: >=7.2
- cakephp/cakephp: ^4.0
Requires (Dev)
None
Suggests
None
Provides
None
Conflicts
None
Replaces
None
README
Installation
You can install this plugin into your CakePHP application using composer.
The recommended way to install composer packages is:
composer require paytm/payment
Configuring
Note: For CakePHP 4.x and above auto-discovery takes care of below configuration.
When composer installs CakePHP Paytm library successfully,
register the Paytm\JsCheckout\PaytmServiceProvider in your config/app.php configuration file.
// Paytm configuration settings... 'Paytm' => [ 'merchantKey' => env('MERCHANT_KEY',''), 'merchantId' => env('MERCHANT_ID',''), 'enviroment' => env('PAYTM_ENVIRONMENT',''), 'callbackUrl' => env('PAYTM_CALLBACK_URL',''), ],
OR
Add the paytm credentials to the .env file
export PAYTM_ENVIRONMENT=staging export PAYTM_MERCHANT_ID=YOUR_MERCHANT_ID_HERE export PAYTM_MERCHANT_KEY =YOUR_SECRET_KEY_HERE export PAYTM_CALLBACK_URL =YOUR_CALLBACK_URL
Note : All the credentials mentioned are provided by Paytm after signing up as merchant.
Usage
Making a transaction
<?php
// src/Controller/PaytmController.php
namespace App\Controller;
use Cake\Controller\Controller;
use Cake\ORM\TableRegistry;
use paytm\payment\Paytm;
class PaytmController extends Controller
{
// display a form for payment
public function initiate()
{
$this->render('paytm');
}
/* Make payment */
public function payment(){
if ($this->request->is('post')) {
$postData = $this->request->getData();
$amount = 1; //Amount to be paid
$order_id = time();
$enviroment = env('PAYTM_ENVIRONMENT');
$userData = [
"mid" => env('PAYTM_MERCHANT_ID'), //mandatory
"websiteName" => (strpos($enviroment, "stage") == true) ? "WEBSTAGING" : "DEFAULT", //mandatory
"callbackUrl" => env('PAYTM_CALLBACK_URL'), //mandatory
'name' => $postData['name'], // Name of user
'mobile' => $postData['mobile'], //Mobile number of user
'email' => $postData['email'], //Email of user
'txnAmount' => $amount, //mandatory
'orderId' => $order_id //mandatory
];
$Paytm = new Paytm();
$txntoken = $Paytm->initiatePayment($userData);
if(!empty($txntoken)){
$data = array('success'=> true,'txnToken' => $txntoken, 'txnAmount' => $amount, 'orderId' =>$order_id );
$jsonData = json_encode($data);
}else{
//echo json_encode(array('success'=> false,'txnToken' => '','data'=>$res));
$data = array('success'=> false,'txnToken' => '', 'txnAmount' => '', 'orderId' => '' );
$jsonData = json_encode($data);
}
$this->response = $this->response->withType('application/json');
// Set the JSON data as the response body
$this->response = $this->response->withStringBody($jsonData);
// Return the response
return $this->response;
}
}
/*Paytm Callback */
public function paymentCallback()
{
if(!empty($_POST['CHECKSUMHASH'])){
$post_checksum = $_POST['CHECKSUMHASH'];
}else{
$post_checksum = "";
}
if(! empty($_POST) && isset($_POST['STATUS'])){
// Access the POST data from the request
$callbackData = $this->request->getData();
$Paytm = new Paytm();
$requestData = $Paytm->verifyPaymentResponse($_POST);
if(isset($requestData['body']) && $requestData['body']['resultInfo']['resultStatus'] == 'TXN_SUCCESS'){
$msg = "Thank you for your order. Your transaction has been successful.";
$this->set(compact('msg'));
$this->render('success');
}else{
$msg = "Thank You. However, the transaction has been Failed For Reason: " . $requestData['body']['resultInfo']['resultMsg'];
$this->set(compact('msg'));
$this->render('error');
}
}
}
}
?>
Making a view page
<!-- File: templates/Paytm/paytm.php -->
<?= $this->Html->css('https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/css/bootstrap.min.css') ?>
<div id="paytm-pg-spinner" class="paytm-pg-loader" style="display: none;">
<div class="bounce1"></div>
<div class="bounce2"></div>
<div class="bounce3"></div>
<div class="bounce4"></div>
<div class="bounce5"></div>
</div>
<div class="paytm-overlay" style="display:none;"></div>
<div class="container" width="500px">
<div class="panel panel-primary" style="margin-top:110px;">
<div class="panel-heading"><h3 class="text-center">Payment gateway using Paytm Cakephp JS Checkout</h3></div>
<div class="panel-body">
<?= $this->Form->create(null, ['url' => ['controller' => 'Paytm', 'action' => '/payment']]) ?>
<div class="row">
<div class="col-md-12">
<strong>Name:</strong>
<?= $this->Form->text('name', ['class' => 'form-control name', 'placeholder' => 'Name', 'required' => true]) ?>
</div>
<div class="col-md-12">
<strong>Mobile No:</strong>
<?= $this->Form->text('mobile', ['class' => 'form-control mobile', 'maxlength' => '10', 'placeholder' => 'Mobile No.', 'required' => true]) ?>
</div>
<div class="col-md-12">
<strong>Email:</strong>
<?= $this->Form->email('email', ['class' => 'form-control email', 'placeholder' => 'Email', 'required' => true]) ?>
</div>
<div class="col-md-12" >
<br/>
<div class="btn btn-info">
Term Fee : 1 Rs/-
</div>
</div>
<div class="col-md-12">
<br/>
<?= $this->Form->button('Paytm', ['type' => 'submit', 'class' => 'btn btn-success pay']) ?>
</div>
</div>
<?= $this->Form->end() ?>
</div>
</div>
</div>
<?= $this->Html->script('https://code.jquery.com/jquery-2.2.4.min.js', ['integrity' => 'sha256-BbhdlvQf/xTY9gja0Dq3HiwQF8LaCRTXxZKRutelT44=', 'crossorigin' => 'anonymous']) ?>
<?php if(env('PAYTM_ENVIRONMENT')=='production'){?>
<script type="application/javascript" crossorigin="anonymous" src="https:\\securegw.paytm.in\merchantpgpui\checkoutjs\merchants\<?php echo env('PAYTM_MERCHANT_ID')?>.js" ></script>
<?php }else{ ?>
<script type="application/javascript" crossorigin="anonymous" src="https:\\securegw-stage.paytm.in\merchantpgpui\checkoutjs\merchants\<?php echo env('PAYTM_MERCHANT_ID')?>.js" ></script>
<?php } ?>
<script type="text/javascript">
$(".pay").click(function(e) {
var name = $('.name').val();
var mobile = $('.mobile').val();
var email = $('.email').val();
if (name === "" || mobile === "" || email === "") {
alert("Please fill all the fields");
return false;
}
e.preventDefault();
$.ajax({
type: 'POST',
url: '<?= $this->Url->build(['controller' => 'Paytm', 'action' => '/payment']) ?>',
data: {
'name': $('.name').val(),
'mobile': $('.mobile').val(),
'email': $('.email').val(),
},
headers: {
'X-CSRF-Token': '<?= $this->request->getAttribute('csrfToken') ?>',
},
success: function(data) {
console.log(data);
$('.paytm-pg-loader').show();
$('.paytm-overlay').show();
if (data.txnToken === "") {
alert(data.message);
$('.paytm-pg-loader').hide();
$('.paytm-overlay').hide();
return false;
}
var token = '<?= $this->request->getAttribute('csrfToken') ?>';
console.log(data.orderId);
console.log(data.txnToken);
console.log(data.txnamount);
invokeBlinkCheckoutPopup(data.orderId, data.txnToken, data.txnamount,token);
}
});
});
function invokeBlinkCheckoutPopup(orderId, txnToken, amount,token) {
console.log('invokeBlinkCheckoutPopup');
window.Paytm.CheckoutJS.init({
"root": "",
"flow": "DEFAULT",
"data": {
"orderId": orderId,
"token": txnToken,
"tokenType": "TXN_TOKEN",
"amount": amount,
},
headers: {
'X-CSRF-Token': token,
},
handler: {
transactionStatus: function(data) {
},
notifyMerchant: function notifyMerchant(eventName, data) {
if (eventName === "APP_CLOSED") {
$('.paytm-pg-loader').hide();
$('.paytm-overlay').hide();
}
console.log("notify merchant about the payment state");
}
}
}).then(function() {
window.Paytm.CheckoutJS.invoke();
});
}
</script>
Making a sucess page
<!-- File: templates/Paytm/success.php -->
<!DOCTYPE html>
<html>
<head>
<title>Order Success</title>
<!-- Add any CSS or other head content here -->
</head>
<body>
<h1>Thank You!!!</h1>
<p style="color:green"><?php echo $msg;?></p>
<!-- Add any other content as needed -->
</body>
</html>
Making a error page
<!-- File: templates/Paytm/error.php -->
<!DOCTYPE html>
<html>
<head>
<title>Order Error</title>
<!-- Add any CSS or other head content here -->
</head>
<body>
<h1>Sorry!!!</h1>
<p style="color:red"><?php echo $msg;?></p>
<!-- Add any other content as needed -->
</body>
</html>
Define routes
Router::connect('/paytm/initiate', ['controller' => 'Paytm', 'action' => 'initiate']);
Router::connect('/paytm/payment', ['controller' => 'Paytm', 'action' => 'payment']);
Router::connect('/paytm/paymentCallback', ['controller' => 'Paytm', 'action' => 'paymentCallback'])->setMethods(['POST']);
Important: The callback_url must not be csrf protected Check out here to how to do that
### Write code in src/Application.php
public function middleware(MiddlewareQueue $middlewareQueue): MiddlewareQueue{
$csrf = new CsrfProtectionMiddleware(['httponly'=>true]);
$csrf->skipCheckCallback(function($request){
$path = $request->getUri()->getPath();
if($path == '/paytm/paymentCallback'){
return true;
}
});
$middlewareQueue
// Catch any exceptions in the lower layers,
// and make an error page/response
->add(new ErrorHandlerMiddleware(Configure::read('Error')))
// Handle plugin/theme assets like CakePHP normally does.
->add(new AssetMiddleware([
'cacheTime' => Configure::read('Asset.cacheTime'),
]))
// Add routing middleware.
// If you have a large number of routes connected, turning on routes
// caching in production could improve performance. For that when
// creating the middleware instance specify the cache config name by
// using it's second constructor argument:
// `new RoutingMiddleware($this, '_cake_routes_')`
->add(new RoutingMiddleware($this))
// Parse various types of encoded request bodies so that they are
// available as array through $request->getData()
// https://book.cakephp.org/4/en/controllers/middleware.html#body-parser-middleware
->add(new BodyParserMiddleware())
->add($csrf);
return $middlewareQueue;
}
** Add autoload file in composer.json file in your project directory
"autoload": {
"psr-4": {
"App\\": "src/",
"paytm\\payment\\":"vendor/paytm/payment/src"
}
},