Skip to content

Commit 070ae9d

Browse files
Refactor: Force Edge Function redeployment
1 parent 5796387 commit 070ae9d

File tree

4 files changed

+300
-23
lines changed

4 files changed

+300
-23
lines changed

src/services/paymentMethodService.ts

Lines changed: 19 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -10,22 +10,23 @@ export interface PaymentMethod {
1010

1111
export const paymentMethodService = {
1212
async getPaymentMethods(userEmail: string): Promise<PaymentMethod[]> {
13-
console.log('🔍 SUPABASE: Chargement des cartes bancaires pour:', userEmail);
13+
console.log('🔍 SUPABASE V2: Chargement des cartes bancaires pour:', userEmail);
1414

1515
try {
1616
const { supabase } = await import('@/integrations/supabase/client');
1717

18-
// Utiliser POST sans action pour déclencher le GET dans la fonction Edge
19-
const { data, error } = await supabase.functions.invoke('stripe-payment-methods', {
18+
// Utiliser la nouvelle fonction V2 pour forcer un déploiement propre
19+
const { data, error } = await supabase.functions.invoke('stripe-payment-methods-v2', {
2020
body: {} // POST vide pour déclencher handleGetPaymentMethods
2121
});
2222

2323
if (error) {
24-
console.error('❌ SUPABASE: Erreur récupération méthodes de paiement:', error);
24+
console.error('❌ SUPABASE V2: Erreur récupération méthodes de paiement:', error);
2525
return [];
2626
}
2727

28-
console.log('✅ SUPABASE: Cartes bancaires chargées:', data?.paymentMethods?.length || 0);
28+
console.log('✅ SUPABASE V2: Cartes bancaires chargées:', data?.paymentMethods?.length || 0);
29+
console.log('📋 SUPABASE V2: Version de fonction:', data?.function_version || 'unknown');
2930

3031
// Mapper les données pour correspondre à l'interface PaymentMethod
3132
const paymentMethods = data?.paymentMethods?.map((pm: any) => ({
@@ -40,59 +41,59 @@ export const paymentMethodService = {
4041

4142
return paymentMethods;
4243
} catch (error) {
43-
console.error('❌ SUPABASE: Erreur chargement cartes:', error);
44+
console.error('❌ SUPABASE V2: Erreur chargement cartes:', error);
4445
return [];
4546
}
4647
},
4748

4849
async deletePaymentMethod(paymentMethodId: string): Promise<void> {
49-
console.log(`🗑️ SUPABASE: Suppression de la carte ${paymentMethodId}`);
50+
console.log(`🗑️ SUPABASE V2: Suppression de la carte ${paymentMethodId}`);
5051

5152
try {
5253
const { supabase } = await import('@/integrations/supabase/client');
5354

54-
// Utiliser la méthode POST avec action delete
55-
const { error } = await supabase.functions.invoke('stripe-payment-methods', {
55+
// Utiliser la nouvelle fonction V2 avec action delete
56+
const { error } = await supabase.functions.invoke('stripe-payment-methods-v2', {
5657
body: {
5758
action: 'delete',
5859
paymentMethodId
5960
}
6061
});
6162

6263
if (error) {
63-
console.error('❌ SUPABASE: Erreur suppression carte:', error);
64+
console.error('❌ SUPABASE V2: Erreur suppression carte:', error);
6465
throw error;
6566
}
6667

67-
console.log('✅ SUPABASE: Carte supprimée de Stripe');
68+
console.log('✅ SUPABASE V2: Carte supprimée de Stripe');
6869
} catch (error) {
69-
console.error('❌ SUPABASE: Erreur suppression carte:', error);
70+
console.error('❌ SUPABASE V2: Erreur suppression carte:', error);
7071
throw error;
7172
}
7273
},
7374

7475
async setDefaultPaymentMethod(userEmail: string, paymentMethodId: string): Promise<void> {
75-
console.log(`⭐ SUPABASE: Définition de la carte par défaut ${paymentMethodId} pour ${userEmail}`);
76+
console.log(`⭐ SUPABASE V2: Définition de la carte par défaut ${paymentMethodId} pour ${userEmail}`);
7677

7778
try {
7879
const { supabase } = await import('@/integrations/supabase/client');
7980

80-
// Utiliser la méthode POST avec action set_default
81-
const { error } = await supabase.functions.invoke('stripe-payment-methods', {
81+
// Utiliser la nouvelle fonction V2 avec action set_default
82+
const { error } = await supabase.functions.invoke('stripe-payment-methods-v2', {
8283
body: {
8384
action: 'set_default',
8485
paymentMethodId
8586
}
8687
});
8788

8889
if (error) {
89-
console.error('❌ SUPABASE: Erreur définition carte par défaut:', error);
90+
console.error('❌ SUPABASE V2: Erreur définition carte par défaut:', error);
9091
throw error;
9192
}
9293

93-
console.log('✅ SUPABASE: Carte par défaut mise à jour');
94+
console.log('✅ SUPABASE V2: Carte par défaut mise à jour');
9495
} catch (error) {
95-
console.error('❌ SUPABASE: Erreur définition carte par défaut:', error);
96+
console.error('❌ SUPABASE V2: Erreur définition carte par défaut:', error);
9697
throw error;
9798
}
9899
}

supabase/config.toml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,9 @@ project_id = "wsvhmozduyiftmuuynpi"
44
[functions.stripe-payment-methods]
55
verify_jwt = true
66

7+
[functions.stripe-payment-methods-v2]
8+
verify_jwt = true
9+
710
# Shopify functions (public)
811
[functions.shopify-auth]
912
verify_jwt = false
Lines changed: 250 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,250 @@
1+
import { serve } from "https://deno.land/std@0.190.0/http/server.ts";
2+
import Stripe from "https://esm.sh/stripe@14.21.0";
3+
import { createClient } from "https://esm.sh/@supabase/supabase-js@2.45.0";
4+
5+
const corsHeaders = {
6+
"Access-Control-Allow-Origin": "*",
7+
"Access-Control-Allow-Headers": "authorization, x-client-info, apikey, content-type",
8+
};
9+
10+
serve(async (req) => {
11+
// Handle CORS preflight requests
12+
if (req.method === "OPTIONS") {
13+
return new Response(null, { headers: corsHeaders });
14+
}
15+
16+
try {
17+
console.log('💳 STRIPE PAYMENT METHODS V2 - Début traitement [FRESH-DEPLOYMENT-2025-01-11]');
18+
19+
// DIAGNOSTIC COMPLET DES VARIABLES D'ENVIRONNEMENT
20+
console.log('🔍 DIAGNOSTIC V2 - Variables d\'environnement disponibles:');
21+
console.log(' - SUPABASE_URL:', !!Deno.env.get("SUPABASE_URL"));
22+
console.log(' - SUPABASE_ANON_KEY:', !!Deno.env.get("SUPABASE_ANON_KEY"));
23+
console.log(' - SUPABASE_SERVICE_ROLE_KEY:', !!Deno.env.get("SUPABASE_SERVICE_ROLE_KEY"));
24+
console.log(' - STRIPE_SECRET_KEY:', !!Deno.env.get("STRIPE_SECRET_KEY"));
25+
console.log(' - STRIPE_WEBHOOK_SECRET:', !!Deno.env.get("STRIPE_WEBHOOK_SECRET"));
26+
console.log(' - SHOPIFY_API_KEY:', !!Deno.env.get("SHOPIFY_API_KEY"));
27+
console.log(' - SHOPIFY_API_SECRET:', !!Deno.env.get("SHOPIFY_API_SECRET"));
28+
29+
// Liste TOUTES les variables d'environnement disponibles (masquées)
30+
const allEnvVars = Object.keys(Deno.env.toObject());
31+
console.log('🔍 DIAGNOSTIC V2 - Toutes les variables disponibles:', allEnvVars.length, 'variables');
32+
console.log('🔍 DIAGNOSTIC V2 - Variables contenant "STRIPE":', allEnvVars.filter(key => key.includes('STRIPE')));
33+
console.log('🔍 DIAGNOSTIC V2 - Variables contenant "SECRET":', allEnvVars.filter(key => key.includes('SECRET')).map(key => `${key}=[MASKED]`));
34+
35+
// Initialize Supabase client
36+
const supabaseClient = createClient(
37+
Deno.env.get("SUPABASE_URL") ?? "",
38+
Deno.env.get("SUPABASE_ANON_KEY") ?? ""
39+
);
40+
41+
// Get authenticated user
42+
const authHeader = req.headers.get("Authorization")!;
43+
const token = authHeader.replace("Bearer ", "");
44+
const { data } = await supabaseClient.auth.getUser(token);
45+
const user = data.user;
46+
47+
if (!user?.email) {
48+
console.error('❌ AUTH V2 - Utilisateur non authentifié');
49+
throw new Error("User not authenticated");
50+
}
51+
52+
console.log('👤 UTILISATEUR V2 - Email:', user.email);
53+
54+
// Check if Stripe secret key is available avec diagnostic avancé
55+
const stripeSecretKey = Deno.env.get("STRIPE_SECRET_KEY");
56+
console.log('🔑 STRIPE SECRET KEY V2 - Disponible:', !!stripeSecretKey);
57+
console.log('🔑 STRIPE SECRET KEY V2 - Longueur:', stripeSecretKey?.length || 0);
58+
console.log('🔑 STRIPE SECRET KEY V2 - Commence par sk_:', stripeSecretKey?.startsWith('sk_') || false);
59+
60+
if (!stripeSecretKey) {
61+
console.error('❌ STRIPE SECRET KEY V2 - Variable manquante dans l\'environnement');
62+
console.error('❌ DIAGNOSTIC V2 - Vérifiez que le secret STRIPE_SECRET_KEY existe dans Supabase');
63+
console.error('❌ DIAGNOSTIC V2 - Vérifiez que supabase/config.toml contient [functions.stripe-payment-methods-v2]');
64+
throw new Error("STRIPE_SECRET_KEY not found in environment variables - Check Supabase secrets configuration");
65+
}
66+
67+
console.log('✅ V2 - STRIPE SECRET KEY trouvée, initialisation de Stripe...');
68+
69+
// Initialize Stripe
70+
const stripe = new Stripe(stripeSecretKey, {
71+
apiVersion: "2023-10-16",
72+
});
73+
74+
console.log('✅ V2 - Stripe initialisé avec succès');
75+
76+
// Handle different HTTP methods
77+
if (req.method === "GET") {
78+
return await handleGetPaymentMethods(stripe, user.email);
79+
} else if (req.method === "POST") {
80+
const body = await req.json();
81+
82+
// Si aucune action spécifiée, c'est un GET via POST (pour compatibilité)
83+
if (!body || !body.action || body.action === undefined) {
84+
console.log('📋 V2 - POST sans action - Redirection vers GET');
85+
return await handleGetPaymentMethods(stripe, user.email);
86+
}
87+
88+
return await handlePaymentMethodAction(stripe, body, user.email);
89+
}
90+
91+
return new Response(JSON.stringify({ error: "Method not allowed" }), {
92+
status: 405,
93+
headers: { ...corsHeaders, "Content-Type": "application/json" },
94+
});
95+
96+
} catch (error) {
97+
console.error('❌ STRIPE PAYMENT METHODS V2 - Erreur:', error);
98+
return new Response(JSON.stringify({
99+
error: error instanceof Error ? error.message : "Internal server error",
100+
function_version: "v2",
101+
timestamp: new Date().toISOString()
102+
}), {
103+
status: 500,
104+
headers: { ...corsHeaders, "Content-Type": "application/json" },
105+
});
106+
}
107+
});
108+
109+
async function handleGetPaymentMethods(stripe: Stripe, userEmail: string) {
110+
console.log('📋 GET PAYMENT METHODS V2 - Récupération pour:', userEmail);
111+
112+
try {
113+
// Find customer by email
114+
const customers = await stripe.customers.list({
115+
email: userEmail,
116+
limit: 1
117+
});
118+
119+
if (customers.data.length === 0) {
120+
console.log('👤 GET PAYMENT METHODS V2 - Aucun client Stripe trouvé');
121+
return new Response(JSON.stringify({ paymentMethods: [] }), {
122+
headers: { ...corsHeaders, "Content-Type": "application/json" },
123+
status: 200,
124+
});
125+
}
126+
127+
const customer = customers.data[0];
128+
console.log('👤 GET PAYMENT METHODS V2 - Client trouvé:', customer.id);
129+
130+
// Get payment methods for customer
131+
const paymentMethods = await stripe.paymentMethods.list({
132+
customer: customer.id,
133+
type: 'card',
134+
});
135+
136+
console.log('💳 GET PAYMENT METHODS V2 - Méthodes trouvées:', paymentMethods.data.length);
137+
138+
// Get default payment method
139+
const defaultPaymentMethodId = typeof customer.invoice_settings?.default_payment_method === 'string'
140+
? customer.invoice_settings.default_payment_method
141+
: null;
142+
143+
// Format payment methods for frontend
144+
const formattedMethods = paymentMethods.data.map(pm => ({
145+
id: pm.id,
146+
type: pm.type,
147+
card: pm.card ? {
148+
brand: pm.card.brand,
149+
last4: pm.card.last4,
150+
exp_month: pm.card.exp_month,
151+
exp_year: pm.card.exp_year,
152+
} : null,
153+
isDefault: pm.id === defaultPaymentMethodId,
154+
created: pm.created,
155+
}));
156+
157+
console.log('✅ GET PAYMENT METHODS V2 - Méthodes formatées avec succès');
158+
159+
return new Response(JSON.stringify({
160+
paymentMethods: formattedMethods,
161+
customerId: customer.id,
162+
function_version: "v2"
163+
}), {
164+
headers: { ...corsHeaders, "Content-Type": "application/json" },
165+
status: 200,
166+
});
167+
168+
} catch (error) {
169+
console.error('❌ GET PAYMENT METHODS V2 - Erreur:', error);
170+
throw error;
171+
}
172+
}
173+
174+
async function handlePaymentMethodAction(stripe: Stripe, body: any, userEmail: string) {
175+
const { action, customerId, paymentMethodId } = body;
176+
177+
console.log('⚙️ PAYMENT METHOD ACTION V2 - Action:', action);
178+
179+
if (action === 'delete') {
180+
// Delete/detach payment method
181+
if (!paymentMethodId) {
182+
return new Response(JSON.stringify({ error: "Payment method ID required" }), {
183+
status: 400,
184+
headers: { ...corsHeaders, "Content-Type": "application/json" },
185+
});
186+
}
187+
188+
await stripe.paymentMethods.detach(paymentMethodId);
189+
console.log('✅ PAYMENT METHOD ACTION V2 - Méthode supprimée');
190+
191+
return new Response(JSON.stringify({ success: true, function_version: "v2" }), {
192+
headers: { ...corsHeaders, "Content-Type": "application/json" },
193+
status: 200,
194+
});
195+
196+
} else if (action === 'attach') {
197+
// Attach payment method to customer
198+
await stripe.paymentMethods.attach(paymentMethodId, {
199+
customer: customerId,
200+
});
201+
202+
console.log('✅ PAYMENT METHOD ACTION V2 - Méthode attachée');
203+
return new Response(JSON.stringify({ success: true, function_version: "v2" }), {
204+
headers: { ...corsHeaders, "Content-Type": "application/json" },
205+
status: 200,
206+
});
207+
208+
} else if (action === 'set_default') {
209+
// Set as default payment method - need to find customer first
210+
if (!paymentMethodId) {
211+
return new Response(JSON.stringify({ error: "Payment method ID required" }), {
212+
status: 400,
213+
headers: { ...corsHeaders, "Content-Type": "application/json" },
214+
});
215+
}
216+
217+
// Find customer by email
218+
const customers = await stripe.customers.list({
219+
email: userEmail,
220+
limit: 1
221+
});
222+
223+
if (customers.data.length === 0) {
224+
return new Response(JSON.stringify({ error: "Customer not found" }), {
225+
status: 404,
226+
headers: { ...corsHeaders, "Content-Type": "application/json" },
227+
});
228+
}
229+
230+
const customer = customers.data[0];
231+
232+
// Set as default payment method
233+
await stripe.customers.update(customer.id, {
234+
invoice_settings: {
235+
default_payment_method: paymentMethodId,
236+
},
237+
});
238+
239+
console.log('✅ PAYMENT METHOD ACTION V2 - Méthode définie par défaut');
240+
return new Response(JSON.stringify({ success: true, function_version: "v2" }), {
241+
headers: { ...corsHeaders, "Content-Type": "application/json" },
242+
status: 200,
243+
});
244+
}
245+
246+
return new Response(JSON.stringify({ error: "Invalid action" }), {
247+
status: 400,
248+
headers: { ...corsHeaders, "Content-Type": "application/json" },
249+
});
250+
}

0 commit comments

Comments
 (0)