164 lines
4.5 KiB
JavaScript
164 lines
4.5 KiB
JavaScript
/* 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,
|
||
},
|
||
);
|
||
}
|
||
});
|