From 0421cfd7a58ace83eafc9cddda761178bc5db263 Mon Sep 17 00:00:00 2001 From: Matthew Wire <mjw@mjwconsult.co.uk> Date: Thu, 23 Jun 2022 19:49:46 +0100 Subject: [PATCH] Improve handling of already canceled payment intents --- api/v3/Job/ProcessStripe.php | 18 ++++++++++++++---- 1 file changed, 14 insertions(+), 4 deletions(-) diff --git a/api/v3/Job/ProcessStripe.php b/api/v3/Job/ProcessStripe.php index 96405f3b..5188aed2 100644 --- a/api/v3/Job/ProcessStripe.php +++ b/api/v3/Job/ProcessStripe.php @@ -43,8 +43,11 @@ function civicrm_api3_job_process_stripe($params) { $incompletePaymentintents = StripePaymentintent::get(FALSE) ->addWhere('status', 'NOT IN', ['succeeded', 'cancelled', 'canceled', 'failed']) ->addWhere('created_date', '<', $params['cancel_incomplete']) - ->addWhere('stripe_intent_id', 'IS NOT EMPTY') - ->execute(); + ->addWhere('stripe_intent_id', 'IS NOT EMPTY'); + if (!empty($params['stripe_paymentintent_id'])) { + $incompletePaymentintents->addWhere('id', '=', $params['stripe_paymentintent_id']); + } + $incompletePaymentintents = $incompletePaymentintents->execute(); $cancelledIDs = []; foreach ($incompletePaymentintents as $incompletePaymentintent) { @@ -52,7 +55,10 @@ function civicrm_api3_job_process_stripe($params) { /** @var \CRM_Core_Payment_Stripe $paymentProcessor */ $paymentProcessor = Civi\Payment\System::singleton()->getById($incompletePaymentintent['payment_processor_id']); $intent = $paymentProcessor->stripeClient->paymentIntents->retrieve($incompletePaymentintent['stripe_intent_id']); - $intent->cancel(['cancellation_reason' => 'abandoned']); + // Check intent was not already cancelled - this could happen eg. at Stripe before we process it + if ($intent->status !== 'canceled') { + $intent->cancel(['cancellation_reason' => 'abandoned']); + } $cancelledIDs[] = $incompletePaymentintent['id']; } catch (Exception $e) { if ($e instanceof \Stripe\Exception\InvalidRequestException) { @@ -62,7 +68,7 @@ function civicrm_api3_job_process_stripe($params) { $cancelledIDs[] = $incompletePaymentintent['id']; } } - \Civi::log()->error('Stripe.process_stripe: Unable to cancel paymentIntent. ' . $e->getMessage()); + \Civi::log()->error("Stripe.process_stripe: Unable to cancel paymentIntentID: {$incompletePaymentintent['id']}: " . $e->getMessage()); } } if (!empty($cancelledIDs)) { @@ -89,4 +95,8 @@ function _civicrm_api3_job_process_stripe_spec(&$params) { $params['cancel_incomplete']['api.default'] = '-1 hour'; $params['cancel_incomplete']['title'] = 'Cancel incomplete records after (default: -1hour)'; $params['cancel_incomplete']['description'] = 'Cancel incomplete paymentIntents in your stripe account. Specify 0 to disable. Default is "-1hour"'; + $params['stripe_paymentintent_id']['title'] = 'ID of record from civicrm_stripe_paymentintent table'; + $params['stripe_paymentintent_id']['description'] = 'If specified, only this record will be processed'; + $params['stripe_paymentintent_id']['type'] = CRM_Utils_Type::T_INT; + } -- GitLab