. * * Copyright (C) 2012 * Licensed to CiviCRM under the GPL v3 or higher * * Modified by Lisa Marie Maginnis (http://www.fsf.org) * */ class CRM_Core_Payment_trustcommerce_IPN extends CRM_Core_Payment_BaseIPN { function __construct() { parent::__construct(); } function main($component = 'contribute') { static $no = NULL; $billingid = CRM_Utils_Request::retrieve('billingid', 'String', $no, FALSE, 'GET'); $input['status'] = CRM_Utils_Request::retrieve('status', 'String', $no, FALSE, 'GET'); $input['amount'] = CRM_Utils_Request::retrieve('amount', 'String', $no, FALSE, 'GET'); $input['date'] = CRM_Utils_Request::retrieve('date', 'String', $no, FALSE, 'GET'); $input['trxn_id'] = CRM_Utils_Request::retrieve('trxn_id', 'String', $no, FALSE, 'GET'); $checksum = CRM_Utils_Request::retrieve('checksum', 'String', $no, FALSE, 'GET'); if ($billingid) { if( $input['status'] == '' || $input['amount'] == '' || $input['date'] == '' || $input['trxn_id'] == '' || md5($billingid.$input['trxn_id'].$input['amount'].$input['date']) != $checksum) { CRM_Core_Error::debug_log_message("Error: IPN called with out proper fields"); echo "Error: invalid paramaters

\n"; exit; } $ids = $objects = array(); $input['component'] = $component; // load post ids in $ids $ids = NULL; $ids = $this->getIDs($billingid, $input, $input['component']); $ids['trxn_id'] = $input['trxn_id']; if($this->checkDuplicate($input, $ids) != NULL) { CRM_Core_Error::debug_log_message("Success: This payment has already been processed."); echo "Success: This payment has already been processed

\n"; exit; } var_dump($ids); var_dump($input); if(array_key_exists('membership', $ids)) { $membership = array(); $params = array('id' => $ids['membership']); $obj = CRM_Member_BAO_Membership::retrieve($params, $membership); $objects['membership'] = array(&$obj); } var_dump($ids); var_dump($input); $paymentProcessorID = CRM_Core_DAO::getFieldValue('CRM_Financial_DAO_PaymentProcessorType', 'TrustCommerce', 'id', 'name' ); if (!$this->validateData($input, $ids, $objects, TRUE, $paymentProcessorID)) { return FALSE; } // var_dump($objects); if ($component == 'contribute' && $ids['contributionRecur']) { // check if first contribution is completed, else complete first contribution $first = TRUE; if ($objects['contribution']->contribution_status_id == 1) { $first = FALSE; } return $this->processRecur($input, $ids, $objects, $first); } } } protected function checkDuplicate($input, $ids) { // $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'; $sql="select id from civicrm_contribution where trxn_id = '".$ids['trxn_id']."'"; $result = CRM_Core_DAO::executeQuery($sql); $result->fetch(); $id = $result->id; return $id; } protected function processRecur($input, $ids, $objects, $first) { $recur = &$objects['contributionRecur']; $contributionStatus = CRM_Contribute_PseudoConstant::contributionStatus(NULL, 'name'); $transaction = new CRM_Core_Transaction(); $now = date('YmdHis'); // fix dates that already exist $dates = array('create_date', 'start_date', 'end_date', 'cancel_date', 'modified_date'); foreach ($dates as $name) { if ($recur->$name) { $recur->$name = CRM_Utils_Date::isoToMysql($recur->$name); } } if (!$first) { // create a contribution and then get it processed $contribution = new CRM_Contribute_BAO_Contribution(); $contribution->contact_id = $ids['contact']; $contribution->financial_type_id = $objects['contributionType']->id; $contribution->contribution_page_id = $ids['contributionPage']; $contribution->contribution_recur_id = $ids['contributionRecur']; $contribution->receive_date = $input['date']; $contribution->currency = $objects['contribution']->currency; $contribution->payment_instrument_id = 1; $contribution->amount_level = $objects['contribution']->amount_level; $contribution->address_id = $objects['contribution']->address_id; $contribution->honor_contact_id = $objects['contribution']->honor_contact_id; $contribution->honor_type_id = $objects['contribution']->honor_type_id; $contribution->campaign_id = $objects['contribution']->campaign_id; $contribution->total_amount = $input['amount']; $objects['contribution'] = &$contribution; } $objects['contribution']->invoice_id = md5(uniqid(rand(), TRUE)); // $objects['contribution']->total_amount = $objects['contribution']->total_amount; $objects['contribution']->trxn_id = $input['trxn_id']; // check if contribution is already completed, if so we ignore this ipn if ($objects['contribution']->contribution_status_id == 1) { $transaction->commit(); CRM_Core_Error::debug_log_message("returning since contribution has already been handled"); echo 'Success: Contribution has already been handled

'; echo ''; return TRUE; } $sendNotification = FALSE; if ($input['status'] == 1) { // Approved if ($first) { $recur->start_date = $now; $sendNotification = TRUE; $subscriptionPaymentStatus = CRM_Core_Payment::RECURRING_PAYMENT_START; } $statusName = 'In Progress'; if (($recur->installments > 0) && ($input['subscription_paynum'] >= $recur->installments) ) { // this is the last payment $statusName = 'Completed'; $recur->end_date = $now; $sendNotification = TRUE; $subscriptionPaymentStatus = CRM_Core_Payment::RECURRING_PAYMENT_END; } $recur->trxn_id = $input['trxn_id']; $recur->total_amount = $input['amount']; $recur->payment_instrument_id = 1; $recur->fee = 0; $recur->net_amount = $input['amount']; $recur->modified_date = $now; $recur->contribution_status_id = array_search($statusName, $contributionStatus); $recur->save(); } else { // Declined // failed status $recur->trxn_id = $input['trxn_id']; $recur->total_amount = $input['amount']; $recur->payment_instrument_id = 1; $recur->fee = 0; $recur->net_amount = $input['amount']; $recur->contribution_status_id = array_search('Failed', $contributionStatus); $recur->cancel_date = $now; $recur->save(); CRM_Core_Error::debug_log_message("Subscription payment failed"); $input['skipComponentSync'] = TRUE; $this->failed($objects, $transaction, $input); } $input['is_test'] = 0; $this->completeTransaction($input, $ids, $objects, $transaction, $recur); echo 'Success: Created new contribution: '.$ids['contribution'].' for cid: '.$ids['contact'].'\n'; CRM_Core_Error::debug_log_message('Success: Created new contribution: '.$ids['contribution'].' for cid: '.$ids['contact']); if ($sendNotification) { $autoRenewMembership = FALSE; if ($recur->id && isset($ids['membership']) && $ids['membership'] ) { $autoRenewMembership = TRUE; } //send recurring Notification email for user CRM_Contribute_BAO_ContributionPage::recurringNotify($subscriptionPaymentStatus, $ids['contact'], $ids['contributionPage'], $recur, $autoRenewMembership ); } } protected function getIDs($billingid, $input, $module) { $sql = "SELECT cr.id, cr.contact_id, co.id as coid FROM civicrm_contribution_recur cr INNER JOIN civicrm_contribution co ON co.contribution_recur_id = cr.id WHERE cr.processor_id = '$billingid' LIMIT 1"; $result = CRM_Core_DAO::executeQuery($sql); $result->fetch(); $ids['contribution'] = $result->coid; $ids['contributionRecur'] = $result->id; $ids['contact'] = $result->contact_id; if (!$ids['contributionRecur']) { CRM_Core_Error::debug_log_message("Could not find billingid: ".$billingid); echo "Failure: Could not find contributionRecur

\n"; exit(); } // get page id based on contribution id $ids['contributionPage'] = CRM_Core_DAO::getFieldValue('CRM_Contribute_DAO_Contribution', $ids['contribution'], 'contribution_page_id' ); if ($module == 'event') { // FIXME: figure out fields for event } else { // get the optional ids // Get membershipId. Join with membership payment table for additional checks $sql = " SELECT m.id FROM civicrm_membership as m WHERE m.contribution_recur_id = '{$ids['contributionRecur']}' LIMIT 1"; if ($membershipId = CRM_Core_DAO::singleValueQuery($sql)) { $ids['membership'] = $membershipId; } } return $ids; } }