Sivo 悉见

PayPal IPN with PHP

匿名 · 更新于 2013/11/6

PayPal IPN with PHP

如何在PHP中实现即时付款通知侦听器脚本

使用PayPal的即时付款通知(IPN)服务可以是一个有点复杂和难以解决的新的PayPal开发者。在这篇文章中我将步行通过你的整个过程中使用的 PHP-PayPal-IPN 项目避免在后端的PHP代码的常见陷阱多。

  1. Read the Manual... Seriously
  2. Understanding the IPN Process
  3. Create a PayPal Sandbox Account
  4. Code the IPN Listener
  5. Test the IPN Listener
  6. Secure the IPN Listener
  7. Final Sandbox Testing

阅读手册…严肃地

为了实现一个互穿网络监听你应该知道IPN是什么,它是如何工作的,以及为什么你需要它。读 PayPal Instant Payment Notification Guide. 我也将锤几点,访问了很多开发商在下一节。

Document:       Instant Payment Notification Guide 

Has moved to the following location: 

New URL:        https://developer.paypal.com/webapps/developer/docs/classic/ipn/integration-guide/IPNIntro/ 

Please update your bookmarks. 

 

了解IPN的过程

最常见的问题,我看到开发商具有IPN一体化的概念进行了paypal IPN服务器和Web服务器之间的。这是一个完全独立的过程中从最终用户通过点击贝宝网站支付,回到你的网站。此外,这些过程是异步的——你不知道如果PayPal IPN之前或之后将用户返回到您的网站。

通过HTTP协议使用 Client-server model ,最终用户的Web浏览器通常是“客户”和“服务器”您的Web服务器。与即时付款通知,支付服务器是“客户”,而不是最终用户的Web浏览器。没有任何浏览器参与。没人看到你的IPN脚本的输出。

这意味着你的互穿网络侦听器将不输出任何东西。你不能在你的IPN脚本使用 回波 或 打印 。调试时必须使用日志和电子邮件。

作为一个例子,让我们说,你有一个“现在购买”一页上被称为 shop.php按钮。你的按钮被配置为发送用户 成功。PHP 他们提交他们的支付和 IPN之后。PHP 配置为IPN的听众。看下面的图,蓝色的路径显示过程最终用户:在这种情况下,和红色的路径显示您的贝宝和Web服务器之间的互穿网络。
PayPal IPN Process Diagram
 

创建一个贝宝Sandbox帐户

如果你还没有这样做的话,你应该有两个测试账号,有一个PayPal帐户设置一个沙箱,作为测试买方和一个卖方测试。沙盒允许您测试交易和互穿网络处理而无需执行现场交易。按照 Sandbox User Guide 指令来设置你的帐户。

代码的IPN的听众

  1. 创建队列called ipn.php on你的Web服务器。这是你的脚本的URL to the IPN监听器。
  2. 下载 PHP-PayPal-IPN 复制ipnlistener.php到相同的目录下作为ipn.php或是别的包含路径的某处。

在你喜欢用的编辑器中打开ipn.php文件,这是刚刚开始

<?php
//告诉PHP错误记录到ipn_errors.log在此目录
ini_set('log_errors', true);
ini_set('error_log', dirname(__FILE__).'/ipn_errors.log');

//intantiate IPN侦听
include('ipnlistener.php');
$listener = new IpnListener();

//你能告诉IPN侦听器使用贝宝的测试沙箱
$listener->use_sandbox = true;

//尝试处理的IPN POST
try {
    $listener->requirePostMethod();
    $verified = $listener->processIpn();
} catch (Exception $e) {
    error_log($e->getMessage());
    exit(0);
}

/ / TODO:在这里处理IPN响应
?>

IPN校验

在try/catch块processIpn()方法处理所有的IPN的听众棘手位你。这种方法将:

  1. 编码的数据为回发到贝宝
  2. 的数据返回正确的PayPal URL
  3. 确保贝宝的HTTP响应状态代码200
  4. 从PayPal解析响应

processIpn() 方法将返回true如果IPN返回的是“验证”并返回false则是“无效的”。异常抛出致命错误如连接的或意外的反应从PayPal的问题。

Error Logging

由于互穿网络将发生您的贝宝和Web服务器之间的(而不是你的浏览器),你可以解决问题的唯一方式就是记录到一个文件或电子邮件错误。上面的代码设置PHP错误记录到一个文件名为 错误日志 在同一文件夹中的 ipn.php本。

安全警告: 在生产环境中你应该确保错误日志不可从网站。理想情况下你将“error_log '你网站的根目录之外。至少你应该配置您的Web服务器访问,日志文件(或所有的日志文件。)。Apache这可以使用.htaccess文件

继续向前,你应该测试以确保该错误记录工作那么你可以解决连接和服务器配置问题。由于PayPal使用IPN的“后”的方法,该方法将requirePostMethod()如果你尝试用其他方法访问IPN的听众抛出一个异常。因此,你可以通过访问 IPN力异常。PHP 直接在你的浏览器。把你的浏览器指向你的ipn.php URL。

