Pular para o conteúdo principal

Visão Geral

As assinaturas sob demanda permitem que você autorize o método de pagamento de um cliente uma vez e, em seguida, cobre valores variáveis sempre que precisar, em vez de em um cronograma fixo. Esse recurso está disponível para todas as contas—sem aprovação necessária. Use este guia para:
  • Criar uma assinatura sob demanda (autorizar um mandato com preço inicial opcional)
  • Acionar cobranças subsequentes com valores personalizados
  • Rastrear resultados usando webhooks
Para uma configuração geral de assinatura, consulte o Guia de Integração de Assinatura.

Pré-requisitos

  • Conta de comerciante Dodo Payments e chave de API
  • Segredo do webhook configurado e um endpoint para receber eventos
  • Um produto de assinatura em seu catálogo
Se você quiser que o cliente aprove o mandato por meio do checkout hospedado, configure payment_link: true e forneça um return_url.

Como funciona a assinatura sob demanda

  1. Você cria uma assinatura com o objeto on_demand para autorizar um método de pagamento e opcionalmente coletar uma cobrança inicial.
  2. Depois, você gera cobranças para essa assinatura com valores personalizados usando o endpoint dedicado de cobrança.
  3. Você monitora webhooks (por exemplo, payment.succeeded, payment.failed) para atualizar seu sistema.

Criar uma assinatura sob demanda

Endpoint: POST /checkouts Campos de solicitação chave (corpo):
Consulte-os em Criar Sessão de Checkout

Criar uma assinatura sob demanda

import DodoPayments from 'dodopayments';

const client = new DodoPayments({
  bearerToken: process.env.DODO_PAYMENTS_API_KEY,
  environment: 'test_mode', // defaults to 'live_mode'
});

async function main() {
  const subscription = await client.checkoutSessions.create({
    product_cart: [{ product_id: 'pdt_123', quantity: 1 }],
    billing_address:  { city: 'SF', country: 'US', state: 'CA', street: '1 Market St', zipcode: '94105' },
    customer: { customer_id: 'cus_123' },
    return_url: 'https://example.com/billing/success',
    subscription_data: {
        on_demand: {
            mandate_only: true // set false to collect an initial charge
            // product_price: 1000, // optional: charge $10.00 now if mandate_only is false
            // product_currency: 'USD',
            // product_description: 'Custom initial charge',
            // adaptive_currency_fees_inclusive: false,
        }
    }
  });

  console.log(subscription.checkout_url);
}

main().catch(console.error);
Success
{
  "session_id": "cks_123",
  "checkout_url": "https://test.checkout.dodopayments.com/session/cks123"
}

Cobrar uma assinatura sob demanda

Após o mandato ser autorizado, crie cobranças conforme necessário. Endpoint: POST /subscriptions/{subscription_id}/charge Campos de solicitação chave (corpo):
product_price
integer
obrigatório
Valor a ser cobrado (na menor unidade da moeda). Exemplo: para cobrar $25,00, passe 2500.
product_currency
string
Substituição opcional de moeda para a cobrança.
product_description
string
Substituição opcional de descrição para esta cobrança.
adaptive_currency_fees_inclusive
boolean
Se verdadeiro, inclui as taxas de moedas adaptáveis dentro de product_price. Se falso, as taxas são adicionadas por cima.
metadata
object
Metadados adicionais para o pagamento. Se omitido, os metadados da assinatura são usados.
import DodoPayments from 'dodopayments';

const client = new DodoPayments({ bearerToken: process.env.DODO_PAYMENTS_API_KEY });

async function chargeNow(subscriptionId) {
  const res = await client.subscriptions.charge(subscriptionId, { product_price: 2500 });
  console.log(res.payment_id);
}

chargeNow('sub_123').catch(console.error);
Success
{ "payment_id": "pay_abc123" }
Cobrar uma assinatura que não é sob demanda pode falhar. Garanta que a assinatura tenha on_demand: true em seus detalhes antes de cobrar.

Tentativas de pagamento

Nosso sistema de detecção de fraudes pode bloquear padrões de tentativas agressivas (e pode sinalizá-los como testes de cartão potenciais). Siga uma política de tentativas segura.
Padrões de tentativa em rajada podem ser sinalizados como fraudulentos ou suspeita de teste de cartão pelos nossos sistemas de risco e processadores. Evite tentativas agrupadas; siga o cronograma de retrocesso e as orientações de alinhamento de tempo abaixo.

