Merge pull request #15838 from demeritcowboy/getcasereport-split
[civicrm-core.git] / tests / phpunit / CRM / Core / Payment / AuthorizeNetIPNTest.php
CommitLineData
0dbefed3
EM
1<?php
2
12fde6ae 3use Civi\Payment\Exception\PaymentProcessorException;
4
0dbefed3
EM
5/**
6 * Class CRM_Core_Payment_PayPalProIPNTest
acb109b7 7 * @group headless
0dbefed3
EM
8 */
9class CRM_Core_Payment_AuthorizeNetIPNTest extends CiviUnitTestCase {
7aeb7f06 10 use CRMTraits_Financial_OrderTrait;
11
0dbefed3
EM
12 protected $_contributionID;
13 protected $_invoiceID = 'c2r9c15f7be20b4f3fef1f77e4c37424';
14 protected $_financialTypeID = 1;
15 protected $_contactID;
16 protected $_contributionRecurID;
17 protected $_contributionPageID;
18 protected $_paymentProcessorID;
19
7aeb7f06 20 /**
21 *
22 * @throws \CRM_Core_Exception
23 */
00be9182 24 public function setUp() {
0dbefed3 25 parent::setUp();
9099cab3 26 $this->_paymentProcessorID = $this->paymentProcessorAuthorizeNetCreate(['is_test' => 0]);
0dbefed3 27 $this->_contactID = $this->individualCreate();
9099cab3 28 $contributionPage = $this->callAPISuccess('contribution_page', 'create', [
7aeb7f06 29 'title' => 'Test Contribution Page',
0dbefed3
EM
30 'financial_type_id' => $this->_financialTypeID,
31 'currency' => 'USD',
32 'payment_processor' => $this->_paymentProcessorID,
481312d9 33 'max_amount' => 1000,
34 'receipt_from_email' => 'gaia@the.cosmos',
35 'receipt_from_name' => 'Pachamama',
36 'is_email_receipt' => TRUE,
9099cab3 37 ]);
0dbefed3
EM
38 $this->_contributionPageID = $contributionPage['id'];
39 }
40
00be9182 41 public function tearDown() {
0dbefed3
EM
42 $this->quickCleanUpFinancialEntities();
43 }
39b959db 44
0495f30c 45 /**
46 * Ensure recurring contributions from Contribution Pages
47 * with receipt turned off don't send a receipt.
12fde6ae 48 *
49 * @throws \CiviCRM_API3_Exception
50 * @throws \CRM_Core_Exception
0495f30c 51 */
52 public function testIPNPaymentRecurNoReceipt() {
53 $mut = new CiviMailUtils($this, TRUE);
54 // Turn off receipts in contribution page.
9099cab3 55 $api_params = [
0495f30c 56 'id' => $this->_contributionPageID,
57 'is_email_receipt' => FALSE,
9099cab3 58 ];
0495f30c 59 $this->callAPISuccess('contributionPage', 'update', $api_params);
60
61 // Create initial recurring payment and initial contribution.
62 // Note - we can't use setupRecurringPaymentProcessorTransaction(), which
63 // would be convenient because it does not fully mimic the real user
64 // experience. Using setupRecurringPaymentProcessorTransaction() doesn't
65 // specify is_email_receipt so it is always set to 1. We need to more
66 // closely mimic what happens with a live transaction to test that
67 // is_email_receipt is not set to 1 if the originating contribution page
68 // has is_email_receipt set to 0.
69 $form = new CRM_Contribute_Form_Contribution();
70 $form->_mode = 'Live';
12fde6ae 71 try {
72 $contribution = $form->testSubmit([
73 'total_amount' => 200,
74 'financial_type_id' => 1,
75 'receive_date' => date('m/d/Y'),
76 'receive_date_time' => date('H:i:s'),
77 'contact_id' => $this->_contactID,
78 'contribution_status_id' => 1,
79 'credit_card_number' => 4444333322221111,
80 'cvv2' => 123,
81 'credit_card_exp_date' => [
82 'M' => 9,
83 'Y' => 2025,
84 ],
85 'credit_card_type' => 'Visa',
86 'billing_first_name' => 'Junko',
87 'billing_middle_name' => '',
88 'billing_last_name' => 'Adams',
89 'billing_street_address-5' => time() . ' Lincoln St S',
90 'billing_city-5' => 'Maryknoll',
91 'billing_state_province_id-5' => 1031,
92 'billing_postal_code-5' => 10545,
93 'billing_country_id-5' => 1228,
94 'frequency_interval' => 1,
95 'frequency_unit' => 'month',
96 'installments' => '',
97 'hidden_AdditionalDetail' => 1,
98 'hidden_Premium' => 1,
99 'payment_processor_id' => $this->_paymentProcessorID,
100 'currency' => 'USD',
101 'source' => 'bob sled race',
102 'contribution_page_id' => $this->_contributionPageID,
103 'is_recur' => TRUE,
104 ], CRM_Core_Action::ADD);
105 }
106 catch (PaymentProcessorException $e) {
107 $this->markTestSkipped('Error from A.net - cannot proceed');
108 }
0495f30c 109 $this->_contributionID = $contribution->id;
7aeb7f06 110 $this->ids['Contribution'][0] = $contribution->id;
0495f30c 111 $this->_contributionRecurID = $contribution->contribution_recur_id;
9099cab3 112 $recur_params = [
0495f30c 113 'id' => $this->_contributionRecurID,
114 'return' => 'processor_id',
9099cab3 115 ];
0495f30c 116 $processor_id = civicrm_api3('ContributionRecur', 'getvalue', $recur_params);
117 // Process the initial one.
118 $IPN = new CRM_Core_Payment_AuthorizeNetIPN(
9099cab3 119 $this->getRecurTransaction(['x_subscription_id' => $processor_id])
0495f30c 120 );
121 $IPN->main();
122
123 // Now send a second one (authorize seems to treat first and second contributions
124 // differently.
125 $IPN = new CRM_Core_Payment_AuthorizeNetIPN($this->getRecurSubsequentTransaction(
9099cab3 126 ['x_subscription_id' => $processor_id]
0495f30c 127 ));
128 $IPN->main();
129
130 // There should not be any email.
131 $mut->assertMailLogEmpty();
132 }
0dbefed3
EM
133
134 /**
100fef9d 135 * Test IPN response updates contribution_recur & contribution for first & second contribution
7aeb7f06 136 *
137 * @throws \CRM_Core_Exception
0dbefed3 138 */
00be9182 139 public function testIPNPaymentRecurSuccess() {
0dbefed3 140 $this->setupRecurringPaymentProcessorTransaction();
8f234057 141 $IPN = new CRM_Core_Payment_AuthorizeNetIPN($this->getRecurTransaction());
142 $IPN->main();
9099cab3 143 $contribution = $this->callAPISuccess('contribution', 'getsingle', ['id' => $this->_contributionID]);
0dbefed3
EM
144 $this->assertEquals(1, $contribution['contribution_status_id']);
145 $this->assertEquals('6511143069', $contribution['trxn_id']);
146 // source gets set by processor
147 $this->assertTrue(substr($contribution['contribution_source'], 0, 20) == "Online Contribution:");
9099cab3 148 $contributionRecur = $this->callAPISuccess('contribution_recur', 'getsingle', ['id' => $this->_contributionRecurID]);
0dbefed3 149 $this->assertEquals(5, $contributionRecur['contribution_status_id']);
8f234057 150 $IPN = new CRM_Core_Payment_AuthorizeNetIPN($this->getRecurSubsequentTransaction());
151 $IPN->main();
9099cab3 152 $contribution = $this->callAPISuccess('contribution', 'get', [
39b959db
SL
153 'contribution_recur_id' => $this->_contributionRecurID,
154 'sequential' => 1,
9099cab3 155 ]);
0dbefed3
EM
156 $this->assertEquals(2, $contribution['count']);
157 $this->assertEquals('second_one', $contribution['values'][1]['trxn_id']);
4a1ba425 158 $this->assertEquals(date('Y-m-d'), date('Y-m-d', strtotime($contribution['values'][1]['receive_date'])));
0dbefed3
EM
159 }
160
f4aff12e
JP
161 /**
162 * Test payment processor is correctly assigned for the IPN payment.
163 */
164 public function testIPNPaymentRecurSuccessMultiAuthNetProcessor() {
165 //Create and set up recur payment using second instance of AuthNet Processor.
9099cab3
CW
166 $this->_paymentProcessorID2 = $this->paymentProcessorAuthorizeNetCreate(['name' => 'Authorize2', 'is_test' => 0]);
167 $this->setupRecurringPaymentProcessorTransaction(['payment_processor_id' => $this->_paymentProcessorID2]);
f4aff12e
JP
168
169 //Call IPN with processor id.
9099cab3 170 $IPN = new CRM_Core_Payment_AuthorizeNetIPN($this->getRecurTransaction(['processor_id' => $this->_paymentProcessorID2]));
f4aff12e 171 $IPN->main();
9099cab3 172 $contribution = $this->callAPISuccess('contribution', 'getsingle', ['id' => $this->_contributionID]);
f4aff12e
JP
173 $this->assertEquals(1, $contribution['contribution_status_id']);
174 $this->assertEquals('6511143069', $contribution['trxn_id']);
175 // source gets set by processor
176 $this->assertTrue(substr($contribution['contribution_source'], 0, 20) == "Online Contribution:");
9099cab3 177 $contributionRecur = $this->callAPISuccess('contribution_recur', 'getsingle', ['id' => $this->_contributionRecurID]);
f4aff12e
JP
178 $this->assertEquals(5, $contributionRecur['contribution_status_id']);
179 }
180
4a1ba425 181 /**
182 * Test IPN response updates contribution_recur & contribution for first & second contribution
183 */
184 public function testIPNPaymentRecurSuccessSuppliedReceiveDate() {
185 $this->setupRecurringPaymentProcessorTransaction();
186 $IPN = new CRM_Core_Payment_AuthorizeNetIPN($this->getRecurTransaction());
187 $IPN->main();
9099cab3 188 $contribution = $this->callAPISuccess('contribution', 'getsingle', ['id' => $this->_contributionID]);
4a1ba425 189 $this->assertEquals(1, $contribution['contribution_status_id']);
190 $this->assertEquals('6511143069', $contribution['trxn_id']);
191 // source gets set by processor
192 $this->assertTrue(substr($contribution['contribution_source'], 0, 20) == "Online Contribution:");
9099cab3 193 $contributionRecur = $this->callAPISuccess('contribution_recur', 'getsingle', ['id' => $this->_contributionRecurID]);
4a1ba425 194 $this->assertEquals(5, $contributionRecur['contribution_status_id']);
9099cab3 195 $IPN = new CRM_Core_Payment_AuthorizeNetIPN(array_merge(['receive_date' => '1 July 2010'], $this->getRecurSubsequentTransaction()));
4a1ba425 196 $IPN->main();
9099cab3 197 $contribution = $this->callAPISuccess('contribution', 'get', [
4a1ba425 198 'contribution_recur_id' => $this->_contributionRecurID,
199 'sequential' => 1,
9099cab3 200 ]);
4a1ba425 201 $this->assertEquals(2, $contribution['count']);
202 $this->assertEquals('second_one', $contribution['values'][1]['trxn_id']);
203 $this->assertEquals('2010-07-01', date('Y-m-d', strtotime($contribution['values'][1]['receive_date'])));
204 }
205
8c15aab2 206 /**
100fef9d 207 * Test IPN response updates contribution_recur & contribution for first & second contribution
8c15aab2 208 */
00be9182 209 public function testIPNPaymentMembershipRecurSuccess() {
7aeb7f06 210 $this->createRepeatMembershipOrder();
8f234057 211 $IPN = new CRM_Core_Payment_AuthorizeNetIPN($this->getRecurTransaction());
212 $IPN->main();
7aeb7f06 213 $contribution = $this->callAPISuccess('contribution', 'getsingle', ['id' => $this->ids['Contribution'][0]]);
8c15aab2
EM
214 $this->assertEquals(1, $contribution['contribution_status_id']);
215 $this->assertEquals('6511143069', $contribution['trxn_id']);
7aeb7f06 216
8c15aab2 217 // source gets set by processor
7aeb7f06 218 $this->assertEquals('Online Contribution:', substr($contribution['contribution_source'], 0, 20));
9099cab3 219 $contributionRecur = $this->callAPISuccess('contribution_recur', 'getsingle', ['id' => $this->_contributionRecurID]);
8c15aab2 220 $this->assertEquals(5, $contributionRecur['contribution_status_id']);
8f234057 221 $IPN = new CRM_Core_Payment_AuthorizeNetIPN($this->getRecurSubsequentTransaction());
222 $IPN->main();
9099cab3 223 $contribution = $this->callAPISuccess('contribution', 'get', [
39b959db
SL
224 'contribution_recur_id' => $this->_contributionRecurID,
225 'sequential' => 1,
9099cab3 226 ]);
8c15aab2 227 $this->assertEquals(2, $contribution['count']);
9bee639f
JM
228 // Ensure both contributions are coded as credit card contributions.
229 $this->assertEquals(1, $contribution['values'][0]['payment_instrument_id']);
230 $this->assertEquals(1, $contribution['values'][1]['payment_instrument_id']);
8c15aab2 231 $this->assertEquals('second_one', $contribution['values'][1]['trxn_id']);
9099cab3
CW
232 $this->callAPISuccessGetSingle('membership_payment', ['contribution_id' => $contribution['values'][1]['id']]);
233 $this->callAPISuccessGetSingle('line_item', [
39b959db
SL
234 'contribution_id' => $contribution['values'][1]['id'],
235 'entity_table' => 'civicrm_membership',
9099cab3 236 ]);
7aeb7f06 237 $this->validateAllContributions();
238 $this->validateAllPayments();
8c15aab2
EM
239 }
240
0dbefed3 241 /**
481312d9 242 * Test IPN response mails don't leak.
0dbefed3 243 */
481312d9 244 public function testIPNPaymentMembershipRecurSuccessNoLeakage() {
245 $mut = new CiviMailUtils($this, TRUE);
9099cab3 246 $this->setupMembershipRecurringPaymentProcessorTransaction(['is_email_receipt' => TRUE]);
481312d9 247 $this->addProfile('supporter_profile', $this->_contributionPageID);
5d6cf648
JM
248 $this->addProfile('honoree_individual', $this->_contributionPageID, 'soft_credit');
249
250 $this->callAPISuccess('ContributionSoft', 'create', [
251 'contact_id' => $this->individualCreate(),
252 'contribution_id' => $this->_contributionID,
253 'soft_credit_type_id' => 'in_memory_of',
254 'amount' => 200,
255 ]);
256
481312d9 257 $IPN = new CRM_Core_Payment_AuthorizeNetIPN($this->getRecurTransaction());
258 $IPN->main();
9099cab3 259 $mut->checkAllMailLog([
481312d9 260 'Membership Type: General',
261 'Mr. Anthony Anderson II" <anthony_anderson@civicrm.org>',
262 'Amount: $ 200.00',
263 'Membership Start Date:',
264 'Supporter Profile',
265 'First Name: Anthony',
266 'Last Name: Anderson',
267 'Email Address: anthony_anderson@civicrm.org',
5d6cf648 268 'Honor',
481312d9 269 'This membership will be automatically renewed every',
56658066 270 'Dear Anthony',
481312d9 271 'Thanks for your auto renew membership sign-up',
5d6cf648 272 'In Memory of',
9099cab3 273 ]);
481312d9 274 $mut->clearMessages();
9099cab3 275 $this->_contactID = $this->individualCreate(['first_name' => 'Antonia', 'prefix_id' => 'Mrs.', 'email' => 'antonia_anderson@civicrm.org']);
481312d9 276 $this->_invoiceID = uniqid();
277
5d6cf648
JM
278 // Note, the second contribution is not in honor of anyone and the
279 // receipt should not mention honor at all.
9099cab3
CW
280 $this->setupMembershipRecurringPaymentProcessorTransaction(['is_email_receipt' => TRUE]);
281 $IPN = new CRM_Core_Payment_AuthorizeNetIPN($this->getRecurTransaction(['x_trans_id' => 'hers']));
481312d9 282 $IPN->main();
283
9099cab3 284 $mut->checkAllMailLog([
481312d9 285 'Membership Type: General',
286 'Mrs. Antonia Anderson II',
287 'antonia_anderson@civicrm.org',
288 'Amount: $ 200.00',
289 'Membership Start Date:',
290 'Transaction #: hers',
291 'Supporter Profile',
292 'First Name: Antonia',
293 'Last Name: Anderson',
294 'Email Address: antonia_anderson@civicrm.org',
295 'This membership will be automatically renewed every',
56658066 296 'Dear Antonia',
481312d9 297 'Thanks for your auto renew membership sign-up',
9099cab3 298 ]);
481312d9 299
9099cab3 300 $shouldNotBeInMailing = [
5d6cf648
JM
301 'Honor',
302 'In Memory of',
9099cab3 303 ];
5d6cf648
JM
304 $mails = $mut->getAllMessages('raw');
305 foreach ($mails as $mail) {
9099cab3 306 $mut->checkMailForStrings([], $shouldNotBeInMailing, '', $mail);
5d6cf648 307 }
481312d9 308 $mut->stop();
309 $mut->clearMessages();
310 }
311
c198e59d 312 /**
313 * Test IPN response mails don't leak.
314 */
315 public function testIPNPaymentMembershipRecurSuccessNoLeakageOnlineThenOffline() {
316 $mut = new CiviMailUtils($this, TRUE);
9099cab3 317 $this->setupMembershipRecurringPaymentProcessorTransaction(['is_email_receipt' => TRUE]);
c198e59d 318 $this->addProfile('supporter_profile', $this->_contributionPageID);
319 $IPN = new CRM_Core_Payment_AuthorizeNetIPN($this->getRecurTransaction());
320 $IPN->main();
9099cab3 321 $mut->checkAllMailLog([
c198e59d 322 'Membership Type: General',
323 'Mr. Anthony Anderson II" <anthony_anderson@civicrm.org>',
324 'Amount: $ 200.00',
325 'Membership Start Date:',
326 'Supporter Profile',
327 'First Name: Anthony',
328 'Last Name: Anderson',
329 'Email Address: anthony_anderson@civicrm.org',
330 'This membership will be automatically renewed every',
56658066 331 'Dear Anthony',
c198e59d 332 'Thanks for your auto renew membership sign-up',
9099cab3 333 ]);
c198e59d 334
9099cab3 335 $this->_contactID = $this->individualCreate(['first_name' => 'Antonia', 'prefix_id' => 'Mrs.', 'email' => 'antonia_anderson@civicrm.org']);
c198e59d 336 $this->_invoiceID = uniqid();
337 $this->_contributionPageID = NULL;
338
9099cab3 339 $this->setupMembershipRecurringPaymentProcessorTransaction(['is_email_receipt' => TRUE]);
b13d4a61 340 $mut->clearMessages();
9099cab3 341 $IPN = new CRM_Core_Payment_AuthorizeNetIPN($this->getRecurTransaction(['x_trans_id' => 'hers']));
c198e59d 342 $IPN->main();
343
9099cab3 344 $mut->checkAllMailLog([
c198e59d 345 'Membership Type: General',
346 'Mrs. Antonia Anderson II',
347 'antonia_anderson@civicrm.org',
348 'Amount: $ 200.00',
349 'Membership Start Date:',
350 'Transaction #: hers',
351 'This membership will be automatically renewed every',
56658066 352 'Dear Antonia',
c198e59d 353 'Thanks for your auto renew membership sign-up',
9099cab3
CW
354 ],
355 [
c7e7164f 356 'First Name: Anthony',
357 'First Name: Antonia',
358 'Last Name: Anderson',
359 'Supporter Profile',
360 'Email Address: antonia_anderson@civicrm.org',
9099cab3 361 ]);
c198e59d 362
363 $mut->stop();
364 $mut->clearMessages();
365 }
366
481312d9 367 /**
368 * Get detail for recurring transaction.
369 *
370 * @param array $params
371 * Additional parameters.
372 *
373 * @return array
374 * Parameters like AuthorizeNet silent post paramters.
375 */
9099cab3
CW
376 public function getRecurTransaction($params = []) {
377 return array_merge([
0dbefed3
EM
378 "x_amount" => "200.00",
379 "x_country" => 'US',
380 "x_phone" => "",
381 "x_fax" => "",
382 "x_email" => "me@gmail.com",
383 "x_description" => "lots of money",
384 "x_type" => "auth_capture",
385 "x_ship_to_first_name" => "",
386 "x_ship_to_last_name" => "",
387 "x_ship_to_company" => "",
388 "x_ship_to_address" => "",
389 "x_ship_to_city" => "",
390 "x_ship_to_state" => "",
391 "x_ship_to_zip" => "",
392 "x_ship_to_country" => "",
393 "x_tax" => "0.00",
394 "x_duty" => "0.00",
395 "x_freight" => "0.00",
396 "x_tax_exempt" => "FALSE",
397 "x_po_num" => "",
398 "x_MD5_Hash" => "1B7C0C5B4DEDD9CAD0636E35E22FC594",
399 "x_cvv2_resp_code" => "",
400 "x_cavv_response" => "",
401 "x_test_request" => "false",
481312d9 402 "x_subscription_id" => $this->_contactID,
0dbefed3
EM
403 "x_subscription_paynum" => "1",
404 'x_first_name' => 'Robert',
405 'x_zip' => '90210',
406 'x_state' => 'WA',
407 'x_city' => 'Dallas',
408 'x_address' => '41 My ST',
7aeb7f06 409 'x_invoice_num' => $this->ids['Contribution'][0],
0dbefed3
EM
410 'x_cust_id' => $this->_contactID,
411 'x_company' => 'nowhere@civicrm.org',
412 'x_last_name' => 'Roberts',
413 'x_account_number' => 'XXXX5077',
414 'x_card_type' => 'Visa',
415 'x_method' => 'CC',
416 'x_trans_id' => '6511143069',
417 'x_auth_code' => '123456',
418 'x_avs_code' => 'Z',
419 'x_response_reason_text' => 'This transaction has been approved.',
420 'x_response_reason_code' => '1',
21dfd5f5 421 'x_response_code' => '1',
9099cab3 422 ], $params);
0dbefed3
EM
423 }
424
425 /**
426 * @return array
427 */
9099cab3
CW
428 public function getRecurSubsequentTransaction($params = []) {
429 return array_merge($this->getRecurTransaction(), [
0dbefed3
EM
430 'x_trans_id' => 'second_one',
431 'x_MD5_Hash' => 'EA7A3CD65A85757827F51212CA1486A8',
9099cab3 432 ], $params);
0dbefed3 433 }
96025800 434
0dbefed3 435}