diff --git a/CRM/Core/Payment/StripeIPN.php b/CRM/Core/Payment/StripeIPN.php index 850915dd61f1797979d6915721215343427bb9ba..ca9a6ae8e3de1c713bf78205da64f3ffa31d4c48 100644 --- a/CRM/Core/Payment/StripeIPN.php +++ b/CRM/Core/Payment/StripeIPN.php @@ -6,7 +6,7 @@ class CRM_Core_Payment_StripeIPN extends CRM_Core_Payment_BaseIPN { - protected $_paymentProcessor; + use CRM_Core_Payment_StripeIPNTrait; /** * Transaction ID is the contribution in the redirect flow and a random number in the on-site->POST flow @@ -77,20 +77,7 @@ class CRM_Core_Payment_StripeIPN extends CRM_Core_Payment_BaseIPN { // Determine the proper Stripe Processor ID so we can get the secret key // and initialize Stripe. - - // The $_GET['processor_id'] value is set by CRM_Core_Payment::handlePaymentMethod. - $paymentProcessorId = (int) CRM_Utils_Array::value('processor_id', $_GET); - if (empty($paymentProcessorId)) { - $this->exception('Cannot determine payment processor id'); - } - - // Get the Stripe secret key. - try { - $this->_paymentProcessor = \Civi\Payment\System::singleton()->getById($paymentProcessorId)->getPaymentProcessor(); - } - catch(Exception $e) { - $this->exception('Failed to get Stripe secret key'); - } + $this->getPaymentProcessor(); // Now re-retrieve the data from Stripe to ensure it's legit. \Stripe\Stripe::setApiKey($this->_paymentProcessor['user_name']); diff --git a/CRM/Core/Payment/StripeIPNTrait.php b/CRM/Core/Payment/StripeIPNTrait.php new file mode 100644 index 0000000000000000000000000000000000000000..86cef1b1c0016376a94c5910b51775ccc23b8841 --- /dev/null +++ b/CRM/Core/Payment/StripeIPNTrait.php @@ -0,0 +1,108 @@ +<?php +/** + * Shared payment IPN functions that should one day be migrated to CiviCRM core + * Version: 20190304 + */ + +trait CRM_Core_Payment_StripeIPNTrait { + + /** + * @var array Payment processor + */ + private $_paymentProcessor; + + /** + * Get the payment processor + * The $_GET['processor_id'] value is set by CRM_Core_Payment::handlePaymentMethod. + */ + protected function getPaymentProcessor() { + $paymentProcessorId = (int) CRM_Utils_Array::value('processor_id', $_GET); + if (empty($paymentProcessorId)) { + $this->exception('Failed to get payment processor id'); + } + + try { + $this->_paymentProcessor = \Civi\Payment\System::singleton()->getById($paymentProcessorId)->getPaymentProcessor(); + } + catch(Exception $e) { + $this->exception('Failed to get payment processor'); + } + } + + /** + * Mark a contribution as cancelled and update related entities + * + * @param array $params [ 'id' -> contribution_id, 'payment_processor_id' -> payment_processor_id] + * + * @return bool + * @throws \CiviCRM_API3_Exception + */ + protected function canceltransaction($params) { + return $this->incompletetransaction($params, 'cancel'); + } + + /** + * Mark a contribution as failed and update related entities + * + * @param array $params [ 'id' -> contribution_id, 'payment_processor_id' -> payment_processor_id] + * + * @return bool + * @throws \CiviCRM_API3_Exception + */ + protected function failtransaction($params) { + return $this->incompletetransaction($params, 'fail'); + } + + /** + * Handler for failtransaction and canceltransaction - do not call directly + * + * @param array $params + * @param string $mode + * + * @return bool + * @throws \CiviCRM_API3_Exception + */ + protected function incompletetransaction($params, $mode) { + $requiredParams = ['id', 'payment_processor_id']; + foreach ($requiredParams as $required) { + if (!isset($params[$required])) { + $this->exception('canceltransaction: Missing mandatory parameter: ' . $required); + } + } + + if (isset($params['payment_processor_id'])) { + $input['payment_processor_id'] = $params['payment_processor_id']; + } + $contribution = new CRM_Contribute_BAO_Contribution(); + $contribution->id = $params['id']; + if (!$contribution->find(TRUE)) { + throw new CiviCRM_API3_Exception('A valid contribution ID is required', 'invalid_data'); + } + + if (!$contribution->loadRelatedObjects($input, $ids, TRUE)) { + throw new CiviCRM_API3_Exception('failed to load related objects'); + } + + $input['trxn_id'] = !empty($params['trxn_id']) ? $params['trxn_id'] : $contribution->trxn_id; + if (!empty($params['fee_amount'])) { + $input['fee_amount'] = $params['fee_amount']; + } + + $objects['contribution'] = &$contribution; + $objects = array_merge($objects, $contribution->_relatedObjects); + + $transaction = new CRM_Core_Transaction(); + switch ($mode) { + case 'cancel': + return $this->cancelled($objects, $transaction); + + case 'fail': + return $this->failed($objects, $transaction); + + default: + throw new CiviCRM_API3_Exception('Unknown incomplete transaction type: ' . $mode); + } + + } + +}