Files
site/supabase/functions/create-checkout-session/index.js
2026-01-03 21:11:17 +01:00

164 lines
4.5 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/* eslint-disable no-undef */
// Edge Function: create-checkout-session
// Environnement: Deno (Supabase Edge Functions self-host)
// Secrets/vars à définir (ex: volumes/functions/.env ou env docker):
// STRIPE_SECRET_KEY=sk_live_...
// SUPABASE_URL=https://supabase.abcdcode.fr (ou ce que tu utilises)
// SUPABASE_SERVICE_ROLE_KEY=xxxxxxxxxxxxxxxx
import { serve } from "https://deno.land/std@0.168.0/http/server.ts";
import Stripe from "https://esm.sh/stripe@12.0.0";
import { createClient } from "https://esm.sh/@supabase/supabase-js@2";
const STRIPE_SECRET_KEY = Deno.env.get("STRIPE_SECRET_KEY") ?? "";
const SUPABASE_URL = Deno.env.get("SUPABASE_URL") ?? "";
const SUPABASE_SERVICE_ROLE_KEY =
Deno.env.get("SUPABASE_SERVICE_ROLE_KEY") ?? "";
if (!STRIPE_SECRET_KEY) {
console.warn("⚠️ STRIPE_SECRET_KEY is not set Stripe calls will fail.");
}
if (!SUPABASE_URL || !SUPABASE_SERVICE_ROLE_KEY) {
console.warn(
"⚠️ SUPABASE_URL or SUPABASE_SERVICE_ROLE_KEY is not set database writes may fail.",
);
}
const stripe = new Stripe(STRIPE_SECRET_KEY, {
apiVersion: "2022-11-15",
httpClient: Stripe.createFetchHttpClient(),
});
const corsHeaders = {
"Access-Control-Allow-Origin": "*",
"Access-Control-Allow-Headers":
"authorization, x-client-info, apikey, content-type",
};
serve(async (req) => {
// Préflight CORS
if (req.method === "OPTIONS") {
return new Response("ok", { headers: corsHeaders });
}
try {
const body = await req.json().catch(() => null);
if (!body) {
return new Response(
JSON.stringify({ error: "Invalid JSON body" }),
{
status: 400,
headers: { ...corsHeaders, "Content-Type": "application/json" },
},
);
}
const { priceId, orderData, successUrl, cancelUrl } = body;
if (!priceId) {
return new Response(
JSON.stringify({ error: "priceId is required" }),
{
status: 400,
headers: { ...corsHeaders, "Content-Type": "application/json" },
},
);
}
if (!successUrl || !cancelUrl) {
return new Response(
JSON.stringify({
error: "successUrl and cancelUrl are required",
}),
{
status: 400,
headers: { ...corsHeaders, "Content-Type": "application/json" },
},
);
}
if (!STRIPE_SECRET_KEY) {
return new Response(
JSON.stringify({
error: "Stripe secret key is not configured on the server",
}),
{
status: 500,
headers: { ...corsHeaders, "Content-Type": "application/json" },
},
);
}
// 1. Client Supabase pour sauver la commande
const supabaseClient = createClient(
SUPABASE_URL,
SUPABASE_SERVICE_ROLE_KEY,
{
global: {
// On forwarde l'Authorization si tu en as besoin côté RLS
headers: {
Authorization: req.headers.get("Authorization") ?? "",
},
},
},
);
// 2. Insertion dans la table "orders"
const { data: order, error: orderError } = await supabaseClient
.from("orders")
.insert({
...orderData,
status: "pending_payment",
created_at: new Date().toISOString(),
})
.select()
.single();
if (orderError) {
console.error("Error saving order:", orderError);
throw new Error(`Error saving order: ${orderError.message}`);
}
// 3. Création de la session de paiement Stripe
const session = await stripe.checkout.sessions.create({
payment_method_types: ["card"],
line_items: [
{
price: priceId,
quantity: 1,
},
],
mode: "payment",
// ⚠️ Champs Stripe doivent être en snake_case
success_url: `${successUrl}&session_id={CHECKOUT_SESSION_ID}&order_id=${order?.id}`,
cancel_url: cancelUrl,
metadata: {
order_id: order?.id?.toString(),
product_name: orderData?.productName ?? "",
},
customer_email: orderData?.email ?? undefined,
});
return new Response(
JSON.stringify({ sessionId: session.id, url: session.url }),
{
headers: { ...corsHeaders, "Content-Type": "application/json" },
status: 200,
},
);
} catch (error) {
console.error("create-checkout-session error:", error);
return new Response(
JSON.stringify({ error: error.message ?? "Unknown error" }),
{
headers: { ...corsHeaders, "Content-Type": "application/json" },
status: 400,
},
);
}
});