Busque em todas as páginas da documentação
🤖 Read the SystemsArchitect.io Blog for over 100+ cloud architecture articles 🔥
Instale os três pacotes Stripe, configure variáveis de ambiente, crie instâncias Stripe do servidor e do cliente, e envolva seu aplicativo com o provedor Elements.
npm install stripe @stripe/stripe-js @stripe/react-stripe-jsConfigure as variáveis de ambiente em .env.local:
STRIPE_SECRET_KEY=sk_test_...
NEXT_PUBLIC_STRIPE_PUBLISHABLE_KEY=pk_test_...Crie a instância Stripe do lado do servidor:
// lib/stripe.ts
import Stripe from "stripe";
export const stripe = new Stripe(process.env.STRIPE_SECRET_KEY!, {
apiVersion: "2024-12-18.acacia",
typescript: true,
});Crie o carregador Stripe do lado do cliente:
// lib/stripe-client.ts
import { loadStripe } from "@stripe/stripe-js";
export const stripePromise = loadStripe(
process.env.NEXT_PUBLIC_STRIPE_PUBLISHABLE_KEY!
);Envolva seu aplicativo com o provedor Elements:
// app/providers.tsx
"use client";
import { Elements } from "@stripe/react-stripe-js";
import { stripePromise } from "@/lib/stripe-client";
export function StripeProvider({ children }: { children: React.ReactNode }) {
return <Elements stripe={stripePromise}>{children}</Elements>;
}// app/layout.tsx
import { StripeProvider } from "./providers";
export default function RootLayout({ children }: { children: React.ReactNode }) {
return (
<html lang="en">
<body>
<StripeProvider>{children}</StripeProvider>
</body>
</html>
);
}// app/checkout/page.tsx
"use client";
import { useStripe, useElements } from "@stripe/react-stripe-js";
export default function CheckoutPage() {
const stripe = useStripe();
const elements = useElements();
if (!stripe || !elements) {
return <div>Carregando Stripe...</div>;
}
return (
<div>
<h1>Checkout</h1>
<p>Stripe carregado com sucesso. Pronto para aceitar pagamentos.</p>
<p>
Use o cartão de teste: <code>4242 4242 4242 4242</code> com qualquer
data de validade futura e qualquer CVC.
</p>
</div>
);
}stripe do npm é o SDK Node.js do lado do servidor. Ele deve ser importado apenas em código do servidor (Server Actions, Route Handlers, componentes do servidor).@stripe/stripe-js fornece a função loadStripe que carrega assincronamente o script Stripe.js do CDN da Stripe. Isso simplifica a conformidade PCI, pois os dados do cartão nunca tocam seu servidor.@stripe/react-stripe-js fornece componentes React (Elements, PaymentElement, CardElement) e hooks (useStripe, useElements) que envolvem o Stripe.js.Elements deve envolver qualquer componente que use hooks ou elementos Stripe. Ele inicializa o Stripe.js e o disponibiliza via React Context.loadStripe retorna uma Promise que resolve assim que o script carrega. Passar essa Promise diretamente para Elements é o padrão recomendado -- ele lida com o carregamento assíncrono internamente.Carregar Elements sob demanda apenas em páginas de checkout:
// app/checkout/layout.tsx
"use client";
import { Elements } from "@stripe/react-stripe-js";
import { stripePromise } from "@/lib/stripe-client";
export default function CheckoutLayout({
children,
}: {
children: React.ReactNode;
}) {
return <Elements stripe={stripePromise}>{children}</Elements>;
}Passar um segredo do cliente para Elements para fluxos de PaymentIntent:
<Elements
stripe={stripePromise}
options={{ clientSecret: "pi_xxx_secret_yyy" }}
>
{children}
</Elements>Stripe do pacote stripe é tipado com a versão da API. Sempre passe uma apiVersion explícita para evitar incompatibilidades de tipo.loadStripe retorna Promise<Stripe | null>. O componente Elements lida com o caso null internamente.Stripe como um tipo de stripe para tipagem do lado do servidor, e Stripe de @stripe/stripe-js para tipagem do lado do cliente. São tipos diferentes.// Tipo do lado do servidor
import type Stripe from "stripe";
// Tipo do lado do cliente
import type { Stripe as StripeJS } from "@stripe/stripe-js";stripe (SDK do servidor) em componentes cliente. Isso expõe sua chave secreta e falhará no tempo de compilação.NEXT_PUBLIC_ para estar disponível em código do lado do cliente no Next.js.loadStripe deve ser chamado fora dos componentes (no escopo do módulo) para evitar recriar a instância Stripe a cada renderização.apiVersion passada para o SDK do servidor deve corresponder à versão para a qual seu Painel Stripe está configurado. Fixá-la evita surpresas quando a Stripe lança novas versões da API.| Número do Cartão | Cenário |
|---|---|
| 4242 4242 4242 4242 | Pagamento bem-sucedido |
| 4000 0000 0000 3220 | Autenticação 3D Secure necessária |
| 4000 0000 0000 9995 | Recusado (fundos insuficientes) |
| 4000 0000 0000 0002 | Recusa genérica |
| 4000 0025 0000 3155 | Autenticação necessária |
Use qualquer data de validade futura e qualquer CVC de 3 dígitos para todos os cartões de teste.
| Abordagem | Prós | Contras |
|---|---|---|
| Provedor Elements Global | Configuração simples, funciona em todos os lugares | Carrega Stripe.js em todas as páginas |
| Wrapper Elements por página | Carrega Stripe apenas em páginas de checkout | Requer envolver cada página de pagamento |
| Importação dinâmica de Elements | Menor bundle inicial | Configuração mais complexa, pequeno atraso no checkout |
stripe -- SDK Node.js do lado do servidor para chamar a API Stripe@stripe/stripe-js -- carregador do lado do cliente (loadStripe) que busca Stripe.js do CDN@stripe/react-stripe-js -- componentes React (Elements, PaymentElement) e hooks (useStripe, useElements)O Next.js só expõe variáveis de ambiente para código do lado do cliente se elas começarem com NEXT_PUBLIC_. Sem o prefixo, a variável é undefined no navegador e loadStripe falhará silenciosamente.
stripe depende de APIs do Node.js não disponíveis no navegadorChamar dentro do corpo de um componente reexecutaria a cada renderização, criando uma nova instância Stripe a cada vez. Chamar no escopo do módulo garante uma única Promise compartilhada que resolve uma vez.
useStripe, useElements ou componentes Stripe Element deve ser um descendente de <Elements>loadStripe diretamente e lida com o carregamento assíncrono internamenteEnvolva apenas o layout.tsx da rota de checkout com o provedor <Elements> em vez do layout raiz. Dessa forma, o Stripe.js não é carregado em páginas que não o necessitam.
Ela fixa a versão da API Stripe que seu código espera. Sem ela, a Stripe usa a versão padrão do seu Painel, que pode mudar e causar comportamentos inesperados que quebram a compatibilidade.
São tipos completamente diferentes. O Stripe do lado do servidor (de stripe) tipa o SDK do Node. O Stripe do lado do cliente (de @stripe/stripe-js) tipa a instância Stripe.js do navegador. Importe-os separadamente usando import type.
import type Stripe from "stripe"; // servidor
import type { Stripe as StripeJS } from "@stripe/stripe-js"; // cliente<Elements
stripe={stripePromise}
options={{ clientSecret: "pi_xxx_secret_yyy" }}
>
{children}
</Elements>loadStripe retorna Promise<Stripe | null>. Ele resolve para null se o script falhar ao carregar. O componente <Elements> lida com isso internamente -- hooks como useStripe retornarão null até que o carregamento seja bem-sucedido.
function StripeProvider({ children }: { children: React.ReactNode }) {
return <Elements stripe={stripePromise}>{children}</Elements>;
}children é tipado como React.ReactNode. A prop stripe em <Elements> aceita Promise<Stripe | null> | Stripe | null.
Não. Chaves de teste (sk_test_, pk_test_) e chaves ao vivo (sk_live_, pk_live_) operam em ambientes completamente separados. Misturá-las (por exemplo, servidor usa ao vivo, cliente usa teste) causará erros de API. Sempre use pares correspondentes.
Revisado por Chris St. John·Última atualização: 7 de jul. de 2026
🤖 Read the SystemsArchitect.io Blog for over 100+ cloud architecture articles 🔥