Commit 011016c5 authored by bgm's avatar bgm Committed by Aegir user

Removed com.iatspayments.civicrm, now bundled with CiviCRM core.

parent 480dbf10
<?php
/**
* Copyright iATS Payments (c) 2014
* @author Alan Dixon
*
* This file is a part of CiviCRM published extension.
*
* This extension is free software; you can copy, modify, and distribute it
* under the terms of the GNU Affero General Public License
* Version 3, 19 November 2007.
*
* It is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public
* License with this program; if not, see http://www.gnu.org/licenses/
*
* This code provides glue between CiviCRM payment model and the iATS Payment model encapsulated in the iATS_Service_Request object
*/
class CRM_Core_Payment_iATSServiceACHEFT extends CRM_Core_Payment {
/**
* We only need one instance of this object. So we use the singleton
* pattern and cache the instance in this variable
*
* @var object
* @static
*/
static private $_singleton = NULL;
/**
* Constructor.
*
* @param string $mode the mode of operation: live or test
* @param array $paymentProcessor
*/
public function __construct($mode, &$paymentProcessor) {
$this->_paymentProcessor = $paymentProcessor;
$this->_processorName = ts('iATS Payments ACHEFT');
// live or test
$this->_profile['mode'] = $mode;
// we only use the domain of the configured url, which is different for NA vs. UK
$this->_profile['iats_domain'] = parse_url($this->_paymentProcessor['url_site'], PHP_URL_HOST);
}
static function &singleton($mode, &$paymentProcessor, &$paymentForm = NULL, $force = FALSE) {
$processorName = $paymentProcessor['name'];
if (self::$_singleton[$processorName] === NULL) {
self::$_singleton[$processorName] = new CRM_Core_Payment_iATSServiceACHEFT($mode, $paymentProcessor);
}
return self::$_singleton[$processorName];
}
function doDirectPayment(&$params) {
if (!$this->_profile) {
return self::error('Unexpected error, missing profile');
}
// use the iATSService object for interacting with iATS, mostly the same for recurring contributions
require_once("CRM/iATS/iATSService.php");
// TODO: force bail if it's not recurring?
$isRecur = CRM_Utils_Array::value('is_recur', $params) && $params['contributionRecurID'];
$method = $isRecur ? 'acheft_create_customer_code':'acheft';
// to add debugging info in the drupal log, assign 1 to log['all'] below
$iats = new iATS_Service_Request(array('type' => 'process', 'method' => $method, 'iats_domain' => $this->_profile['iats_domain'], 'currencyID' => $params['currencyID']));
$request = $this->convertParams($params, $method);
$request['customerIPAddress'] = (function_exists('ip_address') ? ip_address() : $_SERVER['REMOTE_ADDR']);
$credentials = array('agentCode' => $this->_paymentProcessor['user_name'],
'password' => $this->_paymentProcessor['password' ]);
// Get the API endpoint URL for the method's transaction mode.
// TODO: enable override of the default url in the request object
// $url = $this->_paymentProcessor['url_site'];
// make the soap request
$response = $iats->request($credentials,$request);
// process the soap response into a readable result
$result = $iats->result($response);
if ($result['status']) {
$params['contribution_status_id'] = 2; // always pending status
$params['payment_status_id'] = 2; // for future versions, the proper key
$params['trxn_id'] = trim($result['remote_id']) . ':' . time();
$params['gross_amount'] = $params['amount'];
if ($isRecur) {
// save the client info in my custom table
// Allow further manipulation of the arguments via custom hooks,
// before initiating processCreditCard()
// CRM_Utils_Hook::alterPaymentProcessorParams($this, $params, $iatslink1);
$processresult = $response->PROCESSRESULT;
$customer_code = (string) $processresult->CUSTOMERCODE;
// $exp = sprintf('%02d%02d', ($params['year'] % 100), $params['month']);
$exp = '0000';
$email ='';
if (isset($params['email'])) {
$email = $params['email'];
}
elseif(isset($params['email-5'])) {
$email = $params['email-5'];
}
elseif(isset($params['email-Primary'])) {
$email = $params['email-Primary'];
}
$query_params = array(
1 => array($customer_code, 'String'),
2 => array($request['customerIPAddress'], 'String'),
3 => array($exp, 'String'),
4 => array($params['contactID'], 'Integer'),
5 => array($email, 'String'),
6 => array($params['contributionRecurID'], 'Integer'),
);
CRM_Core_DAO::executeQuery("INSERT INTO civicrm_iats_customer_codes
(customer_code, ip, expiry, cid, email, recur_id) VALUES (%1, %2, %3, %4, %5, %6)", $query_params);
// also set next_sched_contribution, the field name is civicrm version dependent
$field_name = _iats_civicrm_nscd_fid();
$params[$field_name] = strtotime('+'.$params['frequency_interval'].' '.$params['frequency_unit']);
}
return $params;
}
else {
return self::error($result['reasonMessage']);
}
}
function changeSubscriptionAmount(&$message = '', $params = array()) {
$userAlert = ts('You have updated the amount of this recurring contribution.');
CRM_Core_Session::setStatus($userAlert, ts('Warning'), 'alert');
return TRUE;
}
function cancelSubscription(&$message = '', $params = array()) {
$userAlert = ts('You have cancelled this recurring contribution.');
CRM_Core_Session::setStatus($userAlert, ts('Warning'), 'alert');
return TRUE;
}
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;
}
/**
* 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['user_name'])) {
$error[] = ts('Agent Code is not set in the Administer CiviCRM &raquo; System Settings &raquo; Payment Processors.');
}
if (empty($this->_paymentProcessor['password'])) {
$error[] = ts('Password is not set in the Administer CiviCRM &raquo; System Settings &raquo; Payment Processors.');
}
if (!empty($error)) {
return implode('<p>', $error);
}
else {
return NULL;
}
}
/*
* Convert the values in the civicrm params to the request array with keys as expected by iATS
*/
function convertParams($params, $method) {
$request = array();
$convert = array(
'firstName' => 'billing_first_name',
'lastName' => 'billing_last_name',
'address' => 'street_address',
'city' => 'city',
'state' => 'state_province',
'zipCode' => 'postal_code',
'country' => 'country',
'invoiceNum' => 'invoiceID',
/* 'accountNum' => 'bank_account_number', */
'accountType' => 'bank_account_type',
);
foreach($convert as $r => $p) {
if (isset($params[$p])) {
$request[$r] = $params[$p];
}
}
$request['total'] = sprintf('%01.2f', CRM_Utils_Rule::cleanMoney($params['amount']));
// place for ugly hacks
switch($method) {
case 'acheft':
case 'acheft_create_customer_code':
// add bank number + transit to account number
// TODO: verification?
$request['accountNum'] = preg_replace('/^0-9]/','',$params['bank_identification_number'].$params['bank_account_number']);
break;
}
return $request;
}
}
<?php
/* Copyright iATS Payments (c) 2014
* @author Alan Dixon
*
* This file is a part of CiviCRM published extension.
*
* This extension is free software; you can copy, modify, and distribute it
* under the terms of the GNU Affero General Public License
* Version 3, 19 November 2007.
*
* It is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public
* License with this program; if not, see http://www.gnu.org/licenses/
*
* This code provides glue between CiviCRM payment model and the iATS Payment model encapsulated in the iATS_Service_Request object
*
*/
class CRM_Core_Payment_iATSServiceSWIPE extends CRM_Core_Payment_iATSService {
/**
* We only need one instance of this object. So we use the singleton
* pattern and cache the instance in this variable
*
* @var object
* @static
*/
static private $_singleton = NULL;
/**
* Constructor
*
* @param string $mode the mode of operation: live or test
*
* @return void
*/
function __construct($mode, &$paymentProcessor) {
$this->_paymentProcessor = $paymentProcessor;
$this->_processorName = ts('iATS Payments SWIPE');
// get merchant data from config
$config = CRM_Core_Config::singleton();
// live or test
$this->_profile['mode'] = $mode;
// we only use the domain of the configured url, which is different for NA vs. UK
$this->_profile['iats_domain'] = parse_url($this->_paymentProcessor['url_site'], PHP_URL_HOST);
}
static function &singleton($mode, &$paymentProcessor, &$paymentForm = NULL, $force = FALSE) {
$processorName = $paymentProcessor['name'];
if (self::$_singleton[$processorName] === NULL) {
self::$_singleton[$processorName] = new CRM_Core_Payment_iATSServiceSWIPE($mode, $paymentProcessor);
}
return self::$_singleton[$processorName];
}
public function validatePaymentInstrument($values, &$errors) {
// override the default and don't do any validation because my values are encrypted
}
}
<?php
require_once 'CRM/Core/Form.php';
/**
* Form controller class
*
* @see http://wiki.civicrm.org/confluence/display/CRMDOC43/QuickForm+Reference
*/
class CRM_iATS_Form_IATSCustomerLink extends CRM_Core_Form {
/**
* Get the field names and labels expected by iATS CustomerLink,
* and the corresponding fields in CiviCRM
*
* @return array
*/
public function getFields() {
$civicrm_fields = array(
'firstName' => 'billing_first_name',
'lastName' => 'billing_last_name',
'address' => 'street_address',
'city' => 'city',
'state' => 'state_province',
'zipCode' => 'postal_code',
'creditCardNum' => 'credit_card_number',
'creditCardExpiry' => 'credit_card_expiry',
'mop' => 'credit_card_type',
);
// when querying using CustomerLink
$iats_fields = array(
'creditCardCustomerName' => 'CSTN', // FLN
'address' => 'ADD',
'city' => 'CTY',
'state' => 'ST',
'zipCode' => 'ZC',
'creditCardNum' => 'CCN',
'creditCardExpiry' => 'EXP',
'mop' => 'MP'
);
$labels = array(
//'firstName' => 'First Name',
// 'lastName' => 'Last Name',
'creditCardCustomerName' => 'Name on Card',
'address' => 'Street Address',
'city' => 'City',
'state' => 'State or Province',
'zipCode' => 'Postal Code or Zip Code',
'creditCardNum' => 'Credit Card Number',
'creditCardExpiry' => 'Credit Card Expiry Date',
'mop' => 'Credit Card Type',
);
return array($civicrm_fields, $iats_fields, $labels);
}
protected function getCustomerCodeDetail($params) {
require_once("CRM/iATS/iATSService.php");
$credentials = iATS_Service_Request::credentials($params['paymentProcessorId'], $params['is_test']);
$iats_service_params = array('type' => 'customer', 'iats_domain' => $credentials['domain'], 'method' => 'get_customer_code_detail');
$iats = new iATS_Service_Request($iats_service_params);
// print_r($iats); die();
$request = array('customerCode' => $params['customerCode']);
// make the soap request
$response = $iats->request($credentials,$request);
$customer = $iats->result($response, FALSE); // note: don't log this to the iats_response table
// print_r($customer); die();
$ac1 = $customer['ac1']; // this is a SimpleXMLElement Object
$card = get_object_vars($ac1->CC);
return $customer + $card;
}
protected function updateCreditCardCustomer($params) {
require_once("CRM/iATS/iATSService.php");
$credentials = iATS_Service_Request::credentials($params['paymentProcessorId'], $params['is_test']);
unset($params['paymentProcessorId']);
unset($params['is_test']);
unset($params['domain']);
$iats_service_params = array('type' => 'customer', 'iats_domain' => $credentials['domain'], 'method' => 'update_credit_card_customer');
$iats = new iATS_Service_Request($iats_service_params);
// print_r($iats); die();
$params['updateCreditCardNum'] = (0 < strlen($params['creditCardNum']) && (FALSE === strpos($params['creditCardNum'],'*'))) ? 1 : 0;
if (empty($params['updateCreditCardNum'])) {
unset($params['creditCardNum']);
unset($params['updateCreditCardNum']);
}
$params['customerIPAddress'] = (function_exists('ip_address') ? ip_address() : $_SERVER['REMOTE_ADDR']);
foreach(array('qfKey','entryURL','firstName','lastName','_qf_default','_qf_IATSCustomerLink_submit') as $key) {
if (isset($params[$key])) {
unset($params[$key]);
}
}
// make the soap request
$response = $iats->request($credentials,$params);
$result = $iats->result($response, TRUE); // note: don't log this to the iats_response table
return $result;
}
function buildQuickForm() {
list($civicrm_fields, $iats_fields, $labels) = $this->getFields();
// I don't need cid, but it allows the back button to work
$this->add('hidden','cid');
$cid = CRM_Utils_Request::retrieve('cid', 'Integer');
foreach($labels as $name => $label) {
$this->add('text', $name, $label);
}
$this->add('hidden','customerCode');
$this->add('hidden','paymentProcessorId');
$this->add('hidden','is_test');
$customerCode = CRM_Utils_Request::retrieve('customerCode', 'String');
$paymentProcessorId = CRM_Utils_Request::retrieve('paymentProcessorId', 'Positive');
$is_test = CRM_Utils_Request::retrieve('is_test', 'Integer');
$defaults = array(
'cid' => $cid,
'customerCode' => $customerCode,
'paymentProcessorId' => $paymentProcessorId,
'is_test' => $is_test,
);
if (empty($_POST)) { // get my current values from iATS as defaults
$customer = $this->getCustomerCodeDetail($defaults);
foreach(array_keys($labels) as $name) {
$iats_field = $iats_fields[$name];
if (is_string($customer[$iats_field])) {
$defaults[$name] = $customer[$iats_field];
}
}
}
$this->setDefaults($defaults);
$this->addButtons(array(
array(
'type' => 'submit',
'name' => ts('Submit'),
'isDefault' => TRUE,
),
array(
'type' => 'cancel',
'name' => ts('Back')
)
));
// export form elements
$this->assign('elementNames', $this->getRenderableElementNames());
parent::buildQuickForm();
}
function postProcess() {
$values = $this->exportValues();
// send update to iATS
// print_r($values); die();
$result = $this->updateCreditCardCustomer($values);
$message = '<pre>'.print_r($result,TRUE).'</pre>';
CRM_Core_Session::setStatus($message, 'Customer Updated'); // , $type, $options);
if ($result['AUTHORIZATIONRESULT'] == 'OK') {
// update my copy of the expiry date
list($month,$year) = explode('/',$values['creditCardExpiry']);
$exp = sprintf('%02d%02d', $year, $month);
$query_params = array(
1 => array($values['customerCode'], 'String'),
2 => array($exp, 'String'),
);
CRM_Core_DAO::executeQuery("UPDATE civicrm_iats_customer_codes SET expiry = %2 WHERE customer_code = %1", $query_params);
}
parent::postProcess();
}
/**
* Get the fields/elements defined in this form.
*
* @return array (string)
*/
function getRenderableElementNames() {
// The _elements list includes some items which should not be
// auto-rendered in the loop -- such as "qfKey" and "buttons". These
// items don't have labels. We'll identify renderable by filtering on
// the 'label'.
$elementNames = array();
foreach ($this->_elements as $element) {
$label = $element->getLabel();
if (!empty($label)) {
$elementNames[] = $element->getName();
}
}
return $elementNames;
}
}
<?php
require_once 'CRM/Core/Form.php';
/**
* Form controller class
*
* @see http://wiki.civicrm.org/confluence/display/CRMDOC43/QuickForm+Reference
* A form to generate new one-time charges on an existing recurring schedule.
*/
class CRM_iATS_Form_IATSOneTimeCharge extends CRM_Core_Form {
public function getFields() {
$civicrm_fields = array(
'firstName' => 'billing_first_name',
'lastName' => 'billing_last_name',
'address' => 'street_address',
'city' => 'city',
'state' => 'state_province',
'zipCode' => 'postal_code',
'creditCardNum' => 'credit_card_number',
'creditCardExpiry' => 'credit_card_expiry',
'mop' => 'credit_card_type',
);
// when querying using CustomerLink
$iats_fields = array(
'creditCardCustomerName' => 'CSTN', // FLN
'address' => 'ADD',
'city' => 'CTY',
'state' => 'ST',
'zipCode' => 'ZC',
'creditCardNum' => 'CCN',
'creditCardExpiry' => 'EXP',
'mop' => 'MP'
);
$labels = array(
//'firstName' => 'First Name',
// 'lastName' => 'Last Name',
'creditCardCustomerName' => 'Name on Card',
'address' => 'Street Address',
'city' => 'City',
'state' => 'State or Province',
'zipCode' => 'Postal Code or Zip Code',
'creditCardNum' => 'Credit Card Number',
'creditCardExpiry' => 'Credit Card Expiry Date',
'mop' => 'Credit Card Type',
);
return array($civicrm_fields, $iats_fields, $labels);
}
protected function getCustomerCodeDetail($params) {
require_once("CRM/iATS/iATSService.php");
$credentials = iATS_Service_Request::credentials($params['paymentProcessorId'], $params['is_test']);
$iats_service_params = array('type' => 'customer', 'iats_domain' => $credentials['domain'], 'method' => 'get_customer_code_detail');
$iats = new iATS_Service_Request($iats_service_params);
// print_r($iats); die();
$request = array('customerCode' => $params['customerCode']);
// make the soap request
$response = $iats->request($credentials,$request);
$customer = $iats->result($response, FALSE); // note: don't log this to the iats_response table
// print_r($customer); die();
$ac1 = $customer['ac1']; // this is a SimpleXMLElement Object
$card = get_object_vars($ac1->CC);
return $customer + $card;
}
protected function processCreditCardCustomer($values) {
// generate another recurring contribution, matching our recurring template with submitted value
$total_amount = $values['amount'];
$contribution_template = _iats_civicrm_getContributionTemplate(array('contribution_recur_id' => $values['crid']));
$contact_id = $values['cid'];
$hash = md5(uniqid(rand(), true));
$contribution_recur_id = $values['crid'];
$payment_processor_id = $values['paymentProcessorId'];
$type = _iats_civicrm_is_iats($payment_processor_id);
$subtype = substr($type,11);
$source = "iATS Payments $subtype Recurring Contribution (id=$contribution_recur_id)";
$receive_date = date("YmdHis",time()); // i.e. now
$contribution = array(
'version' => 3,
'contact_id' => $contact_id,
'receive_date' => $receive_date,
'total_amount' => $total_amount,
'contribution_recur_id' => $contribution_recur_id,
'invoice_id' => $hash,
'source' => $source,
'contribution_status_id' => 2, /* initialize as pending, so we can run completetransaction after taking the money */
'payment_processor' => $payment_processor_id,
'is_test' => $values['is_test'], /* propagate the is_test value from the form */
);
foreach(array('payment_instrument_id','currency','financial_type_id') as $key) {
$contribution[$key] = $contribution_template[$key];
}
$options = array(
'is_email_receipt' => (empty($values['is_email_receipt']) ? '0' : '1'),
'customer_code' => $values['customerCode'],
'subtype' => $subtype,
);
// now all the hard work in this function, recycled from the original recurring payment job
$result = _iats_process_contribution_payment($contribution,$options);
return $result;
}
function buildQuickForm() {
list($civicrm_fields, $iats_fields, $labels) = $this->getFields();
$this->add('hidden','cid');
$this->add('hidden','crid');
$this->add('hidden','customerCode');
$this->add('hidden','paymentProcessorId');
$this->add('hidden','is_test');
$cid = CRM_Utils_Request::retrieve('cid', 'Integer');
$crid = CRM_Utils_Request::retrieve('crid', 'Integer');
$customerCode = CRM_Utils_Request::retrieve('customerCode', 'String');
$paymentProcessorId = CRM_Utils_Request::retrieve('paymentProcessorId', 'Positive');
$is_test = CRM_Utils_Request::retrieve('is_test', 'Integer');
$defaults = array(
'cid' => $cid,
'crid' => $crid,
'customerCode' => $customerCode,
'paymentProcessorId' => $paymentProcessorId,
'is_test' => $is_test,
);
$this->setDefaults($defaults);
/* always show lots of detail about the card about to be charged or just charged */
$customer = $this->getCustomerCodeDetail($defaults);
foreach($labels as $name => $label) {
$iats_field = $iats_fields[$name];
if (is_string($customer[$iats_field])) {
$this->add('static', $name, $label, $customer[$iats_field]);
}
}
// todo: show past charges/dates ?
// add form elements
$this->addMoney(
'amount', // field name
'Amount', // field label
TRUE, NULL, FALSE
);
$this->add(
'checkbox', // field type
'is_email_receipt', // field name
ts('Automated email receipt for this contribution.')
);
$this->addButtons(array(
array(
'type' => 'submit',
'name' => ts('Charge this card'),
'isDefault' => TRUE,
),
array(
'type' => 'cancel',
'name' => ts('Back')
)
));
// export form elements
$this->assign('elementNames', $this->getRenderableElementNames());
// warn the user about the nature of what they are about to do.
$message = ts('The contribution created by this form will be saved as a recurring contribution.');
CRM_Core_Session::setStatus($message, 'One-Time Charge'); // , $type, $options);
parent::buildQuickForm();
}
function postProcess() {
$values = $this->exportValues();
// print_r($values); die();
// send charge request to iATS
$result = $this->processCreditCardCustomer($values);
$message = print_r($result,TRUE);
CRM_Core_Session::setStatus($message, 'Customer Card Charged'); // , $type, $options);
parent::postProcess();
}
/**
* Get the fields/elements defined in this form.