Skip to content

Commit

Permalink
fix: New webhook rehandler
Browse files Browse the repository at this point in the history
  • Loading branch information
richiemcilroy committed Nov 14, 2024
1 parent 2b8c404 commit ac415c1
Showing 1 changed file with 68 additions and 39 deletions.
107 changes: 68 additions & 39 deletions apps/web/app/api/webhooks/stripe/route.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,50 @@ const relevantEvents = new Set([
"customer.subscription.deleted",
]);

// Helper function to find user with retries
async function findUserWithRetry(email: string, userId?: string, maxRetries = 3): Promise<typeof users.$inferSelect | null> {
for (let i = 0; i < maxRetries; i++) {
console.log(`Attempt ${i + 1} to find user (email: ${email}, userId: ${userId})`);

try {
let user;

if (userId) {
user = await db
.select()
.from(users)
.where(eq(users.id, userId))
.limit(1)
.then(rows => rows[0] || null);
} else if (email) {
user = await db
.select()
.from(users)
.where(eq(users.email, email))
.limit(1)
.then(rows => rows[0] || null);
}

if (user) {
console.log(`User found on attempt ${i + 1}`);
return user;
}

// Wait before retrying, with exponential backoff
if (i < maxRetries - 1) {
const delay = Math.pow(2, i) * 1000; // 1s, 2s, 4s
console.log(`Waiting ${delay}ms before retry`);
await new Promise(resolve => setTimeout(resolve, delay));
}
} catch (error) {
console.error(`Error finding user on attempt ${i + 1}:`, error);
// Continue to next retry
}
}

return null;
}

export const POST = async (req: Request) => {
const buf = await req.text();
const sig = req.headers.get("Stripe-Signature") as string;
Expand All @@ -36,50 +80,34 @@ export const POST = async (req: Request) => {
const customer = await stripe.customers.retrieve(
session.customer as string
);

// Get potential user identifiers
let foundUserId;
let customerEmail;

if ("metadata" in customer) {
foundUserId = customer.metadata.userId;
}
if (!foundUserId) {
console.log("No user found in metadata, checking customer email");
if ("email" in customer && customer.email) {
const userByEmail = await db
.select()
.from(users)
.where(eq(users.email, customer.email))
.limit(1);

if (userByEmail && userByEmail.length > 0 && userByEmail[0]) {
foundUserId = userByEmail[0].id;
console.log(`User found by email: ${foundUserId}`);
// Update customer metadata with userId
await stripe.customers.update(customer.id, {
metadata: { userId: foundUserId },
});
} else {
console.log("No user found by email");
return new Response("No user found", {
status: 400,
});
}
} else {
console.log("No email found for customer");
return new Response("No user found", {
status: 400,
});
}
if ("email" in customer) {
customerEmail = customer.email;
}

const userResult = await db
.select()
.from(users)
.where(eq(users.id, foundUserId));

if (!userResult || userResult.length === 0) {
console.log("No user found in database");
return new Response("No user found", { status: 400 });
console.log("Looking for user with:", { foundUserId, customerEmail });

// Try to find user with retries
const dbUser = await findUserWithRetry(customerEmail as string, foundUserId);

if (!dbUser) {
console.log("No user found after retries");
// Instead of failing, we'll store the subscription info and retry later
// You might want to implement a queue system for this in production
return new Response("User not found, webhook will be retried", {
status: 202, // Accepted but not processed
});
}

console.log("Found user:", dbUser.id);

const subscription = await stripe.subscriptions.retrieve(
session.subscription as string
);
Expand All @@ -92,12 +120,13 @@ export const POST = async (req: Request) => {
.update(users)
.set({
stripeSubscriptionId: session.subscription as string,
stripeSubscriptionStatus: session.status,
stripeSubscriptionStatus: subscription.status,
stripeCustomerId: customer.id,
inviteQuota: inviteQuota,
})
.where(eq(users.id, foundUserId));
.where(eq(users.id, dbUser.id));

console.log("User updated successfully", { foundUserId, inviteQuota });
console.log("User updated successfully", { userId: dbUser.id, inviteQuota });
}

if (event.type === "customer.subscription.updated") {
Expand Down

1 comment on commit ac415c1

@vercel
Copy link

@vercel vercel bot commented on ac415c1 Nov 14, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please sign in to comment.