你应该得到一个空白的屏幕和/或HTTP 405错误。该 ipn_errors.log 应已创建并包含消息如下:

[09-Sep-2011 11:57:09] Invalid HTTP request method.

如果ipn_errors.log没有被创建,或者它不包含错误信息后直接ipn.php然后您的Web服务器可能没有权限创建和写入文件。它的好,知道现在不是浪费时间,后来不知道为什么穿不工作。如果你不知道如何 安全 给PHP写权限,日志文件,然后您需要与您的托管公司或系统管理员的帮助或使用不同类型的日志记录策略。

注意: 你可以改变的异常处理程序对自己在一封邮件中,发送错误信息,然而,我会建议对直播系统这样做。如果或者我敢说贝宝服务器下去有一个错误的你不想得到一个每个IPN尝试电子邮件可能拖垮你的电子邮件服务器

Handle IPN Response

从电话到processIpn()方法的返回值是存储在$verified变量。一个简单的if/else块可以用来处理IPN的响应。把这段代码尝试/后立即catch块在TODO注释是。

// ... 

if ($verified) {
    // TODO:在实施额外的欺诈检查和MySQL存储
    mail('您的电子邮件地址', 'Valid IPN', $listener->getTextReport());
} else {
    //手动调查无效IPN
    mail('您的电子邮件地址', 'Invalid IPN', $listener->getTextReport());
}

// ...

现在你向自己发送的电子邮件无论IPN验证或无效。一个电子邮件通知通常是适合无效状态。然而,你需要多做一点的验证状态编码。但首先要确保代码正常工作为止

该getTextReport()方法是一种方便的方法来产生所有的互穿网络数据报告。它包括URI用于后回到paypal,使用网络的图书馆(cURL or fsockopen),完整的响应的内容,和所有的格式化的文本域后。

测试的IPN的听众

贝宝Sandbox包括便携小工具来测试你的IPN的听众没有经历的所有步骤所需测试的订单。登录到您的帐户点击测试工具 PayPal Sandbox ”,左侧导航

PayPal Sandbox Test Tools

单击“立即付款的通知(IPN)模拟器”链接,进入到你的 IPN的PHP脚本的URL。 。选择任何类型的交易通常你会选择适合您的项目需求交易类型它不用于测试脚本迄今物)

PayPal Sandbox IPN Simulator

PayPal将填写后的IPN的一堆的默认值。你可以让他们自己现在,向下滚动到“发送IPN”按钮在窗体的底部。
后点击“发送IPN”按钮下面2件事应该发生的。你应该有一个致命的错误,在 ipn_errors.log 新项或你应该和IPN报告的电子邮件。如果情况不是这样,双重检查下列:

  1. 确保你互穿网络仿真工具输入正确的URL
  2. 确保你正确输入您的电子邮件地址的源代码在这里所说的电子邮件地址
  3. 回到 Error Logging 并确保你的错误日志工作正常

安全的IPN的听众

现在,IPN的听众是工作你需要添加一些更多的支票欺诈交易。实现的具体细节可能会有所不同,这取决于你的具体经营什么贝宝服务被使用,但是基本的防欺诈技术都是一样的

  1. 确保支付状态是“已完成”,你会得到其他身份“也得到互穿网络”挂起“。
  2. 确保卖方电子邮件与您的主要帐户的电子邮件。
  3. 确保支付的金额(次)比赛你实际上你的商品或服务收费。
  4. 确保货币代码匹配。
  5. 确保交易是没有重复的命令已经处理。

为了这个例子,让我们假设你是销售数字下载9.99美元,说一本电子书,使用PayPal的“立即购买”按钮。 IPN验证时,你会向客户发送电子邮件的链接下载他们购买。
 

上面第4项中的欺诈检查是很容易检查。应改为下面的代码来处理您的IPN响应(自己的价值观填写您的电子邮件地址和你的主要的PayPal电子邮件):

// ...

if ($verified) {

    $errmsg = '';   / /存储错误欺诈检查

    // 1。确保支付状态是“已完成”
    if ($_POST['payment_status'] != 'Completed') { 
        //简单地忽略任何未完成的IPN
        exit(0); 
    }

    / / 2。确保卖方电子邮件与您的主要帐户的电子邮件。
    if ($_POST['receiver_email'] != '您的主PayPal电子邮件') {
        $errmsg .= "'receiver_email' does not match: ";
        $errmsg .= $_POST['receiver_email']."\n";
    }
    
    // 3。确保支付的金额(次)匹配
    if ($_POST['mc_gross'] != '9.99') {
        $errmsg .= "'mc_gross' does not match: ";
        $errmsg .= $_POST['mc_gross']."\n";
    }
    
    // 4。确保货币代码匹配
    if ($_POST['mc_currency'] != 'USD') {
        $errmsg .= "'mc_currency' does not match: ";
        $errmsg .= $_POST['mc_currency']."\n";
    }

    // TODO:在检查重复txn_id
    
    if (!empty($errmsg)) {
    
        //手动调查欺诈检查错误
        $body = "IPN failed fraud checks: \n$errmsg\n\n";
        $body .= $listener->getTextReport();
        mail('您的电子邮件地址', 'IPN Fraud Warning', $body);
        
    } else {
    
        / / TODO:在这里处理顺序
    }
    
} else {
    //手动调查无效IPN
    mail('您的电子邮件地址', 'Invalid IPN', $listener->getTextReport());
}

