GatewayMerchantID=$GatewayMerchantID; $this->GatewayPassword=$GatewayPassword; $this->GatewaySignature=$GatewaySignature; } /** * Processes a direct credit card payment. Returns true on successful payment, otherwise false. * @return bool */ public function ProcessTransaction() { try { $aErrors=array(); //clear the request and response fields $this->ClearLog(); //validate the credit card expiration date $iExpirationTime=mktime(0,0,0,$this->ExpirationMonth,1,$this->ExpirationYear); if($iExpirationTime==-1) { throw new Exception("The expiration date is invalid."); } elseif($iExpirationTimeCardNumber)) $sCardType="Visa"; //All Visa card numbers start with a 4. New cards have 16 digits. Old cards have 13. elseif(preg_match("/^5[1-5][0-9]{14}$/",$this->CardNumber)) $sCardType="MasterCard"; // All MasterCard numbers start with the numbers 51 through 55. All have 16 digits. elseif(preg_match("/^3[47][0-9]{13}$/",$this->CardNumber)) $sCardType="Amex"; // American Express card numbers start with 34 or 37 and have 15 digits. elseif(preg_match("/^6(?:011|5[0-9]{2})[0-9]{12}$/",$this->CardNumber)) $sCardType="Discover"; //Discover card numbers begin with 6011 or 65. All have 16 digits. else throw new Exception("The credit card number is not valid."); //validate other fields if(!$this->Amount) $aErrors[]="The amount to charge is required."; elseif($this->Amount<.5) $aErrors[]="The amount to charge is required."; if(!$this->GatewayMerchantID) $aErrors[]="The GatewayMerchantID is required."; if(!$this->GatewayPassword) $aErrors[]="The GatewayPassword is required."; if(!$this->CardNumber) $aErrors[]="The credit card number is required."; if(!$this->SecurityCode) $aErrors[]="The security code is required."; if(!$this->FirstName) $aErrors[]="The first name is required."; if(!$this->LastName) $aErrors[]="The last name is required."; if(!$this->Address) $aErrors[]="The address is required."; if(!$this->City) $aErrors[]="The city is required."; if(!$this->State) $aErrors[]="The state is required."; if(!$this->Zip) $aErrors[]="The zip code is required."; if(count($aErrors)>0) throw new Exception(implode(", ",$aErrors)); //sanitize the credit card number $this->CardNumber=preg_replace("/[^0-9]/","",$this->CardNumber); $aFields=array(); //transaction method $aFields["METHOD"]="DoDirectPayment"; //information specific to this transaction $aFields["AMT"]=$this->Amount; $aFields["CURRENCYCODE"]=$this->CurrencyCode; $aFields["PAYMENTACTION"]="Sale"; $aFields["CREDITCARDTYPE"]=$sCardType; $aFields["ACCT"]=$this->CardNumber; $aFields["EXPDATE"]=date("mY",$iExpirationTime); $aFields["CVV2"]=$this->SecurityCode; $aFields["FIRSTNAME"]=$this->FirstName; $aFields["LASTNAME"]=$this->LastName; $aFields["STREET"]=$this->Address; $aFields["CITY"]=$this->City; $aFields["STATE"]=$this->State; $aFields["COUNTRYCODE"]=$this->Country; $aFields["ZIP"]=preg_replace("/[^0-9A-Za-z]/","",$this->Zip); $aFields["IPADDRESS"]=$_SERVER['REMOTE_ADDR']; $aFields["SHIPPINGAMT"]=$this->Shipping; $aFields["TAXAMT"]=$this->Tax; if($this->Description) $aFields["DESC"]=$this->Description; if($this->Custom) $aFields["CUSTOM"]=$this->Custom; $aFields["INVNUM"]=$this->InvoiceNumber; if($this->IPN) $aFields["NOTIFYURL"]=$this->IPN; $aFields["ITEMAMT"]=$this->SubTotal; //submit the request to PayPal $this->SubmitRequest($aFields); //break the response into an associative array $aResponseParts=explode("&",$this->LastResponse); $aReturn=array(); if(count($aResponseParts)>0) { foreach($aResponseParts as $sResponsePart) { list($sKey,$sValue)=explode("=",$sResponsePart,2); $aReturn[urldecode($sKey)]=urldecode($sValue); } } else throw new Exception("An invalid response was returned."); $sResult = strtoupper($aReturn["ACK"]); if($sResult=="SUCCESS" || $sResult=="SUCCESSWITHWARNING") { $this->TransactionID=$aReturn["TRANSACTIONID"]; return true; } else { $this->ResponseReason=$aReturn["L_LONGMESSAGE0"]; return false; } } catch(Exception $e) { $this->LastError=$e->getMessage(); $this->ResponseReason=$this->LastError; return false; } return false; } /** * Completes a previously begun Express Checkout transaction. Returns true on success, false on failure. * @return bool */ public function CompleteExpressCheckout() { try { //clear the request and response fields $this->ClearLog(); $aFields["METHOD"]="DoExpressCheckoutPayment"; $aFields["TOKEN"]=$this->Token; $aFields["PAYERID"]=$this->PayerID; $aFields["PAYMENTREQUEST_0_PAYMENTACTION"]="Sale"; $aFields["PAYMENTREQUEST_0_AMT"]=$this->Amount; $aFields["PAYMENTREQUEST_0_CURRENCYCODE"]=$this->CurrencyCode; $aFields["IPADDRESS"]=$_SERVER['REMOTE_ADDR']; if(isset($this->SubTotal)) $aFields["PAYMENTREQUEST_0_ITEMAMT"]=$this->SubTotal; if(isset($this->Shipping)) $aFields["PAYMENTREQUEST_0_SHIPPINGAMT"]=$this->Shipping; if(isset($this->Tax)) $aFields["PAYMENTREQUEST_0_TAXAMT"]=$this->Tax; $aFields["PAYMENTREQUEST_0_DESC"]=$this->Description; if(isset($this->InvoiceNumber)) $aFields["PAYMENTREQUEST_0_INVNUM"]=$this->InvoiceNumber; if(isset($this->IPN)) $aFields["PAYMENTREQUEST_0_NOTIFYURL"]=$this->IPN; if(isset($this->Custom)) $aFields["PAYMENTREQUEST_0_CUSTOM"]=$this->Custom; //submit the request to PayPal $this->SubmitRequest($aFields); //break the response into an associative array $aResponseParts=explode("&",$this->LastResponse); $aReturn=array(); if(count($aResponseParts)>0) { foreach($aResponseParts as $sResponsePart) { list($sKey,$sValue)=explode("=",$sResponsePart,2); $aReturn[urldecode($sKey)]=urldecode($sValue); } } else throw new Exception("An invalid response was returned."); $sResult = strtoupper($aReturn["ACK"]); if($sResult=="SUCCESS" || $sResult=="SUCCESSWITHWARNING") { if($aResult["PAYMENTINFO_0_PAYMENTSTATUS"]=="Completed") { $this->TransactionID=$aResult["PAYMENTINFO_0_TRANSACTIONID"]; return true; } else { if($aReturn["PAYMENTINFO_0_PENDINGREASON"]=="address") $sReason="The payment is pending because your customer did not include a confirmed shipping address and your Payment Receiving Preferences is set such that you want to manually accept or deny each of these payments. To change your preference, go to the Preferences section of your Profile. "; elseif($aReturn["PAYMENTINFO_0_PENDINGREASON"]=="echeck") $sReason="The payment is pending because it was made by an eCheck that has not yet cleared. "; elseif($aReturn["PAYMENTINFO_0_PENDINGREASON"]=="intl") $sReason="The payment is pending because you hold a non-U.S. account and do not have a withdrawal mechanism. You must manually accept or deny this payment from your Account Overview. "; elseif($aReturn["PAYMENTINFO_0_PENDINGREASON"]=="multi-currency") $sReason="You do not have a balance in the currency sent, and you do not have your Payment Receiving Preferences set to automatically convert and accept this payment. You must manually accept or deny this payment. "; elseif($aReturn["PAYMENTINFO_0_PENDINGREASON"]=="verify") $sReason="The payment is pending because you are not yet verified. You must verify your account before you can accept this payment. "; else $sReason="The payment is pending for an unknown reason. For more information, contact PayPal customer service."; $sMessage='The order was submitted, but payment has not yet been completed. You will be notified once payment has been completed. '.$sReason; throw new Exception($sMessage); } } else { $this->ResponseReason=$aReturn["L_LONGMESSAGE0"]; return false; } } catch(Exception $e) { $this->LastError=$e->getMessage(); $this->ResponseReason=$this->LastError; return false; } } /** * Retrieves information from PayPal regarding the current express checkout user's account. Returns true on success, false on failure. * @param string The Token received from PayPal. The Token is originally generated by the SetExpressCheckout method, but is sent back in a GET variable from PayPal upon return. Returns true on success, otherwise false. * @return bool */ public function GetExpressCheckoutDetails($Token) { try { //clear the request and response fields $this->ClearLog(); $aFields["METHOD"]="GetExpressCheckoutDetails"; $aFields["TOKEN"]=$Token; //submit the request to PayPal $this->SubmitRequest($aFields); //break the response into an associative array $aResponseParts=explode("&",$this->LastResponse); $aReturn=array(); if(count($aResponseParts)>0) { foreach($aResponseParts as $sResponsePart) { list($sKey,$sValue)=explode("=",$sResponsePart,2); $aReturn[urldecode($sKey)]=urldecode($sValue); } } else throw new Exception("An invalid response was returned."); $sResult = strtoupper($aReturn["ACK"]); if($sResult=="SUCCESS" || $sResult=="SUCCESSWITHWARNING") { $this->Email=$aReturn["EMAIL"]; $this->FirstName=$aReturn["FIRSTNAME"]; $this->LastName=$aReturn["LASTNAME"]; $this->Country=$aReturn["COUNTRYCODE"]; $this->Address=$aReturn["SHIPTOSTREET"]; $this->City=$aReturn["SHIPTOCITY"]; $this->State=$aReturn["SHIPTOSTATE"]; $this->Zip=$aReturn["SHIPTOZIP"]; $this->PayerID=$aReturn["PAYERID"]; $this->Custom=$aReturn["CUSTOM"]; $this->Note=$aReturn["PAYMENTREQUEST_0_NOTETEXT"]; return true; } else { $this->ResponseReason=$aReturn["L_LONGMESSAGE0"]; return false; } } catch(Exception $e) { $this->LastError=$e->getMessage(); $this->ResponseReason=$this->LastError; return false; } } /** * Notifies PayPal to begin an Express checkout, and generates the token. Returns true on successful payment, otherwise false. * @return bool */ public function SetExpressCheckout() { try { $aErrors=array(); //clear the request and response fields $this->ClearLog(); if(count($aErrors)>0) throw new Exception(implode(", ",$aErrors)); $aFields=array(); $aFields["METHOD"]="SetExpressCheckout"; //information specific to this transaction $aFields["PAYMENTREQUEST_0_AMT"]=$this->Amount; $aFields["PAYMENTREQUEST_0_CURRENCYCODE"]=$this->CurrencyCode; $aFields["PAYMENTREQUEST_0_PAYMENTACTION"]="Sale"; $aFields["RETURNURL"]=$this->ReturnURL; $aFields["CANCELURL"]=$this->CancelURL; $aFields["NOSHIPPING"]=($this->ShowShipping?0:1); if(isset($this->LastName)) $aFields["PAYMENTREQUEST_0_SHIPTONAME"]=trim($this->FirstName." ".$this->LastName); if(isset($this->Address)) $aFields["PAYMENTREQUEST_0_SHIPTOSTREET"]=$this->Address; if(isset($this->City)) $aFields["PAYMENTREQUEST_0_SHIPTOCITY"]=$this->City; if(isset($this->State)) $aFields["PAYMENTREQUEST_0_SHIPTOSTATE"]=$this->State; if(isset($this->Zip)) $aFields["PAYMENTREQUEST_0_SHIPTOZIP"]=$this->Zip; if(isset($this->Country)) $aFields["PAYMENTREQUEST_0_SHIPTOCOUNTRYCODE"]=$this->Country; if(isset($this->Email)) $aFields["EMAIL"]=$this->Email; if(isset($this->SubTotal)) $aFields["PAYMENTREQUEST_0_ITEMAMT"]=$this->SubTotal; if(isset($this->Shipping)) $aFields["PAYMENTREQUEST_0_SHIPPINGAMT"]=$this->Shipping; if(isset($this->Tax)) $aFields["PAYMENTREQUEST_0_TAXAMT"]=$this->Tax; if(isset($this->Description)) $aFields["PAYMENTREQUEST_0_DESC"]=$this->Description; if(isset($this->Custom)) $aFields["PAYMENTREQUEST_0_CUSTOM"]=$this->Custom; if(isset($this->InvoiceNumber)) $aFields["PAYMENTREQUEST_0_INVNUM"]=$this->InvoiceNumber; if(isset($this->IPN)) $aFields["PAYMENTREQUEST_0_NOTIFYURL"]=$this->IPN; //submit the request to PayPal $this->SubmitRequest($aFields); //break the response into an associative array $aResponseParts=explode("&",$this->LastResponse); $aReturn=array(); if(count($aResponseParts)>0) { foreach($aResponseParts as $sResponsePart) { list($sKey,$sValue)=explode("=",$sResponsePart,2); $aReturn[urldecode($sKey)]=urldecode($sValue); } } else throw new Exception("An invalid response was returned."); $sResult = strtoupper($aReturn["ACK"]); if($sResult=="SUCCESS" || $sResult=="SUCCESSWITHWARNING") { $this->Token=$aReturn["TOKEN"]; return true; } else { $this->ResponseReason=$aReturn["L_LONGMESSAGE0"]; return false; } } catch(Exception $e) { $this->LastError=$e->getMessage(); $this->ResponseReason=$this->LastError; return false; } return false; } /********************************* Private Methods **********************************************/ /* @access private */ private function ClearLog() { $this->LastRequest=""; $this->LastResponse=""; $this->LastError=""; } /* @access private */ private function SubmitRequest($aFields) { //authentication information $aFields["VERSION"]="65"; $aFields["PWD"]=$this->GatewayPassword; $aFields["USER"]=$this->GatewayMerchantID; $aFields["SIGNATURE"]=$this->GatewaySignature; //encode the values to ensure they are passed properly foreach($aFields as $key => $value) if(($key=="CANCELURL") || ($key=="RETURNURL")) $aFields[$key]=urlencode($key)."=".$value; else $aFields[$key]=urlencode($key)."=".urlencode($value); //initialize CURL and set the options $oCURL = curl_init(); $sURL=(true==$this->Test?$this->sTestAPIEndpoint:$this->sProductionAPIEndpoint); curl_setopt($oCURL, CURLOPT_URL,$sURL); curl_setopt($oCURL, CURLOPT_VERBOSE, 1); curl_setopt($oCURL, CURLOPT_RETURNTRANSFER,1); curl_setopt($oCURL, CURLOPT_POST, 1); //turning off the server and peer verification curl_setopt($oCURL, CURLOPT_SSL_VERIFYPEER, FALSE); curl_setopt($oCURL, CURLOPT_SSL_VERIFYHOST, FALSE); //setting the nvpreq as POST FIELD to curl $this->LastRequest=implode("&",$aFields); curl_setopt($oCURL, CURLOPT_POSTFIELDS, $this->LastRequest); //getting response from server $sResponse = curl_exec($oCURL); if (curl_errno($oCURL)) { throw new Exception("An error ocurred while communicating with PayPal."); } else { //Close the CURL handle. curl_close($oCurl); } $this->LastResponse=$sResponse; } } ?>