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 via checkout hospedado, defina 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. Mais tarde, você cria cobranças contra essa assinatura com valores personalizados usando o endpoint de cobrança dedicado.
  3. Você escuta 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
Sobrescrição de moeda opcional para a cobrança.
product_description
string
Sobrescrição de descrição opcional para esta cobrança.
adaptive_currency_fees_inclusive
boolean
Se verdadeiro, inclui taxas de moeda adaptativa 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. Certifique-se de 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 tentativas em massa podem ser sinalizados como fraudulentos ou suspeitos de teste de cartão pelos nossos sistemas de risco e processadores. Evite tentativas agrupadas; siga o cronograma de recuo e as orientações de alinhamento de tempo abaixo.

Princípios para políticas de tentativas seguras

  • Mecanismo de recuo: Use recuo exponencial entre as tentativas.
  • Limites de tentativas: Limite o total de tentativas (máximo de 3 a 4 tentativas).
  • Filtragem inteligente: Tente novamente apenas em falhas recuperáveis (por exemplo, erros de rede/emissor, fundos insuficientes); nunca tente novamente em recusas definitivas.
  • Prevenção de testes de cartão: Não tente novamente falhas como DO_NOT_HONOR, STOLEN_CARD, LOST_CARD, PICKUP_CARD, FRAUDULENT, AUTHENTICATION_FAILURE.
  • Variar metadados (opcional): Se você mantiver seu próprio sistema de tentativas, diferencie as tentativas por meio de 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

  • Ancore as tentativas ao timestamp de autorização original para evitar comportamento de “explosão” em seu portfólio.
  • Exemplo: Se o cliente iniciar um teste ou mandato às 13h10 de hoje, agende tentativas de acompanhamento às 13h10 nos dias subsequentes conforme seu recuo (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 DST: use um padrão de horário consistente para agendamento e converta apenas para exibição para 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 razões de recusa e se são corrigíveis pelo usuário, consulte a documentação de Falhas de Transação.
Tente novamente apenas em problemas temporários/suaves (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 exato deslocamento de horário (por exemplo, T + 3 days no mesmo HH:MM).
  • Mantenha e faça referência ao timestamp do último pagamento bem-sucedido T para calcular a próxima tentativa; não agrupe várias assinaturas no mesmo instante.
  • Sempre avalie a última razão de recusa; pare as tentativas para recusas definitivas na lista de exclusão acima.
  • Limite tentativas simultâneas por cliente e por conta para evitar picos acidentais.
  • Comunique-se proativamente: envie um 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 irrelevantes.

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

Criar em modo de teste

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

Acionar uma cobrança

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

Ir ao vivo

Mude para sua chave de API ao vivo assim que você tiver validado eventos e atualizações de estado interno.

Solução de problemas

  • 422 Solicitação Inválida: Certifique-se de 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 é suportado para sua conta e cliente.
  • Nenhum webhook recebido: Verifique sua URL de webhook e a configuração do segredo da assinatura.