PayPal IPN开发

时间:2013-01-29 22:30:35

标签: php paypal paypal-ipn

我在我的网站上设置PayPal IPN以管理订阅付款方面取得了一些成功。我目前正处于PayPal设置付款的状态,并且从PayPal沙箱向我的IPN发送完成的付款效果很好,并将MySQL行设置为is_paid为Yes而不是No,然后允许用户登录。

我现在想知道,当用户的订阅付款失败或他们取消时,IPN会如何让我知道(所有那些在现实世界中发生的糟糕和讨厌的事情!)?我希望IPN向管理员发送电子邮件

<?php
// tell PHP to log errors to ipn_errors.log in this directory
ini_set('log_errors', true);
ini_set('error_log', dirname(__FILE__).'/ipn_errors.log');

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

// tell the IPN listener to use the PayPal test sandbox
$listener->use_sandbox = true;

// try to process the IPN POST
try {
    $listener->requirePostMethod();
    $verified = $listener->processIpn();
} catch (Exception $e) {
    error_log($e->getMessage());
    exit(0);
}

// TODO: Handle IPN Response here

if ($verified) {

    $errmsg = '';   // stores errors from fraud checks

    // 1. Make sure the payment status is "Completed" 
    if ($_POST['payment_status'] != 'Completed') { 
        // simply ignore any IPN that is not completed
        exit(0); 
    }

    // 2. Make sure seller email matches your primary account email.
    if ($_POST['receiver_email'] != 'EMAILHERE') {
        $errmsg .= "'receiver_email' does not match: ";
        $errmsg .= $_POST['receiver_email']."\n";
    }

    // 3. Make sure the amount(s) paid match
    if ($_POST['mc_gross'] != '3.99') {
        $errmsg .= "'mc_gross' does not match: ";
        $errmsg .= $_POST['mc_gross']."\n";
    }

    // 4. Make sure the currency code matches
    if ($_POST['mc_currency'] != 'GBP') {
        $errmsg .= "'mc_currency' does not match: ";
        $errmsg .= $_POST['mc_currency']."\n";
    }

    // 5. Ensure the transaction is not a duplicate.
    mysql_connect('', '', '') or exit(0);
    mysql_select_db('') or exit(0);

    $txn_id = mysql_real_escape_string($_POST['txn_id']);
    $sql = "SELECT COUNT(*) FROM payments 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";
    }

    if (!empty($errmsg)) {

        // manually investigate errors from the fraud checking
        $body = "IPN failed fraud checks: \n$errmsg\n\n";
        $body .= $listener->getTextReport();
        mail('EMAILHERE', 'PayPal IPN Fraud Warning', $body);

    } else {

    // add this order to a table of completed orders
    $payer_email = mysql_real_escape_string($_POST['payer_email']);
    $mc_gross = mysql_real_escape_string($_POST['mc_gross']);
    $sql = "INSERT INTO payments VALUES 
            (NULL, '$txn_id', '$payer_email', $mc_gross)";

    if (!mysql_query($sql)) {
        error_log(mysql_error());
        exit(0);
    }

    // sends an email to the user to confirm subscription
    $websitepath="http://www.gaymate.co.uk";
    $message='<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
        <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
        <head>
        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
        <title>gaymate.co.uk</title>

        <style type="text/css">

        p {
            font-family: Arial;
            font-size: 12px;
            padding: 0 20px 0 20px; }

        .boldTitle {
            font-size: 13px;
            font-weight: bold; }

        .headerTitle {
            font-size: 16px;
            font-weight: bold; }

        .divider2 {
            padding: 0 20px 0 20px; }

        </style>

        </head>

        <body>
        <table width="500" border="0" cellspacing="0" cellpadding="0">
          <tr>
            <td>
            <a href="http://www.gaymate.co.uk/"><img src="http://www.gaymate.co.uk/images/email-header.jpg"></a>
            <img class="divider2" src="'.$websitepath.'/images/email/email-divider2.gif" alt="email-divider2" width="460" height="4" />
        <p>We have recieved confirmation from PayPal that you have completed payment and we are pleased to tell you that your account will be live on our site as soon as it has been approved by one of the moderators.</br></br>The Admin Team @ GayMate.co.uk</p>
       <img src="'.$websitepath.'/images/email/email-divider.gif" alt="email-divider" width="500" height="10" />
    </td>
  </tr>
</table>
<p>&nbsp;</p>
</body>
</html>
          ';


    $to = filter_var($_POST['payer_email'], FILTER_SANITIZE_EMAIL);
    $subject = "GayMate.co.uk Subscription Set-Up Completed";
    $header = "MIME-Version: 1.0\r\n";
    $header .= "From: EMAILHERE\r\n";
    $header .= "Reply-To: EMAILHERE\r\n";
    $header .= "Content-type: text/html; charset=iso-8859-1\r\n";
    mail($to, $subject, $message, $header);  
    }
    $sql = "UPDATE member SET is_paid='Yes' WHERE email='$to'";

    if (!mysql_query($sql)) {
        error_log(mysql_error());
        exit(0);
    }

} else {
    // manually investigate the invalid IPN
    mail('EMAILHERE', 'Invalid IPN', $listener->getTextReport());
}


?>

2 个答案:

答案 0 :(得分:1)

您需要检查$_POST['txn_type']的值,以了解通知的内容。

来自PayPal的文档:https://www.paypal.com/cgi-bin/webscr?cmd=p/acc/ipn-subscriptions-outside

我相信您对subscr_eotsubscr_failed感兴趣。

可能对您有所帮助的一些额外信息:

    用户取消订阅后立即发送
  • subscr_cancel
  • 订阅到期后发送
  • subscr_eot并且付款未通过。

用户取消订阅后,PayPal会向您发送subscr_cancel,然后在下次付款到期时发送subscr_eot

您可能还想阅读此相关问题:Subscriptions with Paypal IPN

答案 1 :(得分:1)

将这些内容添加到您的代码中并将//电子邮件代码//注释更改为您的电子邮件代码,它将正常运行。

在:

if ($_POST['payment_status'] != 'Completed') { 

添加:

// denied payment
if ($_POST['payment_status'] == 'Denied') { 
// email code
exit(0);
}

// failed subscription payment
if ($_POST['txn_type'] == 'subscr_failed') { 
// email code
exit(0);
}

// canceled subscription
if ($_POST['txn_type'] == 'subscr_cancel') { 
// email code
exit(0);
}

只需创建在评论中发送电子邮件所必需的内容。