PageRenderTime 53ms CodeModel.GetById 24ms RepoModel.GetById 1ms app.codeStats 0ms

/public_html/sites/all/modules/civicrm/CRM/Core/Payment/IATS.php

https://github.com/timstephenson/NatureBridge
PHP | 316 lines | 196 code | 34 blank | 86 comment | 27 complexity | b7ae7eef7b95871a49c45a71e4a899d5 MD5 | raw file
  1. <?php
  2. /*
  3. +--------------------------------------------------------------------+
  4. | CiviCRM version 4.0 |
  5. +--------------------------------------------------------------------+
  6. | Copyright CiviCRM LLC (c) 2004-2011 |
  7. +--------------------------------------------------------------------+
  8. | This file is a part of CiviCRM. |
  9. | |
  10. | CiviCRM is free software; you can copy, modify, and distribute it |
  11. | under the terms of the Affero General Public License Version 1, |
  12. | March 2002. |
  13. | |
  14. | CiviCRM is distributed in the hope that it will be useful, but |
  15. | WITHOUT ANY WARRANTY; without even the implied warranty of |
  16. | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. |
  17. | See the Affero General Public License for more details. |
  18. | |
  19. | You should have received a copy of the Affero General Public |
  20. | License and the CiviCRM Licensing Exception along |
  21. | with this program; if not, contact CiviCRM LLC |
  22. | at info[AT]civicrm[DOT]org. If you have questions about the |
  23. | Affero General Public License or the licensing of CiviCRM, |
  24. | see the CiviCRM license FAQ at http://civicrm.org/licensing |
  25. +--------------------------------------------------------------------+
  26. */
  27. /**
  28. *
  29. * @package CRM
  30. * @author Alan Dixon
  31. * @copyright CiviCRM LLC (c) 2004-2011
  32. * $Id$
  33. *
  34. */
  35. require_once 'CRM/Core/Payment.php';
  36. class CRM_Core_Payment_IATS extends CRM_Core_Payment {
  37. const
  38. CHARSET = 'UFT-8'; # (not used, implicit in the API, might need to convert?)
  39. const
  40. CURRENCIES = 'CAD,USD,AUD,GBP,EUR,NZD'; /* check IATS website for additional supported currencies */
  41. /**
  42. * We only need one instance of this object. So we use the singleton
  43. * pattern and cache the instance in this variable
  44. *
  45. * @var object
  46. * @static
  47. */
  48. static private $_singleton = null;
  49. /**
  50. * Constructor
  51. *
  52. * @param string $mode the mode of operation: live or test
  53. *
  54. * @return void
  55. */
  56. function __construct( $mode, &$paymentProcessor ) {
  57. $this->_paymentProcessor = $paymentProcessor;
  58. $this->_processorName = ts('IATS');
  59. $config = CRM_Core_Config::singleton( ); // get merchant data from config
  60. $this->_profile['mode'] = $mode; // live or test
  61. $this->_profile['webserver'] = parse_url($this->_paymentProcessor['url_site'],PHP_URL_HOST);
  62. $currencyID = $config->defaultCurrency;
  63. if (!in_array($currencyID,explode(',',self::CURRENCIES))) {
  64. // Configuration error: default currency must be in CURRENCIES const
  65. return self::error('Invalid configuration:'.$currencyID.', you must use one of '.self::CURRENCIES.' with IATS');
  66. }
  67. }
  68. static function &singleton( $mode, &$paymentProcessor ) {
  69. $processorName = $paymentProcessor['name'];
  70. if (self::$_singleton[$processorName] === null ) {
  71. self::$_singleton[$processorName] = new CRM_Core_Payment_IATS( $mode, $paymentProcessor );
  72. }
  73. return self::$_singleton[$processorName];
  74. }
  75. function doDirectPayment( &$params ) {
  76. // $result = '';
  77. // foreach($params as $key => $value) {
  78. // $result .= "<strong>$key</strong>: $value<br />";
  79. // }
  80. // return self::error($result);
  81. // make sure i've been called correctly ...
  82. if ( ! $this->_profile ) {
  83. return self::error('Unexpected error, missing profile');
  84. }
  85. if ( !in_array($params['currencyID'], explode(',',self::CURRENCIES ) ) ) {
  86. return self::error( 'Invalid currency selection, must be one of '.self::CURRENCIES );
  87. }
  88. $isRecur = $params['is_recur'];
  89. // AgentCode = $this->_paymentProcessor['signature'];
  90. // Password = $this->_paymentProcessor['password' ];
  91. // beginning of modified sample code from IATS php api include IATS supplied api library
  92. if ( $isRecur ) {
  93. include_once('Services/IATS/iats_reoccur.php');
  94. $iatslink1 = new iatslinkReoccur;
  95. } else {
  96. include_once('Services/IATS/iatslink.php');
  97. $iatslink1 = new iatslink;
  98. }
  99. $iatslink1->setTestMode( $this->_profile['mode'] != 'live' );
  100. $iatslink1->setWebServer( $this->_profile['webserver'] );
  101. // return self::error($this->_profile['webserver']);
  102. $iatslink1->setInvoiceNumber($params['invoiceID']); // Put your invoice here
  103. // $iatslink1->setCardType("VISA");
  104. // If CardType is not set, iatslink will find the cardType
  105. // CardType not set because IATS uses different names!
  106. // $iatslink1->setCardType($params['credit_card_type']);
  107. $iatslink1->setCardNumber($params['credit_card_number']);
  108. $expiry_string = sprintf('%02d/%02d',$params['month'],($params['year'] % 100));
  109. $iatslink1->setCardExpiry($expiry_string);
  110. $amount = sprintf('%01.2f',$params['amount']);
  111. $iatslink1->setDollarAmount($amount); //sell
  112. //$iatslink1->setDollarAmount(-1.15); //refund
  113. $AgentCode = $this->_paymentProcessor['signature'];
  114. $Password = $this->_paymentProcessor['password' ];
  115. $iatslink1->setAgentCode($AgentCode);
  116. $iatslink1->setPassword($Password);
  117. // send IATS my invoiceID to match things up later
  118. $iatslink1->setInvoiceNumber($params['invoiceID']);
  119. // Set billing fields
  120. $iatslink1->setFirstName($params['billing_first_name']);
  121. $iatslink1->setLastName($params['billing_last_name']);
  122. $iatslink1->setStreetAddress($params['street_address']);
  123. $iatslink1->setCity($params['city']);
  124. $iatslink1->setState($params['state_province']);
  125. $iatslink1->setZipCode($params['postal_code']);
  126. // and now go! ... uses curl to post and retrieve values
  127. // after various data integrity tests
  128. if (!$isRecur) { // simple version
  129. // cvv2 only seems to get set for this!
  130. $iatslink1->setCVV2($params['cvv2']);
  131. // Allow further manipulation of the arguments via custom hooks,
  132. // before initiating processCreditCard()
  133. CRM_Utils_Hook::alterPaymentProcessorParams( $this, $params, $iatslink1 );
  134. $iatslink1->processCreditCard();
  135. } else { // extra fields for recurring donations
  136. // implicit - test?: 1 == $params['frequency_interval'];
  137. $scheduleType = NULL;
  138. if ($params['installments']) {
  139. $paymentsRecur = $params['installments'] - 1;
  140. }
  141. else { // handle unspecified installments by setting to 10 years, IATS doesn't allow indefinitely recurring contributions
  142. switch($params['frequency_unit']) {
  143. case 'week':
  144. $paymentsRecur = 520;
  145. case 'month':
  146. $paymentsRecur = 120;
  147. }
  148. }
  149. // IATS requires end date, calculated here
  150. $startTime = time(); // to be converted to date format later
  151. $date = getdate($startTime);
  152. switch($params['frequency_unit']) {
  153. case 'week':
  154. $scheduleType = 'WEEKLY';
  155. $scheduleDate = $date['wday'] + 1;
  156. $endTime = $startTime + ($paymentsRecur * 7 * 24 * 60 * 60);
  157. break;
  158. case 'month':
  159. $scheduleType = 'MONTHLY';
  160. $scheduleDate = $date['mday'];
  161. $date['mon'] += $paymentsRecur;
  162. while ($date['mon'] > 12) {
  163. $date['mon'] -= 12;
  164. $date['year'] += 1;
  165. }
  166. $endTime = mktime($date['hours'],$date['minutes'],$date['seconds'],$date['mon'],$date['mday'],$date['year']);
  167. break;
  168. default: die('Invalid frequency unit!'); break;
  169. }
  170. $endDate = date('Y-m-d',$endTime);
  171. $startDate = date('Y-m-d',$startTime);
  172. $iatslink1->setReoccuringStatus("ON");
  173. $iatslink1->setBeginDate($startDate);
  174. $iatslink1->setEndDate($endDate);
  175. $iatslink1->setScheduleType($scheduleType);
  176. $iatslink1->setScheduleDate($scheduleDate);
  177. // Allow further manipulation of the arguments via custom hooks,
  178. // before initiating the curl process
  179. CRM_Utils_Hook::alterPaymentProcessorParams( $this, $params, $iatslink1 );
  180. // this next line is the reoccc equiv of processCreditCard
  181. $iatslink1->createReoccCustomer();
  182. }
  183. if ($iatslink1->getStatus() == 1) {
  184. // this just means we got some kind of answer, not necessarily approved
  185. $result = $iatslink1->getAuthorizationResult();
  186. //return self::error($result);
  187. $result = explode(':',$result,2);
  188. $trxn_result = trim($result[0]);
  189. $trxn_id = trim($result[1]);
  190. if ($trxn_result == 'OK') {
  191. $params['trxn_id'] = $trxn_id.':'.time();
  192. $params['gross_amount'] = $amount;
  193. return $params;
  194. }
  195. // createReoccCustomer() may return other, valid result codes...
  196. else if (preg_match('/A\d+/', $trxn_result)) {
  197. $params['trxn_id'] = $trxn_result;
  198. $params['gross_amount'] = $amount;
  199. return $params;
  200. }
  201. else {
  202. return self::error($trxn_id);
  203. }
  204. } else {
  205. return self::error($iatslink1->getError());
  206. }
  207. }
  208. function &error( $error = null ) {
  209. $e =& CRM_Core_Error::singleton( );
  210. if ( is_object($error) ) {
  211. $e->push( $error->getResponseCode( ),
  212. 0, null,
  213. $error->getMessage( ) );
  214. } elseif ($error && is_numeric($error) ) {
  215. $e->push( $error,
  216. 0, null,
  217. $this->errorString($error) );
  218. } elseif ( is_string($error) ) {
  219. $e->push( 9002,
  220. 0, null,
  221. $error );
  222. } else {
  223. $e->push( 9001, 0, null, "Unknown System Error." );
  224. }
  225. return $e;
  226. }
  227. function errorString($error_id) {
  228. $errors = array(
  229. 1 => 'Agent Code has not been set up on the authorization system.',
  230. 2 => 'Unable to process transaction. Verify and re-enter credit card information.',
  231. 3 => 'Charge card expired.',
  232. 4 => 'Incorrect expiration date.',
  233. 5 => 'Invalid transaction. Verify and re-enter credit card information.',
  234. 6 => 'Transaction not supported by institution.',
  235. 7 => 'Lost or stolen card.',
  236. 8 => 'Invalid card status.',
  237. 9 => 'Restricted card status. Usually on corporate cards restricted to specific sales.',
  238. 10 => 'Error. Please verify and re-enter credit card information.',
  239. 11 => 'General decline code, may have different reasons for each card type. Please have your client call customer service.',
  240. 14 => 'This means that the credit card is over the limit.',
  241. 15 => 'Decline code, may have different reasons for each card type. Please have your client call customer service.',
  242. 16 => 'Invalid charge card number. Verify and re-enter credit card information.',
  243. 17 => 'Unable to authorize transaction. Verify card information with customer and re-enter. Could be invalid name or expiry date.',
  244. 18 => 'Card not supported by institution.',
  245. 19 => 'Incorrect CVV2.',
  246. 22 => 'Bank Timeout. Bank lines may be down or busy. Re-try transaction later.',
  247. 23 => 'System error. Re-try transaction later.',
  248. 24 => 'Charge card expired.',
  249. 25 => 'Capture card. Reported lost or stolen.',
  250. 27 => 'System error, please re-enter transaction.',
  251. 29 => 'Rejected by Ticketmaster.',
  252. 31 => 'Manual reject code ',
  253. 39 => 'Contact Ticketmaster 1-888-955-5455 ',
  254. 40 => 'Card not supported by Ticketmaster. Invalid cc number.',
  255. 41 => 'Invalid Expiry date ',
  256. 100 => 'Authorization system down. DO NOT REPROCESS.',
  257. );
  258. return ' <strong>'.$errors[(integer) $error_id].'</strong>';
  259. }
  260. /**
  261. * This function checks to see if we have the right config values
  262. *
  263. * @param string $mode the mode we are operating in (live or test)
  264. *
  265. * @return string the error message if any
  266. * @public
  267. */
  268. function checkConfig( ) {
  269. $error = array( );
  270. if ( empty( $this->_paymentProcessor['signature'] ) ) {
  271. $error[] = ts( 'Agent Code is not set in the Administer CiviCRM &raquo; Payment Processor.' );
  272. }
  273. if ( empty( $this->_paymentProcessor['password'] ) ) {
  274. $error[] = ts( 'Password is not set in the Administer CiviCRM &raquo; Payment Processor.' );
  275. }
  276. if ( ! empty( $error ) ) {
  277. return implode( '<p>', $error );
  278. } else {
  279. return null;
  280. }
  281. }
  282. }