micahcarrick / php-paypal-ipn Goto Github PK
View Code? Open in Web Editor NEWPHP 5 class to listen for and handle Instant Payment Notifications (IPN) from PayPal.
License: BSD 3-Clause "New" or "Revised" License
PHP 5 class to listen for and handle Instant Payment Notifications (IPN) from PayPal.
License: BSD 3-Clause "New" or "Revised" License
Because some frameworks delete $_POST
and save all post data to some other location. Or when you want to test IPN data.
A library should never depend on environment variables (like $_POST
).
So I propose:
public function processIpn( $ipn ) {
and
$verified = $listener->processIpn($_POST);
// or
$verified = $listener->processIpn(array('a' => 'b', 'c' => 'd', 'e' => 'f'));
// etc
(I also don't see why processIpn
would check the request's REQUEST_METHOD
...)
Class was working fine but recently i'm getting: "cURL error: [0]" for all transactions.
The issue appears with both with "use_ssl" true or false.
With "use_curl" FALSE the class works fine.
If you're using POST data again, you can read the entire body with 1 cmd:
$encoded_data = file_get_contents('php://input')
instead of looping through $_POST
and urlencoding en stripslashing and checking magic_quotes_gpc.
Hello all
I'm very self taught and have been very busy for the last year so I'm just relearning the basics of my web sites. I upgraded paypal to PayPal USA, Canada v1.3.8 because of the ssl bug. Now I get paid but the back office never gets to order completed. I see that I get 301 redirects in logs when paypal sends https://www.mysite.com/modules/paypalusa/validation.php. I have checked .htaccess and robot.txt, I have looked in cpanel for redirects no luck. I have upgraded Backward compatibility v0.6.1 by PrestaShop still no luck. I'm using Prestashop 1.4.6.2 on this site and I did a lot of custom work so upgrading at this time is a no go. This is my first time here and I'm over my head so I would really like a little advice.
Thanks Wayne
Hi,
All the :
for ($i = 0; $i < 80; $i++)
{
$r .= '-';
}
in ipnlistener::getTextReport can be replaced by :
$r .= str_repeat('-', 80);
Thanks anyway for this good IPN Listner !
I can't seem to make this work. It works fine with the IPN Simulator, but I cannot get anything except INVALID from a live listener.
I'm using the following:
ini_set('log_errors', true);
ini_set('error_log', dirname(FILE).'/ipn_errors.log');
$listener = new \IpnListener();
$listener->use_sandbox = true;
try {
$listener->requirePostMethod();
$verified = $listener->processIpn();
error_log("_RAW POST_".file_get_contents('php://input'));
error_log("**_getPostUri_".$listener->getPostUri());
error_log("**getResponse**".$listener->getResponse());
error_log("**getResponseStatus**".$listener->getResponseStatus());
error_log("**getTextReport*******".$listener->getTextReport());
return $verified;
}
catch (Exception $e){
error_log($e->getMessage());
exit(0);
}
I'm writing all these things out to the log trying to figure out what is going on. Here is a dump for all of these (first is the live example, followed by the logs from the simulator) ...
Had lots of 400 errors in sandbox until i added (@~ line 149)
$header .= "HOST: ".$this->getPaypalHost()."\r\n";
PS: Im using your code un-moded in a production system (loving it btw) with exactly the same setting as the new test system where I found this issue, so im not 100% if this is a real bug; maybe im going crazy; maybe its paypals sandbox; maybe i need some sleep... But perhaps this issue report will help some other luckless soul from loosing a couple clumps of hair like i have today.
On lines 140 to 143 of ipnlistener.php, you have
$header .= "POST /cgi-bin/webscr HTTP/1.0\r\n";
$header .= "Content-Type: application/x-www-form-urlencoded\r\n";
$header .= "Content-Length: ".strlen($encoded_data)."\r\n";
but the $header variable isnt defined anywhere else, it was causing my code to fail. I changed the first line and now I have
$header = "POST /cgi-bin/webscr HTTP/1.0\r\n";
$header .= "Content-Type: application/x-www-form-urlencoded\r\n";
$header .= "Content-Length: ".strlen($encoded_data)."\r\n";
It works.
[02-Dec-2011 12:08:58] PHP Warning: curl_setopt() [function.curl-setopt]: CURLOPT_FOLLOWLOCATION cannot be activated when in safe_mode or an open_basedir is set in /public/sites/www.fangate.info/ipnlistener.p... on line 92
When I receive IPN, CurlVerifier make this error:
Curl error: [35] SSL connect error.
I try solve with $verifier->forceSSLv3(false); and $verifier->forceSSLv3(true);, but don't work. Trying with CURLOPT_SSLVERSION = 4 generate other errors.
Can you help me?
I'm having that issue, whats wrong?
[27-Feb-2015 18:41:18 UTC] cURL error: [77] error setting certificate verify locations:
CAfile: /home/mcarthur/public_html/paypalTest/PHP-PayPal-IPN/cert/api_cert_chain.crt
CApath: none
Can I suggest that self:: be used instead of IpnListener:: lines 170 and 171
http://php.net/manual/en/language.oop5.constants.php
private function getPaypalHost() {
if ($this->use_sandbox) return self::SANDBOX_HOST;
else return self::PAYPAL_HOST;
}
I'm getting INVALID IPN status every time even the payment is made.
I'm using the php api.
Is there any way to do this properly?
Hello,
Great class. It's only that Curl had to be off in order to work. Thanks.
Hi, i have the Problem, that the $verified is all time Pending... but i get the money with sandbox test
Since the SSLv3 is no longer used from PayPal (See http://googleonlinesecurity.blogspot.com/2014/10/this-poodle-bites-exploiting-ssl-30.html
and https://ppmts.custhelp.com/ci/fattach/get/430695/1413497213/redirect/1/filename/Poodle%20SSL%203%200%20Vulnerability%20-%20Merchant%20Response%20Guide.pdf )
I recommend to change the default value of public $force_ssl_v3 = true; to false or compltly remove SSLv3 Support.
hi,
sometimes the IPS returns this error: Invalid response status: 500, but the server is running well and the payment is regular.
what could it be?
thank you
Days ago, script return this error message:
ERROR Message: cURL error: [60] Peer certificate cannot be authenticated with known CA certificates
It's something about api_cert_chain.crt or is about my server?
I have the same script in two domains and both began to return the same error.
Regards...
I've created a class to do verification with all of the issues fixed (plus it's OOP) after pulling my hair out for a few days.
It's updated with the current endpoints, tls1.2 and correct certs. Would have done a pull request, except it seems this repo is no longer maintained.
https://github.com/overint/php-paypal-ipn
will this code be affected by the upgrades made by paypal?
What I have already done:
-set ipn url at paypal (not localhost);
-removed "completed" condition;
-removed "txn_id" and others conditions trying to make it works;
None of these attempts worked for me, even if I use ipn simulator.
<?php
// tell PHP to log errors to ipn_errors.log in this directory
ini_set('log_errors', true);
ini_set('error_log', dirname(__FILE__).'/ipn_errors.log');
// intantiate the IPN listener
include('PHP-PayPal-IPN-master/ipnlistener.php');
$listener = new IpnListener();
// tell the IPN listener to use the PayPal test sandbox
$listener->use_sandbox = true;
// try to process the IPN POST
try {
$listener->requirePostMethod();
$verified = $listener->processIpn();
} catch (Exception $e) {
error_log($e->getMessage());
exit(0);
}
if ($verified) {
$errmsg = ' <br/>'; // stores errors from fraud checks
// 1. Make sure the payment status is "Completed"
if ($_POST['payment_status'] != 'Completed') {
//simply ignore any IPN that is not completed
exit(0);
}
// 2. Make sure seller email matches your primary account email.
if ($_POST['receiver_email'] != '[email protected]') {
$errmsg .= "'receiver_email' does not match: ";
$errmsg .= $_POST['receiver_email']."\n";
}
// 3. Make sure the amount(s) paid match
if ($_POST['mc_gross'] != '10') {
$errmsg .= "'mc_gross' does not match: ";
$errmsg .= $_POST['mc_gross']."\n";
}
// 4. Make sure the currency code matches
if ($_POST['mc_currency'] != 'USD') {
$errmsg .= "'mc_currency' does not match: ";
$errmsg .= $_POST['mc_currency']."\n";
}
// 5. Ensure the transaction is not a duplicate.
include_once("../includes/psl-config.php");
$mysqli = new mysqli(HOST, USER, PASSWORD, DATABASE);
$txn_id = mysqli_real_escape_string($mysqli, $_POST['txn_id']);
$sql = "SELECT COUNT(*) FROM paypal WHERE txn_id = '$txn_id'";
$r = mysqli_query($mysqli, $sql);
if (!$r) {
error_log(mysqli_error($mysqli));
exit(0);
}
$exists = $r;
if ($exists) {
$errmsg .= "'txn_id' has already been processed: ".$_POST['txn_id']."\n";
}
if (!empty($errmsg)) {
// manually investigate errors from the fraud checking
$body = "IPN failed fraud checks: \n$errmsg\n\n";
$body .= $listener->getTextReport();
mail('[email protected]', 'IPN Fraud Warning', $body);
} else {
// add this order to a table of completed orders
if (isset($_POST['item_number'])) {
$item_number = $_POST['item_number'];
}
if($stmt = $mysqli->prepare("INSERT INTO paypal (item_number) VALUES (?)")){
$stmt->bind_param('s', $item_number);
$stmt->execute();
}else{
$errmsg .= "Error trying to insert into DB<br/>";
error_log(mysqli_error($mysqli));
}
// free user ads here
}
} else {
// manually investigate the invalid IPN
mail('[email protected]', 'Invalid IPN', $listener->getTextReport());
}
?>
I´m receiving fraud email all the time. Sometimes it brings me txn_id has already been processed but how can it check this if nothing has been inserted into database?
I was getting a this messsage from the ipnlistener.php in my error log:
Unexpected response from PayPal" so I appended the whole response, and it begins with:
HTTP/1.0 302 Found
Location: https://www.sandbox.paypal.com
Server: BigIP
Connection: Keep-Alive
Content-Length: 0
HTTP/1.1 301 Moved Permanently
Date: Tue, 02 Apr 2013 20:49:12 GMT
Server: Apache
X-Frame-Options: SAMEORIGIN
Set-Cookie: c9MWDuvPtT9GIMyPc3jwol1VSlO=%7cXvmjn23Tcb0azc7NMszAIsuJMaiY_jL-QYumQHoPR4stjLVr_ivSLJTXCMHJc1gsmzQqBm%7cId2lWRNEPD4zIWpXBFpP9Kk0ZLqfGRljP87gzjM7ntnK4kLPfHEMg_hEntbStokIqA7VMm%7c; domain=.paypal.com; path=/; Secure; HttpOnly
Set-Cookie: -1ILhdyICORs4hS4xTUr41S8iP0=_00KImvKbtWRtkGJZuur813tcCmPUBI4CMQZJcBj9YzsQtY0XwfHsjAvEHTk2ZCaJBj8VHSDpZx7raqO; expires=Mon, 28-Mar-2033 20:49:12 GMT; domain=.paypal.com; path=/; Secure; HttpOnly
Set-Cookie: cookie_check=yes; expires=Fri, 31-Mar-2023 20:49:12 GMT; domain=.paypal.com; path=/; Secure; HttpOnly
Set-Cookie: Apache=10.72.109.11.1364935752095343; path=/; expires=Thu, 26-Mar-43 20:49:12 GMT
Location: https://www.sandbox.paypal.com/cgi-bin/webscr?cmd=_home&country_lang.x=true
Connection: close
Content-Type: text/plain; charset=ISO-8859-1
Which is followed by:
HTTP/1.1 200 OK and a paypal web page....
I set the options for my instance of the class to:
$listener->use_sandbox = true;
$listener->use_ssl = false;
$listener->follow_location = true;
I added the cert file to my server. Otherwise I'm using this "out of the box". So far I'm only testing with a paypal initiated ipn from their test site. Any idea what I'm doing wrong? I know paypal is in the middle of migrating their developer tools to a new domain... but I don't know if this is related to that or not. Any help greatly appreciated...
Thanks,
Hi,
For some reason 'processIpn()' is always returning 'false'.
I checked my PHP config and allow_url_fopen and Curl are On.
I checked my server logs and I am not getting any error.
This problem happens when using PayPal IPN simulator and also when using real code from my server.
Please note it is in Sandbox mode, I have not tested in the Live PayPal server.
The script keeps trowing he following error:
cURL error: [77] Problem with the SSL CA cert (path? access rights?)
What might be the problem?
Hi,
thank you for the excellent code. I am wondering whether this works with the latest PayPal updates.
Due to POODLE security vulnerability, PayPal has blocked SSL v3, which prevents this script from working.
A temporary workaround that will stop working on or around Nov 6 is changing PayPal host domain to ipnpb.paypal.com (line 71), but a long term issue that replaces SSL v3 in this script will be needed. Is a fix coming?
It's a couple of days that it returns this error:
cURL error: [60] Peer certificate cannot be authenticated with known CA certificates
i noticed that everything goes fine through sandbox...
does anyone experienced this error?
thanks in advance
I was getting: cURL error: [60] SSL certificate problem, verify that the CA cert is OK.
Then I read this: http://unitstep.net/blog/2009/05/05/using-curl-in-php-to-access-https-ssltls-protected-sites/
I've added in ipnlistener.php this:
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
on function curlPost() after "curl_setopt($ch, CURLOPT_HEADER, true);" (around line 103)
I think this needs the "proper fix", maybe you should bundle PayPal CA certificate along with the example?.
Thank you very much.
Issue from Sandro originally posted on my Blog http://www.micahcarrick.com/paypal-ipn-with-php.html
I used your new ipnlistener: https://github.com/Quixotix/PHP-PayPal-IPN/blob/master/ipnlistener.php
But the respons is always the same as: But, I still get the same (when I use cURL) response, as:
[16-Sep-2011 17:36:40] PayPal IPN: Invalid response status: 0 :-(
Did you consider adding this to Composer? I think it would be useful to have it there.
Great library. Can you add this to Packagist?
Hello @MicahCarrick
I am using curl to verify the PayPal IPN but it throws error: SSL certificate problem: unable to get local issuer certificate.
The same code is working on localhost
But I upload to the shared hosting, it is not working and display error above.
Please help me!
Thanks
Isnt it possible to specify a return url after payment?
Hello Micah,
not sure if this is the right place to ask for help, but I found your file in a plugin I am using and since the support is no help, I thought I go to the source and see if you can help me.
I have a paid membership site that has a paypal gateway. However eventho I am receiving IPNs on my Paypal account with the status of 200 which means everything went ok, the IPNs aren't send back to the website so the memberships obviously are not beeing activated. Maybe I inserted the wrong url in my paypal account? I am going mad here because I can not find the cause for my problem.
It would be great of yout to get back to me on this issue.
kind regards,
Joanne
replace this:
$fp = fsockopen($url_parsed[host],"80",$err_num,$err_str,30);
with:
if ($url_parsed['scheme'] == 'https') {
$url_parsed['port'] = 443;
$ssl = 'ssl://';
} else {
$url_parsed['port'] = 80;
$ssl = '';
}
$fp = @fsockopen($ssl.$url_parsed['host'], $url_parsed['port'], $err_num, $err_str, 30);
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.