// ...

 

注意: 你需要检查的确切字段取决于您正在使用PayPal服务。 IPN和PDT变量在PayPal的文档一个领域可能存在的IPN列表。

$errmsg变量填入一个错误消息不具有价值,我们预计各个领域。如果发现错误,然后在电子邮件中发送IPN报告,随着这些错误消息。

此时您可以测试每个欺诈检查 Test the IPN Listener 节中描述的使用方法,只有这个时候,你需要确保使用的“Web接受”的交易类型和模拟场景,你将需要调整的领域您正在测试。

现在,你需要检查txn_id,确保你已经处理此交易。要做到这一点,创建一个简单的小MySQL表,您将在其中存储每一个完成的订单。然后,您可以对这个表在每个IPN检查txn_id的。

CREATE TABLE orders (
  order_id INT NOT NULL auto_increment PRIMARY KEY,
  txn_id VARCHAR(19) NOT NULL,
  payer_email VARCHAR(75) NOT NULL,
  mc_gross FLOAT(9,2) NOT NULL,
  UNIQUE INDEX (txn_id)
);

注意: 您还可以扩大这个表,,包括取其字段你想添加一个txn_id列,如果你已经有一个现有订单表。这仅仅是一个简单的例子。

随着MySQL表到位,你可以完成你的IPN侦听器脚本。首先,更换的注释/ / TODO:检查重复txn_id与下面的代码(填写您自己的数据库连接参数):

    // ...
    
    //5。确保交易不重复。
    mysql_connect('localhost', 'DB_USER', 'DB_PW') or exit(0);
    mysql_select_db('DB_NAME') or exit(0);

    $txn_id = mysql_real_escape_string($_POST['txn_id']);
    $sql = "SELECT COUNT(*) FROM orders WHERE txn_id = '$txn_id'";
    $r = mysql_query($sql);
    
    if (!$r) {
        error_log(mysql_error());
        exit(0);
    }
    
    $exists = mysql_result($r, 0);
    mysql_free_result($r);
    
    if ($exists) {
        $errmsg .= "'txn_id' has already been processed: ".$_POST['txn_id']."\n";
    }
    
    // ...

一个简单的SELECT COUNT(*)查询进行检查,看是否存在txn_id已经。任何MySQL错误记录,同一个错误日志。

接下来,取代评论// TODO:这里处理顺序用下面的代码:

 

 // ...
    
    / /添加一个表以完成订单
    $payer_email = mysql_real_escape_string($_POST['payer_email']);
    $mc_gross = mysql_real_escape_string($_POST['mc_gross']);
    $sql = "INSERT INTO orders VALUES 
            (NULL, '$txn_id', '$payer_email', $mc_gross)";
    
    if (!mysql_query($sql)) {
        error_log(mysql_error());
        exit(0);
    }
    
    / /用户发送一封电子邮件,链接到他们的数字下载
    $to = filter_var($_POST['payer_email'], FILTER_SANITIZE_EMAIL);
    $subject = "Your digital download is ready";
    mail($to, "Thank you for your order", "Download URL: ...");
    
    // ...

当IPN已经过验证,所有欺诈抽查合格,存储在表中的顺序,向客户发送一封电子邮件,链接到他们的数字下载。

最终沙盒测试

现在您就可以开始测试使用您的两个SANBOX账户的实际交易。您可以创建一个“立即购买”按钮,您的沙箱卖家帐户像下面。到HTML页面某处在您的网站上,并通过购买过程中使用沙箱买家帐户。 这个现实世界的测试,将让您的工作其他任何错误和微调的领域,以满足您的需求。

<form name="_xclick" action="https://www.sandbox.paypal.com/cgi-bin/webscr" 
    method="post">
    <input type="hidden" name="cmd" value="_xclick">
    <input type="hidden" name="business" value="您的沙盘卖方电子邮件">
    <input type="hidden" name="currency_code" value="USD">
    <input type="hidden" name="item_name" value="Digital Download">
    <input type="hidden" name="amount" value="9.99">
    <input type="hidden" name="return" value="这个网址">
    <input type="hidden" name="notify_url" value="你的ipn.php脚本的URL">
    <input type="image" src="http://www.paypal.com/en_US/i/btn/btn_buynow_LG.gif" 
        border="0" name="submit" alt="Make payments with PayPal - it's fast, free and secure!">
</form>
你喜欢的PayPal IPN PHP?如果您想帮助支持我的工作,捐赠的降压或两个是非常赞赏。