diff --git a/src/pages/Configuracoes.tsx b/src/pages/Configuracoes.tsx index ca7c014..9eda431 100644 --- a/src/pages/Configuracoes.tsx +++ b/src/pages/Configuracoes.tsx @@ -1,4 +1,3 @@ - import { Tabs, TabsList, TabsTrigger, TabsContent } from "@/components/ui/tabs"; import MeuCadastroForm from "@/components/settings/MeuCadastroForm"; import { useState } from "react"; @@ -16,6 +15,7 @@ import { import { format } from "date-fns"; import { ptBR } from "date-fns/locale"; import { toast } from "sonner"; +import { supabase } from "@/integrations/supabase/client"; const Configuracoes = () => { const [tab, setTab] = useState("visao-geral"); @@ -28,47 +28,29 @@ const Configuracoes = () => { const handleSubscribe = async () => { setIsSubscribing(true); - // TODO: O e-mail do usuário deve ser obtido dinamicamente do estado de autenticação. - const userEmail = "test@example.com"; - - const body = { - reason: "Plano Mensal Finance Home", - auto_recurring: { - frequency: 1, - frequency_type: "months", - transaction_amount: 14.99, - currency_id: "BRL" - }, - back_url: "https://meusite.com/sucesso", - payer_email: userEmail - }; - try { - const response = await fetch("https://api.mercadopago.com/preapproval", { - method: "POST", - headers: { - // ATENÇÃO: O ideal é que este token não esteja no código do frontend. - // Deve ser movido para uma variável de ambiente segura no backend. - "Authorization": "Bearer APP_USR-7056966967213571-061515-4157ceccce3dbae552ddee5cd5ec685e-163267528", - "Content-Type": "application/json" - }, - body: JSON.stringify(body) - }); + // A edge function buscará o e-mail do usuário a partir da sessão de autenticação. + const { data, error } = await supabase.functions.invoke('mercado-pago-subscribe'); - const data = await response.json(); - - if (!response.ok) { - throw new Error(data.message || "Erro ao criar a assinatura."); + if (error) { + // Lida com erros de rede ou falhas na invocação da função. + throw new Error(`Erro de comunicação: ${error.message}`); + } + + if (data.error) { + // Lida com erros retornados pela lógica da função. + throw new Error(data.error); } if (data.init_point) { window.location.href = data.init_point; } else { - throw new Error("URL de checkout não foi encontrada na resposta."); + throw new Error("Não foi possível obter a URL de checkout. Tente novamente."); } } catch (error: any) { - toast.error(error.message || "Ocorreu um erro inesperado. Tente novamente mais tarde."); + console.error("Erro ao criar a assinatura:", error); + toast.error(error.message || "Ocorreu um erro inesperado. Por favor, tente mais tarde."); } finally { setIsSubscribing(false); } diff --git a/supabase/functions/mercado-pago-subscribe/index.ts b/supabase/functions/mercado-pago-subscribe/index.ts new file mode 100644 index 0000000..993662a --- /dev/null +++ b/supabase/functions/mercado-pago-subscribe/index.ts @@ -0,0 +1,86 @@ + +import { serve } from 'https://deno.land/std@0.168.0/http/server.ts' +import { createClient } from 'https://esm.sh/@supabase/supabase-js@2' + +const corsHeaders = { + 'Access-Control-Allow-Origin': '*', + 'Access-Control-Allow-Headers': 'authorization, x-client-info, apikey, content-type', +} + +serve(async (req) => { + // Necessário para invocações a partir do navegador + if (req.method === 'OPTIONS') { + return new Response('ok', { headers: corsHeaders }) + } + + try { + // Cria um cliente Supabase com o contexto de autenticação do usuário logado. + const supabaseClient = createClient( + Deno.env.get('SUPABASE_URL') ?? '', + Deno.env.get('SUPABASE_ANON_KEY') ?? '', + { global: { headers: { Authorization: req.headers.get('Authorization')! } } } + ) + + // Obtém o usuário a partir da sessão + const { data: { user } } = await supabaseClient.auth.getUser() + + if (!user || !user.email) { + return new Response(JSON.stringify({ error: 'Usuário não autenticado ou e-mail não encontrado.' }), { + headers: { ...corsHeaders, 'Content-Type': 'application/json' }, + status: 401, + }) + } + + const MERCADO_PAGO_ACCESS_TOKEN = Deno.env.get('MERCADO_PAGO_ACCESS_TOKEN') + if (!MERCADO_PAGO_ACCESS_TOKEN) { + return new Response(JSON.stringify({ error: 'Chave de acesso do Mercado Pago não configurada no servidor.' }), { + headers: { ...corsHeaders, 'Content-Type': 'application/json' }, + status: 500, + }) + } + + const body = { + reason: "Plano Mensal Finance Home", + auto_recurring: { + frequency: 1, + frequency_type: "months", + transaction_amount: 14.99, + currency_id: "BRL" + }, + back_url: req.headers.get("origin") || "http://localhost:5173/configuracoes", + payer_email: user.email + }; + + const mpResponse = await fetch("https://api.mercadopago.com/preapproval", { + method: "POST", + headers: { + "Authorization": `Bearer ${MERCADO_PAGO_ACCESS_TOKEN}`, + "Content-Type": "application/json" + }, + body: JSON.stringify(body) + }); + + const mpData = await mpResponse.json(); + + if (!mpResponse.ok) { + console.error('Erro da API do Mercado Pago:', mpData); + throw new Error(mpData.message || "Erro ao criar a assinatura no Mercado Pago."); + } + + if (!mpData.init_point) { + throw new Error("URL de checkout não foi encontrada na resposta do Mercado Pago."); + } + + return new Response(JSON.stringify({ init_point: mpData.init_point }), { + headers: { ...corsHeaders, 'Content-Type': 'application/json' }, + status: 200, + }) + + } catch (error) { + return new Response(JSON.stringify({ error: error.message }), { + headers: { ...corsHeaders, 'Content-Type': 'application/json' }, + status: 500, + }) + } +}) +