* You should have received a copy of the GNU General Public License
* along with CiviCRM. If not, see <http://www.gnu.org/licenses/>.
*
- * Copyright (C) 2012
- * Licensed to CiviCRM under the GPL v3 or higher
- *
- * Modified by Lisa Marie Maginnis <lisa@fsf.org> (http://www.fsf.org)
+ * Copyright 2016, Lisa Marie Maginnis <lisa@fsf.org> (http://www.fsf.org)
*
*/
+/**
+ * CiviCRM (Instant Payment Notification) IPN processor module for
+ * TrustCommerece.
+ *
+ * For full documentation on the
+ * TrustCommerece API, please see the TCDevGuide for more information:
+ * https://vault.trustcommerce.com/downloads/TCDevGuide.htm
+ *
+ * This module supports the following features: Single credit/debit card
+ * transactions, AVS checking, recurring (create, update, and cancel
+ * subscription) optional blacklist with fail2ban,
+ *
+ * @copyright Lisa Marie Maginnis <lisa@fsf.org> (http://www.fsf.org)
+ * @version 1.0
+ * @package org.fsf.payment.trustcommerce.ipn
+ */
+
+define("MAX_FAILURES", 4);
+
class CRM_Core_Payment_trustcommerce_IPN extends CRM_Core_Payment_BaseIPN {
+
+ /**
+ * Inheret
+ *
+ * @return void
+ */
function __construct() {
parent::__construct();
}
+ function getLastFailures($recur_id) {
+ $sql=<<<EOF
+SELECT count(*) as numfails
+ FROM civicrm_contribution
+ WHERE contribution_recur_id = $recur_id
+ AND
+ id > (SELECT MAX(id) FROM civicrm_contribution WHERE contribution_recur_id = $recur_id AND contribution_status_id = 1);
+EOF;
+
+ $result = CRM_Core_DAO::executeQuery($sql);
+ if($result->fetch()) {
+ $failures = $result->numfails;
+ } else {
+ $failures = NULL;
+ }
+
+ return $failures;
+
+ }
function main($component = 'contribute') {
static $no = NULL;
$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<p>\n";
+ $msg = 'TrustCommerceIPN: Skipping duplicate contribution: for contact: '.$ids['contact'].' amount: $'.$input['amount'].' trxn_id: '.$input['trxn_id']."\n";
+ echo $msg;
+ CRM_Core_Error::debug_log_message($msg);
exit;
}
- var_dump($ids);
- var_dump($input);
if(array_key_exists('membership', $ids)) {
$membership = array();
$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'
return $this->processRecur($input, $ids, $objects, $first);
+ }
+
}
+ }
+
+ protected function disableAutorenew($recur_id) {
+ /* Load payment processor object */
+ // HARD CODED
+ $msg = 'TrustCommerceIPN: MAX_FAILURES hit, unstoring billing ID: '.$recur_id."\n";
+
+ CRM_Core_Error::debug_log_message($msg);
+ echo $msg;
+
+ $sql = "SELECT user_name, password, url_site FROM civicrm_payment_processor WHERE id = 8 LIMIT 1";
+
+ $result = CRM_Core_DAO::executeQuery($sql);
+ if($result->fetch()) {
+ $request = array(
+ 'custid' => $result->user_name,
+ 'password' => $result->password,
+ 'action' => 'unstore',
+ 'billingid' => $recur_id
+ );
+
+ $update = 'UPDATE civicrm_contribution_recur SET contribution_status_id = 3 WHERE processor_id = "'.$recur_id.'";';
+ $result1 = CRM_Core_DAO::executeQuery($update);
+
+ $tc = tclink_send($request);
+ if(!$tc) {
+ return -1;
+ }
+
+ return TRUE;
+
+ } else {
+ echo 'CRITICAL ERROR: Could not load payment processor object';
+ return;
+ }
+
+
}
-}
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';
$result = CRM_Core_DAO::executeQuery($sql);
- $result->fetch();
- $id = $result->id;
+ if($result->fetch()) {
+ $id = $result->id;
+ } else {
+ $id = NULL;
+ }
+
return $id;
}
protected function processRecur($input, $ids, $objects, $first) {
$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'];
- // since we have processor loaded for sure at this point,
+ // 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<p>';
+ echo '';
+ return TRUE;
+ }
$sendNotification = FALSE;
+
+ $recur->trxn_id = $input['trxn_id'];
+ $recur->total_amount = $input['amount'];
+ $recur->payment_instrument_id = 1;
+ $recur->fee = 0;
+ $recur->net_amount = $input['amount'];
+
if ($input['status'] == 1) {
// Approved
$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 = NULL;
- $recur->net_amount = NULL;
$recur->modified_date = $now;
$recur->contribution_status_id = array_search($statusName, $contributionStatus);
$recur->save();
+ $input['is_test'] = 0;
+ $msg = 'TrustCommerceIPN: Created contribution: for contact: '.$ids['contact'].' amount: $'.$input['amount'].' trxn_id: '.$input['trxn_id'].' status: Completed'."\n";
+ echo $msg;
+ CRM_Core_Error::debug_log_message($msg);
+
+ $this->completeTransaction($input, $ids, $objects, $transaction, $recur);
}
- else {
+ else if( $input['status'] == 4 ) {
// Declined
// failed status
-
- $recur->trxn_id = $input['trxn_id'];
- $recur->total_amount = $input['amount'];
- $recur->payment_instrument_id = 1;
- $recur->fee = NULL;
- $recur->net_amount = NULL;
-
-
+
$recur->contribution_status_id = array_search('Failed', $contributionStatus);
$recur->cancel_date = $now;
$recur->save();
-
- CRM_Core_Error::debug_log_message("Subscription payment failed");
-
- // the recurring contribution has declined a payment or has failed
- // so we just fix the recurring contribution and not change any of
- // the existing contribiutions
- // CRM-9036
- return TRUE;
-
- }
-
-
- // 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<p>';
- echo '';
- return TRUE;
+
+ $msg = 'TrustCommerceIPN: Created contribution: for contact: '.$ids['contact'].' amount: $'.$input['amount'].' trxn_id: '.$input['trxn_id'].' status: Failed'."\n";
+ echo $msg;
+ CRM_Core_Error::debug_log_message($msg);
+
+ /* Action for repeated failures */
+ if(MAX_FAILURES <= $this->getLastFailures($ids['contributionRecur'])) {
+ //$this->disableAutoRenew(($ids['contributionRecur']));
+ $this->disableAutorenew($ids['processor_id']);
+ }
+
+ return $this->failed($objects, $transaction);
}
- $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']
- ) {
+ if ($recur->id && isset($ids['membership']) && $ids['membership'] ) {
$autoRenewMembership = TRUE;
}
-
-
-
//send recurring Notification email for user
CRM_Contribute_BAO_ContributionPage::recurringNotify($subscriptionPaymentStatus,
$ids['contact'],
$recur,
$autoRenewMembership
);
-
-
-
-
}
-
-
-
}
protected function getIDs($billingid, $input, $module) {
$ids['contribution'] = $result->coid;
$ids['contributionRecur'] = $result->id;
$ids['contact'] = $result->contact_id;
+ $ids['processor_id'] = $billingid;
if (!$ids['contributionRecur']) {
CRM_Core_Error::debug_log_message("Could not find billingid: ".$billingid);