Skip to content

Commit 9ace81b

Browse files
Merge pull request #16 from cashfree/version_bump_2.1.2
Fix for duplicate transaction id
2 parents 4e2a0d0 + ce84bfb commit 9ace81b

File tree

2 files changed

+118
-130
lines changed

2 files changed

+118
-130
lines changed

modules/gateways/callback/cashfree.php

Lines changed: 50 additions & 63 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,16 @@
1313
require_once __DIR__ . '/../../../includes/gatewayfunctions.php';
1414
require_once __DIR__ . '/../../../includes/invoicefunctions.php';
1515

16+
function checkTransIdExist($transactionId)
17+
{
18+
$result = select_query("tblaccounts", "id", array("transid" => $transactionId));
19+
$numRows = mysql_num_rows($result);
20+
if ($numRows) {
21+
return true;
22+
}
23+
return false;
24+
}
25+
1626
// Detect module name from filename.
1727
$gatewayModuleName = 'cashfree';
1828

@@ -24,37 +34,38 @@
2434
die("Module Not Activated");
2535
}
2636

27-
$appId = $gatewayParams["appId"];
28-
$secretKey = $gatewayParams["secretKey"];
37+
$appId = $gatewayParams["appId"];
38+
$secretKey = $gatewayParams["secretKey"];
2939

30-
//Gateway response parameters
31-
$cashfreeOrderId = $_REQUEST["order_id"];
32-
$invoiceId = substr($cashfreeOrderId, strpos($cashfreeOrderId, "_") + 1);
40+
// Gateway response parameters
41+
$cashfreeOrderId = $_REQUEST["order_id"];
42+
$invoiceId = substr($cashfreeOrderId, strpos($cashfreeOrderId, "_") + 1);
3343

3444
// Validate Callback Invoice ID.
35-
$invoiceId = checkCbInvoiceID($invoiceId, $gatewayParams['name']);
36-
$error = "";
45+
$invoiceId = checkCbInvoiceID($invoiceId, $gatewayParams['name']);
46+
47+
$error = "";
3748

