comment tidies
[civicrm-core.git] / tests / phpunit / api / v3 / ContributionPageTest.php
CommitLineData
6a488035
TO
1<?php
2/*
3 +--------------------------------------------------------------------+
81621fee 4 | CiviCRM version 4.7 |
6a488035 5 +--------------------------------------------------------------------+
e7112fa7 6 | Copyright CiviCRM LLC (c) 2004-2015 |
6a488035
TO
7 +--------------------------------------------------------------------+
8 | This file is a part of CiviCRM. |
9 | |
10 | CiviCRM is free software; you can copy, modify, and distribute it |
11 | under the terms of the GNU Affero General Public License |
12 | Version 3, 19 November 2007 and the CiviCRM Licensing Exception. |
13 | |
14 | CiviCRM is distributed in the hope that it will be useful, but |
15 | WITHOUT ANY WARRANTY; without even the implied warranty of |
16 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. |
17 | See the GNU Affero General Public License for more details. |
18 | |
19 | You should have received a copy of the GNU Affero General Public |
20 | License and the CiviCRM Licensing Exception along |
21 | with this program; if not, contact CiviCRM LLC |
22 | at info[AT]civicrm[DOT]org. If you have questions about the |
23 | GNU Affero General Public License or the licensing of CiviCRM, |
24 | see the CiviCRM license FAQ at http://civicrm.org/licensing |
25 +--------------------------------------------------------------------+
d25dd0ee 26 */
6a488035
TO
27
28require_once 'CiviTest/CiviUnitTestCase.php';
dd1b539a 29require_once 'CiviTest/CiviMailUtils.php';
6a488035
TO
30
31/**
32 * Test APIv3 civicrm_contribute_recur* functions
33 *
6c6e6187
TO
34 * @package CiviCRM_APIv3
35 * @subpackage API_Contribution
6a488035 36 */
6a488035
TO
37class api_v3_ContributionPageTest extends CiviUnitTestCase {
38 protected $_apiversion = 3;
39 protected $testAmount = 34567;
40 protected $params;
41 protected $id = 0;
42 protected $contactIds = array();
43 protected $_entity = 'contribution_page';
6c6e6187 44 protected $contribution_result = NULL;
f64a217a 45 protected $_priceSetParams = array();
f8fe0df6 46 /**
eceb18cc 47 * Payment processor details.
f8fe0df6 48 * @var array
49 */
50 protected $_paymentProcessor = array();
f64a217a
EM
51
52 /**
53 * @var array
16b10e64
CW
54 * - contribution_page
55 * - price_set
56 * - price_field
57 * - price_field_value
f64a217a
EM
58 */
59 protected $_ids = array();
60
b7c9bc4c 61
6a488035 62 public $DBResetRequired = TRUE;
5896d037 63
6a488035
TO
64 public function setUp() {
65 parent::setUp();
66 $this->contactIds[] = $this->individualCreate();
67 $this->params = array(
6a488035
TO
68 'title' => "Test Contribution Page",
69 'financial_type_id' => 1,
70 'currency' => 'NZD',
71 'goal_amount' => $this->testAmount,
6cdac50b 72 'is_pay_later' => 1,
f64a217a 73 'is_monetary' => TRUE,
dd1b539a 74 'is_email_receipt' => TRUE,
75 'receipt_from_email' => 'yourconscience@donate.com',
76 'receipt_from_name' => 'Ego Freud',
f64a217a
EM
77 );
78
79 $this->_priceSetParams = array(
80 'is_quick_config' => 1,
81 'extends' => 'CiviContribute',
82 'financial_type_id' => 'Donation',
21dfd5f5 83 'title' => 'my Page',
6a488035
TO
84 );
85 }
86
00be9182 87 public function tearDown() {
6a488035 88 foreach ($this->contactIds as $id) {
fc928539 89 $this->callAPISuccess('contact', 'delete', array('id' => $id));
611c7ece 90 }
f9342903 91 $this->quickCleanUpFinancialEntities();
6a488035
TO
92 }
93
94 public function testCreateContributionPage() {
fc928539 95 $result = $this->callAPIAndDocument($this->_entity, 'create', $this->params, __FUNCTION__, __FILE__);
96 $this->assertEquals(1, $result['count']);
97 $this->assertNotNull($result['values'][$result['id']]['id']);
6a488035
TO
98 $this->getAndCheck($this->params, $result['id'], $this->_entity);
99 }
100
101 public function testGetBasicContributionPage() {
fc928539 102 $createResult = $this->callAPISuccess($this->_entity, 'create', $this->params);
6a488035 103 $this->id = $createResult['id'];
6a488035 104 $getParams = array(
6a488035
TO
105 'currency' => 'NZD',
106 'financial_type_id' => 1,
107 );
fc928539 108 $getResult = $this->callAPIAndDocument($this->_entity, 'get', $getParams, __FUNCTION__, __FILE__);
109 $this->assertEquals(1, $getResult['count']);
6a488035
TO
110 }
111
112 public function testGetContributionPageByAmount() {
fc928539 113 $createResult = $this->callAPISuccess($this->_entity, 'create', $this->params);
6a488035 114 $this->id = $createResult['id'];
6a488035 115 $getParams = array(
5896d037 116 'amount' => '' . $this->testAmount, // 3456
6a488035
TO
117 'currency' => 'NZD',
118 'financial_type_id' => 1,
119 );
fc928539 120 $getResult = $this->callAPIAndDocument($this->_entity, 'get', $getParams, __FUNCTION__, __FILE__);
121 $this->assertEquals(1, $getResult['count']);
6a488035
TO
122 }
123
124 public function testDeleteContributionPage() {
fc928539 125 $createResult = $this->callAPISuccess($this->_entity, 'create', $this->params);
126 $deleteParams = array('id' => $createResult['id']);
611c7ece 127 $this->callAPIAndDocument($this->_entity, 'delete', $deleteParams, __FUNCTION__, __FILE__);
fc928539 128 $checkDeleted = $this->callAPISuccess($this->_entity, 'get', array());
129 $this->assertEquals(0, $checkDeleted['count']);
6a488035
TO
130 }
131
132 public function testGetFieldsContributionPage() {
fc928539 133 $result = $this->callAPISuccess($this->_entity, 'getfields', array('action' => 'create'));
6a488035
TO
134 $this->assertEquals(12, $result['values']['start_date']['type']);
135 }
136
be26f3e0 137
d58b453e 138 /**
eceb18cc 139 * Test form submission with basic price set.
d58b453e 140 */
be26f3e0 141 public function testSubmit() {
f64a217a
EM
142 $this->setUpContributionPage();
143 $priceFieldID = reset($this->_ids['price_field']);
144 $priceFieldValueID = reset($this->_ids['price_field_value']);
145 $submitParams = array(
146 'price_' . $priceFieldID => $priceFieldValueID,
147 'id' => (int) $this->_ids['contribution_page'],
21dfd5f5 148 'amount' => 10,
be26f3e0
EM
149 );
150
f64a217a
EM
151 $this->callAPISuccess('contribution_page', 'submit', $submitParams);
152 $this->callAPISuccess('contribution', 'getsingle', array('contribution_page_id' => $this->_ids['contribution_page']));
153 }
5896d037 154
870156d6 155 /**
156 * Test form submission with billing first & last name where the contact does NOT
157 * otherwise have one.
158 */
159 public function testSubmitNewBillingNameData() {
160 $this->setUpContributionPage();
161 $contact = $this->callAPISuccess('Contact', 'create', array('contact_type' => 'Individual', 'email' => 'wonderwoman@amazon.com'));
162 $priceFieldID = reset($this->_ids['price_field']);
163 $priceFieldValueID = reset($this->_ids['price_field_value']);
164 $submitParams = array(
165 'price_' . $priceFieldID => $priceFieldValueID,
166 'id' => (int) $this->_ids['contribution_page'],
167 'amount' => 10,
168 'billing_first_name' => 'Wonder',
169 'billing_last_name' => 'Woman',
170 'contactID' => $contact['id'],
171 'email' => 'wonderwoman@amazon.com',
172 );
173
174 $this->callAPISuccess('contribution_page', 'submit', $submitParams);
175 $contact = $this->callAPISuccess('Contact', 'get', array(
176 'id' => $contact['id'],
177 'return' => array(
178 'first_name',
179 'last_name',
180 'sort_name',
181 'display_name',
182 ),
183 ));
184 $this->assertEquals(array(
185 'first_name' => 'Wonder',
186 'last_name' => 'Woman',
187 'display_name' => 'Wonder Woman',
188 'sort_name' => 'Woman, Wonder',
189 'id' => $contact['id'],
190 'contact_id' => $contact['id'],
191 ), $contact['values'][$contact['id']]);
192
193 }
194
195 /**
196 * Test form submission with billing first & last name where the contact does
197 * otherwise have one and should not be overwritten.
198 */
199 public function testSubmitNewBillingNameDoNotOverwrite() {
200 $this->setUpContributionPage();
201 $contact = $this->callAPISuccess('Contact', 'create', array(
202 'contact_type' => 'Individual',
203 'email' => 'wonderwoman@amazon.com',
204 'first_name' => 'Super',
205 'last_name' => 'Boy',
206 ));
207 $priceFieldID = reset($this->_ids['price_field']);
208 $priceFieldValueID = reset($this->_ids['price_field_value']);
209 $submitParams = array(
210 'price_' . $priceFieldID => $priceFieldValueID,
211 'id' => (int) $this->_ids['contribution_page'],
212 'amount' => 10,
213 'billing_first_name' => 'Wonder',
214 'billing_last_name' => 'Woman',
215 'contactID' => $contact['id'],
216 'email' => 'wonderwoman@amazon.com',
217 );
218
219 $this->callAPISuccess('contribution_page', 'submit', $submitParams);
220 $contact = $this->callAPISuccess('Contact', 'get', array(
221 'id' => $contact['id'],
222 'return' => array(
223 'first_name',
224 'last_name',
225 'sort_name',
226 'display_name',
227 ),
228 ));
229 $this->assertEquals(array(
230 'first_name' => 'Super',
231 'last_name' => 'Boy',
232 'display_name' => 'Super Boy',
233 'sort_name' => 'Boy, Super',
234 'id' => $contact['id'],
235 'contact_id' => $contact['id'],
236 ), $contact['values'][$contact['id']]);
237
238 }
239
7bc789a5 240 /**
241 * Test process with instant payment when more than one configured for the page.
242 *
243 * CRM-16923
244 */
245 public function testSubmitRecurMultiProcessorInstantPayment() {
246 $this->setUpContributionPage();
247 $this->setupPaymentProcessor();
d27635dc 248 $paymentProcessor2ID = $this->paymentProcessorCreate(array(
7bc789a5 249 'payment_processor_type_id' => 'Dummy',
250 'name' => 'processor 2',
251 'class_name' => 'Payment_Dummy',
252 'billing_mode' => 1,
253 ));
254 $dummyPP = Civi\Payment\System::singleton()->getById($paymentProcessor2ID);
70cc8754 255 $dummyPP->setDoDirectPaymentResult(array(
256 'payment_status_id' => 1,
257 'trxn_id' => 'create_first_success',
258 'fee_amount' => .85,
259 ));
7bc789a5 260 $this->callAPISuccess('ContributionPage', 'create', array(
d27635dc 261 'id' => $this->_ids['contribution_page'],
262 'payment_processor' => array($paymentProcessor2ID, $this->_ids['payment_processor']),
7bc789a5 263 ));
264
265 $priceFieldID = reset($this->_ids['price_field']);
266 $priceFieldValueID = reset($this->_ids['price_field_value']);
267 $submitParams = array(
268 'price_' . $priceFieldID => $priceFieldValueID,
269 'id' => (int) $this->_ids['contribution_page'],
270 'amount' => 10,
271 'is_recur' => 1,
272 'frequency_interval' => 1,
273 'frequency_unit' => 'month',
274 'payment_processor_id' => $paymentProcessor2ID,
275 );
276
277 $this->callAPISuccess('contribution_page', 'submit', $submitParams);
70cc8754 278 $contribution = $this->callAPISuccess('contribution', 'getsingle', array(
7bc789a5 279 'contribution_page_id' => $this->_ids['contribution_page'],
280 'contribution_status_id' => 1,
281 ));
70cc8754 282 $this->assertEquals('create_first_success', $contribution['trxn_id']);
283 $this->assertEquals(10, $contribution['total_amount']);
284 $this->assertEquals(.85, $contribution['fee_amount']);
285 $this->assertEquals(9.15, $contribution['net_amount']);
7bc789a5 286 }
70cc8754 287
f64a217a 288 /**
eceb18cc 289 * Test submit with a membership block in place.
f64a217a 290 */
f9342903
EM
291 public function testSubmitMembershipBlockNotSeparatePayment() {
292 $this->setUpMembershipContributionPage();
f64a217a 293 $submitParams = array(
3e28c791 294 'price_' . $this->_ids['price_field'][0] => reset($this->_ids['price_field_value']),
f9342903 295 'id' => (int) $this->_ids['contribution_page'],
f64a217a
EM
296 'amount' => 10,
297 'billing_first_name' => 'Billy',
298 'billing_middle_name' => 'Goat',
299 'billing_last_name' => 'Gruff',
300 'selectMembership' => $this->_ids['membership_type'],
301
302 );
303
a828d7b8 304 $this->callAPIAndDocument('contribution_page', 'submit', $submitParams, __FUNCTION__, __FILE__, 'submit contribution page', NULL);
f9342903 305 $contribution = $this->callAPISuccess('contribution', 'getsingle', array('contribution_page_id' => $this->_ids['contribution_page']));
f64a217a 306 $this->callAPISuccess('membership_payment', 'getsingle', array('contribution_id' => $contribution['id']));
f9342903
EM
307 }
308
2f59d010 309 /**
310 * Test submit with a membership block in place.
311 */
312 public function testSubmitMembershipBlockNotSeparatePaymentWithEmail() {
313 $mut = new CiviMailUtils($this, TRUE);
314 $this->setUpMembershipContributionPage();
315 $this->addProfile('supporter_profile', $this->_ids['contribution_page']);
316
317 $submitParams = array(
318 'price_' . $this->_ids['price_field'][0] => reset($this->_ids['price_field_value']),
319 'id' => (int) $this->_ids['contribution_page'],
320 'amount' => 10,
321 'billing_first_name' => 'Billy',
322 'billing_middle_name' => 'Goat',
323 'billing_last_name' => 'Gruff',
324 'selectMembership' => $this->_ids['membership_type'],
325 'email-Primary' => 'billy-goat@the-bridge.net',
326 );
327
328 $this->callAPIAndDocument('contribution_page', 'submit', $submitParams, __FUNCTION__, __FILE__, 'submit contribution page', NULL);
329 $contribution = $this->callAPISuccess('contribution', 'getsingle', array('contribution_page_id' => $this->_ids['contribution_page']));
330 $this->callAPISuccess('membership_payment', 'getsingle', array('contribution_id' => $contribution['id']));
331 $mut->checkMailLog(array(
332 'Membership Type: General',
333 ));
334 $mut->stop();
335 $mut->clearMessages();
336 }
337
338 /**
339 * Test submit with a membership block in place.
340 */
341 public function testSubmitMembershipBlockNotSeparatePaymentZeroDollarsWithEmail() {
342 $mut = new CiviMailUtils($this, TRUE);
343 $this->_ids['membership_type'] = array($this->membershipTypeCreate(array('minimum_fee' => 0)));
344 $this->setUpMembershipContributionPage();
345 $this->addProfile('supporter_profile', $this->_ids['contribution_page']);
346
347 $submitParams = array(
348 'price_' . $this->_ids['price_field'][0] => reset($this->_ids['price_field_value']),
349 'id' => (int) $this->_ids['contribution_page'],
350 'amount' => 0,
351 'billing_first_name' => 'Billy',
352 'billing_middle_name' => 'Goat',
353 'billing_last_name' => 'Gruffier',
354 'selectMembership' => $this->_ids['membership_type'],
355 'email-Primary' => 'billy-goat@the-new-bridge.net',
356 );
357
358 $this->callAPIAndDocument('contribution_page', 'submit', $submitParams, __FUNCTION__, __FILE__, 'submit contribution page', NULL);
359 $contribution = $this->callAPISuccess('contribution', 'getsingle', array('contribution_page_id' => $this->_ids['contribution_page']));
360 $this->callAPISuccess('membership_payment', 'getsingle', array('contribution_id' => $contribution['id']));
361 $mut->checkMailLog(array(
362 'Membership Type: General',
363 'Gruffier',
364 ),
365 array(
366 'Amount',
367 )
368 );
369 $mut->stop();
370 $mut->clearMessages();
371 }
372
f9342903 373 /**
eceb18cc 374 * Test submit with a membership block in place.
f9342903
EM
375 */
376 public function testSubmitMembershipBlockIsSeparatePayment() {
377 $this->setUpMembershipContributionPage(TRUE);
378 $submitParams = array(
3e28c791 379 'price_' . $this->_ids['price_field'][0] => reset($this->_ids['price_field_value']),
f9342903
EM
380 'id' => (int) $this->_ids['contribution_page'],
381 'amount' => 10,
382 'billing_first_name' => 'Billy',
383 'billing_middle_name' => 'Goat',
384 'billing_last_name' => 'Gruff',
385 'selectMembership' => $this->_ids['membership_type'],
386 );
387
a828d7b8 388 $this->callAPIAndDocument('contribution_page', 'submit', $submitParams, __FUNCTION__, __FILE__, 'submit contribution page', NULL);
f9342903
EM
389 $contributions = $this->callAPISuccess('contribution', 'get', array('contribution_page_id' => $this->_ids['contribution_page']));
390 $this->assertCount(2, $contributions['values']);
391 $membershipPayment = $this->callAPISuccess('membership_payment', 'getsingle', array());
392 $this->assertTrue(in_array($membershipPayment['contribution_id'], array_keys($contributions['values'])));
393 $membership = $this->callAPISuccessGetSingle('membership', array('id' => $membershipPayment['membership_id']));
394 $this->assertEquals($membership['contact_id'], $contributions['values'][$membershipPayment['contribution_id']]['contact_id']);
395 }
f64a217a 396
2f59d010 397 /**
398 * Test submit with a membership block in place.
399 */
400 public function testSubmitMembershipBlockIsSeparatePaymentWithEmail() {
401 $mut = new CiviMailUtils($this, TRUE);
402 $this->setUpMembershipContributionPage(TRUE);
403 $this->addProfile('supporter_profile', $this->_ids['contribution_page']);
404
405 $submitParams = array(
406 'price_' . $this->_ids['price_field'][0] => reset($this->_ids['price_field_value']),
407 'id' => (int) $this->_ids['contribution_page'],
408 'amount' => 10,
409 'billing_first_name' => 'Billy',
410 'billing_middle_name' => 'Goat',
411 'billing_last_name' => 'Gruff',
412 'selectMembership' => $this->_ids['membership_type'],
413 'email-Primary' => 'billy-goat@the-bridge.net',
414 );
415
416 $this->callAPIAndDocument('contribution_page', 'submit', $submitParams, __FUNCTION__, __FILE__, 'submit contribution page', NULL);
417 $contributions = $this->callAPISuccess('contribution', 'get', array('contribution_page_id' => $this->_ids['contribution_page']));
418 $this->assertCount(2, $contributions['values']);
419 $membershipPayment = $this->callAPISuccess('membership_payment', 'getsingle', array());
420 $this->assertTrue(in_array($membershipPayment['contribution_id'], array_keys($contributions['values'])));
421 $membership = $this->callAPISuccessGetSingle('membership', array('id' => $membershipPayment['membership_id']));
422 $this->assertEquals($membership['contact_id'], $contributions['values'][$membershipPayment['contribution_id']]['contact_id']);
423 $mut->checkMailLog(array(
424 'General Membership: $ 2.00',
425 'Membership Fee',
426 ));
427 $mut->stop();
428 $mut->clearMessages();
429 }
430
431 /**
432 * Test submit with a membership block in place.
433 */
434 public function testSubmitMembershipBlockIsSeparatePaymentZeroDollarsPayLaterWithEmail() {
435 $mut = new CiviMailUtils($this, TRUE);
436 $this->_ids['membership_type'] = array($this->membershipTypeCreate(array('minimum_fee' => 0)));
437 $this->setUpMembershipContributionPage(TRUE);
438 $this->addProfile('supporter_profile', $this->_ids['contribution_page']);
439
440 $submitParams = array(
441 'price_' . $this->_ids['price_field'][0] => reset($this->_ids['price_field_value']),
442 'id' => (int) $this->_ids['contribution_page'],
443 'amount' => 0,
444 'billing_first_name' => 'Billy',
445 'billing_middle_name' => 'Goat',
446 'billing_last_name' => 'Gruffalo',
447 'selectMembership' => $this->_ids['membership_type'],
448 'payment_processor_id' => 0,
449 'email-Primary' => 'gruffalo@the-bridge.net',
450 );
451
452 $this->callAPIAndDocument('contribution_page', 'submit', $submitParams, __FUNCTION__, __FILE__, 'submit contribution page', NULL);
453 $contributions = $this->callAPISuccess('contribution', 'get', array('contribution_page_id' => $this->_ids['contribution_page']));
454 $this->assertCount(2, $contributions['values']);
455 $membershipPayment = $this->callAPISuccess('membership_payment', 'getsingle', array());
456 $this->assertTrue(in_array($membershipPayment['contribution_id'], array_keys($contributions['values'])));
457 $membership = $this->callAPISuccessGetSingle('membership', array('id' => $membershipPayment['membership_id']));
458 $this->assertEquals($membership['contact_id'], $contributions['values'][$membershipPayment['contribution_id']]['contact_id']);
459 $mut->checkMailLog(array(
460 'Gruffalo',
461 'General Membership: $ 0.00',
462 'Membership Fee',
463 ));
464 $mut->stop();
465 $mut->clearMessages();
466 }
467
797c4f88 468 /**
eceb18cc 469 * Test submit with a membership block in place.
797c4f88
EM
470 */
471 public function testSubmitMembershipBlockTwoTypesIsSeparatePayment() {
472 $this->_ids['membership_type'] = array($this->membershipTypeCreate(array('minimum_fee' => 6)));
473 $this->_ids['membership_type'][] = $this->membershipTypeCreate(array('name' => 'Student', 'minimum_fee' => 50));
474 $this->setUpMembershipContributionPage(TRUE);
475 $submitParams = array(
476 'price_' . $this->_ids['price_field'][0] => $this->_ids['price_field_value'][1],
477 'id' => (int) $this->_ids['contribution_page'],
478 'amount' => 10,
479 'billing_first_name' => 'Billy',
480 'billing_middle_name' => 'Goat',
481 'billing_last_name' => 'Gruff',
482 'selectMembership' => $this->_ids['membership_type'][1],
483 );
484
a828d7b8 485 $this->callAPIAndDocument('contribution_page', 'submit', $submitParams, __FUNCTION__, __FILE__, 'submit contribution page', NULL);
6c6e6187 486 $contributions = $this->callAPISuccess('contribution', 'get', array('contribution_page_id' => $this->_ids['contribution_page']));
797c4f88
EM
487 $this->assertCount(2, $contributions['values']);
488 $ids = array_keys($contributions['values']);
489 $this->assertEquals('10.00', $contributions['values'][$ids[0]]['total_amount']);
490 $this->assertEquals('50.00', $contributions['values'][$ids[1]]['total_amount']);
491 $membershipPayment = $this->callAPISuccess('membership_payment', 'getsingle', array());
492 $this->assertArrayHasKey($membershipPayment['contribution_id'], $contributions['values']);
493 $membership = $this->callAPISuccessGetSingle('membership', array('id' => $membershipPayment['membership_id']));
494 $this->assertEquals($membership['contact_id'], $contributions['values'][$membershipPayment['contribution_id']]['contact_id']);
495 }
496
8ca611b7 497 /**
eceb18cc 498 * Test submit with a membership block in place.
329f3f66
EM
499 *
500 * We are expecting a separate payment for the membership vs the contribution.
8ca611b7 501 */
329f3f66 502 public function testSubmitMembershipBlockIsSeparatePaymentPaymentProcessorNow() {
8ca611b7 503 $this->setUpMembershipContributionPage(TRUE);
0193ebdb 504 $processor = Civi\Payment\System::singleton()->getById($this->_paymentProcessor['id']);
505 $processor->setDoDirectPaymentResult(array('fee_amount' => .72));
8ca611b7
EM
506 $submitParams = array(
507 'price_' . $this->_ids['price_field'][0] => reset($this->_ids['price_field_value']),
508 'id' => (int) $this->_ids['contribution_page'],
509 'amount' => 10,
510 'billing_first_name' => 'Billy',
511 'billing_middle_name' => 'Goat',
512 'billing_last_name' => 'Gruff',
513 'selectMembership' => $this->_ids['membership_type'],
7bc789a5 514 'payment_processor_id' => $this->_paymentProcessor['id'],
8ca611b7
EM
515 'credit_card_number' => '4111111111111111',
516 'credit_card_type' => 'Visa',
5896d037 517 'credit_card_exp_date' => array('M' => 9, 'Y' => 2040),
8ca611b7
EM
518 'cvv2' => 123,
519 );
05990684 520
a828d7b8 521 $this->callAPIAndDocument('contribution_page', 'submit', $submitParams, __FUNCTION__, __FILE__, 'submit contribution page', NULL);
5896d037 522 $contributions = $this->callAPISuccess('contribution', 'get', array(
92915c55
TO
523 'contribution_page_id' => $this->_ids['contribution_page'],
524 'contribution_status_id' => 1,
525 ));
8ca611b7
EM
526 $this->assertCount(2, $contributions['values']);
527 $membershipPayment = $this->callAPISuccess('membership_payment', 'getsingle', array());
528 $this->assertTrue(in_array($membershipPayment['contribution_id'], array_keys($contributions['values'])));
529 $membership = $this->callAPISuccessGetSingle('membership', array('id' => $membershipPayment['membership_id']));
530 $this->assertEquals($membership['contact_id'], $contributions['values'][$membershipPayment['contribution_id']]['contact_id']);
0193ebdb 531 foreach ($contributions['values'] as $contribution) {
532 $this->assertEquals(.72, $contribution['fee_amount']);
533 $this->assertEquals($contribution['total_amount'] - .72, $contribution['net_amount']);
534 }
8ca611b7 535 }
f8fe0df6 536
5961bd47
EM
537 /**
538 * Test that when a transaction fails the pending contribution remains.
539 *
540 * An activity should also be created. CRM-16417.
541 */
542 public function testSubmitPaymentProcessorFailure() {
543 $this->setUpContributionPage();
544 $this->setupPaymentProcessor();
545 $this->createLoggedInUser();
546 $priceFieldID = reset($this->_ids['price_field']);
547 $priceFieldValueID = reset($this->_ids['price_field_value']);
548 $submitParams = array(
549 'price_' . $priceFieldID => $priceFieldValueID,
550 'id' => (int) $this->_ids['contribution_page'],
551 'amount' => 10,
552 'payment_processor_id' => 1,
553 'credit_card_number' => '4111111111111111',
554 'credit_card_type' => 'Visa',
555 'credit_card_exp_date' => array('M' => 9, 'Y' => 2008),
556 'cvv2' => 123,
557 );
558
559 $this->callAPISuccess('contribution_page', 'submit', $submitParams);
560 $contribution = $this->callAPISuccessGetSingle('contribution', array(
561 'contribution_page_id' => $this->_ids['contribution_page'],
562 'contribution_status_id' => 2,
563 ));
564
565 $this->callAPISuccessGetSingle('activity', array(
566 'source_record_id' => $contribution['id'],
567 'activity_type_id' => 'Failed Payment',
568 ));
569
5961bd47
EM
570 }
571
f8fe0df6 572 /**
dd1b539a 573 * Test submit recurring membership with immediate confirmation (IATS style).
574 *
e6fa4056 575 * - we process 2 membership transactions against with a recurring contribution against a contribution page with an immediate
1fee3ad2 576 * processor (IATS style - denoted by returning trxn_id)
e6fa4056
EM
577 * - the first creates a new membership, completed contribution, in progress recurring. Check these
578 * - create another - end date should be extended
f8fe0df6 579 */
8bef2e38 580 public function testSubmitMembershipPriceSetPaymentPaymentProcessorRecurInstantPayment() {
f8fe0df6 581 $this->params['is_recur'] = 1;
f8fe0df6 582 $this->params['recur_frequency_unit'] = 'month';
583 $this->setUpMembershipContributionPage();
7c85dc65 584 $dummyPP = Civi\Payment\System::singleton()->getByProcessor($this->_paymentProcessor);
8bef2e38 585 $dummyPP->setDoDirectPaymentResult(array('payment_status_id' => 1, 'trxn_id' => 'create_first_success'));
f8fe0df6 586
587 $submitParams = array(
588 'price_' . $this->_ids['price_field'][0] => reset($this->_ids['price_field_value']),
589 'id' => (int) $this->_ids['contribution_page'],
590 'amount' => 10,
591 'billing_first_name' => 'Billy',
592 'billing_middle_name' => 'Goat',
593 'billing_last_name' => 'Gruff',
594 'email' => 'billy@goat.gruff',
595 'selectMembership' => $this->_ids['membership_type'],
579a1fb7 596 'payment_processor_id' => 1,
f8fe0df6 597 'credit_card_number' => '4111111111111111',
598 'credit_card_type' => 'Visa',
5896d037 599 'credit_card_exp_date' => array('M' => 9, 'Y' => 2040),
f8fe0df6 600 'cvv2' => 123,
601 'is_recur' => 1,
602 'frequency_interval' => 1,
603 'frequency_unit' => 'month',
604 );
605
a828d7b8 606 $this->callAPIAndDocument('contribution_page', 'submit', $submitParams, __FUNCTION__, __FILE__, 'submit contribution page', NULL);
5896d037 607 $contribution = $this->callAPISuccess('contribution', 'getsingle', array(
92915c55
TO
608 'contribution_page_id' => $this->_ids['contribution_page'],
609 'contribution_status_id' => 1,
610 ));
0739d6cf 611
612 $this->assertEquals('create_first_success', $contribution['trxn_id']);
f8fe0df6 613 $membershipPayment = $this->callAPISuccess('membership_payment', 'getsingle', array());
614 $this->assertEquals($membershipPayment['contribution_id'], $contribution['id']);
615 $membership = $this->callAPISuccessGetSingle('membership', array('id' => $membershipPayment['membership_id']));
616 $this->assertEquals($membership['contact_id'], $contribution['contact_id']);
617 $this->assertEquals(1, $membership['status_id']);
618 $this->callAPISuccess('contribution_recur', 'getsingle', array('id' => $contribution['contribution_recur_id']));
e6fa4056
EM
619 //@todo - check with Joe about these not existing
620 //$this->callAPISuccess('line_item', 'getsingle', array('contribution_id' => $contribution['id'], 'entity_id' => $membership['id']));
f8fe0df6 621 //renew it with processor setting completed - should extend membership
622 $submitParams['contact_id'] = $contribution['contact_id'];
8bef2e38 623 $dummyPP->setDoDirectPaymentResult(array('payment_status_id' => 1, 'trxn_id' => 'create_second_success'));
f8fe0df6 624 $this->callAPISuccess('contribution_page', 'submit', $submitParams);
5896d037 625 $this->callAPISuccess('contribution', 'getsingle', array(
92915c55
TO
626 'id' => array('NOT IN' => array($contribution['id'])),
627 'contribution_page_id' => $this->_ids['contribution_page'],
628 'contribution_status_id' => 1,
629 ));
f8fe0df6 630 $renewedMembership = $this->callAPISuccessGetSingle('membership', array('id' => $membershipPayment['membership_id']));
631 $this->assertEquals(date('Y-m-d', strtotime('+ 1 year', strtotime($membership['end_date']))), $renewedMembership['end_date']);
632 $recurringContribution = $this->callAPISuccess('contribution_recur', 'getsingle', array('id' => $contribution['contribution_recur_id']));
e6fa4056 633 $this->assertEquals(2, $recurringContribution['contribution_status_id']);
f8fe0df6 634 }
635
449f4c90 636 /**
637 * Test submit recurring membership with immediate confirmation (IATS style).
638 *
639 * - we process 2 membership transactions against with a recurring contribution against a contribution page with an immediate
640 * processor (IATS style - denoted by returning trxn_id)
641 * - the first creates a new membership, completed contribution, in progress recurring. Check these
642 * - create another - end date should be extended
643 */
644 public function testSubmitMembershipPriceSetPaymentPaymentProcessorSeparatePaymentRecurInstantPayment() {
645
646 $this->setUpMembershipContributionPage(TRUE);
647 $dummyPP = Civi\Payment\System::singleton()->getByProcessor($this->_paymentProcessor);
648 $dummyPP->setDoDirectPaymentResult(array('payment_status_id' => 1, 'trxn_id' => 'create_first_success'));
649
650 $submitParams = array(
651 'price_' . $this->_ids['price_field'][0] => reset($this->_ids['price_field_value']),
652 'id' => (int) $this->_ids['contribution_page'],
653 'amount' => 10,
654 'billing_first_name' => 'Billy',
655 'billing_middle_name' => 'Goat',
656 'billing_last_name' => 'Gruff',
657 'email' => 'billy@goat.gruff',
658 'selectMembership' => $this->_ids['membership_type'],
659 'payment_processor_id' => 1,
660 'credit_card_number' => '4111111111111111',
661 'credit_card_type' => 'Visa',
662 'credit_card_exp_date' => array('M' => 9, 'Y' => 2040),
663 'cvv2' => 123,
664 'is_recur' => 1,
665 'auto_renew' => TRUE,
666 'frequency_interval' => 1,
667 'frequency_unit' => 'month',
668 );
669
670 $this->callAPIAndDocument('contribution_page', 'submit', $submitParams, __FUNCTION__, __FILE__, 'submit contribution page', NULL);
671 $contribution = $this->callAPISuccess('contribution', 'get', array(
672 'contribution_page_id' => $this->_ids['contribution_page'],
673 'contribution_status_id' => 1,
674 ));
675
676 $this->assertEquals(2, $contribution['count']);
677 $membershipPayment = $this->callAPISuccess('membership_payment', 'getsingle', array());
678 $this->callAPISuccessGetSingle('membership', array('id' => $membershipPayment['membership_id']));
679 $this->assertNotEmpty($contribution['values'][$membershipPayment['contribution_id']]['contribution_recur_id']);
680 $this->callAPISuccess('contribution_recur', 'getsingle', array());
681 }
682
f8fe0df6 683 /**
e6fa4056
EM
684 * Test submit recurring membership with delayed confirmation (Authorize.net style)
685 * - we process 2 membership transactions against with a recurring contribution against a contribution page with a delayed
686 * processor (Authorize.net style - denoted by NOT returning trxn_id)
687 * - the first creates a pending membership, pending contribution, penging recurring. Check these
688 * - complete the transaction
689 * - create another - end date should NOT be extended
f8fe0df6 690 */
691 public function testSubmitMembershipPriceSetPaymentPaymentProcessorRecurDelayed() {
692 $this->params['is_recur'] = 1;
f8fe0df6 693 $this->params['recur_frequency_unit'] = 'month';
694 $this->setUpMembershipContributionPage();
ab30e033 695 $dummyPP = Civi\Payment\System::singleton()->getByProcessor($this->_paymentProcessor);
b5eacf76 696 $dummyPP->setDoDirectPaymentResult(array('payment_status_id' => 2));
f8fe0df6 697
698 $submitParams = array(
699 'price_' . $this->_ids['price_field'][0] => reset($this->_ids['price_field_value']),
700 'id' => (int) $this->_ids['contribution_page'],
701 'amount' => 10,
702 'billing_first_name' => 'Billy',
703 'billing_middle_name' => 'Goat',
704 'billing_last_name' => 'Gruff',
705 'email' => 'billy@goat.gruff',
706 'selectMembership' => $this->_ids['membership_type'],
579a1fb7 707 'payment_processor_id' => 1,
f8fe0df6 708 'credit_card_number' => '4111111111111111',
709 'credit_card_type' => 'Visa',
5896d037 710 'credit_card_exp_date' => array('M' => 9, 'Y' => 2040),
f8fe0df6 711 'cvv2' => 123,
e6fa4056
EM
712 'is_recur' => 1,
713 'frequency_interval' => 1,
714 'frequency_unit' => 'month',
f8fe0df6 715 );
716
a828d7b8 717 $this->callAPIAndDocument('contribution_page', 'submit', $submitParams, __FUNCTION__, __FILE__, 'submit contribution page', NULL);
5896d037 718 $contribution = $this->callAPISuccess('contribution', 'getsingle', array(
92915c55
TO
719 'contribution_page_id' => $this->_ids['contribution_page'],
720 'contribution_status_id' => 2,
721 ));
f8fe0df6 722 $membershipPayment = $this->callAPISuccess('membership_payment', 'getsingle', array());
723 $this->assertEquals($membershipPayment['contribution_id'], $contribution['id']);
724 $membership = $this->callAPISuccessGetSingle('membership', array('id' => $membershipPayment['membership_id']));
725 $this->assertEquals($membership['contact_id'], $contribution['contact_id']);
e6fa4056
EM
726 $this->assertEquals(5, $membership['status_id']);
727 //@todo - check with Joe about these not existing
728 //$this->callAPISuccess('line_item', 'getsingle', array('contribution_id' => $contribution['id'], 'entity_id' => $membership['id']));
5896d037 729 $this->callAPISuccess('contribution', 'completetransaction', array(
92915c55
TO
730 'id' => $contribution['id'],
731 'trxn_id' => 'ipn_called',
b396c447 732 'payment_processor_id' => $this->_paymentProcessor['id'],
92915c55 733 ));
e6fa4056 734 $membership = $this->callAPISuccessGetSingle('membership', array('id' => $membershipPayment['membership_id']));
f8fe0df6 735 //renew it with processor setting completed - should extend membership
736 $submitParams = array_merge($submitParams, array(
5896d037
TO
737 'contact_id' => $contribution['contact_id'],
738 'is_recur' => 1,
739 'frequency_interval' => 1,
740 'frequency_unit' => 'month',
741 )
f8fe0df6 742 );
b5eacf76 743 $dummyPP->setDoDirectPaymentResult(array('payment_status_id' => 2));
f8fe0df6 744 $this->callAPISuccess('contribution_page', 'submit', $submitParams);
6c6e6187 745 $newContribution = $this->callAPISuccess('contribution', 'getsingle', array(
5896d037 746 'id' => array(
21dfd5f5 747 'NOT IN' => array($contribution['id']),
5896d037
TO
748 ),
749 'contribution_page_id' => $this->_ids['contribution_page'],
21dfd5f5 750 'contribution_status_id' => 2,
5896d037 751 )
f8fe0df6 752 );
e6fa4056 753
f8fe0df6 754 $renewedMembership = $this->callAPISuccessGetSingle('membership', array('id' => $membershipPayment['membership_id']));
755 //no renewal as the date hasn't changed
756 $this->assertEquals($membership['end_date'], $renewedMembership['end_date']);
e6fa4056
EM
757 $recurringContribution = $this->callAPISuccess('contribution_recur', 'getsingle', array('id' => $newContribution['contribution_recur_id']));
758 $this->assertEquals(2, $recurringContribution['contribution_status_id']);
f8fe0df6 759 }
760
f9342903 761 /**
eceb18cc 762 * Set up membership contribution page.
f9342903
EM
763 * @param bool $isSeparatePayment
764 */
00be9182 765 public function setUpMembershipContributionPage($isSeparatePayment = FALSE) {
f9342903 766 $this->setUpMembershipBlockPriceSet();
a380f4a0 767 $this->setupPaymentProcessor();
f9342903
EM
768 $this->setUpContributionPage();
769
770 $this->callAPISuccess('membership_block', 'create', array(
771 'entity_id' => $this->_ids['contribution_page'],
772 'entity_table' => 'civicrm_contribution_page',
773 'is_required' => TRUE,
774 'is_active' => TRUE,
775 'is_separate_payment' => $isSeparatePayment,
776 'membership_type_default' => $this->_ids['membership_type'],
777 ));
f64a217a
EM
778 }
779
f9342903 780 /**
dd1b539a 781 * The default data set does not include a complete default membership price set - not quite sure why.
782 *
f9342903
EM
783 * This function ensures it exists & populates $this->_ids with it's data
784 */
00be9182 785 public function setUpMembershipBlockPriceSet() {
5896d037 786 $this->_ids['price_set'][] = $this->callAPISuccess('price_set', 'getvalue', array(
92915c55
TO
787 'name' => 'default_membership_type_amount',
788 'return' => 'id',
789 ));
f9342903 790 if (empty($this->_ids['membership_type'])) {
3e28c791 791 $this->_ids['membership_type'] = array($this->membershipTypeCreate(array('minimum_fee' => 2)));
f9342903 792 }
3e28c791
EM
793 $priceField = $this->callAPISuccess('price_field', 'create', array(
794 'price_set_id' => reset($this->_ids['price_set']),
795 'name' => 'membership_amount',
796 'label' => 'Membership Amount',
797 'html_type' => 'Radio',
798 'sequential' => 1,
799 ));
800 $this->_ids['price_field'][] = $priceField['id'];
dd1b539a 801
3e28c791
EM
802 foreach ($this->_ids['membership_type'] as $membershipTypeID) {
803 $priceFieldValue = $this->callAPISuccess('price_field_value', 'create', array(
f9342903
EM
804 'name' => 'membership_amount',
805 'label' => 'Membership Amount',
3e28c791 806 'amount' => 1,
43dbd988 807 'financial_type_id' => 'Donation',
3e28c791
EM
808 'format.only_id' => TRUE,
809 'membership_type_id' => $membershipTypeID,
810 'price_field_id' => $priceField['id'],
f9342903 811 ));
3e28c791 812 $this->_ids['price_field_value'][] = $priceFieldValue['id'];
f9342903
EM
813 }
814 }
3e28c791 815
2f59d010 816 /**
817 * Add text field other amount to the price set.
818 */
819 public function addOtherAmountFieldToMembershipPriceSet() {
820 $this->_ids['price_field']['other_amount'] = $this->callAPISuccess('price_field', 'create', array(
821 'price_set_id' => reset($this->_ids['price_set']),
822 'name' => 'other_amount',
823 'label' => 'Other Amount',
824 'html_type' => 'Text',
825 'format.only_id' => TRUE,
826 'sequential' => 1,
827 ));
828 $this->_ids['price_field_value']['other_amount'] = $this->callAPISuccess('price_field_value', 'create', array(
829 'financial_type_id' => 'Donation',
830 'format.only_id' => TRUE,
831 'label' => 'Other Amount',
832 'amount' => 1,
833 'price_field_id' => $this->_ids['price_field']['other_amount'],
834 ));
835 }
836
f64a217a 837 /**
eceb18cc 838 * Help function to set up contribution page with some defaults.
f64a217a 839 */
00be9182 840 public function setUpContributionPage() {
f64a217a
EM
841 $contributionPageResult = $this->callAPISuccess($this->_entity, 'create', $this->params);
842 if (empty($this->_ids['price_set'])) {
843 $priceSet = $this->callAPISuccess('price_set', 'create', $this->_priceSetParams);
844 $this->_ids['price_set'][] = $priceSet['id'];
845 }
846 $priceSetID = reset($this->_ids['price_set']);
5896d037 847 CRM_Price_BAO_PriceSet::addTo('civicrm_contribution_page', $contributionPageResult['id'], $priceSetID);
f9342903
EM
848
849 if (empty($this->_ids['price_field'])) {
850 $priceField = $this->callAPISuccess('price_field', 'create', array(
851 'price_set_id' => $priceSetID,
852 'label' => 'Goat Breed',
853 'html_type' => 'Radio',
854 ));
855 $this->_ids['price_field'] = array($priceField['id']);
856 }
857 if (empty($this->_ids['price_field_value'])) {
858 $this->callAPISuccess('price_field_value', 'create', array(
859 'price_set_id' => $priceSetID,
860 'price_field_id' => $priceField['id'],
861 'label' => 'Long Haired Goat',
43dbd988 862 'financial_type_id' => 'Donation',
f9342903 863 'amount' => 20,
3300bf67 864 'financial_type_id' => 'Donation',
f9342903
EM
865 )
866 );
867 $priceFieldValue = $this->callAPISuccess('price_field_value', 'create', array(
868 'price_set_id' => $priceSetID,
869 'price_field_id' => $priceField['id'],
870 'label' => 'Shoe-eating Goat',
43dbd988 871 'financial_type_id' => 'Donation',
f9342903 872 'amount' => 10,
3300bf67 873 'financial_type_id' => 'Donation',
f9342903
EM
874 )
875 );
876 $this->_ids['price_field_value'] = array($priceFieldValue['id']);
877 }
f64a217a 878 $this->_ids['contribution_page'] = $contributionPageResult['id'];
be26f3e0
EM
879 }
880
6a488035 881 public static function setUpBeforeClass() {
6c6e6187 882 // put stuff here that should happen before all tests in this unit
6a488035
TO
883 }
884
5896d037 885 public static function tearDownAfterClass() {
6a488035
TO
886 $tablesToTruncate = array(
887 'civicrm_contact',
888 'civicrm_financial_type',
889 'civicrm_contribution',
890 'civicrm_contribution_page',
891 );
892 $unitTest = new CiviUnitTestCase();
893 $unitTest->quickCleanup($tablesToTruncate);
894 }
96025800 895
a380f4a0
EM
896 /**
897 * Create a payment processor instance.
898 */
899 protected function setupPaymentProcessor() {
900 $this->params['payment_processor_id'] = $this->_ids['payment_processor'] = $this->paymentProcessorCreate(array(
901 'payment_processor_type_id' => 'Dummy',
902 'class_name' => 'Payment_Dummy',
903 'billing_mode' => 1,
904 ));
905 $this->_paymentProcessor = $this->callAPISuccess('payment_processor', 'getsingle', array('id' => $this->params['payment_processor_id']));
906 }
907
6a488035 908}