User management for the world wide web

Main Page | Alphabetical List | Class List | File List | Class Members

PayPal.php

00001 <?php
00081 class PayPal {
00082     var $log_file = FALSE;
00083 
00084     var $host = "www.paypal.com";
00085     var $port = 80;
00086     var $timeout = 45;
00087     
00088     var $debug_response = FALSE;
00089     
00090     // This is a dispatch array for the payment_status.
00091     var $STATUS = array(    Completed           => 'status_completed',
00092                             Canceled_Reversal   => 'status_cancel_reverse',
00093                             Denied              => 'status_denied',
00094                             Failed              => 'status_failed',
00095                             Pending             => 'status_pending',
00096                             Refunded            => 'status_refunded',
00097                             Reversed            => 'status_reversed'                            
00098                         );
00099 
00100     // Table lookup of codes for their meanings.
00101     var $RC_CODES = array( "Success",
00102                            "Socket or network problem",
00103                            "Email verification failed",
00104                            "txn_id is invalid or a duplicate",
00105                            "Payment amount or currency incorrect",
00106                            "Payment status not recognized",
00107                            "INVALID transaction (possible attempted forgery?)",
00108                            "Problem dealing with transaction status",
00109                            "Neither VERIFIED nor INVALID was recieved from paypal"
00110                           );
00114     function PayPal(){
00115     }
00116     
00121     function log_file($filename = FALSE){
00122         if($filename){
00123             $this->log_file = $filename;
00124         }
00125         return($this->log_file);
00126     }
00127     
00137     function logit($level,$message){
00138         if(! $this->log_file){
00139             return;
00140         }
00141         if(substr($message, -1) != "\n"){
00142                 $message .= "\n";
00143         }
00144         error_log($level . "\t" . $message,3,$this->log_file);
00145         if($level == "E"){
00146             error_log($message);
00147         }
00148     }
00162     function status_completed(){
00163         $this->logit("D","Not doing anything about status_completed");
00164         return(TRUE);
00165     }
00172     function status_pending(){
00173         $this->logit("D","Not doing anything about status_pending: " . $_POST[pending_reason]);
00174         return(TRUE);
00175     }
00180     function status_cancel_reverse(){
00181         $this->logit("D","Not doing anything about status_cancel_reverse");
00182         return(TRUE);
00183     }
00188     function status_denied(){
00189         $this->logit("D","Not doing anything about status_denied");
00190         return(TRUE);
00191     }
00196     function status_failed(){
00197         $this->logit("D","Not doing anything about status_failed");
00198         return(TRUE);
00199     }
00204     function status_refunded(){
00205         $this->logit("D","Not doing anything about status_refunded");
00206         return(TRUE);
00207     }
00212     function status_reversed(){
00213         $this->logit("D","Not doing anything about status_reversed " . $_POST[reason_code]);
00214         return(TRUE);
00215     }
00226     function debug_response($filename){
00227         $this->debug_response = $filename;
00228     }
00233     function paypal_host($timeout = 45,$host = "www.paypal.com",$port = 80){
00234         $this->host = $host;
00235         $this->port = $port;
00236         $this->timeout = $timeout;
00237     }
00238     
00245     function connect_paypal(){
00246         // Using a debug response file.
00247         if($this->debug_response){
00248             $fp = fopen($this->debug_response,"r");
00249             if(! $fp){
00250                 $this->logit("E","Error opening debug response file: $this->debug_response");
00251             }
00252             $this->logit("D","Using debug file $this->debug_response");
00253             return($fp);
00254         }
00255         $this->logit("D","Connecting to: $this->host $this->port");
00256         $fp = fsockopen($this->host, $this->port, $errno, $errstr, $this->timeout);
00257         if(! $fp){
00258             $this->logit("E","Socket error: [" . $errno . "] " . $errstr);
00259         }
00260         return($fp);
00261     }
00269     function test_form($form_tags = TRUE){
00270         if($form_tags){
00271             echo "<FORM ACTION=\"$_SERVER[PHP_SELF]\" METHOD=\"POST\">";
00272         }
00273         ?>
00274         <LI>DEBUG (for internal debug flags):<INPUT NAME="DEBUG">
00275         <LI>receiver_email:<INPUT NAME="receiver_email">
00276         <LI>item_number:<INPUT NAME="item_number">
00277         <LI>mc_gross:<INPUT NAME="mc_gross">
00278         <LI>mc_currency:<SELECT NAME="mc_currency">
00279                             <OPTION VALUE="USD">USD</OPTION>
00280                             <OPTION VALUE="CAD">CAD</OPTION>
00281                             <OPTION VALUE="GBP">GBP</OPTION>
00282                             <OPTION VALUE="EUR">EUR</OPTION>
00283                             <OPTION VALUE="JPY">JPY</OPTION>
00284                         </SELECT>
00285         <LI>txn_id<INPUT NAME="txn_id" VALUE="">
00286         <LI>parent_txn_id:<INPUT NAME="parent_txn_id">
00287         <LI>invoice:<INPUT NAME="invoice">
00288         <LI>custom:<INPUT NAME="custom">
00289         <LI>first_name:<INPUT NAME="first_name">
00290         <LI>last_name:<INPUT NAME="last_name">
00291         <LI>payer_business_name:<INPUT NAME="payer_business_name">
00292         <LI>address_street:<INPUT NAME="address_street">
00293         <LI>address_city:<INPUT NAME="address_city">
00294         <LI>address_state:<INPUT NAME="address_state">
00295         <LI>address_zip:<INPUT NAME="address_zip">
00296         <LI>address_country:<INPUT NAME="address_country">
00297         <LI>payer_email:<INPUT NAME="payer_email">
00298         <LI>payment_status:<SELECT NAME="payment_status">
00299                                 <OPTION VALUE="Canceled_Reversal">Canceled_Reversal</OPTION>
00300                                 <OPTION VALUE="Completed">Completed</OPTION>
00301                                 <OPTION VALUE="Denied">Denied</OPTION>
00302                                 <OPTION VALUE="Failed">Failed</OPTION>
00303                                 <OPTION VALUE="Pending">Pending</OPTION>
00304                                 <OPTION VALUE="Refunded">Refunded</OPTION>
00305                                 <OPTION VALUE="Reversed">Reversed</OPTION>
00306                           </SELECT>
00307         <LI><B>This variable is only set if payment_status=&quot;Pending&quot;</B>
00308         <LI>pending_reason:<SELECT NAME="pending_reason">
00309                             <OPTION VALUE="">(None)</OPTION>
00310                             <OPTION VALUE="address">address</OPTION>
00311                             <OPTION VALUE="echeck">echeck</OPTION>
00312                             <OPTION VALUE="intl">intl</OPTION>
00313                             <OPTION VALUE="multi_currency">multi_currency</OPTION>
00314                             <OPTION VALUE="unilateral">unilateral</OPTION>
00315                             <OPTION VALUE="upgrade">upgrade</OPTION>
00316                             <OPTION VALUE="verify">verify</OPTION>
00317                             <OPTION VALUE="other">other</OPTION>
00318                             </SELECT>
00319         <LI><B>This variable is only set if payment_status=&quot;Reversed&quot;</B>
00320         <LI>reason_code:<SELECT NAME="reason_code">
00321                         <OPTION VALUE="">(None)</OPTION>
00322                         <OPTION VALUE="buyer_complaint">buyer_complaint</OPTION>
00323                         <OPTION VALUE="chargeback">chargeback</OPTION>
00324                         <OPTION VALUE="guarantee">guarantee</OPTION>
00325                         <OPTION VALUE="refund">refund</OPTION>
00326                         <OPTION VALUE="other">other</OPTION>
00327                         </SELECT>       
00328                 
00329         <?php
00330         if($form_tags){
00331             echo "<INPUT TYPE=\"SUBMIT\" VALUE=\"Run Test\">";
00332             echo "</FORM>";
00333         }
00334     }
00335     
00353     function processIPN(){
00354         $this->logit("D","Processing paypal IPN");
00355         // read the post from PayPal system and add 'cmd'
00356         $req = 'cmd=_notify-validate';
00357         foreach ($_POST as $key => $value) {
00358             $this->logit("D","Variable: $key=[$value]");
00359             $value = urlencode(stripslashes($value));
00360             $req .= "&$key=$value";
00361         }
00362         // Connect with paypal.
00363         $fp = $this->connect_paypal();
00364         if(! $fp){
00365             return(-1);
00366         }
00367         // If in debug mode, don't post anything.
00368         if(! $this->debug_response){
00369             // post back to corroborate with PayPal 
00370             $header .= "POST /cgi-bin/webscr HTTP/1.0\r\n";
00371             $header .= "Content-Type: application/x-www-form-urlencoded\r\n";
00372             $header .= "Content-Length: " . strlen($req) . "\r\n\r\n";
00373             fputs ($fp, $header . $req);
00374         }
00375         $return_code = -8;
00376         $payment_status = $_POST[payment_status];
00377         $in_hdr = TRUE;
00378         while (!feof($fp)) {
00379             $res = trim(fgets ($fp, 1024));
00380 
00381             // Don't process the header.
00382             if(strlen($res) == 0){
00383                 $in_hdr = FALSE;
00384                 continue;
00385             }
00386             if($in_hdr){
00387                 continue;
00388             }
00389             
00390             $this->logit("D","Response: [" . $res . "]");
00391             if (strcmp ($res, "VERIFIED") == 0) {
00392                 $return_code = 0;
00393                 $this->logit("D","Verified");
00394                 // Make sure credit wasn't toward someone else.
00395                 if(! $this->check_email($_POST[receiver_email])){
00396                     $return_code = -2;
00397                     break;
00398                 }
00399                 // Check txn_id is OK. (not been re-used)
00400                 if(! $this->check_txn_id($_POST[txn_id])){
00401                     $return_code = -3;
00402                     break;
00403                 }
00404                 // Check that the ammount was correct for this item.
00405                 if(! $this->check_amount($_POST[item_number],$_POST[mc_gross],$_POST[mc_currency])){
00406                     $return_code = -4;
00407                     break;
00408                 }
00409                 // Determine disposition of payment_status
00410                 if($return_code == 0){
00411                     // payment_status is Completed, Pending
00412                     $method = $this->STATUS[$payment_status];
00413                     if($method){
00414                         $this->logit("D","Running: $method (from $payment_status)");
00415                         $meth_code = $this->$method();
00416                         if(! $meth_code){
00417                             $this->logit("E","Method [$method] did not return TRUE");
00418                             $return_code = -7;
00419                         }
00420                     }else{
00421                         $this->logit("E","Payment Status: $payment_status not recognized");
00422                         $return_code = -5;
00423                     }
00424                     break;
00425                 }
00426                 break;
00427             }else if (strcmp ($res, "INVALID") == 0) {
00428                 $this->logit("I","Invalid response: " . $res);
00429                 $return_code = -6;
00430                 break;
00431             }
00432         }
00433         fclose ($fp);
00434         return($return_code);
00435     }
00436 
00443     function errstr($code){
00444         $code = abs($code);
00445         return($this->RC_CODES[$code]);
00446     }
00458     function check_amount($item_no,$amount,$currency){
00459         $this->logit("D","Not doing check_amount($item_no,$amount,$currency)");
00460         return(TRUE);
00461     }
00470     function check_txn_id($id){
00471         $this->logit("D","Not doing check_txn_id($id)");
00472         return(TRUE);
00473     }
00482     function check_email($email){
00483         $this->logit("D","Not doing check_email($email)");
00484         return(TRUE);
00485     }
00486 }
00487 ?>

DoxyGen Documentation generated by DoxyGen