从PayPal获取交易后的信息

25

我想在我的网站上创建一个简单的交易,当交易完成后,我希望PayPal将用户重定向到我的网站上的某个位置,并且我希望PayPal提供细节,以便我可以使用PHP解析它并将购买链接发送给他们。我不确定notify_url是什么?谢谢。

我想在我的网站上创建一个简单的交易,当交易完成后,我希望PayPal将用户重定向到我的网站上的某个位置,并且我希望PayPal提供细节,以便我可以使用PHP解析它并将购买链接发送给他们。我不确定notify_url是什么?谢谢。
4个回答

60

PayPal的工作原理如下:

您有一个带有“购买”按钮的表单。当点击该按钮时,它会将信息(产品、价格、您的账户名称等)发送到PayPal。

然后买家同意向您付款,当交易完成时,PayPal会向您的通知URL发送“IPN”(即时支付通知)-它会向该URL发送POST数据以供您的服务器处理。您回复PayPal询问他们是否发送了POST数据(而不是冒名顶替者),如果他们回答这是一笔真正的交易,您就可以向客户发布产品。请注意,所有这些都是在您的买家仍然“在”PayPal网站的情况下发生的。

最后有一个可选阶段,即PayPal将买家返回到您的网站。在这种情况下,他们将买家送回您的“返回”URL,并且他们可以(可选地)再次传递交易数据(他们称之为PDT)。然后您可以再次与Paypal联系以确定这是否是有效交易,并在那时提供下载等操作。

没有人解释的最困难的部分是买家不会重定向到您的通知URL。也就是说,“访问者”到您网站的通知URL是PayPal,而不是买家,因此这不是您买家会话的一部分。如果您希望在这个过程的三个部分之间保持会话,那么您需要创建一种跟踪买家的方法,并将其传递到表单的一个名为“custom”的字段中以便传递给PayPal。这些数据将通过IPN和PDT数据传递回给您,您可以使用它来重新建立与原始用户会话的连接。

你确实需要同时实现IPN和PDT - 如果IPN电子邮件失败,则可以使用PDT作为备份。如果用户在重定向回到您的PDT页面之前关闭了他们的Web浏览器,则已发送IPN电子邮件作为备份。

搜索IPN和PDT,你会找到很多信息。PayPal也有完整的文档和示例脚本。


也许我误解了,但我认为这是非此即彼的。我认为您可以在商家配置文件中选择PDT或IPN,但不能同时拥有两者。您能向我展示如何同时设置PDT和IPN吗? - Volomike
@Volomike:阅读最后两段这里(paypal)和其他SO答案,比如这个 - Jason Williams
@JasonWilliams 链接似乎已经失效。 - Bhargav Nanekalva
损坏了,仅仅三年过去了? :-) ... 这里有一个更加现行的,在PayPal开发者网站上。他们的文档非常好,值得多次阅读,直到你确定你理解了所有内容为止。如果仍然感到困惑,网络搜索引擎会带来更多信息。 - Jason Williams
一个小修正:然后买家同意支付您的款项,当交易完成时,PayPal会向您的通知URL发送“IPN”(即时付款通知),即使交易未完成(例如付款仍在等待),也会发送IPN。此外,请注意,这一切都是在您的买家仍然“在”PayPal网站的背景下发生的并不完全准确,Paypal会在至少两种情况下(处理程序没有响应或处理订阅等情况)在用户返回网站后的几天内向监听器(或处理程序)发送通知。 - bg17aw

6

通知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;
   }

3
$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']; 

}

0

在解析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),这些值将被设置为全局变量。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接