【发布时间】:2011-01-26 22:56:27
【问题描述】:
我想在我的网站上创建一个简单的交易,在此人的交易完成后,我希望 paypal 将用户重定向到我网站上的某个地方,并且我希望 PayPal 向我提供详细信息,以便我可以使用 PHP解析它并将购买链接通过电子邮件发送给他们。我不确定 notify_url 是做什么的?谢谢
【问题讨论】:
我想在我的网站上创建一个简单的交易,在此人的交易完成后,我希望 paypal 将用户重定向到我网站上的某个地方,并且我希望 PayPal 向我提供详细信息,以便我可以使用 PHP解析它并将购买链接通过电子邮件发送给他们。我不确定 notify_url 是做什么的?谢谢
【问题讨论】:
PayPal 的工作原理如下:
您有一个带有“购买”按钮的表单。单击该按钮后,它会将信息(产品、价格、您的帐户名称等)发送到 PayPal。
然后买家同意向您付款,当交易完成时,PayPal 会向您的通知 URL 发送“IPN”(即时付款通知) - 它将 POST 数据发送到该 URL 以供您的服务器处理。您回复 PayPal 询问他们是否发送了 POST 数据(而不是冒名顶替者),如果他们回答这是真实交易,您可以将产品发布给客户。请注意,这一切都发生在后台,而您的买家仍“在”PayPal 网站。
还有最后一个可选阶段,即 PayPal 将买家返回到您的网站。在这种情况下,他们将买家发送回您的“退货”网址,并且他们可以(可选地)再次传回交易数据(他们称之为 PDT)。如果这是一个有效的交易,你可以再次与 Paypal 核对,并在那时提供下载等。
没有人解释的最困难的一点是 买家 没有被重定向到您的通知 URL。即,您网站通知 URL 的“访问者”是 PayPal,不是买家,因此这不会作为买家会话的一部分发生。如果您希望在此过程的三个部分中保持会话,那么您需要在表单中创建一种跟踪买家的方法,并将其传递给 PayPal 在称为“自定义”的表单字段中。此数据以 IPN 和 PDT 数据的形式传回给您,您可以使用它重新建立与原始用户会话的连接。
您确实需要同时实施 IPN 和 PDT - 如果 IPN 电子邮件失败,那么您有 PDT 作为备份。如果用户在被重定向回您的 PDT 页面之前关闭了他们的网络浏览器,那么您已经发送了一封 IPN 电子邮件作为备份。
在 IPN 和 PDT 上搜索,您会发现很多信息。 PayPal 也有完整的文档和示例脚本。
【讨论】:
The buyer then agrees to pay you and when the transaction is completed, PayPal send an "IPN" (instant payment notification) to your notify URL 即使交易未完成(如付款待处理),也会发送 IPN。此外,Note that this all happens in the background while your buyer is still "at" the PayPal website 在技术上并不正确,Paypal 将在用户返回网站很久之后(几天后)向侦听器(或处理程序)发送通知,至少在两种情况下:处理程序没有响应或处理时订阅等。
Notify URL应该指向保存从PayPal返回的数据的脚本,例如:
/** Fetch order from PayPal (IPN reply)
* @return int received ID of inserted row if received correctly, 0 otherwise
*/
function FetchOrder()
{
$transactionID=$_POST["txn_id"];
$item=$_POST["item_name"];
$amount=$_POST["mc_gross"];
$currency=$_POST["mc_currency"];
$datefields=explode(" ",$_POST["payment_date"]);
$time=$datefields[0];
$date=str_replace(",","",$datefields[2])." ".$datefields[1]." ".$datefields[3];
$timestamp=strtotime($date." ".$time);
$status=$_POST["payment_status"];
$firstname=$_POST["first_name"];
$lastname=$_POST["last_name"];
$email=$_POST["payer_email"];
$custom=$_POST["option_selection1"];
if ($transactionID AND $amount)
{
// query to save data
return $this->insertID;
}
else
{
return 0;
}
}
您也可以选择稍后验证订单:
/** Verify PayPal order (IPN)
* PayPal returns VERIFIED or INVALID on request
* @return bool verified 1 if verified, 0 if invalid
*/
function VerifyOrder()
{
$_POST["cmd"]="_notify-validate";
$ch=curl_init();
curl_setopt($ch,CURLOPT_HEADER,0);
curl_setopt($ch,CURLOPT_RETURNTRANSFER,1);
curl_setopt($ch,CURLOPT_USERAGENT,"your agent - replace");
curl_setopt($ch,CURLOPT_URL,"https://www.paypal.com/cgi-bin/webscr");
curl_setopt($ch,CURLOPT_POST, 1);
foreach ($_POST as $key=>$value)
{
$string.="&".$key."=".urlencode(stripslashes($value));
}
curl_setopt($ch, CURLOPT_POSTFIELDS, $string);
$result=curl_exec($ch);
if ($result=="VERIFIED") return 1;
else return 0;
}
【讨论】:
$tx=$_REQUEST['tx'];
$paypal_url='https://www.paypal.com/cgi-bin/webscr?cmd=_notify-synch&tx='.$tx.'&at=token here';
$curl = curl_init($paypal_url);
$data = array(
"cmd" => "_notify-synch",
"tx" => $tx,
"at" => "token here"
);
$data_string = json_encode($data);
curl_setopt ($curl, CURLOPT_HEADER, 0);
curl_setopt ($curl, CURLOPT_POST, 1);
curl_setopt ($curl, CURLOPT_POSTFIELDS, $data_string);
curl_setopt ($curl, CURLOPT_SSL_VERIFYPEER, 0);
curl_setopt ($curl, CURLOPT_RETURNTRANSFER, 1);
curl_setopt ($curl, CURLOPT_SSL_VERIFYHOST, 1);
$headers = array (
'Content-Type: application/x-www-form-urlencoded',
'Host: www.paypal.com',
'Connection: close'
);
curl_setopt ($curl, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_1);
curl_setopt ($curl, CURLOPT_HTTPHEADER, $headers);
$response = curl_exec($curl);
$lines = explode("\n", $response);
$keyarray = array();
if (strcmp ($lines[0], "SUCCESS") == 0) {
for ($i=1; $i<count($lines);$i++){
list($key,$val) = explode("=", $lines[$i]);
$keyarray[urldecode($key)] = urldecode($val);
}
$first_name=$keyarray['first_name'];
$last_name=$keyarray['last_name'];
$payment_status=$keyarray['payment_status'];
$business=$keyarray['business'];
$payer_email=$keyarray['payer_email'];
$payment_gross=$keyarray['payment_gross'];
$mc_currency=$keyarray['mc_currency'];
}
【讨论】:
在解析 PDT 响应时,我使用的是 parse_str。由于响应的主体是 url 编码的,因此只需用 & 号替换换行符 - 就像这样
$result = curl_exec($ch);
//replace the breaks with '&'
$r_string = str_replace("\n", "&", $result);
//parse the response into a key->value array
parse_str($r_string, $this->details);
if(!isset($this->details['SUCCESS'])){
//the "SUCCESS" or "FAIL" response is the first key
return FALSE;
}
else{
//the values of the response are now in an array
return TRUE;
}
根据应用程序,您甚至可以省略第二个参数 ($this->details),并将值设置为全局变量。
【讨论】: