Merge pull request #15321 from yashodha/dev_1065
[civicrm-core.git] / CRM / Admin / Form / PaymentProcessor.php
CommitLineData
6a488035
TO
1<?php
2/*
3 +--------------------------------------------------------------------+
fee14197 4 | CiviCRM version 5 |
6a488035 5 +--------------------------------------------------------------------+
6b83d5bd 6 | Copyright CiviCRM LLC (c) 2004-2019 |
6a488035
TO
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 GNU Affero General Public License |
12 | Version 3, 19 November 2007 and the CiviCRM Licensing Exception. |
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 GNU Affero General Public License for more details. |
18 | |
19 | You should have received a copy of the GNU 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 | GNU Affero General Public License or the licensing of CiviCRM, |
24 | see the CiviCRM license FAQ at http://civicrm.org/licensing |
25 +--------------------------------------------------------------------+
d25dd0ee 26 */
6a488035
TO
27
28/**
29 *
30 * @package CRM
6b83d5bd 31 * @copyright CiviCRM LLC (c) 2004-2019
6a488035
TO
32 */
33
34/**
ce064e4f 35 * This class generates form components for Payment Processor.
6a488035
TO
36 */
37class CRM_Admin_Form_PaymentProcessor extends CRM_Admin_Form {
38 protected $_id = NULL;
39
40 protected $_testID = NULL;
41
42 protected $_fields = NULL;
43
8461467c
MW
44 protected $_paymentProcessorDAO;
45
46 /**
62d3ee27
SL
47 * @var int
48 * Payment processor Type ID
8461467c
MW
49 */
50 protected $_paymentProcessorType;
8ef12e64 51
1d2a585a 52 /**
b30c9316 53 * Get the name of the base entity being edited.
1d2a585a 54 *
55 * @return string
1d2a585a 56 */
57 public function getDefaultEntity() {
58 return 'PaymentProcessor';
59 }
60
00be9182 61 public function preProcess() {
6a488035
TO
62 parent::preProcess();
63
6a488035 64 if ($this->_id) {
8461467c
MW
65 $this->_paymentProcessorType = CRM_Utils_Request::retrieve('pp', 'String', $this, FALSE, NULL);
66 if (!$this->_paymentProcessorType) {
67 $this->_paymentProcessorType = CRM_Core_DAO::getFieldValue('CRM_Financial_DAO_PaymentProcessor',
6a488035
TO
68 $this->_id,
69 'payment_processor_type_id'
70 );
71 }
8461467c 72 $this->set('pp', $this->_paymentProcessorType);
6a488035
TO
73 }
74 else {
8461467c 75 $this->_paymentProcessorType = CRM_Utils_Request::retrieve('pp', 'String', $this, TRUE, NULL);
6a488035
TO
76 }
77
8461467c 78 $this->assign('ppType', $this->_paymentProcessorType);
481a74f4 79 $ppTypeName = CRM_Core_DAO::getFieldValue('CRM_Financial_DAO_PaymentProcessorType',
8461467c 80 $this->_paymentProcessorType,
6a488035
TO
81 'name'
82 );
481a74f4 83 $this->assign('ppTypeName', $ppTypeName);
6a488035 84
8461467c
MW
85 $this->_paymentProcessorDAO = new CRM_Financial_DAO_PaymentProcessorType();
86 $this->_paymentProcessorDAO->id = $this->_paymentProcessorType;
6a488035 87
8461467c 88 $this->_paymentProcessorDAO->find(TRUE);
6a488035
TO
89
90 if ($this->_id) {
91 $refreshURL = CRM_Utils_System::url('civicrm/admin/paymentProcessor',
92 "reset=1&action=update&id={$this->_id}",
93 FALSE, NULL, FALSE
94 );
95 }
96 else {
97 $refreshURL = CRM_Utils_System::url('civicrm/admin/paymentProcessor',
98 "reset=1&action=add",
99 FALSE, NULL, FALSE
100 );
101 }
102
103 //CRM-4129
104 $destination = CRM_Utils_Request::retrieve('civicrmDestination', 'String', $this);
105 if ($destination) {
106 $destination = urlencode($destination);
107 $refreshURL .= "&civicrmDestination=$destination";
108 }
109
3eecd5bc 110 $this->refreshURL = $refreshURL;
6a488035
TO
111 $this->assign('refreshURL', $refreshURL);
112
8461467c 113 $this->assign('is_recur', $this->_paymentProcessorDAO->is_recur);
6a488035 114
be2fb01f
CW
115 $this->_fields = [
116 [
6a488035 117 'name' => 'user_name',
8461467c 118 'label' => $this->_paymentProcessorDAO->user_name_label,
be2fb01f
CW
119 ],
120 [
6a488035 121 'name' => 'password',
8461467c 122 'label' => $this->_paymentProcessorDAO->password_label,
be2fb01f
CW
123 ],
124 [
6a488035 125 'name' => 'signature',
8461467c 126 'label' => $this->_paymentProcessorDAO->signature_label,
be2fb01f
CW
127 ],
128 [
6a488035 129 'name' => 'subject',
8461467c 130 'label' => $this->_paymentProcessorDAO->subject_label,
be2fb01f
CW
131 ],
132 [
6a488035
TO
133 'name' => 'url_site',
134 'label' => ts('Site URL'),
135 'rule' => 'url',
136 'msg' => ts('Enter a valid URL'),
be2fb01f
CW
137 ],
138 ];
6a488035 139
8461467c 140 if ($this->_paymentProcessorDAO->is_recur) {
be2fb01f 141 $this->_fields[] = [
6a488035
TO
142 'name' => 'url_recur',
143 'label' => ts('Recurring Payments URL'),
144 'rule' => 'url',
145 'msg' => ts('Enter a valid URL'),
be2fb01f 146 ];
6a488035
TO
147 }
148
8461467c 149 if (!empty($this->_paymentProcessorDAO->url_button_default)) {
be2fb01f 150 $this->_fields[] = [
6a488035
TO
151 'name' => 'url_button',
152 'label' => ts('Button URL'),
153 'rule' => 'url',
154 'msg' => ts('Enter a valid URL'),
be2fb01f 155 ];
6a488035
TO
156 }
157
8461467c 158 if (!empty($this->_paymentProcessorDAO->url_api_default)) {
be2fb01f 159 $this->_fields[] = [
6a488035
TO
160 'name' => 'url_api',
161 'label' => ts('API URL'),
162 'rule' => 'url',
163 'msg' => ts('Enter a valid URL'),
be2fb01f 164 ];
6a488035
TO
165 }
166 }
167
168 /**
eceb18cc 169 * Build the form object.
6a488035 170 *
fd31fa4c 171 * @param bool $check
6a488035
TO
172 */
173 public function buildQuickForm($check = FALSE) {
174 parent::buildQuickForm();
175
176 if ($this->_action & CRM_Core_Action::DELETE) {
177 return;
178 }
179
180 $attributes = CRM_Core_DAO::getAttribute('CRM_Financial_DAO_PaymentProcessor');
181
182 $this->add('text', 'name', ts('Name'),
183 $attributes['name'], TRUE
184 );
185
be2fb01f 186 $this->addRule('name', ts('Name already exists in Database.'), 'objectExists', [
0d48f1cc
TO
187 'CRM_Financial_DAO_PaymentProcessor',
188 $this->_id,
189 'name',
190 CRM_Core_Config::domainID(),
191 ]);
6a488035
TO
192
193 $this->add('text', 'description', ts('Description'),
194 $attributes['description']
195 );
196
8461467c
MW
197 $this->add('select',
198 'payment_processor_type_id',
199 ts('Payment Processor Type'),
200 CRM_Financial_BAO_PaymentProcessor::buildOptions('payment_processor_type_id'),
201 TRUE,
be2fb01f 202 ['onchange' => "reload(true)"]
6a488035
TO
203 );
204
205 // Financial Account of account type asset CRM-11515
f743a6eb 206 $accountType = CRM_Core_PseudoConstant::accountOptionValues('financial_account_type', NULL, " AND v.name = 'Asset' ");
6a488035
TO
207 $financialAccount = CRM_Contribute_PseudoConstant::financialAccount(NULL, key($accountType));
208 if ($fcount = count($financialAccount)) {
209 $this->assign('financialAccount', $fcount);
210 }
8ef12e64 211 $this->add('select', 'financial_account_id', ts('Financial Account'),
be2fb01f 212 ['' => ts('- select -')] + $financialAccount,
02fc859b 213 TRUE
6a488035 214 );
b7e7f943 215 $this->addSelect('payment_instrument_id',
be2fb01f 216 [
b7e7f943 217 'entity' => 'contribution',
218 'label' => ts('Payment Method'),
219 'placeholder' => NULL,
be2fb01f 220 ]
b7e7f943 221 );
222
6a488035
TO
223 // is this processor active ?
224 $this->add('checkbox', 'is_active', ts('Is this Payment Processor active?'));
225 $this->add('checkbox', 'is_default', ts('Is this Payment Processor the default?'));
cb5962bd 226 $creditCardTypes = CRM_Contribute_PseudoConstant::creditCard();
660ef5f6 227 $this->addCheckBox('accept_credit_cards', ts('Accepted Credit Card Type(s)'),
cb5962bd 228 $creditCardTypes, NULL, NULL, NULL, NULL, '&nbsp;&nbsp;&nbsp;');
6a488035
TO
229 foreach ($this->_fields as $field) {
230 if (empty($field['label'])) {
231 continue;
232 }
233
be2fb01f 234 $this->addField($field['name'], ['label' => $field['label']]);
1d2a585a 235
be2fb01f 236 $fieldSpec = civicrm_api3($this->getDefaultEntity(), 'getfield', [
1d2a585a 237 'name' => $field['name'],
238 'action' => 'create',
be2fb01f 239 ]);
1d2a585a 240 $this->add($fieldSpec['values']['html']['type'], "test_{$field['name']}",
6a488035
TO
241 $field['label'], $attributes[$field['name']]
242 );
a7488080 243 if (!empty($field['rule'])) {
6a488035
TO
244 $this->addRule($field['name'], $field['msg'], $field['rule']);
245 $this->addRule("test_{$field['name']}", $field['msg'], $field['rule']);
246 }
247 }
248
be2fb01f 249 $this->addFormRule(['CRM_Admin_Form_PaymentProcessor', 'formRule']);
6a488035
TO
250 }
251
e0ef6999
EM
252 /**
253 * @param $fields
254 *
255 * @return array|bool
256 */
00be9182 257 public static function formRule($fields) {
6a488035
TO
258
259 // make sure that at least one of live or test is present
260 // and we have at least name and url_site
261 // would be good to make this processor specific
be2fb01f 262 $errors = [];
6a488035
TO
263
264 if (!(self::checkSection($fields, $errors) ||
353ffa53
TO
265 self::checkSection($fields, $errors, 'test')
266 )
267 ) {
6a488035
TO
268 $errors['_qf_default'] = ts('You must have at least the test or live section filled');
269 }
270
271 if (!empty($errors)) {
272 return $errors;
273 }
274
275 return empty($errors) ? TRUE : $errors;
276 }
277
e0ef6999
EM
278 /**
279 * @param $fields
280 * @param $errors
281 * @param null $section
282 *
283 * @return bool
284 */
00be9182 285 public static function checkSection(&$fields, &$errors, $section = NULL) {
be2fb01f 286 $names = ['user_name'];
6a488035
TO
287
288 $present = FALSE;
289 $allPresent = TRUE;
290 foreach ($names as $name) {
291 if ($section) {
292 $name = "{$section}_$name";
293 }
294 if (!empty($fields[$name])) {
295 $present = TRUE;
296 }
297 else {
298 $allPresent = FALSE;
299 }
300 }
301
302 if ($present) {
303 if (!$allPresent) {
304 $errors['_qf_default'] = ts('You must have at least the user_name specified');
305 }
306 }
307 return $present;
308 }
309
e0ef6999
EM
310 /**
311 * @return array
312 */
00be9182 313 public function setDefaultValues() {
be2fb01f 314 $defaults = [];
6d5de837 315
6a488035
TO
316 if (!$this->_id) {
317 $defaults['is_active'] = $defaults['is_default'] = 1;
8461467c
MW
318 $defaults['url_site'] = $this->_paymentProcessorDAO->url_site_default;
319 $defaults['url_api'] = $this->_paymentProcessorDAO->url_api_default;
320 $defaults['url_recur'] = $this->_paymentProcessorDAO->url_recur_default;
321 $defaults['url_button'] = $this->_paymentProcessorDAO->url_button_default;
322 $defaults['test_url_site'] = $this->_paymentProcessorDAO->url_site_test_default;
323 $defaults['test_url_api'] = $this->_paymentProcessorDAO->url_api_test_default;
324 $defaults['test_url_recur'] = $this->_paymentProcessorDAO->url_recur_test_default;
325 $defaults['test_url_button'] = $this->_paymentProcessorDAO->url_button_test_default;
326 $defaults['payment_instrument_id'] = $this->_paymentProcessorDAO->payment_instrument_id;
6d5de837 327 // When user changes payment processor type, it is passed in via $this->_ppType so update defaults array.
8461467c
MW
328 if ($this->_paymentProcessorType) {
329 $defaults['payment_processor_type_id'] = $this->_paymentProcessorType;
6d5de837 330 }
8563c1ce 331 $defaults['financial_account_id'] = CRM_Financial_BAO_PaymentProcessor::getDefaultFinancialAccountID();
6a488035
TO
332 return $defaults;
333 }
334 $domainID = CRM_Core_Config::domainID();
335
481a74f4 336 $dao = new CRM_Financial_DAO_PaymentProcessor();
353ffa53 337 $dao->id = $this->_id;
6a488035
TO
338 $dao->domain_id = $domainID;
339 if (!$dao->find(TRUE)) {
340 return $defaults;
341 }
342
343 CRM_Core_DAO::storeValues($dao, $defaults);
8461467c
MW
344 // If payment processor ID does not exist, $paymentProcessorName will be FALSE
345 $paymentProcessorName = CRM_Core_PseudoConstant::getName('CRM_Financial_BAO_PaymentProcessor', 'payment_processor_type_id', $this->_paymentProcessorType);
346 if ($this->_paymentProcessorType && $paymentProcessorName) {
347 // When user changes payment processor type, it is passed in via $this->_ppType so update defaults array.
348 $defaults['payment_processor_type_id'] = $this->_paymentProcessorType;
6d5de837 349 }
8461467c
MW
350 else {
351 CRM_Core_Session::setStatus('Payment Processor Type (ID=' . $this->_paymentProcessorType . ') not found. Did you disable the payment processor extension?', 'Missing Payment Processor', 'alert');
352 }
353
c294dbbc 354 $cards = json_decode(CRM_Core_DAO::getFieldValue('CRM_Financial_DAO_PaymentProcessor',
cb5962bd
SL
355 $this->_id,
356 'accepted_credit_cards'
357 ), TRUE);
be2fb01f 358 $acceptedCards = [];
27b252af
SL
359 if (!empty($cards)) {
360 foreach ($cards as $card => $val) {
361 $acceptedCards[$card] = 1;
362 }
c294dbbc
SL
363 }
364 $defaults['accept_credit_cards'] = $acceptedCards;
cb5962bd 365 unset($defaults['accepted_credit_cards']);
6a488035
TO
366 // now get testID
367 $testDAO = new CRM_Financial_DAO_PaymentProcessor();
353ffa53
TO
368 $testDAO->name = $dao->name;
369 $testDAO->is_test = 1;
6a488035
TO
370 $testDAO->domain_id = $domainID;
371 if ($testDAO->find(TRUE)) {
372 $this->_testID = $testDAO->id;
373
374 foreach ($this->_fields as $field) {
375 $testName = "test_{$field['name']}";
376 $defaults[$testName] = $testDAO->{$field['name']};
377 }
378 }
74afdc40 379 $defaults['financial_account_id'] = CRM_Contribute_PseudoConstant::getRelationalFinancialAccount($dao->id, NULL, 'civicrm_payment_processor');
6a488035
TO
380
381 return $defaults;
382 }
383
384 /**
eceb18cc 385 * Process the form submission.
6a488035
TO
386 */
387 public function postProcess() {
6a488035
TO
388
389 if ($this->_action & CRM_Core_Action::DELETE) {
390 CRM_Financial_BAO_PaymentProcessor::del($this->_id);
391 CRM_Core_Session::setStatus("", ts('Payment Processor Deleted.'), "success");
28a04ea9 392 return NULL;
6a488035
TO
393 }
394
395 $values = $this->controller->exportValues($this->_name);
396 $domainID = CRM_Core_Config::domainID();
397
a7488080 398 if (!empty($values['is_default'])) {
6a488035 399 $query = "UPDATE civicrm_payment_processor SET is_default = 0 WHERE domain_id = $domainID";
33621c4f 400 CRM_Core_DAO::executeQuery($query);
6a488035
TO
401 }
402
8461467c
MW
403 if ($this->_paymentProcessorType !== $values['payment_processor_type_id']) {
404 // If we changed the payment processor type, need to update the object as well
405 $this->_paymentProcessorType = $values['payment_processor_type_id'];
406 $this->_paymentProcessorDAO = new CRM_Financial_DAO_PaymentProcessorType();
407 $this->_paymentProcessorDAO->id = $values['payment_processor_type_id'];
408 $this->_paymentProcessorDAO->find(TRUE);
409 }
6a488035
TO
410 $this->updatePaymentProcessor($values, $domainID, FALSE);
411 $this->updatePaymentProcessor($values, $domainID, TRUE);
3eecd5bc 412
be2fb01f 413 $processor = civicrm_api3('payment_processor', 'getsingle', ['name' => $values['name'], 'is_test' => 0]);
3eecd5bc
MW
414 $errors = Civi\Payment\System::singleton()->checkProcessorConfig($processor);
415 if ($errors) {
416 CRM_Core_Session::setStatus($errors, 'Payment processor configuration invalid', 'error');
417 Civi::log()->error('Payment processor configuration invalid: ' . $errors);
418 CRM_Core_Session::singleton()->pushUserContext($this->refreshURL);
419 }
420 else {
be2fb01f 421 CRM_Core_Session::setStatus(ts('Payment processor %1 has been saved.', [1 => "<em>{$values['name']}</em>"]), ts('Saved'), 'success');
3eecd5bc 422 }
6a488035
TO
423 }
424
425 /**
eceb18cc 426 * Save a payment processor.
6a488035 427 *
ce064e4f 428 * @param array $values
100fef9d 429 * @param int $domainID
ce064e4f 430 * @param bool $test
6a488035 431 */
00be9182 432 public function updatePaymentProcessor(&$values, $domainID, $test) {
be725500 433 if ($test) {
be2fb01f 434 foreach (['user_name', 'password', 'signature', 'url_site', 'url_recur', 'url_api', 'url_button', 'subject'] as $field) {
be725500 435 $values[$field] = empty($values["test_{$field}"]) ? CRM_Utils_Array::value($field, $values) : $values["test_{$field}"];
436 }
437 }
c294dbbc 438 if (!empty($values['accept_credit_cards'])) {
be2fb01f 439 $creditCards = [];
c294dbbc
SL
440 $accptedCards = array_keys($values['accept_credit_cards']);
441 $creditCardTypes = CRM_Contribute_PseudoConstant::creditCard();
442 foreach ($creditCardTypes as $type => $val) {
443 if (in_array($type, $accptedCards)) {
444 $creditCards[$type] = $creditCardTypes[$type];
445 }
446 }
447 $creditCards = json_encode($creditCards);
448 }
449 else {
450 $creditCards = "NULL";
451 }
62d3ee27 452 $params = array_merge([
b7e7f943 453 'id' => $test ? $this->_testID : $this->_id,
454 'domain_id' => $domainID,
455 'is_test' => $test,
456 'is_active' => 0,
457 'is_default' => 0,
8461467c
MW
458 'is_recur' => $this->_paymentProcessorDAO->is_recur,
459 'billing_mode' => $this->_paymentProcessorDAO->billing_mode,
460 'class_name' => $this->_paymentProcessorDAO->class_name,
461 'payment_type' => $this->_paymentProcessorDAO->payment_type,
462 'payment_instrument_id' => $this->_paymentProcessorDAO->payment_instrument_id,
21dfd5f5 463 'financial_account_id' => $values['financial_account_id'],
cb5962bd 464 'accepted_credit_cards' => $creditCards,
be2fb01f 465 ], $values);
b7e7f943 466
467 civicrm_api3('PaymentProcessor', 'create', $params);
6a488035 468 }
96025800 469
6a488035 470}