From: eileenmcnaugton Date: Tue, 13 Oct 2015 13:39:58 +0000 (+1300) Subject: CRM-17256 fix for paylater billing_required X-Git-Url: https://vcs.fsf.org/?a=commitdiff_plain;h=1d1fee72e665d235f26adeaee6c613de707f3542;p=civicrm-core.git CRM-17256 fix for paylater billing_required This commit sets up pay-later as a payment processor class in limited capacity to allow it to cope with the field loading for billing_required_for_pay_later contribution forms. I had hoped not to have to do this in 4.7 but the address fields were not loading correctly on form-change :-(. This did allow me to remove quite a few hacks that were in place to support the way the billing_for_pay_later was working though :-). Note that a better solution than a check-box for billing-required-for-pay-later would be to allow joining a profile of field that the paymnet processor should be 'encouraged' to provide on the payment form. ie. the payment processor could then build the form to include the profile fields and those required (if any) by it's processor. The code is written on the assumption the billing profile might be changed to a real profile at some point --- diff --git a/CRM/Contribute/Form/Contribution.php b/CRM/Contribute/Form/Contribution.php index 074fe609e9..7b00a75e11 100644 --- a/CRM/Contribute/Form/Contribution.php +++ b/CRM/Contribute/Form/Contribution.php @@ -907,7 +907,7 @@ class CRM_Contribute_Form_Contribution extends CRM_Contribute_Form_AbstractEditP } else { // validate payment instrument (e.g. credit card number) - CRM_Core_Payment_Form::validatePaymentInstrument($fields['payment_processor_id'], $fields, $errors, $self); + CRM_Core_Payment_Form::validatePaymentInstrument($fields['payment_processor_id'], $fields, $errors, NULL); } } diff --git a/CRM/Contribute/Form/Contribution/Main.php b/CRM/Contribute/Form/Contribution/Main.php index 59d431f716..051786be2d 100644 --- a/CRM/Contribute/Form/Contribution/Main.php +++ b/CRM/Contribute/Form/Contribution/Main.php @@ -893,19 +893,18 @@ class CRM_Contribute_Form_Contribution_Main extends CRM_Contribute_Form_Contribu } } - // also return if paylater mode - if (CRM_Utils_Array::value('payment_processor_id', $fields) == 0 && $self->_isBillingAddressRequiredForPayLater == 0) { - return empty($errors) ? TRUE : $errors; - } - // if the user has chosen a free membership or the amount is less than zero - // i.e. we skip calling the payment processor and hence dont need credit card - // info + // i.e. we don't need to validate payment related fields or profiles. if ((float) $amount <= 0.0) { return $errors; } - CRM_Core_Payment_Form::validatePaymentInstrument($fields['payment_processor_id'], $fields, $errors, $self); + CRM_Core_Payment_Form::validatePaymentInstrument( + $fields['payment_processor_id'], + $fields, + $errors, + (!$self->_isBillingAddressRequiredForPayLater ? NULL : 'billing') + ); foreach (CRM_Contact_BAO_Contact::$_greetingTypes as $greeting) { if ($greetingType = CRM_Utils_Array::value($greeting, $fields)) { @@ -1161,7 +1160,7 @@ class CRM_Contribute_Form_Contribution_Main extends CRM_Contribute_Form_Contribu // be & by requiring $memFee down here we make it harder to do a sensible refactoring of the function // above (ie. extract the amount in a small function). if ($this->_values['is_monetary'] && - is_array($this->_paymentProcessor) && + !empty($this->_paymentProcessor) && ((float ) $params['amount'] > 0.0 || $memFee > 0.0) ) { $this->setContributeMode(); diff --git a/CRM/Contribute/Form/ContributionBase.php b/CRM/Contribute/Form/ContributionBase.php index 0984975146..1bc1a51747 100644 --- a/CRM/Contribute/Form/ContributionBase.php +++ b/CRM/Contribute/Form/ContributionBase.php @@ -451,6 +451,17 @@ class CRM_Contribute_Form_ContributionBase extends CRM_Core_Form { $this->_isBillingAddressRequiredForPayLater = CRM_Utils_Array::value('is_billing_required', $this->_values); $this->assign('isBillingAddressRequiredForPayLater', $this->_isBillingAddressRequiredForPayLater); } + + // We save the fact that the profile 'billing' is required on the payment form. + // Currently pay-later is the only 'processor' that takes notice of this - but ideally + // 1) it would be possible to select the minimum_billing_profile_id for the contribution form + // 2) that profile_id would be set on the payment processor + // 3) the payment processor would return a billing form that combines these user-configured + // minimums with the payment processor minimums. This would lead to fields like 'postal_code' + // only being on the form if either the admin has configured it as wanted or the processor + // requires it. + $this->assign('billing_profile_id', ($this->_isBillingAddressRequiredForPayLater ? 'billing' : '')); + } /** diff --git a/CRM/Contribute/Form/UpdateBilling.php b/CRM/Contribute/Form/UpdateBilling.php index db3dd856f5..588ac72a0e 100644 --- a/CRM/Contribute/Form/UpdateBilling.php +++ b/CRM/Contribute/Form/UpdateBilling.php @@ -222,7 +222,7 @@ class CRM_Contribute_Form_UpdateBilling extends CRM_Core_Form { CRM_Core_Form::validateMandatoryFields($self->_fields, $fields, $errors); // validate the payment instrument values (e.g. credit card number) - CRM_Core_Payment_Form::validatePaymentInstrument($self->_paymentProcessor['id'], $fields, $errors, $self); + CRM_Core_Payment_Form::validatePaymentInstrument($self->_paymentProcessor['id'], $fields, $errors, NULL); return empty($errors) ? TRUE : $errors; } diff --git a/CRM/Core/Form.php b/CRM/Core/Form.php index 9a99b67fc3..f5ba798e2b 100644 --- a/CRM/Core/Form.php +++ b/CRM/Core/Form.php @@ -733,6 +733,7 @@ class CRM_Core_Form extends HTML_QuickForm_Page { */ protected function preProcessPaymentOptions() { $this->_paymentProcessorID = NULL; + $this->_paymentProcessors[0] = CRM_Financial_BAO_PaymentProcessor::getPayment(0); if ($this->_paymentProcessors) { if (!empty($this->_submitValues)) { $this->_paymentProcessorID = CRM_Utils_Array::value('payment_processor_id', $this->_submitValues); @@ -750,7 +751,9 @@ class CRM_Core_Form extends HTML_QuickForm_Page { } } } - if ($this->_paymentProcessorID) { + if ($this->_paymentProcessorID + || (isset($this->_submitValues['payment_processor_id']) && $this->_submitValues['payment_processor_id'] == 0) + ) { CRM_Core_Payment_ProcessorForm::preProcess($this); } else { diff --git a/CRM/Core/Payment.php b/CRM/Core/Payment.php index e80568779e..2d20cef15c 100644 --- a/CRM/Core/Payment.php +++ b/CRM/Core/Payment.php @@ -91,6 +91,22 @@ abstract class CRM_Core_Payment { */ protected $baseReturnUrl; + /** + * The profile configured to show on the billing form. + * + * Currently only the pseudo-profile 'billing' is supported but hopefully in time we will take an id and + * load that from the DB and the processor will be able to return a set of fields that combines it's minimum + * requirements with the configured requirements. + * + * Currently only the pseudo-processor 'manual' or 'pay-later' uses this setting to return a 'curated' set + * of fields. + * + * Note this change would probably include converting 'billing' to a reserved profile. + * + * @var int|string + */ + protected $billingProfile; + /** * Set Base return URL. * @@ -101,6 +117,15 @@ abstract class CRM_Core_Payment { $this->baseReturnUrl = $url; } + /** + * Set the configured payment profile. + * + * @param int|string $value + */ + public function setBillingProfile($value) { + $this->billingProfile = $value; + } + /** * Opportunity for the payment processor to override the entire form build. * diff --git a/CRM/Core/Payment/Form.php b/CRM/Core/Payment/Form.php index 6fe963ab1e..3ac8637c5c 100644 --- a/CRM/Core/Payment/Form.php +++ b/CRM/Core/Payment/Form.php @@ -48,18 +48,20 @@ class CRM_Core_Payment_Form { * @param CRM_Contribute_Form_AbstractEditPayment|CRM_Contribute_Form_Contribution_Main $form * @param array $processor * Array of properties including 'object' as loaded from CRM_Financial_BAO_PaymentProcessor::getPaymentProcessors. - * @param bool $forceBillingFieldsForPayLater + * @param int $billing_profile_id * 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. */ - static public function setPaymentFieldsByProcessor(&$form, $processor, $forceBillingFieldsForPayLater = FALSE, $isBackOffice = FALSE) { + static public function setPaymentFieldsByProcessor(&$form, $processor, $billing_profile_id = NULL, $isBackOffice = FALSE) { $form->billingFieldSets = array(); + // Load the pay-later processor + // @todo load this right up where the other processors are loaded initially. if (empty($processor)) { - self::hackyHandlePayLaterInPaymentProcessorFunction($form, $forceBillingFieldsForPayLater); - return; + $processor = CRM_Financial_BAO_PaymentProcessor::getPayment(0); } + $processor['object']->setBillingProfile($billing_profile_id); $paymentTypeName = self::getPaymentTypeName($processor); $paymentTypeLabel = self::getPaymentTypeLabel($processor); $form->assign('paymentTypeName', $paymentTypeName); @@ -84,126 +86,6 @@ class CRM_Core_Payment_Form { $smarty->assign('billingDetailsFields', self::getBillingAddressFields($processor, $billingID)); } - /** - * Add pay later billing fields - * - * @deprecated - * - * This is here to preserve the old flow for pay-later requiring billing as I am unsure how to replicate it or what to - * expect from it/ whether it even works. - * - * Including the pay-later flow in this form is pretty hacky unless we adopt the proposed process of adding - * an offline / pay later processor (CRM_Core_Payment_Offline). In which case it would either be implemented - * (preferably) like other processors or (possibly) as a pseudo-processor with the Civi\Payment\System->getById - * turning that class if $id === 0 or getByProcessor returning it when $processor === array(); If we go down the path - * we probably also want to add the default pay-later text into the signature field of the pay later processor and - * implement a function similar to the dummy class where the payment processor outcome class can be set. - * - * Then doPayment could be called regardless of whether the flow is paylater or not - it wouldn't do much although - * people might leverage it's hook - but it would simplify the main postProcess flow as it would look like - * - * if ($paymentStatus === Completed) { - * $processor->setPaymentResult = array('payment_status_id', 1); - * } - * $processor->doDirectPayment(); - * etc - * - * And the postProcess code would not need to distinguish between pay later/ offline & online payments. - * - * Alternatively enforcing certain fields for pay later in some cases would be a candidate for an extension. - * - * @param CRM_Core_Form $form - */ - static protected function setBillingDetailsFields(&$form) { - $bltID = $form->_bltID; - - $form->_paymentFields['billing_first_name'] = array( - 'htmlType' => 'text', - 'name' => 'billing_first_name', - 'title' => ts('Billing First Name'), - 'cc_field' => TRUE, - 'attributes' => array('size' => 30, 'maxlength' => 60, 'autocomplete' => 'off'), - 'is_required' => TRUE, - ); - - $form->_paymentFields['billing_middle_name'] = array( - 'htmlType' => 'text', - 'name' => 'billing_middle_name', - 'title' => ts('Billing Middle Name'), - 'cc_field' => TRUE, - 'attributes' => array('size' => 30, 'maxlength' => 60, 'autocomplete' => 'off'), - 'is_required' => FALSE, - ); - - $form->_paymentFields['billing_last_name'] = array( - 'htmlType' => 'text', - 'name' => 'billing_last_name', - 'title' => ts('Billing Last Name'), - 'cc_field' => TRUE, - 'attributes' => array('size' => 30, 'maxlength' => 60, 'autocomplete' => 'off'), - 'is_required' => TRUE, - ); - - $form->_paymentFields["billing_street_address-{$bltID}"] = array( - 'htmlType' => 'text', - 'name' => "billing_street_address-{$bltID}", - 'title' => ts('Street Address'), - 'cc_field' => TRUE, - 'attributes' => array('size' => 30, 'maxlength' => 60, 'autocomplete' => 'off'), - 'is_required' => TRUE, - ); - - $form->_paymentFields["billing_city-{$bltID}"] = array( - 'htmlType' => 'text', - 'name' => "billing_city-{$bltID}", - 'title' => ts('City'), - 'cc_field' => TRUE, - 'attributes' => array('size' => 30, 'maxlength' => 60, 'autocomplete' => 'off'), - 'is_required' => TRUE, - ); - - $form->_paymentFields["billing_state_province_id-{$bltID}"] = array( - 'htmlType' => 'chainSelect', - 'title' => ts('State/Province'), - 'name' => "billing_state_province_id-{$bltID}", - 'cc_field' => TRUE, - 'is_required' => TRUE, - ); - - $form->_paymentFields["billing_postal_code-{$bltID}"] = array( - 'htmlType' => 'text', - 'name' => "billing_postal_code-{$bltID}", - 'title' => ts('Postal Code'), - 'cc_field' => TRUE, - 'attributes' => array('size' => 30, 'maxlength' => 60, 'autocomplete' => 'off'), - 'is_required' => TRUE, - ); - - $form->_paymentFields["billing_country_id-{$bltID}"] = array( - 'htmlType' => 'select', - 'name' => "billing_country_id-{$bltID}", - 'title' => ts('Country'), - 'cc_field' => TRUE, - 'attributes' => array( - '' => ts('- select -'), - ) + - CRM_Core_PseudoConstant::country(), - 'is_required' => TRUE, - ); - //CRM-15509 working towards giving control over billing fields to payment processors. For now removing tpl hard-coding - $smarty = CRM_Core_Smarty::singleton(); - $smarty->assign('billingDetailsFields', array( - 'billing_first_name', - 'billing_middle_name', - 'billing_last_name', - "billing_street_address-{$bltID}", - "billing_city-{$bltID}", - "billing_country_id-{$bltID}", - "billing_state_province_id-{$bltID}", - "billing_postal_code-{$bltID}", - )); - } - /** * Add the payment fields to the template. * @@ -287,8 +169,7 @@ class CRM_Core_Payment_Form { * @return array */ public static function getBillingAddressFields($paymentProcessor, $billingLocationID) { - $paymentProcessorObject = Civi\Payment\System::singleton()->getByProcessor($paymentProcessor); - return $paymentProcessorObject->getBillingAddressFields($billingLocationID); + return $paymentProcessor['object']->getBillingAddressFields($billingLocationID); } /** @@ -313,8 +194,7 @@ class CRM_Core_Payment_Form { * @return string */ public static function getPaymentTypeName($paymentProcessor) { - $paymentProcessorObject = Civi\Payment\System::singleton()->getByProcessor($paymentProcessor); - return $paymentProcessorObject->getPaymentTypeName(); + return $paymentProcessor['object']->getPaymentTypeName(); } /** @@ -331,10 +211,9 @@ class CRM_Core_Payment_Form { * @param CRM_Contribute_Form_AbstractEditPayment|CRM_Contribute_Form_Contribution_Main|CRM_Core_Payment_ProcessorForm|CRM_Contribute_Form_UpdateBilling $form * @param array $processor * Array of properties including 'object' as loaded from CRM_Financial_BAO_PaymentProcessor::getPaymentProcessors. - * @param bool $isBillingDataOptional - * This manifests for 'NULL' (pay later) payment processor as the addition of billing fields to the form and. - * for payment processors that gather payment data on site as rendering the fields as not being required. (not entirely sure why but this - * is implemented for back office forms) + * @param int|string $billing_profile_id + * Id of a profile to be passed to the processor for the processor to merge with it's required fields. + * (currently only implemented by manual/ pay-later processor) * * @param bool $isBackOffice * Is this a backoffice form. This could affect the display of the cvn or whether some processors show, @@ -344,7 +223,7 @@ class CRM_Core_Payment_Form { * * @return bool */ - public static function buildPaymentForm(&$form, $processor, $isBillingDataOptional, $isBackOffice) { + public static function buildPaymentForm(&$form, $processor, $billing_profile_id, $isBackOffice) { //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)) { @@ -355,7 +234,7 @@ class CRM_Core_Payment_Form { return NULL; } - self::setPaymentFieldsByProcessor($form, $processor, empty($isBillingDataOptional), $isBackOffice); + self::setPaymentFieldsByProcessor($form, $processor, $billing_profile_id, $isBackOffice); self::addCommonFields($form, $form->_paymentFields); self::addRules($form, $form->_paymentFields); return (!empty($form->_paymentFields)); @@ -386,12 +265,10 @@ class CRM_Core_Payment_Form { * We want this to be overrideable by the payment processor, and default to using * this object's validCreditCard for credit cards (implemented as the default in the Payment class). */ - public static function validatePaymentInstrument($payment_processor_id, $values, &$errors, $form) { - // ignore if we don't have a payment instrument to validate (e.g. backend payments) - if ($payment_processor_id > 0) { - $payment = Civi\Payment\System::singleton()->getById($payment_processor_id); - $payment->validatePaymentInstrument($values, $errors); - } + public static function validatePaymentInstrument($payment_processor_id, $values, &$errors, $billing_profile_id) { + $payment = Civi\Payment\System::singleton()->getById($payment_processor_id); + $payment->setBillingProfile($billing_profile_id); + $payment->validatePaymentInstrument($values, $errors); } /** @@ -528,22 +405,4 @@ class CRM_Core_Payment_Form { return CRM_Utils_Array::value('Y', $src['credit_card_exp_date']); } - /** - * Set billing fields for pay later. - * - * This is considered hacky because pay later has basically been cludged onto the payment processor form. - * - * See notes on the deprecated function as to how this could be restructured. Alternatively this pay later - * handling could be moved out of the payment processor form all together. - * - * @param CRM_Core_Form $form - * @param int $forceBillingFieldsForPayLater - */ - protected static function hackyHandlePayLaterInPaymentProcessorFunction(&$form, $forceBillingFieldsForPayLater) { - if ($forceBillingFieldsForPayLater) { - CRM_Core_Payment_Form::setBillingDetailsFields($form); - $form->billingFieldSets['billing_name_address-group']['fields'] = array(); - } - } - } diff --git a/CRM/Core/Payment/Manual.php b/CRM/Core/Payment/Manual.php new file mode 100644 index 0000000000..b438b8faaf --- /dev/null +++ b/CRM/Core/Payment/Manual.php @@ -0,0 +1,161 @@ +billingProfile == 'billing') { + // @todo - use profile api to retrieve this - either as pseudo-profile or (better) set up billing + // as a reserved profile in the DB and (even better) allow the profile to be selected + // on the form instead of just 'billing for pay=later bool' + return array( + 'first_name' => 'billing_first_name', + 'middle_name' => 'billing_middle_name', + 'last_name' => 'billing_last_name', + 'street_address' => "billing_street_address-{$billingLocationID}", + 'city' => "billing_city-{$billingLocationID}", + 'country' => "billing_country_id-{$billingLocationID}", + 'state_province' => "billing_state_province_id-{$billingLocationID}", + 'postal_code' => "billing_postal_code-{$billingLocationID}", + ); + } + else { + return array(); + } + } + + /** + * Get array of fields that should be displayed on the payment form. + * + * @return array + */ + public function getPaymentFormFields() { + return array(); + } + /** + * Process payment. + * + * The function ensures an exception is thrown & moves some of this logic out of the form layer and makes the forms + * more agnostic. + * + * @param array $params + * + * @param string $component + * + * @return array + * Result array + * + * @throws \Civi\Payment\Exception\PaymentProcessorException + */ + public function doPayment(&$params, $component = 'contribute') { + $params['payment_status_id'] = $this->getResult(); + return $params; + } + + /** + * Get the result of the payment. + * + * Usually this will be pending but the calling layer has a chance to set the result. + * + * This would apply in particular when the form accepts status id. + * + * Note that currently this payment class is only being used to manage the 'billing block' aspect + * of pay later. However, a longer term idea is that by treating 'pay-later' as 'just another processor' + * will allow code simplification. + * + * @return int + */ + protected function getResult() { + if (!$this->result) { + $this->setResult(CRM_Core_PseudoConstant::getKey('CRM_Contribute_BAO_Contribution', 'status_id', 'Pending')); + } + return $this->result; + } + + /** + * Set the result to be returned. + * + * This would be set from outside the function where we want to pass on the status from the form. + * + * @param int $result + */ + public function setResult($result) { + $this->result = $result; + } + + /** + * Get the name of the payment type. + * + * @return string + */ + public function getPaymentTypeName() { + return 'pay-later'; + } + + /** + * Get the name of the payment type. + * + * @return string + */ + public function getPaymentTypeLabel() { + return ''; + } +} diff --git a/CRM/Core/Payment/ProcessorForm.php b/CRM/Core/Payment/ProcessorForm.php index e90bedf7a6..86706dd81b 100644 --- a/CRM/Core/Payment/ProcessorForm.php +++ b/CRM/Core/Payment/ProcessorForm.php @@ -70,7 +70,11 @@ class CRM_Core_Payment_ProcessorForm { //checks after setting $form->_paymentProcessor // we do this outside of the above conditional to avoid // saving the country/state list in the session (which could be huge) - CRM_Core_Payment_Form::setPaymentFieldsByProcessor($form, $form->_paymentProcessor); + CRM_Core_Payment_Form::setPaymentFieldsByProcessor( + $form, + $form->_paymentProcessor, + CRM_Utils_Request::retrieve('billing_profile_id', 'String') + ); $form->assign_by_ref('paymentProcessor', $form->_paymentProcessor); @@ -113,12 +117,14 @@ class CRM_Core_Payment_ProcessorForm { //CRM-15743 - we should not set/create hidden element for pay later // because payment processor is not selected $processorId = $form->getVar('_paymentProcessorID'); - $isBillingAddressRequiredForPayLater = $form->_isBillingAddressRequiredForPayLater; + $billing_profile_id = CRM_Utils_Request::retrieve('billing_profile_id', 'String'); + if (!empty($form->_values) && !empty($form->_values['is_billing_required'])) { + $billing_profile_id = 'billing'; + } if (!empty($processorId)) { - $isBillingAddressRequiredForPayLater = FALSE; $form->addElement('hidden', 'hidden_processor', 1); } - CRM_Core_Payment_Form::buildPaymentForm($form, $form->_paymentProcessor, empty($isBillingAddressRequiredForPayLater), FALSE); + CRM_Core_Payment_Form::buildPaymentForm($form, $form->_paymentProcessor, $billing_profile_id, FALSE); } } diff --git a/CRM/Financial/BAO/PaymentProcessor.php b/CRM/Financial/BAO/PaymentProcessor.php index e79722e603..4e9f92c059 100644 --- a/CRM/Financial/BAO/PaymentProcessor.php +++ b/CRM/Financial/BAO/PaymentProcessor.php @@ -303,6 +303,19 @@ class CRM_Financial_BAO_PaymentProcessor extends CRM_Financial_DAO_PaymentProces $processors['values'][$processor['id']]['object'] = Civi\Payment\System::singleton()->getByProcessor($processor); } + // Add the pay-later pseudo-processor. + $processors['values'][0] = array( + 'object' => new CRM_Core_Payment_Manual(), + 'id' => 0, + 'payment_processor_type_id' => 0, + 'class_name' => 'Payment_Manual', + 'name' => 'pay_later', + 'billing_mode' => '', + // 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, + ); + CRM_Utils_Cache::singleton()->set($cacheKey, $processors['values']); return $processors['values']; diff --git a/CRM/Financial/Form/Payment.php b/CRM/Financial/Form/Payment.php index 8089960eed..b3fca54abf 100644 --- a/CRM/Financial/Form/Payment.php +++ b/CRM/Financial/Form/Payment.php @@ -31,6 +31,16 @@ * @copyright CiviCRM LLC (c) 2004-2015 */ class CRM_Financial_Form_Payment extends CRM_Core_Form { + + /** + * @var int + */ + protected $_paymentProcessorID; + + /** + * @var array + */ + public $_paymentProcessor; /** * Set variables up before form is built. */ @@ -42,6 +52,7 @@ class CRM_Financial_Form_Payment extends CRM_Core_Form { $this->assignBillingType(); $this->_paymentProcessor = CRM_Financial_BAO_PaymentProcessor::getPayment($this->_paymentProcessorID); + CRM_Core_Payment_ProcessorForm::preProcess($this); self::addCreditCardJs(); @@ -52,6 +63,9 @@ class CRM_Financial_Form_Payment extends CRM_Core_Form { $this->controller->_generateQFKey = FALSE; } + /** + * Build quickForm. + */ public function buildQuickForm() { CRM_Core_Payment_ProcessorForm::buildQuickForm($this); } @@ -66,7 +80,7 @@ class CRM_Financial_Form_Payment extends CRM_Core_Form { } /** - * Add JS to show icons for the accepted credit cards + * Add JS to show icons for the accepted credit cards. */ public static function addCreditCardJs() { $creditCardTypes = CRM_Core_Payment_Form::getCreditCardCSSNames(); diff --git a/Civi/Payment/System.php b/Civi/Payment/System.php index 5bfa71b2a0..9ce8cb196f 100644 --- a/Civi/Payment/System.php +++ b/Civi/Payment/System.php @@ -73,12 +73,17 @@ class System { } /** + * Get payment processor by it's ID. + * * @param int $id * * @return \Civi\Payment\CRM_Core_Payment|NULL * @throws \CiviCRM_API3_Exception */ public function getById($id) { + if ($id == 0) { + return new \CRM_Core_Payment_Manual(); + } $processor = civicrm_api3('payment_processor', 'getsingle', array('id' => $id, 'is_test' => NULL)); return self::getByProcessor($processor); } diff --git a/templates/CRM/common/paymentBlock.tpl b/templates/CRM/common/paymentBlock.tpl index 79f43994ce..042711b40c 100644 --- a/templates/CRM/common/paymentBlock.tpl +++ b/templates/CRM/common/paymentBlock.tpl @@ -29,14 +29,7 @@ CRM.$(function($) { function buildPaymentBlock(type) { var $form = $('#billing-payment-block').closest('form'); - - {/literal}{if !$isBillingAddressRequiredForPayLater}{literal} - if (type == 0) { - $("#billing-payment-block").html(''); - return; - } - {/literal}{/if} - + {/literal} {if $contributionPageID} {capture assign='contributionPageID'}id={$contributionPageID}&{/capture} {else} @@ -47,8 +40,13 @@ {else} {capture assign='urlPathVar'}{/capture} {/if} + {if $billing_profile_id} + {capture assign='profilePathVar'}billing_profile_id={$billing_profile_id}&{/capture} + {else} + {capture assign='profilePathVar'}{/capture} + {/if} - var dataUrl = "{crmURL p='civicrm/payment/form' h=0 q="`$urlPathVar``$contributionPageID`processor_id="}" + type; + var dataUrl = "{crmURL p='civicrm/payment/form' h=0 q="`$urlPathVar``$profilePathVar``$contributionPageID`processor_id="}" + type; {literal} if (typeof(CRM.vars) != "undefined") { if (typeof(CRM.vars.coreForm) != "undefined") {