How can I prevent paypal duplicate payment using txn_id? - php

So I am using PHP cURL and PayPal IPN.
I don't want my customer to pay twice by mistake. I have heard that I can do that using txn_id but I don't know how.
Here is my code ...
<?php
// connecting to database
// Prepare the URL to send via cURL
$req = 'cmd=_notify-validate';
if(function_exists('get_magic_quotes_gpc')) {
$get_magic_quotes_exists = true;
}
foreach ($_POST as $key => $value) {
if($get_magic_quotes_exists == true && get_magic_quotes_gpc() == 1) {
$value = urlencode(stripslashes($value));
} else {
$value = urlencode($value);
}
$req .= "&$key=$value";
}
// Initial cURL
$ch = curl_init();
// Set opt
curl_setopt($ch, CURLOPT_URL,"https://www.paypal.com/cgi-bin/webscr");
curl_setopt($ch, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_1);
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_RETURNTRANSFER,1);
curl_setopt($ch, CURLOPT_POSTFIELDS, $req);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, 1);
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 2);
curl_setopt($ch, CURLOPT_FORBID_REUSE, 1);
// Return result
$result = curl_exec($ch);
// Close cURL connection
curl_close($ch);
// If condition
if($result == "VERIFIED"){
// perform database update
}
?>
How can I prevent the buyer from paying more than once?

The code you provided here is for PayPal IPN, which I think could help little to avoid duplicated payment. Instead, I recommend you adding invoice into your payment data. As PayPal system by default blocks payments with same Invoice ID, I hope this could help you avoid your customers from paying twice by mistake.
If you are integrating PayPal Payment Standard, please check below page for variable list.
https://developer.paypal.com/webapps/developer/docs/classic/paypal-payments-standard/integration-guide/Appx_websitestandard_htmlvariables/
If you are integrating PayPal Express Checkout, please check below pages.
https://developer.paypal.com/docs/classic/api/merchant/SetExpressCheckout_API_Operation_NVP/
https://developer.paypal.com/docs/classic/api/merchant/DoExpressCheckoutPayment_API_Operation_NVP/

Related

I am using paypal payment gateway, its working but some time on success auto return showing blank screen?

I am using paypal payment gateway (currently using sandbox), its working but some time on success auto return showing blank screen?? response url is pretty good, but some times after auto return its showing blank screen.
My code:
after success auto return redirect properly:
http://domainname/client/paypal/success?amt=9.24&cc=USD&item_name=Weight%20Loss%20Diet%20Program&st=Completed&tx=9CX31984H5808205U
after success auto return redirect properly but showing website blank screen:
http://domainname/client/paypal/success?amt=9.24&cc=USD&item_name=Weight%20Loss%20Diet%20Program&st=Completed&tx=9CX31984H5808205U
everything is looking good with code & return url, then why after return sometimes website showing blank screen??
My Code Snippet to execute paypal response:
switch($action){
case "success":
if(isset($_GET['tx']))
{
$tx_token = $_GET['tx'];
$req = 'cmd=_notify-synch';
$auth_token = PDT_IDENTITY_TOKEN;
$req .= "&tx=$tx_token&at=$auth_token";
$ch = curl_init();
if($sandbox==0){
curl_setopt($ch, CURLOPT_URL, "https://www.paypal.com/cgi-bin/webscr"); //Live
}else{
curl_setopt($ch, CURLOPT_URL, "https://www.sandbox.paypal.com/cgi-bin/webscr"); //Sandbox
}
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_RETURNTRANSFER,1);
curl_setopt($ch, CURLOPT_POSTFIELDS, $req);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, 1);
//set cacert.pem verisign certificate path in curl using 'CURLOPT_CAINFO' field here,
//if your server does not bundled with default verisign certificates.
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 2);
if($sandbox==0){
curl_setopt($ch, CURLOPT_HTTPHEADER, array("Host: www.paypal.com")); //Live
}else{
curl_setopt($ch, CURLOPT_HTTPHEADER, array("Host: www.sandbox.paypal.com")); //Sandbox
}
$res = curl_exec($ch);
curl_close($ch);
$lines = explode("\n", trim($res));
$keyarray = array();
if (strcmp ($lines[0], "SUCCESS") == 0)
{
for ($i = 1; $i < count($lines); $i++)
{
$temp = explode("=", $lines[$i],2);
$keyarray[urldecode($temp[0])] = urldecode($temp[1]);
}
$invoice_id = $keyarray['invoice'];
$transaction_id = $keyarray['txn_id'];
$payment_status = $keyarray['payment_status'];
if($payment_status=='Completed')
{
........
}
}
}
....
break;
....
}
During PayPal operations, the variables you are using are part of PDT (Paypal data transfer), which is PayPal a/c feature which needs to be enabled. Please check your PayPal a/c PDT settings once.

PayPal Integration Not Working

