Advertisement
DEATHMETALGORE

Untitled

Sep 21st, 2013
122
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
PHP 10.24 KB | None | 0 0
  1. /**
  2. * PayPal IPN Listener
  3. *
  4. * A class to listen for and handle Instant Payment Notifications (IPN) from
  5. * the PayPal server.
  6. *
  7. * https://github.com/Quixotix/PHP-PayPal-IPN
  8. *
  9. * @package    PHP-PayPal-IPN
  10. * @author     Micah Carrick
  11. * @copyright  (c) 2011 - Micah Carrick
  12. * @version    2.0.5
  13. * @license    http://opensource.org/licenses/gpl-license.php
  14. *
  15. * This library is originally licensed under GPL v3, but I received
  16. * permission from the author to use it under GPL v2.
  17. */
  18. class ipn_handler
  19. {
  20.     /**
  21.      *  If true, the recommended cURL PHP library is used to send the post back
  22.      *  to PayPal. If flase then fsockopen() is used. Default true.
  23.      *
  24.      *  @var boolean
  25.      */
  26.     public $use_curl = true;    
  27.    
  28.     /**
  29.      *  If true, explicitly sets cURL to use SSL version 3. Use this if cURL
  30.      *  is compiled with GnuTLS SSL.
  31.      *
  32.      *  @var boolean
  33.      */
  34.     public $force_ssl_v3 = true;    
  35.    
  36.     /**
  37.      *  If true, cURL will use the CURLOPT_FOLLOWLOCATION to follow any
  38.      *  "Location: ..." headers in the response.
  39.      *
  40.      *  @var boolean
  41.      */
  42.     public $follow_location = false;    
  43.    
  44.     /**
  45.      *  If true, an SSL secure connection (port 443) is used for the post back
  46.      *  as recommended by PayPal. If false, a standard HTTP (port 80) connection
  47.      *  is used. Default true.
  48.      *
  49.      *  @var boolean
  50.      */
  51.     public $use_ssl = true;      
  52.    
  53.     /**
  54.      *  If true, the paypal sandbox URI www.sandbox.paypal.com is used for the
  55.      *  post back. If false, the live URI www.paypal.com is used. Default false.
  56.      *
  57.      *  @var boolean
  58.      */
  59.     public $use_sandbox = false;
  60.    
  61.     /**
  62.      *  The amount of time, in seconds, to wait for the PayPal server to respond
  63.      *  before timing out. Default 30 seconds.
  64.      *
  65.      *  @var int
  66.      */
  67.     public $timeout = 60;      
  68.    
  69.     private $post_data = array();
  70.     private $post_uri = '';    
  71.     private $response_status = '';
  72.     private $response = '';
  73.  
  74.     const PAYPAL_HOST = 'www.paypal.com';
  75.     const SANDBOX_HOST = 'www.sandbox.paypal.com';
  76.    
  77.     /**
  78.      *  Post Back Using cURL
  79.      *
  80.      *  Sends the post back to PayPal using the cURL library. Called by
  81.      *  the processIpn() method if the use_curl property is true. Throws an
  82.      *  exception if the post fails. Populates the response, response_status,
  83.      *  and post_uri properties on success.
  84.      *
  85.      *  @param  string  The post data as a URL encoded string
  86.      */
  87.     protected function curlPost($encoded_data)
  88.     {
  89.         global $user;
  90.        
  91.         if ($this->use_ssl)
  92.         {
  93.             $uri = 'https://' . $this->getPaypalHost() . '/cgi-bin/webscr';
  94.             $this->post_uri = $uri;
  95.         }
  96.         else
  97.         {
  98.             $uri = 'http://' . $this->getPaypalHost() . '/cgi-bin/webscr';
  99.             $this->post_uri = $uri;
  100.         }
  101.        
  102.         $ch = curl_init();
  103.        
  104.         curl_setopt($ch, CURLOPT_URL, $uri);
  105.         curl_setopt($ch, CURLOPT_POST, true);
  106.         curl_setopt($ch, CURLOPT_POSTFIELDS, $encoded_data);
  107.         curl_setopt($ch, CURLOPT_FOLLOWLOCATION, $this->follow_location);
  108.         curl_setopt($ch, CURLOPT_TIMEOUT, $this->timeout);
  109.         curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
  110.         curl_setopt($ch, CURLOPT_HEADER, true);
  111.        
  112.         if ($this->force_ssl_v3)
  113.         {
  114.             curl_setopt($ch, CURLOPT_SSLVERSION, 3);
  115.         }
  116.        
  117.         $this->response = curl_exec($ch);
  118.         $this->response_status = strval(curl_getinfo($ch, CURLINFO_HTTP_CODE));
  119.        
  120.         if ($this->response === false || $this->response_status == '0')
  121.         {
  122.             $errno = curl_errno($ch);
  123.             $errstr = curl_error($ch);
  124.             throw new Exception($user->lang['CURL_ERROR'] . "[$errno] $errstr");
  125.         }
  126.     }
  127.    
  128.     /**
  129.      *  Post Back Using fsockopen()
  130.      *
  131.      *  Sends the post back to PayPal using the fsockopen() function. Called by
  132.      *  the processIpn() method if the use_curl property is false. Throws an
  133.      *  exception if the post fails. Populates the response, response_status,
  134.      *  and post_uri properties on success.
  135.      *
  136.      *  @param  string  The post data as a URL encoded string
  137.      */
  138.     protected function fsockPost($encoded_data)
  139.     {
  140.         global $user;
  141.        
  142.         if ($this->use_ssl)
  143.         {
  144.             $uri = 'ssl://' . $this->getPaypalHost();
  145.             $port = '443';
  146.             $this->post_uri = $uri . '/cgi-bin/webscr';
  147.         }
  148.         else
  149.         {
  150.             $uri = $this->getPaypalHost(); // no "http://" in call to fsockopen()
  151.             $port = '80';
  152.             $this->post_uri = 'http://' . $uri . '/cgi-bin/webscr';
  153.         }
  154.  
  155.         $fp = fsockopen($uri, $port, $errno, $errstr, $this->timeout);
  156.        
  157.         if (!$fp)
  158.         {
  159.             // fsockopen error
  160.             throw new Exception($user->lang['FSOCKOPEN_ERROR'] . "[$errno] $errstr");
  161.         }
  162.  
  163.         $header = "POST /cgi-bin/webscr HTTP/1.1\r\n";
  164.         $header .= "Content-Length: " . strlen($encoded_data) . "\r\n";
  165.         $header .= "Content-Type: application/x-www-form-urlencoded\r\n";
  166.         $header .= "Host: " . $this->getPaypalHost() . "\r\n";
  167.         $header .= "Connection: close\r\n\r\n";
  168.        
  169.         fputs($fp, $header . $encoded_data . "\r\n\r\n");
  170.        
  171.         while(!feof($fp))
  172.         {
  173.             if (empty($this->response))
  174.             {
  175.                 // extract HTTP status from first line
  176.                 $this->response .= $status = fgets($fp, 1024);
  177.                 $this->response_status = trim(substr($status, 9, 4));
  178.             }
  179.             else
  180.             {
  181.                 $this->response .= fgets($fp, 1024);
  182.             }
  183.         }
  184.        
  185.         fclose($fp);
  186.     }
  187.    
  188.     private function getPaypalHost()
  189.     {
  190.         if ($this->use_sandbox)
  191.         {
  192.             return ipn_handler::SANDBOX_HOST;
  193.         }
  194.         else
  195.         {
  196.             return ipn_handler::PAYPAL_HOST;
  197.         }
  198.     }
  199.    
  200.     /**
  201.      *  Get POST URI
  202.      *
  203.      *  Returns the URI that was used to send the post back to PayPal. This can
  204.      *  be useful for troubleshooting connection problems. The default URI
  205.      *  would be "ssl://www.sandbox.paypal.com:443/cgi-bin/webscr"
  206.      *
  207.      *  @return string
  208.      */
  209.     public function getPostUri()
  210.     {
  211.         return $this->post_uri;
  212.     }
  213.    
  214.     /**
  215.      *  Get Response
  216.      *
  217.      *  Returns the entire response from PayPal as a string including all the
  218.      *  HTTP headers.
  219.      *
  220.      *  @return string
  221.      */
  222.     public function getResponse()
  223.     {
  224.         return $this->response;
  225.     }
  226.    
  227.     /**
  228.      *  Get Response Status
  229.      *
  230.      *  Returns the HTTP response status code from PayPal. This should be "200"
  231.      *  if the post back was successful.
  232.      *
  233.      *  @return string
  234.      */
  235.     public function getResponseStatus()
  236.     {
  237.         return $this->response_status;
  238.     }
  239.    
  240.     /**
  241.      *  Get Text Report
  242.      *
  243.      *  Returns a report of the IPN transaction in plain text format. This is
  244.      *  useful in emails to order processors and system administrators. Override
  245.      *  this method in your own class to customize the report.
  246.      *
  247.      *  @return string
  248.      */
  249.     public function getTextReport()
  250.     {
  251.         $r = '';
  252.        
  253.         // date and POST url
  254.         for ($i = 0; $i < 80; $i++)
  255.         {
  256.             $r .= '-';
  257.         }
  258.        
  259.         $r .= "\n[" . date('m/d/Y g:i A') . '] - ' . $this->getPostUri();
  260.         if ($this->use_curl)
  261.         {
  262.             $r .= " (curl)\n";
  263.         }
  264.         else
  265.         {
  266.             $r .= " (fsockopen)\n";
  267.         }
  268.        
  269.         // HTTP Response
  270.         for ($i = 0; $i < 80; $i++)
  271.         {
  272.             $r .= '-';
  273.         }
  274.        
  275.         $r .= "\n{$this->getResponse()}\n";
  276.        
  277.         // POST vars
  278.         for ($i = 0; $i < 80; $i++)
  279.         {
  280.             $r .= '-';
  281.         }
  282.        
  283.         $r .= "\n";
  284.        
  285.         foreach ($this->post_data as $key => $value)
  286.         {
  287.             $r .= str_pad($key, 25) . "$value\n";
  288.         }
  289.        
  290.         $r .= "\n\n";
  291.        
  292.         return $r;
  293.     }
  294.    
  295.     /**
  296.      *  Process IPN
  297.      *
  298.      *  Handles the IPN post back to PayPal and parsing the response. Call this
  299.      *  method from your IPN listener script. Returns true if the response came
  300.      *  back as "VERIFIED", false if the response came back "INVALID", and
  301.      *  throws an exception if there is an error.
  302.      *
  303.      *  @param array
  304.      *
  305.      *  @return boolean
  306.      */    
  307.     public function processIpn($post_data = null)
  308.     {
  309.         global $user;
  310.        
  311.         $encoded_data = 'cmd=_notify-validate';
  312.        
  313.         if ($post_data === null)
  314.         {
  315.             // use raw POST data
  316.             if (!empty($_POST))
  317.             {
  318.                 $this->post_data = $_POST;
  319.                 $encoded_data .= '&' . file_get_contents('php://input');
  320.             }
  321.             else
  322.             {
  323.                 throw new Exception($user->lang['NO_POST_DATA']);
  324.             }
  325.         }
  326.         else
  327.         {
  328.             // use provided data array
  329.             $this->post_data = $post_data;
  330.            
  331.             foreach ($this->post_data as $key => $value)
  332.             {
  333.                 $encoded_data .= "&$key=" . urlencode($value);
  334.             }
  335.         }
  336.  
  337.         if ($this->use_curl)
  338.         {
  339.             $this->curlPost($encoded_data);
  340.         }
  341.         else
  342.         {
  343.             $this->fsockPost($encoded_data);
  344.         }
  345.        
  346.         if (strpos($this->response_status, '200') === false)
  347.         {
  348.             throw new Exception($user->lang['INVALID_RESPONSE'] . $this->response_status);
  349.         }
  350.        
  351.         if (strpos(trim($this->response), "VERIFIED") !== false)
  352.         {
  353.             return true;
  354.         }
  355.         elseif (trim(strpos($this->response), "INVALID") !== false)
  356.         {
  357.             return false;
  358.         }
  359.         else
  360.         {
  361.             throw new Exception($user->lang['UNEXPECTED_ERROR']);
  362.         }
  363.     }
  364.    
  365.     /**
  366.      *  Require Post Method
  367.      *
  368.      *  Throws an exception and sets a HTTP 405 response header if the request
  369.      *  method was not POST.
  370.      */    
  371.     public function requirePostMethod()
  372.     {
  373.         global $user;
  374.        
  375.         // require POST requests
  376.         if ($_SERVER['REQUEST_METHOD'] && $_SERVER['REQUEST_METHOD'] != 'POST')
  377.         {
  378.             header('Allow: POST', true, 405);
  379.             throw new Exception($user->lang['INVALID_REQUEST_METHOD']);
  380.         }
  381.     }
  382. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement