PayPal в лайв-режиме игнорируется IPN

245
08 января 2018, 11:19

На сайте установлена PayPal кнопка мгновенного платежа "Купить сейчас". Оплата реализована через php-скрипт IPN, в результате работы которого в случае успешной транзакции заносятся в БД данные о покупке и на емэйл-адрес покупателя отправляется письмо с данными о совершённой покупке и ссылкой на скачивание купленного файла. В "песочнице" (через sandbox) всё работает отлично - оплата проходит, заносятся данные в БД, генерится ссылка на файл и отправляется письмо, но в реальном режиме работает только оплата, а всё остальное, что должно происходить после успешной оплаты - не работает. Аккаунт PayPal - Премьер, в настройках продавца всё что нужно включено (страница возврата, PDT, IPN). Такое ощущение, что в реальном режиме игнорируется IPN, а срабатывает только PDT, так как на страницу возврата (success.php) редирект происходит успешно и передаёт все необходимые POST-данные о совершённой транзакции в адресной строке. Так же замечено, что номер транзакции в этой адресной строке отличается от кода операции, указанного в квитанции от PayPal, которая приходит после оплаты на емэйл покупателя. Ниже приведён код самой кнопки и фрагмент кода файла ipn.php

Форма оплаты:

<form action="https://www.paypal.com/cgi-bin/webscr" method="post"/>
    <input type="hidden" name="cmd"           value="_xclick"/>
    <input type="hidden" name="notify_url"    value="http://mysite.com/ipn.php"/>
    <input type="hidden" name="cancel_return" id="cancel_return" value="http://mysite.com"/>
    <input type="hidden" name="bn"            value="Product"/>
    <input type="hidden" name="business"      value="business@email.com"/>
    <input type="hidden" name="item_name"     value="Product Name"/>
    <input type="hidden" name="currency_code" value="RUB"/>
    <input type="hidden" name="custom"        value="Product ID>"/>
    <input type="hidden" name="image_url"     value="http://mysite.com/img/my_logo.jpg"/>
    <input type="hidden" name="no_shipping"   value="1"/>
    <input type="hidden" name="quantity"      value="1"/>
    <input type="hidden" name="lc"            value="RU"/>
    <input type="hidden" name="return"        value="http://mysite.com/success.php"/>
    <input type="hidden" name="charset"       value="utf-8"/>
    <input type="hidden" name="amount"        value="20.00"/>
    <input type="submit" id="submit" name="submit" value="Buy Now - 20.00 RUB"/>
    </div/>
</form/>

Фрагмент кода файла ipn.php:

    <?php
    require_once($_SERVER["DOCUMENT_ROOT"].'/config.php');
    // initialize swiftmailer
    $transport_smtp = Swift_SmtpTransport::newInstance($smtp_server, $smtp_port)
        ->setUsername($smtp_user)
        ->setPassword($smtp_pass);
    $mailer = Swift_Mailer::newInstance($transport_smtp);
    /*--------------------------------------------------------------
    RECEIVE POST FROM PAYPAL
    --------------------------------------------------------------*/
    // Reading POSTed data directly from $_POST causes serialization issues with array data in the POST.
    // Instead, read raw POST data from the input stream.
    $raw_post_data  = file_get_contents('php://input');
    $raw_post_array = explode('&', $raw_post_data);
    $paypal_post    = array();
    foreach ($raw_post_array as $keyval) {
        $keyval = explode ('=', $keyval);
        if (count($keyval) == 2) {
            $paypal_post[$keyval[0]] = urldecode($keyval[1]);
        }
    }
    //extract vars
    extract($paypal_post, EXTR_OVERWRITE);
    // build request
    $req = 'cmd=' . urlencode('_notify-validate');
    $ipn_vars = 'cmd=' . urlencode('_notify-validate');
    foreach ($paypal_post as $k => $v) {
        $v = urlencode($v);
        $req .= "&$k=$v";
    }
    // sort array keys (only after building $req var which will be used to send curl to paypal)
    ksort($paypal_post);
    foreach ($paypal_post as $k => $v) {
        $ipn_vars .= "\n$k=" . urldecode($v);
    }
    /*--------------------------------------------------------------
    SEND POST BACK TO PAYPAL
    --------------------------------------------------------------*/
    // paypal mode
    $paypal_mode = 1;
    // sandbox on/off
    if($paypal_mode == 1) {
        $paypal_url = 'https://www.paypal.com/cgi-bin/webscr';
    }
    // else is production site
    else {
        $paypal_url = 'https://www.sandbox.paypal.com/cgi-bin/webscr';
    }
    $ch = curl_init();
    curl_setopt($ch, CURLOPT_URL, $paypal_url);
    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, false);
    curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);
    curl_setopt($ch, CURLOPT_FORBID_REUSE, 1);
    curl_setopt($ch, CURLOPT_HTTPHEADER, array('Connection: Close'));
    $res = curl_exec($ch);
    //Check if any error occured
    if(curl_errno($ch)) {
        $ipn_response = curl_error($ch);
    }
    // else no curl error
    else {
        if(strcmp($res, "VERIFIED") == 0 || 1) {
          // ipn vars
    $business       = (isset($_POST['business']))       ? $_POST['business']       : '';
    $custom         = (isset($_POST['custom']))         ? $_POST['custom']         : '';
    $first_name     = (isset($_POST['first_name']))     ? $_POST['first_name']     : '';
    $item_name      = (isset($_POST['item_name']))      ? $_POST['item_name']      : '';
    $item_number    = (isset($_POST['item_number']))    ? $_POST['item_number']    : '';
    $last_name      = (isset($_POST['last_name']))      ? $_POST['last_name']      : '';
    $mc_currency    = (isset($_POST['mc_currency']))    ? $_POST['mc_currency']    : '';
    $mc_gross       = (isset($_POST['mc_gross']))       ? $_POST['mc_gross']       : '';
    $payer_email    = (isset($_POST['payer_email']))    ? $_POST['payer_email']    : '';
    $payer_id       = (isset($_POST['payer_id']))       ? $_POST['payer_id']       : '';
    $payment_gross  = (isset($_POST['payment_gross']))  ? $_POST['payment_gross']  : '';
    $payment_status = (isset($_POST['payment_status'])) ? $_POST['payment_status'] : '';
    $receiver_email = (isset($_POST['receiver_email'])) ? $_POST['receiver_email'] : '';
    $txn_id         = (isset($_POST['txn_id']))         ? $_POST['txn_id']         : '';
    $txn_type       = (isset($_POST['txn_type']))       ? $_POST['txn_type']       : '';
          .......................
          //здесь код, добавляющий информацию о покупке в БД, генерирующий 
          //ссылку на скачивание файла и отправляющий письмо покупателю с этой 
          //ссылкой и данными о совершенной покупке
          .......................
    }
?>

В файле config.php служебная инфа для подключения к БД и т.п., не относящаяся к самому процессу оплаты.

В чем может быть проблема и в каком направлении искать её решение?

UPD: В качестве проверки в файле ipn.php в блоке

if(strcmp($res, "VERIFIED") == 0 || 1) {}

написал небольшую функцию по сохранению всех данных, полученных с IPN, в текстовый файл на сервере. В режиме sandbox всё сохраняет и записывает, т.е. проверку (VERIFIED) проходит. Но в лайв режиме файл не создаётся и ничего не записывается, т.е. проверку не проходит. В таком случае не понятно почему проходит оплата и откуда берётся код операции в квитанции от PayPal, отличающийся от того, который возвращается через PDT??

READ ALSO
php ssh2 ошибка

php ssh2 ошибка

Windows 10 64 (Пробовал и для windows 7 64)

267
Создать select циклом

Создать select циклом

Нужно сделать выпадающий список, где option - это штаты

205
Php Mysql FT vs LIKE

Php Mysql FT vs LIKE

Здравствуйте, стоит выбор при помощи чего реализовывать поиск по сайту, оператор LIKE, или же FullTextПодскажите пожалуйста что лучше, и желательно...

206
PHP помогите найти ошибку - РЕШЕНО, кажется

PHP помогите найти ошибку - РЕШЕНО, кажется

Испортила шаблон на БитриксНе знаю, где ошиблась

220