fix: resolve subscription ID lookup and checkout URL issues
- Fix getBaseUrl() ReferenceError by changing to resolveBaseUrl(req) for free-to-paid upgrades - Add subscription lookup by customer email when dodoSubscriptionId is missing - Log critical issues when paid users have no subscription ID in database or Dodo - Return clear error message to contact support when subscription cannot be found - Prevent silent failures in plan changes from settings page
This commit is contained in:
@@ -2247,7 +2247,7 @@
|
||||
}
|
||||
|
||||
const tourSteps = [
|
||||
{ target: null, color: '#008060' },
|
||||
{ target: '#apps-content', color: '#008060' },
|
||||
{ target: '#create-new-app', color: '#5A31F4' },
|
||||
{ target: '#upload-app-btn', color: '#F59E0B' },
|
||||
{ target: '#browse-templates-btn', color: '#10B981' },
|
||||
|
||||
@@ -12115,6 +12115,62 @@ async function handleAccountSettingsUpdate(req, res) {
|
||||
const isPaidToPaid = PAID_PLANS.has(user.plan) && PAID_PLANS.has(requestedPlan);
|
||||
const isFreeToPaid = user.plan === 'hobby' && PAID_PLANS.has(requestedPlan);
|
||||
|
||||
// Helper function to lookup subscription by customer
|
||||
async function lookupSubscriptionByCustomer(user) {
|
||||
try {
|
||||
const customerId = await ensureDodoCustomer(user);
|
||||
if (!customerId) return null;
|
||||
|
||||
const subscriptions = await dodoRequest('/subscriptions', {
|
||||
method: 'GET',
|
||||
query: { customer_id: customerId, status: 'active' }
|
||||
});
|
||||
|
||||
if (subscriptions?.items && subscriptions.items.length > 0) {
|
||||
const activeSub = subscriptions.items[0];
|
||||
log('Found missing subscription ID via Dodo lookup', {
|
||||
userId: user.id,
|
||||
email: user.email,
|
||||
subscriptionId: activeSub.subscription_id || activeSub.id,
|
||||
customerId
|
||||
});
|
||||
return activeSub.subscription_id || activeSub.id;
|
||||
}
|
||||
return null;
|
||||
} catch (error) {
|
||||
log('Failed to lookup subscription by customer', {
|
||||
userId: user.id,
|
||||
email: user.email,
|
||||
error: String(error)
|
||||
});
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
// If paid user is missing dodoSubscriptionId, try to look it up
|
||||
if ((isPaidToFree || isPaidToPaid) && !user.dodoSubscriptionId && PAID_PLANS.has(user.plan)) {
|
||||
const foundSubscriptionId = await lookupSubscriptionByCustomer(user);
|
||||
if (foundSubscriptionId) {
|
||||
user.dodoSubscriptionId = foundSubscriptionId;
|
||||
await persistUsersDb();
|
||||
log('Recovered missing subscription ID', {
|
||||
userId: user.id,
|
||||
email: user.email,
|
||||
subscriptionId: foundSubscriptionId
|
||||
});
|
||||
} else {
|
||||
// Log the issue for investigation
|
||||
log('CRITICAL: Paid user missing dodoSubscriptionId and no active subscription found in Dodo', {
|
||||
userId: user.id,
|
||||
email: user.email,
|
||||
currentPlan: user.plan,
|
||||
requestedPlan: requestedPlan,
|
||||
billingStatus: user.billingStatus,
|
||||
subscriptionRenewsAt: user.subscriptionRenewsAt
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
// Schedule cancellation at period end when changing from paid to free hobby plan
|
||||
// User keeps premium features until the end of their billing period
|
||||
if (isPaidToFree && user.dodoSubscriptionId) {
|
||||
@@ -12171,6 +12227,19 @@ async function handleAccountSettingsUpdate(req, res) {
|
||||
return sendJson(res, 400, { error: error.message || 'Unable to change subscription plan' });
|
||||
}
|
||||
}
|
||||
// Handle paid-to-free or paid-to-paid when subscription ID is still missing after lookup
|
||||
else if ((isPaidToFree || isPaidToPaid) && !user.dodoSubscriptionId) {
|
||||
log('ERROR: Cannot change plan - paid user missing dodoSubscriptionId after lookup', {
|
||||
userId: user.id,
|
||||
email: user.email,
|
||||
currentPlan: user.plan,
|
||||
requestedPlan: requestedPlan,
|
||||
changeType: isPaidToFree ? 'paid_to_free' : 'paid_to_paid'
|
||||
});
|
||||
return sendJson(res, 400, {
|
||||
error: 'Subscription ID not found. Please contact support to resolve this issue.'
|
||||
});
|
||||
}
|
||||
// For free-to-paid upgrades, create a checkout session and return the URL
|
||||
else if (isFreeToPaid || (!user.dodoSubscriptionId && PAID_PLANS.has(requestedPlan))) {
|
||||
try {
|
||||
@@ -12217,7 +12286,7 @@ async function handleAccountSettingsUpdate(req, res) {
|
||||
},
|
||||
};
|
||||
|
||||
const returnUrl = `${getBaseUrl()}/subscription-success`;
|
||||
const returnUrl = `${resolveBaseUrl(req)}/subscription-success`;
|
||||
checkoutBody.return_url = returnUrl;
|
||||
|
||||
const checkoutSession = await dodoRequest('/checkouts', {
|
||||
|
||||
Reference in New Issue
Block a user