From: eileen Date: Tue, 11 Apr 2017 14:43:08 +0000 (+1200) Subject: CRM-20413 fix to setting wrong payment_instrument_id, by passing responsibility to... X-Git-Url: https://vcs.fsf.org/?a=commitdiff_plain;h=181354227024fe6825aec038f891a66057d26c9b;p=civicrm-core.git CRM-20413 fix to setting wrong payment_instrument_id, by passing responsibility to the processor. This also reflects work towards allowing payment_instrument specific fields on the payment form - ie. check, credit_card_type, pan_truncation. This idea is to finish the code allowing pay-later to be the manual payment processor indexed with a 0 on all payment forms, and have the form render with appropriate fields. Note that I got this working on multiple forms, this commit reflects the smallest piece I could break off that is complete within itself, and resolves an issue I tested that it was still possible to enter checks on the offline contribution as well as membership & additional payment forms, and the check number still shows up. I also tested front end contribution credit card & pay later & front end event forms --- diff --git a/CRM/Contribute/BAO/Contribution.php b/CRM/Contribute/BAO/Contribution.php index aee8f8beba..0f5e0c674b 100644 --- a/CRM/Contribute/BAO/Contribution.php +++ b/CRM/Contribute/BAO/Contribution.php @@ -2330,7 +2330,7 @@ INNER JOIN civicrm_activity ON civicrm_activity_contact.activity_id = civicrm_ac $ids )); - if (!$paymentProcessorID && $this->contribution_page_id) { + if (!isset($input['payment_processor_id']) && !$paymentProcessorID && $this->contribution_page_id) { $paymentProcessorID = CRM_Core_DAO::getFieldValue('CRM_Contribute_DAO_ContributionPage', $this->contribution_page_id, 'payment_processor' diff --git a/CRM/Contribute/Form/AbstractEditPayment.php b/CRM/Contribute/Form/AbstractEditPayment.php index 3e466db5e7..fcf663822e 100644 --- a/CRM/Contribute/Form/AbstractEditPayment.php +++ b/CRM/Contribute/Form/AbstractEditPayment.php @@ -187,13 +187,20 @@ class CRM_Contribute_Form_AbstractEditPayment extends CRM_Contact_Form_Task { /** * Is this a backoffice form - * (this will affect whether paypal express code is displayed) + * * @var bool */ public $isBackOffice = TRUE; protected $_formType; + /** + * Payment instrument id for the transaction. + * + * @var int + */ + public $paymentInstrumentID; + /** * Array of fields to display on billingBlock.tpl - this is not fully implemented but basically intent is the panes/fieldsets on this page should * be all in this array in order like @@ -307,7 +314,6 @@ WHERE contribution_id = {$id} * @throws Exception */ public function getValidProcessors() { - $defaultID = NULL; $capabilities = array('BackOffice'); if ($this->_mode) { $capabilities[] = (ucfirst($this->_mode) . 'Mode'); @@ -323,36 +329,37 @@ WHERE contribution_id = {$id} public function assignProcessors() { //ensure that processor has a valid config //only valid processors get display to user - - if ($this->_mode) { - $this->assign('processorSupportsFutureStartDate', CRM_Financial_BAO_PaymentProcessor::hasPaymentProcessorSupporting(array('FutureRecurStartDate'))); - $this->_paymentProcessors = $this->getValidProcessors(); - if (!isset($this->_paymentProcessor['id'])) { - // if the payment processor isn't set yet (as indicated by the presence of an id,) we'll grab the first one which should be the default - $this->_paymentProcessor = reset($this->_paymentProcessors); - } - if (empty($this->_paymentProcessors)) { - throw new CRM_Core_Exception(ts('You will need to configure the %1 settings for your Payment Processor before you can submit a credit card transactions.', array(1 => $this->_mode))); - } - $this->_processors = array(); - foreach ($this->_paymentProcessors as $id => $processor) { - // @todo review this. The inclusion of this IF was to address test processors being incorrectly loaded. - // However the function $this->getValidProcessors() is expected to only return the processors relevant - // to the mode (using the actual id - ie. the id of the test processor for the test processor). - // for some reason there was a need to filter here per commit history - but this indicates a problem - // somewhere else. - if ($processor['is_test'] == ($this->_mode == 'test')) { - $this->_processors[$id] = ts($processor['name']); - if (!empty($processor['description'])) { - $this->_processors[$id] .= ' : ' . ts($processor['description']); - } - if ($processor['is_recur']) { - $this->_recurPaymentProcessors[$id] = $this->_processors[$id]; - } + $this->assign('processorSupportsFutureStartDate', CRM_Financial_BAO_PaymentProcessor::hasPaymentProcessorSupporting(array('FutureRecurStartDate'))); + $this->_paymentProcessors = $this->getValidProcessors(); + if (!isset($this->_paymentProcessor['id'])) { + // if the payment processor isn't set yet (as indicated by the presence of an id,) we'll grab the first one which should be the default + $this->_paymentProcessor = reset($this->_paymentProcessors); + } + if (!$this->_mode) { + $this->_paymentProcessor = $this->_paymentProcessors[0]; + } + elseif (empty($this->_paymentProcessors) || array_keys($this->_paymentProcessors) === array(0)) { + throw new CRM_Core_Exception(ts('You will need to configure the %1 settings for your Payment Processor before you can submit a credit card transactions.', array(1 => $this->_mode))); + } + $this->_processors = array(); + foreach ($this->_paymentProcessors as $id => $processor) { + // @todo review this. The inclusion of this IF was to address test processors being incorrectly loaded. + // However the function $this->getValidProcessors() is expected to only return the processors relevant + // to the mode (using the actual id - ie. the id of the test processor for the test processor). + // for some reason there was a need to filter here per commit history - but this indicates a problem + // somewhere else. + if ($processor['is_test'] == ($this->_mode == 'test')) { + $this->_processors[$id] = ts($processor['name']); + if (!empty($processor['description'])) { + $this->_processors[$id] .= ' : ' . ts($processor['description']); + } + if ($processor['is_recur']) { + $this->_recurPaymentProcessors[$id] = $this->_processors[$id]; } } - CRM_Financial_Form_Payment::addCreditCardJs($id); } + CRM_Financial_Form_Payment::addCreditCardJs($id); + $this->assign('recurringPaymentProcessorIds', empty($this->_recurPaymentProcessors) ? '' : implode(',', array_keys($this->_recurPaymentProcessors)) ); @@ -531,13 +538,9 @@ WHERE contribution_id = {$id} list($this->userDisplayName, $this->userEmail) = CRM_Contact_BAO_Contact_Location::getEmailDetails($this->_contactID); $this->assign('displayName', $this->userDisplayName); } - if ($this->_mode) { - $this->assignProcessors(); - - $this->assignBillingType(); - - CRM_Core_Payment_Form::setPaymentFieldsByProcessor($this, $this->_paymentProcessor, FALSE, TRUE); - } + $this->assignProcessors(); + $this->assignBillingType(); + CRM_Core_Payment_Form::setPaymentFieldsByProcessor($this, $this->_paymentProcessor, FALSE, TRUE, CRM_Utils_Request::retrieve('payment_instrument_id', 'Integer')); } catch (CRM_Core_Exception $e) { CRM_Core_Error::fatal($e->getMessage()); diff --git a/CRM/Contribute/Form/AdditionalPayment.php b/CRM/Contribute/Form/AdditionalPayment.php index 28321f2c40..8540925c5e 100644 --- a/CRM/Contribute/Form/AdditionalPayment.php +++ b/CRM/Contribute/Form/AdditionalPayment.php @@ -209,7 +209,7 @@ class CRM_Contribute_Form_AdditionalPayment extends CRM_Contribute_Form_Abstract return; } - CRM_Core_Payment_Form::buildPaymentForm($this, $this->_paymentProcessor, FALSE, TRUE); + CRM_Core_Payment_Form::buildPaymentForm($this, $this->_paymentProcessor, FALSE, TRUE, CRM_Utils_Request::retrieve('payment_instrument_id', 'Integer')); $attributes = CRM_Core_DAO::getAttribute('CRM_Financial_DAO_FinancialTrxn'); $this->add('select', 'payment_processor_id', ts('Payment Processor'), $this->_processors, NULL); diff --git a/CRM/Contribute/Form/Contribution/Confirm.php b/CRM/Contribute/Form/Contribution/Confirm.php index 85574cca95..55844c1b68 100644 --- a/CRM/Contribute/Form/Contribution/Confirm.php +++ b/CRM/Contribute/Form/Contribution/Confirm.php @@ -943,6 +943,7 @@ class CRM_Contribute_Form_Contribution_Confirm extends CRM_Contribute_Form_Contr $params['is_email_receipt'] = $isEmailReceipt; } $params['is_recur'] = $isRecur; + $params['payment_instrument_id'] = $contributionParams['payment_instrument_id']; $recurringContributionID = self::processRecurringContribution($form, $params, $contactID, $financialType); $nonDeductibleAmount = self::getNonDeductibleAmount($params, $financialType, $online, $form); @@ -1668,8 +1669,9 @@ class CRM_Contribute_Form_Contribution_Confirm extends CRM_Contribute_Form_Contr // also it reset any payment processor selection result into pending free membership // so its a kind of hack to complete free membership at this point since there is no $form->_paymentProcessor info if (!empty($membershipContribution) && !is_a($membershipContribution, 'CRM_Core_Error')) { - $paymentProcessorIDs = explode(CRM_Core_DAO::VALUE_SEPARATOR, CRM_Utils_Array::value('payment_processor', $this->_values)); - if (empty($form->_paymentProcessor) && !empty($paymentProcessorIDs)) { + if (empty($form->_paymentProcessor)) { + // @todo this can maybe go now we are setting payment_processor_id = 0 more reliably. + $paymentProcessorIDs = explode(CRM_Core_DAO::VALUE_SEPARATOR, CRM_Utils_Array::value('payment_processor', $this->_values)); $this->_paymentProcessor['id'] = $paymentProcessorIDs[0]; } $result = array('payment_status_id' => 1, 'contribution' => $membershipContribution); @@ -1943,10 +1945,14 @@ class CRM_Contribute_Form_Contribution_Confirm extends CRM_Contribute_Form_Contr $form->_values['fee'] = $priceSetFields['fields']; $form->_priceSetId = $priceSetID; $form->setFormAmountFields($priceSetID); + $capabilities = array(); + if ($form->_mode) { + $capabilities[] = (ucfirst($form->_mode) . 'Mode'); + } + $form->_paymentProcessors = CRM_Financial_BAO_PaymentProcessor::getPaymentProcessors($capabilities); + $form->_params['payment_processor_id'] = !empty($params['payment_processor_id']) ? $params['payment_processor_id'] : 0; + $form->_paymentProcessor = $form->_paymentProcessors[$form->_params['payment_processor_id']]; if (!empty($params['payment_processor_id'])) { - $form->_paymentProcessor = civicrm_api3('payment_processor', 'getsingle', array( - 'id' => $params['payment_processor_id'], - )); // The concept of contributeMode is deprecated as is the billing_mode concept. if ($form->_paymentProcessor['billing_mode'] == 1) { $form->_contributeMode = 'direct'; @@ -1955,9 +1961,6 @@ class CRM_Contribute_Form_Contribution_Confirm extends CRM_Contribute_Form_Contr $form->_contributeMode = 'notify'; } } - else { - $form->_params['payment_processor_id'] = 0; - } $priceFields = $priceFields[$priceSetID]['fields']; CRM_Price_BAO_PriceSet::processAmount($priceFields, $paramsProcessedForForm, $lineItems, 'civicrm_contribution'); diff --git a/CRM/Contribute/Form/ContributionBase.php b/CRM/Contribute/Form/ContributionBase.php index 80644b8063..7655c6a310 100644 --- a/CRM/Contribute/Form/ContributionBase.php +++ b/CRM/Contribute/Form/ContributionBase.php @@ -187,6 +187,23 @@ class CRM_Contribute_Form_ContributionBase extends CRM_Core_Form { */ public $_isBillingAddressRequiredForPayLater; + /** + * Is this a backoffice form + * (this will affect whether paypal express code is displayed) + * @var bool + */ + public $isBackOffice = FALSE; + + /** + * Payment instrument if for the transaction. + * + * This will generally be drawn from the payment processor and is ignored for + * front end forms. + * + * @var int + */ + public $paymentInstrumentID; + /** * Set variables up before form is built. * diff --git a/CRM/Core/Payment.php b/CRM/Core/Payment.php index 7d08cbd2b0..3138d1f95b 100644 --- a/CRM/Core/Payment.php +++ b/CRM/Core/Payment.php @@ -119,6 +119,58 @@ abstract class CRM_Core_Payment { */ protected $billingProfile; + /** + * Payment instrument ID. + * + * This is normally retrieved from the payment_processor table. + * + * @var int + */ + protected $paymentInstrumentID; + + /** + * Is this a back office transaction. + * + * @var bool + */ + protected $backOffice = FALSE; + + /** + * @return bool + */ + public function isBackOffice() { + return $this->backOffice; + } + + /** + * Set back office property. + * + * @param bool $isBackOffice + */ + public function setBackOffice($isBackOffice) { + $this->backOffice = $isBackOffice; + } + + /** + * Get payment instrument id. + * + * @return int + */ + public function getPaymentInstrumentID() { + return $this->paymentInstrumentID ? $this->paymentInstrumentID : $this->_paymentProcessor['payment_instrument_id']; + } + + /** + * Set payment Instrument id. + * + * By default we actually ignore the form value. The manual processor takes it more seriously. + * + * @param int $paymentInstrumentID + */ + public function setPaymentInstrumentID($paymentInstrumentID) { + $this->paymentInstrumentID = $this->_paymentProcessor['payment_instrument_id']; + } + /** * Set base return path (offsite processors). * diff --git a/CRM/Core/Payment/Form.php b/CRM/Core/Payment/Form.php index d4ee8c09d7..eadec63d93 100644 --- a/CRM/Core/Payment/Form.php +++ b/CRM/Core/Payment/Form.php @@ -52,8 +52,10 @@ class CRM_Core_Payment_Form { * Display billing fields even for pay later. * @param bool $isBackOffice * Is this a back office function? If so the option to suppress the cvn needs to be evaluated. + * @param int $paymentInstrumentID + * ID of the payment processor. */ - static public function setPaymentFieldsByProcessor(&$form, $processor, $billing_profile_id = NULL, $isBackOffice = FALSE) { + static public function setPaymentFieldsByProcessor(&$form, $processor, $billing_profile_id = NULL, $isBackOffice = FALSE, $paymentInstrumentID = NULL) { $form->billingFieldSets = array(); // Load the pay-later processor // @todo load this right up where the other processors are loaded initially. @@ -62,10 +64,13 @@ class CRM_Core_Payment_Form { } $processor['object']->setBillingProfile($billing_profile_id); + $processor['object']->setBackOffice($isBackOffice); + $processor['object']->setPaymentInstrumentID($paymentInstrumentID); $paymentTypeName = self::getPaymentTypeName($processor); $paymentTypeLabel = self::getPaymentTypeLabel($processor); $form->assign('paymentTypeName', $paymentTypeName); $form->assign('paymentTypeLabel', $paymentTypeLabel); + $form->assign('isBackOffice', $isBackOffice); $form->_paymentFields = $form->billingFieldSets[$paymentTypeName]['fields'] = self::getPaymentFieldMetadata($processor); $form->_paymentFields = array_merge($form->_paymentFields, self::getBillingAddressMetadata($processor, $form->_bltID)); $form->assign('paymentFields', self::getPaymentFields($processor)); @@ -111,6 +116,7 @@ class CRM_Core_Payment_Form { protected static function addCommonFields(&$form, $paymentFields) { $requiredPaymentFields = array(); foreach ($paymentFields as $name => $field) { + // @todo - remove the cc_field check - no longer useful. if (!empty($field['cc_field'])) { if ($field['htmlType'] == 'chainSelect') { $form->addChainSelect($field['name'], array('required' => FALSE)); @@ -142,8 +148,7 @@ class CRM_Core_Payment_Form { * @return array */ public static function getPaymentFields($paymentProcessor) { - $paymentProcessorObject = Civi\Payment\System::singleton()->getByProcessor($paymentProcessor); - return $paymentProcessorObject->getPaymentFormFields(); + return $paymentProcessor['object']->getPaymentFormFields(); } /** @@ -152,8 +157,7 @@ class CRM_Core_Payment_Form { * @return array */ public static function getPaymentFieldMetadata($paymentProcessor) { - $paymentProcessorObject = Civi\Payment\System::singleton()->getByProcessor($paymentProcessor); - return array_intersect_key($paymentProcessorObject->getPaymentFormFieldsMetadata(), array_flip(self::getPaymentFields($paymentProcessor))); + return array_intersect_key($paymentProcessor['object']->getPaymentFormFieldsMetadata(), array_flip(self::getPaymentFields($paymentProcessor))); } /** @@ -220,10 +224,12 @@ class CRM_Core_Payment_Form { * although the distinction is losing it's meaning as front end forms are used for back office and a permission * for the 'enter without cvn' is probably more appropriate. Paypal std does not support another user * entering details but once again the issue is not back office but 'another user'. + * @param int $paymentInstrumentID + * Payment instrument ID. * * @return bool */ - public static function buildPaymentForm(&$form, $processor, $billing_profile_id, $isBackOffice) { + public static function buildPaymentForm(&$form, $processor, $billing_profile_id, $isBackOffice, $paymentInstrumentID = NULL) { //if the form has address fields assign to the template so the js can decide what billing fields to show $profileAddressFields = $form->get('profileAddressFields'); if (!empty($profileAddressFields)) { @@ -234,7 +240,7 @@ class CRM_Core_Payment_Form { return NULL; } - self::setPaymentFieldsByProcessor($form, $processor, $billing_profile_id, $isBackOffice); + self::setPaymentFieldsByProcessor($form, $processor, $billing_profile_id, $isBackOffice, $paymentInstrumentID); self::addCommonFields($form, $form->_paymentFields); self::addRules($form, $form->_paymentFields); return (!empty($form->_paymentFields)); diff --git a/CRM/Core/Payment/Manual.php b/CRM/Core/Payment/Manual.php index b2d12dd7d2..55bae03df2 100644 --- a/CRM/Core/Payment/Manual.php +++ b/CRM/Core/Payment/Manual.php @@ -137,6 +137,15 @@ class CRM_Core_Payment_Manual extends CRM_Core_Payment { $this->result = $result; } + /** + * Set payment instrument id. + * + * @param int $paymentInstrumentID + */ + public function setPaymentInstrumentID($paymentInstrumentID) { + $this->paymentInstrumentID = $paymentInstrumentID; + } + /** * Get the name of the payment type. * @@ -173,6 +182,15 @@ class CRM_Core_Payment_Manual extends CRM_Core_Payment { return TRUE; } + /** + * Are back office payments supported. + * + * @return bool + */ + protected function supportsBackOffice() { + return TRUE; + } + /** * Submit a manual payment. * diff --git a/CRM/Core/Payment/PayPalImpl.php b/CRM/Core/Payment/PayPalImpl.php index 7e34d17283..427477386e 100644 --- a/CRM/Core/Payment/PayPalImpl.php +++ b/CRM/Core/Payment/PayPalImpl.php @@ -137,6 +137,7 @@ class CRM_Core_Payment_PayPalImpl extends CRM_Core_Payment { * @param CRM_Core_Form $form */ protected function addPaypalExpressCode(&$form) { + // @todo use $this->isBackOffice() instead, test. if (empty($form->isBackOffice)) { $form->_expressButtonName = $form->getButtonName('upload', 'express'); $form->assign('expressButtonName', $form->_expressButtonName); diff --git a/CRM/Core/Payment/ProcessorForm.php b/CRM/Core/Payment/ProcessorForm.php index 6b875773a8..1cab78655c 100644 --- a/CRM/Core/Payment/ProcessorForm.php +++ b/CRM/Core/Payment/ProcessorForm.php @@ -54,6 +54,7 @@ class CRM_Core_Payment_ProcessorForm { } if ($form->_type) { + // @todo not sure when this would be true. Never passed in. $form->_paymentProcessor = CRM_Financial_BAO_PaymentProcessor::getPayment($form->_type, $form->_mode); } @@ -63,6 +64,11 @@ class CRM_Core_Payment_ProcessorForm { } $form->set('paymentProcessor', $form->_paymentProcessor); $form->_paymentObject = System::singleton()->getByProcessor($form->_paymentProcessor); + if ($form->paymentInstrumentID) { + $form->_paymentObject->setPaymentInstrumentID($form->paymentInstrumentID); + } + $form->_paymentObject->setBackOffice($form->isBackOffice); + $form->assign('isBackOffice', $form->isBackOffice); $form->assign('suppressSubmitButton', $form->_paymentObject->isSuppressSubmitButtons()); @@ -92,7 +98,9 @@ class CRM_Core_Payment_ProcessorForm { CRM_Core_Payment_Form::setPaymentFieldsByProcessor( $form, $form->_paymentProcessor, - CRM_Utils_Request::retrieve('billing_profile_id', 'String') + CRM_Utils_Request::retrieve('billing_profile_id', 'String'), + $form->isBackOffice, + $form->paymentInstrumentID ); $form->assign_by_ref('paymentProcessor', $form->_paymentProcessor); @@ -131,7 +139,7 @@ class CRM_Core_Payment_ProcessorForm { * * @param CRM_Core_Form $form */ - public static function buildQuickform(&$form) { + public static function buildQuickForm(&$form) { //@todo document why this addHidden is here //CRM-15743 - we should not set/create hidden element for pay later // because payment processor is not selected @@ -143,7 +151,7 @@ class CRM_Core_Payment_ProcessorForm { if (!empty($processorId)) { $form->addElement('hidden', 'hidden_processor', 1); } - CRM_Core_Payment_Form::buildPaymentForm($form, $form->_paymentProcessor, $billing_profile_id, FALSE); + CRM_Core_Payment_Form::buildPaymentForm($form, $form->_paymentProcessor, $billing_profile_id, $form->isBackOffice, $form->paymentInstrumentID); } } diff --git a/CRM/Event/Form/Registration.php b/CRM/Event/Form/Registration.php index cf567cc3da..05e9060412 100644 --- a/CRM/Event/Form/Registration.php +++ b/CRM/Event/Form/Registration.php @@ -167,8 +167,30 @@ class CRM_Event_Form_Registration extends CRM_Core_Form { public $_forcePayement; + /** + * @deprecated + * + * @var + */ public $_isBillingAddressRequiredForPayLater; + /** + * Is this a back office form + * + * @var bool + */ + public $isBackOffice = FALSE; + + /** + * Payment instrument iD for the transaction. + * + * This will generally be drawn from the payment processor and is ignored for + * front end forms. + * + * @var int + */ + public $paymentInstrumentID; + /** * Set variables up before form is built. */ diff --git a/CRM/Financial/BAO/PaymentProcessor.php b/CRM/Financial/BAO/PaymentProcessor.php index 37b6f2f678..a3b89b4caa 100644 --- a/CRM/Financial/BAO/PaymentProcessor.php +++ b/CRM/Financial/BAO/PaymentProcessor.php @@ -346,11 +346,11 @@ class CRM_Financial_BAO_PaymentProcessor extends CRM_Financial_DAO_PaymentProces 'name' => 'pay_later', 'billing_mode' => '', 'is_default' => 0, - // This should ideally be retrieved from the DB but existing default is check so we'll code that for now. - 'payment_instrument_id' => CRM_Core_OptionGroup::getValue('payment_instrument', 'Check', 'name'), + 'payment_instrument_id' => key(CRM_Core_OptionGroup::values('payment_instrument', FALSE, FALSE, FALSE, 'AND is_default = 1')), // Making this optionally recur would give lots of options -but it should // be a row in the payment processor table before we do that. 'is_recur' => FALSE, + 'is_test' => FALSE, ); CRM_Utils_Cache::singleton()->set($cacheKey, $processors['values']); @@ -376,7 +376,6 @@ class CRM_Financial_BAO_PaymentProcessor extends CRM_Financial_DAO_PaymentProces * available processors */ public static function getPaymentProcessors($capabilities = array(), $ids = FALSE) { - $mode = NULL; $testProcessors = in_array('TestMode', $capabilities) ? self::getAllPaymentProcessors('test') : array(); if (is_array($ids)) { $processors = self::getAllPaymentProcessors('all', TRUE, FALSE); diff --git a/CRM/Financial/Form/Payment.php b/CRM/Financial/Form/Payment.php index 8d4969ee4f..0830426248 100644 --- a/CRM/Financial/Form/Payment.php +++ b/CRM/Financial/Form/Payment.php @@ -43,6 +43,12 @@ class CRM_Financial_Form_Payment extends CRM_Core_Form { * @var array */ public $_paymentProcessor; + + /** + * @var bool + */ + public $isBackOffice = FALSE; + /** * Set variables up before form is built. */ @@ -56,6 +62,9 @@ class CRM_Financial_Form_Payment extends CRM_Core_Form { $this->currency = CRM_Utils_Request::retrieve('currency', 'String', CRM_Core_DAO::$_nullObject, TRUE); + $this->paymentInstrumentID = CRM_Utils_Request::retrieve('payment_instrument_id', 'Integer'); + $this->isBackOffice = CRM_Utils_Request::retrieve('is_back_office', 'Integer'); + $this->assignBillingType(); $this->_paymentProcessor = CRM_Financial_BAO_PaymentProcessor::getPayment($this->_paymentProcessorID); @@ -100,7 +109,6 @@ class CRM_Financial_Form_Payment extends CRM_Core_Form { * @param int $paymentProcessorID */ public static function addCreditCardJs($paymentProcessorID = NULL) { - $creditCards = array(); $creditCards = CRM_Financial_BAO_PaymentProcessor::getCreditCards($paymentProcessorID); $creditCardTypes = CRM_Core_Payment_Form::getCreditCardCSSNames($creditCards); CRM_Core_Resources::singleton() diff --git a/CRM/Member/Form.php b/CRM/Member/Form.php index db5b8eda72..178b4420f0 100644 --- a/CRM/Member/Form.php +++ b/CRM/Member/Form.php @@ -169,6 +169,7 @@ class CRM_Member_Form extends CRM_Contribute_Form_AbstractEditPayment { ); CRM_Core_Payment_Form::buildPaymentForm($this, $this->_paymentProcessor, FALSE, TRUE); } + // Build the form for auto renew. This is displayed when in credit card mode or update mode. // The reason for showing it in update mode is not that clear. if ($this->_mode || ($this->_action & CRM_Core_Action::UPDATE)) { @@ -189,7 +190,6 @@ class CRM_Member_Form extends CRM_Contribute_Form_AbstractEditPayment { ts('Membership renewed automatically') ); - $this->assignPaymentRelatedVariables(); } $this->assign('autoRenewOptions', json_encode($this->membershipTypeRenewalStatus)); @@ -303,9 +303,7 @@ class CRM_Member_Form extends CRM_Contribute_Form_AbstractEditPayment { } } - if ($this->_mode) { - $this->assignPaymentRelatedVariables(); - } + $this->assignPaymentRelatedVariables(); if ($this->_id) { $this->_memType = CRM_Core_DAO::getFieldValue('CRM_Member_DAO_Membership', $this->_id, 'membership_type_id'); @@ -441,6 +439,7 @@ class CRM_Member_Form extends CRM_Contribute_Form_AbstractEditPayment { * @param array $formValues */ public function testSubmit($formValues) { + $this->setContextVariables($formValues); $this->_memType = $formValues['membership_type_id'][1]; $this->_params = $formValues; $this->submit(); diff --git a/CRM/Member/Form/Membership.php b/CRM/Member/Form/Membership.php index 7036478727..4bc2375003 100644 --- a/CRM/Member/Form/Membership.php +++ b/CRM/Member/Form/Membership.php @@ -1110,6 +1110,7 @@ class CRM_Member_Form_Membership extends CRM_Member_Form { $joinDate = $startDate = $endDate = NULL; $membershipTypes = $membership = $calcDate = array(); $membershipType = NULL; + $paymentInstrumentID = $this->_paymentProcessor['object']->getPaymentInstrumentID(); $mailSend = FALSE; $formValues = $this->setPriceSetParameters($formValues); @@ -1139,6 +1140,7 @@ class CRM_Member_Form_Membership extends CRM_Member_Form { $config = CRM_Core_Config::singleton(); + // @todo this is no longer required if we convert some date fields. $this->convertDateFieldsToMySQL($formValues); $membershipTypeValues = array(); @@ -1362,11 +1364,6 @@ class CRM_Member_Form_Membership extends CRM_Member_Form { $params['financial_type_id'] = CRM_Utils_Array::value('financial_type_id', $formValues); } - // @todo - test removing this line. The beginPostProcess Function should have done it for us. - $this->_paymentProcessor = CRM_Financial_BAO_PaymentProcessor::getPayment($formValues['payment_processor_id'], - $this->_mode - ); - //get the payment processor id as per mode. Try removing in favour of beginPostProcess. $params['payment_processor_id'] = $formValues['payment_processor_id'] = $this->_paymentProcessor['id']; $params['register_date'] = date('YmdHis'); @@ -1411,7 +1408,7 @@ class CRM_Member_Form_Membership extends CRM_Member_Form { $financialType->id = $params['financial_type_id']; $financialType->find(TRUE); $this->_params = $formValues; - $paymentParams['payment_instrument_id'] = $this->_paymentProcessor['payment_instrument_id']; + $contribution = CRM_Contribute_Form_Contribution_Confirm::processFormContribution($this, $paymentParams, NULL, @@ -1423,7 +1420,7 @@ class CRM_Member_Form_Membership extends CRM_Member_Form { 'contribution_page_id' => CRM_Utils_Array::value('contribution_page_id', $formValues), 'source' => CRM_Utils_Array::value('source', $paymentParams, CRM_Utils_Array::value('description', $paymentParams)), 'thankyou_date' => CRM_Utils_Array::value('thankyou_date', $paymentParams), - 'payment_instrument_id' => $this->_paymentProcessor['payment_instrument_id'], + 'payment_instrument_id' => $paymentInstrumentID, ), $financialType, FALSE, @@ -1545,7 +1542,7 @@ class CRM_Member_Form_Membership extends CRM_Member_Form { // of a single path! unset($membershipParams['lineItems']); } - + $membershipParams['payment_instrument_id'] = $paymentInstrumentID; $membership = CRM_Member_BAO_Membership::create($membershipParams, $ids); $params['contribution'] = CRM_Utils_Array::value('contribution', $membershipParams); unset($params['lineItems']); diff --git a/templates/CRM/common/paymentBlock.tpl b/templates/CRM/common/paymentBlock.tpl index 5ce34848f6..c2e74f96cb 100644 --- a/templates/CRM/common/paymentBlock.tpl +++ b/templates/CRM/common/paymentBlock.tpl @@ -105,7 +105,11 @@ {capture assign='profilePathVar'}{/capture} {/if} - var dataUrl = "{crmURL p='civicrm/payment/form' h=0 q="currency=`$currency`&`$urlPathVar``$profilePathVar``$contributionPageID``$preProfileID`processor_id="}" + type; + {capture assign='isBackOfficePathVar'}&is_back_office={$isBackOffice}&{/capture} + + var payment_instrument_id = $('#payment_instrument_id').val(); + + var dataUrl = "{crmURL p='civicrm/payment/form' h=0 q="¤cy=`$currency`&`$urlPathVar``$isBackOfficePathVar``$profilePathVar``$contributionPageID``$preProfileID`processor_id="}" + type; {literal} if (typeof(CRM.vars) != "undefined") { if (typeof(CRM.vars.coreForm) != "undefined") { @@ -118,6 +122,7 @@ } } } + dataUrl = dataUrl + "&payment_instrument_id=" + payment_instrument_id; // Processors like pp-express will hide the form submit buttons, so re-show them when switching $('.crm-submit-buttons', $form).show().find('input').prop('disabled', true); @@ -127,6 +132,7 @@ $('[name=payment_processor_id]').on('change.paymentBlock', function() { buildPaymentBlock($(this).val()); }); + $('#billing-payment-block').on('crmLoad', function() { $('.crm-submit-buttons input').prop('disabled', false); }) diff --git a/tests/phpunit/api/v3/ContributionPageTest.php b/tests/phpunit/api/v3/ContributionPageTest.php index 474dd0bcdc..9765868aa0 100644 --- a/tests/phpunit/api/v3/ContributionPageTest.php +++ b/tests/phpunit/api/v3/ContributionPageTest.php @@ -411,6 +411,7 @@ class api_v3_ContributionPageTest extends CiviUnitTestCase { 'billing_last_name' => 'Gruffier', 'selectMembership' => $this->_ids['membership_type'], 'email-Primary' => 'billy-goat@the-new-bridge.net', + 'payment_processor_id' => $this->params['payment_processor_id'], ); $this->callAPISuccess('contribution_page', 'submit', $submitParams);