Princípios para políticas de tentativas seguras

  • Mecanismo de retrocesso: use retrocesso exponencial entre as tentativas.
  • Limites de tentativas: limite o total de tentativas (máximo de 3 a 4 tentativas).
  • Filtragem inteligente: reitere apenas em falhas passíveis de nova tentativa (por exemplo, erros de rede/emitente, fundos insuficientes); nunca reitere recusas definitivas.
  • Prevenção de testes de cartão: não reitere falhas como DO_NOT_HONOR, STOLEN_CARD, LOST_CARD, PICKUP_CARD, FRAUDULENT, AUTHENTICATION_FAILURE.
  • Variação de metadados (opcional): se você mantiver seu próprio sistema de tentativa, diferencie as tentativas via metadados (por exemplo, retry_attempt).

Cronograma de tentativas sugerido (assinaturas)

  • 1ª tentativa: Imediata quando você cria a cobrança
  • 2ª tentativa: Após 3 dias
  • 3ª tentativa: Após mais 7 dias (10 dias no total)
  • 4ª tentativa (final): Após mais 7 dias (17 dias no total)
Passo final: se ainda não pago, marque a assinatura como não paga ou cancele-a, com base em sua política. Notifique o cliente durante a janela para atualizar seu método de pagamento.

Evite tentativas em massa; alinhe-se ao horário de autorização

  • Víncule as tentativas ao timestamp de autorização original para evitar comportamento de “rajada” em seu portfólio.
  • Exemplo: se o cliente iniciar um teste ou mandato às 13h10 de hoje, agende as tentativas de acompanhamento às 13h10 nos dias seguintes conforme seu retrocesso (por exemplo, +3 dias → 13h10, +7 dias → 13h10).
  • Alternativamente, se você armazenar o horário do último pagamento bem-sucedido T, agende a próxima tentativa em T + X days para preservar o alinhamento do horário do dia.
Fuso horário e horário de verão: use um padrão de horário consistente para agendar e converta apenas para exibição a fim de manter os intervalos.

Códigos de recusa que você não deve tentar novamente

  • STOLEN_CARD
  • DO_NOT_HONOR
  • FRAUDULENT
  • PICKUP_CARD
  • AUTHENTICATION_FAILURE
  • LOST_CARD
Para uma lista abrangente de motivos de recusa e se eles podem ser corrigidos pelo usuário, consulte a documentação Transaction Failures.
Reitere apenas em problemas temporários/soft (por exemplo, insufficient_funds, issuer_unavailable, processing_error, timeouts de rede). Se a mesma recusa se repetir, pause novas tentativas.

Diretrizes de implementação (sem código)

  • Use um agendador/fila que persista timestamps precisos; calcule a próxima tentativa no deslocamento exato do horário do dia (por exemplo, T + 3 days no mesmo HH:MM).
  • Mantenha e consulte o timestamp do último pagamento bem-sucedido T para calcular a próxima tentativa; não agrupe várias assinaturas no mesmo instante.
  • Sempre avalie o motivo da última recusa; interrompa as tentativas em recusas definitivas da lista acima.
  • Limite as tentativas simultâneas por cliente e por conta para evitar surtos acidentais.
  • Comunique proativamente: envie e-mail/SMS ao cliente para atualizar seu método de pagamento antes da próxima tentativa agendada.
  • Use metadados apenas para observabilidade (por exemplo, retry_attempt); nunca tente “evadir” sistemas de fraude/risco rotacionando campos inconsequentes.

Rastrear resultados com webhooks

Implemente o manuseio de webhooks para rastrear a jornada do cliente. Consulte Implementando Webhooks.
  • subscription.active: Mandato autorizado e assinatura ativada
  • subscription.failed: Criação falhou (por exemplo, falha de mandato)
  • subscription.on_hold: Assinatura colocada em espera (por exemplo, estado não pago)
  • payment.succeeded: Cobrança bem-sucedida
  • payment.failed: Cobrança falhou
Para fluxos sob demanda, concentre-se em payment.succeeded e payment.failed para reconciliar cobranças baseadas em uso.

Testes e próximos passos

1

Create in test mode

Use sua chave de API de teste para criar a assinatura com payment_link: true, depois abra o link e conclua o mandato.
2

Trigger a charge

Chame o endpoint de cobrança com um product_price pequeno (por exemplo, 100) e verifique se você recebe payment.succeeded.
3

Go live

Mude para sua chave de API de produção depois de validar eventos e atualizações de estado internas.

Solução de problemas

  • 422 Invalid Request: garanta que on_demand.mandate_only seja fornecido na criação e product_price seja fornecido para cobranças.
  • Erros de moeda: se você sobrescrever product_currency, confirme se ela é compatível com sua conta e cliente.
  • Nenhum webhook recebido: verifique sua URL de webhook e a configuração do segredo de assinatura.