Merge pull request #117 from weknowyourgame/fix/stripe-checkout-session-error

fix: stripe checkout session error
This commit is contained in:
John Yeo
2025-07-25 15:32:30 +01:00
committed by GitHub
2 changed files with 102 additions and 23 deletions

View File

@@ -12,7 +12,7 @@ import { ErrCode } from "@/errors/errCodes.js";
import { getNextStartOfMonthUnix } from "@/internal/products/prices/billingIntervalUtils.js";
import { APIVersion } from "@autumn/shared";
import { SuccessCode } from "@autumn/shared";
import { notNullish, nullish } from "@/utils/genUtils.js";
import { notNullish } from "@/utils/genUtils.js";
import Stripe from "stripe";
@@ -48,7 +48,6 @@ export const handleCreateCheckout = async ({
});
}
// Handle first item set
const { items } = itemSets[0];
attachParams.itemSets = itemSets;
@@ -96,7 +95,14 @@ export const handleCreateCheckout = async ({
};
}
const checkout = await stripeCli.checkout.sessions.create({
// Prepare checkout session parameters
let checkout;
let paymentMethodSet =
notNullish(checkoutParams.payment_method_types) ||
notNullish(checkoutParams.payment_method_configuration);
const sessionParams = {
customer: customer.processor.id,
line_items: items,
subscription_data: subscriptionData,
@@ -108,21 +114,36 @@ export const handleCreateCheckout = async ({
...(attachParams.metadata ? attachParams.metadata : {}),
},
allow_promotion_codes: allowPromotionCodes,
invoice_creation: !isRecurring ? { enabled: true } : undefined,
saved_payment_method_options: { payment_method_save: "enabled" },
...rewardData,
invoice_creation: !isRecurring
? {
enabled: true,
}
: undefined,
saved_payment_method_options: {
payment_method_save: "enabled",
},
...(attachParams.checkoutSessionParams || {}),
});
};
logger.info(`✅ Successfully created checkout for customer ${customer.id}`);
try {
checkout = await stripeCli.checkout.sessions.create(sessionParams);
logger.info(
`✅ Successfully created checkout for customer ${customer.id || customer.internal_id}`
);
} catch (error: any) {
let msg = error.message;
if (
msg &&
msg.includes("No valid payment method types") &&
!paymentMethodSet
) {
checkout = await stripeCli.checkout.sessions.create({
...sessionParams,
payment_method_types: ["card"],
});
logger.info(
`✅ Created fallback checkout session with card payment method for customer ${customer.id || customer.internal_id}`
);
} else {
throw error;
}
}
if (returnCheckout) {
return checkout;

View File

@@ -1,8 +1,10 @@
import { routeHandler } from "@/utils/routerUtils.js";
import { getOrCreateCustomer } from "../cusUtils/getOrCreateCustomer.js";
import { ExtendedRequest, ExtendedResponse } from "@/utils/models/Request.js";
import { ExtendedRequest } from "@/utils/models/Request.js";
import { createStripeCusIfNotExists } from "@/external/stripe/stripeCusUtils.js";
import { createStripeCli } from "@/external/stripe/utils.js";
import RecaseError from "@/utils/errorUtils.js";
import { ErrCode } from "@/errors/errCodes.js";
export const handleSetupPayment = async (req: any, res: any) =>
routeHandler({
@@ -10,8 +12,8 @@ export const handleSetupPayment = async (req: any, res: any) =>
res,
action: "setup_payment",
handler: async (req: ExtendedRequest, res: any) => {
// 1. Get the customer
const { db, env, org } = req;
const logger = req.logger;
let { customer_id, customer_data, success_url, checkout_session_params } =
req.body;
@@ -31,17 +33,73 @@ export const handleSetupPayment = async (req: any, res: any) =>
});
const stripeCli = createStripeCli({ org, env });
const session = await stripeCli.checkout.sessions.create({
// check if user already specified payment methods in their request
const hasUserSpecifiedPaymentMethods =
checkout_session_params && checkout_session_params.payment_method_types;
const sessionParams = {
customer: customer.processor?.id,
mode: "setup",
success_url: success_url || org.stripe_config?.success_url,
currency: org.default_currency || "usd",
...(checkout_session_params as any),
});
};
return res.json({
customer_id: customer.id,
url: session.url,
});
try {
// let stripe automatically determine payment methods
const session = await stripeCli.checkout.sessions.create(sessionParams);
return res.json({
customer_id: customer.id,
url: session.url,
});
} catch (error: any) {
// payment method errors
if (error.message &&
(error.message.includes("payment method") ||
error.message.includes("No valid payment"))) {
logger.warn("Stripe checkout session creation failed", {
customerId: customer.id,
error: error.message,
});
if (hasUserSpecifiedPaymentMethods) {
throw error;
}
try {
// card payment method fallback
const fallbackSession = await stripeCli.checkout.sessions.create({
...sessionParams,
payment_method_types: ["card"],
});
logger.info("Created checkout session with card payment method", {
customerId: customer.id,
});
return res.json({
customer_id: customer.id,
url: fallbackSession.url,
});
} catch (fallbackError: any) {
// if fallback failed
logger.error("Failed to create checkout session even with card payment method", {
customerId: customer.id,
error: fallbackError.message,
});
throw new RecaseError({
code: ErrCode.InvalidRequest,
message: "Unable to create checkout session. Please ensure you have activated card payment method in your Stripe dashboard.",
statusCode: 400,
});
}
}
// Re-throw errors
throw error;
}
},
});