3 +--------------------------------------------------------------------+
4 | Copyright CiviCRM LLC. All rights reserved. |
6 | This work is published under the GNU AGPLv3 license with some |
7 | permitted exceptions and without any warranty. For full license |
8 | and copyright information, see https://civicrm.org/licensing |
9 +--------------------------------------------------------------------+
12 use Civi\Api4\PriceSet
;
15 * Test APIv3 civicrm_contribute_* functions
17 * @package CiviCRM_APIv3
18 * @subpackage API_Contribution
21 class CRM_Contribute_Form_ContributionTest
extends CiviUnitTestCase
{
22 use CRMTraits_PCP_PCPTestTrait
;
24 protected $_individualId;
25 protected $_contribution;
26 protected $_financialTypeId = 1;
27 protected $_entity = 'Contribution';
30 protected $_pageParams = [];
34 * Parameters to create payment processor.
38 protected $_processorParams = [];
41 * ID of created event.
48 * Payment instrument mapping.
52 protected $paymentInstruments = [];
59 protected $products = [];
62 * Dummy payment processor.
64 * @var CRM_Core_Payment_Dummy
66 protected $paymentProcessor;
69 * Payment processor ID.
73 protected $paymentProcessorID;
78 * @throws \CRM_Core_Exception
79 * @throws \CiviCRM_API3_Exception
81 public function setUp(): void
{
82 $this->_apiversion
= 3;
84 $this->_userId
= $this->createLoggedInUser();
86 $this->_individualId
= $this->ids
['contact'][0] = $this->individualCreate();
88 'contact_id' => $this->_individualId
,
89 'receive_date' => '20120511',
90 'total_amount' => 100.00,
91 'financial_type_id' => $this->_financialTypeId
,
92 'non_deductible_amount' => 10.00,
94 'net_amount' => 95.00,
96 'contribution_status_id' => 1,
98 $this->_processorParams
= [
101 'payment_processor_type_id' => 10,
102 'financial_account_id' => 12,
105 'url_site' => 'http://dummy.com',
106 'url_recur' => 'http://dummy.com',
110 $instruments = $this->callAPISuccess('contribution', 'getoptions', ['field' => 'payment_instrument_id']);
111 $this->paymentInstruments
= $instruments['values'];
112 $product1 = $this->callAPISuccess('product', 'create', [
114 'options' => 'brainy smurf, clumsy smurf, papa smurf',
117 $this->products
[] = $product1['values'][$product1['id']];
118 $this->paymentProcessor
= $this->dummyProcessorCreate();
119 $processor = $this->paymentProcessor
->getPaymentProcessor();
120 $this->paymentProcessorID
= $processor['id'];
124 * Clean up after each test.
126 * @throws \CRM_Core_Exception
128 public function tearDown(): void
{
129 $this->quickCleanUpFinancialEntities();
130 $this->quickCleanup(['civicrm_note', 'civicrm_uf_match', 'civicrm_address']);
134 * CHeck that all tests that have created payments have created them with the right financial entities.
136 * @throws \CRM_Core_Exception
138 protected function assertPostConditions(): void
{
139 $this->validateAllPayments();
143 * Test the submit function on the contribution page.
145 * @param string $thousandSeparator
147 * @dataProvider getThousandSeparators
149 public function testSubmit(string $thousandSeparator): void
{
150 $this->setCurrencySeparators($thousandSeparator);
151 $form = $this->getContributionForm([
152 'total_amount' => $this->formatMoneyInput(1234),
153 'financial_type_id' => 1,
154 'contact_id' => $this->_individualId
,
155 'payment_instrument_id' => $this->getPaymentInstrument('Check'),
156 'contribution_status_id' => 1,
158 $form->postProcess();
159 $contribution = $this->callAPISuccessGetSingle('Contribution', ['contact_id' => $this->_individualId
]);
160 $this->assertEmpty($contribution['amount_level']);
161 $this->assertEquals(1234, $contribution['total_amount']);
162 $this->assertEquals(1234, $contribution['net_amount']);
166 * Test the submit function on the contribution page.
168 * @throws \CRM_Core_Exception
169 * @throws \CiviCRM_API3_Exception
171 public function testSubmitCreditCard(): void
{
172 $form = new CRM_Contribute_Form_Contribution();
174 'total_amount' => 50,
175 'financial_type_id' => 1,
176 'contact_id' => $this->_individualId
,
177 'payment_instrument_id' => array_search('Credit Card', $this->paymentInstruments
),
178 'contribution_status_id' => 1,
179 ], CRM_Core_Action
::ADD
);
180 $this->callAPISuccessGetCount('Contribution', [
181 'contact_id' => $this->_individualId
,
182 'contribution_status_id' => 'Completed',
187 * Test the submit function on the contribution page.
189 * @throws \CRM_Core_Exception
190 * @throws \CiviCRM_API3_Exception
192 public function testSubmitCreditCardPayPal(): void
{
193 $mut = new CiviMailUtils($this, TRUE);
194 $mut->clearMessages();
195 $form = new CRM_Contribute_Form_Contribution();
196 $paymentProcessorID = $this->paymentProcessorCreate(['is_test' => 0]);
197 $form->_mode
= 'Live';
201 'total_amount' => 50,
202 'financial_type_id' => 1,
203 'contact_id' => $this->_individualId
,
204 'contribution_status_id' => 1,
205 'credit_card_number' => 4444333322221111,
207 'credit_card_exp_date' => [
211 'credit_card_type' => 'Visa',
212 'billing_first_name' => 'Junko',
213 'billing_middle_name' => '',
214 'billing_last_name' => 'Adams',
215 'billing_street_address-5' => '790L Lincoln St S',
216 'billing_city-5' => 'Maryknoll',
217 'billing_state_province_id-5' => 1031,
218 'billing_postal_code-5' => 10545,
219 'billing_country_id-5' => 1228,
220 'frequency_interval' => 1,
221 'frequency_unit' => 'month',
222 'installments' => '',
223 'hidden_AdditionalDetail' => 1,
224 'hidden_Premium' => 1,
225 'from_email_address' => '"civi45" <civi45@civicrm.com>',
226 'is_email_receipt' => TRUE,
227 'receipt_date' => '',
228 'receipt_date_time' => '',
229 'payment_processor_id' => $paymentProcessorID,
231 'source' => 'bob sled race',
232 ], CRM_Core_Action
::ADD
);
234 catch (Civi\Payment\Exception\PaymentProcessorException
$e) {
238 $contribution = $this->callAPISuccess('Contribution', 'get', [
239 'contact_id' => $this->_individualId
,
240 'contribution_status_id' => $error ?
'Failed' : 'Completed',
241 'payment_instrument_id' => $this->callAPISuccessGetValue('PaymentProcessor', [
242 'return' => 'payment_instrument_id',
243 'id' => $paymentProcessorID,
247 $this->assertEquals(1, $contribution['count'], 'Contribution count should be one.');
248 $this->assertNotTrue(empty($contribution['values'][$contribution['id']]['receipt_date']), 'Receipt date should not be blank.');
250 $contact = $this->callAPISuccessGetSingle('Contact', ['id' => $this->_individualId
]);
251 $this->assertTrue(empty($contact['source']));
253 $msgs = $mut->getAllMessages();
254 $this->assertEquals(1, count($msgs));
256 $mut->clearMessages();
261 * Test the submit function on the contribution page
263 * @throws \CRM_Core_Exception
265 public function testSubmitCreditCardWithEmailReceipt() {
266 $mut = new CiviMailUtils($this, TRUE);
267 $mut->clearMessages();
268 $form = new CRM_Contribute_Form_Contribution();
269 $form->_mode
= 'Live';
272 'total_amount' => 50,
273 'financial_type_id' => 1,
274 'contact_id' => $this->_individualId
,
275 'contribution_status_id' => 1,
276 'credit_card_number' => 4444333322221111,
278 'credit_card_exp_date' => [
282 'credit_card_type' => 'Visa',
283 'billing_first_name' => 'Junko',
284 'billing_middle_name' => '',
285 'billing_last_name' => 'Adams',
286 'billing_street_address-5' => '790L Lincoln St S',
287 'billing_city-5' => 'Maryknoll',
288 'billing_state_province_id-5' => 1031,
289 'billing_postal_code-5' => 10545,
290 'billing_country_id-5' => 1228,
291 'frequency_interval' => 1,
292 'frequency_unit' => 'month',
293 'installments' => '',
294 'hidden_AdditionalDetail' => 1,
295 'hidden_Premium' => 1,
296 'from_email_address' => '"civi45" <civi45@civicrm.com>',
297 'is_email_receipt' => TRUE,
298 'receipt_date' => '',
299 'receipt_date_time' => '',
300 'payment_processor_id' => $this->paymentProcessorID
,
302 'source' => 'bob sled race',
303 ], CRM_Core_Action
::ADD
);
305 $this->callAPISuccessGetCount('Contribution', [
306 'contact_id' => $this->_individualId
,
307 'contribution_status_id' => 'Completed',
308 'payment_instrument_id' => $this->callAPISuccessGetValue('PaymentProcessor', [
309 'return' => 'payment_instrument_id',
310 'id' => $this->paymentProcessorID
,
313 $contact = $this->callAPISuccessGetSingle('Contact', ['id' => $this->_individualId
]);
314 $this->assertTrue(empty($contact['source']));
315 $msgs = $mut->getAllMessages();
316 $this->assertEquals(1, count($msgs));
321 * Test the submit function on the contribution page.
323 public function testSubmitCreditCardNoReceipt() {
324 $mut = new CiviMailUtils($this, TRUE);
325 $mut->clearMessages();
326 $form = new CRM_Contribute_Form_Contribution();
327 $form->_mode
= 'Live';
331 'total_amount' => 60,
332 'financial_type_id' => 1,
333 'contact_id' => $this->_individualId
,
334 'contribution_status_id' => 1,
335 'credit_card_number' => 4444333322221111,
337 'credit_card_exp_date' => [
341 'credit_card_type' => 'Visa',
342 'billing_first_name' => 'Junko',
343 'billing_middle_name' => '',
344 'billing_last_name' => 'Adams',
345 'billing_street_address-5' => '790L Lincoln St S',
346 'billing_city-5' => 'Maryknoll',
347 'billing_state_province_id-5' => 1031,
348 'billing_postal_code-5' => 10545,
349 'billing_country_id-5' => 1228,
350 'frequency_interval' => 1,
351 'frequency_unit' => 'month',
352 'installments' => '',
353 'hidden_AdditionalDetail' => 1,
354 'hidden_Premium' => 1,
355 'from_email_address' => '"civi45" <civi45@civicrm.com>',
356 'is_email_receipt' => FALSE,
357 'receipt_date' => '',
358 'receipt_date_time' => '',
359 'payment_processor_id' => $this->paymentProcessorID
,
361 'source' => 'bob sled race',
362 ], CRM_Core_Action
::ADD
);
364 catch (Civi\Payment\Exception\PaymentProcessorException
$e) {
368 $this->callAPISuccessGetCount('Contribution', [
369 'contact_id' => $this->_individualId
,
370 'contribution_status_id' => $error ?
'Failed' : 'Completed',
371 'payment_instrument_id' => $this->callAPISuccessGetValue('PaymentProcessor', [
372 'return' => 'payment_instrument_id',
373 'id' => $this->paymentProcessorID
,
376 $contact = $this->callAPISuccessGetSingle('Contact', ['id' => $this->_individualId
]);
377 $this->assertTrue(empty($contact['source']));
378 $mut->assertMailLogEmpty();
383 * Test the submit function on the contribution page.
385 public function testSubmitCreditCardFee() {
386 $form = new CRM_Contribute_Form_Contribution();
387 $this->paymentProcessor
->setDoDirectPaymentResult(['payment_status_id' => 1, 'is_error' => 0, 'trxn_id' => 'tx', 'fee_amount' => .08]);
388 $form->_mode
= 'Live';
390 'total_amount' => 50,
391 'financial_type_id' => 1,
392 'contact_id' => $this->_individualId
,
393 'payment_instrument_id' => array_search('Credit Card', $this->paymentInstruments
),
394 'contribution_status_id' => 1,
395 'credit_card_number' => 4444333322221111,
397 'credit_card_exp_date' => [
401 'credit_card_type' => 'Visa',
402 'billing_first_name' => 'Junko',
403 'billing_middle_name' => '',
404 'billing_last_name' => 'Adams',
405 'billing_street_address-5' => '790L Lincoln St S',
406 'billing_city-5' => 'Maryknoll',
407 'billing_state_province_id-5' => 1031,
408 'billing_postal_code-5' => 10545,
409 'billing_country_id-5' => 1228,
410 'frequency_interval' => 1,
411 'frequency_unit' => 'month',
412 'installments' => '',
413 'hidden_AdditionalDetail' => 1,
414 'hidden_Premium' => 1,
415 'from_email_address' => '"civi45" <civi45@civicrm.com>',
416 'receipt_date' => '',
417 'receipt_date_time' => '',
418 'payment_processor_id' => $this->paymentProcessorID
,
421 ], CRM_Core_Action
::ADD
);
423 $contribution = $this->callAPISuccessGetSingle('Contribution', [
424 'contact_id' => $this->_individualId
,
425 'contribution_status_id' => 'Completed',
427 $this->assertEquals('50.00', $contribution['total_amount']);
428 $this->assertEquals(.08, $contribution['fee_amount']);
429 $this->assertEquals(49.92, $contribution['net_amount']);
430 $this->assertEquals('tx', $contribution['trxn_id']);
431 $this->assertEmpty($contribution['amount_level']);
435 * Test a fully deductible contribution submitted by credit card (CRM-16669).
437 public function testSubmitCreditCardFullyDeductible() {
438 $form = new CRM_Contribute_Form_Contribution();
439 $form->_mode
= 'Live';
441 'total_amount' => 50,
442 'financial_type_id' => 1,
443 'contact_id' => $this->_individualId
,
444 'payment_instrument_id' => array_search('Credit Card', $this->paymentInstruments
),
445 'contribution_status_id' => 1,
446 'credit_card_number' => 4444333322221111,
448 'credit_card_exp_date' => [
452 'credit_card_type' => 'Visa',
453 'billing_first_name' => 'Junko',
454 'billing_middle_name' => '',
455 'billing_last_name' => 'Adams',
456 'billing_street_address-5' => '790L Lincoln St S',
457 'billing_city-5' => 'Maryknoll',
458 'billing_state_province_id-5' => 1031,
459 'billing_postal_code-5' => 10545,
460 'billing_country_id-5' => 1228,
461 'frequency_interval' => 1,
462 'frequency_unit' => 'month',
463 'installments' => '',
464 'hidden_AdditionalDetail' => 1,
465 'hidden_Premium' => 1,
466 'from_email_address' => '"civi45" <civi45@civicrm.com>',
467 'receipt_date' => '',
468 'receipt_date_time' => '',
469 'payment_processor_id' => $this->paymentProcessorID
,
472 ], CRM_Core_Action
::ADD
);
474 $contribution = $this->callAPISuccessGetSingle('Contribution', [
475 'contact_id' => $this->_individualId
,
476 'contribution_status_id' => 'Completed',
478 $this->assertEquals('50.00', $contribution['total_amount']);
479 $this->assertEquals(0, $contribution['non_deductible_amount']);
483 * Test the submit function with an invalid payment.
485 * We expect the contribution to be created but left pending. The payment has failed.
487 * Test covers CRM-16417 change to keep failed transactions.
490 * - 1 Contribution with status = Pending
492 * - 1 civicrm_financial_item. This is linked to the line item and has a status of 3
494 * @throws \CRM_Core_Exception
495 * @throws \CiviCRM_API3_Exception
497 public function testSubmitCreditCardInvalid() {
498 $form = new CRM_Contribute_Form_Contribution();
499 $this->paymentProcessor
->setDoDirectPaymentResult(['is_error' => 1]);
502 'total_amount' => 50,
503 'financial_type_id' => 1,
504 'contact_id' => $this->_individualId
,
505 'payment_instrument_id' => array_search('Credit Card', $this->paymentInstruments
),
506 'payment_processor_id' => $this->paymentProcessorID
,
507 'credit_card_exp_date' => ['M' => 5, 'Y' => 2012],
508 'credit_card_number' => '411111111111111',
509 ], CRM_Core_Action
::ADD
, 'live');
511 catch (\Civi\Payment\Exception\PaymentProcessorException
$e) {
512 $this->callAPISuccessGetCount('Contribution', [
513 'contact_id' => $this->_individualId
,
514 'contribution_status_id' => 'Failed',
516 $lineItem = $this->callAPISuccessGetSingle('line_item', []);
517 $this->assertEquals('50.00', $lineItem['unit_price']);
518 $this->assertEquals('50.00', $lineItem['line_total']);
519 $this->assertEquals(1, $lineItem['qty']);
520 $this->assertEquals(1, $lineItem['financial_type_id']);
521 $financialItem = $this->callAPISuccessGetSingle('financial_item', [
522 'civicrm_line_item' => $lineItem['id'],
523 'entity_id' => $lineItem['id'],
525 $this->assertEquals('50.00', $financialItem['amount']);
526 $this->assertEquals(3, $financialItem['status_id']);
529 $this->fail('An expected exception has not been raised.');
533 * Test the submit function creates a billing address if provided.
535 * @throws \CRM_Core_Exception
536 * @throws \CiviCRM_API3_Exception
538 public function testSubmitCreditCardWithBillingAddress() {
539 $form = new CRM_Contribute_Form_Contribution();
541 'total_amount' => 50,
542 'financial_type_id' => 1,
543 'contact_id' => $this->_individualId
,
544 'payment_instrument_id' => array_search('Credit Card', $this->paymentInstruments
),
545 'payment_processor_id' => $this->paymentProcessorID
,
546 'credit_card_exp_date' => ['M' => 5, 'Y' => 2025],
547 'credit_card_number' => '411111111111111',
548 'billing_city-5' => 'Vancouver',
549 ], CRM_Core_Action
::ADD
, 'live');
550 $contribution = $this->callAPISuccessGetSingle('Contribution', ['return' => 'address_id']);
551 $this->assertNotEmpty($contribution['address_id']);
552 // CRM-18490 : There is a unwanted test leakage due to below getsingle Api as it only fails in Jenkin
553 // for now we are only fetching address on based on Address ID (removed filter location_type_id and city)
554 $this->callAPISuccessGetSingle('Address', [
555 'id' => $contribution['address_id'],
560 * CRM-20745: Test the submit function correctly sets the
561 * receive date for recurring contribution.
563 public function testSubmitCreditCardWithRecur() {
564 $form = new CRM_Contribute_Form_Contribution();
565 $receiveDate = date('Y-m-d H:i:s', strtotime('+1 month'));
567 'total_amount' => 50,
568 'financial_type_id' => 1,
570 'frequency_interval' => 2,
571 'frequency_unit' => 'month',
573 'receive_date' => $receiveDate,
574 'contact_id' => $this->_individualId
,
575 'payment_instrument_id' => array_search('Credit Card', $this->paymentInstruments
),
576 'payment_processor_id' => $this->paymentProcessorID
,
577 'credit_card_exp_date' => ['M' => 5, 'Y' => 2025],
578 'credit_card_number' => '411111111111111',
579 'billing_city-5' => 'Vancouver',
580 ], CRM_Core_Action
::ADD
, 'live');
581 $contribution = $this->callAPISuccessGetSingle('Contribution', ['return' => 'receive_date']);
582 $this->assertEquals($contribution['receive_date'], $receiveDate);
586 * Test the submit function does not create a billing address if no details provided.
588 public function testSubmitCreditCardWithNoBillingAddress() {
589 $form = new CRM_Contribute_Form_Contribution();
591 'total_amount' => 50,
592 'financial_type_id' => 1,
593 'contact_id' => $this->_individualId
,
594 'payment_instrument_id' => array_search('Credit Card', $this->paymentInstruments
),
595 'payment_processor_id' => $this->paymentProcessorID
,
596 'credit_card_exp_date' => ['M' => 5, 'Y' => 2025],
597 'credit_card_number' => '411111111111111',
598 ], CRM_Core_Action
::ADD
, 'live');
599 $contribution = $this->callAPISuccessGetSingle('Contribution', ['return' => 'address_id']);
600 $this->assertEmpty($contribution['address_id']);
601 $this->callAPISuccessGetCount('Address', [
602 'city' => 'Vancouver',
603 'location_type_id' => 5,
608 * Test the submit function on the contribution page.
610 * @throws \CRM_Core_Exception
611 * @throws \CiviCRM_API3_Exception
613 public function testSubmitEmailReceipt() {
614 $form = new CRM_Contribute_Form_Contribution();
615 $mut = new CiviMailUtils($this, TRUE);
617 'total_amount' => 50,
618 'financial_type_id' => 1,
619 'contact_id' => $this->_individualId
,
620 'is_email_receipt' => TRUE,
621 'from_email_address' => 'test@test.com',
622 'contribution_status_id' => 1,
623 ], CRM_Core_Action
::ADD
);
624 $this->callAPISuccessGetCount('Contribution', ['contact_id' => $this->_individualId
], 1);
626 'Contribution Information',
632 * Test the submit function on the contribution page using numerical from email address.
634 public function testSubmitEmailReceiptUserEmailFromAddress(): void
{
635 $email = $this->callAPISuccess('Email', 'create', [
636 'contact_id' => $this->_userId
,
637 'email' => 'testLoggedIn@example.com',
639 $mut = new CiviMailUtils($this, TRUE);
640 $form = $this->getContributionForm([
641 'contribution_status_id' => 1,
642 'total_amount' => 50,
643 'financial_type_id' => 1,
644 'contact_id' => $this->_individualId
,
645 'is_email_receipt' => TRUE,
646 'from_email_address' => $email['id'],
649 $form->postProcess();
650 $this->callAPISuccessGetCount('Contribution', ['contact_id' => $this->_individualId
], 1);
652 'Below you will find a receipt for this contribution.',
653 '<testloggedin@example.com>',
659 * Ensure that price field are shown during pay later/pending Contribution
661 * @throws \API_Exception
663 public function testEmailReceiptOnPayLater(): void
{
664 $donationFT = CRM_Core_DAO
::getFieldValue('CRM_Financial_DAO_FinancialType', 'Donation', 'id', 'name');
665 $priceSetID = PriceSet
::create(FALSE)->setValues([
666 'title' => 'Price Set abcd',
668 'financial_type_id:name' => 'Donation',
670 'name' => 'price_set_abcd',
671 ])->execute()->first()['id'];
674 'label' => 'Price Field',
675 'name' => 'price_field',
676 'html_type' => 'CheckBox',
677 'option_label' => ['1' => 'Price Field 1', '2' => 'Price Field 2'],
678 'option_value' => ['1' => 100, '2' => 200],
679 'option_name' => ['1' => 'Price Field 1', '2' => 'Price Field 2'],
680 'option_weight' => ['1' => 1, '2' => 2],
681 'option_amount' => ['1' => 100, '2' => 200],
682 'is_display_amounts' => 1,
684 'options_per_line' => 1,
685 'is_active' => ['1' => 1, '2' => 1],
686 'price_set_id' => $priceSetID,
688 'financial_type_id' => $donationFT,
690 $priceField = CRM_Price_BAO_PriceField
::create($paramsField);
691 $priceFieldValue = $this->callAPISuccess('PriceFieldValue', 'get', ['price_field_id' => $priceField->id
]);
694 'total_amount' => 100,
695 'financial_type_id' => $donationFT,
696 'contact_id' => $this->_individualId
,
697 'is_email_receipt' => TRUE,
698 'from_email_address' => 'test@test.com',
699 'price_set_id' => $priceSetID,
700 'contribution_status_id' => CRM_Core_PseudoConstant
::getKey('CRM_Contribute_BAO_Contribution', 'contribution_status_id', 'Pending'),
703 foreach ($priceFieldValue['values'] as $id => $price) {
704 if ($price['amount'] == 100) {
705 $params['price_' . $priceField->id
] = [$id => 1];
708 $form = $this->getContributionForm($params);
709 $mut = new CiviMailUtils($this, TRUE);
710 $form->_priceSet
= current(CRM_Price_BAO_PriceSet
::getSetDetail($priceSetID));
711 $form->postProcess();
714 'Financial Type: Donation
715 ---------------------------------------------------------
717 ----------------------------------------------------------
718 Price Field - Price Field 1 1 $ 100.00 $ 100.00
725 * Test that a contribution is assigned against a pledge.
727 public function testUpdatePledge() {
728 $pledge = $this->callAPISuccess('pledge', 'create', [
729 'contact_id' => $this->_individualId
,
730 'pledge_create_date' => date('Ymd'),
731 'start_date' => date('Ymd'),
733 'pledge_status_id' => '2',
734 'pledge_financial_type_id' => '1',
735 'pledge_original_installment_amount' => 20,
736 'frequency_interval' => 5,
737 'frequency_unit' => 'year',
738 'frequency_day' => 15,
742 $pledgePaymentID = $this->callAPISuccess('pledge_payment', 'getvalue', [
743 'pledge_id' => $pledge['id'],
744 'options' => ['limit' => 1],
747 $form = new CRM_Contribute_Form_Contribution();
749 'total_amount' => 50,
750 'financial_type_id' => 1,
751 'contact_id' => $this->_individualId
,
752 'payment_instrument_id' => array_search('Check', $this->paymentInstruments
),
753 'pledge_payment_id' => $pledgePaymentID,
754 'contribution_status_id' => 1,
755 ], CRM_Core_Action
::ADD
);
756 $pledgePayment = $this->callAPISuccess('pledge_payment', 'getsingle', ['id' => $pledgePaymentID]);
757 $this->assertNotEmpty($pledgePayment['contribution_id']);
758 $this->assertEquals($pledgePayment['actual_amount'], 50);
759 $this->assertEquals(1, $pledgePayment['status_id']);
763 * Test functions involving premiums.
765 public function testPremiumUpdate() {
766 $form = new CRM_Contribute_Form_Contribution();
767 $mut = new CiviMailUtils($this, TRUE);
769 'total_amount' => 50,
770 'financial_type_id' => 1,
771 'contact_id' => $this->_individualId
,
772 'payment_instrument_id' => array_search('Check', $this->paymentInstruments
),
773 'contribution_status_id' => 1,
774 'product_name' => [$this->products
[0]['id'], 1],
775 'fulfilled_date' => '',
776 'is_email_receipt' => TRUE,
777 'from_email_address' => 'test@test.com',
778 ], CRM_Core_Action
::ADD
);
779 $contributionProduct = $this->callAPISuccess('contribution_product', 'getsingle', []);
780 $this->assertEquals('clumsy smurf', $contributionProduct['product_option']);
782 'Premium Information',
790 * Test functions involving premiums.
792 public function testPremiumUpdateCreditCard() {
793 $form = new CRM_Contribute_Form_Contribution();
794 $mut = new CiviMailUtils($this, TRUE);
796 'total_amount' => 50,
797 'financial_type_id' => 1,
798 'contact_id' => $this->_individualId
,
799 'payment_instrument_id' => array_search('Check', $this->paymentInstruments
),
800 'contribution_status_id' => 1,
801 'product_name' => [$this->products
[0]['id'], 1],
802 'fulfilled_date' => '',
803 'is_email_receipt' => TRUE,
804 'from_email_address' => 'test@test.com',
805 'payment_processor_id' => $this->paymentProcessorID
,
806 'credit_card_exp_date' => ['M' => 5, 'Y' => 2026],
807 'credit_card_number' => '411111111111111',
808 ], CRM_Core_Action
::ADD
, 'live');
809 $contributionProduct = $this->callAPISuccess('contribution_product', 'getsingle', []);
810 $this->assertEquals('clumsy smurf', $contributionProduct['product_option']);
812 'Premium Information',
820 * Test submitting the back office contribution form with pcp data.
822 * @throws \CRM_Core_Exception
823 * @throws \CiviCRM_API3_Exception
824 * @throws \Civi\Payment\Exception\PaymentProcessorException
826 public function testSubmitWithPCP(): void
{
827 $mut = new CiviMailUtils($this, TRUE);
828 $mut->clearMessages();
829 $params = $this->pcpParams();
830 $pcpID = $this->createPCPBlock($params);
831 $form = new CRM_Contribute_Form_Contribution();
833 'financial_type_id' => 3,
834 'contact_id' => $this->_individualId
,
835 'payment_instrument_id' => CRM_Core_PseudoConstant
::getKey('CRM_Contribute_BAO_Contribution', 'payment_instrument_id', 'Check'),
836 'contribution_status_id' => 1,
838 'pcp_made_through_id' => $pcpID,
839 'pcp_display_in_roll' => '1',
840 'pcp_roll_nickname' => 'Dobby',
841 'pcp_personal_note' => 'I wuz here',
842 ], CRM_Core_Action
::ADD
);
843 $softCredit = $this->callAPISuccessGetSingle('ContributionSoft', []);
844 $this->assertEquals('Dobby', $softCredit['pcp_roll_nickname']);
845 $mut->checkMailLog(['Personal Campaign Page Owner Notification']);
849 * Test the submit function on the contribution page.
851 public function testSubmitWithNote() {
852 $form = new CRM_Contribute_Form_Contribution();
854 'total_amount' => 50,
855 'financial_type_id' => 1,
856 'contact_id' => $this->_individualId
,
857 'payment_instrument_id' => array_search('Check', $this->paymentInstruments
),
858 'contribution_status_id' => 1,
859 'note' => 'Super cool and interesting stuff',
860 ], CRM_Core_Action
::ADD
);
861 $this->callAPISuccessGetCount('Contribution', ['contact_id' => $this->_individualId
], 1);
862 $note = $this->callAPISuccessGetSingle('note', ['entity_table' => 'civicrm_contribution']);
863 $this->assertEquals($note['note'], 'Super cool and interesting stuff');
867 * Test the submit function on the contribution page.
869 public function testSubmitWithNoteCreditCard() {
870 $form = new CRM_Contribute_Form_Contribution();
873 'total_amount' => 50,
874 'financial_type_id' => 1,
875 'contact_id' => $this->_individualId
,
876 'payment_instrument_id' => array_search('Check', $this->paymentInstruments
),
877 'contribution_status_id' => 1,
878 'note' => 'Super cool and interesting stuff',
879 ] +
$this->getCreditCardParams(),
880 CRM_Core_Action
::ADD
);
881 $this->callAPISuccessGetCount('Contribution', ['contact_id' => $this->_individualId
], 1);
882 $note = $this->callAPISuccessGetSingle('note', ['entity_table' => 'civicrm_contribution']);
883 $this->assertEquals($note['note'], 'Super cool and interesting stuff');
887 * Test that if a negative contribution is entered it does not get reset to $0.
889 * Note that this fails locally for me & I believe there may be an issue for some sites
890 * with negative numbers. Grep for CRM-16460 to find the places I think that might
891 * be affected if you hit this.
893 public function testEnterNegativeContribution() {
894 $form = new CRM_Contribute_Form_Contribution();
896 'total_amount' => -5,
897 'financial_type_id' => 1,
898 'contact_id' => $this->_individualId
,
899 'payment_instrument_id' => array_search('Check', $this->paymentInstruments
),
900 'contribution_status_id' => 1,
902 CRM_Core_Action
::ADD
);
903 $this->callAPISuccessGetCount('Contribution', ['contact_id' => $this->_individualId
], 1);
905 $contribution = $this->callAPISuccessGetSingle('Contribution', [
906 'contact_id' => $this->_individualId
,
908 $this->assertEquals(-5, $contribution['total_amount']);
912 * Test the submit function on the contribution page.
914 * @param string $thousandSeparator
916 * @throws \CRM_Core_Exception
917 * @throws \CiviCRM_API3_Exception
918 * @throws \Civi\Payment\Exception\PaymentProcessorException
920 * @dataProvider getThousandSeparators
922 public function testSubmitUpdate(string $thousandSeparator): void
{
923 $this->setCurrencySeparators($thousandSeparator);
924 $form = new CRM_Contribute_Form_Contribution();
927 'total_amount' => $this->formatMoneyInput(6100.10),
928 'financial_type_id' => 1,
929 'contact_id' => $this->_individualId
,
930 'payment_instrument_id' => array_search('Check', $this->paymentInstruments
),
931 'contribution_status_id' => 1,
933 ], CRM_Core_Action
::ADD
);
934 $contribution = $this->callAPISuccessGetSingle('Contribution', ['contact_id' => $this->_individualId
]);
936 'total_amount' => $this->formatMoneyInput(5200.20),
937 'net_amount' => $this->formatMoneyInput(5200.20),
938 'financial_type_id' => 1,
939 'contact_id' => $this->_individualId
,
940 'payment_instrument_id' => array_search('Check', $this->paymentInstruments
),
941 'contribution_status_id' => 1,
943 'id' => $contribution['id'],
944 ], CRM_Core_Action
::UPDATE
);
945 $contribution = $this->callAPISuccessGetSingle('Contribution', ['contact_id' => $this->_individualId
]);
946 $this->assertEquals(5200.20, $contribution['total_amount'], 2);
948 $financialTransactions = $this->callAPISuccess('FinancialTrxn', 'get', ['sequential' => TRUE]);
949 $this->assertEquals(2, $financialTransactions['count']);
950 $this->assertEquals(6100.10, $financialTransactions['values'][0]['total_amount']);
951 $this->assertEquals(-899.90, $financialTransactions['values'][1]['total_amount']);
952 $this->assertEquals(-899.90, $financialTransactions['values'][1]['net_amount']);
953 $lineItem = $this->callAPISuccessGetSingle('LineItem', []);
954 $this->assertEquals(5200.20, $lineItem['line_total']);
958 * Test the submit function if only payment instrument is changed from 'Check' to 'Credit Card'
960 * @param string $thousandSeparator
962 * @dataProvider getThousandSeparators
964 public function testSubmitUpdateChangePaymentInstrument($thousandSeparator) {
965 $this->setCurrencySeparators($thousandSeparator);
966 $form = new CRM_Contribute_Form_Contribution();
969 'total_amount' => 1200.55,
970 'financial_type_id' => 1,
971 'contact_id' => $this->_individualId
,
972 'payment_instrument_id' => array_search('Check', $this->paymentInstruments
),
973 'check_number' => '123AX',
974 'contribution_status_id' => 1,
976 ], CRM_Core_Action
::ADD
);
977 $contribution = $this->callAPISuccessGetSingle('Contribution', ['contact_id' => $this->_individualId
]);
979 'total_amount' => 1200.55,
980 'net_amount' => 1200.55,
981 'financial_type_id' => 1,
982 'contact_id' => $this->_individualId
,
983 'payment_instrument_id' => array_search('Credit Card', $this->paymentInstruments
),
984 'card_type_id' => CRM_Core_PseudoConstant
::getKey('CRM_Financial_DAO_FinancialTrxn', 'card_type_id', 'Visa'),
985 'pan_truncation' => '1011',
986 'contribution_status_id' => 1,
988 'id' => $contribution['id'],
989 ], CRM_Core_Action
::UPDATE
);
990 $contribution = $this->callAPISuccessGetSingle('Contribution', ['contact_id' => $this->_individualId
]);
991 $this->assertEquals(1200.55, $contribution['total_amount']);
993 $financialTransactions = $this->callAPISuccess('FinancialTrxn', 'get', ['sequential' => TRUE]);
994 $this->assertEquals(3, $financialTransactions['count']);
996 [$oldTrxn, $reversedTrxn, $latestTrxn] = $financialTransactions['values'];
998 $this->assertEquals(1200.55, $oldTrxn['total_amount']);
999 $this->assertEquals('123AX', $oldTrxn['check_number']);
1000 $this->assertEquals(array_search('Check', $this->paymentInstruments
), $oldTrxn['payment_instrument_id']);
1002 $this->assertEquals(-1200.55, $reversedTrxn['total_amount']);
1003 $this->assertEquals('123AX', $reversedTrxn['check_number']);
1004 $this->assertEquals(array_search('Check', $this->paymentInstruments
), $reversedTrxn['payment_instrument_id']);
1006 $this->assertEquals(1200.55, $latestTrxn['total_amount']);
1007 $this->assertEquals('1011', $latestTrxn['pan_truncation']);
1008 $this->assertEquals(array_search('Credit Card', $this->paymentInstruments
), $latestTrxn['payment_instrument_id']);
1009 $lineItem = $this->callAPISuccessGetSingle('LineItem', []);
1013 * Get parameters for credit card submit calls.
1016 * Credit card specific parameters.
1018 protected function getCreditCardParams() {
1020 'payment_processor_id' => $this->paymentProcessorID
,
1021 'credit_card_exp_date' => ['M' => 5, 'Y' => 2012],
1022 'credit_card_number' => '411111111111111',
1027 * Test the submit function that completes the partially paid payment using Credit Card
1029 * @throws \CRM_Core_Exception
1030 * @throws \CiviCRM_API3_Exception
1032 public function testPartialPaymentWithCreditCard(): void
{
1033 // create a partially paid contribution by using back-office form
1034 $form = $this->getContributionForm([
1035 'total_amount' => 50,
1036 'financial_type_id' => 1,
1037 'contact_id' => $this->_individualId
,
1038 'payment_instrument_id' => CRM_Core_PseudoConstant
::getKey('CRM_Contribute_BAO_Contribution', 'payment_instrument_id', 'Check'),
1039 'check_number' => '7890',
1040 'billing_city-5' => 'Vancouver',
1041 'contribution_status_id' => CRM_Core_PseudoConstant
::getKey('CRM_Contribute_BAO_Contribution', 'contribution_status_id', 'Pending'),
1043 $form->postProcess();
1045 $contribution = $this->callAPISuccessGetSingle('Contribution', []);
1046 $this->callAPISuccess('Payment', 'create', ['contribution_id' => $contribution['id'], 'total_amount' => 10, 'payment_instrument_id' => 'Cash']);
1047 $contribution = $this->callAPISuccessGetSingle('Contribution', ['id' => $contribution['id']]);
1048 $this->assertEquals('Partially paid', $contribution['contribution_status']);
1049 // pay additional amount by using Credit Card
1050 $form = new CRM_Contribute_Form_AdditionalPayment();
1052 'contribution_id' => $contribution['id'],
1053 'contact_id' => $this->_individualId
,
1054 'total_amount' => 40,
1055 'currency' => 'USD',
1056 'financial_type_id' => 1,
1057 'payment_instrument_id' => array_search('Credit Card', $this->paymentInstruments
),
1058 'payment_processor_id' => $this->paymentProcessorID
,
1059 'credit_card_exp_date' => ['M' => 5, 'Y' => 2025],
1060 'credit_card_number' => '411111111111111',
1062 'credit_card_type' => 'Visa',
1063 'billing_city-5' => 'Vancouver',
1064 'billing_state_province_id-5' => 1059,
1065 'billing_postal_code-5' => 1321312,
1066 'billing_country_id-5' => 1228,
1067 'trxn_date' => '2017-04-11 13:05:11',
1069 $contribution = $this->callAPISuccessGetSingle('Contribution', []);
1070 $this->assertNotEmpty($contribution);
1071 $this->assertEquals('Completed', $contribution['contribution_status']);
1075 * Test the submit function for FT with tax.
1077 * @param string $thousandSeparator
1079 * @dataProvider getThousandSeparators
1081 public function testSubmitSaleTax($thousandSeparator) {
1082 $this->setCurrencySeparators($thousandSeparator);
1083 $this->enableTaxAndInvoicing();
1084 $this->addTaxAccountToFinancialType($this->_financialTypeId
);
1085 $form = new CRM_Contribute_Form_Contribution();
1088 'total_amount' => $this->formatMoneyInput(1000.00),
1089 'financial_type_id' => $this->_financialTypeId
,
1090 'contact_id' => $this->_individualId
,
1091 'payment_instrument_id' => array_search('Check', $this->paymentInstruments
),
1092 'contribution_status_id' => 1,
1093 'price_set_id' => 0,
1095 CRM_Core_Action
::ADD
1097 $contribution = $this->callAPISuccessGetSingle('Contribution',
1099 'contact_id' => $this->_individualId
,
1100 'return' => ['tax_amount', 'total_amount'],
1103 $this->assertEquals(1100, $contribution['total_amount']);
1104 $this->assertEquals(100, $contribution['tax_amount']);
1105 $this->callAPISuccessGetCount('FinancialTrxn', [], 1);
1106 $this->callAPISuccessGetCount('FinancialItem', [], 2);
1107 $lineItem = $this->callAPISuccessGetSingle('LineItem', ['contribution_id' => $contribution['id']]);
1108 $this->assertEquals(1000, $lineItem['line_total']);
1109 $this->assertEquals(100, $lineItem['tax_amount']);
1111 // CRM-20423: Upon simple submit of 'Edit Contribution' form ensure that total amount is same
1113 'id' => $contribution['id'],
1114 'financial_type_id' => 3,
1115 'contact_id' => $this->_individualId
,
1116 'payment_instrument_id' => array_search('Check', $this->paymentInstruments
),
1117 'contribution_status_id' => 1,
1118 ], CRM_Core_Action
::UPDATE
);
1120 $contribution = $this->callAPISuccessGetSingle('Contribution', ['contact_id' => $this->_individualId
]);
1121 // Check if total amount is unchanged
1122 $this->assertEquals(1100, $contribution['total_amount']);
1126 * Test the submit function for FT without tax.
1128 * @throws \CRM_Core_Exception
1129 * @throws \CiviCRM_API3_Exception
1130 * @throws \Civi\Payment\Exception\PaymentProcessorException
1132 public function testSubmitWithOutSaleTax() {
1133 $this->enableTaxAndInvoicing();
1134 $this->addTaxAccountToFinancialType($this->_financialTypeId
);
1135 $form = new CRM_Contribute_Form_Contribution();
1138 'total_amount' => 100,
1139 'financial_type_id' => 3,
1140 'contact_id' => $this->_individualId
,
1141 'payment_instrument_id' => array_search('Check', $this->paymentInstruments
),
1142 'contribution_status_id' => 1,
1143 'price_set_id' => 0,
1144 ], CRM_Core_Action
::ADD
);
1145 $contribution = $this->callAPISuccessGetSingle('Contribution',
1147 'contact_id' => $this->_individualId
,
1148 'return' => ['tax_amount', 'total_amount'],
1151 $this->assertEquals(100, $contribution['total_amount']);
1152 $this->assertEquals(0, (float) $contribution['tax_amount']);
1153 $this->callAPISuccessGetCount('FinancialTrxn', [], 1);
1154 $this->callAPISuccessGetCount('FinancialItem', [], 1);
1155 $lineItem = $this->callAPISuccessGetSingle('LineItem', [
1156 'contribution_id' => $contribution['id'],
1157 'return' => ['line_total', 'tax_amount'],
1159 $this->assertEquals(100, $lineItem['line_total']);
1160 $this->assertEquals(0.00, $lineItem['tax_amount']);
1164 * Create a contribution & then edit it via backoffice form, checking tax with: default price_set
1166 * @param string $thousandSeparator
1168 * @dataProvider getThousandSeparators
1170 * @throws \Exception
1172 public function testReSubmitSaleTax($thousandSeparator): void
{
1173 $this->setCurrencySeparators($thousandSeparator);
1174 $this->enableTaxAndInvoicing();
1175 $this->addTaxAccountToFinancialType($this->_financialTypeId
);
1176 [$form, $contribution] = $this->doInitialSubmit();
1177 $this->assertEquals(11000, $contribution['total_amount']);
1178 $this->assertEquals(1000, $contribution['tax_amount']);
1179 $this->assertEquals(11000, $contribution['net_amount']);
1181 $mut = new CiviMailUtils($this, TRUE);
1182 // Testing here if when we edit something trivial like adding a check_number tax, net, total amount stay the same:
1184 'id' => $contribution['id'],
1185 'tax_amount' => $contribution['tax_amount'],
1186 'financial_type_id' => $contribution['financial_type_id'],
1187 'receive_date' => $contribution['receive_date'],
1188 'payment_instrument_id' => $contribution['payment_instrument_id'],
1189 'price_set_id' => 0,
1190 'check_number' => 12345,
1191 'contribution_status_id' => 1,
1192 'is_email_receipt' => 1,
1193 'from_email_address' => 'demo@example.com',
1194 ], CRM_Core_Action
::UPDATE
);
1195 $contribution = $this->callAPISuccessGetSingle('Contribution',
1197 'contribution_id' => 1,
1198 'return' => ['tax_amount', 'total_amount', 'net_amount', 'financial_type_id', 'receive_date', 'payment_instrument_id'],
1201 $this->assertEquals(11000, $contribution['total_amount']);
1202 $this->assertEquals(1000, $contribution['tax_amount']);
1203 $this->assertEquals(11000, $contribution['net_amount']);
1206 'Total Tax Amount : $ ' . $this->formatMoneyInput(1000.00),
1207 'Total Amount : $ ' . $this->formatMoneyInput(11000.00),
1208 'Date Received: April 21st, 2015',
1210 'Check Number: 12345',
1213 $mut->checkMailLog($strings);
1214 $this->callAPISuccessGetCount('FinancialTrxn', [], 3);
1215 $items = $this->callAPISuccess('FinancialItem', 'get', ['sequential' => 1])['values'];
1216 $this->assertCount(2, $items);
1217 $this->assertEquals('Contribution Amount', $items[0]['description']);
1218 $this->assertEquals('Sales Tax', $items[1]['description']);
1220 $this->assertEquals(10000, $items[0]['amount']);
1221 $this->assertEquals(1000, $items[1]['amount']);
1225 * Create a contribution & then edit it via backoffice form, checking tax with: default price_set
1227 * @param string $thousandSeparator
1229 * @dataProvider getThousandSeparators
1231 * @throws \Exception
1233 public function testReSubmitSaleTaxAlteredAmount($thousandSeparator) {
1234 $this->setCurrencySeparators($thousandSeparator);
1235 $this->enableTaxAndInvoicing();
1236 $this->addTaxAccountToFinancialType($this->_financialTypeId
);
1237 [$form, $contribution] = $this->doInitialSubmit();
1239 $mut = new CiviMailUtils($this, TRUE);
1240 // Testing here if when we edit something trivial like adding a check_number tax, net, total amount stay the same:
1242 'id' => $contribution['id'],
1243 'total_amount' => $this->formatMoneyInput(20000),
1244 'tax_amount' => $this->formatMoneyInput(2000),
1245 'financial_type_id' => $contribution['financial_type_id'],
1246 'receive_date' => $contribution['receive_date'],
1247 'payment_instrument_id' => $contribution['payment_instrument_id'],
1248 'price_set_id' => 0,
1249 'check_number' => 12345,
1250 'contribution_status_id' => 1,
1251 'is_email_receipt' => 1,
1252 'from_email_address' => 'demo@example.com',
1253 ], CRM_Core_Action
::UPDATE
);
1254 $contribution = $this->callAPISuccessGetSingle('Contribution',
1256 'contribution_id' => 1,
1257 'return' => ['tax_amount', 'total_amount', 'net_amount', 'financial_type_id', 'receive_date', 'payment_instrument_id'],
1260 $this->assertEquals(22000, $contribution['total_amount']);
1261 $this->assertEquals(2000, $contribution['tax_amount']);
1262 $this->assertEquals(22000, $contribution['net_amount']);
1265 'Total Tax Amount : $ ' . $this->formatMoneyInput(2000),
1266 'Total Amount : $ ' . $this->formatMoneyInput(22000.00),
1267 'Date Received: April 21st, 2015',
1269 'Check Number: 12345',
1272 $mut->checkMailLog($strings);
1273 $this->callAPISuccessGetCount('FinancialTrxn', [], 4);
1274 $items = $this->callAPISuccess('FinancialItem', 'get', ['sequential' => 1]);
1275 $this->assertEquals(4, $items['count']);
1276 $this->assertEquals('Contribution Amount', $items['values'][0]['description']);
1277 $this->assertEquals('Sales Tax', $items['values'][1]['description']);
1278 $this->assertEquals('Contribution Amount', $items['values'][0]['description']);
1279 $this->assertEquals('Sales Tax', $items['values'][1]['description']);
1281 $this->assertEquals(10000, $items['values'][0]['amount']);
1282 $this->assertEquals(1000, $items['values'][1]['amount']);
1283 $this->assertEquals(10000, $items['values'][2]['amount']);
1284 $this->assertEquals(1000, $items['values'][3]['amount']);
1288 * Do the first contributions, in preparation for an edit-submit.
1292 * @throws \Exception
1294 protected function doInitialSubmit() {
1295 $form = new CRM_Contribute_Form_Contribution();
1298 'total_amount' => $this->formatMoneyInput(10000),
1299 'financial_type_id' => $this->_financialTypeId
,
1300 'receive_date' => '2015-04-21 00:00:00',
1301 'contact_id' => $this->_individualId
,
1302 'payment_instrument_id' => array_search('Check', $this->paymentInstruments
),
1303 'contribution_status_id' => 1,
1304 'price_set_id' => 0,
1305 ], CRM_Core_Action
::ADD
);
1306 $contribution = $this->callAPISuccessGetSingle('Contribution',
1308 'contribution_id' => 1,
1313 'financial_type_id',
1315 'payment_instrument_id',
1319 $this->assertEquals(11000, $contribution['total_amount']);
1320 $this->assertEquals(1000, $contribution['tax_amount']);
1321 $this->assertEquals(11000, $contribution['net_amount']);
1322 return [$form, $contribution];
1326 * function to test card_type and pan truncation.
1328 public function testCardTypeAndPanTruncation(): void
{
1329 $form = $this->getContributionForm([
1330 'total_amount' => 100,
1331 'financial_type_id' => 3,
1332 'contact_id' => $this->_individualId
,
1333 'payment_instrument_id' => array_search('Credit Card', $this->paymentInstruments
),
1334 'contribution_status_id' => 1,
1335 'credit_card_type' => 'Visa',
1336 'pan_truncation' => 4567,
1337 'price_set_id' => 0,
1339 $form->postProcess();
1340 $contribution = $this->callAPISuccessGetSingle('Contribution',
1342 'contact_id' => $this->_individualId
,
1346 $lastFinancialTrxnId = CRM_Core_BAO_FinancialTrxn
::getFinancialTrxnId($contribution['id'], 'DESC');
1347 $financialTrxn = $this->callAPISuccessGetSingle(
1350 'id' => $lastFinancialTrxnId['financialTrxnId'],
1351 'return' => ['card_type_id.label', 'pan_truncation'],
1354 $this->assertEquals('Visa', $financialTrxn['card_type_id.label']);
1355 $this->assertEquals(4567, $financialTrxn['pan_truncation']);
1359 * Check payment processor is correctly assigned for a contribution page.
1361 * @throws \CRM_Core_Exception
1362 * @throws \CRM_Contribute_Exception_InactiveContributionPageException
1364 public function testContributionBasePreProcess(): void
{
1365 //Create contribution page with only pay later enabled.
1367 'title' => 'Test Contribution Page',
1368 'financial_type_id' => 1,
1369 'currency' => 'NZD',
1370 'goal_amount' => 100,
1371 'is_pay_later' => 1,
1372 'pay_later_text' => 'Send check',
1373 'is_monetary' => TRUE,
1374 'is_active' => TRUE,
1375 'is_email_receipt' => TRUE,
1376 'receipt_from_email' => 'yourconscience@donate.com',
1377 'receipt_from_name' => 'Ego Freud',
1380 $page1 = $this->callAPISuccess('ContributionPage', 'create', $params);
1382 //Execute CRM_Contribute_Form_ContributionBase preProcess
1383 //and check the assignment of payment processors
1384 $form = new CRM_Contribute_Form_ContributionBase();
1385 $form->controller
= new CRM_Core_Controller();
1386 $form->set('id', $page1['id']);
1387 $_REQUEST['id'] = $page1['id'];
1389 $form->preProcess();
1390 $this->assertEquals('pay_later', $form->_paymentProcessor
['name']);
1392 //Disable all the payment processor for the contribution page.
1393 $params['is_pay_later'] = 0;
1394 $page2 = $this->callAPISuccess('ContributionPage', 'create', $params);
1396 //Assert an exception is thrown on loading the contribution page.
1397 $form = new CRM_Contribute_Form_ContributionBase();
1398 $form->controller
= new CRM_Core_Controller();
1399 $_REQUEST['id'] = $page2['id'];
1400 $form->set('id', $page2['id']);
1401 $form->preProcess();
1405 * function to test card_type and pan truncation.
1407 public function testCardTypeAndPanTruncationLiveMode() {
1408 $visaID = CRM_Core_PseudoConstant
::getKey('CRM_Core_BAO_FinancialTrxn', 'card_type_id', 'Visa');
1409 $form = new CRM_Contribute_Form_Contribution();
1410 $form->_mode
= 'Live';
1413 'total_amount' => 50,
1414 'financial_type_id' => 1,
1415 'contact_id' => $this->_individualId
,
1416 'credit_card_number' => 4444333322221111,
1417 'payment_instrument_id' => array_search('Credit Card', $this->paymentInstruments
),
1419 'credit_card_exp_date' => [
1421 'Y' => date('Y', strtotime('+5 years')),
1423 'credit_card_type' => 'Visa',
1424 'billing_first_name' => 'Junko',
1425 'billing_middle_name' => '',
1426 'billing_last_name' => 'Adams',
1427 'billing_street_address-5' => '790L Lincoln St S',
1428 'billing_city-5' => 'Maryknoll',
1429 'billing_state_province_id-5' => 1031,
1430 'billing_postal_code-5' => 10545,
1431 'billing_country_id-5' => 1228,
1432 'frequency_interval' => 1,
1433 'frequency_unit' => 'month',
1434 'installments' => '',
1435 'hidden_AdditionalDetail' => 1,
1436 'hidden_Premium' => 1,
1437 'from_email_address' => '"civi45" <civi45@civicrm.com>',
1438 'receipt_date' => '',
1439 'receipt_date_time' => '',
1440 'payment_processor_id' => $this->paymentProcessorID
,
1441 'currency' => 'USD',
1442 'source' => 'bob sled race',
1444 CRM_Core_Action
::ADD
1446 $contribution = $this->callAPISuccessGetSingle('Contribution', ['contact_id' => $this->_individualId
]);
1447 $lastFinancialTrxnId = CRM_Core_BAO_FinancialTrxn
::getFinancialTrxnId($contribution['id'], 'DESC');
1448 $financialTrxn = $this->callAPISuccessGetSingle(
1451 'id' => $lastFinancialTrxnId['financialTrxnId'],
1452 'return' => ['card_type_id', 'pan_truncation'],
1455 $this->assertEquals($visaID, $financialTrxn['card_type_id']);
1456 $this->assertEquals(1111, $financialTrxn['pan_truncation']);
1460 * CRM-21711 Test that custom fields on relevant memberships get updated wehn
1461 * updating multiple memberships
1463 * @throws \CRM_Core_Exception
1464 * @throws \CiviCRM_API3_Exception
1465 * @throws \Civi\API\Exception\UnauthorizedException
1467 public function testCustomFieldsOnMembershipGetUpdated(): void
{
1468 $contactID = $this->individualCreate();
1469 $contactID1 = $this->organizationCreate();
1470 $contactID2 = $this->organizationCreate();
1472 // create membership types
1473 $membershipTypeOne = civicrm_api3('MembershipType', 'create', [
1476 'member_of_contact_id' => $contactID1,
1477 'duration_unit' => 'year',
1478 'minimum_fee' => 50,
1479 'duration_interval' => 1,
1480 'period_type' => 'fixed',
1481 'fixed_period_start_day' => '101',
1482 'fixed_period_rollover_day' => '1231',
1483 'financial_type_id' => 1,
1486 'visibility' => 'Public',
1489 $membershipTypeTwo = civicrm_api3('MembershipType', 'create', [
1492 'member_of_contact_id' => $contactID2,
1493 'duration_unit' => 'year',
1494 'minimum_fee' => 50,
1495 'duration_interval' => 1,
1496 'period_type' => 'fixed',
1497 'fixed_period_start_day' => '101',
1498 'fixed_period_rollover_day' => '1231',
1499 'financial_type_id' => 1,
1502 'visibility' => 'Public',
1505 //create custom Fields
1506 $membershipCustomFieldsGroup = civicrm_api3('CustomGroup', 'create', [
1507 'title' => 'Custom Fields on Membership',
1508 'extends' => 'Membership',
1511 $membershipCustomField = civicrm_api3('CustomField', 'create', [
1512 'custom_group_id' => $membershipCustomFieldsGroup['id'],
1513 'name' => 'my_membership_custom_field',
1514 'label' => 'Membership Custom Field',
1515 'data_type' => 'String',
1516 'html_type' => 'Text',
1517 'is_active' => TRUE,
1518 'text_length' => 255,
1522 $membershipCustomFieldsProfile = civicrm_api3('UFGroup', 'create', [
1524 "group_type" => "Membership,Individual",
1525 "title" => "Membership Custom Fields",
1526 "add_captcha" => "0",
1528 "is_edit_link" => "0",
1529 "is_uf_link" => "0",
1530 "is_update_dupe" => "0",
1533 // add custom fields to profile
1534 civicrm_api3('UFField', 'create', [
1535 "uf_group_id" => $membershipCustomFieldsProfile['id'],
1536 "field_name" => "custom_" . $membershipCustomField['id'],
1538 "visibility" => "User and User Admin Only",
1539 "in_selector" => "0",
1540 "is_searchable" => "0",
1541 "label" => "custom text field on membership",
1542 "field_type" => "Membership",
1545 $contribPage = civicrm_api3('ContributionPage', 'create', [
1546 "title" => "Membership",
1547 "financial_type_id" => 1,
1548 'financial_account_id' => 1,
1549 "is_credit_card_only" => "0",
1550 "is_monetary" => "0",
1552 "is_confirm_enabled" => "1",
1553 "is_recur_interval" => "0",
1554 "is_recur_installments" => "0",
1555 "adjust_recur_start_date" => "0",
1556 "is_pay_later" => "1",
1557 "pay_later_text" => "I will send payment by check",
1558 "is_partial_payment" => "0",
1559 "is_email_receipt" => "0",
1561 "amount_block_is_active" => "0",
1562 "currency" => "USD",
1564 "is_billing_required" => "0",
1565 "contribution_type_id" => "2",
1566 'is_allow_other_amount' => 1,
1568 'max_amount' => 1000,
1570 $contribPage1 = $contribPage['id'];
1572 //create price set with two options for the two different memberships
1573 $priceSet = civicrm_api3('PriceSet', 'create', [
1574 'title' => "Two Membership Type Checkbox",
1575 'extends' => "CiviMember",
1577 "financial_type_id" => "1",
1579 CRM_Core_DAO
::executeQuery("INSERT INTO civicrm_price_set_entity (entity_table, entity_id, price_set_id) VALUES('civicrm_contribution_page', $contribPage1, {$priceSet['id']})");
1581 $priceField = civicrm_api3('PriceField', 'create', [
1582 'price_set_id' => $priceSet['id'],
1584 "label" => "Membership Types",
1585 "html_type" => "CheckBox",
1586 "is_enter_qty" => "0",
1588 "is_display_amounts" => "1",
1589 "options_per_line" => "1",
1591 "is_required" => "0",
1592 "visibility_id" => "1",
1595 $priceFieldOption1 = civicrm_api3('PriceFieldValue', 'create', [
1596 "price_field_id" => $priceField['id'],
1597 "name" => "membership_type_one",
1598 "label" => "Membership Type One",
1601 "membership_type_id" => $membershipTypeOne['id'],
1602 "membership_num_terms" => "1",
1603 "is_default" => "0",
1605 "financial_type_id" => "1",
1606 "non_deductible_amount" => "0.00",
1607 "contribution_type_id" => "2",
1610 $priceFieldOption2 = civicrm_api3('PriceFieldValue', 'create', [
1611 "price_field_id" => $priceField['id'],
1612 "name" => "membership_type_two",
1613 "label" => "Membership Type Two",
1616 "membership_type_id" => $membershipTypeTwo['id'],
1617 "membership_num_terms" => "1",
1618 "is_default" => "0",
1620 "financial_type_id" => "1",
1621 "non_deductible_amount" => "0.00",
1622 "contribution_type_id" => "2",
1625 // assign profile with custom fields to contribution page
1626 civicrm_api3('UFJoin', 'create', [
1627 'module' => "CiviContribute",
1629 'uf_group_id' => $membershipCustomFieldsProfile['id'],
1630 "entity_table" => "civicrm_contribution_page",
1631 "entity_id" => $contribPage1,
1634 $form = new CRM_Contribute_Form_Contribution_Confirm();
1636 'id' => $contribPage1,
1637 'qfKey' => "donotcare",
1638 "custom_{$membershipCustomField['id']}" => "Hello",
1639 "priceSetId" => $priceSet['id'],
1640 'price_set_id' => $priceSet['id'],
1641 "price_" . $priceField['id'] => [$priceFieldOption1['id'] => 1, $priceFieldOption2['id'] => 1],
1642 'invoiceID' => "9a6f7b49358dc31c3604e463b225c5be",
1643 'email' => "admin@example.com",
1644 "currencyID" => "USD",
1645 'description' => "Membership Contribution",
1646 'contact_id' => $contactID,
1647 'skipLineItem' => 0,
1648 'email-5' => 'test@test.com',
1650 'tax_amount' => 0.00,
1651 'is_pay_later' => 1,
1652 'is_quick_config' => 1,
1654 $form->submit($form->_params
);
1655 $membership1 = civicrm_api3('Membership', 'getsingle', [
1656 'contact_id' => $contactID,
1657 'membership_type_id' => $membershipTypeOne['id'],
1659 $this->assertEquals("Hello", $membership1["custom_{$membershipCustomField['id']}"]);
1661 $membership2 = civicrm_api3('Membership', 'getsingle', [
1662 'contact_id' => $contactID,
1663 'membership_type_id' => $membershipTypeTwo['id'],
1665 $this->assertEquals("Hello", $membership2["custom_{$membershipCustomField['id']}"]);
1669 * Test non-membership donation on a contribution page
1670 * using membership priceset.
1672 public function testDonationOnMembershipPagePriceset() {
1673 $contactID = $this->individualCreate();
1674 $this->createPriceSetWithPage();
1675 $form = new CRM_Contribute_Form_Contribution_Confirm();
1676 $form->controller
= new CRM_Core_Controller();
1678 'id' => $this->_ids
['contribution_page'],
1679 "qfKey" => "donotcare",
1680 "priceSetId" => $this->_ids
['price_set'],
1681 'price_set_id' => $this->_ids
['price_set'],
1682 "price_" . $this->_ids
['price_field'][0] => $this->_ids
['price_field_value']['cont'],
1683 "invoiceID" => "9a6f7b49358dc31c3604e463b225c5be",
1684 "email" => "admin@example.com",
1685 "currencyID" => "USD",
1686 'description' => "Membership Contribution",
1687 'contact_id' => $contactID,
1688 'select_contact_id' => $contactID,
1689 'useForMember' => 1,
1690 'skipLineItem' => 0,
1691 'email-5' => 'test@test.com',
1693 'tax_amount' => NULL,
1694 'is_pay_later' => 1,
1695 'is_quick_config' => 1,
1697 $form->submit($form->_params
);
1699 $contribution = $this->callAPISuccessGetSingle('Contribution', [
1700 'contact_id' => $contactID,
1702 //Check no membership is created.
1703 $this->callAPIFailure('Membership', 'getsingle', [
1704 'contact_id' => $contactID,
1706 $this->contributionDelete($contribution['id']);
1708 //Choose Membership Priceset
1709 $form->_params
["price_{$this->_ids['price_field'][0]}"] = $this->_ids
['price_field_value'][0];
1710 $form->_params
["amount"] = 20;
1711 $form->submit($form->_params
);
1713 $contribution = $this->callAPISuccessGetSingle('Contribution', [
1714 'contact_id' => $contactID,
1716 //Check membership is created for the contact.
1717 $membership = $this->callAPISuccessGetSingle('Membership', [
1718 'contact_id' => $contactID,
1720 $membershipPayment = $this->callAPISuccessGetSingle('MembershipPayment', [
1721 'contribution_id' => $contribution['id'],
1723 $this->assertEquals($membershipPayment['membership_id'], $membership['id']);
1724 $this->membershipDelete($membership['id']);
1728 * Test no warnings or errors during preProcess when editing.
1730 public function testPreProcessContributionEdit() {
1731 // Simulate a contribution in pending status
1732 $contribution = $this->callAPISuccess(
1735 array_merge($this->_params
, ['contribution_status_id' => 'Pending'])
1738 // set up the form to edit the contribution and call preProcess
1739 $form = $this->getFormObject('CRM_Contribute_Form_Contribution');
1740 $_REQUEST['cid'] = $this->_individualId
;
1741 $_REQUEST['id'] = $contribution['id'];
1742 $form->_action
= CRM_Core_Action
::UPDATE
;
1743 $form->preProcess();
1745 // Check something while we're here
1746 $this->assertEquals($contribution['id'], $form->_values
['contribution_id']);
1748 unset($_REQUEST['cid']);
1749 unset($_REQUEST['id']);
1753 * Mostly just check there's no errors opening the Widget tab on contribution
1756 public function testOpeningWidgetAdminPage() {
1757 $page_id = $this->callAPISuccess('ContributionPage', 'create', [
1758 'title' => 'my page',
1759 'financial_type_id' => $this->_financialTypeId
,
1760 'payment_processor' => $this->paymentProcessorID
,
1763 $form = new CRM_Contribute_Form_ContributionPage_Widget();
1764 $form->controller
= new CRM_Core_Controller_Simple('CRM_Contribute_Form_ContributionPage_Widget', 'Widget');
1766 $form->set('reset', '1');
1767 $form->set('action', 'update');
1768 $form->set('id', $page_id);
1771 $form->controller
->_actions
['display']->perform($form, 'display');
1772 $contents = ob_get_contents();
1775 // The page contents load later by ajax, so there's just the surrounding
1776 // html available now, but we can check at least one thing while we're here.
1777 $this->assertStringContainsString("mainTabContainer", $contents);
1781 * Test AdditionalInfo::postProcessCommon
1782 * @dataProvider additionalInfoProvider
1783 * @param array $input
1784 * @param array $expectedFormatted
1786 public function testAdditionalInfoPostProcessCommon(array $input, array $expectedFormatted) {
1788 $dummy = new CRM_Contribute_Form_AdditionalInfo();
1789 CRM_Contribute_Form_AdditionalInfo
::postProcessCommon($input, $formatted, $dummy);
1790 $this->assertEquals($expectedFormatted, $formatted);
1794 * Dataprovider for testAdditionalInfoPostProcessCommon
1797 public function additionalInfoProvider(): array {
1801 'qfKey' => 'CRMContributeFormContributionu2pbzqqmz74oscck4ss4osccw4wgccc884wkk4ws0o8wgss4w_8953',
1802 'entryURL' => 'http://example.org/civicrm/contact/view/contribution?reset=1&action=add&cid=1&context=contribution',
1803 'check_number' => '',
1804 'frequency_interval' => '1',
1805 'hidden_AdditionalDetail' => '1',
1806 'contact_id' => '1',
1807 'financial_type_id' => '1',
1808 'payment_instrument_id' => '4',
1810 'from_email_address' => '2',
1811 'contribution_status_id' => '1',
1812 // This is unused here but is iffy to put in a dataprovider
1813 'receive_date' => '2021-01-14 11:12:13',
1814 'receipt_date' => '',
1815 'cancel_date' => '',
1816 'cancel_reason' => '',
1817 'price_set_id' => '',
1818 'total_amount' => 10,
1819 'currency' => 'USD',
1820 'source' => 'a source',
1821 'soft_credit_contact_id' => [
1833 'soft_credit_amount' => [
1845 'soft_credit_type' => [
1857 'sct_default_id' => '3',
1858 'MAX_FILE_SIZE' => '2097152',
1859 'ip_address' => '127.0.0.1',
1866 'non_deductible_amount' => NULL,
1867 'total_amount' => 10,
1868 'fee_amount' => NULL,
1870 'invoice_id' => NULL,
1871 'creditnote_id' => NULL,
1872 'campaign_id' => NULL,
1873 'contribution_page_id' => NULL,
1874 'thankyou_date' => 'null',
1881 'qfKey' => 'CRMContributeFormContributionu2pbzqqmz74oscck4ss4osccw4wgccc884wkk4ws0o8wgss4w_8953',
1882 'entryURL' => 'http://example.org/civicrm/contact/view/contribution?reset=1&action=add&cid=1&context=contribution',
1884 'frequency_interval' => '1',
1885 'hidden_AdditionalDetail' => '1',
1886 'thankyou_date' => '2021-01-14',
1887 'non_deductible_amount' => '0.00',
1888 'fee_amount' => '0.00',
1890 'creditnote_id' => '',
1891 'contribution_page_id' => '',
1893 'contact_id' => '1',
1894 'financial_type_id' => '1',
1895 'from_email_address' => '2',
1896 'contribution_status_id' => '1',
1897 // This is unused here but is iffy to put in a dataprovider
1898 'receive_date' => '2021-01-14 11:12:13',
1899 'receipt_date' => '',
1900 'cancel_date' => '',
1901 'cancel_reason' => '',
1902 'price_set_id' => '',
1903 'total_amount' => '10.00',
1904 'currency' => 'USD',
1905 'source' => 'a source',
1906 'soft_credit_contact_id' => [
1918 'soft_credit_amount' => [
1930 'soft_credit_type' => [
1942 'sct_default_id' => '3',
1943 'MAX_FILE_SIZE' => '2097152',
1944 'ip_address' => '127.0.0.1',
1945 // leaving out since don't want to enforce string 'null' in a test
1946 //'tax_amount' => 'null',
1949 'non_deductible_amount' => '0.00',
1950 'total_amount' => '10.00',
1951 'fee_amount' => '0.00',
1954 'creditnote_id' => '',
1955 'campaign_id' => NULL,
1956 'contribution_page_id' => NULL,
1957 'thankyou_date' => '20210114000000',
1962 'date-and-time' => [
1964 'qfKey' => 'CRMContributeFormContributionu2pbzqqmz74oscck4ss4osccw4wgccc884wkk4ws0o8wgss4w_8953',
1965 'entryURL' => 'http://example.org/civicrm/contact/view/contribution?reset=1&action=add&cid=1&context=contribution',
1967 'frequency_interval' => '1',
1968 'hidden_AdditionalDetail' => '1',
1969 'thankyou_date' => '2021-01-14 10:11:12',
1970 'non_deductible_amount' => '0.00',
1971 'fee_amount' => '0.00',
1973 'creditnote_id' => '',
1974 'contribution_page_id' => '',
1976 'contact_id' => '1',
1977 'financial_type_id' => '1',
1978 'from_email_address' => '2',
1979 'contribution_status_id' => '1',
1980 // This is unused here but is iffy to put in a dataprovider
1981 'receive_date' => '2021-01-14 11:12:13',
1982 'receipt_date' => '',
1983 'cancel_date' => '',
1984 'cancel_reason' => '',
1985 'price_set_id' => '',
1986 'total_amount' => '10.00',
1987 'currency' => 'USD',
1988 'source' => 'a source',
1989 'soft_credit_contact_id' => [
2001 'soft_credit_amount' => [
2013 'soft_credit_type' => [
2025 'sct_default_id' => '3',
2026 'MAX_FILE_SIZE' => '2097152',
2027 'ip_address' => '127.0.0.1',
2028 // leaving out since don't want to enforce string 'null' in a test
2029 //'tax_amount' => 'null',
2032 'non_deductible_amount' => '0.00',
2033 'total_amount' => '10.00',
2034 'fee_amount' => '0.00',
2037 'creditnote_id' => '',
2038 'campaign_id' => NULL,
2039 'contribution_page_id' => NULL,
2040 'thankyou_date' => '20210114101112',
2050 public function testContributionFormRule() {
2052 'contact_id' => $this->_individualId
,
2053 'financial_type_id' => CRM_Core_PseudoConstant
::getKey('CRM_Contribute_BAO_Contribution', 'financial_type_id', 'Donation'),
2054 'currency' => 'USD',
2055 'total_amount' => '10',
2056 'price_set_id' => '',
2058 'contribution_status_id' => CRM_Core_PseudoConstant
::getKey('CRM_Contribute_BAO_Contribution', 'contribution_status_id', 'Completed'),
2059 'cancel_date' => '',
2060 'cancel_reason' => '',
2061 'receive_date' => date('Y-m-d H:i:s'),
2062 'from_email_address' => key(CRM_Core_BAO_Email
::getFromEmail()),
2063 'receipt_date' => '',
2064 'payment_instrument_id' => CRM_Core_PseudoConstant
::getKey('CRM_Contribute_BAO_Contribution', 'payment_instrument_id', 'Check'),
2066 'check_number' => '',
2067 'soft_credit_contact_id' => [
2079 'soft_credit_amount' => [
2091 'soft_credit_type' => [
2105 $form = new CRM_Contribute_Form_Contribution();
2106 $this->assertSame([], $form::formRule($fields, [], $form));
2110 * Check that formRule validates you can only have one contribution with a
2113 public function testContributionFormRuleDuplicateTrxn() {
2114 $contribution = $this->callAPISuccess('Contribution', 'create', array_merge($this->_params
, ['trxn_id' => '1234']));
2117 'contact_id' => $this->_individualId
,
2118 'financial_type_id' => CRM_Core_PseudoConstant
::getKey('CRM_Contribute_BAO_Contribution', 'financial_type_id', 'Donation'),
2119 'currency' => 'USD',
2120 'total_amount' => '10',
2121 'price_set_id' => '',
2123 'contribution_status_id' => CRM_Core_PseudoConstant
::getKey('CRM_Contribute_BAO_Contribution', 'contribution_status_id', 'Completed'),
2124 'cancel_date' => '',
2125 'cancel_reason' => '',
2126 'receive_date' => date('Y-m-d H:i:s'),
2127 'from_email_address' => key(CRM_Core_BAO_Email
::getFromEmail()),
2128 'receipt_date' => '',
2129 'payment_instrument_id' => CRM_Core_PseudoConstant
::getKey('CRM_Contribute_BAO_Contribution', 'payment_instrument_id', 'Check'),
2130 'trxn_id' => '1234',
2131 'check_number' => '',
2132 'soft_credit_contact_id' => [
2144 'soft_credit_amount' => [
2156 'soft_credit_type' => [
2170 $form = new CRM_Contribute_Form_Contribution();
2171 $this->assertEquals(['trxn_id' => "Transaction ID's must be unique. Transaction '1234' already exists in your database."], $form->formRule($fields, [], $form));
2175 * Get the contribution form object.
2177 * @param array $formValues
2179 * @return \CRM_Contribute_Form_Contribution
2181 protected function getContributionForm(array $formValues): CRM_Contribute_Form_Contribution
{
2182 /* @var CRM_Contribute_Form_Contribution $form */
2183 $form = $this->getFormObject('CRM_Contribute_Form_Contribution', $formValues);
2189 * Get the payment instrument ID.
2191 * Function just exists to avoid line-wrapping hell with the
2192 * longer function it calls.
2194 * @param string $name
2198 protected function getPaymentInstrument(string $name): int {
2199 return CRM_Core_PseudoConstant
::getKey('CRM_Contribute_BAO_Contribution', 'payment_instrument_id', $name);