Merge pull request #3874 from rohankatkar/CRM-15136
[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 * @param $paymentProcessor
37 *
38 * @return \CRM_Core_Payment_PayJunction
39 */
40 function __construct($mode, &$paymentProcessor) {
41 //require PayJunction API library
42 require_once 'PayJunction/pjClasses.php';
43
44 $this->_mode = $mode;
45 $this->_paymentProcessor = $paymentProcessor;
46 $this->_processorName = ts('PayJunction');
47 }
48
49 /**
50 * singleton function used to manage this object
51 *
52 * @param string $mode the mode of operation: live or test
53 *
54 * @param object $paymentProcessor
55 * @param null $paymentForm
56 * @param bool $force
57 *
58 * @return object
59 * @static
60 */
61 static function &singleton($mode, &$paymentProcessor, &$paymentForm = NULL, $force = false) {
62 $processorName = $paymentProcessor['name'];
63 if (self::$_singleton[$processorName] === NULL) {
64 self::$_singleton[$processorName] = new CRM_Core_Payment_PayJunction($mode, $paymentProcessor);
65 }
66 return self::$_singleton[$processorName];
67 }
68
69 /*
70 * This function sends request and receives response from
71 * PayJunction payment process
72 */
73 /**
74 * This function collects all the information from a web/api form and invokes
75 * the relevant payment processor specific functions to perform the transaction
76 *
77 * @param array $params assoc array of input parameters for this transaction
78 *
79 * @return array the result in an nice formatted array (or an error object)
80 * @abstract
81 */
82 function doDirectPayment(&$params) {
83 $logon = $this->_paymentProcessor['user_name'];
84 $password = $this->_paymentProcessor['password'];
85 $url_site = $this->_paymentProcessor['url_site'];
86
87 // create pjpgCustInfo object
88 $pjpgCustInfo = new pjpgCustInfo();
89
90 $pjpgCustInfo->setEmail($params['email']);
91
92 $billing = array(
93 "logon" => $logon,
94 "password" => $password,
95 "url_site" => $url_site,
96 "first_name" => $params['first_name'],
97 "last_name" => $params['last_name'],
98 "address" => $params['street_address'],
99 "city" => $params['city'],
100 "province" => $params['state_province'],
101 "postal_code" => $params['postal_code'],
102 "country" => $params['country'],
103 );
104 $pjpgCustInfo->setBilling($billing);
105
106 // create pjpgTransaction object
107 $my_orderid = $params['invoiceID'];
108
109 $expiry_string = sprintf('%04d%02d', $params['year'], $params['month']);
110
111 $txnArray = array(
112 'type' => 'purchase',
113 'order_id' => $my_orderid,
114 'amount' => sprintf('%01.2f', $params['amount']),
115 'pan' => $params['credit_card_number'],
116 'expdate' => $expiry_string,
117 'crypt_type' => '7',
118 'cust_id' => $params['contact_id'],
119 );
120
121 // Allow further manipulation of params via custom hooks
122 CRM_Utils_Hook::alterPaymentProcessorParams($this, $params, $txnArray);
123
124 $pjpgTxn = new pjpgTransaction($txnArray);
125
126 // set customer info (level 3 data) for the transaction
127 $pjpgTxn->setCustInfo($pjpgCustInfo);
128
129
130 // empty installments convert to 999 because PayJunction do not allow open end donation
131 if ($params['installments'] == "") {
132 $params['installments'] = "999";
133 }
134
135 // create recurring object
136 if ($params['is_recur'] == TRUE && $params['installments'] > 1) {
137 // schedule start date as today
138 // format: YYYY-MM-DD
139 $params['dc_schedule_start'] = date("Y-m-d");
140
141 // Recur Variables
142 $dc_schedule_create = $params['is_recur'];
143 $recurUnit = $params['frequency_unit'];
144 $recurInterval = $params['frequency_interval'];
145 $dc_schedule_start = $params['dc_schedule_start'];
146
147 // next payment in moneris required format
148 $startDate = date("Y/m/d", $next);
149
150 $numRecurs = $params['installments'];
151
152 $recurArray = array(
153 'dc_schedule_create' => $dc_schedule_create,
154 // (day | week | month)
155 'recur_unit' => $recurUnit,
156 // yyyy/mm/dd
157 'start_date' => $startDate,
158 'num_recurs' => $numRecurs,
159 'start_now' => 'false',
160 'period' => $recurInterval,
161 'dc_schedule_start' => $dc_schedule_start,
162 'amount' => sprintf('%01.2f', $params['amount']),
163 );
164
165 $pjpgRecur = new pjpgRecur($recurArray);
166
167 $pjpgTxn->setRecur($pjpgRecur);
168 }
169
170 // create a pjpgRequest object passing the transaction object
171 $pjpgRequest = new pjpgRequest($pjpgTxn);
172
173 $pjpgHttpPost = new pjpgHttpsPost($pjpgRequest);
174
175 // get an pjpgResponse object
176 $pjpgResponse = $pjpgHttpPost->getPJpgResponse();
177
178 if (self::isError($pjpgResponse)) {
179 return self::error($pjpgResponse);
180 }
181
182 /* Check for application errors */
183
184 $result = self::checkResult($pjpgResponse);
185 if (is_a($result, 'CRM_Core_Error')) {
186 return $result;
187 }
188
189 // Success
190 $params['trxn_result_code'] = $pjpgResponse['dc_response_code'];
191 $params['trxn_id'] = $pjpgResponse['dc_transaction_id'];
192 $params['gross_amount'] = $params['amount'];
193
194 return $params;
195 }
196 // end function doDirectPayment
197
198
199 /*
200 * This function checks the PayJunction response code
201 */
202 /**
203 * @param $response
204 *
205 * @return bool
206 */
207 function isError(&$response) {
208 $responseCode = $response['dc_response_code'];
209
210 if ($responseCode == "00" || $responseCode == "85") {
211 return FALSE;
212 }
213 else {
214 return TRUE;
215 }
216 }
217
218
219 // ignore for now, more elaborate error handling later.
220 /**
221 * @param $response
222 *
223 * @return mixed
224 */
225 function &checkResult(&$response) {
226 return $response;
227 }
228
229 /**
230 * Get the value of a field if set
231 *
232 * @param string $field the field
233 *
234 * @return mixed value of the field, or empty string if the field is
235 * not set
236 */
237 function _getParam($field) {
238 if (isset($this->_params[$field])) {
239 return $this->_params[$field];
240 }
241 else {
242 return '';
243 }
244 }
245
246 /**
247 * @param null $error
248 *
249 * @return object
250 */
251 function &error($error = NULL) {
252 $e = CRM_Core_Error::singleton();
253 if ($error) {
254 $e->push($error['dc_response_code'],
255 0, NULL,
256 $error['dc_response_message']
257 );
258 }
259 else {
260 $e->push(9001, 0, NULL, "Unknown System Error.");
261 }
262 return $e;
263 }
264
265 /**
266 * Set a field to the specified value. Value must be a scalar (int,
267 * float, string, or boolean)
268 *
269 * @param string $field
270 * @param mixed $value
271 *
272 * @return bool false if value is not a scalar, true if successful
273 */
274 function _setParam($field, $value) {
275 if (!is_scalar($value)) {
276 return FALSE;
277 }
278 else {
279 $this->_params[$field] = $value;
280 }
281 }
282
283 /**
284 * This function checks to see if we have the right config values
285 *
286 * @return string the error message if any
287 * @public
288 */
289 function checkConfig() {
290 $error = array();
291 if (empty($this->_paymentProcessor['user_name'])) {
292 $error[] = ts('Username is not set for this payment processor');
293 }
294
295 if (empty($this->_paymentProcessor['password'])) {
296 $error[] = ts('Password is not set for this payment processor');
297 }
298
299 if (empty($this->_paymentProcessor['url_site'])) {
300 $error[] = ts('Site URL is not set for this payment processor');
301 }
302
303 if (!empty($error)) {
304 return implode('<p>', $error);
305 }
306 else {
307 return NULL;
308 }
309 }
310 }
311 // end class CRM_Core_Payment_PayJunction
312