Merge pull request #15861 from JMAConsulting/core-1398
[civicrm-core.git] / tests / phpunit / CRM / Core / Payment / AuthorizeNetTest.php
1 <?php
2 /*
3 +--------------------------------------------------------------------+
4 | Copyright CiviCRM LLC. All rights reserved. |
5 | |
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 +--------------------------------------------------------------------+
10 */
11
12 /**
13 * Class CRM_Core_Payment_AuthorizeNetTest
14 * @group headless
15 */
16 class CRM_Core_Payment_AuthorizeNetTest extends CiviUnitTestCase {
17
18 public function setUp() {
19 parent::setUp();
20 $this->_paymentProcessorID = $this->paymentProcessorAuthorizeNetCreate();
21
22 $this->processor = Civi\Payment\System::singleton()->getById($this->_paymentProcessorID);
23 $this->_financialTypeId = 1;
24
25 // for some strange unknown reason, in batch mode this value gets set to null
26 // so crude hack here to avoid an exception and hence an error
27 $GLOBALS['_PEAR_ERRORSTACK_OVERRIDE_CALLBACK'] = [];
28 }
29
30 public function tearDown() {
31 $this->quickCleanUpFinancialEntities();
32 }
33
34 /**
35 * Create a single post dated payment as a recurring transaction.
36 *
37 * Test works but not both due to some form of caching going on in the SmartySingleton
38 */
39 public function testCreateSingleNowDated() {
40 $firstName = 'John_' . substr(sha1(rand()), 0, 7) . uniqid();
41 $lastName = 'Smith_' . substr(sha1(rand()), 0, 7) . uniqid();
42 $nameParams = ['first_name' => $firstName, 'last_name' => $lastName];
43 $contactId = $this->individualCreate($nameParams);
44
45 $invoiceID = sha1(rand());
46 $amount = rand(100, 1000) . '.00';
47
48 $recur = $this->callAPISuccess('ContributionRecur', 'create', [
49 'contact_id' => $contactId,
50 'amount' => $amount,
51 'currency' => 'USD',
52 'frequency_unit' => 'week',
53 'frequency_interval' => 1,
54 'installments' => 2,
55 'start_date' => date('Ymd'),
56 'create_date' => date('Ymd'),
57 'invoice_id' => $invoiceID,
58 'contribution_status_id' => 2,
59 'is_test' => 1,
60 'payment_processor_id' => $this->_paymentProcessorID,
61 ]);
62
63 $contribution = $this->callAPISuccess('Contribution', 'create', [
64 'contact_id' => $contactId,
65 'financial_type_id' => $this->_financialTypeId,
66 'receive_date' => date('Ymd'),
67 'total_amount' => $amount,
68 'invoice_id' => $invoiceID,
69 'currency' => 'USD',
70 'contribution_recur_id' => $recur['id'],
71 'is_test' => 1,
72 'contribution_status_id' => 2,
73 ]);
74
75 $params = [
76 'qfKey' => '08ed21c7ca00a1f7d32fff2488596ef7_4454',
77 'hidden_CreditCard' => 1,
78 'billing_first_name' => $firstName,
79 'billing_middle_name' => "",
80 'billing_last_name' => $lastName,
81 'billing_street_address-5' => '8 Hobbitton Road',
82 'billing_city-5' => 'The Shire',
83 'billing_state_province_id-5' => 1012,
84 'billing_postal_code-5' => 5010,
85 'billing_country_id-5' => 1228,
86 'credit_card_number' => '4444333322221111',
87 'cvv2' => 123,
88 'credit_card_exp_date' => [
89 'M' => 9,
90 'Y' => 2025,
91 ],
92 'credit_card_type' => 'Visa',
93 'is_recur' => 1,
94 'frequency_interval' => 1,
95 'frequency_unit' => 'month',
96 'installments' => 12,
97 'financial_type_id' => $this->_financialTypeId,
98 'is_email_receipt' => 1,
99 'from_email_address' => "{$firstName}.{$lastName}@example.com",
100 'receive_date' => date('Ymd'),
101 'receipt_date_time' => '',
102 'payment_processor_id' => $this->_paymentProcessorID,
103 'price_set_id' => '',
104 'total_amount' => $amount,
105 'currency' => 'USD',
106 'source' => "Mordor",
107 'soft_credit_to' => '',
108 'soft_contact_id' => '',
109 'billing_state_province-5' => 'IL',
110 'state_province-5' => 'IL',
111 'billing_country-5' => 'US',
112 'country-5' => 'US',
113 'year' => 2025,
114 'month' => 9,
115 'ip_address' => '127.0.0.1',
116 'amount' => 7,
117 'amount_level' => 0,
118 'currencyID' => 'USD',
119 'pcp_display_in_roll' => "",
120 'pcp_roll_nickname' => "",
121 'pcp_personal_note' => "",
122 'non_deductible_amount' => "",
123 'fee_amount' => "",
124 'net_amount' => "",
125 'invoiceID' => $invoiceID,
126 'contribution_page_id' => "",
127 'thankyou_date' => NULL,
128 'honor_contact_id' => NULL,
129 'first_name' => $firstName,
130 'middle_name' => '',
131 'last_name' => $lastName,
132 'street_address' => '8 Hobbiton Road' . uniqid(),
133 'city' => 'The Shire',
134 'state_province' => 'IL',
135 'postal_code' => 5010,
136 'country' => 'US',
137 'contributionType_name' => 'My precious',
138 'contributionType_accounting_code' => '',
139 'contributionPageID' => '',
140 'email' => "{$firstName}.{$lastName}@example.com",
141 'contactID' => $contactId,
142 'contributionID' => $contribution['id'],
143 'contributionTypeID' => $this->_financialTypeId,
144 'contributionRecurID' => $recur['id'],
145 ];
146
147 // turn verifySSL off
148 Civi::settings()->set('verifySSL', '0');
149 $this->doPayment($params);
150 // turn verifySSL on
151 Civi::settings()->set('verifySSL', '0');
152
153 // if subscription was successful, processor_id / subscription-id must not be null
154 $this->assertDBNotNull('CRM_Contribute_DAO_ContributionRecur', $recur['id'], 'processor_id',
155 'id', 'Failed to create subscription with Authorize.'
156 );
157
158 // cancel it or the transaction will be rejected by A.net if the test is re-run
159 $subscriptionID = CRM_Core_DAO::getFieldValue('CRM_Contribute_DAO_ContributionRecur', $recur['id'], 'processor_id');
160 $message = '';
161 $result = $this->processor->cancelSubscription($message, ['subscriptionId' => $subscriptionID]);
162 $this->assertTrue($result, 'Failed to cancel subscription with Authorize.');
163 }
164
165 /**
166 * Create a single post dated payment as a recurring transaction.
167 */
168 public function testCreateSinglePostDated() {
169 $start_date = date('Ymd', strtotime("+ 1 week"));
170
171 $firstName = 'John_' . substr(sha1(rand()), 0, 7);
172 $lastName = 'Smith_' . substr(sha1(rand()), 0, 7);
173 $nameParams = ['first_name' => $firstName, 'last_name' => $lastName];
174 $contactId = $this->individualCreate($nameParams);
175
176 $ids = ['contribution' => NULL];
177 $invoiceID = sha1(rand());
178 $amount = rand(100, 1000) . '.00';
179
180 $contributionRecurParams = [
181 'contact_id' => $contactId,
182 'amount' => $amount,
183 'currency' => 'USD',
184 'frequency_unit' => 'month',
185 'frequency_interval' => 1,
186 'installments' => 3,
187 'start_date' => $start_date,
188 'create_date' => date('Ymd'),
189 'invoice_id' => $invoiceID,
190 'contribution_status_id' => 2,
191 'is_test' => 1,
192 'payment_processor_id' => $this->_paymentProcessorID,
193 ];
194 $recur = CRM_Contribute_BAO_ContributionRecur::add($contributionRecurParams, $ids);
195
196 $contributionParams = [
197 'contact_id' => $contactId,
198 'financial_type_id' => $this->_financialTypeId,
199 'receive_date' => $start_date,
200 'total_amount' => $amount,
201 'invoice_id' => $invoiceID,
202 'currency' => 'USD',
203 'contribution_recur_id' => $recur->id,
204 'is_test' => 1,
205 'contribution_status_id' => 2,
206 ];
207
208 $contribution = $this->callAPISuccess('contribution', 'create', $contributionParams);
209
210 $params = [
211 'qfKey' => '00ed21c7ca00a1f7d555555596ef7_4454',
212 'hidden_CreditCard' => 1,
213 'billing_first_name' => $firstName,
214 'billing_middle_name' => "",
215 'billing_last_name' => $lastName,
216 'billing_street_address-5' => '8 Hobbitton Road',
217 'billing_city-5' => 'The Shire',
218 'billing_state_province_id-5' => 1012,
219 'billing_postal_code-5' => 5010,
220 'billing_country_id-5' => 1228,
221 'credit_card_number' => '4007000000027',
222 'cvv2' => 123,
223 'credit_card_exp_date' => [
224 'M' => 11,
225 'Y' => 2022,
226 ],
227 'credit_card_type' => 'Visa',
228 'is_recur' => 1,
229 'frequency_interval' => 1,
230 'frequency_unit' => 'month',
231 'installments' => 3,
232 'financial_type_id' => $this->_financialTypeId,
233 'is_email_receipt' => 1,
234 'from_email_address' => "{$firstName}.{$lastName}@example.com",
235 'receive_date' => $start_date,
236 'receipt_date_time' => '',
237 'payment_processor_id' => $this->_paymentProcessorID,
238 'price_set_id' => '',
239 'total_amount' => $amount,
240 'currency' => 'USD',
241 'source' => "Mordor",
242 'soft_credit_to' => '',
243 'soft_contact_id' => '',
244 'billing_state_province-5' => 'IL',
245 'state_province-5' => 'IL',
246 'billing_country-5' => 'US',
247 'country-5' => 'US',
248 'year' => 2022,
249 'month' => 10,
250 'ip_address' => '127.0.0.1',
251 'amount' => 70,
252 'amount_level' => 0,
253 'currencyID' => 'USD',
254 'pcp_display_in_roll' => "",
255 'pcp_roll_nickname' => "",
256 'pcp_personal_note' => "",
257 'non_deductible_amount' => "",
258 'fee_amount' => "",
259 'net_amount' => "",
260 'invoice_id' => "",
261 'contribution_page_id' => "",
262 'thankyou_date' => NULL,
263 'honor_contact_id' => NULL,
264 'invoiceID' => $invoiceID,
265 'first_name' => $firstName,
266 'middle_name' => 'bob',
267 'last_name' => $lastName,
268 'street_address' => '8 Hobbiton Road' . uniqid(),
269 'city' => 'The Shire',
270 'state_province' => 'IL',
271 'postal_code' => 5010,
272 'country' => 'US',
273 'contributionPageID' => '',
274 'email' => "{$firstName}.{$lastName}@example.com",
275 'contactID' => $contactId,
276 'contributionID' => $contribution['id'],
277 'contributionRecurID' => $recur->id,
278 ];
279
280 // if cancel-subscription has been called earlier 'subscriptionType' would be set to cancel.
281 // to make a successful call for another trxn, we need to set it to something else.
282 $smarty = CRM_Core_Smarty::singleton();
283 $smarty->assign('subscriptionType', 'create');
284
285 // turn verifySSL off
286 Civi::settings()->set('verifySSL', '0');
287 $this->doPayment($params);
288 // turn verifySSL on
289 Civi::settings()->set('verifySSL', '0');
290
291 // if subscription was successful, processor_id / subscription-id must not be null
292 $this->assertDBNotNull('CRM_Contribute_DAO_ContributionRecur', $recur->id, 'processor_id',
293 'id', 'Failed to create subscription with Authorize.'
294 );
295
296 // cancel it or the transaction will be rejected by A.net if the test is re-run
297 $subscriptionID = CRM_Core_DAO::getFieldValue('CRM_Contribute_DAO_ContributionRecur', $recur->id, 'processor_id');
298 $message = '';
299 $result = $this->processor->cancelSubscription($message, ['subscriptionId' => $subscriptionID]);
300 $this->assertTrue($result, 'Failed to cancel subscription with Authorize.');
301 }
302
303 /**
304 * Process payment against the Authorize.net test server.
305 *
306 * Skip the test if the server is unresponsive.
307 *
308 * @param array $params
309 *
310 * @throws PHPUnit\Framework\SkippedTestError
311 */
312 public function doPayment($params) {
313 try {
314 $this->processor->doPayment($params);
315 }
316 catch (Exception $e) {
317 $this->assertTrue((strpos($e->getMessage(), 'E00001: Internal Error Occurred.') !== FALSE),
318 'AuthorizeNet failed for unknown reason.' . $e->getMessage());
319 $this->markTestSkipped('AuthorizeNet test server is not in a good mood so we can\'t test this right now');
320 }
321 }
322
323 }