简体   繁体   English

使用电子邮件功能时,贝宝IPN不起作用

[英]paypal IPN not working when using email function

I'm implementing payments through paypal on my website and I'm having trouble with the Instant Payment Notification's, 我正在通过我的网站上的贝宝(Paypal)进行付款,而即时付款通知(Instant Payment Notification)却遇到问题,

I've got the following base code copied from the paypal's example: 我从贝宝的示例中复制了以下基本代码:

<?php
// CONFIG: Enable debug mode. This means we'll log requests into 'ipn.log' in the same directory.
// Especially useful if you encounter network errors or other intermittent problems with IPN (validation).
// Set this to 0 once you go live or don't require logging.
define("DEBUG", 1);
// Set to 0 once you're ready to go live
define("USE_SANDBOX", 1);
define("LOG_FILE", "./ipn.log");

$raw_post_data = file_get_contents('php://input');
$raw_post_array = explode('&', $raw_post_data);
$myPost = array();
foreach ($raw_post_array as $keyval) {
    $keyval = explode ('=', $keyval);
    if (count($keyval) == 2)
        $myPost[$keyval[0]] = urldecode($keyval[1]);
}
// read the post from PayPal system and add 'cmd'
$req = 'cmd=_notify-validate';
if(function_exists('get_magic_quotes_gpc')) {
    $get_magic_quotes_exists = true;
}
foreach ($myPost as $key => $value) {
    if($get_magic_quotes_exists == true && get_magic_quotes_gpc() == 1) {
        $value = urlencode(stripslashes($value));
    } else {
        $value = urlencode($value);
    }
    $req .= "&$key=$value";
}
// Post IPN data back to PayPal to validate the IPN data is genuine
// Without this step anyone can fake IPN data
if(USE_SANDBOX == true) {
    $paypal_url = "https://www.sandbox.paypal.com/cgi-bin/webscr";
} else {
    $paypal_url = "https://www.paypal.com/cgi-bin/webscr";
}
$ch = curl_init($paypal_url);
if ($ch == FALSE) {
    return FALSE;
}
curl_setopt($ch, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_1);
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_RETURNTRANSFER,1);
curl_setopt($ch, CURLOPT_POSTFIELDS, $req);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, 1);
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 2);
curl_setopt($ch, CURLOPT_FORBID_REUSE, 1);
if(DEBUG == true) {
    curl_setopt($ch, CURLOPT_HEADER, 1);
    curl_setopt($ch, CURLINFO_HEADER_OUT, 1);
}

// Set TCP timeout to 30 seconds
curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 30);
curl_setopt($ch, CURLOPT_HTTPHEADER, array('Connection: Close'));

$res = curl_exec($ch);
if (curl_errno($ch) != 0) // cURL error
    {
    if(DEBUG == true) { 
        error_log(date('[Y-m-d H:i e] '). "Can't connect to PayPal to validate IPN message: " . curl_error($ch) . PHP_EOL, 3, LOG_FILE);
    }
    curl_close($ch);
    exit;
} else {
        // Log the entire HTTP response if debug is switched on.
        if(DEBUG == true) {
            error_log(date('[Y-m-d H:i e] '). "HTTP request of validation request:". curl_getinfo($ch, CURLINFO_HEADER_OUT) ." for IPN payload: $req" . PHP_EOL, 3, LOG_FILE);
            error_log(date('[Y-m-d H:i e] '). "HTTP response of validation request: $res" . PHP_EOL, 3, LOG_FILE);
        }
        curl_close($ch);
}
// Inspect IPN validation result and act accordingly
// Split response headers and payload, a better way for strcmp
$tokens = explode("\r\n\r\n", trim($res));
$res = trim(end($tokens));
if (strcmp ($res, "VERIFIED") == 0) {


    mail('try@website.com', 'New Order', 'New Order', 'From: support@website.com');



    if(DEBUG == true) {
        error_log(date('[Y-m-d H:i e] '). "Verified IPN: $req ". PHP_EOL, 3, LOG_FILE);
    }
} else if (strcmp ($res, "INVALID") == 0) {
    // log for manual investigation
    // Add business logic here which deals with invalid IPN messages
    if(DEBUG == true) {
        error_log(date('[Y-m-d H:i e] '). "Invalid IPN: $req" . PHP_EOL, 3, LOG_FILE);
    }
}
?>

If I remove the mail function everything works as intended, the log is written once and a "sent" state appears at the IPN history. 如果我删除了邮件功能,那么一切都会按预期工作,日志将被写入一次,并且IPN历史记录中将出现“已发送”状态。

Now, when the mail function is used, everything is executed for like 8 times, this means 8 log writings and 8 emails sent. 现在,当使用邮件功能时,所有内容将执行8次,这意味着8次日志记录和8封电子邮件已发送。 Meanwhile The IPN History keeps in "retrying" state turning into "error" state after some time, mention that the http response field is empty in both cases. 同时,“ IPN历史记录”经过一段时间后一直处于“重试”状态,变为“错误”状态,并提到在两种情况下http响应字段均为空。

Thanks for your time mates. 感谢您的时间伙伴。

Edit 1: 编辑1:

this is the content in the log file: 这是日志文件中的内容:

[2016-04-27 12:19 America/New_York] HTTP request of validation request:POST /cgi-bin/webscr HTTP/1.1
Host: www.sandbox.paypal.com
Accept: */*
Connection: Close
Content-Length: 1052
Content-Type: application/x-www-form-urlencoded
Expect: 100-continue



for IPN payload: bla bla bla
[2016-04-27 12:19 America/New_York] HTTP response of validation request: HTTP/1.1 100 Continue

HTTP/1.1 200 OK

bla bla bla

VERIFIED

i think everything is OK, also the apache log doesen't display any error... 我认为一切都很好,Apache日志也不会显示任何错误...

Edit 2: 编辑2:

Solved, See the solution below. 解决了,请参阅下面的解决方案。

I think that your mail function is failing and giving a header other than 200 which paypal expects that is why the 8 more retries. 我认为您的邮件功能失败,并且给定了200以外的标头,贝宝希望这就是为什么要重试8次的原因。 Anyway I edited the code and placed the mail() function within a try catch block and logged the error. 无论如何,我编辑了代码并将mail()函数放在try catch块中并记录了错误。

    <?php
        // CONFIG: Enable debug mode. This means we'll log requests into 'ipn.log' in the same directory.
        // Especially useful if you encounter network errors or other intermittent problems with IPN (validation).
        // Set this to 0 once you go live or don't require logging.
        define("DEBUG", 1);
        // Set to 0 once you're ready to go live
        define("USE_SANDBOX", 1);
        define("LOG_FILE", "./ipn.log");

        $raw_post_data = file_get_contents('php://input');
        $raw_post_array = explode('&', $raw_post_data);
        $myPost = array();
        foreach ($raw_post_array as $keyval) {
            $keyval = explode ('=', $keyval);
            if (count($keyval) == 2)
                $myPost[$keyval[0]] = urldecode($keyval[1]);
        }
        // read the post from PayPal system and add 'cmd'
        $req = 'cmd=_notify-validate';
        if(function_exists('get_magic_quotes_gpc')) {
            $get_magic_quotes_exists = true;
        }
        foreach ($myPost as $key => $value) {
            if($get_magic_quotes_exists == true && get_magic_quotes_gpc() == 1) {
                $value = urlencode(stripslashes($value));
            } else {
                $value = urlencode($value);
            }
            $req .= "&$key=$value";
        }
        // Post IPN data back to PayPal to validate the IPN data is genuine
        // Without this step anyone can fake IPN data
        if(USE_SANDBOX == true) {
            $paypal_url = "https://www.sandbox.paypal.com/cgi-bin/webscr";
        } else {
            $paypal_url = "https://www.paypal.com/cgi-bin/webscr";
        }
        $ch = curl_init($paypal_url);
        if ($ch == FALSE) {
            return FALSE;
        }
        curl_setopt($ch, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_1);
        curl_setopt($ch, CURLOPT_POST, 1);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER,1);
        curl_setopt($ch, CURLOPT_POSTFIELDS, $req);
        curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, 1);
        curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 2);
        curl_setopt($ch, CURLOPT_FORBID_REUSE, 1);
        if(DEBUG == true) {
            curl_setopt($ch, CURLOPT_HEADER, 1);
            curl_setopt($ch, CURLINFO_HEADER_OUT, 1);
        }

        // Set TCP timeout to 30 seconds
        curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 30);
        curl_setopt($ch, CURLOPT_HTTPHEADER, array('Connection: Close'));

        $res = curl_exec($ch);
        if (curl_errno($ch) != 0) // cURL error
            {
            if(DEBUG == true) { 
                error_log(date('[Y-m-d H:i e] '). "Can't connect to PayPal to validate IPN message: " . curl_error($ch) . PHP_EOL, 3, LOG_FILE);
            }
            curl_close($ch);
            exit;
        } else {
                // Log the entire HTTP response if debug is switched on.
                if(DEBUG == true) {
                    error_log(date('[Y-m-d H:i e] '). "HTTP request of validation request:". curl_getinfo($ch, CURLINFO_HEADER_OUT) ." for IPN payload: $req" . PHP_EOL, 3, LOG_FILE);
                    error_log(date('[Y-m-d H:i e] '). "HTTP response of validation request: $res" . PHP_EOL, 3, LOG_FILE);
                }
                curl_close($ch);
        }
        // Inspect IPN validation result and act accordingly
        // Split response headers and payload, a better way for strcmp
        $tokens = explode("\r\n\r\n", trim($res));
        $res = trim(end($tokens));
        if (strcmp ($res, "VERIFIED") == 0) {


            try{
mail('try@website.com', 'New Order', 'New Order', 'From: support@website.com');

}
catch(Exception $e){
error_log(date('[Y-m-d H:i e] '). "Email could not be sent. Error" . $e->getMessage(). PHP_EOL, 3, LOG_FILE);
}


            if(DEBUG == true) {
                error_log(date('[Y-m-d H:i e] '). "Verified IPN: $req ". PHP_EOL, 3, LOG_FILE);
            }
        } else if (strcmp ($res, "INVALID") == 0) {
            // log for manual investigation
            // Add business logic here which deals with invalid IPN messages
            if(DEBUG == true) {
                error_log(date('[Y-m-d H:i e] '). "Invalid IPN: $req" . PHP_EOL, 3, LOG_FILE);
            }
        }
        ?>

Okey I finally found the solution, this is only for people working with a virtual private server. Okey我终于找到了解决方案,这仅适用于使用虚拟专用服务器的人员。 The problem for me was the mail function that was taking too long and maybe generating a timeout in the IPN listener, 对我来说,问题是邮件功能花费的时间太长,可能会在IPN侦听器中产生超时,

To solve this: 要解决这个问题:
- First you get the hostname tiping hostname in the command prompt -首先,您会在命令提示符下获得提示hostname的主机hostname
- Then I edit the hosts file : sudo nano /etc/hosts -然后我编辑主机文件: sudo nano /etc/hosts
-----------and change this line -> 127.0.0.1 localhost myhostname -----------并更改此行-> 127.0.0.1 localhost myhostname
-----------to this line -> 127.0.0.1 localhost localhost.localdomain myhostname -----------至此行-> 127.0.0.1 localhost localhost.localdomain myhostname

Source: 资源:
http://deeemm.com/entry/general/fix-your-painfully-slow-php-mail-function http://deeemm.com/entry/general/fix-your-painfully-slow-php-mail-function

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM