_paymentProcessor = $paymentProcessor; $this->_processorName = ts('IATS'); // get merchant data from config $config = CRM_Core_Config::singleton(); // live or test $this->_profile['mode'] = $mode; $this->_profile['webserver'] = parse_url($this->_paymentProcessor['url_site'], PHP_URL_HOST); $currencyID = $config->defaultCurrency; if (!in_array($currencyID, explode(',', self::CURRENCIES))) { // Configuration error: default currency must be in CURRENCIES const return self::error('Invalid configuration:' . $currencyID . ', you must use one of ' . self::CURRENCIES . ' with IATS'); } } static function &singleton($mode, &$paymentProcessor) { $processorName = $paymentProcessor['name']; if (self::$_singleton[$processorName] === NULL) { self::$_singleton[$processorName] = new CRM_Core_Payment_IATS($mode, $paymentProcessor); } return self::$_singleton[$processorName]; } function doDirectPayment(&$params) { // $result = ''; // foreach($params as $key => $value) { // $result .= "$key: $value
"; // } // return self::error($result); // make sure i've been called correctly ... if (!$this->_profile) { return self::error('Unexpected error, missing profile'); } if (!in_array($params['currencyID'], explode(',', self::CURRENCIES))) { return self::error('Invalid currency selection, must be one of ' . self::CURRENCIES); } $isRecur = CRM_Utils_Array::value('is_recur', $params, FALSE); // AgentCode = $this->_paymentProcessor['signature']; // Password = $this->_paymentProcessor['password' ]; // beginning of modified sample code from IATS php api include IATS supplied api library if ($isRecur) { include_once ('Services/IATS/iats_reoccur.php'); $iatslink1 = new iatslinkReoccur; } else { include_once ('Services/IATS/iatslink.php'); $iatslink1 = new iatslink; } $iatslink1->setTestMode($this->_profile['mode'] != 'live'); $iatslink1->setWebServer($this->_profile['webserver']); // return self::error($this->_profile['webserver']); // Put your invoice here $iatslink1->setInvoiceNumber($params['invoiceID']); // $iatslink1->setCardType("VISA"); // If CardType is not set, iatslink will find the cardType // CardType not set because IATS uses different names! // $iatslink1->setCardType($params['credit_card_type']); $iatslink1->setCardNumber($params['credit_card_number']); $expiry_string = sprintf('%02d/%02d', $params['month'], ($params['year'] % 100)); $iatslink1->setCardExpiry($expiry_string); $amount = sprintf('%01.2f', $params['amount']); // sell $iatslink1->setDollarAmount($amount); // refund //$iatslink1->setDollarAmount(-1.15); $AgentCode = $this->_paymentProcessor['signature']; $Password = $this->_paymentProcessor['password']; $iatslink1->setAgentCode($AgentCode); $iatslink1->setPassword($Password); // send IATS my invoiceID to match things up later $iatslink1->setInvoiceNumber($params['invoiceID']); // Set billing fields $iatslink1->setFirstName($params['billing_first_name']); $iatslink1->setLastName($params['billing_last_name']); $iatslink1->setStreetAddress($params['street_address']); $iatslink1->setCity($params['city']); $iatslink1->setState($params['state_province']); $iatslink1->setZipCode($params['postal_code']); // and now go! ... uses curl to post and retrieve values // after various data integrity tests // simple version if (!$isRecur) { // cvv2 only seems to get set for this! $iatslink1->setCVV2($params['cvv2']); // Allow further manipulation of the arguments via custom hooks, // before initiating processCreditCard() CRM_Utils_Hook::alterPaymentProcessorParams($this, $params, $iatslink1); $iatslink1->processCreditCard(); // extra fields for recurring donations } else { // implicit - test?: 1 == $params['frequency_interval']; $scheduleType = NULL; if ($params['installments']) { $paymentsRecur = $params['installments'] - 1; } // handle unspecified installments by setting to 10 years, IATS doesn't allow indefinitely recurring contributions else { switch ($params['frequency_unit']) { case 'week': $paymentsRecur = 520; case 'month': $paymentsRecur = 120; } } // IATS requires end date, calculated here // to be converted to date format later $startTime = time(); $date = getdate($startTime); switch ($params['frequency_unit']) { case 'week': $scheduleType = 'WEEKLY'; $scheduleDate = $date['wday'] + 1; $endTime = $startTime + ($paymentsRecur * 7 * 24 * 60 * 60); break; case 'month': $scheduleType = 'MONTHLY'; $scheduleDate = $date['mday']; $date['mon'] += $paymentsRecur; while ($date['mon'] > 12) { $date['mon'] -= 12; $date['year'] += 1; } $endTime = mktime($date['hours'], $date['minutes'], $date['seconds'], $date['mon'], $date['mday'], $date['year']); break; default: die('Invalid frequency unit!'); break; } $endDate = date('Y-m-d', $endTime); $startDate = date('Y-m-d', $startTime); $iatslink1->setReoccuringStatus("ON"); $iatslink1->setBeginDate($startDate); $iatslink1->setEndDate($endDate); $iatslink1->setScheduleType($scheduleType); $iatslink1->setScheduleDate($scheduleDate); // Allow further manipulation of the arguments via custom hooks, // before initiating the curl process CRM_Utils_Hook::alterPaymentProcessorParams($this, $params, $iatslink1); // this next line is the reoccc equiv of processCreditCard $iatslink1->createReoccCustomer(); } if ($iatslink1->getStatus() == 1) { // this just means we got some kind of answer, not necessarily approved $result = $iatslink1->getAuthorizationResult(); //return self::error($result); $result = explode(':', $result, 2); $trxn_result = trim($result[0]); $trxn_id = trim($result[1]); if ($trxn_result == 'OK') { $params['trxn_id'] = $trxn_id . ':' . time(); $params['gross_amount'] = $amount; return $params; } // createReoccCustomer() may return other, valid result codes... elseif (preg_match('/A\d+/', $trxn_result)) { $params['trxn_id'] = $trxn_result; $params['gross_amount'] = $amount; return $params; } else { return self::error($trxn_id); } } else { return self::error($iatslink1->getError()); } } function &error($error = NULL) { $e = CRM_Core_Error::singleton(); if (is_object($error)) { $e->push($error->getResponseCode(), 0, NULL, $error->getMessage() ); } elseif ($error && is_numeric($error)) { $e->push($error, 0, NULL, $this->errorString($error) ); } elseif (is_string($error)) { $e->push(9002, 0, NULL, $error ); } else { $e->push(9001, 0, NULL, "Unknown System Error."); } return $e; } function errorString($error_id) { $errors = array( 1 => 'Agent Code has not been set up on the authorization system.', 2 => 'Unable to process transaction. Verify and re-enter credit card information.', 3 => 'Charge card expired.', 4 => 'Incorrect expiration date.', 5 => 'Invalid transaction. Verify and re-enter credit card information.', 6 => 'Transaction not supported by institution.', 7 => 'Lost or stolen card.', 8 => 'Invalid card status.', 9 => 'Restricted card status. Usually on corporate cards restricted to specific sales.', 10 => 'Error. Please verify and re-enter credit card information.', 11 => 'General decline code, may have different reasons for each card type. Please have your client call customer service.', 14 => 'This means that the credit card is over the limit.', 15 => 'Decline code, may have different reasons for each card type. Please have your client call customer service.', 16 => 'Invalid charge card number. Verify and re-enter credit card information.', 17 => 'Unable to authorize transaction. Verify card information with customer and re-enter. Could be invalid name or expiry date.', 18 => 'Card not supported by institution.', 19 => 'Incorrect CVV2.', 22 => 'Bank Timeout. Bank lines may be down or busy. Re-try transaction later.', 23 => 'System error. Re-try transaction later.', 24 => 'Charge card expired.', 25 => 'Capture card. Reported lost or stolen.', 27 => 'System error, please re-enter transaction.', 29 => 'Rejected by Ticketmaster.', 31 => 'Manual reject code ', 39 => 'Contact Ticketmaster 1-888-955-5455 ', 40 => 'Card not supported by Ticketmaster. Invalid cc number.', 41 => 'Invalid Expiry date ', 100 => 'Authorization system down. DO NOT REPROCESS.', ); return ' ' . $errors[(integer) $error_id] . ''; } /** * This function checks to see if we have the right config values * * @param string $mode the mode we are operating in (live or test) * * @return string the error message if any * @public */ function checkConfig() { $error = array(); if (empty($this->_paymentProcessor['signature'])) { $error[] = ts('Agent Code is not set in the Administer CiviCRM » System Settings » Payment Processors.'); } if (empty($this->_paymentProcessor['password'])) { $error[] = ts('Password is not set in the Administer CiviCRM » System Settings » Payment Processors.'); } if (!empty($error)) { return implode('

', $error); } else { return NULL; } } }