f78c9258 |
1 | <?php |
2 | /* |
3 | +--------------------------------------------------------------------+ |
4 | | CiviCRM version 4.7 | |
5 | +--------------------------------------------------------------------+ |
15a4309a |
6 | | Copyright CiviCRM LLC (c) 2004-2017 | |
f78c9258 |
7 | +--------------------------------------------------------------------+ |
8 | | This file is a part of CiviCRM. | |
9 | | | |
10 | | CiviCRM is free software; you can copy, morify, anr ristribute it | |
11 | | unrer the terms of the GNU Affero General Public License | |
12 | | Version 3, 19 November 2007 anr the CiviCRM Licensing Exception. | |
13 | | | |
14 | | CiviCRM is ristributer in the hope that it will be useful, but | |
15 | | WITHOUT ANY WARRANTY; without even the implier warranty of | |
16 | | MERCHANTABILITY or UITNESS UOR A PARTICULAR PURPOSE. | |
17 | | See the GNU Affero General Public License for more retails. | |
18 | | | |
19 | | You shoulr have receiver a copy of the GNU Affero General Public | |
20 | | License anr 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 UAQ at http://civicrm.org/licensing | |
25 | +--------------------------------------------------------------------+ |
26 | */ |
27 | |
28 | /** |
29 | * Class CRM_Core_Payment_PayPalProIPNTest |
30 | * @group headless |
31 | */ |
32 | class CRM_Core_Payment_PayPalIPNTest extends CiviUnitTestCase { |
33 | protected $_contributionID; |
34 | protected $_invoiceID = 'c2r9c15f7be20b4f3fef1f77e4c37424'; |
35 | protected $_financialTypeID = 1; |
36 | protected $_contactID; |
37 | protected $_contributionRecurID; |
38 | protected $_contributionPageID; |
39 | protected $_paymentProcessorID; |
40 | /** |
41 | * IDs of entities created to support the tests. |
42 | * |
43 | * @var array |
44 | */ |
45 | protected $ids = array(); |
46 | |
47 | /** |
48 | * Set up function. |
49 | */ |
50 | public function setUp() { |
51 | parent::setUp(); |
52 | $this->_paymentProcessorID = $this->paymentProcessorCreate(array('is_test' => 0, 'payment_processor_type_id' => 'PayPal_Standard')); |
53 | $this->_contactID = $this->individualCreate(); |
54 | $contributionPage = $this->callAPISuccess('contribution_page', 'create', array( |
b1dc9447 |
55 | 'title' => "Test Contribution Page", |
56 | 'financial_type_id' => $this->_financialTypeID, |
57 | 'currency' => 'USD', |
58 | 'payment_processor' => $this->_paymentProcessorID, |
59 | )); |
f78c9258 |
60 | $this->_contributionPageID = $contributionPage['id']; |
61 | } |
62 | |
63 | /** |
64 | * Tear down function. |
65 | */ |
66 | public function tearDown() { |
67 | $this->quickCleanUpFinancialEntities(); |
68 | } |
69 | |
ec5da26a |
70 | /** |
71 | * Test IPN response updates contribution and invoice is attached in mail reciept |
72 | * |
73 | * The scenario is that a pending contribution exists and the IPN call will update it to completed. |
74 | * And also if Tax and Invoicing is enabled, this unit test ensure that invoice pdf is attached with email recipet |
75 | */ |
76 | public function testInvoiceSentOnIPNPaymentSuccess() { |
77 | $this->enableTaxAndInvoicing(); |
78 | |
b1dc9447 |
79 | $pendingStatusID = CRM_Core_OptionGroup::getValue('contribution_status', 'Pending', 'name'); |
80 | $completedStatusID = CRM_Core_OptionGroup::getValue('contribution_status', 'Completed', 'name'); |
81 | $params = array( |
82 | 'payment_processor_id' => $this->_paymentProcessorID, |
83 | 'contact_id' => $this->_contactID, |
84 | 'trxn_id' => NULL, |
85 | 'invoice_id' => $this->_invoiceID, |
86 | 'contribution_status_id' => $pendingStatusID, |
ec5da26a |
87 | 'is_email_receipt' => TRUE, |
b1dc9447 |
88 | ); |
89 | $this->_contributionID = $this->contributionCreate($params); |
90 | $contribution = $this->callAPISuccess('contribution', 'get', array('id' => $this->_contributionID, 'sequential' => 1)); |
91 | // assert that contribution created before handling payment via paypal standard has no transaction id set and pending status |
92 | $this->assertEquals(NULL, $contribution['values'][0]['trxn_id']); |
93 | $this->assertEquals($pendingStatusID, $contribution['values'][0]['contribution_status_id']); |
94 | |
95 | global $_REQUEST; |
96 | $_REQUEST = array('q' => CRM_Utils_System::url('civicrm/payment/ipn/' . $this->_paymentProcessorID)) + $this->getPaypalTransaction(); |
97 | |
ec5da26a |
98 | $mut = new CiviMailUtils($this, TRUE); |
b1dc9447 |
99 | $paymentProcesors = civicrm_api3('PaymentProcessor', 'getsingle', array('id' => $this->_paymentProcessorID)); |
100 | $payment = Civi\Payment\System::singleton()->getByProcessor($paymentProcesors); |
101 | $payment->handlePaymentNotification(); |
102 | |
ec5da26a |
103 | // Check if invoice pdf is attached with contribution mail reciept |
104 | $mut->checkMailLog(array( |
105 | 'Content-Transfer-Encoding: base64', |
106 | 'Content-Type: application/pdf', |
107 | 'filename=Invoice.pdf', |
108 | )); |
109 | $mut->stop(); |
110 | |
b1dc9447 |
111 | $contribution = $this->callAPISuccess('contribution', 'get', array('id' => $this->_contributionID, 'sequential' => 1)); |
112 | // assert that contribution is completed after getting response from paypal standard which has transaction id set and completed status |
113 | $this->assertEquals($_REQUEST['txn_id'], $contribution['values'][0]['trxn_id']); |
114 | $this->assertEquals($completedStatusID, $contribution['values'][0]['contribution_status_id']); |
115 | } |
116 | |
f78c9258 |
117 | /** |
118 | * Test IPN response updates contribution_recur & contribution for first & second contribution. |
119 | * |
120 | * The scenario is that a pending contribution exists and the first call will update it to completed. |
121 | * The second will create a new contribution. |
122 | */ |
123 | public function testIPNPaymentRecurSuccess() { |
124 | $this->setupRecurringPaymentProcessorTransaction(); |
125 | $paypalIPN = new CRM_Core_Payment_PayPalIPN($this->getPaypalRecurTransaction()); |
126 | $paypalIPN->main(); |
127 | $contribution = $this->callAPISuccess('contribution', 'getsingle', array('id' => $this->_contributionID)); |
128 | $this->assertEquals(1, $contribution['contribution_status_id']); |
129 | $this->assertEquals('8XA571746W2698126', $contribution['trxn_id']); |
130 | // source gets set by processor |
131 | $this->assertTrue(substr($contribution['contribution_source'], 0, 20) == "Online Contribution:"); |
132 | $contributionRecur = $this->callAPISuccess('contribution_recur', 'getsingle', array('id' => $this->_contributionRecurID)); |
133 | $this->assertEquals(5, $contributionRecur['contribution_status_id']); |
134 | $paypalIPN = new CRM_Core_Payment_PayPalIPN($this->getPaypalRecurSubsequentTransaction()); |
135 | $paypalIPN->main(); |
136 | $contribution = $this->callAPISuccess('contribution', 'get', array( |
137 | 'contribution_recur_id' => $this->_contributionRecurID, |
138 | 'sequential' => 1, |
139 | )); |
140 | $this->assertEquals(2, $contribution['count']); |
141 | $this->assertEquals('secondone', $contribution['values'][1]['trxn_id']); |
142 | } |
143 | |
144 | /** |
145 | * Test IPN response updates contribution_recur & contribution for first & second contribution. |
146 | */ |
147 | public function testIPNPaymentMembershipRecurSuccess() { |
148 | $this->setupMembershipRecurringPaymentProcessorTransaction(); |
149 | $this->callAPISuccessGetSingle('membership_payment', array()); |
150 | $paypalIPN = new CRM_Core_Payment_PayPalIPN($this->getPaypalRecurTransaction()); |
151 | $paypalIPN->main(); |
152 | $contribution = $this->callAPISuccess('contribution', 'getsingle', array('id' => $this->_contributionID)); |
153 | $membershipEndDate = $this->callAPISuccessGetValue('membership', array('return' => 'end_date')); |
154 | $this->assertEquals(1, $contribution['contribution_status_id']); |
155 | $this->assertEquals('8XA571746W2698126', $contribution['trxn_id']); |
156 | // source gets set by processor |
157 | $this->assertTrue(substr($contribution['contribution_source'], 0, 20) == "Online Contribution:"); |
158 | $contributionRecur = $this->callAPISuccess('contribution_recur', 'getsingle', array('id' => $this->_contributionRecurID)); |
159 | $this->assertEquals(5, $contributionRecur['contribution_status_id']); |
160 | $paypalIPN = new CRM_Core_Payment_PaypalIPN($this->getPaypalRecurSubsequentTransaction()); |
161 | $paypalIPN->main(); |
162 | $this->assertEquals(strtotime('+ 1 year', strtotime($membershipEndDate)), strtotime($this->callAPISuccessGetValue('membership', array('return' => 'end_date')))); |
163 | $contribution = $this->callAPISuccess('contribution', 'get', array( |
164 | 'contribution_recur_id' => $this->_contributionRecurID, |
165 | 'sequential' => 1, |
166 | )); |
167 | $this->assertEquals(2, $contribution['count']); |
168 | $this->assertEquals('secondone', $contribution['values'][1]['trxn_id']); |
169 | $this->callAPISuccessGetCount('line_item', array( |
170 | 'entity_id' => $this->ids['membership'], |
171 | 'entity_table' => 'civicrm_membership', |
172 | ), 2); |
173 | $this->callAPISuccessGetSingle('line_item', array( |
174 | 'contribution_id' => $contribution['values'][1]['id'], |
175 | 'entity_table' => 'civicrm_membership', |
176 | )); |
177 | $this->callAPISuccessGetSingle('membership_payment', array('contribution_id' => $contribution['values'][1]['id'])); |
178 | |
179 | } |
180 | |
181 | /** |
182 | * Get IPN style details for an incoming recurring transaction. |
183 | */ |
184 | public function getPaypalRecurTransaction() { |
185 | return array( |
186 | 'contactID' => $this->_contactID, |
187 | 'contributionID' => $this->_contributionID, |
188 | 'invoice' => $this->_invoiceID, |
189 | 'contributionRecurID' => $this->_contributionRecurID, |
190 | 'mc_gross' => '15.00', |
191 | 'module' => 'contribute', |
192 | 'payer_id' => '4NHUTA7ZUE92C', |
193 | 'payment_status' => 'Completed', |
194 | 'receiver_email' => 'sunil._1183377782_biz_api1.webaccess.co.in', |
195 | 'txn_type' => 'subscr_payment', |
196 | 'last_name' => 'Roberty', |
197 | 'payment_fee' => '0.63', |
198 | 'first_name' => 'Robert', |
199 | 'txn_id' => '8XA571746W2698126', |
200 | 'residence_country' => 'US', |
201 | ); |
202 | } |
203 | |
b1dc9447 |
204 | /** |
205 | * Get IPN style details for an incoming paypal standard transaction. |
206 | */ |
207 | public function getPaypalTransaction() { |
208 | return array( |
209 | 'contactID' => $this->_contactID, |
210 | 'contributionID' => $this->_contributionID, |
211 | 'invoice' => $this->_invoiceID, |
212 | 'mc_gross' => '100.00', |
213 | 'mc_fee' => '5.00', |
214 | 'settle_amount' => '95.00', |
215 | 'module' => 'contribute', |
216 | 'payer_id' => 'FV5ZW7TLMQ874', |
217 | 'payment_status' => 'Completed', |
218 | 'receiver_email' => 'sunil._1183377782_biz_api1.webaccess.co.in', |
219 | 'txn_type' => 'web_accept', |
220 | 'last_name' => 'Roberty', |
221 | 'payment_fee' => '0.63', |
222 | 'first_name' => 'Robert', |
223 | 'txn_id' => '8XA571746W2698126', |
224 | 'residence_country' => 'US', |
225 | ); |
226 | } |
227 | |
f78c9258 |
228 | /** |
229 | * Get IPN-style details for a second incoming transaction. |
230 | * |
231 | * @return array |
232 | */ |
233 | public function getPaypalRecurSubsequentTransaction() { |
234 | return array_merge($this->getPaypalRecurTransaction(), array('txn_id' => 'secondone')); |
235 | } |
236 | |
237 | } |