Pular para o conteúdo principal

Payments

Integracao de deposito e saque no template. Suporta PIX (Brasil), SPEI/OXXO (Mexico), Wallet/MACH (Chile), Credit Card, Checkout Page, Redirect e outros metodos via @cactus-agents/payments.

Arquitetura

usePayments() hook
|
+---> Store Zustand (payments.ts)
+---> API Routes (server-side, token HttpOnly)
| |
| v
| @cactus-agents/payments (SDK)
| |
| v
| Backend API
|
+---> Componentes (DepositModal, WithdrawModal)

Como o token JWT fica em cookie HttpOnly, todas as chamadas de pagamento passam por API routes no servidor.

Arquivos principais

ArquivoTipoDescricao
store/payments.tsStore (Zustand)Estado dos modais, providers, metodo selecionado, cupom
hooks/usePayments.tsHookOrquestra fetch providers, submit deposit/withdraw, polling
config/deposit.config.tsConfigAtalhos de valor por moeda (fork-overridable)
components/payments/DepositModal.tsxComponentModal de deposito
components/payments/WithdrawModal.tsxComponentModal de saque
components/payments/LazyPaymentModals.tsxComponentLazy wrapper

Store — usePaymentsStore

interface PaymentsState {
paymentModal: "deposit" | "withdraw" | null;
providers: PaymentProviders | null;
providersLoading: boolean;
selectedDepositMethod: PaymentMethodSlug | null;
selectedWithdrawMethod: PaymentMethodSlug | null;
depositLoading: boolean;
withdrawLoading: boolean;
coupon: CouponData | null;
}

Hook — usePayments()

Retorna estado derivado e actions:

Estado derivado

PropriedadeDescricao
depositMethodsProviders de deposito filtrados pela moeda da marca
withdrawMethodsProviders de saque filtrados pela moeda da marca
minDeposit / maxDepositLimites de deposito (do brand settings, fallback 100 / 4.900.000)
minWithdraw / maxWithdrawLimites de saque (do brand settings, fallback 100 / 50.000)
currency / countryMoeda e pais do ambiente

Actions

ActionDescricao
fetchProviders()Busca providers disponiveis
submitDeposit(payload)Envia deposito
checkDepositStatus(transactionId)Polling do status do deposito
submitWithdraw(payload)Envia saque
fetchBankList()Lista de bancos disponiveis
fetchPixKey()Busca chave PIX do usuario
updatePixKey(payload)Atualiza chave PIX

API Routes

RotaMetodoDescricao
api/payments/providersGETProviders de deposito/saque
api/payments/depositPOSTSubmit deposito
api/payments/deposit-statusPOSTStatus do deposito (polling)
api/payments/withdrawPOSTSubmit saque
api/payments/bank-listGETLista de bancos
api/payments/pix-keyPOSTGet/update chave PIX
api/payments/couponPOSTValidar cupom

Configuracao — deposit.config.ts

Define atalhos de valor por moeda (fork-overridable):

export const depositConfig: DepositConfig = {
shortcuts: {
BRL: [
{ value: 20 }, { value: 50, hot: true }, { value: 100 },
{ value: 250, hot: true }, { value: 500 }, { value: 1000, hot: true },
],
MXN: [
{ value: 200 }, { value: 500 }, { value: 1000, hot: true },
{ value: 2500, hot: true }, { value: 5000 }, { value: 10000, hot: true },
],
CLP: [
{ value: 5000 }, { value: 20000, hot: true }, { value: 50000, hot: true },
{ value: 200000 }, { value: 400000, hot: true }, { value: 800000 },
],
PEN: [
{ value: 20 }, { value: 50, hot: true }, { value: 100 },
{ value: 250, hot: true }, { value: 500 }, { value: 1000, hot: true },
],
EUR: [
{ value: 10 }, { value: 25, hot: true }, { value: 50 },
{ value: 100, hot: true }, { value: 250 }, { value: 500, hot: true },
],
// ARS, COP, UYU, INR...
},
defaultShortcuts: [
{ value: 20 }, { value: 50, hot: true }, { value: 100 },
{ value: 250, hot: true }, { value: 500 }, { value: 1000, hot: true },
],
};

Moedas com atalhos: BRL, MXN, ARS, CLP, COP, UYU, INR, PEN, EUR. Moedas sem configuracao usam defaultShortcuts.

Componentes de deposito

DepositModal

Fluxo completo de deposito com routing automatico de resultado baseado no tipo de metodo:

  1. MethodSelector — selecao do metodo
  2. DepositForm — valor + campo especifico do metodo (+ CreditCardFields para credit-card-2)
  3. Resultado — roteado automaticamente pelo classificador do SDK:
ClassificadorComponenteDescricao
isPixMethodDepositResultPixQR code + copia-e-cola + countdown + polling
isSpeiMethodDepositResultSpeiCLABE + barcode + countdown
isWalletMethodDepositResultWalletQR + deep-link (MACH) + countdown + polling
isCheckoutPageMethodDepositResultCheckoutPageIframe com checkout_page (credit-card, bank-transfer, khipu)
isCreditCardFormMethodDepositResultCreditCardTela de confirmacao pos-submit
isRedirectMethodDepositResultRedirectIframe com URL (astropay, worldline, prontopaga, crypto)
isExternalRedirectMethodDepositResultExternalRedirectAbre nova aba + tela informativa

WithdrawModal

  1. MethodSelector — selecao do metodo
  2. WithdrawForm — valor + dados especificos:
    • PIX: PixKeySelector (tipo + valor da chave)
    • SPEI: tipo de conta (CLABE/debito/telefone) + numero
    • Bank-transfer (CHL): tipo de conta + codigo banco + numero
    • Wallet (CHL): info do usuario (email + documento)
    • AstroPay: telefone com DDI
  3. WithdrawConfirm — confirmacao e senha

Componentes compartilhados

  • CurrencyInput — input de valor com mascara de moeda. Aceita countryCodeAlpha3 opcional para resolucao de flag. Usa @cactus-agents/country-config (getCountriesByCurrency, getCountryByAlpha3) para descobrir o pais a partir da moeda.
  • AmountShortcuts — botoes de atalho de valor
  • CopyableField — campo com botao de copiar (para PIX, CLABE)
  • PixKeySelector — seletor de tipo de chave PIX
  • CreditCardFields — formulario de cartao (numero, nome, vencimento, CVV) com icones de bandeiras
  • DepositCoupon — campo de cupom promocional

Icones de pagamento

Os icones SVG dos metodos de pagamento sao fornecidos pelo pacote @cactus-agents/payments/icons/. Um plugin Vite (copyPaymentIcons em vite.config.ts) copia automaticamente os icones para public/icons/ no build e dev server.

A pasta public/icons/payments/ esta no .gitignore — nao precisa commitar os icones, eles sao auto-gerados.

Para adicionar novos icones, coloque o SVG em front-cactus-core/packages/payments/icons/payments/ e publique uma nova versao do pacote.

Abrindo o modal programaticamente

import { usePaymentsStore } from "~/store/payments";

const openPaymentModal = usePaymentsStore((s) => s.openPaymentModal);

openPaymentModal("deposit"); // abre deposito
openPaymentModal("withdraw"); // abre saque