3 * This file is part of CiviCRM.
5 * CiviCRM is free software: you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation, either version 3 of the License, or
8 * (at your option) any later version.
10 * CiviCRM is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with CiviCRM. If not, see <http://www.gnu.org/licenses/>.
19 * Licensed to CiviCRM under the GPL v3 or higher
21 * Modified by Lisa Marie Maginnis <lisa@fsf.org> (http://www.fsf.org)
25 class CRM_Core_Payment_trustcommerce_IPN
extends CRM_Core_Payment_BaseIPN
{
26 function __construct() {
27 parent
::__construct();
31 function main($component = 'contribute') {
33 $billingid = CRM_Utils_Request
::retrieve('billingid', 'String', $no, FALSE, 'GET');
34 $input['status'] = CRM_Utils_Request
::retrieve('status', 'String', $no, FALSE, 'GET');
35 $input['amount'] = CRM_Utils_Request
::retrieve('amount', 'String', $no, FALSE, 'GET');
36 $input['date'] = CRM_Utils_Request
::retrieve('date', 'String', $no, FALSE, 'GET');
37 $input['trxn_id'] = CRM_Utils_Request
::retrieve('trxn_id', 'String', $no, FALSE, 'GET');
38 $checksum = CRM_Utils_Request
::retrieve('checksum', 'String', $no, FALSE, 'GET');
41 if( $input['status'] == '' ||
$input['amount'] == '' ||
$input['date'] == '' ||
$input['trxn_id'] == '' ||
md5($billingid.$input['trxn_id'].$input['amount'].$input['date']) != $checksum) {
42 CRM_Core_Error
::debug_log_message("Error: IPN called with out proper fields");
43 echo "Error: invalid paramaters<p>\n";
48 $ids = $objects = array();
49 $input['component'] = $component;
51 // load post ids in $ids
53 $ids = $this->getIDs($billingid, $input, $input['component']);
55 $ids['trxn_id'] = $input['trxn_id'];
57 if($this->checkDuplicate($input, $ids) != NULL) {
58 CRM_Core_Error
::debug_log_message("Success: This payment has already been processed.");
59 echo "Success: This payment has already been processed<p>\n";
65 if(array_key_exists('membership', $ids)) {
66 $membership = array();
67 $params = array('id' => $ids['membership']);
68 $obj = CRM_Member_BAO_Membership
::retrieve($params, $membership);
69 $objects['membership'] = array(&$obj);
74 $paymentProcessorID = CRM_Core_DAO
::getFieldValue('CRM_Financial_DAO_PaymentProcessorType',
75 'TrustCommerce', 'id', 'name'
78 if (!$this->validateData($input, $ids, $objects, TRUE, $paymentProcessorID)) {
81 // var_dump($objects);
83 if ($component == 'contribute' && $ids['contributionRecur']) {
84 // check if first contribution is completed, else complete first contribution
86 if ($objects['contribution']->contribution_status_id
== 1) {
91 return $this->processRecur($input, $ids, $objects, $first);
98 protected function checkDuplicate($input, $ids) {
99 // $sql='select id from civicrm_contribution where receive_date like \''.$input['date'].'%\' and total_amount='.$input['amount'].' and contact_id='.$ids['contact'].' and contribution_status_id = 1 limit 1';
100 $sql="select id from civicrm_contribution where trxn_id = '".$ids['trxn_id']."'";
103 $result = CRM_Core_DAO
::executeQuery($sql);
108 protected function processRecur($input, $ids, $objects, $first) {
109 $recur = &$objects['contributionRecur'];
110 $contributionStatus = CRM_Contribute_PseudoConstant
::contributionStatus(NULL, 'name');
112 $transaction = new CRM_Core_Transaction();
114 $now = date('YmdHis');
116 // fix dates that already exist
117 $dates = array('create_date', 'start_date', 'end_date', 'cancel_date', 'modified_date');
118 foreach ($dates as $name) {
120 $recur->$name = CRM_Utils_Date
::isoToMysql($recur->$name);
125 // create a contribution and then get it processed
126 $contribution = new CRM_Contribute_BAO_Contribution();
127 $contribution->contact_id
= $ids['contact'];
128 $contribution->financial_type_id
= $objects['contributionType']->id
;
129 $contribution->contribution_page_id
= $ids['contributionPage'];
130 $contribution->contribution_recur_id
= $ids['contributionRecur'];
131 $contribution->receive_date
= $input['date'];
132 $contribution->currency
= $objects['contribution']->currency
;
133 $contribution->payment_instrument_id
= 1;
134 $contribution->amount_level
= $objects['contribution']->amount_level
;
135 $contribution->address_id
= $objects['contribution']->address_id
;
136 $contribution->honor_contact_id
= $objects['contribution']->honor_contact_id
;
137 $contribution->honor_type_id
= $objects['contribution']->honor_type_id
;
138 $contribution->campaign_id
= $objects['contribution']->campaign_id
;
139 $contribution->total_amount
= $input['amount'];
141 $objects['contribution'] = &$contribution;
143 $objects['contribution']->invoice_id
= md5(uniqid(rand(), TRUE));
144 // $objects['contribution']->total_amount = $objects['contribution']->total_amount;
145 $objects['contribution']->trxn_id
= $input['trxn_id'];
147 // since we have processor loaded for sure at this point,
149 $sendNotification = FALSE;
150 if ($input['status'] == 1) {
154 $recur->start_date
= $now;
155 $sendNotification = TRUE;
156 $subscriptionPaymentStatus = CRM_Core_Payment
::RECURRING_PAYMENT_START
;
158 $statusName = 'In Progress';
159 if (($recur->installments
> 0) &&
160 ($input['subscription_paynum'] >= $recur->installments
)
162 // this is the last payment
163 $statusName = 'Completed';
164 $recur->end_date
= $now;
166 $sendNotification = TRUE;
167 $subscriptionPaymentStatus = CRM_Core_Payment
::RECURRING_PAYMENT_END
;
169 $recur->trxn_id
= $input['trxn_id'];
170 $recur->total_amount
= $input['amount'];
171 $recur->payment_instrument_id
= 1;
173 $recur->net_amount
= NULL;
175 $recur->modified_date
= $now;
176 $recur->contribution_status_id
= array_search($statusName, $contributionStatus);
183 $recur->trxn_id
= $input['trxn_id'];
184 $recur->total_amount
= $input['amount'];
185 $recur->payment_instrument_id
= 1;
187 $recur->net_amount
= NULL;
190 $recur->contribution_status_id
= array_search('Failed', $contributionStatus);
191 $recur->cancel_date
= $now;
194 CRM_Core_Error
::debug_log_message("Subscription payment failed");
196 // the recurring contribution has declined a payment or has failed
197 // so we just fix the recurring contribution and not change any of
198 // the existing contribiutions
205 // check if contribution is already completed, if so we ignore this ipn
206 if ($objects['contribution']->contribution_status_id
== 1) {
207 $transaction->commit();
208 CRM_Core_Error
::debug_log_message("returning since contribution has already been handled");
209 echo 'Success: Contribution has already been handled<p>';
213 $input['is_test'] = 0;
215 $this->completeTransaction($input, $ids, $objects, $transaction, $recur);
217 echo 'Success: Created new contribution: '.$ids['contribution'].' for cid: '.$ids['contact'].'\n';
218 CRM_Core_Error
::debug_log_message('Success: Created new contribution: '.$ids['contribution'].' for cid: '.$ids['contact']);
220 if ($sendNotification) {
221 $autoRenewMembership = FALSE;
223 isset($ids['membership']) && $ids['membership']
225 $autoRenewMembership = TRUE;
231 //send recurring Notification email for user
232 CRM_Contribute_BAO_ContributionPage
::recurringNotify($subscriptionPaymentStatus,
234 $ids['contributionPage'],
248 protected function getIDs($billingid, $input, $module) {
249 $sql = "SELECT cr.id, cr.contact_id, co.id as coid
250 FROM civicrm_contribution_recur cr
251 INNER JOIN civicrm_contribution co ON co.contribution_recur_id = cr.id
252 WHERE cr.processor_id = '$billingid' LIMIT 1";
255 $result = CRM_Core_DAO
::executeQuery($sql);
257 $ids['contribution'] = $result->coid
;
258 $ids['contributionRecur'] = $result->id
;
259 $ids['contact'] = $result->contact_id
;
261 if (!$ids['contributionRecur']) {
262 CRM_Core_Error
::debug_log_message("Could not find billingid: ".$billingid);
263 echo "Failure: Could not find contributionRecur<p>\n";
267 // get page id based on contribution id
268 $ids['contributionPage'] = CRM_Core_DAO
::getFieldValue('CRM_Contribute_DAO_Contribution',
269 $ids['contribution'],
270 'contribution_page_id'
273 if ($module == 'event') {
274 // FIXME: figure out fields for event
277 // get the optional ids
279 // Get membershipId. Join with membership payment table for additional checks
282 FROM civicrm_membership as m
283 WHERE m.contribution_recur_id = '{$ids['contributionRecur']}'
285 if ($membershipId = CRM_Core_DAO
::singleValueQuery($sql)) {
287 $ids['membership'] = $membershipId;