Skip to content

Commit 2d2b2d9

Browse files
Fix Stripe integration issues
1 parent f21250e commit 2d2b2d9

File tree

8 files changed

+447
-187
lines changed

8 files changed

+447
-187
lines changed
Lines changed: 41 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,9 @@
1-
21
import { useAuth } from '@/hooks/useAuth';
32
import { useCampaigns } from '@/hooks/useCampaigns';
43
import { useStripePayment } from '@/hooks/useStripePayment';
54
import { usePaymentMethods } from '@/hooks/usePaymentMethods';
65
import { useToast } from '@/hooks/use-toast';
76
import { CampaignFormData } from './useCampaignFormState';
8-
import { functions } from '@/lib/firebase';
9-
import { httpsCallable } from 'firebase/functions';
107

118
export const useCampaignFormSubmission = (
129
formData: CampaignFormData,
@@ -17,20 +14,19 @@ export const useCampaignFormSubmission = (
1714
const { user } = useAuth();
1815
const { createCampaign } = useCampaigns();
1916
const { setupPaymentForCampaign } = useStripePayment();
20-
const { refreshPaymentMethods } = usePaymentMethods();
17+
const { refreshPaymentMethods, paymentMethods } = usePaymentMethods();
2118
const { toast } = useToast();
2219

2320
const redirectToStripeForNewCard = async (campaignData: CampaignFormData) => {
24-
console.log('🎯 NOUVEAU FLOW: Redirection vers Stripe SANS créer la campagne');
21+
console.log('🎯 SUPABASE: Redirection vers Stripe SANS créer la campagne');
2522

2623
try {
27-
// Store campaign data securely with encryption
24+
// Store campaign data securely
2825
import('@/utils/secureClientStorage').then(({ secureStorage }) => {
29-
secureStorage.setCampaignData('pendingCampaignData', campaignData, 2); // 2 hours expiry
26+
secureStorage.setCampaignData('pendingCampaignData', campaignData, 2);
3027
console.log('🔒 Campaign data stored securely');
3128
});
3229

33-
// Stocker aussi dans le state pour le flow normal
3430
setPendingCampaignData(campaignData);
3531

3632
// Rediriger vers Stripe avec un ID temporaire
@@ -53,66 +49,65 @@ export const useCampaignFormSubmission = (
5349
};
5450

5551
const createCampaignWithExistingCard = async (campaignData: CampaignFormData, cardId: string) => {
56-
console.log('🎯 Création campagne avec carte existante validée:', cardId);
57-
58-
// Créer la campagne directement finalisée car la carte est déjà validée
59-
const campaignId = await createCampaign({
60-
...campaignData,
61-
isDraft: false,
62-
paymentConfigured: true,
63-
defaultCommissionRate: 10,
64-
stripePaymentMethodId: cardId,
65-
});
52+
console.log('🎯 SUPABASE: Création campagne avec carte existante validée:', cardId);
6653

67-
console.log('✅ Campagne créée et finalisée:', campaignId);
68-
return campaignId;
54+
try {
55+
// Utiliser la nouvelle Edge Function Supabase pour finaliser la campagne
56+
const { supabase } = await import('@/integrations/supabase/client');
57+
58+
const { data, error } = await supabase.functions.invoke('finalize-campaign', {
59+
body: {
60+
campaignData: {
61+
...campaignData,
62+
defaultCommissionRate: 10
63+
},
64+
cardId
65+
}
66+
});
67+
68+
if (error) {
69+
throw new Error(error.message || 'Failed to create campaign');
70+
}
71+
72+
console.log('✅ SUPABASE: Campagne créée et finalisée:', data.campaign.id);
73+
return data.campaign.id;
74+
} catch (error) {
75+
console.error('❌ SUPABASE: Erreur création campagne:', error);
76+
throw error;
77+
}
6978
};
7079

7180
const handleSubmit = async (e: React.FormEvent) => {
7281
e.preventDefault();
7382
setLoading(true);
7483

7584
try {
76-
console.log('🎯 FLOW CORRIGÉ: Validation AVANT création de campagne...');
77-
78-
if (!formData.name) {
79-
throw new Error('Le nom de la campagne est requis');
80-
}
85+
console.log('🎯 SUPABASE: Validation AVANT création de campagne...');
8186

82-
if (!formData.targetUrl) {
83-
throw new Error('L\'URL de destination est requise');
87+
if (!formData.name || !formData.targetUrl) {
88+
throw new Error('Le nom et l\'URL de la campagne sont requis');
8489
}
8590

86-
// Vérifier les cartes disponibles
87-
console.log('🔄 Vérification des cartes existantes...');
91+
// Vérifier les cartes disponibles via Supabase
92+
console.log('🔄 SUPABASE: Vérification des cartes existantes...');
8893
await refreshPaymentMethods();
8994

90-
// Attendre pour s'assurer de la synchronisation
91-
await new Promise(resolve => setTimeout(resolve, 500));
92-
93-
// Récupérer les données fraîches via Firebase
94-
const getPaymentMethods = httpsCallable(functions, 'stripeGetPaymentMethods');
95-
const freshCardsResponse = await getPaymentMethods({ userEmail: user?.email });
96-
const freshCardsData = freshCardsResponse.data as { paymentMethods?: any[] };
97-
98-
const availableCards = freshCardsData.paymentMethods || [];
99-
100-
console.log('💳 Cartes disponibles:', availableCards.length);
95+
console.log('💳 Cartes disponibles:', paymentMethods.length);
10196

102-
if (availableCards.length === 0) {
103-
console.log('💳 FLOW CORRIGÉ: Aucune carte → Redirection Stripe (PAS de création campagne)');
97+
if (paymentMethods.length === 0) {
98+
console.log('💳 SUPABASE: Aucune carte → Redirection Stripe');
10499
await redirectToStripeForNewCard(formData);
105100
return;
106101
}
107102

108-
// 🔥 CORRECTION: TOUJOURS afficher le sélecteur, même avec une seule carte
109-
console.log('💳 FLOW CORRIGÉ: Cartes disponibles → TOUJOURS afficher le sélecteur');
103+
// Afficher le sélecteur de cartes
104+
console.log('💳 SUPABASE: Cartes disponibles → Afficher le sélecteur');
110105
setPendingCampaignData(formData);
111106
setShowPaymentSelector(true);
112107
setLoading(false);
113108

114109
} catch (error: any) {
115-
console.error('❌ Erreur dans le flow corrigé:', error);
110+
console.error('❌ SUPABASE: Erreur dans le flow:', error);
116111
toast({
117112
title: "Erreur",
118113
description: error.message || "Impossible de traiter la demande",
@@ -127,4 +122,4 @@ export const useCampaignFormSubmission = (
127122
createCampaignWithExistingCard,
128123
redirectToStripeForNewCard,
129124
};
130-
};
125+
};

src/hooks/useStripePayment.ts

Lines changed: 24 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
21
import { useState } from 'react';
32
import { useAuth } from '@/hooks/useAuth';
43

@@ -16,37 +15,34 @@ export const useStripePayment = () => {
1615
setError(null);
1716

1817
try {
19-
console.log('🔄 API: Création du setup de paiement pour la campagne:', campaignId);
18+
console.log('🔄 SUPABASE: Création du setup de paiement pour la campagne:', campaignId);
2019

2120
// Si c'est pour une nouvelle campagne, stocker les données en local
2221
if (campaignId === 'temp_new_campaign') {
2322
const pendingData = localStorage.getItem('pendingCampaignData');
2423
console.log('💾 Données campagne stockées pour après validation Stripe:', pendingData);
2524
}
2625

27-
// Appel à l'API Vercel
28-
const response = await fetch('/api/stripe-setup-intent', {
29-
method: 'POST',
30-
headers: {
31-
'Content-Type': 'application/json',
32-
},
33-
body: JSON.stringify({
34-
userEmail: user.email,
26+
// Utiliser Supabase Edge Function au lieu de l'API Vercel
27+
const { supabase } = await import('@/integrations/supabase/client');
28+
29+
const { data: setupData, error: supabaseError } = await supabase.functions.invoke('stripe-setup-intent', {
30+
body: {
3531
campaignName
36-
}),
32+
}
3733
});
3834

39-
if (!response.ok) {
40-
throw new Error('Failed to create setup intent');
35+
if (supabaseError) {
36+
console.error('❌ SUPABASE: Erreur setup paiement:', supabaseError);
37+
throw new Error(supabaseError.message || 'Failed to create setup intent');
4138
}
4239

43-
const setupData = await response.json();
44-
console.log('✅ API: Setup de paiement créé:', setupData);
40+
console.log('✅ SUPABASE: Setup de paiement créé:', setupData);
4541

4642
// Retourner les données pour utilisation avec Stripe Elements
4743
return setupData;
4844
} catch (err: any) {
49-
console.error('❌ API: Erreur setup paiement:', err);
45+
console.error('❌ SUPABASE: Erreur setup paiement:', err);
5046
setError(err.message);
5147
throw err;
5248
} finally {
@@ -59,31 +55,29 @@ export const useStripePayment = () => {
5955
setError(null);
6056

6157
try {
62-
console.log('🔄 API: Vérification du setup pour:', setupIntentId);
58+
console.log('🔄 SUPABASE: Vérification du setup pour:', setupIntentId);
59+
60+
// Utiliser Supabase Edge Function au lieu de l'API Vercel
61+
const { supabase } = await import('@/integrations/supabase/client');
6362

64-
// Appel à l'API Vercel
65-
const response = await fetch('/api/stripe-check-setup', {
66-
method: 'POST',
67-
headers: {
68-
'Content-Type': 'application/json',
69-
},
70-
body: JSON.stringify({ setupIntentId }),
63+
const { data, error: supabaseError } = await supabase.functions.invoke('stripe-check-setup', {
64+
body: { setupIntentId }
7165
});
7266

73-
if (!response.ok) {
74-
throw new Error('Failed to verify setup intent');
67+
if (supabaseError) {
68+
console.error('❌ SUPABASE: Erreur vérification setup:', supabaseError);
69+
throw new Error(supabaseError.message || 'Failed to verify setup intent');
7570
}
7671

77-
const data = await response.json();
78-
console.log('✅ API: Setup vérifié et finalisé:', data);
72+
console.log('✅ SUPABASE: Setup vérifié et finalisé:', data);
7973

8074
// **IMPORTANT: Retourner aussi le paymentMethodId pour la finalisation**
8175
return {
8276
...data,
8377
paymentMethodId: data.paymentMethodId
8478
};
8579
} catch (err: any) {
86-
console.error('❌ API: Erreur vérification setup:', err);
80+
console.error('❌ SUPABASE: Erreur vérification setup:', err);
8781
setError(err.message);
8882
throw err;
8983
} finally {
@@ -97,4 +91,4 @@ export const useStripePayment = () => {
9791
loading,
9892
error,
9993
};
100-
};
94+
};

src/services/paymentMethodService.ts

Lines changed: 18 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -13,11 +13,11 @@ export const paymentMethodService = {
1313
console.log('🔍 SUPABASE: Chargement des cartes bancaires pour:', userEmail);
1414

1515
try {
16-
// Utiliser Supabase Edge Function au lieu de l'ancienne API
1716
const { supabase } = await import('@/integrations/supabase/client');
1817

18+
// Utiliser POST sans action pour déclencher le GET dans la fonction Edge
1919
const { data, error } = await supabase.functions.invoke('stripe-payment-methods', {
20-
body: { userEmail }
20+
body: {} // POST vide pour déclencher handleGetPaymentMethods
2121
});
2222

2323
if (error) {
@@ -26,7 +26,19 @@ export const paymentMethodService = {
2626
}
2727

2828
console.log('✅ SUPABASE: Cartes bancaires chargées:', data?.paymentMethods?.length || 0);
29-
return data?.paymentMethods || [];
29+
30+
// Mapper les données pour correspondre à l'interface PaymentMethod
31+
const paymentMethods = data?.paymentMethods?.map((pm: any) => ({
32+
id: pm.id,
33+
type: pm.type,
34+
last4: pm.card?.last4 || '',
35+
brand: pm.card?.brand || '',
36+
exp_month: pm.card?.exp_month || 0,
37+
exp_year: pm.card?.exp_year || 0,
38+
isDefault: pm.isDefault || false
39+
})) || [];
40+
41+
return paymentMethods;
3042
} catch (error) {
3143
console.error('❌ SUPABASE: Erreur chargement cartes:', error);
3244
return [];
@@ -39,6 +51,7 @@ export const paymentMethodService = {
3951
try {
4052
const { supabase } = await import('@/integrations/supabase/client');
4153

54+
// Utiliser la méthode POST avec action delete
4255
const { error } = await supabase.functions.invoke('stripe-payment-methods', {
4356
body: {
4457
action: 'delete',
@@ -64,10 +77,10 @@ export const paymentMethodService = {
6477
try {
6578
const { supabase } = await import('@/integrations/supabase/client');
6679

80+
// Utiliser la méthode POST avec action set_default
6781
const { error } = await supabase.functions.invoke('stripe-payment-methods', {
6882
body: {
69-
action: 'setDefault',
70-
userEmail,
83+
action: 'set_default',
7184
paymentMethodId
7285
}
7386
});

src/utils/stripeUtils.ts

Lines changed: 31 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,4 @@
1-
2-
import { functions } from '@/lib/firebase';
3-
import { httpsCallable } from 'firebase/functions';
4-
5-
// Configuration Stripe sécurisée via variables d'environnement
1+
// Configuration Stripe - Note: pas de clé publique nécessaire pour les Edge Functions
62
export const STRIPE_PUBLIC_KEY = import.meta.env.VITE_STRIPE_PUBLIC_KEY || '';
73

84
export interface CreatePaymentSetupRequest {
@@ -13,44 +9,58 @@ export interface CreatePaymentSetupRequest {
139

1410
export interface CreatePaymentSetupResponse {
1511
setupIntentId: string;
16-
checkoutUrl: string;
1712
clientSecret: string;
13+
customerId: string;
1814
}
1915

20-
// Fonction pour créer un SetupIntent Stripe via Firebase
16+
// Fonction pour créer un SetupIntent Stripe via Supabase Edge Function
2117
export const createPaymentSetup = async (data: CreatePaymentSetupRequest): Promise<CreatePaymentSetupResponse> => {
22-
console.log('🔄 FIREBASE: Création réelle du setup de paiement pour:', data.campaignName);
18+
console.log('🔄 SUPABASE: Création réelle du setup de paiement pour:', data.campaignName);
2319

2420
try {
25-
const createSetup = httpsCallable(functions, 'stripeCreateSetup');
26-
const result = await createSetup(data);
27-
const setupData = result.data as CreatePaymentSetupResponse;
21+
const { supabase } = await import('@/integrations/supabase/client');
22+
23+
const { data: setupData, error } = await supabase.functions.invoke('stripe-setup-intent', {
24+
body: { campaignName: data.campaignName }
25+
});
26+
27+
if (error) {
28+
console.error('❌ SUPABASE: Erreur création setup:', error);
29+
throw new Error(`Erreur lors de la création du setup: ${error.message}`);
30+
}
2831

29-
console.log('✅ FIREBASE: Setup de paiement créé:', setupData.setupIntentId);
32+
console.log('✅ SUPABASE: Setup de paiement créé:', setupData.setupIntentId);
3033
return setupData;
3134
} catch (error: any) {
32-
console.error('❌ FIREBASE: Erreur création setup:', error);
35+
console.error('❌ SUPABASE: Erreur création setup:', error);
3336
throw new Error(`Erreur lors de la création du setup: ${error.message}`);
3437
}
3538
};
3639

37-
// Fonction pour vérifier le statut d'un SetupIntent via Firebase
40+
// Fonction pour vérifier le statut d'un SetupIntent via Supabase Edge Function
3841
export const checkPaymentSetupStatus = async (setupIntentId: string): Promise<{ status: string; paymentMethod?: string }> => {
39-
console.log('🔄 FIREBASE: Vérification réelle du statut pour:', setupIntentId);
42+
console.log('🔄 SUPABASE: Vérification réelle du statut pour:', setupIntentId);
4043

4144
try {
42-
const checkSetup = httpsCallable(functions, 'stripeCheckSetup');
43-
const result = await checkSetup({ setupIntentId });
44-
const data = result.data as any;
45+
const { supabase } = await import('@/integrations/supabase/client');
4546

46-
console.log('✅ FIREBASE: Statut vérifié:', data.success ? 'success' : 'failed');
47+
const { data, error } = await supabase.functions.invoke('stripe-check-setup', {
48+
body: { setupIntentId }
49+
});
50+
51+
if (error) {
52+
console.error('❌ SUPABASE: Erreur vérification statut:', error);
53+
throw new Error(`Erreur lors de la vérification: ${error.message}`);
54+
}
55+
56+
console.log('✅ SUPABASE: Statut vérifié:', data.success ? 'success' : 'failed');
4757

4858
return {
4959
status: data.success ? 'succeeded' : 'failed',
5060
paymentMethod: data.paymentMethodId,
5161
};
5262
} catch (error: any) {
53-
console.error('❌ FIREBASE: Erreur vérification statut:', error);
63+
console.error('❌ SUPABASE: Erreur vérification statut:', error);
5464
throw new Error(`Erreur lors de la vérification: ${error.message}`);
5565
}
5666
};
@@ -72,4 +82,4 @@ export const calculateMonthlyCommissions = (conversions: any[], period: string):
7282
export const calculateFees = (revenue: number): number => {
7383
if (revenue < 20) return 0;
7484
return revenue * 0.025;
75-
};
85+
};

0 commit comments

Comments
 (0)