/** * 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; }
/** * 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; }
public function PerformConfirmation($request, $response) { // // Verify that we have a transaction ID for the confirmation // message. // $confirmGUID = $response->Get(GatewayResponse::TRANSACT_ID()); if ($confirmGUID == NULL) { // Don't have reference? $response->Set(GatewayResponse::EXCEPTION(), "BUG-CHECK - Missing confirmation GUID"); $response->SetResults(GatewayCodes__RESPONSE_SYSTEM_ERROR, GatewayCodes__REASON_BUGCHECK); return FALSE; // Transaction failed } // // Add the GUID to the request and send it back to the // original server for confirmation. // $confirmResponse = new GatewayResponse(); // Need a new response object $request->Set(GatewayRequest::TRANSACTION_TYPE(), "CC_CONFIRM"); $request->Set(GatewayRequest::REFERENCE_GUID(), $confirmGUID); if ($this->PerformTargetedTransaction($request, $confirmResponse)) { return TRUE; } ////////////////////////////////////////////////////////////////////// // // 12-21-2011 darcy // // If we experienced a system error, retry the confirmation. // if ($confirmResponse->Get(GatewayResponse::RESPONSE_CODE()) == GatewayCodes__RESPONSE_SYSTEM_ERROR) { sleep(2); // Short delay if ($this->PerformTargetedTransaction($request, $confirmResponse)) { return TRUE; } } // ////////////////////////////////////////////////////////////////////// // // If the confirmation failed, copy the reason and response code // into the original response object to override the success. // $response->SetResults($confirmResponse->Get(GatewayResponse::RESPONSE_CODE()), $confirmResponse->Get(GatewayResponse::REASON_CODE())); $response->Set(GatewayResponse::EXCEPTION(), $confirmResponse->Get(GatewayResponse::EXCEPTION())); return FALSE; // And quit }
$transaction_types = array('P' => 'AUTH_CAPTURE', 'A' => 'AUTH_ONLY', 'C' => 'CAPTURE_ONLY', 'R' => 'CREDIT', 'I' => 'PRIOR_AUTH_CAPTURE'); $trans_type = $processor_data['processor_params']['transaction_type']; $__version = '3.1'; $post = array(); if ($trans_type == 'R') { $post['x_trans_id'] = $order_info['payment_info']['transaction_id']; } $processor_error = array(); $processor_error['avs'] = array('A' => 'Address (Street) matches, ZIP does not', 'B' => 'Address information not provided for AVS check', 'D' => 'Exact AVS Match', 'E' => 'AVS error', 'F' => 'Exact AVS Match', 'G' => 'Service not supported by issuer', 'M' => 'Address (Street) matches', 'N' => 'No Match on Address (Street) or ZIP', 'P' => 'ZIP/Postal code matches, Address (Street) does not', 'R' => 'Retry. System unavailable or timed out', 'S' => 'Service not supported by issuer', 'U' => 'Address information is unavailable', 'W' => '9 digit ZIP matches, Address (Street) does not', 'X' => 'Exact AVS Match', 'Y' => 'Address (Street) and 5 digit ZIP match', 'Z' => '5 digit ZIP matches, Address (Street) does not', '1' => 'Exact AVS Match', '2' => 'Exact AVS Match', '3' => 'Address (Street) matches, ZIP does not'); $processor_error['cvv'] = array('M' => 'Match', 'N' => 'CVV2 code: No Match', 'P' => 'CVV2 code: Not Processed', 'S' => 'CVV2 code: Should have been present', 'U' => 'CVV2 code: Issuer unable to process request'); $processor_error['cavv'] = array('0' => 'CAVV not validated because erroneous data was submitted', '1' => 'CAVV failed validation', '2' => 'CAVV passed validation', '3' => 'CAVV validation could not be performed; issuer attempt incomplete', '4' => 'CAVV validation could not be performed; issuer system error', '7' => 'CAVV attempt - failed validation - issuer available (US issued card/non-US acquirer)', '8' => 'CAVV attempt - passed validation - issuer available (US issued card/non-US acquirer)', '9' => 'CAVV attempt - failed validation - issuer unavailable (US issued card/non-US acquirer)', 'A' => 'CAVV attempt - passed validation - issuer unavailable (US issued card/non-US acquirer)', 'B' => 'CAVV passed validation, information only, no liability shift'); $processor_error['order_status'] = array('1' => 'P', '2' => 'D', '3' => 'F', '4' => 'O'); $tran_error = array('0' => "Transaction Successful", '100' => 'No matching transaction', '101' => 'A void operation cannot be performed because the original transaction has already been voided, credited, or settled.', '102' => 'A credit operation cannot be performed because the original transaction has already been voided, credited, or has not been settled.', '103' => 'A ticket operation cannot be performed because the original auth-only transaction has been voided or ticketed.', '104' => 'The bank has declined the transaction.', '105' => 'The bank has declined the transaction because the account is over limit.', '106' => 'The transaction was declined because the security code (CVV) supplied was invalid.', '107' => 'The bank has declined the transaction because the card is expired.', '108' => 'The bank has declined the transaction and has requested that the merchant call.', '109' => 'The bank has declined the transaction and has requested that the merchant pickup the card.', '110' => 'The bank has declined the transaction due to excessive use of the card.', '111' => 'The bank has indicated that the account is invalid.', '112' => 'The bank has indicated that the account is expired.', '113' => 'The issuing bank is temporarily unavailable. May be tried again later.', '117' => 'The transaction was declined because the address could not be verified.', '150' => 'The transaction was declined because the address could not be verified.', '151' => 'The transaction was declined because the security code (CVV) supplied was invalid.', '152' => 'The TICKET request was for an invalid amount. Please verify the TICKET for less then the AUTH_ONLY.', '200' => 'Transaction was declined', '201' => 'Transaction was declined', '300' => 'A DNS failure has prevented the merchant application from resolving gateway host names.', '301' => 'The merchant application is unable to connect to an appropriate host.', '303' => 'A timeout occurred while waiting for a transaction response from the gateway servers.', '305' => 'Service Unavailable', '307' => 'Unexpected/Internal Error', '311' => 'Bank Communications Error', '312' => 'Bank Communications Error', '313' => 'Bank Communications Error', '314' => 'Bank Communications Error', '315' => 'Bank Communications Error', '400' => 'Invalid XML', '402' => 'Invalid Transaction', '403' => 'Invalid Card Number', '404' => 'Invalid Expiration', '405' => 'Invalid Amount', '406' => 'Invalid Merchant ID', '407' => 'Invalid Merchant Account', '408' => 'The merchant account specified in the request is not setup to accept the card type included in the request.', '409' => 'No Suitable Account', '410' => 'Invalid Transact ID', '411' => 'Invalid Access Code', '412' => 'Invalid Customer Data Length', '413' => 'Invalid External Data Length', '418' => 'Invalid Currency', '419' => 'Incompatible Currency', '420' => 'Invalid Rebill Arguments', '421' => 'Invalid Phone', '436' => 'Incompatible Descriptors', '438' => 'Invalid Site ID', '443' => 'Transaction Declined, Invalid Request. Please contact support', '444' => 'Transaction Declined, Invalid Request. Please contact support', '445' => 'Transaction Declined, Invalid Request. Please contact support', '446' => 'Transaction Declined, Invalid Request. Please contact support'); $invoice_no = $processor_data['processor_params']['order_prefix'] . ($order_info['repaid'] ? $order_id . '_' . $order_info['repaid'] : $order_id); require_once 'rocketgate_files/GatewayService.php'; $request = new GatewayRequest(); $response = new GatewayResponse(); $service = new GatewayService(); $request->Set(GatewayRequest::MERCHANT_ID(), $processor_data['processor_params']['login']); $request->Set(GatewayRequest::MERCHANT_PASSWORD(), $processor_data['processor_params']['transaction_key']); $request->Set(GatewayRequest::MERCHANT_CUSTOMER_ID(), Tygh::$app['session']['auth']['user_id']); $request->Set(GatewayRequest::MERCHANT_INVOICE_ID(), $invoice_no); // BEGIN Risk Management $request->Set(GatewayRequest::SCRUB(), $processor_data['processor_params']['scrubmode']); $request->Set(GatewayRequest::CVV2_CHECK(), 'true'); $request->Set(GatewayRequest::AVS_CHECK(), $processor_data['processor_params']['avsmode']); // END Risk Management // Pass requested payment info. $request->Set(GatewayRequest::CARDNO(), $order_info['payment_info']['card_number']); $request->Set(GatewayRequest::EXPIRE_MONTH(), $order_info['payment_info']['expiry_month']); $request->Set(GatewayRequest::EXPIRE_YEAR(), $order_info['payment_info']['expiry_year']);
public static function TRANSACT_ID() { return GatewayRequest::REFERENCE_GUID(); }