CRM-20413 fix to setting wrong payment_instrument_id, by passing responsibility to...
authoreileen <emcnaughton@wikimedia.org>
Tue, 11 Apr 2017 14:43:08 +0000 (02:43 +1200)
committereileen <emcnaughton@wikimedia.org>
Thu, 13 Apr 2017 01:58:52 +0000 (13:58 +1200)
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

17 files changed:
CRM/Contribute/BAO/Contribution.php
CRM/Contribute/Form/AbstractEditPayment.php
CRM/Contribute/Form/AdditionalPayment.php
CRM/Contribute/Form/Contribution/Confirm.php
CRM/Contribute/Form/ContributionBase.php
CRM/Core/Payment.php
CRM/Core/Payment/Form.php
CRM/Core/Payment/Manual.php
CRM/Core/Payment/PayPalImpl.php
CRM/Core/Payment/ProcessorForm.php
CRM/Event/Form/Registration.php
CRM/Financial/BAO/PaymentProcessor.php
CRM/Financial/Form/Payment.php
CRM/Member/Form.php
CRM/Member/Form/Membership.php
templates/CRM/common/paymentBlock.tpl
tests/phpunit/api/v3/ContributionPageTest.php

index aee8f8beba1236a298bcd2be5f3ebeaeed751cda..0f5e0c674b4a42098445c07c9ea6e9240d839cc6 100644 (file)
@@ -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'
index 3e466db5e72be5c88c4f2750c794859102188afd..fcf663822e2a1ea7cc1e8bbd56136d257aa34e74 100644 (file)
@@ -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());
index 28321f2c40f4ffe71ed0cc7c303f14c5660af877..8540925c5e255756f76be3a082a8072d21e123d1 100644 (file)
@@ -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);
index 85574cca9544df41aa2996a7a795c95527b2c77a..55844c1b68d906e028cd64edcb3d54d685a879a9 100644 (file)
@@ -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');
index 80644b80636f62823bc7839d942e0da1fcdbf560..7655c6a310064e5f7f5bdc667763c22107b9d43a 100644 (file)
@@ -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.
    *
index 7d08cbd2b0145908f1d561314ec678245307494b..3138d1f95b1aadbde27dbb4340fcf63eba9d4f72 100644 (file)
@@ -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).
    *
index d4ee8c09d7584e4f379824d3d47c7d9d098550d8..eadec63d937c6ba52f9a9f95dc1c96c31248ad14 100644 (file)
@@ -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));
index b2d12dd7d250c8d4c931223c5fb8153ffba4513a..55bae03df26b461a16284010b8b96b2bcd836a3c 100644 (file)
@@ -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.
    *
index 7e34d17283dbb60bb1cc5c55562c5509cb9dffb6..427477386ef1adf21d7a5c260618109bfeea42e3 100644 (file)
@@ -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);
index 6b875773a847d52ae94406600a5297e9cfb71ce9..1cab78655c2a4117ef3d629cc6e356be40461450 100644 (file)
@@ -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);
   }
 
 }
index cf567cc3da36cfeaddddd41cc0e3d94f88268c9d..05e90604121ab2501279da9aea1d0452e82750d2 100644 (file)
@@ -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.
    */
index 37b6f2f6781c559a0fedbcd0577f80782eac27e4..a3b89b4caaf053f7e141538570f7384a7b282b07 100644 (file)
@@ -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);
index 8d4969ee4f8ac159be2e0af55dbb4e4871b23e83..0830426248e041cf051e3ca0bd2debc0d3b2413c 100644 (file)
@@ -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()
index db5b8eda720ea57080cbb32ec87c41864d5add68..178b4420f0f3612aba56c8ddf235eabb224f75a3 100644 (file)
@@ -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();
index 7036478727e3faf4613ce1d5103514a89619e3ad..4bc23750031573c74a8e89480b389602c97f46f6 100644 (file)
@@ -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']);
index 5ce34848f6a5f030781e776e05dacce9aadc6621..c2e74f96cbbcf61abb07876fee492c0a29da9c9b 100644 (file)
         {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="&currency=`$currency`&`$urlPathVar``$isBackOfficePathVar``$profilePathVar``$contributionPageID``$preProfileID`processor_id="}" + type;
       {literal}
       if (typeof(CRM.vars) != "undefined") {
         if (typeof(CRM.vars.coreForm) != "undefined") {
           }
         }
       }
+      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);
     $('[name=payment_processor_id]').on('change.paymentBlock', function() {
         buildPaymentBlock($(this).val());
     });
+
     $('#billing-payment-block').on('crmLoad', function() {
       $('.crm-submit-buttons input').prop('disabled', false);
     })
index 474dd0bcdcab18acd4effd594ca33557a516948b..9765868aa0c3713fce9687158c6e5fc9e5be1761 100644 (file)
@@ -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);