Merge pull request #3208 from eileenmcnaughton/comments
[civicrm-core.git] / CRM / Core / Payment / PayJunction.php
1 <?php
2
3 /**
4 * Copyright (C) 2007
5 * Licensed to CiviCRM under the Academic Free License version 3.0.
6 *
7 * Written and contributed by Phase2 Technology, LLC (http://www.phase2technology.com)
8 *
9 */
10
11 /**
12 *
13 * @package CRM
14 * @author Michael Morris and Gene Chi @ Phase2 Technology <mmorris@phase2technology.com>
15 * $Id$
16 *
17 */
18 class CRM_Core_Payment_PayJunction extends CRM_Core_Payment {
19 # (not used, implicit in the API, might need to convert?)
20 CONST CHARSET = 'UFT-8';
21
22 /**
23 * We only need one instance of this object. So we use the singleton
24 * pattern and cache the instance in this variable
25 *
26 * @var object
27 * @static
28 */
29 static private $_singleton = NULL;
30
31 /**
32 * Constructor
33 *
34 * @param string $mode the mode of operation: live or test
35 *
36 * @return void
37 */
38 function __construct($mode, &$paymentProcessor) {
39 //require PayJunction API library
40 require_once 'PayJunction/pjClasses.php';
41
42 $this->_mode = $mode;
43 $this->_paymentProcessor = $paymentProcessor;
44 $this->_processorName = ts('PayJunction');
45 }
46
47 /**
48 * singleton function used to manage this object
49 *
50 * @param string $mode the mode of operation: live or test
51 *
52 * @return object
53 * @static
54 *
55 */
56 static function &singleton($mode, &$paymentProcessor, &$paymentForm = NULL, $force = false) {
57 $processorName = $paymentProcessor['name'];
58 if (self::$_singleton[$processorName] === NULL) {
59 self::$_singleton[$processorName] = new CRM_Core_Payment_PayJunction($mode, $paymentProcessor);
60 }
61 return self::$_singleton[$processorName];
62 }
63
64 /*
65 * This function sends request and receives response from
66 * PayJunction payment process
67 */
68 function doDirectPayment(&$params) {
69 $logon = $this->_paymentProcessor['user_name'];
70 $password = $this->_paymentProcessor['password'];
71 $url_site = $this->_paymentProcessor['url_site'];
72
73 // create pjpgCustInfo object
74 $pjpgCustInfo = new pjpgCustInfo();
75
76 $pjpgCustInfo->setEmail($params['email']);
77
78 $billing = array(
79 "logon" => $logon,
80 "password" => $password,
81 "url_site" => $url_site,
82 "first_name" => $params['first_name'],
83 "last_name" => $params['last_name'],
84 "address" => $params['street_address'],
85 "city" => $params['city'],
86 "province" => $params['state_province'],
87 "postal_code" => $params['postal_code'],
88 "country" => $params['country'],
89 );
90 $pjpgCustInfo->setBilling($billing);
91
92 // create pjpgTransaction object
93 $my_orderid = $params['invoiceID'];
94
95 $expiry_string = sprintf('%04d%02d', $params['year'], $params['month']);
96
97 $txnArray = array(
98 'type' => 'purchase',
99 'order_id' => $my_orderid,
100 'amount' => sprintf('%01.2f', $params['amount']),
101 'pan' => $params['credit_card_number'],
102 'expdate' => $expiry_string,
103 'crypt_type' => '7',
104 'cust_id' => $params['contact_id'],
105 );
106
107 // Allow further manipulation of params via custom hooks
108 CRM_Utils_Hook::alterPaymentProcessorParams($this, $params, $txnArray);
109
110 $pjpgTxn = new pjpgTransaction($txnArray);
111
112 // set customer info (level 3 data) for the transaction
113 $pjpgTxn->setCustInfo($pjpgCustInfo);
114
115
116 // empty installments convert to 999 because PayJunction do not allow open end donation
117 if ($params['installments'] == "") {
118 $params['installments'] = "999";
119 }
120
121 // create recurring object
122 if ($params['is_recur'] == TRUE && $params['installments'] > 1) {
123 // schedule start date as today
124 // format: YYYY-MM-DD
125 $params['dc_schedule_start'] = date("Y-m-d");
126
127 // Recur Variables
128 $dc_schedule_create = $params['is_recur'];
129 $recurUnit = $params['frequency_unit'];
130 $recurInterval = $params['frequency_interval'];
131 $dc_schedule_start = $params['dc_schedule_start'];
132
133 // next payment in moneris required format
134 $startDate = date("Y/m/d", $next);
135
136 $numRecurs = $params['installments'];
137
138 $recurArray = array(
139 'dc_schedule_create' => $dc_schedule_create,
140 // (day | week | month)
141 'recur_unit' => $recurUnit,
142 // yyyy/mm/dd
143 'start_date' => $startDate,
144 'num_recurs' => $numRecurs,
145 'start_now' => 'false',
146 'period' => $recurInterval,
147 'dc_schedule_start' => $dc_schedule_start,
148 'amount' => sprintf('%01.2f', $params['amount']),
149 );
150
151 $pjpgRecur = new pjpgRecur($recurArray);
152
153 $pjpgTxn->setRecur($pjpgRecur);
154 }
155
156 // create a pjpgRequest object passing the transaction object
157 $pjpgRequest = new pjpgRequest($pjpgTxn);
158
159 $pjpgHttpPost = new pjpgHttpsPost($pjpgRequest);
160
161 // get an pjpgResponse object
162 $pjpgResponse = $pjpgHttpPost->getPJpgResponse();
163
164 if (self::isError($pjpgResponse)) {
165 return self::error($pjpgResponse);
166 }
167
168 /* Check for application errors */
169
170 $result = self::checkResult($pjpgResponse);
171 if (is_a($result, 'CRM_Core_Error')) {
172 return $result;
173 }
174
175 // Success
176 $params['trxn_result_code'] = $pjpgResponse['dc_response_code'];
177 $params['trxn_id'] = $pjpgResponse['dc_transaction_id'];
178 $params['gross_amount'] = $params['amount'];
179
180 return $params;
181 }
182 // end function doDirectPayment
183
184
185 /*
186 * This function checks the PayJunction response code
187 */
188 function isError(&$response) {
189 $responseCode = $response['dc_response_code'];
190
191 if ($responseCode == "00" || $responseCode == "85") {
192 return FALSE;
193 }
194 else {
195 return TRUE;
196 }
197 }
198
199
200 // ignore for now, more elaborate error handling later.
201 function &checkResult(&$response) {
202 return $response;
203 }
204
205 /**
206 * Get the value of a field if set
207 *
208 * @param string $field the field
209 *
210 * @return mixed value of the field, or empty string if the field is
211 * not set
212 */
213 function _getParam($field) {
214 if (isset($this->_params[$field])) {
215 return $this->_params[$field];
216 }
217 else {
218 return '';
219 }
220 }
221
222 function &error($error = NULL) {
223 $e = CRM_Core_Error::singleton();
224 if ($error) {
225 $e->push($error['dc_response_code'],
226 0, NULL,
227 $error['dc_response_message']
228 );
229 }
230 else {
231 $e->push(9001, 0, NULL, "Unknown System Error.");
232 }
233 return $e;
234 }
235
236 /**
237 * Set a field to the specified value. Value must be a scalar (int,
238 * float, string, or boolean)
239 *
240 * @param string $field
241 * @param mixed $value
242 *
243 * @return bool false if value is not a scalar, true if successful
244 */
245 function _setParam($field, $value) {
246 if (!is_scalar($value)) {
247 return FALSE;
248 }
249 else {
250 $this->_params[$field] = $value;
251 }
252 }
253
254 /**
255 * This function checks to see if we have the right config values
256 *
257 * @return string the error message if any
258 * @public
259 */
260 function checkConfig() {
261 $error = array();
262 if (empty($this->_paymentProcessor['user_name'])) {
263 $error[] = ts('Username is not set for this payment processor');
264 }
265
266 if (empty($this->_paymentProcessor['password'])) {
267 $error[] = ts('Password is not set for this payment processor');
268 }
269
270 if (empty($this->_paymentProcessor['url_site'])) {
271 $error[] = ts('Site URL is not set for this payment processor');
272 }
273
274 if (!empty($error)) {
275 return implode('<p>', $error);
276 }
277 else {
278 return NULL;
279 }
280 }
281 }
282 // end class CRM_Core_Payment_PayJunction
283