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
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
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
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="Pending"</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="Reversed"</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
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
00363 $fp = $this->connect_paypal();
00364 if(! $fp){
00365 return(-1);
00366 }
00367
00368 if(! $this->debug_response){
00369
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
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
00395 if(! $this->check_email($_POST[receiver_email])){
00396 $return_code = -2;
00397 break;
00398 }
00399
00400 if(! $this->check_txn_id($_POST[txn_id])){
00401 $return_code = -3;
00402 break;
00403 }
00404
00405 if(! $this->check_amount($_POST[item_number],$_POST[mc_gross],$_POST[mc_currency])){
00406 $return_code = -4;
00407 break;
00408 }
00409
00410 if($return_code == 0){
00411
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 ?>