}
}
}
- 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);
- }
+
+ elseif ($isPaymentTransaction && $form->_contributeMode) {
+ if ($form->_contributeMode == 'express' && !empty($paymentParams['is_recur']) && $paymentParams['is_recur'] == 1) {
+ if (is_object($payment)) {
+ $result = $payment->createRecurringPayments($paymentParams);
}
else {
- if (is_object($payment)) {
- $result = $payment->doExpressCheckout($paymentParams);
- }
- else {
- CRM_Core_Error::fatal($paymentObjError);
- }
+ CRM_Core_Error::fatal($paymentObjError);
}
}
- }
- elseif ($isPaymentTransaction) {
- if ($form->_contributeMode == 'direct') {
+ else {
$paymentParams['contactID'] = $contactID;
// Fix for CRM-14354. If the membership is recurring, don't create a
}
//Do not send an email if Recurring contribution is done via Direct Mode
//We will send email once the IPN is received.
- if ($form->_contributeMode == 'direct') {
+ if (!$isPayLater) {
return $result;
}
// generate and set an invoiceID for this transaction
$invoiceID = md5(uniqid(rand(), TRUE));
$this->set('invoiceID', $invoiceID);
+ $params['invoiceID'] = $invoiceID;
+ $params['description'] = ts('Online Contribution') . ': ' . (($this->_pcpInfo['title']) ? $this->_pcpInfo['title'] : $this->_values['title']);
// required only if is_monetary and valid positive amount
if ($this->_values['is_monetary'] &&
is_array($this->_paymentProcessor) &&
((float ) $params['amount'] > 0.0 || $memFee > 0.0)
) {
-
- // default mode is direct
- $this->set('contributeMode', 'direct');
+ $this->setContributeMode();
if ($this->_paymentProcessor &&
- $this->_paymentProcessor['billing_mode'] & CRM_Core_Payment::BILLING_MODE_BUTTON
+ $this->_paymentProcessor['object']->supportsPreApproval()
) {
- //get the button name
- $buttonName = $this->controller->getButtonName();
- if (in_array($buttonName,
- array($this->_expressButtonName, $this->_expressButtonName . '_x', $this->_expressButtonName . '_y')
- ) && empty($params['is_pay_later'])
- ) {
- $this->handlePaypalExpress($invoiceID, $params);
+ $this->handlePreApproval($params);
}
}
- elseif ($this->_paymentProcessor &&
- $this->_paymentProcessor['billing_mode'] & CRM_Core_Payment::BILLING_MODE_NOTIFY
- ) {
- $this->set('contributeMode', 'notify');
- }
- }
- // should we skip the confirm page?
if (empty($this->_values['is_confirm_enabled'])) {
- // call the post process hook for the main page before we switch to confirm
- $this->postProcessHook();
+ $this->skipToThankYouPage();
+ }
- // build the confirm page
- $confirmForm = &$this->controller->_pages['Confirm'];
- $confirmForm->preProcess();
- $confirmForm->buildQuickForm();
+ }
- // the confirmation page is valid
- $data = &$this->controller->container();
- $data['valid']['Confirm'] = 1;
+ /**
+ * Assign the billing mode to the template.
+ *
+ * This is required for legacy support for contributeMode in templates.
+ *
+ * The goal is to remove this parameter & use more relevant parameters.
+ */
+ protected function setContributeMode() {
+ switch ($this->_paymentProcessor['billing_mode']) {
+ case CRM_Core_Payment::BILLING_MODE_FORM:
+ $this->set('contributeMode', 'direct');
+ break;
- // confirm the contribution
- // mainProcess calls the hook also
- $confirmForm->mainProcess();
- $qfKey = $this->controller->_key;
+ case CRM_Core_Payment::BILLING_MODE_BUTTON:
+ $this->set('contributeMode', 'express');
+ break;
- // redirect to thank you page
- CRM_Utils_System::redirect(CRM_Utils_System::url('civicrm/contribute/transact', "_qf_ThankYou_display=1&qfKey=$qfKey", TRUE, NULL, FALSE));
+ case CRM_Core_Payment::BILLING_MODE_NOTIFY:
+ $this->set('contributeMode', 'notify');
+ break;
}
}
/**
- * @param $invoiceID
- * @param $params
+ * Handle pre approval for processors.
+ *
+ * This fits with the flow where a pre-approval is done and then confirmed in the next stage when confirm is hit.
*
- * @return mixed
+ * This applies to processors that
+ * @param array $params
*/
- protected function handlePaypalExpress($invoiceID, $params) {
- $this->set('contributeMode', 'express');
-
- $params['invoiceID'] = $invoiceID;
- $params['description'] = ts('Online Contribution') . ': ' . (($this->_pcpInfo['title']) ? $this->_pcpInfo['title'] : $this->_values['title']);
-
- $payment = Civi\Payment\System::singleton()->getByProcessor($this->_paymentProcessor);
- $token = $payment->setExpressCheckout($params);
- if (is_a($token, 'CRM_Core_Error')) {
- CRM_Core_Error::displaySessionError($token);
+ protected function handlePreApproval(&$params) {
+ try {
+ $payment = Civi\Payment\System::singleton()->getByProcessor($this->_paymentProcessor);
+ $result = $payment->doPreApproval($params);
+ }
+ catch (\Civi\Payment\Exception\PaymentProcessorException $e) {
+ CRM_Core_Error::displaySessionError($e->getMessage());
CRM_Utils_System::redirect($params['cancelURL']);
}
- $this->set('token', $token);
- $paymentURL = $this->_paymentProcessor['url_site'] . "/cgi-bin/webscr?cmd=_express-checkout&token=$token";
- CRM_Utils_System::redirect($paymentURL);
+ $this->set('pre_approval_parameters', $result['pre_approval_parameters']);
+ if (!empty($result['redirect_url'])) {
+ CRM_Utils_System::redirect($result['redirect_url']);
+ }
+ }
+
+ /**
+ * Process confirm function and pass browser to the thank you page.
+ */
+ protected function skipToThankYouPage() {
+ // call the post process hook for the main page before we switch to confirm
+ $this->postProcessHook();
+
+ // build the confirm page
+ $confirmForm = &$this->controller->_pages['Confirm'];
+ $confirmForm->preProcess();
+ $confirmForm->buildQuickForm();
+
+ // the confirmation page is valid
+ $data = &$this->controller->container();
+ $data['valid']['Confirm'] = 1;
+
+ // confirm the contribution
+ // mainProcess calls the hook also
+ $confirmForm->mainProcess();
+ $qfKey = $this->controller->_key;
+
+ // redirect to thank you page
+ CRM_Utils_System::redirect(CRM_Utils_System::url('civicrm/contribute/transact', "_qf_ThankYou_display=1&qfKey=$qfKey", TRUE, NULL, FALSE));
}
}
return FALSE;
}
+ /**
+ * Does this processor support pre-approval.
+ *
+ * This would generally look like a redirect to enter credentials which can then be used in a later payment call.
+ *
+ * Currently Paypal express supports this, with a redirect to paypal after the 'Main' form is submitted in the
+ * contribution page. This token can then be processed at the confirm phase. Although this flow 'looks' like the
+ * 'notify' flow a key difference is that in the notify flow they don't have to return but in this flow they do.
+ *
+ * @return bool
+ */
+ protected function supportsPreApproval() {
+ return FALSE;
+ }
+
+ /**
+ * Function to action pre-approval if supported
+ *
+ * @param array $params
+ * Parameters from the form
+ * @param string component
+ * contribution or event.
+ *
+ * This function returns an array which should contain
+ * - pre_approval_parameters (this will be stored on the calling form & available later)
+ * - redirect_url (if set the browser will be redirected to this.
+ */
+ protected function doPreApproval($params) {}
+
/**
* Default payment instrument validation.
*
* The function ensures an exception is thrown & moves some of this logic out of the form layer and makes the forms
* more agnostic.
*
- * Payment processors should set contribution_status_id. This function adds some historical defaults ie. the
+ * Payment processors should set payment_status_id. This function adds some historical defaults ie. the
* assumption that if a 'doDirectPayment' processors comes back it completed the transaction & in fact
* doTransferCheckout would not traditionally come back.
*
* doDirectPayment does not do an immediate payment for Authorize.net or Paypal so the default is assumed
* to be Pending.
*
+ * Once this function is fully rolled out then it will be preferred for processors to throw exceptions than to
+ * return Error objects
+ *
* @param array $params
*
* @param string $component
}
}
else {
- $result = $this->doDirectPayment($params, $component);
+ if ($this->_paymentProcessor['billing_mode'] ==1) {
+ $result = $this->doDirectPayment($params, $component);
+ }
+ else {
+ $result = $this->doExpressCheckout($params);
+ }
if (is_array($result) && !isset($result['payment_status_id'])) {
if (!empty($params['is_recur'])) {
// See comment block.
return FALSE;
}
+ /**
+ * Does this processor support pre-approval.
+ *
+ * This would generally look like a redirect to enter credentials which can then be used in a later payment call.
+ *
+ * Currently Paypal express supports this, with a redirect to paypal after the 'Main' form is submitted in the
+ * contribution page. This token can then be processed at the confirm phase. Although this flow 'looks' like the
+ * 'notify' flow a key difference is that in the notify flow they don't have to return but in this flow they do.
+ *
+ * @return bool
+ */
+ protected function supportsPreApproval() {
+ if ($this->_processorName == ts('PayPal_Express')) {
+ return TRUE;
+ }
+ return FALSE;
+ }
+
/**
* Opportunity for the payment processor to override the entire form build.
*
return FALSE;
}
+ /**
+ * Function to action pre-approval if supported
+ *
+ * @param array $params
+ * Parameters from the form
+ *
+ * @return array
+ * - pre_approval_parameters (this will be stored on the calling form & available later)
+ * - redirect_url (if set the browser will be redirected to this.
+ */
+ public function doPreApproval(&$params) {
+ $token = $this->setExpressCheckOut($params);
+ return array(
+ 'pre_approval_parameters' => array('token' => $token),
+ 'redirect_url' => $this->_paymentProcessor['url_site'] . "/cgi-bin/webscr?cmd=_express-checkout&token=$token",
+ );
+ }
+
/**
* @param array $params
* @param string $component