paypal / ipn-code-samples

Other
562 stars 486 forks source link

PHP Example - Sandbox IPN response is always INVALID? #134

Open vdonchev opened 6 years ago

vdonchev commented 6 years ago

I have copied the exact files from PHP examples and then using my PayPal developer sandbox tested the IPN listener (the one in "example_usage.php")

The IPN ALWAYS return INVALID, no matter what I try.

Is there anything required except the example code, so the PayPal may return VERIFIED when testing?

spivack1212-zz commented 6 years ago

I'm having the same issue with the C# code!

spivack1212-zz commented 6 years ago

I have verified that this is an issue with the IPN Simulator. The same code that was always getting INVALID in the IPN Simulator is working fine in production.

overint commented 6 years ago

@pp-randy Are you able to have a look at this? Seens a few people are having this issue.

carlcarter commented 6 years ago

Yes, experiencing exactly the same with the ipn simulator.

I’ve checked the parameters passed from the sim and compared them to what I push back for verification and they match exactly.

Have added user agent but still get invalid on every try.

overint commented 6 years ago

@pp-randy

jghankins commented 6 years ago

We're experiencing the same.

vdonchev commented 6 years ago

30 days and still no fix for this?

kwdel commented 6 years ago

Having same problem here. Pulled my hair out for days over this. One user mentioned it works fine when live. Anyone else able to confirm this? Thanks!

vdonchev commented 6 years ago

@kwdel I can confirm that it works with production IPN.

overint commented 6 years ago

Unfortunately i've not got a response from the paypal team, i've sent them a follow up email.

jamminjames commented 6 years ago

Well, you guys are doing better than me. I am using the PaypalIPN.php file with the example_usage.php listener, exactly as shown, and the Sandbox IPN Simulator is giving me the "IPN was not sent, and the handshake was not verified. Review your information" response.

jamminjames commented 6 years ago

Okay, changed a couple variables in the PaypalIPN.php file, and now I'm getting a good handshake, but still Invalid, as with everyone else.

I had to change these to true and false, respectively, even though the public variables were correct:

    /** @var bool Indicates if the sandbox endpoint is used. */
    private $use_sandbox = true;
    /** @var bool Indicates if the local certificates are used. */
    private $use_local_certs = false;
alfonsofoster commented 6 years ago

