2016-04-19 12 views
6

Używam klasy PHP, którą utworzyłem na podstawie przykładowego kodu z witryny PayPal. Używam tego również z CodeIgniter. Testuję słuchacza IPN za pomocą symulatora IPN. Moje e-maile są wysyłane, więc wiem, że jest on dostępny. Problem polega na tym, że zawsze otrzymuję odpowiedź INVALID i nie mam pojęcia dlaczego. To moja pierwsza integracja z PayPal w ramach jednej z moich stron. Co może być przyczyną tego problemu?Dlaczego moje walidacje paypal ipn zawsze zwracają INVALID?

Oto moja klasa:

<?php 

class Paypal { 

    public $sandbox = false; 
    private $_url; 
    public $verified = false; 
    public $fields = array(); 
    public $post_fields = array(); 
    public $result; 

    public function __construct($params = array()){ 

     $this->sandbox = (isset($params['sandbox'])) ? $params['sandbox'] : false; 

     $this->_url = ($this->sandbox) ? 'https://www.sandbox.paypal.com/cgi-bin/webscr' : 'https://www.paypal.com/cgi-bin/webscr'; 

    } 

    public function run(){ 

     $this->verified = false; 

     // STEP 1: read POST data 
     // 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); 

     foreach ($raw_post_array as $keyval) { 

      $keyval = explode ('=', $keyval); 

      if (count($keyval) == 2) 

      $this->post_fields[$keyval[0]] = urldecode($keyval[1]); 

     } 

     // read the IPN message sent from PayPal and prepend 'cmd=_notify-validate' 
     $req = 'cmd=_notify-validate'; 

     if (function_exists('get_magic_quotes_gpc')) { 

      $get_magic_quotes_exists = true; 

     } 

     foreach ($this->post_fields 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->_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, 1); 
     curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 2); 
     curl_setopt($ch, CURLOPT_FORBID_REUSE, 1); 
     curl_setopt($ch, CURLOPT_HTTPHEADER, array('Connection: Close')); 
     // In wamp-like environments that do not come bundled with root authority certificates, 
     // please download 'cacert.pem' from "http://curl.haxx.se/docs/caextract.html" and set 
     // the directory path of the certificate as shown below: 
     curl_setopt($ch, CURLOPT_CAINFO, FCPATH.'cacert.pem'); 
     if (!($res = curl_exec($ch))) { 
      // error_log("Got " . curl_error($ch) . " when processing IPN data"); 
      curl_close($ch); 
      die('curl did not work<br>'.FCPATH.'cacert.pem'); 
     } 
     curl_close($ch); 

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

      $this->verified = true;    

     } 

     $this->result = $res; 

    } 

Oto moja CI Kontroler:

function paypalipn(){ 

     $this->load->model('subscription'); 
     $this->load->library('paypal', array('sandbox' => true));; 

     $this->paypal->run(); 

     $fields = $this->paypal->post_fields; 

     if($this->paypal->verified){ 

      $data = array(
       'user_id' => $fields['buyer_id'], 
       'txn_id' => $fields['txn_id'], 
       'payment_gross' => $fields['mc_gross'], 
       'currency_code' => $fields['mc_currency'], 
       'payer_email' => $fields['payer_email'], 
       'plan_id' => $fields['item_number'], 
       'payment_status' => $fields['payment_status'] 
      ); 

      $this->subscription->create_payment($data); 

     } 

     $this->load->library('email'); 

     $this->email->to('*******@gmail.com'); 
     $this->email->from('**************'); 
     $this->email->subject('PayPal IPN'); 
     $this->email->message($this->paypal->result."\nAmount: ".$fields['mc_gross']."\nCurrency: ".$fields['mc_currency']."\nUser ID: ".$fields['buyer_id']); 

     $this->email->send(); 

    } 

Wszystkie pola są puste w wiadomości e-mail i $ this-> paypal-> Wyniki zawsze zwraca "NIEWAŻNY". Ktoś ma jakieś pomysły? Dziękuję za Twój czas.

+0

Twoja klasa Paypal wygląda na solidną i wydaje się być prawie identyczna z działającym kodem, którego używam. Musi to być jakaś inna kwestia, a protokół SSL to pierwsze miejsce, na które warto zwrócić uwagę. Czy protokół SSL faktycznie działa w Twojej witrynie i czy cacert.pem jest certyfikatem używanym w witrynie? Bez sprawdzonego połączenia https PayPal zawsze zwróci NIEPRAWIDŁOWO. – DFriend

+0

Sprawdź w swoich logach Paypal, aby zobaczyć, co otrzymujesz odpowiedź - chciałbym debugować twój cUrl dalej, aby zobaczyć, czy coś blokuje twoją prośbę. –

+0

Zrobiłem kilka debugowania i widzę, że $ raw_post_data jest zawsze pusta.Czy to może być przyczyną problemu? Jak mogę to naprawić? – ShoeLace1291

Odpowiedz

0

W kontrolerze CI jeśli masz napisane swój kod tak:

function paypalipn(){ 

     $this->load->model('subscription'); 
     $this->load->library('paypal', array('sandbox' => true));; 

     $this->paypal->run(); 

     $fields = $this->paypal->post_fields; 

     if($this->paypal->verified){ 

      $data = array(
       'user_id' => $fields['buyer_id'], 
       'txn_id' => $fields['txn_id'], 
       'payment_gross' => $fields['mc_gross'], 
       'currency_code' => $fields['mc_currency'], 
       'payer_email' => $fields['payer_email'], 
       'plan_id' => $fields['item_number'], 
       'payment_status' => $fields['payment_status'] 
      ); 

      $this->subscription->create_payment($data); 
     $this->load->library('email'); 
     $this->email->to('*******@gmail.com'); 
     $this->email->from('**************'); 
     $this->email->subject('PayPal IPN'); 
     $this->email->message($this->paypal->result."\nAmount: ".$fields['mc_gross']."\nCurrency: ".$fields['mc_currency']."\nUser ID: ".$fields['buyer_id']); 
     $this->email->send(); 
     } 
    } 

lub jeśli masz zatrzymany scenariusz w przypadku if udało

if($this->paypal->verified){ 

      $data = array(
       'user_id' => $fields['buyer_id'], 
       'txn_id' => $fields['txn_id'], 
       'payment_gross' => $fields['mc_gross'], 
       'currency_code' => $fields['mc_currency'], 
       'payer_email' => $fields['payer_email'], 
       'plan_id' => $fields['item_number'], 
       'payment_status' => $fields['payment_status'] 
      ); 

      $this->subscription->create_payment($data); 
} else { 
exit("We are sad to inform you that verification FAILED. Bye!"); 
} 

nie otrzyma żadnego e-maila . Problem jest w public function run() w Twojej klasie paypal i jest to najprawdopodobniej wadliwa część.

 if (!($res = curl_exec($ch))) { 
      curl_close($ch); 
      die('curl did not work<br>'.FCPATH.'cacert.pem'); 
     } 
     curl_close($ch); 
     if (strcmp ($res, "VERIFIED") == 0) { 
      $this->verified = true;     
     } 

Spróbuj ponownie pisząc go jak ten

 $res=curl_exec($ch); // define $res 
     if($res==null){ // check if $res is null 
      exit('curl did not work<br>'.FCPATH.'cacert.pem'); 
     } 
     curl_close($ch); 
     if (strcmp ($res, "VERIFIED") === 0) { 
      $this->verified = true;     
     } 

Odnośnie ostatnich 3 linie gdzie strcmp() jest używany, a opartych na użytkownika comment w strcmp() dokumentacji.

  • strcmp() powróci NULL awarii.
  • Ma to efekt uboczny równości z dopasowaniem przy użyciu porównania równości (==).
  • Zamiast tego możesz chcieć przetestować dopasowanie przy użyciu identycznego porównania (===), które nie powinno wychwycić zwrotu NULL.

Co oznacza powyższe? W małym przykładzie.

if(null==0) { 
echo "1"; 
} 
if(null===0) { 
echo "2"; 
} 

Powyższy przykład tylko wyjście => 1 który w danym przypadku oznacza to, że jeśli nie będzie strcmp() ustawieniu verified do true która nie jest poprawna.