Documentation Index
Fetch the complete documentation index at: https://docs.pagamentos.dev/llms.txt
Use this file to discover all available pages before exploring further.
O que são plugins?
Plugins são bibliotecas de terceiros que empacotam hooks do pagamentos.dev em módulos reutilizáveis. Eles permitem que você compartilhe integrações prontas — como envio de e-mails, auditoria, analytics, sincronização com CRMs, etc. — sem repetir código entre projetos.
Um plugin nada mais é do que uma função (ou conjunto de funções) que retorna hooks configurados. Você os registra da mesma forma que hooks manuais:
import { Pagamentos, mercadopago } from 'pagamentos'
import { pluginAnalytics } from 'pagamentos-plugin-analytics'
import { pluginAuditLog } from 'pagamentos-plugin-audit'
const pg = new Pagamentos({
providers: [mercadopago({ accessToken: '...' })],
hooks: [
...pluginAnalytics({ tracker: 'segment' }),
...pluginAuditLog({ database: db })
]
})
Arquitetura de um plugin
A base de todo plugin são os hooks. Um plugin expõe hooks de lifecycle, webhooks, ou ambos:
// pagamentos-plugin-analytics/index.ts
import type { LifecycleHook, WebhookHook } from 'pagamentos'
import { onCobrancaCreated, onWebhookEvent } from 'pagamentos'
export interface AnalyticsPluginOptions {
tracker: 'segment' | 'mixpanel' | 'posthog'
apiKey: string
}
export function pluginAnalytics(
options: AnalyticsPluginOptions
): (LifecycleHook | WebhookHook)[] {
const client = createTracker(options.tracker, options.apiKey)
return [
// Lifecycle: rastreia criação de cobranças
onCobrancaCreated(async (evt) => {
client.track('cobranca_criada', {
valor: evt.input.valor,
metodo: evt.input.metodoPagamento,
provider: evt.provider
})
}),
// Webhook: rastreia conversão
onWebhookEvent('pagamento.realizado', async (event) => {
client.track('pagamento_convertido', {
cobrancaId: event.data.cobranca.id,
valor: event.data.cobranca.valor,
provider: event.provider
})
})
]
}
Tipos de plugin
Plugin de lifecycle
Reage a operações de API que você realiza. Útil para ações síncronas e previsíveis:
import { onClienteCreated, onCobrancaCancelled } from 'pagamentos'
export function pluginSyncDatabase(db: Database) {
return [
onClienteCreated(async (evt) => {
await db.clientes.upsert({
id: evt.output.id,
nome: evt.input.nome,
documento: evt.input.documento
})
}),
onCobrancaCancelled(async (evt) => {
await db.cobrancas.update({
id: evt.output.id,
status: 'cancelado',
canceladoEm: new Date()
})
})
]
}
Plugin de webhook
Reage a eventos assíncronos enviados pelo provedor. Útil para processar mudanças de status que acontecem fora do seu fluxo:
import { onWebhookEvent } from 'pagamentos'
export function pluginNotificacoesEmail(sender: EmailSender) {
return [
onWebhookEvent('pagamento.realizado', async (event) => {
await sender.send({
to: event.data.cliente?.email,
template: 'pagamento_confirmado',
vars: {
nome: event.data.cliente?.nome,
valor: event.data.cobranca.valor
}
})
}),
onWebhookEvent('cobranca.vencida', async (event) => {
await sender.send({
to: event.data.cobranca.cliente.email,
template: 'cobranca_vencida',
vars: {
linkPagamento: event.data.cobranca.url
}
})
})
]
}
Plugin híbrido
Combina lifecycle e webhook hooks para cobrir todo o ciclo de vida:
import { onCobrancaCreated, onWebhookEvent } from 'pagamentos'
export function pluginSlack(webhookUrl: string) {
return [
onCobrancaCreated(async (evt) => {
await notifySlack(webhookUrl, {
text: `Nova cobrança de R$ ${evt.input.valor / 100} criada`
})
}),
onWebhookEvent('pagamento.realizado', async (event) => {
await notifySlack(webhookUrl, {
text: `Pagamento confirmado: R$ ${event.data.cobranca.valor / 100}`
})
})
]
}
Boas práticas para autores de plugins
1. Não quebre o fluxo principal
Hooks que falham podem impactar o fluxo do usuário. Sempre envolva lógica externa em try/catch:
export function pluginSeguro(handler: () => Promise<void>) {
return onCobrancaCreated(async (evt) => {
try {
await handler()
} catch (error) {
// Loga o erro, mas não propaga para não quebrar o fluxo
console.error('[meu-plugin] Falha ao processar hook:', error)
}
})
}
Lifecycle hooks que lançam exceções interrompem o retorno da operação principal para o chamador. Veja a página de Hooks para mais detalhes sobre o comportamento de erro.
2. Seja idempotente
Webhooks podem ser entregues mais de uma vez. Plugins que processam webhooks devem verificar se o evento já foi tratado:
onWebhookEvent('pagamento.realizado', async (event) => {
const jaProcessado = await db.eventos.exists({ id: event.id })
if (jaProcessado) return
await liberarProduto(event.data.cobranca.id)
await db.eventos.insert({ id: event.id, processadoEm: new Date() })
})
3. Documente os eventos suportados
Deixe claro quais hooks o plugin registra e em que momento eles disparam:
## Eventos
- `onCobrancaCreated` — dispara após `pg.cobrancas.create()`
- `onWebhookEvent('pagamento.realizado')` — dispara quando o provedor confirma o pagamento
4. Aceite opções, não dependências globais
Receba clientes e configurações via argumentos em vez de importar variáveis globais:
// Bom
export function pluginMeuCRM(client: MeuCRMClient, options?: { debug?: boolean })
// Evite
export function pluginMeuCRM() // usa process.env.MEU_CRM_TOKEN implicitamente
5. Use tipagem forte
Exporte as interfaces de opções para que os usuários tenham autocomplete:
export interface PluginMeuPluginOptions {
apiKey: string
ambiente: 'producao' | 'sandbox'
}
export function pluginMeuPlugin(options: PluginMeuPluginOptions) {
// ...
}
Publicando um plugin
Plugins são pacotes npm comuns. A estrutura mínima recomendada é:
pagamentos-plugin-meu-plugin/
├── package.json
├── tsconfig.json
├── src/
│ └── index.ts
└── README.md
No package.json, declare o pagamentos como peerDependency:
{
"name": "pagamentos-plugin-meu-plugin",
"peerDependencies": {
"pagamentos": "^0.x"
},
"devDependencies": {
"pagamentos": "file:../pagamentos"
}
}
Isso evita múltiplas cópias do SDK no node_modules do usuário e garante que os tipos sejam compatíveis.
Exemplo completo: Plugin de Cache
// pagamentos-plugin-cache/index.ts
import {
type LifecycleHook,
onCobrancaCreated,
onCobrancaRetrieved,
onCobrancaUpdated,
onClienteCreated,
onClienteRetrieved,
onClienteUpdated
} from 'pagamentos'
export interface CachePluginOptions {
adapter: CacheAdapter // { get(key), set(key, value, ttl), del(key) }
ttl?: number // segundos
}
export function pluginCache(options: CachePluginOptions): LifecycleHook[] {
const { adapter, ttl = 300 } = options
return [
// Invalida cache em mutações
onCobrancaCreated(async (evt) => {
await adapter.del(`cobrancas:list:${evt.input.cliente?.documento}`)
}),
onCobrancaUpdated(async (evt) => {
await adapter.del(`cobrancas:${evt.output.id}`)
}),
// Popula cache em consultas
onCobrancaRetrieved(async (evt) => {
await adapter.set(
`cobrancas:${evt.output.id}`,
evt.output,
ttl
)
}),
onClienteRetrieved(async (evt) => {
await adapter.set(
`clientes:${evt.output.id}`,
evt.output,
ttl
)
}),
onClienteCreated(async (evt) => {
await adapter.del('clientes:list')
}),
onClienteUpdated(async (evt) => {
await adapter.del(`clientes:${evt.output.id}`)
await adapter.del('clientes:list')
})
]
}
Uso:
import { Pagamentos, mercadopago } from 'pagamentos'
import { pluginCache } from 'pagamentos-plugin-cache'
import { redis } from './redis'
const pg = new Pagamentos({
providers: [mercadopago({ accessToken: '...' })],
hooks: [
...pluginCache({ adapter: redis, ttl: 600 })
]
})