3849
try {
39-
$apiEndpoint = ($gatewayParams["testMode"] == 'on') ? 'https://sandbox.cashfree.com/pg/orders' : 'https://api.cashfree.com/pg/orders';
40-
$getPaymentUrl = $apiEndpoint."/".$cashfreeOrderId."/payments";
50+
$apiEndpoint = ($gatewayParams["testMode"] == 'on') ? 'https://sandbox.cashfree.com/pg/orders' : 'https://api.cashfree.com/pg/orders';
51+
$getPaymentUrl = $apiEndpoint . "/" . $cashfreeOrderId . "/payments";
4152

4253
$curl = curl_init();
4354

4455
curl_setopt_array($curl, [
45-
CURLOPT_URL => $getPaymentUrl,
46-
CURLOPT_RETURNTRANSFER => true,
47-
CURLOPT_ENCODING => "",
48-
CURLOPT_MAXREDIRS => 10,
49-
CURLOPT_TIMEOUT => 30,
50-
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
51-
CURLOPT_CUSTOMREQUEST => "GET",
52-
CURLOPT_HTTPHEADER => [
53-
"Accept: application/json",
54-
"Content-Type: application/json",
55-
"x-api-version: 2021-05-21",
56-
"x-client-id: ".$appId,
57-
"x-client-secret: ".$secretKey
56+
CURLOPT_URL => $getPaymentUrl,
57+
CURLOPT_RETURNTRANSFER => true,
58+
CURLOPT_ENCODING => "",
59+
CURLOPT_MAXREDIRS => 10,
60+
CURLOPT_TIMEOUT => 30,
61+
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
62+
CURLOPT_CUSTOMREQUEST => "GET",
63+
CURLOPT_HTTPHEADER => [
64+
"Accept: application/json",
65+
"Content-Type: application/json",
66+
"x-api-version: 2021-05-21",
67+
"x-client-id: " . $appId,
68+
"x-client-secret: " . $secretKey,
5869
],
5970
]);
6071

@@ -65,62 +76,38 @@
6576
$cfOrder = json_decode($response);
6677
} catch (Exception $e) {
6778
$success = false;
68-
$error ="WHMCS_ERROR:Request to Cashfree Failed";
79+
$error = "WHMCS_ERROR:Request to Cashfree Failed";
6980
}
7081

71-
if (null !== $cfOrder && !empty($cfOrder[0]->payment_status))
72-
{
73-
if($cfOrder[0]->payment_status == 'SUCCESS')
74-
{
82+
if (null !== $cfOrder && !empty($cfOrder[0]->payment_status)) {
83+
if ($cfOrder[0]->payment_status == 'SUCCESS') {
7584
$transactionId = $cfOrder[0]->cf_payment_id;
7685
$paymentAmount = $cfOrder[0]->order_amount;
7786
$success = true;
78-
}
79-
else {
87+
} else {
8088
$success = false;
8189
$error = $cfOrder[0]->payment_message;
8290
}
83-
8491
} else {
85-
if(!empty($cfOrder->message)) {
92+
if (!empty($cfOrder->message)) {
8693
$error = $cfOrder->message;
8794
} else {
8895
$error = "Unable to process your order. Please contact support.";
8996
}
9097
$success = false;
91-
9298
}
93-
//Check if payment successfully paid
9499

95-
if ($success === true)
96-
{
97-
/**
98-
* Check Callback Transaction ID.
99-
*
100-
* Performs a check for any existing transactions with the same given
101-
* transaction number.
102-
*
103-
* Performs a die upon encountering a duplicate.
104-
105-
* @param string $transactionId
106-
*/
107-
checkCbTransID($transactionId);
108-
109-
$result = mysql_fetch_assoc(select_query('tblinvoices', '*', array("id"=>$invoiceId)));
110-
$amount = $result['total'];
111-
112-
# Apply Payment to Invoice: invoiceid, transactionid, amount paid, fees, modulename
113-
addInvoicePayment($invoiceId, $transactionId, $amount, 0, $gatewayParams["name"]);
114-
# Successful
115-
# Save to Gateway Log: name, data array, status
116-
logTransaction($gatewayParams["name"], $cfOrder[0], "Successful");
117-
118-
header("Location: ".$gatewayParams['systemurl']."viewinvoice.php?id=" . $invoiceId."&paymentsuccess=true");
119-
}
120-
else
121-
{
122-
# Save to Gateway Log: name, data array, status
123-
logTransaction($gatewayParams["name"], $_REQUEST["order_id"], "Unsuccessful-".$error . ". Please check cashfree dashboard for order id: ".$cashfreeOrderId);
100+
// Check if payment successfully paid
101+
if ($success === true) {
102+
if (!checkTransIdExist($transactionId)) {
103+
$result = mysql_fetch_assoc(select_query('tblinvoices', '*', array("id" => $invoiceId)));
104+
$amount = $result['total'];
105+
addInvoicePayment($invoiceId, $transactionId, $amount, 0, $gatewayParams["name"]);
106+
logTransaction($gatewayParams["name"], $cfOrder[0], "Successful");
107+
}
124108

125-
header("Location: ".$gatewayParams['systemurl']."viewinvoice.php?id=" . $invoiceId."&paymentfailed=true");
109+
header("Location: " . $gatewayParams['systemurl'] . "viewinvoice.php?id=" . $invoiceId . "&paymentsuccess=true");
110+
} else {
111+
logTransaction($gatewayParams["name"], $_REQUEST["order_id"], "Unsuccessful-" . $error . ". Please check cashfree dashboard for order id: " . $cashfreeOrderId);
112+
header("Location: " . $gatewayParams['systemurl'] . "viewinvoice.php?id=" . $invoiceId . "&paymentfailed=true");
126113
}

modules/gateways/cashfree.php

Lines changed: 68 additions & 67 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
if (!defined("WHMCS")) {
66
die("This file cannot be accessed directly");
77
}
8+
89
/**
910
* Define module related meta data.
1011
* @return array
@@ -13,11 +14,12 @@ function cashfree_MetaData()
1314
{
1415
return array(
1516
'DisplayName' => 'Cashfree',
16-
'APIVersion' => '1.0.2',
17+
'APIVersion' => '2.1.2',
1718
'DisableLocalCredtCardInput' => true,
1819
'TokenisedStorage' => false,
1920
);
2021
}
22+
2123
/**
2224
* Define Cashfree gateway configuration options.
2325
* @return array
@@ -61,6 +63,7 @@ function cashfree_config()
6163
),
6264
);
6365
}
66+
6467
/**
6568
* Payment link.
6669
* Required by third party payment gateway modules only.
@@ -70,29 +73,27 @@ function cashfree_config()
7073
* @return string
7174
*/
7275
function cashfree_link($params)
73-
{
76+
{
7477
// Invoice Parameters
75-
$invoiceId = $params['invoiceid'];
78+
$invoiceId = $params['invoiceid'];
7679

7780
// System Parameters
78-
$systemUrl = $params['systemurl'];
79-
$moduleName = $params['paymentmethod'];
80-
$result = mysql_fetch_assoc(select_query('tblinvoices', '*', array("id"=>$invoiceId)));
81+
$systemUrl = $params['systemurl'];
82+
$moduleName = $params['paymentmethod'];
83+
$result = mysql_fetch_assoc(select_query('tblinvoices', '*', array("id" => $invoiceId)));
8184

8285
#check whether order is already paid or not, if paid then redirect to complete page
83-
if($result['status'] === 'Paid')
84-
{
85-
header("Location: ".$params['systemurl']."/viewinvoice.php?id=" . $invoiceId);
86-
86+
if ($result['status'] === 'Paid') {
87+
header("Location: " . $params['systemurl'] . "/viewinvoice.php?id=" . $invoiceId);
8788
exit;
88-
}
89+
}
8990

9091
//Cashfree request parameters
91-
$cf_request = array();
92-
$cf_request['orderId'] = 'cashfreeWhmcs_'.$invoiceId;
93-
$cf_request['returnUrl'] = $systemUrl . 'modules/gateways/callback/' . $moduleName . '.php?order_id={order_id}&order_token={order_token}';
94-
$cf_request['notifyUrl'] = $systemUrl . 'modules/gateways/callback/' . $moduleName . '_notify.php';
95-
$payment_link = generatePaymentLink($cf_request,$params);
92+
$cf_request = array();
93+
$cf_request['orderId'] = 'cf' . time() . '_' . $invoiceId;
94+
$cf_request['returnUrl'] = $systemUrl . 'modules/gateways/callback/' . $moduleName . '.php?order_id={order_id}&order_token={order_token}';
95+
$cf_request['notifyUrl'] = $systemUrl . 'modules/gateways/callback/' . $moduleName . '_notify.php';
96+
$payment_link = generatePaymentLink($cf_request, $params);
9697

9798
$langPayNow = $params['langpaynow'];
9899
$htmlOutput = '<form method="post" action="' . $payment_link . '">';
@@ -105,107 +106,107 @@ function cashfree_link($params)
105106
function generatePaymentLink($cf_request, $params)
106107
{
107108
$apiEndpoint = ($params['testMode'] == 'on') ? 'https://sandbox.cashfree.com/pg/orders' : 'https://api.cashfree.com/pg/orders';
108-
$getCashfreeOrderUrl = $apiEndpoint."/".$cf_request['orderId'];
109-
109+
$getCashfreeOrderUrl = $apiEndpoint . "/" . $cf_request['orderId'];
110+
110111
$getOrder = getCfOrder($params, $getCashfreeOrderUrl);
111112

112113
if (null !== $getOrder && $getOrder->order_status == "ACTIVE" &&
113114
$getOrder->order_amount == $params['amount'] && $getOrder->order_currency == $params['currency']) {
114-
return $getOrder->payment_link;
115+
return $getOrder->payment_link;
115116
}
116117

117118
$request = array(
118-
"customer_details" => array(
119-
"customer_id" => "WhmcsCustomer",
120-
"customer_email" => $params['clientdetails']['email'],
121-
"customer_name" => $params['clientdetails']['firstname'].' '.$params['clientdetails']['lastname'],
122-
"customer_phone" => $params['clientdetails']['phonenumber']
119+
"customer_details" => array(
120+
"customer_id" => "WhmcsCustomer",
121+
"customer_email" => $params['clientdetails']['email'],
122+
"customer_name" => $params['clientdetails']['firstname'] . ' ' . $params['clientdetails']['lastname'],
123+
"customer_phone" => $params['clientdetails']['phonenumber'],
124+
),
125+
"order_id" => $cf_request['orderId'],
126+
"order_amount" => $params['amount'],
127+
"order_currency" => $params['currency'],
128+
"order_note" => "WHMCS Order",
129+
"order_meta" => array(
130+
"return_url" => $cf_request['returnUrl'],
131+
"notify_url" => $cf_request['notifyUrl'],
123132
),
124-
"order_id" => $cf_request['orderId'],
125-
"order_amount" => $params['amount'],
126-
"order_currency" => $params['currency'],
127-
"order_note" => "WHMCS Order",
128-
"order_meta" => array(
129-
"return_url" => $cf_request['returnUrl'],
130-
"notify_url" => $cf_request['notifyUrl']
131-
)
132133
);
133134

134135
$curlPostfield = json_encode($request);
135136

136137
$curl = curl_init();
137138

138139
curl_setopt_array($curl, [
139-
CURLOPT_URL => $apiEndpoint,
140-
CURLOPT_RETURNTRANSFER => true,
141-
CURLOPT_ENCODING => "",
142-
CURLOPT_MAXREDIRS => 10,
143-
CURLOPT_TIMEOUT => 30,
144-
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
145-
CURLOPT_CUSTOMREQUEST => "POST",
146-
CURLOPT_POSTFIELDS => $curlPostfield,
147-
CURLOPT_HTTPHEADER => [
148-
"Accept: application/json",
149-
"Content-Type: application/json",
150-
"x-api-version: 2022-01-01",
151-
"x-client-id: ".$params['appId'],
152-
"x-client-secret: ".$params['secretKey']
140+
CURLOPT_URL => $apiEndpoint,
141+
CURLOPT_RETURNTRANSFER => true,
142+
CURLOPT_ENCODING => "",
143+
CURLOPT_MAXREDIRS => 10,
144+
CURLOPT_TIMEOUT => 30,
145+
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
146+
CURLOPT_CUSTOMREQUEST => "POST",
147+
CURLOPT_POSTFIELDS => $curlPostfield,
148+
CURLOPT_HTTPHEADER => [
149+
"Accept: application/json",
150+
"Content-Type: application/json",
151+
"x-api-version: 2022-01-01",
152+
"x-client-id: " . $params['appId'],
153+
"x-client-secret: " . $params['secretKey'],
153154
],
154155
]);
155156

156157
$response = curl_exec($curl);
157-
158+
158159
$err = curl_error($curl);
159160

160161
curl_close($curl);
161162

162163
if ($err) {
163164
die("Unable to create your order. Please contact support.");
164165
}
165-
166+
166167
$cfOrder = json_decode($response);
167168

168-
if (null !== $cfOrder && !empty($cfOrder->order_token))
169-
{
169+
if (null !== $cfOrder && !empty($cfOrder->order_token)) {
170170
return $cfOrder->payment_link;
171171
} else {
172-
if(!empty($cfOrder->message)) {
172+
if (!empty($cfOrder->message)) {
173173
die($cfOrder->message);
174174
} else {
175175
die("Unable to create your order. Please contact support.");
176176
}
177177
}
178178
}
179179

180-
function getCfOrder($params, $curlUrl) {
180+
function getCfOrder($params, $curlUrl)
181+
{
181182
$curl = curl_init();
182183

183184
curl_setopt_array($curl, [
184-
CURLOPT_URL => $curlUrl,
185-
CURLOPT_RETURNTRANSFER => true,
186-
CURLOPT_ENCODING => "",
187-
CURLOPT_MAXREDIRS => 10,
188-
CURLOPT_TIMEOUT => 30,
189-
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
190-
CURLOPT_CUSTOMREQUEST => "GET",
191-
CURLOPT_HTTPHEADER => [
192-
"Accept: application/json",
193-
"Content-Type: application/json",
194-
"x-api-version: 2022-01-01",
195-
"x-client-id: ".$params['appId'],
196-
"x-client-secret: ".$params['secretKey']
185+
CURLOPT_URL => $curlUrl,
186+
CURLOPT_RETURNTRANSFER => true,
187+
CURLOPT_ENCODING => "",
188+
CURLOPT_MAXREDIRS => 10,
189+
CURLOPT_TIMEOUT => 30,
190+
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
191+
CURLOPT_CUSTOMREQUEST => "GET",
192+
CURLOPT_HTTPHEADER => [
193+
"Accept: application/json",
194+
"Content-Type: application/json",
195+
"x-api-version: 2022-01-01",
196+
"x-client-id: " . $params['appId'],
197+
"x-client-secret: " . $params['secretKey'],
197198
],
198199
]);
199200

200201
$getOrderResponse = curl_exec($curl);
201-
202+
202203
$err = curl_error($curl);
203204

204205
curl_close($curl);
205206

206207
if ($err) {
207208
die("Unable to create your order. Please contact support.");
208209
}
209-
210+
210211
return json_decode($getOrderResponse);
211212
}

0 commit comments

Comments
 (0)