Невозможно получить ответ PayPal IPN в Code Igniter - PullRequest
0 голосов
/ 24 сентября 2018

Я занимаюсь этим уже 3 дня и до сих пор не могу заставить его работать.

Я хочу получить ответ PayPal от прослушивателя IPN, чтобы я мог соответствующим образом изменить свою базу данных., но что бы я ни делал, это просто не сработает.Я уже сделал следующее в своей учетной записи PayPal Sandbox:

  1. Включен автоматический возврат

  2. Установить URL автоматического возврата («paypal / success»)

  3. Включена передача платежных данных (PDT)
  4. Включен прием сообщений IPN
  5. Установить IPN URL ('paypal / ipn')

Перенаправление на URL-адрес автоматического возврата работает нормально, и я получаю данные платежа на странице успеха, но IPN не будет обрабатываться по не зависящим от меня причинам.Быстрый просмотр истории IPN в моем профиле PayPal показывает, что сообщения отправляются, но я не получаю их на своем конце.

Вот мой текущий прослушиватель IPN: Paypal / ipn

public function ipn() { 
        //Build the data to post back to Paypal
        $postback = 'cmd=_notify-validate'; 
        // go through each of the posted vars and add them to the postback variable
        foreach ($_POST as $key => $value) {
            $value = urlencode(stripslashes($value));
            $postback .= "&$key=$value";
        }

        // build the header string to post back to PayPal system to validate
        $header = "POST /cgi-bin/webscr HTTP/1.0\r\n";
        $header .= "Host: www.sandbox.paypal.com\r\n";//or www.sandbox.paypal.com
        $header .= "Content-Type: application/x-www-form-urlencoded\r\n";
        $header .= "Content-Length: " . strlen($postback) . "\r\n\r\n";

        // Send to paypal or the sandbox depending on whether you're live or developing
        // comment out one of the following lines
        $fp = fsockopen ('www.sandbox.paypal.com', 443, $errno, $errstr, 30);//open the connection
        //$fp = fsockopen ('www.paypal.com', 80, $errno, $errstr, 30);
        // or use port 443 for an SSL connection
        //$fp = fsockopen ('ssl://www.paypal.com', 443, $errno, $errstr, 30);

        if ( ! $fp ) {
            // HTTP ERROR Failed to connect
            $message = 'HTTP ERROR Failed to connect!'; 
            $this->email_me($message);
        } else { // if we've connected OK

            fputs ($fp, $header . $postback); //post the data back
            while ( ! feof($fp) ) {
                $response = fgets ($fp, 1024);

                if (strcmp (trim($response), "VERIFIED") == 0) { //It's verified

                    //read the payment details and the account holder
                    $payment_status = $_POST['payment_status'];
                    $receiver_email = urldecode($_POST['receiver_email']);

                    // further checks
                    if( ($payment_status == 'Completed') && ($receiver_email == $this->business_email) ) {

                        $message = 'IPN verified successfully!';
                        $this->email_me($message);

                        // Insert the transaction data in the database
                        $this->product_model->insert_transaction_details($_POST);

                    } else {

                        $message = 'Payment could not be verified!';
                        $this->email_me($message);  

                    }

                } else {

                    $message = 'IPN invalid!';
                    $this->email_me($message);  

                }
            }
        }
    }

Может кто-нибудь указать мне правильное направление, пожалуйста?Кроме того, могу ли я в любом случае проверить ответ IPN («ПРОВЕРЕНО» или «НЕДОПУСТИМО») на отладчике Chrome или на панели инструментов песочницы PayPal?Я могу видеть статус доставки на своей панели, но он нигде не говорит: «Проверено» или «Недействительно».

Ответы [ 3 ]

0 голосов
/ 25 сентября 2018

Одна из причин, по которой IPN не был получен, заключается в том, что при подключении к PayPal существует проблема, для устранения которой все, что вам нужно сделать, это изменить порт.

Таким образом, для этого кода с

$fp = fsockopen($url_parsed['host'],'80',$err_num,$err_str,30);  

К

$fp = fsockopen($url_parsed['host'],'443',$err_num,$err_str,30);

Вы также можете обратиться от здесь

0 голосов
/ 25 сентября 2018

Я нашел решение!Я написал обработчик IPN внутри контроллера, который разрешает доступ пользователям, которые вошли в систему как администратор.По-видимому, метод IPN запрещал доступ к PayPal для проверки транзакции.Я понял это и написал метод IPN на другом контроллере, и все работало отлично.

Я также изменил свой обработчик IPN на этот код (хотя оригинал может все еще работать ... я не пробовал):

class Paypal_ipn extends MY_Controller {
    public function __construct() {
        parent::__construct();
        $this->load->model('product_model');
        $this->sandbox = $this->config->item('sandbox'); 
        $this->paypal_host = $this->config->item('paypal_host'); 
        $this->paypal_url = $this->config->item('paypal_url'); 
        $this->business_email = $this->config->item('business');
    }


    public function ipn() {
        // STEP 1: Read POST data

        // reading posted data from directly from $_POST causes serialization 
        // issues with array data in POST
        // reading raw POST data from input stream instead. 
        $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";
        }

        // STEP 2: Post IPN data back to paypal to validate

        $ch = curl_init($this->paypal_url);

        $headers = array(
            'POST /cgi-bin/webscr HTTP/1.1',
            'Host: ' . $this->paypal_host,
            'Content-Type: application/x-www-form-urlencoded; charset=utf-8',
            'Content-Length: ' . strlen($req),
            'User-Agent: PayPal-IPN-VerificationScript',
            'Connection: Close'
        );

        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);
        curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);

        if( !($res = curl_exec($ch)) ) {
            curl_close($ch);
            exit;
        }
        curl_close($ch);

        // STEP 3: Inspect IPN validation result and act accordingly

        if (strcmp ($res, "VERIFIED") == 0) {
            // check whether the payment_status is Completed
            // check that txn_id has not been previously processed
            // check that receiver_email is your Primary PayPal email
            // check that payment_amount/payment_currency are correct
            // process payment

            // assign posted variables to local variables
            $item_name = $_POST['item_name'];
            $item_number = $_POST['item_number'];
            $payment_status = $_POST['payment_status'];
            $payment_amount = $_POST['mc_gross'];
            $payment_currency = $_POST['mc_currency'];
            $txn_id = $_POST['txn_id'];
            $receiver_email = urldecode($_POST['receiver_email']); 
            $payer_email = $_POST['payer_email'];
            $school_id = $_POST['custom'];

            // further checks
            if($payment_status == 'Completed') {

                $message = 'IPN verified successfully!';
                $this->email_developer($message);

                // Insert the transaction data in the database
                $this->product_model->insert_transaction_details($_POST);

            } else {

                $message = 'Payment could not be verified!';
                $this->email_developer($message);  

            }

        } else if (strcmp ($res, "INVALID") == 0) {
            // log for manual investigation
            $message = 'IPN Invalid!';
            $this->email_developer($message);

        }
    }

}

Для тех, кто может испытать мое затруднение,убедитесь, что вы также делаете следующее:

  1. Если вы включили подделку межсайтовых запросов (CSRF), убедитесь, что прослушиватель / обработчик IPN внесен в белый список, иначе сообщение IPN не будет выполнено (ошибка 403 в истории PayPal IPN).
  2. Чтобы убедиться, что ваш прослушиватель IPN работает хорошо, запустите его как URL и посмотрите ответ.Если есть какая-либо ошибка, она не будет работать.Для ответа попробуйте повторить «Проверено» или «Недействительно».
  3. Используйте PayPal IPN Simulator для проверки процесса.Включите процедуру, которая будет передавать информацию в базу данных в случае успеха.

Надеюсь, это кому-нибудь поможет.

0 голосов
/ 24 сентября 2018

используйте php: // input вместо $ _POST

резонанс, подробно описанный здесь: PHP "php: // input" vs $ _POST

также paypalимеет документацию для реализации IPN Listener и его в php учебник Paypal

...