<?php
/*
+--------------------------------------------------------------------+
- | CiviCRM version 4.6 |
+ | CiviCRM version 4.7 |
+--------------------------------------------------------------------+
| Copyright CiviCRM LLC (c) 2004-2015 |
+--------------------------------------------------------------------+
* Set the parameters to be passed to contribution create function.
*
* @param array $params
- * @param int $contactID
* @param int $financialTypeID
- * @param bool $online
- * @param int $contributionPageId
* @param float $nonDeductibleAmount
- * @param int $campaignId
- * @param bool $isMonetary
* @param bool $pending
* @param array $paymentProcessorOutcome
* @param string $receiptDate
* @param int $recurringContributionID
- * @param bool $isTest
- * @param int $addressID
- * @param int $softCreditToID
- * @param array $lineItems
*
* @return array
*/
public static function getContributionParams(
- $params, $contactID, $financialTypeID, $online, $contributionPageId, $nonDeductibleAmount, $campaignId, $isMonetary, $pending,
- $paymentProcessorOutcome, $receiptDate, $recurringContributionID, $isTest, $addressID, $softCreditToID, $lineItems) {
+ $params, $financialTypeID, $nonDeductibleAmount, $pending,
+ $paymentProcessorOutcome, $receiptDate, $recurringContributionID) {
$contributionParams = array(
- 'contact_id' => $contactID,
'financial_type_id' => $financialTypeID,
- 'contribution_page_id' => $contributionPageId,
'receive_date' => (CRM_Utils_Array::value('receive_date', $params)) ? CRM_Utils_Date::processDate($params['receive_date']) : date('YmdHis'),
'non_deductible_amount' => $nonDeductibleAmount,
'total_amount' => $params['amount'],
'amount_level' => CRM_Utils_Array::value('amount_level', $params),
'invoice_id' => $params['invoiceID'],
'currency' => $params['currencyID'],
- 'source' => (!$online || !empty($params['source'])) ? CRM_Utils_Array::value('source', $params) : CRM_Utils_Array::value('description', $params),
'is_pay_later' => CRM_Utils_Array::value('is_pay_later', $params, 0),
//configure cancel reason, cancel date and thankyou date
//from 'contribution' type profile if included
'cancel_reason' => CRM_Utils_Array::value('cancel_reason', $params, 0),
'cancel_date' => isset($params['cancel_date']) ? CRM_Utils_Date::format($params['cancel_date']) : NULL,
'thankyou_date' => isset($params['thankyou_date']) ? CRM_Utils_Date::format($params['thankyou_date']) : NULL,
- 'campaign_id' => $campaignId,
- 'is_test' => $isTest,
- 'address_id' => $addressID,
//setting to make available to hook - although seems wrong to set on form for BAO hook availability
- 'soft_credit_to' => $softCreditToID,
- 'line_item' => $lineItems,
'skipLineItem' => CRM_Utils_Array::value('skipLineItem', $params, 0),
);
- if (!$online && isset($params['thankyou_date'])) {
- $contributionParam['thankyou_date'] = $params['thankyou_date'];
- }
- if (!$online || $isMonetary) {
- if (empty($params['is_pay_later'])) {
- $contributionParams['payment_instrument_id'] = 1;
- }
- }
+
if ($paymentProcessorOutcome) {
$contributionParams['payment_processor'] = CRM_Utils_Array::value('payment_processor', $paymentProcessorOutcome);
}
* @param CRM_Core_Form $form
* @param array $params
* @param array $result
- * @param int $contactID
+ * @param array $contributionParams
+ * Parameters to be passed to contribution create action.
+ * This differs from params in that we are currently adding params to it and 1) ensuring they are being
+ * passed consistently & 2) documenting them here.
+ * - contact_id
+ * - line_item
+ * - is_test
+ * - campaign_id
+ * - contribution_page_id
+ * - source
+ * - payment_type_id
+ * - thankyou_date (not all forms will set this)
+ *
* @param CRM_Financial_DAO_FinancialType $financialType
- * @param bool $pending
* @param bool $online
- *
- * @param bool $isTest
- * @param array $lineItems
+ * Is the form a front end form? If so set a bunch of unpredictable things that should be passed in from the form.
*
* @param int $billingLocationID
* ID of billing location type.
&$form,
$params,
$result,
- $contactID,
+ $contributionParams,
$financialType,
- $pending,
$online,
- $isTest,
- $lineItems,
$billingLocationID
) {
$transaction = new CRM_Core_Transaction();
- $contribSoftContactId = $addressID = NULL;
- $isMonetary = !empty($form->_values['is_monetary']);
+ $contactID = $contributionParams['contact_id'];
+
$isEmailReceipt = !empty($form->_values['is_email_receipt']);
- // How do these vary from params? These are currently passed to
- // - custom data function....
- $formParams = $form->_params;
- $isSeparateMembershipPayment = empty($formParams['separate_membership_payment']) ? FALSE : TRUE;
- $pledgeID = empty($formParams['pledge_id']) ? NULL : $formParams['pledge_id'];
+ $isSeparateMembershipPayment = empty($params['separate_membership_payment']) ? FALSE : TRUE;
+ $pledgeID = empty($params['pledge_id']) ? NULL : $params['pledge_id'];
if (!$isSeparateMembershipPayment && !empty($form->_values['pledge_block_id']) &&
- (!empty($formParams['is_pledge']) || $pledgeID)) {
+ (!empty($params['is_pledge']) || $pledgeID)) {
$isPledge = TRUE;
}
else {
// add these values for the recurringContrib function ,CRM-10188
$params['financial_type_id'] = $financialType->id;
- $addressID = CRM_Contribute_BAO_Contribution::createAddress($params, $billingLocationID);
+ $contributionParams['address_id'] = CRM_Contribute_BAO_Contribution::createAddress($params, $billingLocationID);
//@todo - this is being set from the form to resolve CRM-10188 - an
// eNotice caused by it not being set @ the front end
$receiptDate = $now;
}
- //get the contrib page id.
- $contributionPageId = NULL;
- if ($online) {
- $contributionPageId = $form->_id;
- $campaignId = CRM_Utils_Array::value('campaign_id', $params);
- if (!array_key_exists('campaign_id', $params)) {
- $campaignId = CRM_Utils_Array::value('campaign_id', $form->_values);
- }
- }
- else {
- //also for offline we do support - CRM-7290
- $contributionPageId = CRM_Utils_Array::value('contribution_page_id', $params);
- $campaignId = CRM_Utils_Array::value('campaign_id', $params);
- }
-
- // Prepare soft contribution due to pcp or Submit Credit / Debit Card Contribution by admin.
- if (!empty($params['pcp_made_through_id']) || !empty($params['soft_credit_to'])) {
- // if its due to pcp
- if (!empty($params['pcp_made_through_id'])) {
- $contribSoftContactId = CRM_Core_DAO::getFieldValue(
- 'CRM_PCP_DAO_PCP',
- $params['pcp_made_through_id'],
- 'contact_id'
- );
- }
- else {
- $contribSoftContactId = CRM_Utils_Array::value('soft_credit_to', $params);
- }
-
- // Pass these details onto with the contribution to make them
- // available at hook_post_process, CRM-8908
- $params['soft_credit_to'] = $contribSoftContactId;
- }
-
if (isset($params['amount'])) {
- $contribParams = self::getContributionParams(
- $params, $contactID, $financialType->id, $online, $contributionPageId, $nonDeductibleAmount, $campaignId, $isMonetary, $pending, $result, $receiptDate,
- $recurringContributionID, $isTest, $addressID, $contribSoftContactId, $lineItems
+ $contributionParams = array_merge(self::getContributionParams(
+ $params, $financialType->id, $nonDeductibleAmount, TRUE,
+ $result, $receiptDate,
+ $recurringContributionID), $contributionParams
);
- $contribution = CRM_Contribute_BAO_Contribution::add($contribParams);
+ $contribution = CRM_Contribute_BAO_Contribution::add($contributionParams);
$invoiceSettings = CRM_Core_BAO_Setting::getItem(CRM_Core_BAO_Setting::CONTRIBUTE_PREFERENCES_NAME, 'contribution_invoice_settings');
$invoicing = CRM_Utils_Array::value('invoicing', $invoiceSettings);
if ($invoicing) {
$dataArray = array();
+ // @todo - interrogate the line items passed in on the params array.
+ // No reason to assume line items will be set on the form.
foreach ($form->_lineItem as $lineItemKey => $lineItemValue) {
foreach ($lineItemValue as $key => $value) {
if (isset($value['tax_amount']) && isset($value['tax_rate'])) {
$form->_contributionID = $contribution->id;
}
- //CRM-13981, processing honor contact into soft-credit contribution
- CRM_Contact_Form_ProfileContact::postProcess($form);
+ // process soft credit / pcp params first
+ CRM_Contribute_BAO_ContributionSoft::formatSoftCreditParams($params, $form);
- // process soft credit / pcp pages
- CRM_Contribute_Form_Contribution_Confirm::processPcpSoft($params, $contribution);
+ //CRM-13981, processing honor contact into soft-credit contribution
+ CRM_Contribute_BAO_ContributionSoft::processSoftContribution($params, $contribution);
//handle pledge stuff.
if ($isPledge) {
if ($pledgeID) {
//when user doing pledge payments.
//update the schedule when payment(s) are made
- foreach ($form->_params['pledge_amount'] as $paymentId => $dontCare) {
+ foreach ($params['pledge_amount'] as $paymentId => $dontCare) {
$scheduledAmount = CRM_Core_DAO::getFieldValue(
'CRM_Pledge_DAO_PledgePayment',
$paymentId,
$pledgeParams['original_installment_amount'] = $pledgeParams['installment_amount'];
//inherit campaign from contirb page.
- $pledgeParams['campaign_id'] = $campaignId;
+ $pledgeParams['campaign_id'] = CRM_Utils_Array::value('campaign_id', $contributionParams);
$pledge = CRM_Pledge_BAO_Pledge::create($pledgeParams);
}
if ($online && $contribution) {
- CRM_Core_BAO_CustomValueTable::postProcess($form->_params,
+ CRM_Core_BAO_CustomValueTable::postProcess($params,
'civicrm_contribution',
$contribution->id,
'Contribution'
}
}
- /**
- * Function used to save pcp / soft credit entry.
- *
- * This is used by contribution and also event pcps
- *
- * @param array $params
- * @param object $contribution
- * Contribution object.
- */
- public static function processPcpSoft(&$params, &$contribution) {
- // Add soft contribution due to pcp or Submit Credit / Debit Card Contribution by admin.
- if (!empty($params['soft_credit_to'])) {
- $contributionSoftParams = array();
- foreach (array(
- 'pcp_display_in_roll',
- 'pcp_roll_nickname',
- 'pcp_personal_note',
- 'amount',
- ) as $val) {
- if (!empty($params[$val])) {
- $contributionSoftParams[$val] = $params[$val];
- }
- }
-
- $contributionSoftParams['contact_id'] = $params['soft_credit_to'];
- // add contribution id
- $contributionSoftParams['contribution_id'] = $contribution->id;
- // add pcp id
- $contributionSoftParams['pcp_id'] = $params['pcp_made_through_id'];
-
- $contributionSoftParams['soft_credit_type_id'] = CRM_Core_OptionGroup::getValue('soft_credit_type', 'pcp', 'name');
-
- $contributionSoft = CRM_Contribute_BAO_ContributionSoft::add($contributionSoftParams);
-
- //Send notification to owner for PCP
- if ($contributionSoft->id && $contributionSoft->pcp_id) {
- CRM_Contribute_Form_Contribution_Confirm::pcpNotifyOwner($contribution, $contributionSoft);
- }
- }
- }
-
/**
* Function used to send notification mail to pcp owner.
*
$contactID,
$financialTypeID,
'membership',
- array(),
- $isTest,
- $isPayLater
+ $isTest
);
if (!empty($paymentResult['contribution'])) {
}
$payment = Civi\Payment\System::singleton()->getByProcessor($form->_paymentProcessor);
$paymentActionResult = $payment->doPayment($form->_params, 'contribute');
-
- if (CRM_Utils_Array::value('payment_status_id', $paymentActionResult) == 1) {
- // Refer to CRM-16737. Payment processors 'should' return payment_status_id
- // to denote the outcome of the transaction.
- try {
- civicrm_api3('contribution', 'completetransaction', array(
- 'id' => $paymentResult['contribution']->id,
- 'trxn_id' => CRM_Utils_Array::value('trxn_id', $paymentActionResult, $paymentResult['contribution']->trxn_id),
- 'is_transactional' => FALSE,
- 'payment_processor_id' => $form->_paymentProcessor['id'],
- ));
- }
- catch (CiviCRM_API3_Exception $e) {
- if ($e->getErrorCode() != 'contribution_completed') {
- throw new CRM_Core_Exception('Failed to update contribution in database');
- }
- }
- }
+ $this->completeTransaction($paymentActionResult, $paymentResult['contribution']->id);
// Do not send an email if Recurring transaction is done via Direct Mode
// Email will we sent when the IPN is received.
return;
$tempParams['amount'] = $minimumFee;
$tempParams['invoiceID'] = md5(uniqid(rand(), TRUE));
- $result = NULL;
- if ($form->_values['is_monetary'] && !$form->_params['is_pay_later'] && $minimumFee > 0.0) {
- // At the moment our tests are calling this form in a way that leaves 'object' empty. For
- // now we compensate here.
- if (empty($form->_paymentProcessor['object'])) {
- $payment = Civi\Payment\System::singleton()->getByProcessor($this->_paymentProcessor);
- }
- else {
- $payment = $form->_paymentProcessor['object'];
- }
- $result = $payment->doPayment($tempParams, 'contribute');
- }
-
//assign receive date when separate membership payment
//and contribution amount not selected.
if ($form->_amount == 0) {
$form->assign('receive_date', $receiveDate);
}
- $form->set('membership_trx_id', $result['trxn_id']);
$form->set('membership_amount', $minimumFee);
-
- $form->assign('membership_trx_id', $result['trxn_id']);
$form->assign('membership_amount', $minimumFee);
// we don't need to create the user twice, so lets disable cms_create_account
// irrespective of the value, CRM-2888
$tempParams['cms_create_account'] = 0;
- //CRM-16165, scenarios are
- // 1) If contribution is_pay_later and if contribution amount is > 0.0 we set pending = TRUE, vice-versa FALSE
- // 2) If not pay later but auto-renewal membership is chosen then pending = TRUE as it later triggers
- // pending recurring contribution, vice-versa FALSE
- $pending = $form->_params['is_pay_later'] ? (($minimumFee > 0.0) ? TRUE : FALSE) : (!empty($form->_params['auto_renew']) ? TRUE : FALSE);
-
//set this variable as we are not creating pledge for
//separate membership payment contribution.
//so for differentiating membership contribution from
//main contribution.
$form->_params['separate_membership_payment'] = 1;
+ $contributionParams = array(
+ 'contact_id' => $contactID,
+ 'line_item' => $lineItems,
+ 'is_test' => $isTest,
+ 'campaign_id' => CRM_Utils_Array::value('campaign_id', $tempParams, CRM_Utils_Array::value('campaign_id',
+ $form->_values)),
+ 'contribution_page_id' => $form->_id,
+ 'source' => CRM_Utils_Array::value('source', $tempParams, CRM_Utils_Array::value('description', $tempParams)),
+ );
+ $isMonetary = !empty($form->_values['is_monetary']);
+ if ($isMonetary) {
+ if (empty($paymentParams['is_pay_later'])) {
+ $contributionParams['payment_instrument_id'] = $form->_paymentProcessor['payment_instrument_id'];
+ }
+ }
$membershipContribution = CRM_Contribute_Form_Contribution_Confirm::processFormContribution($form,
$tempParams,
- $result,
- $contactID,
+ $tempParams,
+ $contributionParams,
$financialType,
- $pending,
TRUE,
- $isTest,
- $lineItems,
$form->_bltID
);
+
+ if ($form->_values['is_monetary'] && !$form->_params['is_pay_later'] && $minimumFee > 0.0) {
+ // At the moment our tests are calling this form in a way that leaves 'object' empty. For
+ // now we compensate here.
+ if (empty($form->_paymentProcessor['object'])) {
+ $payment = Civi\Payment\System::singleton()->getByProcessor($this->_paymentProcessor);
+ }
+ else {
+ $payment = $form->_paymentProcessor['object'];
+ }
+ $result = $payment->doPayment($tempParams, 'contribute');
+ $form->set('membership_trx_id', $result['trxn_id']);
+ $form->assign('membership_trx_id', $result['trxn_id']);
+ $this->completeTransaction($result, $membershipContribution->id);
+ }
+
return $membershipContribution;
}
// all the payment processors expect the name and address to be in the
// so we copy stuff over to first_name etc.
$paymentParams = $this->_params;
- $contributionTypeId = $this->_values['financial_type_id'];
- $fieldTypes = array();
if (!empty($paymentParams['onbehalf']) &&
is_array($paymentParams['onbehalf'])
) {
$this->_params[$key] = $value;
}
}
- $fieldTypes = array('Contact', 'Organization', 'Contribution');
}
- $financialTypeID = $this->wrangleFinancialTypeID($contributionTypeId);
$result = CRM_Contribute_BAO_Contribution_Utils::processConfirm($this, $paymentParams,
$contactID,
- $financialTypeID,
+ $this->wrangleFinancialTypeID($this->_values['financial_type_id']),
'contribution',
- $fieldTypes,
- ($this->_mode == 'test') ? 1 : 0,
- $isPayLater
+ ($this->_mode == 'test') ? 1 : 0
);
- if (!empty($result['is_payment_failure'])) {
- return $result;
- }
- // @todo move premium processing to complete transaction if it truly is an 'after' action.
- $this->postProcessPremium($premiumParams, $result['contribution']);
- if (CRM_Utils_Array::value('payment_status_id', $result) == 1) {
- try {
- civicrm_api3('contribution', 'completetransaction', array(
- 'id' => $result['contribution']->id,
- 'trxn_id' => CRM_Utils_Array::value('trxn_id', $result),
- 'payment_processor_id' => $this->_paymentProcessor['id'],
- 'is_transactional' => FALSE,
- )
- );
- }
- catch (CiviCRM_API3_Exception $e) {
- if ($e->getErrorCode() != 'contribution_completed') {
- throw new CRM_Core_Exception('Failed to update contribution in database');
- }
- }
-
+ if (empty($result['is_payment_failure'])) {
+ // @todo move premium processing to complete transaction if it truly is an 'after' action.
+ $this->postProcessPremium($premiumParams, $result['contribution']);
+ }
+ if (!empty($result['contribution'])) {
+ // Not quite sure why it would be empty at this stage but tests show it can be ... at least in tests.
+ $this->completeTransaction($result, $result['contribution']->id);
}
return $result;
}
}
}
+ /**
+ * Complete transaction if payment has been processed.
+ *
+ * Check the result for a success outcome & if paid then complete the transaction.
+ *
+ * Completing will trigger update of related entities and emails.
+ *
+ * @param array $result
+ * @param int $contributionID
+ *
+ * @throws \CRM_Core_Exception
+ */
+ protected function completeTransaction($result, $contributionID) {
+ if (CRM_Utils_Array::value('payment_status_id', $result) == 1) {
+ try {
+ civicrm_api3('contribution', 'completetransaction', array(
+ 'id' => $contributionID,
+ 'trxn_id' => CRM_Utils_Array::value('trxn_id', $result),
+ 'payment_processor_id' => $this->_paymentProcessor['id'],
+ 'is_transactional' => FALSE,
+ 'fee_amount' => CRM_Utils_Array::value('fee_amount', $result),
+ )
+ );
+ }
+ catch (CiviCRM_API3_Exception $e) {
+ if ($e->getErrorCode() != 'contribution_completed') {
+ throw new CRM_Core_Exception('Failed to update contribution in database');
+ }
+ }
+ }
+ }
+
}