/**
  * Get request to send to eWay.
  *
  * @param $params
  *   Form parameters - this could be altered by hook so is a reference
  *
  * @return GatewayRequest
  * @throws \CRM_Core_Exception
  */
 protected function getEwayRequest(&$params)
 {
     $eWAYRequest = new GatewayRequest();
     if ($eWAYRequest == NULL || !$eWAYRequest instanceof GatewayRequest) {
         throw new CRM_Core_Exception("Error: Unable to create eWAY Request object.");
     }
     $fullAddress = $params['street_address'] . ", " . $params['city'] . ", " . $params['state_province'] . ".";
     //----------------------------------------------------------------------------------------------------
     // We use CiviCRM's params 'invoiceID' as the unique transaction token to feed to eWAY
     // Trouble is that eWAY only accepts 16 chars for the token, while CiviCRM's invoiceID is an 32.
     // As its made from a "$invoiceID = md5(uniqid(rand(), true));" then using the first 16 chars
     // should be alright
     //----------------------------------------------------------------------------------------------------
     $uniqueTrxnNum = substr($params['invoiceID'], 0, 16);
     //----------------------------------------------------------------------------------------------------
     // OPTIONAL: If TEST Card Number force an Override of URL and CustomerID.
     // During testing CiviCRM once used the LIVE URL.
     // This code can be uncommented to override the LIVE URL that if CiviCRM does that again.
     //----------------------------------------------------------------------------------------------------
     //  if ( ( $gateway_URL == "https://www.eway.com.au/gateway_cvn/xmlpayment.asp")
     //  && ($params['credit_card_number'] == "4444333322221111" )) {
     //  $ewayCustomerID = "87654321";
     //  $gateway_URL    = "https://www.eway.com.au/gateway_cvn/xmltest/testpage.asp";
     //  }
     // 8 Chars - ewayCustomerID - Required
     $eWAYRequest->EwayCustomerID($this->_paymentProcessor['subject']);
     // 12 Chars - ewayTotalAmount (in cents) - Required
     $eWAYRequest->InvoiceAmount($this->getAmountInCents($params));
     // 50 Chars - ewayCustomerFirstName
     $eWAYRequest->PurchaserFirstName($params['first_name']);
     // 50 Chars - ewayCustomerLastName
     $eWAYRequest->PurchaserLastName($params['last_name']);
     // 50 Chars - ewayCustomerEmail
     $eWAYRequest->PurchaserEmailAddress(CRM_Utils_Array::value('email', $params));
     // 255 Chars - ewayCustomerAddress
     $eWAYRequest->PurchaserAddress($fullAddress);
     // 6 Chars - ewayCustomerPostcode
     $eWAYRequest->PurchaserPostalCode($params['postal_code']);
     // 1000 Chars - ewayCustomerInvoiceDescription
     $eWAYRequest->InvoiceDescription($params['description']);
     // 50 Chars - ewayCustomerInvoiceRef
     $eWAYRequest->InvoiceReference($params['invoiceID']);
     // 50 Chars - ewayCardHoldersName - Required
     $eWAYRequest->CardHolderName($this->getCreditCardName($params));
     // 20 Chars - ewayCardNumber  - Required
     $eWAYRequest->CardNumber($params['credit_card_number']);
     $eWAYRequest->CardExpiryMonth($this->getCreditCardExpiryMonth($params));
     // 2 Chars - ewayCardExpiryYear - Required.
     $eWAYRequest->CardExpiryYear($this->getCreditCardExpiryYear($params));
     // 4 Chars - ewayCVN - Required if CVN Gateway used
     $eWAYRequest->CVN($params['cvv2']);
     // 16 Chars - ewayTrxnNumber
     $eWAYRequest->TransactionNumber($uniqueTrxnNum);
     // 255 Chars - ewayOption1
     $eWAYRequest->EwayOption1('');
     // 255 Chars - ewayOption2
     $eWAYRequest->EwayOption2('');
     // 255 Chars - ewayOption3
     $eWAYRequest->EwayOption3('');
     $eWAYRequest->CustomerBillingCountry($params['country']);
     $eWAYRequest->CustomerIPAddress($params['ip_address']);
     // Allow further manipulation of the arguments via custom hooks ..
     CRM_Utils_Hook::alterPaymentProcessorParams($this, $params, $eWAYRequest);
     // Check for a duplicate after the hook has been called.
     if ($this->checkDupe($params['invoiceID'], CRM_Utils_Array::value('contributionID', $params))) {
         throw new CRM_Core_Exception('It appears that this transaction is a duplicate.  Have you already submitted the form once?  If so there may have been a connection problem.  Check your email for a receipts.  If you do not receive a receipt within 2 hours you can try your transaction again.  If you continue to have problems please contact the site administrator.');
     }
     return $eWAYRequest;
 }
