Skip to content

Commit

Permalink
Merge pull request #20294 from eileenmcnaughton/ppp
Browse files Browse the repository at this point in the history
[REF] Provide standardised methods to get recurring contribution id & object
  • Loading branch information
mattwire authored May 16, 2021
2 parents f9da2c1 + 55f6a00 commit 5d33fdd
Showing 1 changed file with 63 additions and 25 deletions.
88 changes: 63 additions & 25 deletions CRM/Core/Payment/PayPalProIPN.php
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,41 @@ class CRM_Core_Payment_PayPalProIPN extends CRM_Core_Payment_BaseIPN {
*/
protected $_isPaymentExpress = FALSE;

/**
* Recurring contribution ID.
*
* @var int|null
*/
protected $contributionRecurID;

/**
* Recurring contribution object.
*
* @var \CRM_Contribute_BAO_ContributionRecur
*/
protected $contributionRecurObject;

/**
* Get the recurring contribution ID, if any.
*
* @return int|null
*
* @throws \CRM_Core_Exception
*/
public function getContributionRecurID(): ?int {
if (!$this->contributionRecurID && $this->getValue('r', FALSE)) {
$this->contributionRecurID = (int) $this->getValue('r', FALSE);
}
return $this->contributionRecurID;
}

/**
* @param int|null $contributionRecurID
*/
public function setContributionRecurID(?int $contributionRecurID): void {
$this->contributionRecurID = $contributionRecurID;
}

/**
* Component.
*
Expand Down Expand Up @@ -219,7 +254,7 @@ public function recur($input, $ids, $recur, $contribution, $first) {
$recur->start_date = $now;
}
else {
if ($input['paymentStatus'] != 'Completed') {
if ($input['paymentStatus'] !== 'Completed') {
throw new CRM_Core_Exception("Ignore all IPN payments that are not completed");
}

Expand Down Expand Up @@ -389,12 +424,12 @@ public function getPayPalPaymentProcessorID() {
public function main() {
CRM_Core_Error::debug_var('GET', $_GET, TRUE, TRUE);
CRM_Core_Error::debug_var('POST', $_POST, TRUE, TRUE);
$ids = $input = [];
try {
if ($this->_isPaymentExpress) {
$this->handlePaymentExpress();
return;
}
$ids = $input = [];
$this->_component = $input['component'] = self::getValue('m');
$input['invoice'] = self::getValue('i', TRUE);
// get the contribution and contact ids from the GET params
Expand All @@ -406,14 +441,14 @@ public function main() {
if ($this->_component == 'event') {
$ids['event'] = self::getValue('e', TRUE);
$ids['participant'] = self::getValue('p', TRUE);
$ids['contributionRecur'] = self::getValue('r', FALSE);
$ids['contributionRecur'] = $this->getContributionRecurID();
}
else {
// get the optional ids
//@ how can this not be broken retrieving from GET as we are dealing with a POST request?
// copy & paste? Note the retrieve function now uses data from _REQUEST so this will be included
$ids['membership'] = self::retrieve('membershipID', 'Integer', 'GET', FALSE);
$ids['contributionRecur'] = self::getValue('r', FALSE);
$ids['contributionRecur'] = $this->getContributionRecurID();
$ids['contributionPage'] = self::getValue('p', FALSE);
$ids['related_contact'] = self::retrieve('relatedContactID', 'Integer', 'GET', FALSE);
$ids['onbehalf_dupe_alert'] = self::retrieve('onBehalfDupeAlert', 'Integer', 'GET', FALSE);
Expand Down Expand Up @@ -472,14 +507,8 @@ public function main() {

$input['payment_processor_id'] = $paymentProcessorID;

if ($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;
}
if ($this->getContributionRecurID()) {
$contributionRecur = $this->getContributionRecurObject();
// check if first contribution is completed, else complete first contribution
$first = TRUE;
$completedStatusId = CRM_Core_PseudoConstant::getKey('CRM_Contribute_BAO_Contribution', 'contribution_status_id', 'Completed');
Expand All @@ -496,7 +525,7 @@ public function main() {
], $contribution, FALSE, FALSE);
}
catch (CRM_Core_Exception $e) {
Civi::log()->debug($e->getMessage());
Civi::log()->debug($e->getMessage() . ' input {input}', ['input' => $input]);
echo 'Invalid or missing data';
}
}
Expand Down Expand Up @@ -569,6 +598,7 @@ public function handlePaymentExpress() {
'return' => 'contact_id, id, payment_processor_id',
'invoice_id' => $input['invoice'],
]);
$this->setContributionRecurID((int) $contributionRecur['id']);

if ($input['txnType'] !== 'recurring_payment' && $input['txnType'] !== 'recurring_payment_profile_created') {
throw new CRM_Core_Exception('Paypal IPNS not handled other than recurring_payments');
Expand All @@ -580,7 +610,7 @@ public function handlePaymentExpress() {
}

$ids['contact'] = $contributionRecur['contact_id'];
$ids['contributionRecur'] = $contributionRecur['id'];
$ids['contributionRecur'] = $this->getContributionRecurID();
$result = civicrm_api3('contribution', 'getsingle', ['invoice_id' => $input['invoice'], 'contribution_test' => '']);

$ids['contribution'] = $result['id'];
Expand Down Expand Up @@ -611,16 +641,6 @@ public function handlePaymentExpress() {
throw new CRM_Core_Exception('Failure: Could not find contribution record for ' . (int) $contribution->id, NULL, ['context' => "Could not find contribution record: {$contribution->id} in IPN request: " . print_r($input, TRUE)]);
}

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;
}
}

$objects['contribution'] = &$contribution;

// CRM-19478: handle oddity when p=null is set in place of contribution page ID,
Expand All @@ -635,7 +655,7 @@ public function handlePaymentExpress() {
$contribution->loadRelatedObjects($input, $ids);
$objects = array_merge($objects, $contribution->_relatedObjects);

$this->recur($input, $ids, $objects['contributionRecur'], $objects['contribution'], $isFirst);
$this->recur($input, $ids, $this->getContributionRecurObject(), $objects['contribution'], $isFirst);
}

/**
Expand All @@ -653,4 +673,22 @@ public function transactionExists($trxn_id) {
}
}

/**
* Get the recurring contribution object.
*
* @return \CRM_Contribute_BAO_ContributionRecur
* @throws \CRM_Core_Exception
*/
protected function getContributionRecurObject(): CRM_Contribute_BAO_ContributionRecur {
if (!$this->contributionRecurObject) {
$contributionRecur = new CRM_Contribute_BAO_ContributionRecur();
$contributionRecur->id = $this->getContributionRecurID();
if (!$contributionRecur->find(TRUE)) {
throw new CRM_Core_Exception('Failure: Could not find contribution recur record');
}
return $this->contributionRecurObject = $contributionRecur;
}
return $this->contributionRecurObject;
}

}

0 comments on commit 5d33fdd

Please sign in to comment.