}
/**
- * @param string $component
+ * Main IPN processing function.
*
* @return bool|void
+ *
+ * @throws \CiviCRM_API3_Exception
*/
- public function main($component = 'contribute') {
+ public function main() {
try {
//we only get invoice num as a key player from payment gateway response.
//for ARB we get x_subscription_id and x_subscription_paynum
}
$ids = $objects = $input = [];
- $input['component'] = $component;
+ $input['component'] = 'contribute';
// load post vars in $input
$this->getInput($input, $ids);
// load post ids in $ids
$this->getIDs($ids, $input);
-
- // Attempt to get payment processor ID from URL
- if (!empty($this->_inputParameters['processor_id'])) {
- $paymentProcessorID = $this->_inputParameters['processor_id'];
- }
- else {
- // 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 AuthNet IPN - this will cause problems if you have more than one instance');
- $paymentProcessorTypeID = CRM_Core_DAO::getFieldValue('CRM_Financial_DAO_PaymentProcessorType',
- 'AuthNet', 'id', 'name'
- );
- $paymentProcessorID = (int) civicrm_api3('PaymentProcessor', 'getvalue', [
- 'is_test' => 0,
- 'options' => ['limit' => 1],
- 'payment_processor_type_id' => $paymentProcessorTypeID,
- 'return' => 'id',
- ]);
- }
+ $paymentProcessorID = $this->getPaymentProcessorID();
// Check if the contribution exists
// make sure contribution exists and is valid
$ids['contact'] = $contribution->contact_id;
}
- if (!empty($ids['contributionRecur'])) {
- $contributionRecur = new CRM_Contribute_BAO_ContributionRecur();
- $contributionRecur->id = $ids['contributionRecur'];
- if (!$contributionRecur->find(TRUE)) {
- CRM_Core_Error::debug_log_message("Could not find contribution recur record: {$ids['ContributionRecur']} in IPN request: " . print_r($input, TRUE));
- echo "Failure: Could not find contribution recur record: {$ids['ContributionRecur']}<p>";
- return FALSE;
- }
+ $contributionRecur = new CRM_Contribute_BAO_ContributionRecur();
+ $contributionRecur->id = $ids['contributionRecur'];
+ if (!$contributionRecur->find(TRUE)) {
+ throw new CRM_Core_Exception("Could not find contribution recur record: {$ids['ContributionRecur']} in IPN request: " . print_r($input, TRUE));
}
$objects['contact'] = &$contact;
$this->loadObjects($input, $ids, $objects, TRUE, $paymentProcessorID);
- if (!empty($ids['paymentProcessor']) && $objects['contributionRecur']->payment_processor_id != $ids['paymentProcessor']) {
- Civi::log()->warning('Payment Processor does not match the recurring processor id.', ['civi.tag' => 'deprecated']);
+ // check if first contribution is completed, else complete first contribution
+ $first = TRUE;
+ if ($objects['contribution']->contribution_status_id == 1) {
+ $first = FALSE;
+ //load new contribution object if required.
+ // create a contribution and then get it processed
+ $contribution = new CRM_Contribute_BAO_Contribution();
+ $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 = $input['receive_date'];
+ $contribution->currency = $objects['contribution']->currency;
+ $contribution->amount_level = $objects['contribution']->amount_level;
+ $contribution->address_id = $objects['contribution']->address_id;
+ $contribution->campaign_id = $objects['contribution']->campaign_id;
+
+ $objects['contribution'] = &$contribution;
}
-
- if ($component == 'contribute' && $ids['contributionRecur']) {
- // check if first contribution is completed, else complete first contribution
- $first = TRUE;
- if ($objects['contribution']->contribution_status_id == 1) {
- $first = FALSE;
- //load new contribution object if required.
- // create a contribution and then get it processed
- $contribution = new CRM_Contribute_BAO_Contribution();
- $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 = $input['receive_date'];
- $contribution->currency = $objects['contribution']->currency;
- $contribution->amount_level = $objects['contribution']->amount_level;
- $contribution->address_id = $objects['contribution']->address_id;
- $contribution->campaign_id = $objects['contribution']->campaign_id;
- $contribution->_relatedObjects = $objects['contribution']->_relatedObjects;
-
- $objects['contribution'] = &$contribution;
- }
- $input['payment_processor_id'] = $paymentProcessorID;
- return $this->recur($input, [
- 'related_contact' => $ids['related_contact'] ?? NULL,
- 'participant' => !empty($objects['participant']) ? $objects['participant']->id : NULL,
- 'contributionRecur' => !empty($objects['contributionRecur']) ? $objects['contributionRecur']->id : NULL,
- 'contact' => $ids['contact'] ?? NULL,
- 'contributionPage' => $ids['contributionPage'] ?? NULL,
- ], $objects['contributionRecur'], $objects['contribution'], $first);
+ $input['payment_processor_id'] = $paymentProcessorID;
+ $isFirstOrLastRecurringPayment = $this->recur($input, [
+ 'related_contact' => $ids['related_contact'] ?? NULL,
+ 'participant' => !empty($objects['participant']) ? $objects['participant']->id : NULL,
+ 'contributionRecur' => $contributionRecur->id,
+ ], $contributionRecur, $objects['contribution'], $first);
+
+ if ($isFirstOrLastRecurringPayment) {
+ //send recurring Notification email for user
+ CRM_Contribute_BAO_ContributionPage::recurringNotify(TRUE,
+ $ids['contact'],
+ $ids['contributionPage'],
+ $contributionRecur,
+ (bool) $this->getMembershipID($contribution->id, $contributionRecur->id)
+ );
}
return TRUE;
// so we just fix the recurring contribution and not change any of
// the existing contributions
// CRM-9036
- return TRUE;
+ return FALSE;
}
// check if contribution is already completed, if so we ignore this ipn
if ($contribution->contribution_status_id == 1) {
CRM_Core_Error::debug_log_message("Returning since contribution has already been handled.");
echo 'Success: Contribution has already been handled<p>';
- return TRUE;
+ return FALSE;
}
CRM_Contribute_BAO_Contribution::completeOrder($input, $ids, $contribution);
-
- if ($isFirstOrLastRecurringPayment) {
- //send recurring Notification email for user
- CRM_Contribute_BAO_ContributionPage::recurringNotify(TRUE,
- $ids['contact'],
- $ids['contributionPage'],
- $recur,
- (bool) $this->getMembershipID($contribution->id, $recur->id)
- );
- }
+ return $isFirstOrLastRecurringPayment;
}
/**
return $contRecur;
}
+ /**
+ * Get the payment processor id.
+ *
+ * @return int
+ *
+ * @throws \CRM_Core_Exception
+ * @throws \CiviCRM_API3_Exception
+ */
+ protected function getPaymentProcessorID(): int {
+ // Attempt to get payment processor ID from URL
+ if (!empty($this->_inputParameters['processor_id'])) {
+ return (int) $this->_inputParameters['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 AuthNet IPN - this will cause problems if you have more than one instance');
+ $paymentProcessorTypeID = CRM_Core_DAO::getFieldValue('CRM_Financial_DAO_PaymentProcessorType',
+ 'AuthNet', 'id', 'name'
+ );
+ return (int) civicrm_api3('PaymentProcessor', 'getvalue', [
+ 'is_test' => 0,
+ 'options' => ['limit' => 1],
+ 'payment_processor_type_id' => $paymentProcessorTypeID,
+ 'return' => 'id',
+ ]);
+ }
+
}