fix(stripePaymentCallback): better errors (#12223)

Co-authored-by: Joe Au-Yeung <65426560+joeauyeung@users.noreply.github.com>
Co-authored-by: Keith Williams <keithwillcode@gmail.com>
This commit is contained in:
Morgan 2023-11-16 10:48:46 +02:00 committed by GitHub
parent ea0a64624c
commit 0a39f53a4b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 24 additions and 10 deletions

View File

@ -73,7 +73,8 @@ const handler = async (req: NextApiRequest, res: NextApiResponse) => {
redirectUrl = handler.redirect?.url || getInstalledAppPath(handler); redirectUrl = handler.redirect?.url || getInstalledAppPath(handler);
res.json({ url: redirectUrl, newTab: handler.redirect?.newTab }); res.json({ url: redirectUrl, newTab: handler.redirect?.newTab });
} }
return res.status(200); if (!res.writableEnded) return res.status(200);
return res;
} catch (error) { } catch (error) {
console.error(error); console.error(error);
if (error instanceof HttpError) { if (error instanceof HttpError) {

View File

@ -3,6 +3,7 @@ import z from "zod";
import { getCustomerAndCheckoutSession } from "@calcom/app-store/stripepayment/lib/getCustomerAndCheckoutSession"; import { getCustomerAndCheckoutSession } from "@calcom/app-store/stripepayment/lib/getCustomerAndCheckoutSession";
import { WEBAPP_URL } from "@calcom/lib/constants"; import { WEBAPP_URL } from "@calcom/lib/constants";
import { HttpError } from "@calcom/lib/http-error";
import { defaultHandler, defaultResponder } from "@calcom/lib/server"; import { defaultHandler, defaultResponder } from "@calcom/lib/server";
import { prisma } from "@calcom/prisma"; import { prisma } from "@calcom/prisma";
import type { Prisma } from "@calcom/prisma/client"; import type { Prisma } from "@calcom/prisma/client";
@ -22,7 +23,13 @@ async function getHandler(req: NextApiRequest, res: NextApiResponse) {
const { callbackUrl, checkoutSessionId } = querySchema.parse(req.query); const { callbackUrl, checkoutSessionId } = querySchema.parse(req.query);
const { stripeCustomer, checkoutSession } = await getCustomerAndCheckoutSession(checkoutSessionId); const { stripeCustomer, checkoutSession } = await getCustomerAndCheckoutSession(checkoutSessionId);
if (!stripeCustomer) return { message: "Stripe customer not found or deleted" }; if (!stripeCustomer)
throw new HttpError({
statusCode: 404,
message: "Stripe customer not found or deleted",
url: req.url,
method: req.method,
});
// first let's try to find user by metadata stripeCustomerId // first let's try to find user by metadata stripeCustomerId
let user = await prisma.user.findFirst({ let user = await prisma.user.findFirst({
@ -43,10 +50,11 @@ async function getHandler(req: NextApiRequest, res: NextApiResponse) {
}); });
} }
if (!user)
throw new HttpError({ statusCode: 404, message: "User not found", url: req.url, method: req.method });
if (checkoutSession.payment_status === "paid" && stripeCustomer.metadata.username) { if (checkoutSession.payment_status === "paid" && stripeCustomer.metadata.username) {
try { try {
if (!user) return { message: "User not found" };
await prisma.user.update({ await prisma.user.update({
data: { data: {
username: stripeCustomer.metadata.username, username: stripeCustomer.metadata.username,
@ -61,10 +69,13 @@ async function getHandler(req: NextApiRequest, res: NextApiResponse) {
}); });
} catch (error) { } catch (error) {
console.error(error); console.error(error);
return { throw new HttpError({
statusCode: 400,
url: req.url,
method: req.method,
message: message:
"We have received your payment. Your premium username could still not be reserved. Please contact support@cal.com and mention your premium username", "We have received your payment. Your premium username could still not be reserved. Please contact support@cal.com and mention your premium username",
}; });
} }
} }
callbackUrl.searchParams.set("paymentStatus", checkoutSession.payment_status); callbackUrl.searchParams.set("paymentStatus", checkoutSession.payment_status);

View File

@ -14,13 +14,14 @@ export function defaultResponder<T>(f: Handle<T>) {
const result = await f(req, res); const result = await f(req, res);
ok = true; ok = true;
if (result && !res.writableEnded) { if (result && !res.writableEnded) {
res.json(result); return res.json(result);
} }
} catch (err) { } catch (err) {
console.error(err); console.error(err);
const error = getServerErrorFromUnknown(err); const error = getServerErrorFromUnknown(err);
res.statusCode = error.statusCode; return res
res.json({ message: error.message }); .status(error.statusCode)
.json({ message: error.message, url: error.url, method: error.method });
} finally { } finally {
performance.mark("End"); performance.mark("End");
performance.measure(`[${ok ? "OK" : "ERROR"}][$1] ${req.method} '${req.url}'`, "Start", "End"); performance.measure(`[${ok ? "OK" : "ERROR"}][$1] ${req.method} '${req.url}'`, "Start", "End");

View File

@ -55,7 +55,8 @@ export function getServerErrorFromUnknown(cause: unknown): HttpError {
const redactedCause = redactError(cause); const redactedCause = redactError(cause);
return { return {
...redactedCause, ...redactedCause,
message: redactedCause.message, name: cause.name,
message: cause.message ?? "",
cause: cause.cause, cause: cause.cause,
url: cause.url, url: cause.url,
statusCode: cause.statusCode, statusCode: cause.statusCode,