views:

200

answers:

3

The PayPal IPN Guide documentation says clearly

  1. Post the request to www.paypal.com or www.sandbox.paypal.com, depending on whether you are going live or testing your listener in the Sandbox.

  2. Wait for a response from PayPal, which is either VERIFIED or INVALID.

Well, I tried that (the Sandbox version), and the response was a full HTML page.

So I glanced at the code sample at https://www.paypal.com/us/cgi-bin/webscr?cmd=p/pdn/ipn-codesamples-pop-outside#php and saw that the suggested URI there was /cgi-bin/webscr. I tried that, and still got a full HTML page. DOCTYPE and everything.

What am I doing wrong? And is it just me, or is PayPal documentation unnecessarily confusing?

Edit to add:

I've tried resetting the URL to a page I control, which simply dumps out $_GET, $_POST and $_SERVER data, and I can see there that I'm sending the correct info. (I'm now putting the information in the $_GET string, as Alex K suggested, instead of in the POST body, but I'm still sending it as a POST request.)

And I'm still getting a HTML reply from the sandbox:

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"&gt;
<html lang="en">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<!--
         Script info: script: webscr, cmd: notify-validate, template: p/wel/sandbox-outside, date: Jul 28, 2010 17:09:26 PDT; country: US, language: en_US, xslt server: 
        web version: 64.0-1430643 branch: UPR_641_int
        content version: -
        pexml version: 64.0-1434686
        page XSL: Merchant/default/en_US/homepage/SandBox-outside.xsl
       hostname : DOxxcnld8je7pj0zYHT0DtWhtm4QxXx1WVQNKYCmQt0
         rlogid : DOxxcnld8je7pj0zYHT0Do0AouceG%2b49A2fz8FNwI82Hi9r1Lzz7MA%3d%3d_12a42bb271e
-->
<title>Welcome - PayPal</title>
<!--googleoff: all-->
<meta name="description" content="PayPal is the safer, easier way to pay online without revealing your credit card number.">
<!--googleon: all-->
<meta http-equiv="X-UA-Compatible" content="IE=8">
<link media="screen" rel="stylesheet" type="text/css" href="https://www.sandbox.paypal.com/WEBSCR-640-20100726-1/css/core/xptdev.css"&gt;
<link media="screen" rel="stylesheet" type="text/css" href="https://www.sandbox.paypal.com/WEBSCR-640-20100726-1/css/core/global.css"&gt;
<!--[if IE 8]><link media="screen" rel="stylesheet" type="text/css" href="https://www.sandbox.paypal.com/WEBSCR-640-20100726-1/css/browsers/ie8.css"&gt;&lt;![endif]--&gt;

<!--[if IE 7]><link media="screen" rel="stylesheet" type="text/css" href="https://www.sandbox.paypal.com/WEBSCR-640-20100726-1/css/browsers/ie7.css"&gt;&lt;![endif]--&gt;