I still having the same Issue with my Python Code!... More than 1 month and no one can solve this issue? :(

MuhammadMohsan786 commented 6 years ago

Hi guys, I'm new to Dot Net Core and Angular. I have implemented the Paypal payment in my system. It takes the payment properly from user, also return them back to ThankYou page. But the problem is, it does not send the IPN response back. I have copied the code, mentioned in code section of ASPNETCORE_MVC. But it does not get called from the PayPal. I have specfied the url like this:

http://www.mywebsite.com/ControllerName

Here in my case the ControllerName is IPN and snapshot code is as below.

http://www.mywebsite.com/IPN

But it does not call the function Receive(), which i think it should call when the paypal sends the response back.

using System; using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; using Microsoft.AspNetCore.Mvc; using System.IO; using System.Net; using System.Text; using System.Web; using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Hosting;

namespace WebApplication4.Controllers { public class IPNController : Controller { private static IHostingEnvironment _hostingEnvironment; public IPNController(IHostingEnvironment environment) { _hostingEnvironment = environment; }

    private class IPNContext
    {
        public HttpRequest IPNRequest { get; set; }

        public string RequestBody { get; set; }

        public string Verification { get; set; } = String.Empty;
    }

    [HttpPost]
    public IActionResult Receive()
    {
        string l_strBody1 = "Paypal Response IPN:  - Hard coded";
        AlertsAndEmails.SendEmail("Muhammad", "muhammadmohsanms@gmail.com", l_strBody1, "https://google.com", _hostingEnvironment, "Paypal Response");

        IPNContext ipnContext = new IPNContext()
        {
            IPNRequest = Request
        };

        using (StreamReader reader = new StreamReader(ipnContext.IPNRequest.Body, Encoding.ASCII))
        {
            ipnContext.RequestBody = reader.ReadToEnd();
        }

        //Store the IPN received from PayPal
        LogRequest(ipnContext);

        //Fire and forget verification task
        Task.Run(() => VerifyTask(ipnContext));

        //Reply back a 200 code
        return Ok();
    }

//The rest of the code. }

Your effort will be highly appreciated. Thanks.

spivack1212-zz commented 6 years ago

Muhammad, make sure you have app.UseMvc() in your Startup.cs file.

Also, make sure your IPN listener is deployed to a website that supports TLS 1.2. I.e. your URL should begin with "https://", not "http://"

dagger59 commented 6 years ago

Still no fix for this? I'm having the same INVALID response problem...

overint commented 6 years ago

@onmas59

Unfortunately I do not work at paypal, however i've escalated it to their IPN team so hopefully they are working on a fix. @pp-randy

daslicht commented 6 years ago

same here with php

Swedz commented 6 years ago

@daslicht Indeed. I saw someone say it operates successfully on the live servers rather than the sandbox ones, if anyone can validate this? I don't want to push something if it is not operating as desired.

vdonchev commented 6 years ago

@Swedz I confirm that the example code works well with the production endpoint.

daslicht commented 6 years ago

Anyways, what the the purpose of a sandbox when it is not working ? How to test the IPN without a real transaction ...

daslicht commented 6 years ago

Just tried it again, today it worked with teh sandbox !

damianobarbati commented 6 years ago

IPN simulator is broken, always returning INVALID when the same code in production returns VERIFIED. And my IPN script correctly sends back the processed the message to https://ipnpb.sandbox.paypal.com/cgi-bin/webscr when using IPN simulator and not 'https://ipnpb.paypal.com/cgi-bin/webscr.

Such a shame...

daslicht commented 6 years ago

Here thats what I get when I do a ExpressCheckout IPN simulation:

damianobarbati commented 6 years ago

@daslicht yeah, me too. Then verification of IPN message to https://ipnpb.sandbox.paypal.com/cgi-bin/webscr miserably fails. Same code of production, just calling sandbox url. We resorted testing with real transactions.

daslicht commented 6 years ago

Just tried it and: $verified = $ipn->verifyIPN(); returns true

in Sandbox mode here. one day ago it always was false

daslicht commented 6 years ago

@damianobarbati Just tried it again this time when i call the listener with the IPN Tester form dev tools I also get false. But when i do a sandbox checkout it is true

saidmrn commented 6 years ago

Same problem here using the sample code.

ataker commented 6 years ago

Same issue. Hoping paypal can look at this soon so my development isn't blocked.

daslicht commented 6 years ago

do you guys also get that error when performing a checkout using a sandbox account ? The only thing which discourage me from using PayPal is their bad support.

I wait for an aswer for some days now, whereas Braintree answers within a few hours.

terrose commented 6 years ago

this is not working for me

On Thu, Jul 19, 2018 at 7:13 AM, Marc Wensauer notifications@github.com wrote:

do you guys also get that error when performing a checkout using a sandbox account ?

— You are receiving this because you are subscribed to this thread. Reply to this email directly, view it on GitHub https://github.com/paypal/ipn-code-samples/issues/134#issuecomment-406255354, or mute the thread https://github.com/notifications/unsubscribe-auth/Ags1R7knDydEssXSfbVhy0C7z-7LLrZ2ks5uIHf1gaJpZM4UKQGf .

vassilisw commented 6 years ago

Always INVALID here too - I wonder... paypal is on vocations for one more time!

topwebstudio commented 6 years ago

Same problem here as well. No official support whatsoever. Thanks a lot

carlcarter commented 6 years ago

For what it’s worth, I can confirm the same works fine in production.

Having said that, watch out for payment_date format differences between the IPN simulator and what production actually sends you. They’re different in the experience I had today.

Sent from my iPhone

On 25 Jul 2018, at 18:07, Top Web Studio notifications@github.com wrote:

Same problem here as well. No official support whatsoever. Thanks a lot

— You are receiving this because you commented. Reply to this email directly, view it on GitHub, or mute the thread.

Alir3z4 commented 6 years ago

I confirm this happens for me. Been dealing with this for over 2 days by now.

topwebstudio commented 6 years ago

Lost whole day with this. Thought It was me doing something wrong. Working on a complex project. I don't need external complications. Leaving validations for now. I hope this doesn't take 2 years to resolve. Testing with live version is not an option at this point.

muokid3 commented 6 years ago

i can confirm it WORKS in PRODUCTION but always returns INVALID in sandbox whether using the simulator or actual sandbox payment

UPDATE In production, you have to go to IPN History (https://www.paypal.com/ke/cgi-bin/webscr?cmd=_display-ipns-history) and turn ON IPN then provide your IPN listener link in that page

tfoote000 commented 6 years ago

I lost a lot of time on this issue but our company's PayPal representative helped out a lot. Here is the information that he gave me: "IPN messages sent using the IPN simulator cannot be verified. They will always return INVALID." -- Clarification -- (thank you @daslicht for the visual) simulator -> always invalid sandbox transaction -> verified

I was able to successfully get a VERIFIED IPN by setting up IPN in the sandbox environment then placing a payment using a sandbox account. Here are the instructions:

As @muokid3 commented, you can see IPN history for both production and sandbox environments.

damianobarbati commented 6 years ago

If the mocked (sandboxed) version does not behave like the production version, then testing is useless because you'd be testing a behaviour not equal to the tested (and expected) one. 🤔

vdonchev commented 6 years ago

@tfoote000 This is not true. The sandbox was working as expected a few months ago. There are plenty of videos on Youtube that show it working as well.

daslicht commented 6 years ago

@tfoote000 as told above, I have exactly the same expericne.

simulator -> always false
sandbox transaction -> vertified

However, yesterday I did some collision tests, where 2 customees pay at teh same time, and there was only ONE time the IPN listener called at all ! weird stuff

ataker commented 6 years ago

Still getting verification failed, even from sandbox transactions. Verifying fine in production.

membiblio commented 6 years ago

tldr; Same Problem, Same Code, Same Result - Always INVALID.

Called Paypal to ask if this was still an issue and if the sandbox was working or broken specifically referencing this thread. You know what happened. Yes they could be more helpful.

The problem is posting the query back to paypal for final handshake approval. Paypal detects SOMETHING different. The code posted here works in the paypal sandbox using a button created with the sandbox button factory - use sandbox buyer credentials, be logged into the sandbox, watch the log file (see end of source code, logging to a file is included, 777 the file to get started then lower permissions until it just works), press your paypal buy it now button and use the buyer sandbox credentials to checkout/pay - when completed, wait up to a minute, the IPN is posted back and it will be VERIFIED - if paypal says so. Please note the code around the variable $testPKT - I took the paypal query, prepended the magic incantation "'cmd=_notify-validate'" and then sent that back to paypal - this code is slightly different from the PayPal git repository - though much of the unused code is still here - so that someone can see the difference and then use the debugging output to try and make this better. All I guarantee is this works in the sandbox for me and returns VERIFIED when it should.

Thanks to everyone in this thread for getting me this close.

Here is the code:

`<?php

//header('Content-Type: text/html; charset=utf-8'); //mb_internal_encoding("UTF-8");

//$log -> log('('.basename(file).':'.line.')'.' Begin IPN Postback **', PEAR_LOG_DEBUG); localLog('('.basename(file).':'.line.')'.' Begin IPN postback.php **');

// STEP 1: read POST data // Reading POSTed data directly from $_POST causes serialization issues with array data in the POST. // Instead, read raw POST data from the input stream. $raw_post_data = file_get_contents('php://input'); localLog("RAW: ".$raw_post_data." END \n");

$raw_post_array = explode('&', $raw_post_data); $myPost = array();

foreach ($raw_post_array as $keyval) { $keyval = explode ('=', $keyval);

if (count($keyval) == 2) 
{
    // Since we do not want the plus in the datetime string to be encoded to a space, we manually encode it.
    if ($keyval[0] === 'payment_date') {
        if (substr_count($keyval[1], '+') === 1) {
            $keyval[1] = str_replace('+', '%2B', $keyval[1]);
        }
    }
    $myPost[$keyval[0]] = rawurldecode($keyval[1]);
    localLog('('.basename(__file__).':'.__line__.')'.'PRE:    $keyval[0]: '.$keyval[0].'= '.rawurldecode($keyval[1]) );
} 

}

//exit();

// read the IPN message sent from PayPal and prepend 'cmd=_notify-validate' $req = 'cmd=_notify-validate';

if (function_exists('get_magic_quotes_gpc')) { $get_magic_quotes_exists = true; }

foreach ($myPost as $key => $value) { if ($get_magic_quotes_exists == true && get_magic_quotes_gpc() == 1) { $value = rawurlencode(stripslashes($value)); localLog('('.basename(file).':'.line.')'.'MQE $key: '.$key.'= '.$value); } else { $value = rawurlencode($value); localLog('('.basename(file).':'.line.')'.' $key: '.$key.'= '.$value); } $req .= "&$key=$value"; }

//$req=str_replace("%40", "@", $req);

localLog('('.basename(file).':'.line.')'.'Final formed $req: '.$req);

// Step 2: POST IPN data back to PayPal to validate //if (0) // 0 sandbox, 1 production //{ // $ch = curl_init('https://ipnpb.paypal.com/cgi-bin/webscr'); //} //else { // $ch = curl_init('https://ipnpb.sandbox.paypal.com/cgi-bin/webscr'); //}

// Be sure... for testing since returned NOT VERIFIED... $ch = curl_init('https://ipnpb.sandbox.paypal.com/cgi-bin/webscr');

//localLog('('.basename(file).':'.line.')'.'POSTING to: '.$ch);

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);

$testPKT='cmd=_notify-validate&'.$raw_post_data; localLog('('.basename(file).':'.line.')'.'$testPKT: '.$testPKT); curl_setopt($ch, CURLOPT_POSTFIELDS, $testPKT);

curl_setopt($ch, CURLOPT_SSLVERSION, 6);

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( 'User-Agent: PHP-IPN-Verification-Script', 'Connection: Close', ));

// In wamp-like environments that do not come bundled with root authority certificates, // please download 'cacert.pem' from "https://curl.haxx.se/docs/caextract.html" and set // the directory path of the certificate as shown below:

//curl_setopt($ch, CURLOPT_CAINFO, dirname(FILE) . '/cacert.pem');

if ( !($res = curl_exec($ch)) ) { //$log -> log('('.basename(file).':'.line.')'.'CURL ERROR: '.curl_error($ch), PEAR_LOG_DEBUG); localLog('('.basename(file).':'.line.')'.'CURL ERROR: '.curl_error($ch)); // error_log("Got " . curl_error($ch) . " when processing IPN data"); curl_close($ch); exit; }

$info = curl_getinfo($ch); $http_code = $info['http_code']; localLog('('.basename(file).':'.line.')'.'PayPal Response: '.$http_code);

curl_close($ch);

localLog('('.basename(file).':'.line.')'.'$res: '.$res);

// inspect IPN validation result and act accordingly if (strcmp ($res, "VERIFIED") == 0) { localLog("APPROVED!!!");

// The IPN is verified, process it: // check whether the payment_status is Completed // check that txn_id has not been previously processed // check that receiver_email is your Primary PayPal email // check that payment_amount/payment_currency are correct // process the notification // assign posted variables to local variables $item_name = $_POST['item_name']; $item_number = $_POST['item_number']; $payment_status = $_POST['payment_status']; $payment_amount = $_POST['mc_gross']; $payment_currency = $_POST['mc_currency']; $txn_id = $_POST['txn_id']; $receiver_email = $_POST['receiver_email']; $payer_email = $_POST['payer_email']; // IPN message values depend upon the type of notification sent.

// To loop through the &_POST array and print the NV pairs to the screen: foreach($_POST as $key => $value) { //echo $key . " = " . $value . "
"; //$log -> log('('.basename(file).':'.line.')'.'$key: '.$key." $value: ".$value, PEAR_LOG_DEBUG); localLog('('.basename(file).':'.line.')'.'APPROVED POST: $key: '.$key." $value: ".$value); }

} else if (strcmp ($res, "INVALID") == 0) { // IPN invalid, log for manual investigation //echo "The response from IPN was: " .$res .""; //$log -> log('('.basename(file).':'.line.')'.'IPN Response: '.$res, PEAR_LOG_DEBUG); localLog('('.basename(file).':'.line.')'.'IPN Response: '.$res); }

function localLog($arg) {

$fh = fopen('/***fully qualified path name***/postback.log', 'a+');

if ($fh)
{

    fwrite($fh, $arg."\n");

    fclose($fh);

}

}

?>`


End of code

ghost commented 6 years ago

It's always invalid for me aswell.

Edit: I'm using c#

membiblio commented 6 years ago

Did you try the code which was posted just above your comment?

Were you logged into your developer sandbox account when you tried to complete a sandbox transaction and were you using one of the buyer accounts in your sandbox account?

Did you watch your server error log to see if there was any issue with the SSL?

Finally did you tail the postback.log file that my code dumps?

Don't give up.

phambinh217 commented 5 years ago

I have same issue, when I use curd with php, the response always is "INVALID". I tried with post man, the response is same, always is "INVALID"

daslicht commented 5 years ago

SANDBOX mock IPN calls can't be verified. Use a real Sandbox transaction.

BTW the legacy API is deprecated, the ReST API is its successor.

membiblio commented 5 years ago

Pham,

Use the IPN simulator in the sandbox just to get your code running as a postback endpoint on your server for paypal to postback to then, after your code is running and you are writing to your database all the essential items which the IPN simulator posted to you - and you added sufficient debugging to write the raw data paypal sends to you to a log file - use the paypal sandbox to test your postback code by creating a 'real' test transaction in the sandbox environment.

Using PayPal's sandbox and developer portal can be a bit confusing here is my crib sheet:

paypal.com is the production environment where you get paid - you knew this :)

sandbox.paypal.com is the sandbox of paypal.com - you can fake it and you don't get paid but the IPN postback works just like the real production environment - get it working here and change all the urls to the live environment and life will be sweet for you. I promise!

developer.paypal.com is where you log in with your REAL paypal credentials that you use on the live site and you setup FAKE credentials (user name and passwords) to use against the sandbox.paypal.com during testing - this can be a bit confusing but just work through it and ask questions - also be sure to observe closely anytime you are testing, or using paypal for real, to watch what credentials your browser autofills - I've tried logging into paypal with sandbox credentials and vice versa because the browser autofilled the popup form and I was busy 'testing' :)

I have this working and you can as well if you start with the code posted above. If you need more help please post again to this thread.

lim3ra commented 5 years ago

Few days ago I started my first project with PayPal IPN. I think I tested everything but I am still getting INVALID status... I tested code from this repo, code from PayPal website and other samples from Internet. It's impossible.

Anyone can help me with that? How can I try my code?

`<?php

$raw_post_data = file_get_contents('php://input'); $raw_post_array = explode('&', $raw_post_data); $myPost = array(); foreach ($raw_post_array as $keyval) { $keyval = explode ('=', $keyval); if (count($keyval) == 2) $myPost[$keyval[0]] = urldecode($keyval[1]); } $req = 'cmd=_notify-validate'; if (function_exists('get_magic_quotes_gpc')) { $get_magic_quotes_exists = true; } foreach ($myPost 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"; }

// Step 2: POST IPN data back to PayPal to validate $ch = curl_init('https://ipnpb.sandbox.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_SSLVERSION, 6); 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( 'User-Agent: PHP-IPN-Verification-Script', 'Connection: Close', ));

if ( !($res = curl_exec($ch)) ) { curl_close($ch); exit; } curl_close($ch);

if (strcmp ($res, "VERIFIED") == 0) {

file_put_contents("valid.txt", "valid"); //debug
$item_name = $_POST['item_name'];
$item_number = $_POST['item_number'];
$payment_status = $_POST['payment_status'];
$payment_amount = $_POST['mc_gross'];
$payment_currency = $_POST['mc_currency'];
$txn_id = $_POST['txn_id'];
$receiver_email = $_POST['receiver_email'];
$payer_email = $_POST['payer_email'];
foreach($_POST as $key => $value) {
    echo $key . " = " . $value . "<br>";
}

} else if (strcmp ($res, "INVALID") == 0) { file_put_contents("invalid.txt", "invalid"); //debug echo "The response from IPN was: " .$res .""; }`

daslicht commented 5 years ago

I think I tested everything but I am still getting INVALID status.. how do you called it ? With a mock event or a real sandbox sale ? Mock events sent from teh developer dashboard will ever be invalid

related: https://github.com/paypal/ipn-code-samples/tree/master/php https://github.com/mike182uk/paypal-ipn-listener

Probably those example help somehow/