The PayPal IPN Guide documentation says clearly
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.
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">
<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">
<link media="screen" rel="stylesheet" type="text/css" href="https://www.sandbox.paypal.com/WEBSCR-640-20100726-1/css/core/global.css">
<!--[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"><![endif]-->
<!--[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"><![endif]-->
<!--[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"><![endif]-->
<link rel="stylesheet" type="text/css" href="https://www.sandbox.paypal.com/WEBSCR-640-20100726-1/css/sandbox.css">
<link media="print" rel="stylesheet" type="text/css" href="https://www.sandbox.paypal.com/WEBSCR-640-20100726-1/css/core/print.css">
<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"></script><script type="text/javascript">PAYPAL.util.lazyLoadRoot = 'https://www.sandbox.paypal.com/WEBSCR-640-20100726-1';</script><link rel="shortcut icon" href="https://www.sandbox.paypal.com/WEBSCR-640-20100726-1/en_US/i/icon/pp_favicon_x.ico">
<link rel="apple-touch-icon" href="https://www.sandbox.paypal.com/WEBSCR-640-20100726-1/en_US/i/pui/apple-touch-icon.png">
</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/">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&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&content_ID=marketing_us/How_does_PayPal_work&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&content_ID=marketing_us/How_does_PayPal_work&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&content_ID=marketing_us/Sign_Up_for_PayPal&nav=0.0.1" class="scTrack:SRD:Nav:YY开发者_JS百科">Getting Started</a></li>
<li><a href="https://personal.paypal.com/cgi-bin/marketingweb?cmd=_render-content&content_ID=marketing_us/My_PayPal_Account&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&content_ID=marketing_us/How_To_Use_PayPal&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&content_ID=marketing_us/PayPal_FAQ&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&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&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&content_ID=marketing_us/pay_online&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&content_ID=marketing_us/paypal_credit_card&nav=0.1.2" class="scTrack:SRD:Nav:W4">PayPal Plus MasterCard</a></li>
<li><a href="https://personal.paypal.com/us/cgi-bin/?&cmd=_render-content&content_ID=marketing_us/mobile_payments#payonline&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&content_ID=marketing_us/send_money&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&content_ID=marketing_us/send_money&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&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&content_ID=marketing_us/student_accounts&nav=0.2.2" class="scTrack:SRD:Nav:MR">To Your Teen</a></li>
<li><a href="https://personal.paypal.com/us/cgi-bin/?&cmd=_render-content&content_ID=marketing_us/mobile_payments#sendmoney&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&content_ID=marketing_us/receive_money&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&content_ID=marketing_us/sell_on_ebay&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&content_ID=merchant/wp_standard&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&content_ID=marketing_us/request_money&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&content_ID=marketing_us/products_services&nav=0.4" class="scTrack:SRD:Nav:P8">Products & Services</a></li>
</ul>
</li>
<li><a href="https://www.sandbox.paypal.com/cgi-bin/webscr?cmd=_home-customer&nav=1" class="scTrack:SRD:Nav:L8">Personal</a></li>
<li><a href="https://merchant.paypal.com/cgi-bin/marketingweb?cmd=_render-content&content_ID=merchant/home&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"></script><script type="text/javascript" src="https://www.sandbox.paypal.com/WEBSCR-640-20100726-1/js/pp_naturalsearch.js"></script><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"></script>
<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>
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.
When the IPN hits your script you should post back to:
https://www.paypal.com/cgi-bin/webscr?cmd=_notify-validate&<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?
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.
- It is a
POST
request, notGET
. - For now, I'm using their sample code, which uses
fsockopen
instead ofcURL
, but it works, which is the main thing. - The request goes to a URL on PayPal which is not reserved for IPN calls: it also exists as an HTML page.
- If you do anything wrong in your request, PayPal returns the HTML page instead of an IPN response.
https://www.x.com/message/180364
精彩评论