<!--[if lte IE 6]><link media="screen" rel="stylesheet" type="text/css" href="https://www.sandbox.paypal.com/WEBSCR-640-20100726-1/css/browsers/ie6.css"&gt;&lt;![endif]--&gt;
<link rel="stylesheet" type="text/css" href="https://www.sandbox.paypal.com/WEBSCR-640-20100726-1/css/sandbox.css"&gt;
<link media="print" rel="stylesheet" type="text/css" href="https://www.sandbox.paypal.com/WEBSCR-640-20100726-1/css/core/print.css"&gt;
<script type="text/javascript">
if (parent.frames.length > 0){
    top.location.replace(document.location);
}</script><script type="text/javascript" src="https://www.sandbox.paypal.com/WEBSCR-640-20100726-1/js/lib/min/global.js"&gt;&lt;/script&gt;&lt;script type="text/javascript">PAYPAL.util.lazyLoadRoot = 'https://www.sandbox.paypal.com/WEBSCR-640-20100726-1';&lt;/script&gt;&lt;link rel="shortcut icon" href="https://www.sandbox.paypal.com/WEBSCR-640-20100726-1/en_US/i/icon/pp_favicon_x.ico"&gt;
<link rel="apple-touch-icon" href="https://www.sandbox.paypal.com/WEBSCR-640-20100726-1/en_US/i/pui/apple-touch-icon.png"&gt;
</head>
<body class="xptSandbox">
<noscript><p class="nonjsAlert">NOTE: Many features on the PayPal Web site require Javascript and cookies. You can enable both via your browser's preference settings.</p></noscript>
<div class="" id="page">
<div id="content">
<div id="headline">
<h2 class="accessAid">Welcome</h2>
</div>
<div id="messageBox"></div>
<div id="main"><div class="layout1">
<p><img src="https://www.sandbox.paypal.com/WEBSCR-640-20100726-1/en_US/i/logo/logo_sandbox_clr_289x39.gif" border="0" alt=""></p>
<p align="center"><strong>Please login to use the <a href="https://developer.paypal.com/"&gt;PayPal Sandbox</a> features.</strong></p>
</div></div>
</div>
<div id="navFull"><ul>
<li class="active">
<a href="https://www.sandbox.paypal.com/cgi-bin/webscr?cmd=_home-general&amp;amp;nav=0" class="scTrack:SRD:Nav:L5">Home</a><ul>
<li class="active">
<a href="https://personal.paypal.com/cgi-bin/marketingweb?cmd=_render-content&amp;amp;content_ID=marketing_us/How_does_PayPal_work&amp;amp;nav=0.0" class="scTrack:SRD:Nav:W8">How PayPal Works</a><ul>
<li><a href="https://personal.paypal.com/cgi-bin/marketingweb?cmd=_render-content&amp;amp;content_ID=marketing_us/How_does_PayPal_work&amp;amp;nav=0.0.0" class="scTrack:SRD:Nav:YX">What is PayPal</a></li>
<li><a href="https://personal.paypal.com/cgi-bin/marketingweb?cmd=_render-content&amp;amp;content_ID=marketing_us/Sign_Up_for_PayPal&amp;amp;nav=0.0.1" class="scTrack:SRD:Nav:YY">Getting Started</a></li>
<li><a href="https://personal.paypal.com/cgi-bin/marketingweb?cmd=_render-content&amp;amp;content_ID=marketing_us/My_PayPal_Account&amp;amp;nav=0.0.2" class="scTrack:SRD:Nav:YZ">Managing Your Account</a></li>
<li><a href="https://personal.paypal.com/cgi-bin/marketingweb?cmd=_render-content&amp;amp;content_ID=marketing_us/How_To_Use_PayPal&amp;amp;nav=0.0.3" class="scTrack:SRD:Nav:W2">Great Ways to Use PayPal</a></li>
<li><a href="https://personal.paypal.com/cgi-bin/marketingweb?cmd=_render-content&amp;amp;content_ID=marketing_us/PayPal_FAQ&amp;amp;nav=0.0.4" class="scTrack:SRD:Nav:Z0">Top Ten Things to Know About PayPal</a></li>
<li><a href="https://www.sandbox.paypal.com/cgi-bin/webscr?cmd=_display-fees-outside&amp;amp;nav=0.0.5" class="scTrack:SRD:Nav:y80">How Much It Costs</a></li>
<li><a href="https://www.sandbox.paypal.com/cgi-bin/webscr?cmd=xpt/Marketing/general/PayPalAccountTypes-outside&amp;amp;nav=0.0.6" class="scTrack:SRD:Nav:Z8">Account Types</a></li>
</ul>
</li>
<li>
<a href="https://personal.paypal.com/cgi-bin/marketingweb?cmd=_render-content&amp;amp;content_ID=marketing_us/pay_online&amp;amp;nav=0.1" class="scTrack:SRD:Nav:W3">Pay Online</a><ul>
<li><a href="https://www.paypal-shopping.com/" class="scTrack:SRD:Nav:Z2">Great Deals</a></li>
<li><a href="https://www.paypal-shopping.com/shop-stores.html" class="scTrack:SRD:Nav:Z3">PayPal Store Directory</a></li>
<li><a href="https://personal.paypal.com/cgi-bin/marketingweb?cmd=_render-content&amp;amp;content_ID=marketing_us/paypal_credit_card&amp;amp;nav=0.1.2" class="scTrack:SRD:Nav:W4">PayPal Plus MasterCard</a></li>
<li><a href="https://personal.paypal.com/us/cgi-bin/?&amp;amp;cmd=_render-content&amp;amp;content_ID=marketing_us/mobile_payments#payonline&amp;amp;nav=0.1.3" class="scTrack:SRD:Nav:L6">Shop Via Mobile</a></li>
</ul>
</li>
<li>
<a href="https://personal.paypal.com/cgi-bin/marketingweb?cmd=_render-content&amp;amp;content_ID=marketing_us/send_money&amp;amp;nav=0.2" class="scTrack:SRD:Nav:N9">Send Money</a><ul>
<li><a href="https://personal.paypal.com/cgi-bin/marketingweb?cmd=_render-content&amp;amp;content_ID=marketing_us/send_money&amp;amp;nav=0.2.0" class="scTrack:SRD:Nav:O1">Send Money Online</a></li>
<li><a href="https://www.sandbox.paypal.com/cgi-bin/webscr?cmd=xpt/Marketing_CommandDriven/general/International_Money_Transfer-outside&amp;amp;nav=0.2.1" class="scTrack:SRD:Nav:O2">Internationally</a></li>
<li><a href="https://student.paypal.com/us/cgi-bin/marketingweb?cmd=_render-content&amp;amp;content_ID=marketing_us/student_accounts&amp;amp;nav=0.2.2" class="scTrack:SRD:Nav:MR">To Your Teen</a></li>
<li><a href="https://personal.paypal.com/us/cgi-bin/?&amp;amp;cmd=_render-content&amp;amp;content_ID=marketing_us/mobile_payments#sendmoney&amp;amp;nav=0.2.3" class="scTrack:SRD:Nav:Y4">Via Your Mobile</a></li>
</ul>
</li>
<li>
<a href="https://personal.paypal.com/cgi-bin/marketingweb?cmd=_render-content&amp;amp;content_ID=marketing_us/receive_money&amp;amp;nav=0.3" class="scTrack:SRD:Nav:Y5">Get Paid</a><ul>
<li><a href="https://personal.paypal.com/cgi-bin/marketingweb?cmd=_render-content&amp;amp;content_ID=marketing_us/sell_on_ebay&amp;amp;nav=0.3.0" class="scTrack:SRD:Nav:Y6">Sell Online</a></li>
<li><a href="https://merchant.paypal.com/cgi-bin/marketingweb?cmd=_render-content&amp;amp;content_ID=merchant/wp_standard&amp;amp;nav=0.3.1" class="scTrack:SRD:Nav:Y7">Accept Credit Cards</a></li>
<li><a href="https://personal.paypal.com/cgi-bin/marketingweb?cmd=_render-content&amp;amp;content_ID=marketing_us/request_money&amp;amp;nav=0.3.2" class="scTrack:SRD:Nav:P6">Request Money</a></li>
<li><a href="https://www.paypal.com/nonprofit" class="scTrack:SRD:Nav:P7">Accept Donations</a></li>
</ul>
</li>
<li><a href="https://personal.paypal.com/cgi-bin/marketingweb?cmd=_render-content&amp;amp;content_ID=marketing_us/products_services&amp;amp;nav=0.4" class="scTrack:SRD:Nav:P8">Products &amp; Services</a></li>
</ul>
</li>
<li><a href="https://www.sandbox.paypal.com/cgi-bin/webscr?cmd=_home-customer&amp;amp;nav=1" class="scTrack:SRD:Nav:L8">Personal</a></li>
<li><a href="https://merchant.paypal.com/cgi-bin/marketingweb?cmd=_render-content&amp;amp;content_ID=merchant/home&amp;amp;nav=2" class="scTrack:SRD:Nav:x60">Business</a></li>
<li><a href="https://www.paypal.com/developer" class="scTrack:SRD:Nav:S9">Developers</a></li>
</ul></div>
<script type="text/javascript">if(typeof PAYPAL != 'undefined'){ PAYPAL.core.Navigation.init(); }</script>
</div>
<script type="text/javascript" src="https://www.sandbox.paypal.com/WEBSCR-640-20100726-1/js/lib/min/widgets.js"&gt;&lt;/script&gt;&lt;script type="text/javascript" src="https://www.sandbox.paypal.com/WEBSCR-640-20100726-1/js/pp_naturalsearch.js"&gt;&lt;/script&gt;&lt;script type="text/javascript">mp_landing();</script>
<!-- SiteCatalyst Code
Copyright 1997-2005 Omniture, Inc.
More info available at http://www.omniture.com -->
<script type="text/javascript" src="https://www.sandbox.paypal.com/WEBSCR-640-20100726-1/js/site_catalyst/pp_jscode_paypalsandboxdev.js"&gt;&lt;/script&gt;
<script type="text/javascript">
s.prop1="p/wel/sandbox-outside";
s.prop7="Unknown";
s.prop8="Unknown";
s.prop9="Unknown";
s.prop10="US";
s.prop14="";
s.prop34="PayPalCredit:Servicing:CO:NoTransactions";
s.pageName="p/wel/sandbox-outside::notify-validate";
s.prop50="en_US";
s.prop18="";
</script>
<script type="text/javascript"><!--
/************* DO NOT ALTER ANYTHING BELOW THIS LINE ! **************/
var s_code=s.t();if(s_code)document.write(s_code);
if(navigator.appVersion.indexOf('MSIE')>=0)document.write(unescape('%3C')+'\!-'+'-')
//-->
</script><noscript><img
src="//paypal.112.2O7.net/b/ss/paypalsandboxdev/1/H.6--NS/0?pageName=NonJavaScript"
height="1" width="1" border="0" alt="" /></noscript>
<!--/DO NOT REMOVE/-->

