diff --git a/CRM/Core/Payment/PayPalImpl.php b/CRM/Core/Payment/PayPalImpl.php index 3fde78c1bbfd..99c25654651d 100644 --- a/CRM/Core/Payment/PayPalImpl.php +++ b/CRM/Core/Payment/PayPalImpl.php @@ -39,6 +39,10 @@ class CRM_Core_Payment_PayPalImpl extends CRM_Core_Payment { const CHARSET = 'iso-8859-1'; + const PAYPAL_PRO = 'PayPal'; + const PAYPAL_STANDARD = 'PayPal_Standard'; + const PAYPAL_EXPRESS = 'PayPal_Express'; + protected $_mode = NULL; /** @@ -50,21 +54,50 @@ class CRM_Core_Payment_PayPalImpl extends CRM_Core_Payment { * @param CRM_Core_Payment $paymentProcessor * * @return \CRM_Core_Payment_PayPalImpl + * @throws \Civi\Payment\Exception\PaymentProcessorException */ public function __construct($mode, &$paymentProcessor) { $this->_mode = $mode; $this->_paymentProcessor = $paymentProcessor; - $this->_processorName = ts('PayPal Pro'); - $paymentProcessorType = CRM_Core_PseudoConstant::paymentProcessorType(FALSE, NULL, 'name'); - if ($this->_paymentProcessor['payment_processor_type_id'] == CRM_Utils_Array::key('PayPal_Standard', $paymentProcessorType)) { + if ($this->isPayPalType($this::PAYPAL_STANDARD)) { $this->_processorName = ts('PayPal Standard'); - return; } - elseif ($this->_paymentProcessor['payment_processor_type_id'] == CRM_Utils_Array::key('PayPal_Express', $paymentProcessorType)) { + elseif ($this->isPayPalType($this::PAYPAL_EXPRESS)) { $this->_processorName = ts('PayPal Express'); } + elseif ($this->isPayPalType($this::PAYPAL_PRO)) { + $this->_processorName = ts('PayPal Pro'); + } + else { + throw new PaymentProcessorException('CRM_Core_Payment_PayPalImpl: Payment processor type is not defined!'); + } + } + /** + * Helper function to check which payment processor type is being used. + * + * @param $typeName + * + * @return bool + * @throws \Civi\Payment\Exception\PaymentProcessorException + */ + public function isPayPalType($typeName) { + // Historically payment_processor_type may have been set to the name of the processor but newer versions of CiviCRM use the id set in payment_processor_type_id + if (empty($this->_paymentProcessor['payment_processor_type_id']) && empty($this->_paymentProcessor['payment_processor_type'])) { + // We need one of them to be set! + throw new PaymentProcessorException('CRM_Core_Payment_PayPalImpl: Payment processor type is not defined!'); + } + if (empty($this->_paymentProcessor['payment_processor_type_id']) && !empty($this->_paymentProcessor['payment_processor_type'])) { + // Handle legacy case where payment_processor_type was set, but payment_processor_type_id was not. + $this->_paymentProcessor['payment_processor_type_id'] + = CRM_Core_PseudoConstant::getKey('CRM_Financial_BAO_PaymentProcessor', 'payment_processor_type_id', $this->_paymentProcessor['payment_processor_type']); + } + if ((int) $this->_paymentProcessor['payment_processor_type_id'] === + CRM_Core_PseudoConstant::getKey('CRM_Financial_BAO_PaymentProcessor', 'payment_processor_type_id', $typeName)) { + return TRUE; + } + return FALSE; } /** @@ -74,6 +107,7 @@ public function __construct($mode, &$paymentProcessor) { * with someone else's login. * * @return bool + * @throws \Civi\Payment\Exception\PaymentProcessorException */ protected function supportsBackOffice() { if ($this->_processorName == ts('PayPal Pro')) { @@ -92,6 +126,7 @@ protected function supportsBackOffice() { * '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 + * @throws \Civi\Payment\Exception\PaymentProcessorException */ protected function supportsPreApproval() { if ($this->_processorName == ts('PayPal Express') || $this->_processorName == ts('PayPal Pro')) { @@ -107,6 +142,7 @@ protected function supportsPreApproval() { * * @return bool * Should form building stop at this point? + * @throws \Civi\Payment\Exception\PaymentProcessorException */ public function buildForm(&$form) { if ($this->supportsPreApproval()) { @@ -186,6 +222,8 @@ protected function supportsRecurContributionsForPledges() { * * @param array $values * @param array $errors + * + * @throws \Civi\Payment\Exception\PaymentProcessorException */ public function validatePaymentInstrument($values, &$errors) { if ($this->_paymentProcessor['payment_processor_type'] == 'PayPal' && !$this->isPaypalExpress($values)) { @@ -251,6 +289,7 @@ protected function setExpressCheckOut(&$params) { * @param array $storedDetails * * @return array + * @throws \Civi\Payment\Exception\PaymentProcessorException */ public function getPreApprovalDetails($storedDetails) { return empty($storedDetails['token']) ? array() : $this->getExpressCheckoutDetails($storedDetails['token']); @@ -266,6 +305,7 @@ public function getPreApprovalDetails($storedDetails) { * * @return array * the result in an nice formatted array (or an error object) + * @throws \Civi\Payment\Exception\PaymentProcessorException */ public function getExpressCheckoutDetails($token) { $args = array(); @@ -362,9 +402,13 @@ public function doExpressCheckout(&$params) { /** * Create recurring payments. * + * Use a pre-authorisation token to activate a recurring payment profile + * https://developer.paypal.com/docs/classic/api/merchant/CreateRecurringPaymentsProfile_API_Operation_NVP/ + * * @param array $params * * @return mixed + * @throws \Exception */ public function createRecurringPayments(&$params) { $args = array(); @@ -481,6 +525,7 @@ public function doPayment(&$params, $component = 'contribute') { * @param string $component * @return array * the result in an nice formatted array (or an error object) + * @throws \Civi\Payment\Exception\PaymentProcessorException */ public function doDirectPayment(&$params, $component = 'contribute') { $args = array(); @@ -538,7 +583,7 @@ public function doDirectPayment(&$params, $component = 'contribute') { $result = $this->invokeAPI($args); - //WAG + // WAG if (is_a($result, 'CRM_Core_Error')) { return $result; } @@ -597,8 +642,9 @@ public function doQuery($params) { /** * This function checks to see if we have the right config values. * - * @return string + * @return null|string * the error message if any + * @throws \Civi\Payment\Exception\PaymentProcessorException */ public function checkConfig() { $error = array(); @@ -627,6 +673,7 @@ public function checkConfig() { /** * @return null|string + * @throws \Civi\Payment\Exception\PaymentProcessorException */ public function cancelSubscriptionURL() { if ($this->_paymentProcessor['payment_processor_type'] == 'PayPal_Standard') { @@ -737,6 +784,7 @@ static public function handlePaymentNotification() { * @param array $params * * @return array|bool|object + * @throws \Civi\Payment\Exception\PaymentProcessorException */ public function updateSubscriptionBillingInfo(&$message = '', $params = array()) { if ($this->_paymentProcessor['payment_processor_type'] == 'PayPal') { @@ -807,6 +855,7 @@ public function changeSubscriptionAmount(&$message = '', $params = array()) { * @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. + * @throws \Civi\Payment\Exception\PaymentProcessorException */ public function doPreApproval(&$params) { if (!$this->isPaypalExpress($params)) { @@ -1125,6 +1174,7 @@ protected function mapPaypalParamsToCivicrmParams($fieldMap, $paypalParams) { * @param array $params * * @return bool + * @throws \Civi\Payment\Exception\PaymentProcessorException */ protected function isPaypalExpress($params) { if ($this->_processorName == ts('PayPal Express')) {