handling changes to stripe account where owner needs to provide information
This commit is contained in:
@@ -16,19 +16,23 @@ class StripeWebhookService {
|
||||
|
||||
/**
|
||||
* Handle account.updated webhook event.
|
||||
* Triggers payouts for owner when payouts_enabled becomes true.
|
||||
* Tracks requirements, triggers payouts when enabled, and notifies when disabled.
|
||||
* @param {Object} account - The Stripe account object from the webhook
|
||||
* @returns {Object} - { processed, payoutsTriggered, payoutResults }
|
||||
* @returns {Object} - { processed, payoutsTriggered, payoutResults, notificationSent }
|
||||
*/
|
||||
static async handleAccountUpdated(account) {
|
||||
const accountId = account.id;
|
||||
const payoutsEnabled = account.payouts_enabled;
|
||||
const requirements = account.requirements || {};
|
||||
|
||||
logger.info("Processing account.updated webhook", {
|
||||
accountId,
|
||||
payoutsEnabled,
|
||||
chargesEnabled: account.charges_enabled,
|
||||
detailsSubmitted: account.details_submitted,
|
||||
currentlyDue: requirements.currently_due?.length || 0,
|
||||
pastDue: requirements.past_due?.length || 0,
|
||||
disabledReason: requirements.disabled_reason,
|
||||
});
|
||||
|
||||
// Find user with this Stripe account
|
||||
@@ -41,18 +45,33 @@ class StripeWebhookService {
|
||||
return { processed: false, reason: "user_not_found" };
|
||||
}
|
||||
|
||||
// Store previous state before update
|
||||
const previousPayoutsEnabled = user.stripePayoutsEnabled;
|
||||
|
||||
// Update user's payouts_enabled status
|
||||
await user.update({ stripePayoutsEnabled: payoutsEnabled });
|
||||
// Update user with all account status fields
|
||||
await user.update({
|
||||
stripePayoutsEnabled: payoutsEnabled,
|
||||
stripeRequirementsCurrentlyDue: requirements.currently_due || [],
|
||||
stripeRequirementsPastDue: requirements.past_due || [],
|
||||
stripeDisabledReason: requirements.disabled_reason || null,
|
||||
stripeRequirementsLastUpdated: new Date(),
|
||||
});
|
||||
|
||||
logger.info("Updated user stripePayoutsEnabled", {
|
||||
logger.info("Updated user Stripe account status", {
|
||||
userId: user.id,
|
||||
accountId,
|
||||
previousPayoutsEnabled,
|
||||
newPayoutsEnabled: payoutsEnabled,
|
||||
currentlyDue: requirements.currently_due?.length || 0,
|
||||
pastDue: requirements.past_due?.length || 0,
|
||||
});
|
||||
|
||||
const result = {
|
||||
processed: true,
|
||||
payoutsTriggered: false,
|
||||
notificationSent: false,
|
||||
};
|
||||
|
||||
// If payouts just became enabled (false -> true), process pending payouts
|
||||
if (payoutsEnabled && !previousPayoutsEnabled) {
|
||||
logger.info("Payouts enabled for user, processing pending payouts", {
|
||||
@@ -60,15 +79,69 @@ class StripeWebhookService {
|
||||
accountId,
|
||||
});
|
||||
|
||||
const result = await this.processPayoutsForOwner(user.id);
|
||||
return {
|
||||
processed: true,
|
||||
payoutsTriggered: true,
|
||||
payoutResults: result,
|
||||
};
|
||||
result.payoutsTriggered = true;
|
||||
result.payoutResults = await this.processPayoutsForOwner(user.id);
|
||||
}
|
||||
|
||||
return { processed: true, payoutsTriggered: false };
|
||||
// If payouts just became disabled (true -> false), notify the owner
|
||||
if (!payoutsEnabled && previousPayoutsEnabled) {
|
||||
logger.warn("Payouts disabled for user", {
|
||||
userId: user.id,
|
||||
accountId,
|
||||
disabledReason: requirements.disabled_reason,
|
||||
currentlyDue: requirements.currently_due,
|
||||
});
|
||||
|
||||
try {
|
||||
const disabledReason = this.formatDisabledReason(requirements.disabled_reason);
|
||||
|
||||
await emailServices.payment.sendPayoutsDisabledEmail(user.email, {
|
||||
ownerName: user.firstName || user.name,
|
||||
disabledReason,
|
||||
});
|
||||
|
||||
result.notificationSent = true;
|
||||
|
||||
logger.info("Sent payouts disabled notification to owner", {
|
||||
userId: user.id,
|
||||
accountId,
|
||||
disabledReason: requirements.disabled_reason,
|
||||
});
|
||||
} catch (emailError) {
|
||||
logger.error("Failed to send payouts disabled notification", {
|
||||
userId: user.id,
|
||||
accountId,
|
||||
error: emailError.message,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Format Stripe disabled_reason code to user-friendly message.
|
||||
* @param {string} reason - Stripe disabled_reason code
|
||||
* @returns {string} User-friendly message
|
||||
*/
|
||||
static formatDisabledReason(reason) {
|
||||
const reasonMap = {
|
||||
"requirements.past_due":
|
||||
"Some required information is past due and must be provided to continue receiving payouts.",
|
||||
"requirements.pending_verification":
|
||||
"Your submitted information is being verified. This usually takes a few minutes.",
|
||||
listed: "Your account has been listed for review due to potential policy concerns.",
|
||||
platform_paused:
|
||||
"Payouts have been temporarily paused by the platform.",
|
||||
rejected_fraud: "Your account was flagged for potential fraudulent activity.",
|
||||
rejected_listed: "Your account has been rejected due to policy concerns.",
|
||||
rejected_terms_of_service:
|
||||
"Your account was rejected due to a terms of service violation.",
|
||||
rejected_other: "Your account was rejected. Please contact support for more information.",
|
||||
under_review: "Your account is under review. We'll notify you when the review is complete.",
|
||||
};
|
||||
|
||||
return reasonMap[reason] || "Additional verification is required for your account.";
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -444,6 +517,10 @@ class StripeWebhookService {
|
||||
await user.update({
|
||||
stripeConnectedAccountId: null,
|
||||
stripePayoutsEnabled: false,
|
||||
stripeRequirementsCurrentlyDue: [],
|
||||
stripeRequirementsPastDue: [],
|
||||
stripeDisabledReason: null,
|
||||
stripeRequirementsLastUpdated: null,
|
||||
});
|
||||
|
||||
logger.info("Cleared Stripe connection for deauthorized account", {
|
||||
|
||||
Reference in New Issue
Block a user