I have PayPal integrated on my website. There's a form on my site which takes the customer to PayPal to finalise the payment then it returns them to my site. My site then sends a request back to PayPal with the transaction token for PDT so that I can run a few checks then auto-credit my customer's with the product they bought.
The system uses PHP and cURL to send process all this.
When I use: "www.sandbox.paypal.com/cgi-bin/webscr"
Along with the sandbox credentials everything works fine, everything.
Once I change it all to "www.paypal.com/cgi-bin/webscr"
It does not work, My code tells me that the request fails.
My Code:
$pp_hostname = "www.paypal.com";
// read the post from PayPal system and add 'cmd'
$req = 'cmd=_notify-synch';
$tx_token = $_GET['tx'];
$auth_token = "#######-hashed_out_here-########";
$req .= "&tx=$tx_token&at=$auth_token";
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, "https://$pp_hostname/cgi-bin/webscr");
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_RETURNTRANSFER,1);
curl_setopt($ch, CURLOPT_POSTFIELDS, $req);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, 1);
//set cacert.pem verisign certificate path in curl using 'CURLOPT_CAINFO' field here,
//if your server does not bundled with default verisign certificates.
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 2);
curl_setopt($ch, CURLOPT_HTTPHEADER, array("Host: $pp_hostname"));
$res = curl_exec($ch);
curl_close($ch);
if(!$res){
$this->twig->error("Request failed.");
}else{
$lines = explode("\n", $res);
$keyarray = array();
if (strcmp ($lines[0], "SUCCESS") == 0) {
for ($i='1'; $i<count($lines);$i++){
$test = explode("=", $lines[$i]);
if(empty($test[1])){
$keyarray[urldecode($test[0])] = '';
}else{
$keyarray[urldecode($test[0])] = urldecode($test[1]);
}
}
//give product
} else if (strcmp ($lines[0], "FAIL") == 0) {
$this->twig->error('Transaction failed!');
}
}
Not sure why I'm having a problem so I don't know how to go about fixing.
My PayPal Account is set up as Business, has PDT and IPN turned on as well as Auto-Return
EDIT: Also there isn't an error occurring with the cURL.
OK so if(!($res = curl_exec($ch))) is returning true, i.e its not working

PayPal Integration HTTP Error

I have PayPal integrated on my website. There's a form on my site which takes the customer to PayPal to finalise the payment then it returns them to my site. My site then sends a request back to PayPal with the transaction token for PDT so that I can run a few checks then auto-credit my customer's with the product they bought.
The system uses PHP and cURL to send process all this.
When I use: "www.sandbox.paypal.com/cgi-bin/webscr"
Along with the sandbox credentials everything works fine, everything.
Once I change it all to "www.paypal.com/cgi-bin/webscr"
It does not work, My code tells me that the request fails.
My Code:
$pp_hostname = "www.paypal.com";
// read the post from PayPal system and add 'cmd'
$req = 'cmd=_notify-synch';
$tx_token = $_GET['tx'];
$auth_token = "#######-hashed_out_here-########";
$req .= "&tx=$tx_token&at=$auth_token";
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, "https://$pp_hostname/cgi-bin/webscr");
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_RETURNTRANSFER,1);
curl_setopt($ch, CURLOPT_POSTFIELDS, $req);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, 1);
//set cacert.pem verisign certificate path in curl using 'CURLOPT_CAINFO' field here,
//if your server does not bundled with default verisign certificates.
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 2);
curl_setopt($ch, CURLOPT_HTTPHEADER, array("Host: $pp_hostname"));
$res = curl_exec($ch);
curl_close($ch);
if(!$res){
$this->twig->error("Request failed.");
}else{
$lines = explode("\n", $res);
$keyarray = array();
if (strcmp ($lines[0], "SUCCESS") == 0) {
for ($i='1'; $i<count($lines);$i++){
$test = explode("=", $lines[$i]);
if(empty($test[1])){
$keyarray[urldecode($test[0])] = '';
}else{
$keyarray[urldecode($test[0])] = urldecode($test[1]);
}
}
//give product
} else if (strcmp ($lines[0], "FAIL") == 0) {
$this->twig->error('Transaction failed!');
}
}
Not sure why I'm having a problem so I don't know how to go about fixing.
My PayPal Account is set up as Business, has PDT and IPN turned on as well as Auto-Return
It appears that I'm receiving HTTP Error, but which I cannot say, if I log the curl_error it simply says " " and if I log the curl_errno I get 0.
I managed to get this fixed. It was due to my server not having the ssl certificates installed, once I did so it worked fine.

Paypal Webhook Response

I have been trying to get Paypal's Webhooks to work but all ive been running into is problems. I am trying to make a simple payment process where the user just pays for a product and then I want to setup webhooks to alert me when the payment is made, refunded, or reversed. I have the payment process setup and that is not a problem. I am also hosting the webhook url at a SSL enabled URL.
When I have a purchase go through it sends the webhook response to the link and I have it upload a basic "test" variable to the database just to show that it is indeed being contacted. I also try to insert all of the post data into the database but that doesn't seem to work. Here is the code that the webhook contacts:
<?php
header('HTTP/1.1 200 OK');
$servername = "xxxx";
$username = "xxxx";
$password = "xxxx";
$db = "xxxx";
// Create connection
$conn = mysqli_connect($servername, $username, $password, $db);
if (!$conn) {
die("Connection failed: " . mysqli_connect_error());
}
$sql = "INSERT INTO vars (var) VALUES ('test')";
$conn->query($sql);
foreach ($_POST as $param_name => $param_val) {
echo "Param: $param_name; Value: $param_val<br />\n";
$sql = "INSERT INTO vars (var) VALUES ('" . $param_name . "')";
$conn->query($sql);
}
?>
So like i said I see it insert the "test" into the database but when I try to go through the post variables (which from what i understand there should be some) it doesnt upload any variables.
But when I use the IPN simulator on the paypal developer sandbox and I send it to the link it inserts all of the post variables.
So why is it contacting the URL but not including any of the information? Am I receiving it incorrectly and not processing it right?
Thank you.
First of all You should verify that this request really came from PayPal. For that you should send a little bit modified POST request back to PayPal.
$paypalurl = 'https://www.paypal.com/cgi-bin/webscr';
$req = 'cmd=_notify-validate';
foreach ($_POST as $key => $value) {
$value = urlencode(stripslashes($value));
$req .= "&$key=$value";
}
$ch = curl_init($paypalurl);
if ($ch == false) {
return false;
}
curl_setopt($ch, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_1);
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_POSTFIELDS, $req);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, 1);
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 2);
curl_setopt($ch, CURLOPT_FORBID_REUSE, 1);
curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 30);
curl_setopt($ch, CURLOPT_HTTPHEADER, array('Connection: Close'));
$res = curl_exec($ch);
In the response you should check if it's verified or not:
if ($res) && strcmp($res, "VERIFIED") == {
// your code here
}
So it's better to always use IPN simulator to test this thing, otherwise (by sending plain POST request to your script) it wouldn't be validated normally.
Besides, I would advise you to take a closer look to $_POST['payment_status'] variable. It could be "Completed" (which is ok when payment is processed normally), or "Refund", "Reversed". And process payment according to that. And of course I strongly recommend to validate input — check _POST request (for availability, possible SQL injections, etc) and then proceed to the rest.
$bodyReceived = file_get_contents('php://input');
This is the information you'll receive from paypal as a json object

paypal ipn problem, url malformed (sandbox works, paypal doesn't)

I have an IPN file that works perfectly in sandbox. It returns valid or not and executes the code correctly. However if I try real live payments it tells me the url is malformed
This is the error with live payments:
bool(false) string(15) " malformed"
this is the curl code I have:
if($testmode === true)
{
$paypalaction = "https://www.sandbox.paypal.com/cgi-bin/webscr";
}
elseif($paypal == "paypal")
{
$paypalaction = "https://www.paypal.com/cgi-bin/webscr";
}
// read the post from PayPal system and add 'cmd'
$req = 'cmd=_notify-validate';
foreach ($_POST as $key => $value)
{
// If magic quotes is enabled strip slashes
if (get_magic_quotes_gpc())
{
$_POST[$key] = stripslashes($value);
$value = stripslashes($value);
}
$value = urlencode($value);
// Add the value to the request parameter
$req .= "&$key=$value";
}
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL,$paypalaction);
curl_setopt($ch, CURLOPT_FAILONERROR, 1);
curl_setopt($ch, CURLOPT_RETURNTRANSFER,1);
curl_setopt($ch, CURLOPT_TIMEOUT, 3);
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_POSTFIELDS, $req);
$res = curl_exec($ch);
var_dump($res);
var_dump(curl_error($ch));
curl_close($ch);
It sounds like you may be posting sandbox transactions to the live URL or the other way around. Make sure that when you try a live transaction, you are doing so with a real, live PayPal account. Double-check your code to ensure that your test for which PayPal URL is working correctly.
The problem wasn't with paypal or sandbox but just me being stupid. i had the following if statement:
if($testmode === true)
{
$paypalaction = "https://www.sandbox.paypal.com/cgi-bin/webscr";
}
elseif($paypal == "paypal")
{
$paypalaction = "https://www.paypal.com/cgi-bin/webscr";
}
But the $paypal variable wasn't used anymore so it never entered the elseif statement. I should have been only an if else:
if($testmode === true)
{
$paypalaction = "https://www.sandbox.paypal.com/cgi-bin/webscr";
}
else
{
$paypalaction = "https://www.paypal.com/cgi-bin/webscr";
}

Categories