From 04e3198b0417b5f1bc8f3f06bfb6a10e3d1b6a97 Mon Sep 17 00:00:00 2001 From: "Matthew Wire (MJW Consulting)" <mjw@mjwconsult.co.uk> Date: Tue, 20 Nov 2018 12:48:34 +0000 Subject: [PATCH] Don't update existing contribution that is completed --- CRM/Core/Payment/Stripe.php | 5 ++-- CRM/Core/Payment/StripeIPN.php | 44 ++++++++++++++++------------------ 2 files changed, 23 insertions(+), 26 deletions(-) diff --git a/CRM/Core/Payment/Stripe.php b/CRM/Core/Payment/Stripe.php index 1315c137..6d58517a 100644 --- a/CRM/Core/Payment/Stripe.php +++ b/CRM/Core/Payment/Stripe.php @@ -869,8 +869,9 @@ class CRM_Core_Payment_Stripe extends CRM_Core_Payment { $data_raw = file_get_contents("php://input"); $data = json_decode($data_raw); $ipnClass = new CRM_Core_Payment_StripeIPN($data); - $ipnClass->main(); - http_response_code(200); + if ($ipnClass->main()) { + http_response_code(200); + } } diff --git a/CRM/Core/Payment/StripeIPN.php b/CRM/Core/Payment/StripeIPN.php index 91692096..06b43cdf 100644 --- a/CRM/Core/Payment/StripeIPN.php +++ b/CRM/Core/Payment/StripeIPN.php @@ -48,9 +48,7 @@ class CRM_Core_Payment_StripeIPN extends CRM_Core_Payment_BaseIPN { protected $amount = NULL; protected $fee = NULL; protected $net_amount = NULL; - protected $previous_contribution_id = NULL; - protected $previous_contribution_status_id = NULL; - protected $previous_contribution_total_amount = NULL; + protected $previous_contribution = []; /** * CRM_Core_Payment_StripeIPN constructor. @@ -235,10 +233,10 @@ class CRM_Core_Payment_StripeIPN extends CRM_Core_Payment_BaseIPN { // Successful recurring payment. case 'invoice.payment_succeeded': $this->setInfo(); - if ($this->previous_contribution_status_id == $pendingStatusId) { + if ($this->previous_contribution['contribution_status_id'] == $pendingStatusId) { $this->completeContribution(); } - else { + elseif ($this->previous_contribution['trxn_id'] != $this->charge_id) { // The first contribution was completed, so create a new one. // api contribution repeattransaction repeats the appropriate contribution if it is given // simply the recurring contribution id. It also updates the membership for us. @@ -259,17 +257,17 @@ class CRM_Core_Payment_StripeIPN extends CRM_Core_Payment_BaseIPN { 'failure_count' => 0, 'contribution_status_id' => 'In Progress' )); - return; + return TRUE; // Failed recurring payment. case 'invoice.payment_failed': $this->setInfo(); $failDate = date('YmdHis'); - if ($this->previous_contribution_status_id == $pendingStatusId) { + if ($this->previous_contribution['contribution_status_id'] == $pendingStatusId) { // If this contribution is Pending, set it to Failed. civicrm_api3('Contribution', 'create', array( - 'id' => $this->previous_contribution_id, + 'id' => $this->previous_contribution['id'], 'contribution_status_id' => "Failed", 'receive_date' => $failDate, 'is_email_receipt' => $this->is_email_receipt, @@ -299,7 +297,7 @@ class CRM_Core_Payment_StripeIPN extends CRM_Core_Payment_BaseIPN { 'failure_count' => $failureCount, 'modified_date' => $failDate, )); - return; + return TRUE; // Subscription is cancelled case 'customer.subscription.deleted': @@ -308,7 +306,7 @@ class CRM_Core_Payment_StripeIPN extends CRM_Core_Payment_BaseIPN { civicrm_api3('ContributionRecur', 'cancel', array( 'id' => $this->contribution_recur_id, )); - return; + return TRUE; // One-time donation and per invoice payment. case 'charge.failed': @@ -321,7 +319,7 @@ class CRM_Core_Payment_StripeIPN extends CRM_Core_Payment_BaseIPN { $note = $failureCode . ' : ' . $failureMessage; civicrm_api3('Contribution', 'create', ['id' => $contribution['id'], 'contribution_status_id' => $failedStatusId, 'note' => $note]); } - return; + return TRUE; case 'charge.refunded': $chargeId = $this->retrieve('charge_id', 'String'); @@ -346,20 +344,20 @@ class CRM_Core_Payment_StripeIPN extends CRM_Core_Payment_BaseIPN { } } } - return; + return TRUE; case 'charge.succeeded': $this->setInfo(); - if ($this->previous_contribution_status_id == $pendingStatusId) { + if ($this->previous_contribution['contribution_status_id'] == $pendingStatusId) { $this->completeContribution(); } - return; + return TRUE; case 'customer.subscription.updated': $this->setInfo(); if (empty($this->previous_plan_id)) { // Not a plan change...don't care. - return; + return TRUE; } civicrm_api3('ContributionRecur', 'create', [ @@ -372,14 +370,14 @@ class CRM_Core_Payment_StripeIPN extends CRM_Core_Payment_BaseIPN { ]); civicrm_api3('Contribution', 'create', [ - 'id' => $this->previous_contribution_id, + 'id' => $this->previous_contribution['id'], 'total_amount' => $this->plan_amount, 'contribution_recur_id' => $this->contribution_recur_id, ]); - return; + return TRUE; } // Unhandled event type. - return; + return TRUE; } /** @@ -390,14 +388,14 @@ class CRM_Core_Payment_StripeIPN extends CRM_Core_Payment_BaseIPN { public function completeContribution() { // Update the contribution to include the fee. civicrm_api3('Contribution', 'create', array( - 'id' => $this->previous_contribution_id, + 'id' => $this->previous_contribution['id'], 'total_amount' => $this->amount, 'fee_amount' => $this->fee, 'net_amount' => $this->net_amount, )); // The last one was not completed, so complete it. civicrm_api3('Contribution', 'completetransaction', array( - 'id' => $this->previous_contribution_id, + 'id' => $this->previous_contribution['id'], 'trxn_date' => $this->receive_date, 'trxn_id' => $this->charge_id, 'total_amount' => $this->amount, @@ -470,13 +468,11 @@ class CRM_Core_Payment_StripeIPN extends CRM_Core_Payment_BaseIPN { // Same approach as api repeattransaction. Find last contribution associated // with our recurring contribution. $contribution = civicrm_api3('contribution', 'getsingle', array( - 'return' => array('id', 'contribution_status_id', 'total_amount'), + 'return' => array('id', 'contribution_status_id', 'total_amount', 'trxn_id'), 'contribution_recur_id' => $this->contribution_recur_id, 'options' => array('limit' => 1, 'sort' => 'id DESC'), )); - $this->previous_contribution_id = $contribution['id']; - $this->previous_contribution_status_id = $contribution['contribution_status_id']; - $this->previous_contribution_total_amount = $contribution['total_amount']; + $this->previous_contribution = $contribution; } catch (Exception $e) { $this->exception('Cannot find recurring contribution for subscription ID: ' . $this->subscription_id . '. ' . $e->getMessage()); -- GitLab