X-Git-Url: https://vcs.fsf.org/?a=blobdiff_plain;f=CRM%2FCore%2FPayment%2FPayPalIPN.php;h=fa4f164a420f5b8798b214d847d3d4a59dbcb79d;hb=22cae9c16b7d4a67b02c64729a34efc1fad41760;hp=b058eb63f6c7e21aa6ce95bc1dac364904119d65;hpb=d28038514c58ae9423d85b2bb114a70f82b6117a;p=civicrm-core.git diff --git a/CRM/Core/Payment/PayPalIPN.php b/CRM/Core/Payment/PayPalIPN.php index b058eb63f6..fa4f164a42 100644 --- a/CRM/Core/Payment/PayPalIPN.php +++ b/CRM/Core/Payment/PayPalIPN.php @@ -223,17 +223,14 @@ class CRM_Core_Payment_PayPalIPN extends CRM_Core_Payment_BaseIPN { throw new CRM_Core_Exception("Ignore all IPN payments that are not completed"); } - $contribution->contact_id = $ids['contact']; - $contribution->financial_type_id = $objects['contributionType']->id; - $contribution->contribution_page_id = $ids['contributionPage']; - $contribution->contribution_recur_id = $ids['contributionRecur']; - $contribution->receive_date = $now; - $contribution->currency = $objects['contribution']->currency; - $contribution->payment_instrument_id = $objects['contribution']->payment_instrument_id; - $contribution->amount_level = $objects['contribution']->amount_level; - $contribution->campaign_id = $objects['contribution']->campaign_id; - - $objects['contribution'] = &$contribution; + // In future moving to create pending & then complete, but this OK for now. + // Also consider accepting 'Failed' like other processors. + $input['contribution_status_id'] = $contributionStatuses['Completed']; + $input['original_contribution_id'] = $ids['contribution']; + $input['contribution_recur_id'] = $ids['contributionRecur']; + + civicrm_api3('Contribution', 'repeattransaction', $input); + return; } $this->single($input, $ids, $objects, @@ -333,23 +330,12 @@ class CRM_Core_Payment_PayPalIPN extends CRM_Core_Payment_BaseIPN { $ids['onbehalf_dupe_alert'] = $this->retrieve('onBehalfDupeAlert', 'Integer', FALSE); } - $paymentProcessorID = $this->retrieve('processor_id', 'Integer', FALSE); - if (empty($paymentProcessorID)) { - $processorParams = array( - 'user_name' => $this->retrieve('business', 'String', FALSE), - 'payment_processor_type_id' => CRM_Core_DAO::getFieldValue('CRM_Financial_DAO_PaymentProcessorType', 'PayPal_Standard', 'id', 'name'), - 'is_test' => empty($input['is_test']) ? 0 : 1, - ); + $paymentProcessorID = self::getPayPalPaymentProcessorID($input, $ids); - $processorInfo = array(); - if (!CRM_Financial_BAO_PaymentProcessor::retrieve($processorParams, $processorInfo)) { - return FALSE; - } - $paymentProcessorID = $processorInfo['id']; - } + Civi::log()->debug('PayPalIPN: Received (ContactID: ' . $ids['contact'] . '; trxn_id: ' . $input['trxn_id'] . ').'); if (!$this->validateData($input, $ids, $objects, TRUE, $paymentProcessorID)) { - return FALSE; + return; } self::$_paymentProcessor = &$objects['paymentProcessor']; @@ -404,6 +390,64 @@ class CRM_Core_Payment_PayPalIPN extends CRM_Core_Payment_BaseIPN { $input['fee_amount'] = $this->retrieve('mc_fee', 'Money', FALSE); $input['net_amount'] = $this->retrieve('settle_amount', 'Money', FALSE); $input['trxn_id'] = $this->retrieve('txn_id', 'String', FALSE); + + $paymentDate = $this->retrieve('payment_date', 'String', FALSE); + if (!empty($paymentDate)) { + $receiveDateTime = new DateTime($paymentDate); + $input['receive_date'] = $receiveDateTime->format('YmdHis'); + } + } + + + /** + * Gets PaymentProcessorID for PayPal + * + * @param array $input + * @param array $ids + * + * @return int + * @throws \CRM_Core_Exception + * @throws \CiviCRM_API3_Exception + */ + public function getPayPalPaymentProcessorID($input, $ids) { + // First we try and retrieve from POST params + $paymentProcessorID = $this->retrieve('processor_id', 'Integer', FALSE); + if (!empty($paymentProcessorID)) { + return $paymentProcessorID; + } + + // Then we try and get it from recurring contribution ID + if (!empty($ids['contributionRecur'])) { + $contributionRecur = civicrm_api3('ContributionRecur', 'getsingle', array( + 'id' => $ids['contributionRecur'], + 'return' => ['payment_processor_id'], + )); + if (!empty($contributionRecur['payment_processor_id'])) { + return $contributionRecur['payment_processor_id']; + } + } + + // This is an unreliable method as there could be more than one instance. + // Recommended approach is to use the civicrm/payment/ipn/xx url where xx is the payment + // processor id & the handleNotification function (which should call the completetransaction api & by-pass this + // entirely). The only thing the IPN class should really do is extract data from the request, validate it + // & call completetransaction or call fail? (which may not exist yet). + + Civi::log()->warning('Unreliable method used to get payment_processor_id for PayPal IPN - this will cause problems if you have more than one instance'); + // Then we try and retrieve based on business email ID + $paymentProcessorTypeID = CRM_Core_DAO::getFieldValue('CRM_Financial_DAO_PaymentProcessorType', 'PayPal_Standard', 'id', 'name'); + $processorParams = [ + 'user_name' => $this->retrieve('business', 'String', FALSE), + 'payment_processor_type_id' => $paymentProcessorTypeID, + 'is_test' => empty($input['is_test']) ? 0 : 1, + 'options' => ['limit' => 1], + 'return' => ['id'], + ]; + $paymentProcessorID = civicrm_api3('PaymentProcessor', 'getvalue', $processorParams); + if (empty($paymentProcessorID)) { + Throw new CRM_Core_Exception('PayPalIPN: Could not get Payment Processor ID'); + } + return $paymentProcessorID; } }