<!-- End SiteCatalyst Code -->
<script type="text/javascript">         
                        YUE.addListener(window, "load", function() {                                
                            PAYPAL.util.lazyLoad("/js/Customer/min/baynote.js", function() {
                                var searchFormsIDs = ["searchForm", "searchformnew", "searchform"];                                 
                                YUE.addListener(searchFormsIDs, 'submit', function() {baynote_handleSubmit(this);});            

                                var bn_timeout = setTimeout(function() {
                                    if (typeof baynote_validateSearchBox == 'function') {
                                        baynote_validateSearchBox();
                                        clearTimeout(bn_timeout);
                                    }
                                }, 200);
                            });
                        });
                        </script>
</body>
</html>
A: 

When the IPN hits your script you should post back to:

https://www.paypal.com/cgi-bin/webscr?cmd=_notify-validate&amp;&lt;all the junk they posted you>
(or https://www.sandbox.paypal.com/...)

Then check the response body of that for VERIFIED.

If all of that's giving you some HTML, what is it?

Alex K.
Aha! I thought the data went back in the POST body, not in the URL itself. I'll give that a whirl and see what happens. I was using `CURLOPT_POSTFIELDS`.
TRiG
Nope. still getting back full HTML. I'll edit my question and paste it in.
TRiG
Nope, rereading their sample code, it should go in the POST body, not the URL. But I'm still getting back a full HTML page.
TRiG
A: 

I've got this sorted now, by using their provided sample code and tweaking it slightly to put in validation. I'm still not sure exactly what I was doing wrong with the code I was using: I haven't bothered debugging it, now that I've got other code working.

  1. It is a POST request, not GET.
  2. For now, I'm using their sample code, which uses fsockopen instead of cURL, but it works, which is the main thing.
  3. The request goes to a URL on PayPal which is not reserved for IPN calls: it also exists as an HTML page.
  4. If you do anything wrong in your request, PayPal returns the HTML page instead of an IPN response.

https://www.x.com/message/180364

TRiG
Would prefer not to accept my own answer, especially as it doesn't actually give much information, but neither of the other answers is accurate.
TRiG
A: 

If you were using CURL, there's a catch - you have to form the POST data block by hand, instead of passing an array. If you pass an array, CURL will send it as multipart data, instead of URL-encoded form, like PayPal expects. I had a very similar issue and got it to work with CURL, eventually. Sample in PHP below:

function deq($s) //Removes the dreaded "magic quotes"
{
    if($s == null)
        return null;
    return
        get_magic_quotes_gpc() ?
        stripslashes($s) : $s;
}

function MakeQS($po) //Makes an URL-encoded query string from an associative array
{
    $ps = "";
    foreach($po as $k => $v)
        $ps .= ($ps == "" ? "" : "&").$k."=".urlencode(deq($v));
    return $ps;
}

$cu = curl_init("https://www.paypal.com/cgi-bin/webscr");
$po = $_POST;
$po["cmd"] = "_notify-validate";
curl_setopt_array($cu, array(
    CURLOPT_RETURNTRANSFER  => true,
    CURLOPT_HEADER => false,
    CURLOPT_POST => 1,
    CURLOPT_POSTFIELDS => MakeQS($po)  //This is the non-obvious bit!
    ));
$resp = curl_exec($cu);
if(curl_errno($cu) !== 0)
    //fail...

curl_close($cu);
if($resp != "VERIFIED")
    //fail...

This is working production code.

Seva Alekseyev
Aha! I've got it working now, and I won't touch it, but if I ever need to poke at it again I'll look into this. Thanks!
TRiG