$paymentParams,
NULL,
$contactID,
- $contributionType,
- TRUE, TRUE,
+ $financialType,
+ TRUE,
+ TRUE,
$isTest,
- $lineItems
+ $lineItems,
+ $form->_bltID
);
- if ($contribution) {
- $form->_params['contributionID'] = $contribution->id;
- }
-
- $form->_params['contributionTypeID'] = $contributionTypeId;
- $form->_params['item_name'] = $form->_params['description'];
+ $paymentParams['contributionTypeID'] = $contributionTypeId;
+ $paymentParams['item_name'] = $form->_params['description'];
- if ($contribution && $form->_values['is_recur'] &&
- $contribution->contribution_recur_id
+ if ($contribution && $form->_values['is_recur'] && $contribution->contribution_recur_id
) {
- $form->_params['contributionRecurID'] = $contribution->contribution_recur_id;
+ $paymentParams['contributionRecurID'] = $contribution->contribution_recur_id;
}
- $form->set('params', $form->_params);
- $form->postProcessPremium($premiumParams, $contribution);
-
- if ($isPaymentTransaction) {
- // add qfKey so we can send to paypal
- $form->_params['qfKey'] = $form->controller->_key;
- if ($component == 'membership') {
- $membershipResult = array(1 => $contribution);
- return $membershipResult;
- }
- else {
- if (!$isPayLater) {
- if (is_object($payment)) {
- // call postProcess hook before leaving
- $form->postProcessHook();
- // this does not return
- $result = $payment->doTransferCheckout($form->_params, 'contribute');
- }
- else {
- CRM_Core_Error::fatal($paymentObjError);
- }
- }
- else {
- // follow similar flow as IPN
- // send the receipt mail
- $form->set('params', $form->_params);
- if ($contributionType->is_deductible) {
- $form->assign('is_deductible', TRUE);
- $form->set('is_deductible', TRUE);
- }
- if (isset($paymentParams['contribution_source'])) {
- $form->_params['source'] = $paymentParams['contribution_source'];
- }
-
- // get the price set values for receipt.
- if ($form->_priceSetId && $form->_lineItem) {
- $form->_values['lineItem'] = $form->_lineItem;
- $form->_values['priceSetID'] = $form->_priceSetId;
- }
-
- $form->_values['contribution_id'] = $contribution->id;
- $form->_values['contribution_page_id'] = $contribution->contribution_page_id;
-
- CRM_Contribute_BAO_ContributionPage::sendMail($contactID,
- $form->_values,
- $contribution->is_test
- );
- return;
- }
- }
+ $paymentParams['qfKey'] = $form->controller->_key;
+ if ($component == 'membership') {
+ return array('contribution' => $contribution);
}
- }
- elseif ($form->_contributeMode == 'express') {
- if ($form->_values['is_monetary'] && $form->_amount > 0.0) {
- // determine if express + recurring and direct accordingly
- if (!empty($paymentParams['is_recur']) && $paymentParams['is_recur'] == 1) {
- if (is_object($payment)) {
- $result = $payment->createRecurringPayments($paymentParams);
- }
- else {
- CRM_Core_Error::fatal($paymentObjError);
- }
- }
- else {
- if (is_object($payment)) {
- $result = $payment->doExpressCheckout($paymentParams);
- }
- else {
- CRM_Core_Error::fatal($paymentObjError);
- }
- }
- }
- }
- elseif ($isPaymentTransaction) {
- if (!empty($paymentParams['is_recur']) &&
- $form->_contributeMode == 'direct'
- ) {
-
- // For recurring contribution, create Contribution Record first.
- // Contribution ID, Recurring ID and Contact ID needed
- // When we get a callback from the payment processor
-
- $paymentParams['contactID'] = $contactID;
-
- // Fix for CRM-14354. If the membership is recurring, don't create a
- // civicrm_contribution_recur record for the additional contribution
- // (i.e., the amount NOT associated with the membership). Temporarily
- // cache the is_recur values so we can process the additional gift as a
- // one-off payment.
- $pending = FALSE;
- if (!empty($form->_values['is_recur'])) {
- if ($form->_membershipBlock['is_separate_payment'] && !empty($form->_params['auto_renew'])) {
- $cachedFormValue = CRM_Utils_Array::value('is_recur', $form->_values);
- $cachedParamValue = CRM_Utils_Array::value('is_recur', $paymentParams);
- unset($form->_values['is_recur']);
- unset($paymentParams['is_recur']);
- }
- else {
- $pending = TRUE;
- }
- }
- $contribution = CRM_Contribute_Form_Contribution_Confirm::processContribution(
- $form,
- $paymentParams,
- NULL,
- $contactID,
- $contributionType,
- $pending, TRUE,
- $isTest,
- $lineItems
- );
-
- // restore cached values (part of fix for CRM-14354)
- if (!empty($cachedFormValue)) {
- $form->_values['is_recur'] = $cachedFormValue;
- $paymentParams['is_recur'] = $cachedParamValue;
- }
-
- $paymentParams['contributionID'] = $contribution->id;
- //CRM-15297 deprecate contributionTypeID
- $paymentParams['financialTypeID'] = $paymentParams['contributionTypeID'] = $contribution->financial_type_id;
- $paymentParams['contributionPageID'] = $contribution->contribution_page_id;
-
- if ($form->_values['is_recur'] && $contribution->contribution_recur_id) {
- $paymentParams['contributionRecurID'] = $contribution->contribution_recur_id;
- }
- }
- if (is_object($payment)) {
- $result = $payment->doDirectPayment($paymentParams);
- }
- else {
- CRM_Core_Error::fatal($paymentObjError);
- }
- }
-
- if ($component == 'membership') {
- $membershipResult = array();
- }
-
- if (is_a($result, 'CRM_Core_Error')) {
- //make sure to cleanup db for recurring case.
- //@todo this clean up has always been controversial as many orgs prefer to see failed transactions.
- // most recent discussion has been that they should be retained and this could be altered
- if (!empty($paymentParams['contributionID'])) {
- CRM_Contribute_BAO_Contribution::deleteContribution($paymentParams['contributionID']);
- }
- if (!empty($paymentParams['contributionRecurID'])) {
- CRM_Contribute_BAO_ContributionRecur::deleteRecurContribution($paymentParams['contributionRecurID']);
- }
-
- if ($component !== 'membership') {
- CRM_Core_Error::displaySessionError($result);
- CRM_Utils_System::redirect(CRM_Utils_System::url('civicrm/contribute/transact',
- "_qf_Main_display=true&qfKey={$form->_params['qfKey']}"
- ));
- }
- $membershipResult[1] = $result;
- }
- elseif ($result || ($form->_amount == 0.0 && !$form->_params['is_pay_later'])) {
- if ($result) {
- $form->_params = array_merge($form->_params, $result);
- }
- $form->set('params', $form->_params);
- $form->assign('trxn_id', CRM_Utils_Array::value('trxn_id', $result));
-
- // result has all the stuff we need
- // lets archive it to a financial transaction
- //@todo - this is done in 2 places - can't we just do it once straight after retrieving contribution type -
- // when would this be a bad thing?
- if ($contributionType->is_deductible) {
- $form->assign('is_deductible', TRUE);
- $form->set('is_deductible', TRUE);
+ // restore cached values (part of fix for CRM-14354)
+ if (!empty($cachedFormValue)) {
+ $form->_values['is_recur'] = $cachedFormValue;
+ $paymentParams['is_recur'] = $cachedParamValue;
}
+ $paymentParams['contributionID'] = $contribution->id;
+ //CRM-15297 deprecate contributionTypeID
+ $paymentParams['financialTypeID'] = $paymentParams['contributionTypeID'] = $contribution->financial_type_id;
+ $paymentParams['contributionPageID'] = $contribution->contribution_page_id;
if (isset($paymentParams['contribution_source'])) {
- $form->_params['source'] = $paymentParams['contribution_source'];
+ $paymentParams['source'] = $paymentParams['contribution_source'];
}
- // check if pending was set to true by payment processor
- $pending = FALSE;
- if (!empty($form->_params['contribution_status_pending'])) {
- $pending = TRUE;
+ if ($form->_values['is_recur'] && $contribution->contribution_recur_id) {
+ $paymentParams['contributionRecurID'] = $contribution->contribution_recur_id;
}
- if (!(!empty($paymentParams['is_recur']) && $form->_contributeMode == 'direct')) {
- $contribution = CRM_Contribute_Form_Contribution_Confirm::processContribution($form,
- $form->_params, $result,
- $contactID, $contributionType,
- $pending, TRUE,
- $isTest,
- $lineItems
- );
- }
- $form->postProcessPremium($premiumParams, $contribution);
- if (is_array($result)) {
- if (!empty($result['trxn_id'])) {
- $contribution->trxn_id = $result['trxn_id'];
- }
- if (!empty($result['payment_status_id'])) {
- $contribution->payment_status_id = $result['payment_status_id'];
- }
- }
- $membershipResult[1] = $contribution;
- }
-
- if ($component == 'membership') {
- return $membershipResult;
- }
- // Email is done when the payment is completed (now or later)
- // by completetransaction, rather than the form.
- // We are moving towards it being done for all payment methods in completetransaction.
- if (!empty($paymentParams['is_recur']) && $form->_contributeMode == 'direct') {
- if (CRM_Utils_Array::value('payment_status_id', $result) == 1) {
+ if ($form->_contributeMode) {
try {
- civicrm_api3('contribution', 'completetransaction', array(
- 'id' => $contribution->id,
- 'trxn_id' => CRM_Utils_Array::value('trxn_id', $result),
- 'is_transactional' => FALSE,
- ));
+ $payment = Civi\Payment\System::singleton()->getByProcessor($form->_paymentProcessor);
+ if ($form->_contributeMode == 'notify') {
+ // We want to get rid of this & make it generic - eg. by making payment processing the last thing
+ // and always calling it first.
+ $form->postProcessHook();
+ }
+ $result = $payment->doPayment($paymentParams);
+ $form->_params = array_merge($form->_params, $result);
+ $form->assign('trxn_id', CRM_Utils_Array::value('trxn_id', $result));
+ if (!empty($result['trxn_id'])) {
+ $contribution->trxn_id = $result['trxn_id'];
+ }
+ if (!empty($result['payment_status_id'])) {
+ $contribution->payment_status_id = $result['payment_status_id'];
+ }
+ $result['contribution'] = $contribution;
+ return $result;
}
- catch (CiviCRM_API3_Exception $e) {
- if ($e->getErrorCode() != 'contribution_completed') {
- throw new CRM_Core_Exception('Failed to update contribution in database');
+ catch (\Civi\Payment\Exception\PaymentProcessorException $e) {
+ // Clean up DB as appropriate.
+ if (!empty($paymentParams['contributionID'])) {
+ CRM_Contribute_BAO_Contribution::failPayment($paymentParams['contributionID'],
+ $paymentParams['contactID'], $e->getMessage());
+ }
+ if (!empty($paymentParams['contributionRecurID'])) {
+ CRM_Contribute_BAO_ContributionRecur::deleteRecurContribution($paymentParams['contributionRecurID']);
}
+
+ $result['is_payment_failure'] = TRUE;
+ $result['error'] = $e;
+ return $result;
}
}
- return TRUE;
+ }
++
+ // Only pay later or unpaid should reach this point. The theory is that paylater should get a receipt now &
+ // processor
+ // transaction receipts should be outcome driven.
+ $form->set('params', $form->_params);
+ if (isset($paymentParams['contribution_source'])) {
+ $form->_params['source'] = $paymentParams['contribution_source'];
}
// get the price set values for receipt.