3 +--------------------------------------------------------------------+
4 | CiviCRM version 4.5 |
5 +--------------------------------------------------------------------+
6 | Copyright CiviCRM LLC (c) 2004-2014 |
7 +--------------------------------------------------------------------+
8 | This file is a part of CiviCRM. |
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. |
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. |
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 +--------------------------------------------------------------------+
31 * @copyright CiviCRM LLC (c) 2004-2014
35 class CRM_Core_Payment_Form
{
38 * Add payment fields are depending on payment type
40 * @param int $type eg CRM_Core_Payment::PAYMENT_TYPE_DIRECT_DEBIT
41 * @param CRM_Core_Form $form
43 static public function setPaymentFieldsByType($type, &$form) {
44 if ($type & CRM_Core_Payment
::PAYMENT_TYPE_DIRECT_DEBIT
) {
45 CRM_Core_Payment_Form
::setDirectDebitFields($form);
48 CRM_Core_Payment_Form
::setCreditCardFields($form);
53 * create all common fields needed for a credit card or direct debit transaction
60 static protected function _setPaymentFields(&$form) {
61 $bltID = $form->_bltID
;
63 $form->_paymentFields
['billing_first_name'] = array(
65 'name' => 'billing_first_name',
66 'title' => ts('Billing First Name'),
68 'attributes' => array('size' => 30, 'maxlength' => 60, 'autocomplete' => 'off'),
69 'is_required' => TRUE,
72 $form->_paymentFields
['billing_middle_name'] = array(
74 'name' => 'billing_middle_name',
75 'title' => ts('Billing Middle Name'),
77 'attributes' => array('size' => 30, 'maxlength' => 60, 'autocomplete' => 'off'),
78 'is_required' => FALSE,
81 $form->_paymentFields
['billing_last_name'] = array(
83 'name' => 'billing_last_name',
84 'title' => ts('Billing Last Name'),
86 'attributes' => array('size' => 30, 'maxlength' => 60, 'autocomplete' => 'off'),
87 'is_required' => TRUE,
90 $form->_paymentFields
["billing_street_address-{$bltID}"] = array(
92 'name' => "billing_street_address-{$bltID}",
93 'title' => ts('Street Address'),
95 'attributes' => array('size' => 30, 'maxlength' => 60, 'autocomplete' => 'off'),
96 'is_required' => TRUE,
99 $form->_paymentFields
["billing_city-{$bltID}"] = array(
100 'htmlType' => 'text',
101 'name' => "billing_city-{$bltID}",
102 'title' => ts('City'),
104 'attributes' => array('size' => 30, 'maxlength' => 60, 'autocomplete' => 'off'),
105 'is_required' => TRUE,
108 $form->_paymentFields
["billing_state_province_id-{$bltID}"] = array(
109 'htmlType' => 'chainSelect',
110 'title' => ts('State/Province'),
111 'name' => "billing_state_province_id-{$bltID}",
113 'is_required' => TRUE,
116 $form->_paymentFields
["billing_postal_code-{$bltID}"] = array(
117 'htmlType' => 'text',
118 'name' => "billing_postal_code-{$bltID}",
119 'title' => ts('Postal Code'),
121 'attributes' => array('size' => 30, 'maxlength' => 60, 'autocomplete' => 'off'),
122 'is_required' => TRUE,
125 $form->_paymentFields
["billing_country_id-{$bltID}"] = array(
126 'htmlType' => 'select',
127 'name' => "billing_country_id-{$bltID}",
128 'title' => ts('Country'),
130 'attributes' => array(
131 '' => ts('- select -')) +
132 CRM_Core_PseudoConstant
::country(),
133 'is_required' => TRUE,
135 //CRM-15509 working towards giving control over billing fields to payment processors. For now removing tpl hard-coding
136 $smarty = CRM_Core_Smarty
::singleton();
137 $smarty->assign('billingDetailsFields', array(
138 'billing_first_name',
139 'billing_middle_name',
141 "billing_street_address-{$bltID}",
142 "billing_city-{$bltID}",
143 "billing_country_id-{$bltID}",
144 "billing_state_province_id-{$bltID}",
145 "billing_postal_code-{$bltID}",
150 * create all fields needed for a credit card transaction
152 * @param CRM_Core_Form $form
157 static function setCreditCardFields(&$form) {
158 CRM_Core_Payment_Form
::_setPaymentFields($form);
160 $form->_paymentFields
['credit_card_number'] = array(
161 'htmlType' => 'text',
162 'name' => 'credit_card_number',
163 'title' => ts('Card Number'),
165 'attributes' => array('size' => 20, 'maxlength' => 20, 'autocomplete' => 'off'),
166 'is_required' => TRUE,
169 $form->_paymentFields
['cvv2'] = array(
170 'htmlType' => 'text',
172 'title' => ts('Security Code'),
174 'attributes' => array('size' => 5, 'maxlength' => 10, 'autocomplete' => 'off'),
175 'is_required' => CRM_Core_BAO_Setting
::getItem(CRM_Core_BAO_Setting
::CONTRIBUTE_PREFERENCES_NAME
,
176 'cvv_backoffice_required',
182 $form->_paymentFields
['credit_card_exp_date'] = array(
183 'htmlType' => 'date',
184 'name' => 'credit_card_exp_date',
185 'title' => ts('Expiration Date'),
187 'attributes' => CRM_Core_SelectValues
::date('creditCard'),
188 'is_required' => TRUE,
191 $creditCardType = array('' => ts('- select -')) + CRM_Contribute_PseudoConstant
::creditCard();
192 $form->_paymentFields
['credit_card_type'] = array(
193 'htmlType' => 'select',
194 'name' => 'credit_card_type',
195 'title' => ts('Card Type'),
197 'attributes' => $creditCardType,
198 'is_required' => FALSE,
200 //CRM-15509 this is probably a temporary resting place for these form assignments but we are working towards putting this
201 // in an option group & having php / payment processors define the billing form rather than the tpl
202 $smarty = CRM_Core_Smarty
::singleton();
203 $smarty->assign('paymentTypeName', 'credit_card');
204 $smarty->assign('paymentTypeLabel', ts('Credit Card Information'));
205 $smarty->assign('paymentFields', array(
207 'credit_card_number',
209 'credit_card_exp_date',
214 * @param CRM_Core_Form $form
215 * @param bool $useRequired
217 static function addCommonFields(&$form, $useRequired) {
218 foreach ($form->_paymentFields
as $name => $field) {
219 if (!empty($field['cc_field'])) {
220 if ($field['htmlType'] == 'chainSelect') {
221 $form->addChainSelect($field['name'], array('required' => $useRequired && $field['is_required']));
224 $form->add($field['htmlType'],
227 $field['attributes'],
228 $useRequired ?
$field['is_required'] : FALSE
236 * create all fields needed for direct debit transaction
243 static function setDirectDebitFields(&$form) {
244 CRM_Core_Payment_Form
::_setPaymentFields($form);
246 $form->_paymentFields
['account_holder'] = array(
247 'htmlType' => 'text',
248 'name' => 'account_holder',
249 'title' => ts('Account Holder'),
251 'attributes' => array('size' => 20, 'maxlength' => 34, 'autocomplete' => 'on'),
252 'is_required' => TRUE,
255 //e.g. IBAN can have maxlength of 34 digits
256 $form->_paymentFields
['bank_account_number'] = array(
257 'htmlType' => 'text',
258 'name' => 'bank_account_number',
259 'title' => ts('Bank Account Number'),
261 'attributes' => array('size' => 20, 'maxlength' => 34, 'autocomplete' => 'off'),
262 'is_required' => TRUE,
265 //e.g. SWIFT-BIC can have maxlength of 11 digits
266 $form->_paymentFields
['bank_identification_number'] = array(
267 'htmlType' => 'text',
268 'name' => 'bank_identification_number',
269 'title' => ts('Bank Identification Number'),
271 'attributes' => array('size' => 20, 'maxlength' => 11, 'autocomplete' => 'off'),
272 'is_required' => TRUE,
275 $form->_paymentFields
['bank_name'] = array(
276 'htmlType' => 'text',
277 'name' => 'bank_name',
278 'title' => ts('Bank Name'),
280 'attributes' => array('size' => 20, 'maxlength' => 64, 'autocomplete' => 'off'),
281 'is_required' => TRUE,
283 //CRM-15509 this is probably a temporary resting place for these form assignments but we are working towards putting this
284 // in an option group & having php / payment processors define the billing form rather than the tpl
285 $smarty = CRM_Core_Smarty
::singleton();
286 // replace these payment type names with an option group - moving name & label assumptions out of the tpl is a step towards that
287 $smarty->assign('paymentTypeName', 'direct_debit');
288 $smarty->assign('paymentTypeLabel', ts('Direct Debit Information'));
289 $smarty->assign('paymentFields', array(
291 'bank_account_number',
292 'bank_identification_number',
298 * Function to add all the credit card fields
301 * @param bool $useRequired
306 static function buildCreditCard(&$form, $useRequired = FALSE) {
307 if ($form->_paymentProcessor
['billing_mode'] & CRM_Core_Payment
::BILLING_MODE_FORM
) {
308 self
::setCreditCardFields($form);
309 self
::addCommonFields($form, $useRequired);
311 $form->addRule('cvv2',
312 ts('Please enter a valid value for your card security code. This is usually the last 3-4 digits on the card\'s signature panel.'),
316 $form->addRule('credit_card_exp_date',
317 ts('Card expiration date cannot be a past date.'),
323 if ($form->_paymentProcessor
['billing_mode'] & CRM_Core_Payment
::BILLING_MODE_BUTTON
) {
324 $form->_expressButtonName
= $form->getButtonName('upload', 'express');
325 $form->assign('expressButtonName', $form->_expressButtonName
);
327 $form->_expressButtonName
,
328 $form->_paymentProcessor
['url_button'],
329 array('class' => 'crm-form-submit')
335 * The credit card pseudo constant results only the CC label, not the key ID
336 * So we normalize the name to use it as a CSS class.
338 static function getCreditCardCSSNames() {
339 $creditCardTypes = array();
340 foreach (CRM_Contribute_PseudoConstant
::creditCard() as $key => $name) {
341 // Replace anything not css-friendly by an underscore
342 // Non-latin names will not like this, but so many things are wrong with
343 // the credit-card type configurations already.
344 $key = str_replace(' ', '', $key);
345 $key = preg_replace('/[^a-zA-Z0-9]/', '_', $key);
346 $key = strtolower($key);
347 $creditCardTypes[$key] = $name;
349 return $creditCardTypes;
353 * Function to add all the direct debit fields
356 * @param bool $useRequired
360 static function buildDirectDebit(&$form, $useRequired = FALSE) {
361 if ($form->_paymentProcessor
['billing_mode'] & CRM_Core_Payment
::BILLING_MODE_FORM
) {
362 self
::setDirectDebitFields($form);
363 self
::addCommonFields($form, $useRequired);
365 $form->addRule('bank_identification_number',
366 ts('Please enter a valid Bank Identification Number (value must not contain punctuation characters).'),
370 $form->addRule('bank_account_number',
371 ts('Please enter a valid Bank Account Number (value must not contain punctuation characters).'),
376 if ($form->_paymentProcessor
['billing_mode'] & CRM_Core_Payment
::BILLING_MODE_BUTTON
) {
377 $form->_expressButtonName
= $form->getButtonName($form->buttonType(), 'express');
379 $form->_expressButtonName
,
380 $form->_paymentProcessor
['url_button'],
381 array('class' => 'crm-form-submit')
387 * Function to add address block
390 * @param bool $useRequired
395 static function buildAddressBlock(&$form, $useRequired = FALSE) {
396 CRM_Core_Payment_Form
::_setPaymentFields($form);
397 foreach ($form->_paymentFields
as $name => $field) {
398 if (isset($field['cc_field']) &&
401 $form->add($field['htmlType'],
404 $field['attributes'],
405 $useRequired ?
$field['is_required'] : FALSE
410 // also take care of state country widget
411 $stateCountryMap = array(
413 'country' => "billing_country_id-{$form->_bltID}",
414 'state_province' => "billing_state_province_id-{$form->_bltID}",
417 CRM_Core_BAO_Address
::addStateCountryMap($stateCountryMap);
421 * Make sure that credit card number and cvv are valid
422 * Called within the scope of a QF formRule function
424 static function validateCreditCard($values, &$errors) {
425 if (!empty($values['credit_card_type'])) {
426 if (!empty($values['credit_card_number']) &&
427 !CRM_Utils_Rule
::creditCardNumber($values['credit_card_number'], $values['credit_card_type'])
429 $errors['credit_card_number'] = ts('Please enter a valid Card Number');
431 if (!empty($values['cvv2']) &&
432 !CRM_Utils_Rule
::cvv($values['cvv2'], $values['credit_card_type'])
434 $errors['cvv2'] = ts('Please enter a valid Card Verification Number');
437 elseif (!empty($values['credit_card_number'])) {
438 $errors['credit_card_number'] = ts('Please enter a valid Card Number');
443 * function to map address fields
448 * @param bool $reverse
453 static function mapParams($id, &$src, &$dst, $reverse = FALSE) {
457 'first_name' => 'billing_first_name',
458 'middle_name' => 'billing_middle_name',
459 'last_name' => 'billing_last_name',
460 'email' => "email-$id",
461 'street_address' => "billing_street_address-$id",
462 'supplemental_address_1' => "billing_supplemental_address_1-$id",
463 'city' => "billing_city-$id",
464 'state_province' => "billing_state_province-$id",
465 'postal_code' => "billing_postal_code-$id",
466 'country' => "billing_country-$id",
470 foreach ($map as $n => $v) {
472 if (isset($src[$n])) {
477 if (isset($src[$v])) {
485 * function to get the credit card expiration month
486 * The date format for this field should typically be "M Y" (ex: Feb 2011) or "m Y" (02 2011)
494 static function getCreditCardExpirationMonth($src) {
495 if ($month = CRM_Utils_Array
::value('M', $src['credit_card_exp_date'])) {
499 return CRM_Utils_Array
::value('m', $src['credit_card_exp_date']);
503 * function to get the credit card expiration year
504 * The date format for this field should typically be "M Y" (ex: Feb 2011) or "m Y" (02 2011)
505 * This function exists only to make it consistant with getCreditCardExpirationMonth
512 static function getCreditCardExpirationYear($src) {
513 return CRM_Utils_Array
::value('Y', $src['credit_card_exp_date']);