Пример #2
0
 /**
  * Sends request and receive response from eWAY payment process.
  *
  * @param array $params
  *
  * @return array|object
  * @throws \Exception
  */
 public function doDirectPayment(&$params)
 {
     if (CRM_Utils_Array::value('is_recur', $params) == TRUE) {
         CRM_Core_Error::fatal(ts('eWAY - recurring payments not implemented'));
     }
     if (!defined('CURLOPT_SSLCERT')) {
         CRM_Core_Error::fatal(ts('eWAY - Gateway requires curl with SSL support'));
     }
     // eWAY Client ID
     $ewayCustomerID = $this->_paymentProcessor['user_name'];
     // eWAY Gateway URL
     $gateway_URL = $this->_paymentProcessor['url_site'];
     //------------------------------------
     // create eWAY gateway objects
     //------------------------------------
     $eWAYRequest = new GatewayRequest();
     if ($eWAYRequest == NULL || !$eWAYRequest instanceof GatewayRequest) {
         return self::errorExit(9001, "Error: Unable to create eWAY Request object.");
     }
     $eWAYResponse = new GatewayResponse();
     if ($eWAYResponse == NULL || !$eWAYResponse instanceof GatewayResponse) {
         return self::errorExit(9002, "Error: Unable to create eWAY Response object.");
     }
     /*
         //-------------------------------------------------------------
         // NOTE: eWAY Doesn't use the following at the moment:
         //-------------------------------------------------------------
         $creditCardType = $params['credit_card_type'];
         $currentcyID    = $params['currencyID'];
         $country        = $params['country'];
     */
     //-------------------------------------------------------------
     // Prepare some composite data from _paymentProcessor fields
     //-------------------------------------------------------------
     $fullAddress = $params['street_address'] . ", " . $params['city'] . ", " . $params['state_province'] . ".";
     $expireYear = substr($params['year'], 2, 2);
     $expireMonth = sprintf('%02d', (int) $params['month']);
     // CiviCRM V1.9 - Picks up reasonable description
     //$description = $params['amount_level'];
     // CiviCRM V2.0 - Picks up description
     $description = $params['description'];
     $txtOptions = "";
     $amountInCents = round((double) $params['amount'] * 100);
     $credit_card_name = $params['first_name'] . " ";
     if (strlen($params['middle_name']) > 0) {
         $credit_card_name .= $params['middle_name'] . " ";
     }
     $credit_card_name .= $params['last_name'];
     //----------------------------------------------------------------------------------------------------
     // We use CiviCRM's param's 'invoiceID' as the unique transaction token to feed to eWAY
     // Trouble is that eWAY only accepts 16 chars for the token, while CiviCRM's invoiceID is an 32.
     // As its made from a "$invoiceID = md5(uniqid(rand(), true));" then using the fierst 16 chars
     // should be alright
     //----------------------------------------------------------------------------------------------------
     $uniqueTrnxNum = substr($params['invoiceID'], 0, 16);
     //----------------------------------------------------------------------------------------------------
     // OPTIONAL: If TEST Card Number force an Override of URL and CutomerID.
     // During testing CiviCRM once used the LIVE URL.
     // This code can be uncommented to override the LIVE URL that if CiviCRM does that again.
     //----------------------------------------------------------------------------------------------------
     //        if ( ( $gateway_URL == "https://www.eway.com.au/gateway_cvn/xmlpayment.asp")
     //             && ( $params['credit_card_number'] == "4444333322221111" ) ) {
     //            $ewayCustomerID = "87654321";
     //            $gateway_URL    = "https://www.eway.com.au/gateway_cvn/xmltest/testpage.asp";
     //        }
     //----------------------------------------------------------------------------------------------------
     // Now set the payment details - see http://www.eway.com.au/Support/Developer/PaymentsRealTime.aspx
     //----------------------------------------------------------------------------------------------------
     // 8 Chars - ewayCustomerID                 - Required
     $eWAYRequest->EwayCustomerID($ewayCustomerID);
     // 12 Chars - ewayTotalAmount  (in cents)    - Required
     $eWAYRequest->InvoiceAmount($amountInCents);
     // 50 Chars - ewayCustomerFirstName
     $eWAYRequest->PurchaserFirstName($params['first_name']);
     // 50 Chars - ewayCustomerLastName
     $eWAYRequest->PurchaserLastName($params['last_name']);
     // 50 Chars - ewayCustomerEmail
     $eWAYRequest->PurchaserEmailAddress($params['email']);
     // 255 Chars - ewayCustomerAddress
     $eWAYRequest->PurchaserAddress($fullAddress);
     // 6 Chars - ewayCustomerPostcode
     $eWAYRequest->PurchaserPostalCode($params['postal_code']);
     // 1000 Chars - ewayCustomerInvoiceDescription
     $eWAYRequest->InvoiceDescription($description);
     // 50 Chars - ewayCustomerInvoiceRef
     $eWAYRequest->InvoiceReference($params['invoiceID']);
     // 50 Chars - ewayCardHoldersName            - Required
     $eWAYRequest->CardHolderName($credit_card_name);
     // 20 Chars - ewayCardNumber                 - Required
     $eWAYRequest->CardNumber($params['credit_card_number']);
     // 2 Chars - ewayCardExpiryMonth            - Required
     $eWAYRequest->CardExpiryMonth($expireMonth);
     // 2 Chars - ewayCardExpiryYear             - Required
     $eWAYRequest->CardExpiryYear($expireYear);
     // 4 Chars - ewayCVN                        - Required if CVN Gateway used
     $eWAYRequest->CVN($params['cvv2']);
     // 16 Chars - ewayTrxnNumber
     $eWAYRequest->TransactionNumber($uniqueTrnxNum);
     // 255 Chars - ewayOption1
     $eWAYRequest->EwayOption1($txtOptions);
     // 255 Chars - ewayOption2
     $eWAYRequest->EwayOption2($txtOptions);
     // 255 Chars - ewayOption3
     $eWAYRequest->EwayOption3($txtOptions);
     $eWAYRequest->CustomerIPAddress($params['ip_address']);
     $eWAYRequest->CustomerBillingCountry($params['country']);
     // Allow further manipulation of the arguments via custom hooks ..
     CRM_Utils_Hook::alterPaymentProcessorParams($this, $params, $eWAYRequest);
     //----------------------------------------------------------------------------------------------------
     // Check to see if we have a duplicate before we send
     //----------------------------------------------------------------------------------------------------
     if ($this->checkDupe($params['invoiceID'], CRM_Utils_Array::value('contributionID', $params))) {
         return self::errorExit(9003, 'It appears that this transaction is a duplicate.  Have you already submitted the form once?  If so there may have been a connection problem.  Check your email for a receipt from eWAY.  If you do not receive a receipt within 2 hours you can try your transaction again.  If you continue to have problems please contact the site administrator.');
     }
     //----------------------------------------------------------------------------------------------------
     // Convert to XML and send the payment information
     //----------------------------------------------------------------------------------------------------
     $requestxml = $eWAYRequest->ToXML();
     $submit = curl_init($gateway_URL);
     if (!$submit) {
         return self::errorExit(9004, 'Could not initiate connection to payment gateway');
     }
     curl_setopt($submit, CURLOPT_POST, TRUE);
     // return the result on success, FALSE on failure
     curl_setopt($submit, CURLOPT_RETURNTRANSFER, TRUE);
     curl_setopt($submit, CURLOPT_POSTFIELDS, $requestxml);
     curl_setopt($submit, CURLOPT_TIMEOUT, 36000);
     // if open_basedir or safe_mode are enabled in PHP settings CURLOPT_FOLLOWLOCATION won't work so don't apply it
     // it's not really required CRM-5841
     if (ini_get('open_basedir') == '' && ini_get('safe_mode' == 'Off')) {
         // ensures any Location headers are followed
         curl_setopt($submit, CURLOPT_FOLLOWLOCATION, 1);
     }
     // Send the data out over the wire
     //--------------------------------
     $responseData = curl_exec($submit);
     //----------------------------------------------------------------------------------------------------
     // See if we had a curl error - if so tell 'em and bail out
     //
     // NOTE: curl_error does not return a logical value (see its documentation), but
     //       a string, which is empty when there was no error.
     //----------------------------------------------------------------------------------------------------
     if (curl_errno($submit) > 0 || strlen(curl_error($submit)) > 0) {
         $errorNum = curl_errno($submit);
         $errorDesc = curl_error($submit);
         // Paranoia - in the unlikley event that 'curl' errno fails
         if ($errorNum == 0) {
             $errorNum = 9005;
         }
         // Paranoia - in the unlikley event that 'curl' error fails
         if (strlen($errorDesc) == 0) {
             $errorDesc = "Connection to eWAY payment gateway failed";
         }
         return self::errorExit($errorNum, $errorDesc);
     }
     //----------------------------------------------------------------------------------------------------
     // If null data returned - tell 'em and bail out
     //
     // NOTE: You will not necessarily get a string back, if the request failed for
     //       any reason, the return value will be the boolean false.
     //----------------------------------------------------------------------------------------------------
     if ($responseData === FALSE || strlen($responseData) == 0) {
         return self::errorExit(9006, "Error: Connection to payment gateway failed - no data returned.");
     }
     //----------------------------------------------------------------------------------------------------
     // If gateway returned no data - tell 'em and bail out
     //----------------------------------------------------------------------------------------------------
     if (empty($responseData)) {
         return self::errorExit(9007, "Error: No data returned from payment gateway.");
     }
     //----------------------------------------------------------------------------------------------------
     // Success so far - close the curl and check the data
     //----------------------------------------------------------------------------------------------------
     curl_close($submit);
     //----------------------------------------------------------------------------------------------------
     // Payment successfully sent to gateway - process the response now
     //----------------------------------------------------------------------------------------------------
     $eWAYResponse->ProcessResponse($responseData);
     //----------------------------------------------------------------------------------------------------
     // See if we got an OK result - if not tell 'em and bail out
     //----------------------------------------------------------------------------------------------------
     if (self::isError($eWAYResponse)) {
         $eWayTrxnError = $eWAYResponse->Error();
         CRM_Core_Error::debug_var('eWay Error', $eWayTrxnError, TRUE, TRUE);
         if (substr($eWayTrxnError, 0, 6) == "Error:") {
             return self::errorExit(9008, $eWayTrxnError);
         }
         $eWayErrorCode = substr($eWayTrxnError, 0, 2);
         $eWayErrorDesc = substr($eWayTrxnError, 3);
         return self::errorExit(9008, "Error: [" . $eWayErrorCode . "] - " . $eWayErrorDesc . ".");
     }
     //-----------------------------------------------------------------------------------------------------
     // Cross-Check - the unique 'TrxnReference' we sent out should match the just received 'TrxnReference'
     //
     // PLEASE NOTE: If this occurs (which is highly unlikely) its a serious error as it would mean we have
     //              received an OK status from eWAY, but their Gateway has not returned the correct unique
     //              token - ie something is broken, BUT money has been taken from the client's account,
     //              so we can't very well error-out as CiviCRM will then not process the registration.
     //              There is an error message commented out here but my preferred response to this unlikley
     //              possibility is to email '*****@*****.**'
     //-----------------------------------------------------------------------------------------------------
     $eWayTrxnReference_OUT = $eWAYRequest->GetTransactionNumber();
     $eWayTrxnReference_IN = $eWAYResponse->InvoiceReference();
     if ($eWayTrxnReference_IN != $eWayTrxnReference_OUT) {
         // return self::errorExit( 9009, "Error: Unique Trxn code was not returned by eWAY Gateway. This is extremely unusual! Please contact the administrator of this site immediately with details of this transaction.");
     }
     /*
         //----------------------------------------------------------------------------------------------------
         // Test mode always returns trxn_id = 0 - so we fix that here
         //
         // NOTE: This code was taken from the AuthorizeNet payment processor, however it now appears
         //       unnecessary for the eWAY gateway - Left here in case it proves useful
         //----------------------------------------------------------------------------------------------------
         if ( $this->_mode == 'test' ) {
         $query             = "SELECT MAX(trxn_id) FROM civicrm_contribution WHERE trxn_id LIKE 'test%'";
         $p                 = array( );
         $trxn_id           = strval( CRM_Core_Dao::singleValueQuery( $query, $p ) );
         $trxn_id           = str_replace( 'test', '', $trxn_id );
         $trxn_id           = intval($trxn_id) + 1;
         $params['trxn_id'] = sprintf('test%08d', $trxn_id);
         }
         else {
         $params['trxn_id'] = $eWAYResponse->TransactionNumber();
         }
     */
     //=============
     // Success !
     //=============
     $beaglestatus = $eWAYResponse->BeagleScore();
     if (!empty($beaglestatus)) {
         $beaglestatus = ": " . $beaglestatus;
     }
     $params['trxn_result_code'] = $eWAYResponse->Status() . $beaglestatus;
     $params['gross_amount'] = $eWAYResponse->Amount();
     $params['trxn_id'] = $eWAYResponse->TransactionNumber();
     return $params;
 }