Commit | Line | Data |
---|---|---|
6a488035 TO |
1 | <?php |
2 | /* | |
3 | +--------------------------------------------------------------------+ | |
232624b1 | 4 | | CiviCRM version 4.4 | |
6a488035 TO |
5 | +--------------------------------------------------------------------+ |
6 | | Copyright CiviCRM LLC (c) 2004-2013 | | |
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 | +--------------------------------------------------------------------+ | |
26 | */ | |
27 | ||
28 | /** | |
29 | * | |
30 | * @package CRM | |
31 | * @copyright CiviCRM LLC (c) 2004-2013 | |
32 | * $Id$ | |
33 | * | |
34 | */ | |
35 | class CRM_Core_Payment_Form { | |
36 | ||
37 | /** | |
38 | * Add payment fields are depending on payment type | |
39 | * | |
40 | * @param int $type eg CRM_Core_Payment::PAYMENT_TYPE_DIRECT_DEBIT | |
41 | * @param CRM_Core_Form $form | |
42 | */ | |
43 | static public function setPaymentFieldsByType($type, &$form) { | |
44 | if ($type & CRM_Core_Payment::PAYMENT_TYPE_DIRECT_DEBIT) { | |
45 | CRM_Core_Payment_Form::setDirectDebitFields($form); | |
46 | } | |
47 | else { | |
48 | CRM_Core_Payment_Form::setCreditCardFields($form); | |
49 | } | |
50 | } | |
51 | ||
52 | /** | |
53 | * create all common fields needed for a credit card or direct debit transaction | |
54 | * | |
55 | * @return void | |
56 | * @access protected | |
57 | */ | |
58 | static protected function _setPaymentFields(&$form) { | |
59 | $bltID = $form->_bltID; | |
60 | ||
61 | $form->_paymentFields['billing_first_name'] = array( | |
62 | 'htmlType' => 'text', | |
63 | 'name' => 'billing_first_name', | |
64 | 'title' => ts('Billing First Name'), | |
65 | 'cc_field' => TRUE, | |
66 | 'attributes' => array('size' => 30, 'maxlength' => 60, 'autocomplete' => 'off'), | |
67 | 'is_required' => TRUE, | |
68 | ); | |
69 | ||
70 | $form->_paymentFields['billing_middle_name'] = array( | |
71 | 'htmlType' => 'text', | |
72 | 'name' => 'billing_middle_name', | |
73 | 'title' => ts('Billing Middle Name'), | |
74 | 'cc_field' => TRUE, | |
75 | 'attributes' => array('size' => 30, 'maxlength' => 60, 'autocomplete' => 'off'), | |
76 | 'is_required' => FALSE, | |
77 | ); | |
78 | ||
79 | $form->_paymentFields['billing_last_name'] = array( | |
80 | 'htmlType' => 'text', | |
81 | 'name' => 'billing_last_name', | |
82 | 'title' => ts('Billing Last Name'), | |
83 | 'cc_field' => TRUE, | |
84 | 'attributes' => array('size' => 30, 'maxlength' => 60, 'autocomplete' => 'off'), | |
85 | 'is_required' => TRUE, | |
86 | ); | |
87 | ||
88 | $form->_paymentFields["billing_street_address-{$bltID}"] = array( | |
89 | 'htmlType' => 'text', | |
90 | 'name' => "billing_street_address-{$bltID}", | |
91 | 'title' => ts('Street Address'), | |
92 | 'cc_field' => TRUE, | |
93 | 'attributes' => array('size' => 30, 'maxlength' => 60, 'autocomplete' => 'off'), | |
94 | 'is_required' => TRUE, | |
95 | ); | |
96 | ||
97 | $form->_paymentFields["billing_city-{$bltID}"] = array( | |
98 | 'htmlType' => 'text', | |
99 | 'name' => "billing_city-{$bltID}", | |
100 | 'title' => ts('City'), | |
101 | 'cc_field' => TRUE, | |
102 | 'attributes' => array('size' => 30, 'maxlength' => 60, 'autocomplete' => 'off'), | |
103 | 'is_required' => TRUE, | |
104 | ); | |
105 | ||
106 | $form->_paymentFields["billing_state_province_id-{$bltID}"] = array( | |
107 | 'htmlType' => 'select', | |
108 | 'name' => "billing_state_province_id-{$bltID}", | |
109 | 'title' => ts('State / Province'), | |
110 | 'cc_field' => TRUE, | |
111 | 'attributes' => array( | |
112 | '' => ts('- select -')) + | |
113 | CRM_Core_PseudoConstant::stateProvince(), | |
114 | 'is_required' => self::checkRequiredStateProvince($form), | |
115 | ); | |
116 | ||
117 | $form->_paymentFields["billing_postal_code-{$bltID}"] = array( | |
118 | 'htmlType' => 'text', | |
119 | 'name' => "billing_postal_code-{$bltID}", | |
120 | 'title' => ts('Postal Code'), | |
121 | 'cc_field' => TRUE, | |
122 | 'attributes' => array('size' => 30, 'maxlength' => 60, 'autocomplete' => 'off'), | |
123 | 'is_required' => TRUE, | |
124 | ); | |
125 | ||
126 | $form->_paymentFields["billing_country_id-{$bltID}"] = array( | |
127 | 'htmlType' => 'select', | |
128 | 'name' => "billing_country_id-{$bltID}", | |
129 | 'title' => ts('Country'), | |
130 | 'cc_field' => TRUE, | |
131 | 'attributes' => array( | |
132 | '' => ts('- select -')) + | |
133 | CRM_Core_PseudoConstant::country(), | |
134 | 'is_required' => TRUE, | |
135 | ); | |
136 | } | |
137 | ||
138 | /** | |
139 | * create all fields needed for a credit card transaction | |
140 | * | |
141 | * @return void | |
142 | * @access public | |
143 | */ | |
144 | static function setCreditCardFields(&$form) { | |
145 | CRM_Core_Payment_Form::_setPaymentFields($form); | |
146 | ||
147 | $form->_paymentFields['credit_card_number'] = array( | |
148 | 'htmlType' => 'text', | |
149 | 'name' => 'credit_card_number', | |
150 | 'title' => ts('Card Number'), | |
151 | 'cc_field' => TRUE, | |
152 | 'attributes' => array('size' => 20, 'maxlength' => 20, 'autocomplete' => 'off'), | |
153 | 'is_required' => TRUE, | |
154 | ); | |
155 | ||
156 | $form->_paymentFields['cvv2'] = array( | |
157 | 'htmlType' => 'text', | |
158 | 'name' => 'cvv2', | |
159 | 'title' => ts('Security Code'), | |
160 | 'cc_field' => TRUE, | |
161 | 'attributes' => array('size' => 5, 'maxlength' => 10, 'autocomplete' => 'off'), | |
162 | 'is_required' => CRM_Core_BAO_Setting::getItem(CRM_Core_BAO_Setting::CONTRIBUTE_PREFERENCES_NAME, | |
163 | 'cvv_backoffice_required', | |
164 | NULL | |
165 | ,1 | |
166 | ), | |
167 | ); | |
168 | ||
169 | $form->_paymentFields['credit_card_exp_date'] = array( | |
170 | 'htmlType' => 'date', | |
171 | 'name' => 'credit_card_exp_date', | |
172 | 'title' => ts('Expiration Date'), | |
173 | 'cc_field' => TRUE, | |
174 | 'attributes' => CRM_Core_SelectValues::date('creditCard'), | |
175 | 'is_required' => TRUE, | |
176 | ); | |
177 | ||
178 | $creditCardType = array('' => ts('- select -')) + CRM_Contribute_PseudoConstant::creditCard(); | |
179 | $form->_paymentFields['credit_card_type'] = array( | |
180 | 'htmlType' => 'select', | |
181 | 'name' => 'credit_card_type', | |
182 | 'title' => ts('Card Type'), | |
183 | 'cc_field' => TRUE, | |
184 | 'attributes' => $creditCardType, | |
15c6517d | 185 | 'is_required' => FALSE, |
6a488035 TO |
186 | ); |
187 | } | |
188 | ||
3f3a3ba0 CW |
189 | /** |
190 | * create all fields needed for direct debit transaction | |
6a488035 TO |
191 | * |
192 | * @return void | |
193 | * @access public | |
194 | */ | |
195 | static function setDirectDebitFields(&$form) { | |
196 | CRM_Core_Payment_Form::_setPaymentFields($form); | |
197 | ||
198 | $form->_paymentFields['account_holder'] = array( | |
199 | 'htmlType' => 'text', | |
200 | 'name' => 'account_holder', | |
201 | 'title' => ts('Account Holder'), | |
202 | 'cc_field' => TRUE, | |
203 | 'attributes' => array('size' => 20, 'maxlength' => 34, 'autocomplete' => 'on'), | |
204 | 'is_required' => TRUE, | |
205 | ); | |
206 | ||
207 | //e.g. IBAN can have maxlength of 34 digits | |
208 | $form->_paymentFields['bank_account_number'] = array( | |
209 | 'htmlType' => 'text', | |
210 | 'name' => 'bank_account_number', | |
211 | 'title' => ts('Bank Account Number'), | |
212 | 'cc_field' => TRUE, | |
213 | 'attributes' => array('size' => 20, 'maxlength' => 34, 'autocomplete' => 'off'), | |
214 | 'is_required' => TRUE, | |
215 | ); | |
216 | ||
217 | //e.g. SWIFT-BIC can have maxlength of 11 digits | |
218 | $form->_paymentFields['bank_identification_number'] = array( | |
219 | 'htmlType' => 'text', | |
220 | 'name' => 'bank_identification_number', | |
221 | 'title' => ts('Bank Identification Number'), | |
222 | 'cc_field' => TRUE, | |
223 | 'attributes' => array('size' => 20, 'maxlength' => 11, 'autocomplete' => 'off'), | |
224 | 'is_required' => TRUE, | |
225 | ); | |
226 | ||
227 | $form->_paymentFields['bank_name'] = array( | |
228 | 'htmlType' => 'text', | |
229 | 'name' => 'bank_name', | |
230 | 'title' => ts('Bank Name'), | |
231 | 'cc_field' => TRUE, | |
232 | 'attributes' => array('size' => 20, 'maxlength' => 64, 'autocomplete' => 'off'), | |
233 | 'is_required' => TRUE, | |
234 | ); | |
235 | } | |
236 | ||
237 | /** | |
238 | * Function to add all the credit card fields | |
239 | * | |
15c6517d | 240 | * @return void |
6a488035 TO |
241 | * @access public |
242 | */ | |
243 | static function buildCreditCard(&$form, $useRequired = FALSE) { | |
244 | if ($form->_paymentProcessor['billing_mode'] & CRM_Core_Payment::BILLING_MODE_FORM) { | |
245 | self::setCreditCardFields($form); | |
246 | foreach ($form->_paymentFields as $name => $field) { | |
247 | if (isset($field['cc_field']) && | |
248 | $field['cc_field'] | |
249 | ) { | |
250 | $form->add($field['htmlType'], | |
251 | $field['name'], | |
252 | $field['title'], | |
253 | $field['attributes'], | |
254 | $useRequired ? $field['is_required'] : FALSE | |
255 | ); | |
256 | } | |
257 | } | |
258 | ||
259 | $form->addRule('cvv2', | |
260 | 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.'), | |
261 | 'integer' | |
262 | ); | |
263 | ||
264 | $form->addRule('credit_card_exp_date', | |
8543f7c1 | 265 | ts('Card expiration date cannot be a past date.'), |
6a488035 TO |
266 | 'currentDate', TRUE |
267 | ); | |
268 | ||
269 | // also take care of state country widget | |
270 | $stateCountryMap = array( | |
271 | 1 => array('country' => "billing_country_id-{$form->_bltID}", | |
272 | 'state_province' => "billing_state_province_id-{$form->_bltID}", | |
273 | )); | |
274 | CRM_Core_BAO_Address::addStateCountryMap($stateCountryMap); | |
275 | } | |
276 | ||
277 | if ($form->_paymentProcessor['billing_mode'] & CRM_Core_Payment::BILLING_MODE_BUTTON) { | |
278 | $form->_expressButtonName = $form->getButtonName('upload', 'express'); | |
279 | $form->assign('expressButtonName', $form->_expressButtonName); | |
280 | $form->add('image', | |
281 | $form->_expressButtonName, | |
282 | $form->_paymentProcessor['url_button'], | |
283 | array('class' => 'form-submit') | |
284 | ); | |
285 | } | |
286 | } | |
287 | ||
bef9421f CW |
288 | /** |
289 | * The credit card pseudo constant results only the CC label, not the key ID | |
290 | * So we normalize the name to use it as a CSS class. | |
291 | */ | |
292 | static function getCreditCardCSSNames() { | |
293 | $creditCardTypes = array(); | |
294 | foreach (CRM_Contribute_PseudoConstant::creditCard() as $key => $name) { | |
295 | // Replace anything not css-friendly by an underscore | |
296 | // Non-latin names will not like this, but so many things are wrong with | |
297 | // the credit-card type configurations already. | |
298 | $key = str_replace(' ', '', $key); | |
299 | $key = preg_replace('/[^a-zA-Z0-9]/', '_', $key); | |
300 | $key = strtolower($key); | |
301 | $creditCardTypes[$key] = $name; | |
302 | } | |
303 | return $creditCardTypes; | |
304 | } | |
305 | ||
6a488035 TO |
306 | /** |
307 | * Function to add all the direct debit fields | |
308 | * | |
309 | * @return None | |
310 | * @access public | |
311 | */ | |
312 | function buildDirectDebit(&$form, $useRequired = FALSE) { | |
313 | if ($form->_paymentProcessor['billing_mode'] & CRM_Core_Payment::BILLING_MODE_FORM) { | |
314 | self::setDirectDebitFields($form); | |
315 | foreach ($form->_paymentFields as $name => $field) { | |
316 | if (isset($field['cc_field']) && | |
317 | $field['cc_field'] | |
318 | ) { | |
319 | $form->add($field['htmlType'], | |
320 | $field['name'], | |
321 | $field['title'], | |
322 | $field['attributes'], | |
323 | $useRequired ? $field['is_required'] : FALSE | |
324 | ); | |
325 | } | |
326 | } | |
327 | ||
328 | $form->addRule('bank_identification_number', | |
329 | ts('Please enter a valid Bank Identification Number (value must not contain punctuation characters).'), | |
330 | 'nopunctuation' | |
331 | ); | |
332 | ||
333 | $form->addRule('bank_account_number', | |
334 | ts('Please enter a valid Bank Account Number (value must not contain punctuation characters).'), | |
335 | 'nopunctuation' | |
336 | ); | |
337 | } | |
338 | ||
339 | if ($form->_paymentProcessor['billing_mode'] & CRM_Core_Payment::BILLING_MODE_BUTTON) { | |
340 | $form->_expressButtonName = $form->getButtonName($form->buttonType(), 'express'); | |
341 | $form->add('image', | |
342 | $form->_expressButtonName, | |
343 | $form->_paymentProcessor['url_button'], | |
344 | array('class' => 'form-submit') | |
345 | ); | |
346 | } | |
347 | } | |
348 | ||
7cb3d4f0 CW |
349 | /** |
350 | * Make sure that credit card number and cvv are valid | |
351 | * Called within the scope of a QF formRule function | |
352 | */ | |
353 | static function validateCreditCard($values, &$errors) { | |
354 | if (!empty($values['credit_card_type'])) { | |
355 | if (!empty($values['credit_card_number']) && | |
356 | !CRM_Utils_Rule::creditCardNumber($values['credit_card_number'], $values['credit_card_type']) | |
357 | ) { | |
8543f7c1 | 358 | $errors['credit_card_number'] = ts('Please enter a valid Card Number'); |
7cb3d4f0 CW |
359 | } |
360 | if (!empty($values['cvv2']) && | |
361 | !CRM_Utils_Rule::cvv($values['cvv2'], $values['credit_card_type']) | |
362 | ) { | |
8543f7c1 | 363 | $errors['cvv2'] = ts('Please enter a valid Card Verification Number'); |
7cb3d4f0 CW |
364 | } |
365 | } | |
15c6517d | 366 | elseif (!empty($values['credit_card_number'])) { |
8543f7c1 | 367 | $errors['credit_card_number'] = ts('Please enter a valid Card Number'); |
15c6517d | 368 | } |
7cb3d4f0 CW |
369 | } |
370 | ||
6a488035 TO |
371 | /** |
372 | * function to map address fields | |
373 | * | |
374 | * @return void | |
375 | * @static | |
376 | */ | |
377 | static function mapParams($id, &$src, &$dst, $reverse = FALSE) { | |
378 | static $map = NULL; | |
379 | if (!$map) { | |
380 | $map = array( | |
381 | 'first_name' => 'billing_first_name', | |
382 | 'middle_name' => 'billing_middle_name', | |
383 | 'last_name' => 'billing_last_name', | |
384 | 'email' => "email-$id", | |
385 | 'street_address' => "billing_street_address-$id", | |
386 | 'supplemental_address_1' => "billing_supplemental_address_1-$id", | |
387 | 'city' => "billing_city-$id", | |
388 | 'state_province' => "billing_state_province-$id", | |
389 | 'postal_code' => "billing_postal_code-$id", | |
390 | 'country' => "billing_country-$id", | |
391 | ); | |
392 | } | |
393 | ||
394 | foreach ($map as $n => $v) { | |
395 | if (!$reverse) { | |
396 | if (isset($src[$n])) { | |
397 | $dst[$v] = $src[$n]; | |
398 | } | |
399 | } | |
400 | else { | |
401 | if (isset($src[$v])) { | |
402 | $dst[$n] = $src[$v]; | |
403 | } | |
404 | } | |
405 | } | |
406 | } | |
407 | ||
408 | /** | |
409 | * function to get the credit card expiration month | |
410 | * The date format for this field should typically be "M Y" (ex: Feb 2011) or "m Y" (02 2011) | |
411 | * See CRM-9017 | |
412 | * | |
413 | * @return int | |
414 | * @static | |
415 | */ | |
416 | static function getCreditCardExpirationMonth($src) { | |
417 | if ($month = CRM_Utils_Array::value('M', $src['credit_card_exp_date'])) { | |
418 | return $month; | |
419 | } | |
420 | ||
421 | return CRM_Utils_Array::value('m', $src['credit_card_exp_date']); | |
422 | } | |
423 | ||
424 | /** | |
425 | * function to get the credit card expiration year | |
426 | * The date format for this field should typically be "M Y" (ex: Feb 2011) or "m Y" (02 2011) | |
427 | * This function exists only to make it consistant with getCreditCardExpirationMonth | |
428 | * | |
429 | * @return int | |
430 | * @static | |
431 | */ | |
432 | static function getCreditCardExpirationYear($src) { | |
433 | return CRM_Utils_Array::value('Y', $src['credit_card_exp_date']); | |
434 | } | |
435 | ||
436 | /** | |
437 | * function to return state/province is_required = true/false | |
438 | * | |
439 | */ | |
440 | static function checkRequiredStateProvince($form) { | |
441 | // If selected country has possible values for state/province mark the | |
442 | // state/province field as required. | |
443 | $config = CRM_Core_Config::singleton(); | |
444 | $stateProvince = new CRM_Core_DAO_StateProvince(); | |
445 | $stateProvince->country_id = CRM_Utils_Array::value("billing_country_id-{$form->_bltID}", $form->_submitValues); | |
446 | ||
447 | if ($stateProvince->count() > 0) { | |
448 | // check that the state/province data is not excluded by a | |
449 | // limitation in the localisation settings. | |
450 | $countryIsoCodes = CRM_Core_PseudoConstant::countryIsoCode(); | |
451 | $limitCodes = $config->provinceLimit(); | |
452 | $limitIds = array(); | |
453 | foreach ($limitCodes as $code) { | |
454 | $limitIds = array_merge($limitIds, array_keys($countryIsoCodes, $code)); | |
455 | } | |
456 | ||
457 | $limitCountryId = CRM_Utils_Array::value("billing_country_id-{$form->_bltID}", $form->_submitValues); | |
458 | if ($limitCountryId && in_array($limitCountryId, $limitIds)) { | |
459 | return TRUE; | |
460 | } | |
461 | return FALSE; | |
462 | } | |
463 | return FALSE; | |
464 | } | |
465 | } | |
466 |