Commit 830aecd6 authored by mattwire's avatar mattwire
Browse files

Update Job.process_stripe to use API4 and clarify that it is NOT domain-specific

parent 26a213de
......@@ -6,7 +6,7 @@
*
* Generated from com.drastikbydesign.stripe/xml/schema/CRM/Stripe/StripePaymentintent.xml
* DO NOT EDIT. Generated by CRM_Core_CodeGen
* (GenCodeChecksum:36236d3e889b48e3fe6a961f193d0af7)
* (GenCodeChecksum:879fe95dcb092ea9b7a6e7df9ed17657)
*/
use CRM_Stripe_ExtensionUtil as E;
......@@ -167,6 +167,7 @@ class CRM_Stripe_DAO_StripePaymentintent extends CRM_Core_DAO {
'entity' => 'StripePaymentintent',
'bao' => 'CRM_Stripe_DAO_StripePaymentintent',
'localizable' => 0,
'readonly' => TRUE,
'add' => NULL,
],
'stripe_intent_id' => [
......
<?php
namespace Civi\Api4;
/**
* StripePaymentintent entity.
*
* Provided by the Stripe extension
*
* @package Civi\Api4
*/
class StripePaymentintent extends Generic\DAOEntity {
}
......@@ -9,8 +9,11 @@
+--------------------------------------------------------------------+
*/
use Civi\Api4\StripePaymentintent;
/**
* This job performs various housekeeping actions related to the Stripe payment processor
* NOT domain-specific. On multidomain only run on one domain.
*
* @param array $params
*
......@@ -19,42 +22,55 @@
* @throws CiviCRM_API3_Exception
*/
function civicrm_api3_job_process_stripe($params) {
$results = [];
// Note: "canceled" is the status from Stripe, we used to record "cancelled" so we check for both
$results = [
'deleted' => 0,
'canceled' => 0,
];
if ($params['delete_old'] !== 0 && !empty($params['delete_old'])) {
// Delete all locally recorded paymentIntents that are older than 3 months
$oldPaymentIntents = civicrm_api3('StripePaymentintent', 'get', [
'status' => ['IN' => ['succeeded', 'cancelled', 'canceled', 'failed']],
'created_date' => ['<' => $params['delete_old']],
]);
foreach ($oldPaymentIntents['values'] as $id => $detail) {
civicrm_api3('StripePaymentintent', 'delete', ['id' => $id]);
$results['deleted'][$id] = $detail['stripe_intent_id'];
}
$oldPaymentintents = StripePaymentintent::delete(FALSE)
->addWhere('status', 'IN', ['succeeded', 'cancelled', 'canceled', 'failed'])
->addWhere('created_date', '<', '-3 month')
->execute();
$results['deleted'] = $oldPaymentintents->count();
}
if ($params['cancel_incomplete'] !== 0 && !empty($params['cancel_incomplete'])) {
// Cancel incomplete paymentIntents after 1 hour
$incompletePaymentIntents = civicrm_api3('StripePaymentintent', 'get', [
'status' => ['NOT IN' => ['succeeded', 'cancelled', 'canceled']],
'created_date' => ['<' => $params['cancel_incomplete']],
]);
foreach ($incompletePaymentIntents['values'] as $id => $detail) {
$incompletePaymentintents = StripePaymentintent::get(FALSE)
->addWhere('status', 'NOT IN', ['succeeded', 'cancelled', 'canceled'])
->addWhere('created_date', '<', $params['cancel_incomplete'])
->execute();
$cancelledIDs = [];
foreach ($incompletePaymentintents as $incompletePaymentintent) {
try {
/** @var \CRM_Core_Payment_Stripe $paymentProcessor */
$paymentProcessor = Civi\Payment\System::singleton()->getById($detail['payment_processor_id']);
$intent = $paymentProcessor->stripeClient->paymentIntents->retrieve($detail['stripe_intent_id']);
$paymentProcessor = Civi\Payment\System::singleton()->getById($incompletePaymentintent['payment_processor_id']);
$intent = $paymentProcessor->stripeClient->paymentIntents->retrieve($incompletePaymentintent['stripe_intent_id']);
$intent->cancel(['cancellation_reason' => 'abandoned']);
$cancelledIDs[] = $incompletePaymentintent['id'];
} catch (Exception $e) {
if ($e instanceof \Stripe\Exception\InvalidRequestException) {
// 404 resource_missing (paymentIntent not found at Stripe)
// 400 bad_request (paymentIntent is already in canceled state?)
if (in_array($e->getHttpStatus(), [400, 404])) {
$cancelledIDs[] = $incompletePaymentintent['id'];
}
}
\Civi::log()->error('Stripe.process_stripe: Unable to cancel paymentIntent. ' . $e->getMessage());
}
civicrm_api3('StripePaymentintent', 'create', [
'id' => $id,
'status' => 'canceled'
]);
$results['cancelled'][$id] = $detail['stripe_intent_id'];
}
if (!empty($cancelledIDs)) {
StripePaymentintent::update(FALSE)
->addValue('status', 'canceled')
->addWhere('id', 'IN', $cancelledIDs)
->execute();
}
$results['canceled'] = count($cancelledIDs);
}
return civicrm_api3_create_success($results, $params);
......
# Setup and configuration
Please make sure you have read and followed the instructions under [Install](install.md) first.
## Scheduled Jobs
### Job.process_stripe
This job automatically cancels abandoned (uncaptured) paymentIntents after 1 hour and cleans up old records in the `civicrm_stripe_paymentintent` table.
* Run: Hourly
* Domain-specific: No. This job only needs to be run on one of the domains for multisite/multidomain setup.
If this job is *not* running then the abandoned payments will show on the clients card for up to one week.
## Receipts
In addition to the receipts that CiviCRM can send, Stripe will send it's own receipt for payment by default.
......@@ -8,7 +19,3 @@ In addition to the receipts that CiviCRM can send, Stripe will send it's own rec
If you wish to disable this under *Administer->CiviContribute->Stripe Settings* you can find a setting that allows you to disable Stripe from sending receipts:
* Allow Stripe to send a receipt for one-off payments?
## Cancelling abandoned payment attempts
A scheduled job (Job.process_stripe) automatically cancels abandoned (uncaptured) paymentIntents after 24 hours.
......@@ -31,4 +31,7 @@
<civix>
<namespace>CRM/Stripe</namespace>
</civix>
<classloader>
<psr4 prefix="Civi\" path="Civi"/>
</classloader>
</extension>
......@@ -8,15 +8,14 @@
--
-- Generated from drop.tpl
-- DO NOT EDIT. Generated by CRM_Core_CodeGen
--
-- /*******************************************************
-- *
-- * Clean up the existing tables
---- /*******************************************************
-- *
-- * Clean up the existing tables-- *
-- *******************************************************/
SET FOREIGN_KEY_CHECKS=0;
DROP TABLE IF EXISTS `civicrm_stripe_paymentintent`;
DROP TABLE IF EXISTS `civicrm_stripe_customers`;
SET FOREIGN_KEY_CHECKS=1;
\ No newline at end of file
SET FOREIGN_KEY_CHECKS=1;
......@@ -221,7 +221,8 @@ function _stripe_civix_upgrader() {
* Search directory tree for files which match a glob pattern.
*
* Note: Dot-directories (like "..", ".git", or ".svn") will be ignored.
* Note: In Civi 4.3+, delegate to CRM_Utils_File::findFiles()
* Note: Delegate to CRM_Utils_File::findFiles(), this function kept only
* for backward compatibility of extension code that uses it.
*
* @param string $dir base dir
* @param string $pattern , glob pattern, eg "*.txt"
......@@ -229,32 +230,7 @@ function _stripe_civix_upgrader() {
* @return array
*/
function _stripe_civix_find_files($dir, $pattern) {
if (is_callable(['CRM_Utils_File', 'findFiles'])) {
return CRM_Utils_File::findFiles($dir, $pattern);
}
$todos = [$dir];
$result = [];
while (!empty($todos)) {
$subdir = array_shift($todos);
foreach (_stripe_civix_glob("$subdir/$pattern") as $match) {
if (!is_dir($match)) {
$result[] = $match;
}
}
if ($dh = opendir($subdir)) {
while (FALSE !== ($entry = readdir($dh))) {
$path = $subdir . DIRECTORY_SEPARATOR . $entry;
if ($entry[0] == '.') {
}
elseif (is_dir($path)) {
$todos[] = $path;
}
}
closedir($dh);
}
}
return $result;
return CRM_Utils_File::findFiles($dir, $pattern);
}
/**
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment