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