Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add Payment PropertyBag for payment processor method arguments #15697

Merged
merged 2 commits into from
Dec 4, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
116 changes: 81 additions & 35 deletions CRM/Core/Payment.php
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@

use Civi\Payment\System;
use Civi\Payment\Exception\PaymentProcessorException;
use Civi\Payment\PropertyBag;

/**
* Class CRM_Core_Payment.
Expand Down Expand Up @@ -134,32 +135,41 @@ abstract class CRM_Core_Payment {
protected $backOffice = FALSE;

/**
* @return bool
*/
public function isBackOffice() {
return $this->backOffice;
}

/**
* Set back office property.
* This is only needed during the transitional phase. In future you should
* pass your own PropertyBag into the method you're calling.
*
* @param bool $isBackOffice
* New code should NOT use $this->propertyBag.
*
* @var Civi\Payment\PropertyBag
*/
public function setBackOffice($isBackOffice) {
$this->backOffice = $isBackOffice;
}
protected $propertyBag;

/**
* Get payment instrument id.
* Return the payment instrument ID to use.
*
* Note:
* We normally SHOULD be returning the payment instrument of the payment processor.
* However there is an outstanding case where this needs overriding, which is
* when using CRM_Core_Payment_Manual which uses the pseudoprocessor (id = 0).
*
* i.e. If you're writing a Payment Processor you should NOT be using
* setPaymentInstrumentID() at all.
*
* @todo
* Ideally this exception-to-the-rule should be handled outside of this class
* i.e. this class's getPaymentInstrumentID method should return it from the
* payment processor and CRM_Core_Payment_Manual could override it to provide 0.
*
* @return int
*/
public function getPaymentInstrumentID() {
return $this->paymentInstrumentID ? $this->paymentInstrumentID : $this->_paymentProcessor['payment_instrument_id'];
return isset($this->paymentInstrumentID)
? $this->paymentInstrumentID
: (int) ($this->_paymentProcessor['payment_instrument_id'] ?? 0);
}

/**
* Getter for the id.
* Getter for the id Payment Processor ID.
*
* @return int
*/
Expand All @@ -168,14 +178,33 @@ public function getID() {
}

/**
* Set payment Instrument id.
* @deprecated Set payment Instrument id - see note on getPaymentInstrumentID.
*
* By default we actually ignore the form value. The manual processor takes it more seriously.
* By default we actually ignore the form value. The manual processor takes
* it more seriously.
artfulrobot marked this conversation as resolved.
Show resolved Hide resolved
*
* @param int $paymentInstrumentID
*/
public function setPaymentInstrumentID($paymentInstrumentID) {
$this->paymentInstrumentID = $this->_paymentProcessor['payment_instrument_id'];
$this->paymentInstrumentID = (int) $paymentInstrumentID;
// See note on getPaymentInstrumentID().
return $this->getPaymentInstrumentID();
}

/**
* @return bool
*/
public function isBackOffice() {
return $this->backOffice;
}

/**
* Set back office property.
*
* @param bool $isBackOffice
*/
public function setBackOffice($isBackOffice) {
$this->backOffice = $isBackOffice;
}

/**
Expand Down Expand Up @@ -669,6 +698,8 @@ protected function getMandatoryFields() {
* Get the metadata of all the fields configured for this processor.
*
* @return array
*
* @throws \CiviCRM_API3_Exception
*/
protected function getAllFields() {
$paymentFields = array_intersect_key($this->getPaymentFormFieldsMetadata(), array_flip($this->getPaymentFormFields()));
Expand Down Expand Up @@ -1042,28 +1073,32 @@ protected function getBaseReturnUrl() {
}

/**
* Get the currency for the transaction.
* Get the currency for the transaction from the params.
*
* Legacy wrapper. Better for a method to work on its own PropertyBag.
*
* Handle any inconsistency about how it is passed in here.
* This code now uses PropertyBag to allow for old inputs like currencyID.
*
* @param $params
*
* @return string
*/
protected function getCurrency($params) {
return CRM_Utils_Array::value('currencyID', $params, CRM_Utils_Array::value('currency', $params));
protected function getCurrency($params = []) {
artfulrobot marked this conversation as resolved.
Show resolved Hide resolved
$localPropertyBag = new PropertyBag();
$localPropertyBag->mergeLegacyInputParams($params);
return $localPropertyBag->getCurrency();
}

/**
* Get the currency for the transaction.
* Legacy. Better for a method to work on its own PropertyBag,
* but also, this function does not do very much.
*
* Handle any inconsistency about how it is passed in here.
*
* @param $params
* @param array $params
*
* @return string
* @throws \CRM_Core_Exception
*/
protected function getAmount($params) {
protected function getAmount($params = []) {
return CRM_Utils_Money::format($params['amount'], NULL, NULL, TRUE);
}

Expand Down Expand Up @@ -1201,6 +1236,23 @@ protected function doDirectPayment(&$params) {
return $params;
}

/**
* Processors may need to inspect, validate, cast and copy data that is
* specific to this Payment Processor from the input array to custom fields
* on the PropertyBag.
*
* @param Civi\Payment\PropertyBag $propertyBag
* @param array $params
* @param string $component
*
* @throws \Civi\Payment\Exception\PaymentProcessorException
*/
public function extractCustomPropertiesForDoPayment(PropertyBag $propertyBag, array $params, $component = 'contribute') {
// example
// (validation and casting goes first)
// $propertyBag->setCustomProperty('myprocessor_customPropertyName', $value);
}

/**
* Process payment - this function wraps around both doTransferCheckout and doDirectPayment.
* Any processor that still implements the deprecated doTransferCheckout() or doDirectPayment() should be updated to use doPayment().
Expand Down Expand Up @@ -1611,7 +1663,7 @@ public function subscriptionURL($entityID = NULL, $entity = NULL, $action = 'can
*
* @return string
*/
protected function getPaymentDescription($params, $length = 24) {
protected function getPaymentDescription($params = [], $length = 24) {
$parts = [
'contactID',
'contributionID',
Expand All @@ -1620,13 +1672,7 @@ protected function getPaymentDescription($params, $length = 24) {
'billing_last_name',
];
$validParts = [];
if (isset($params['description'])) {
$uninformativeStrings = [
ts('Online Event Registration: '),
ts('Online Contribution: '),
];
$params['description'] = str_replace($uninformativeStrings, '', $params['description']);
}
$params['description'] = $this->getDescription();
foreach ($parts as $part) {
if ((!empty($params[$part]))) {
$validParts[] = $params[$part];
Expand Down
4 changes: 3 additions & 1 deletion CRM/Core/Payment/Form.php
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,9 @@ public static function setPaymentFieldsByProcessor(&$form, $processor, $billing_

$processor['object']->setBillingProfile($billing_profile_id);
$processor['object']->setBackOffice($isBackOffice);
$processor['object']->setPaymentInstrumentID($paymentInstrumentID);
if (isset($paymentInstrumentID)) {
$processor['object']->setPaymentInstrumentID($paymentInstrumentID);
}
$paymentTypeName = self::getPaymentTypeName($processor);
$form->assign('paymentTypeName', $paymentTypeName);
$form->assign('paymentTypeLabel', self::getPaymentLabel($processor['object']));
Expand Down
Loading