Pular para o conteúdo principal

O que é um upgrade ou downgrade de assinatura?

Mudar de plano permite que você mova um cliente entre níveis ou quantidades de assinatura. Use isso para:
  • Alinhar preços com uso ou recursos
  • Mover de mensal para anual (ou vice-versa)
  • Ajustar a quantidade para produtos baseados em assentos
Mudanças de plano podem acionar uma cobrança imediata dependendo do modo de prorrata que você escolher.

Quando usar mudanças de plano

  • Upgrade quando um cliente precisa de mais recursos, uso ou assentos
  • Downgrade quando o uso diminui
  • Migrar usuários para um novo produto ou preço sem cancelar sua assinatura

Pré-requisitos

Antes de implementar mudanças de plano de assinatura, certifique-se de que você tem:
  • Uma conta de comerciante Dodo Payments com produtos de assinatura ativos
  • Credenciais da API (chave da API e chave secreta do webhook) do painel
  • Uma assinatura ativa existente para modificar
  • Endpoint de webhook configurado para lidar com eventos de assinatura
Para instruções detalhadas de configuração, consulte nosso Guia de Integração.

Guia de Implementação Passo a Passo

Siga este guia abrangente para implementar mudanças de plano de assinatura em sua aplicação:
1

Entender os Requisitos da Mudança de Plano

Antes de implementar, determine:
  • Quais produtos de assinatura podem ser mudados para quais outros
  • Qual modo de prorrata se encaixa no seu modelo de negócios
  • Como lidar com falhas nas mudanças de plano de forma elegante
  • Quais eventos de webhook rastrear para gerenciamento de estado
Teste mudanças de plano minuciosamente em modo de teste antes de implementar em produção.
2

Escolha Sua Estratégia de Prorrata

Selecione a abordagem de cobrança que se alinha com as necessidades do seu negócio:
Melhor para: Aplicativos SaaS que desejam cobrar de forma justa pelo tempo não utilizado
  • Calcula o valor exato da prorrata com base no tempo restante do ciclo
  • Cobra um valor proporcional com base no tempo não utilizado restante no ciclo
  • Fornece cobrança transparente aos clientes
3

Implemente a API de Mudança de Plano

Use a API de Mudança de Plano para modificar os detalhes da assinatura:
subscription_id
string
required
O ID da assinatura ativa a ser modificada.
product_id
string
required
O novo ID do produto para o qual mudar a assinatura.
quantity
integer
default:"1"
Número de unidades para o novo plano (para produtos baseados em assentos).
proration_billing_mode
string
required
Como lidar com a cobrança imediata: prorated_immediately, full_immediately, ou difference_immediately.
addons
array
Addons opcionais para o novo plano. Deixar isso vazio remove quaisquer addons existentes.
4

Lidar com Eventos de Webhook

Configure o manuseio de webhook para rastrear os resultados da mudança de plano:
  • subscription.active: Mudança de plano bem-sucedida, assinatura atualizada
  • subscription.plan_changed: Plano de assinatura mudado (upgrade/downgrade/atualização de addon)
  • subscription.on_hold: Falha na cobrança da mudança de plano, assinatura pausada
  • payment.succeeded: Cobrança imediata pela mudança de plano bem-sucedida
  • payment.failed: Cobrança imediata falhou
Sempre verifique as assinaturas de webhook e implemente o processamento de eventos idempotentes.
5

Atualize o Estado da Sua Aplicação

Com base nos eventos de webhook, atualize sua aplicação:
  • Conceda/revogue recursos com base no novo plano
  • Atualize o painel do cliente com os detalhes do novo plano
  • Envie e-mails de confirmação sobre mudanças de plano
  • Registre mudanças de cobrança para fins de auditoria
6

Teste e Monitore

Teste minuciosamente sua implementação:
  • Teste todos os modos de prorrata com diferentes cenários
  • Verifique se o manuseio de webhook funciona corretamente
  • Monitore as taxas de sucesso das mudanças de plano
  • Configure alertas para mudanças de plano falhadas
Sua implementação de mudança de plano de assinatura agora está pronta para uso em produção.

Pré-visualizar Mudanças de Plano

Antes de confirmar uma mudança de plano, use a API de Pré-visualização para mostrar aos clientes exatamente o que eles serão cobrados:
const preview = await client.subscriptions.previewChangePlan('sub_123', {
  product_id: 'prod_pro',
  quantity: 1,
  proration_billing_mode: 'prorated_immediately'
});

// Show customer the charge before confirming
console.log('Immediate charge:', preview.immediate_charge.summary);
console.log('New plan details:', preview.new_plan);
Use a API de pré-visualização para construir diálogos de confirmação que mostrem aos clientes o valor exato que eles serão cobrados antes de confirmarem uma mudança de plano.

API de Mudança de Plano

Use a API de Mudança de Plano para modificar o produto, a quantidade e o comportamento de prorrata para uma assinatura ativa.

Exemplos de início rápido

import DodoPayments from 'dodopayments';

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

async function changePlan() {
  const result = await client.subscriptions.changePlan('sub_123', {
    product_id: 'prod_new',
    quantity: 3,
    proration_billing_mode: 'prorated_immediately',
  });
  console.log(result.status, result.invoice_id, result.payment_id);
}

changePlan();
Success
{
  "status": "processing",
  "subscription_id": "sub_123",
  "invoice_id": "inv_789",
  "payment_id": "pay_456",
  "proration_billing_mode": "prorated_immediately"
}
Campos como invoice_id e payment_id são retornados apenas quando uma cobrança imediata e/ou fatura é criada durante a mudança de plano. Sempre confie em eventos de webhook (por exemplo, payment.succeeded, subscription.plan_changed) para confirmar resultados.
Se a cobrança imediata falhar, a assinatura pode ser movida para subscription.on_hold até que o pagamento seja bem-sucedido.

Gerenciando Addons

Ao mudar planos de assinatura, você também pode modificar addons:
// Add addons to the new plan
await client.subscriptions.changePlan('sub_123', {
  product_id: 'prod_new',
  quantity: 1,
  proration_billing_mode: 'difference_immediately',
  addons: [
    { addon_id: 'addon_123', quantity: 2 }
  ]
});

// Remove all existing addons
await client.subscriptions.changePlan('sub_123', {
  product_id: 'prod_new',
  quantity: 1,
  proration_billing_mode: 'difference_immediately',
  addons: [] // Empty array removes all existing addons
});
Addons estão incluídos no cálculo de prorrata e serão cobrados de acordo com o modo de prorrata selecionado.

Modos de Prorrata

Escolha como cobrar o cliente ao mudar de planos:

prorated_immediately

  • Cobra pela diferença parcial no ciclo atual
  • Se em teste, cobra imediatamente e muda para o novo plano agora
  • Downgrade: pode gerar um crédito proporcional aplicado a renovações futuras

full_immediately

  • Cobra o valor total do novo plano imediatamente
  • Ignora o tempo restante do plano antigo
Créditos criados por downgrades usando difference_immediately são específicos da assinatura e distintos de Créditos de Cliente. Eles se aplicam automaticamente a renovações futuras da mesma assinatura e não são transferíveis entre assinaturas.

difference_immediately

  • Upgrade: cobra imediatamente a diferença de preço entre os planos antigo e novo
  • Downgrade: adiciona o valor restante como crédito interno à assinatura e aplica automaticamente nas renovações

Cenários de Exemplo

await client.subscriptions.changePlan('sub_123', {
  product_id: 'prod_pro',
  quantity: 1,
  proration_billing_mode: 'difference_immediately'
})
// Immediate charge: $50
await client.subscriptions.changePlan('sub_123', {
  product_id: 'prod_starter',
  quantity: 1,
  proration_billing_mode: 'difference_immediately'
})
// Credit added: $30 (auto-applied to future renewals for this subscription)
await client.subscriptions.changePlan('sub_123', {
  product_id: 'prod_new',
  quantity: 1,
  proration_billing_mode: 'prorated_immediately'
})
// Immediate prorated charge based on remaining days in cycle
await client.subscriptions.changePlan('sub_123', {
  product_id: 'prod_new',
  quantity: 1,
  proration_billing_mode: 'full_immediately'
})
// Immediate full charge for new plan; no credits calculated
Escolha prorated_immediately para contabilidade justa de tempo; escolha full_immediately para reiniciar a cobrança; use difference_immediately para upgrades simples e crédito automático em downgrades.

Lidar com webhooks

Rastreie o estado da assinatura através de webhooks para confirmar mudanças de plano e pagamentos.

Tipos de eventos a serem tratados

  • subscription.active: assinatura ativada
  • subscription.plan_changed: plano de assinatura mudado (upgrade/downgrade/mudanças de addon)
  • subscription.on_hold: cobrança falhou, assinatura pausada
  • subscription.renewed: renovação bem-sucedida
  • payment.succeeded: pagamento pela mudança de plano ou renovação bem-sucedido
  • payment.failed: pagamento falhou
Recomendamos conduzir a lógica de negócios a partir de eventos de assinatura e usar eventos de pagamento para confirmação e reconciliação.

Verifique assinaturas e lide com intenções

import { NextRequest, NextResponse } from 'next/server';

export async function POST(req) {
  const webhookId = req.headers.get('webhook-id');
  const webhookSignature = req.headers.get('webhook-signature');
  const webhookTimestamp = req.headers.get('webhook-timestamp');
  const secret = process.env.DODO_WEBHOOK_SECRET;

  const payload = await req.text();
  // verifySignature is a placeholder – in production, use a Standard Webhooks library
  const { valid, event } = await verifySignature(
    payload,
    { id: webhookId, signature: webhookSignature, timestamp: webhookTimestamp },
    secret
  );
  if (!valid) return NextResponse.json({ error: 'Invalid signature' }, { status: 400 });

  switch (event.type) {
    case 'subscription.active':
      // mark subscription active in your DB
      break;
    case 'subscription.plan_changed':
      // refresh entitlements and reflect the new plan in your UI
      break;
    case 'subscription.on_hold':
      // notify user to update payment method
      break;
    case 'subscription.renewed':
      // extend access window
      break;
    case 'payment.succeeded':
      // reconcile payment for plan change
      break;
    case 'payment.failed':
      // log and alert
      break;
    default:
      // ignore unknown events
      break;
  }

  return NextResponse.json({ received: true });
}
Para esquemas de payload detalhados, consulte os Payloads de webhook de assinatura e Payloads de webhook de pagamento.

Melhores Práticas

Siga estas recomendações para mudanças de plano de assinatura confiáveis:

Estratégia de Mudança de Plano

  • Teste minuciosamente: Sempre teste mudanças de plano em modo de teste antes da produção
  • Escolha prorrata com cuidado: Selecione o modo de prorrata que se alinha com seu modelo de negócios
  • Lide com falhas de forma elegante: Implemente um tratamento de erros adequado e lógica de repetição
  • Monitore taxas de sucesso: Rastreie taxas de sucesso/falha de mudanças de plano e investigue problemas

Implementação de Webhook

  • Verifique assinaturas: Sempre valide assinaturas de webhook para garantir autenticidade
  • Implemente idempotência: Lide com eventos de webhook duplicados de forma elegante
  • Processe de forma assíncrona: Não bloqueie respostas de webhook com operações pesadas
  • Registre tudo: Mantenha logs detalhados para depuração e fins de auditoria

Experiência do Usuário

  • Comunique-se claramente: Informe os clientes sobre mudanças de cobrança e prazos
  • Forneça confirmações: Envie e-mails de confirmação para mudanças de plano bem-sucedidas
  • Lide com casos extremos: Considere períodos de teste, prorratas e pagamentos falhados
  • Atualize a interface imediatamente: Refletir mudanças de plano na interface da sua aplicação

Problemas Comuns e Soluções

Resolva problemas típicos encontrados durante mudanças de plano de assinatura:
Sintomas: Chamada da API é bem-sucedida, mas a assinatura permanece no plano antigoCausas comuns:
  • Processamento de webhook falhou ou foi atrasado
  • Estado da aplicação não atualizado após receber webhooks
  • Problemas de transação no banco de dados durante a atualização de estado
Soluções:
  • Implemente um manuseio robusto de webhook com lógica de repetição
  • Use operações idempotentes para atualizações de estado
  • Adicione monitoramento para detectar e alertar sobre eventos de webhook perdidos
  • Verifique se o endpoint de webhook está acessível e respondendo corretamente
Sintomas: Cliente faz downgrade, mas não vê saldo de créditoCausas comuns:
  • Expectativas do modo de prorrata: downgrades creditam a diferença total do preço do plano com difference_immediately, enquanto prorated_immediately cria um crédito proporcional com base no tempo restante no ciclo
  • Créditos são específicos da assinatura e não transferem entre assinaturas
  • Saldo de crédito não visível no painel do cliente
Soluções:
  • Use difference_immediately para downgrades quando você quiser créditos automáticos
  • Explique aos clientes que os créditos se aplicam a renovações futuras da mesma assinatura
  • Implemente um portal do cliente para mostrar saldos de crédito
  • Verifique a pré-visualização da próxima fatura para ver créditos aplicados
Sintomas: Eventos de webhook rejeitados devido a assinatura inválidaCausas comuns:
  • Chave secreta de webhook incorreta
  • Corpo da solicitação bruta modificado antes da verificação da assinatura
  • Algoritmo de verificação de assinatura errado
Soluções:
  • Verifique se você está usando a DODO_WEBHOOK_SECRET correta do painel
  • Leia o corpo da solicitação bruta antes de qualquer middleware de análise JSON
  • Use a biblioteca padrão de verificação de webhook para sua plataforma
  • Teste a verificação da assinatura do webhook no ambiente de desenvolvimento
Sintomas: A API retorna erro 422 Unprocessable EntityCausas comuns:
  • ID de assinatura ou ID de produto inválido
  • Assinatura não está em estado ativo
  • Parâmetros obrigatórios ausentes
  • Produto não disponível para mudanças de plano
Soluções:
  • Verifique se a assinatura existe e está ativa
  • Verifique se o ID do produto é válido e disponível
  • Certifique-se de que todos os parâmetros obrigatórios estão fornecidos
  • Revise a documentação da API para requisitos de parâmetros
Sintomas: Mudança de plano iniciada, mas cobrança imediata falhaCausas comuns:
  • Fundos insuficientes no método de pagamento do cliente
  • Método de pagamento expirado ou inválido
  • Banco recusou a transação
  • Detecção de fraude bloqueou a cobrança
Soluções:
  • Lide com eventos de webhook payment.failed de forma apropriada
  • Notifique o cliente para atualizar o método de pagamento
  • Implemente lógica de repetição para falhas temporárias
  • Considere permitir mudanças de plano com cobranças imediatas falhadas
Sintomas: Falha na cobrança da mudança de plano e assinatura move-se para o estado on_holdO que acontece: Quando uma cobrança de mudança de plano falha, a assinatura é automaticamente colocada no estado on_hold. A assinatura não será renovada automaticamente até que o método de pagamento seja atualizado.Solução: Atualize o método de pagamento para reativar a assinaturaPara reativar uma assinatura do estado on_hold após uma falha na mudança de plano:
  1. Atualize o método de pagamento usando a API de Atualização do Método de Pagamento
  2. Criação automática de cobrança: A API cria automaticamente uma cobrança para as pendências restantes
  3. Geração de fatura: Uma fatura é gerada para a cobrança
  4. Processamento de pagamento: O pagamento é processado usando o novo método de pagamento
  5. Reativação: Após o pagamento bem-sucedido, a assinatura é reativada para o estado active
// Reactivate subscription from on_hold after failed plan change
async function reactivateAfterFailedPlanChange(subscriptionId) {
  // Update payment method - automatically creates charge for remaining dues
  const response = await client.subscriptions.updatePaymentMethod(subscriptionId, {
    type: 'new',
    return_url: 'https://example.com/return'
  });
  
  if (response.payment_id) {
    console.log('Charge created for remaining dues:', response.payment_id);
    console.log('Payment link:', response.payment_link);
    
    // Redirect customer to payment_link to complete payment
    // Monitor webhooks for:
    // 1. payment.succeeded - charge succeeded
    // 2. subscription.active - subscription reactivated
  }
  
  return response;
}

// Or use existing payment method if available
async function reactivateWithExistingPaymentMethod(subscriptionId, paymentMethodId) {
  const response = await client.subscriptions.updatePaymentMethod(subscriptionId, {
    type: 'existing',
    payment_method_id: paymentMethodId
  });
  
  // Monitor webhooks for payment.succeeded and subscription.active
  return response;
}
Eventos de webhook a serem monitorados:
  • subscription.on_hold: Assinatura colocada em espera (recebido quando a cobrança da mudança de plano falha)
  • payment.succeeded: Pagamento das pendências restantes bem-sucedido (após atualizar o método de pagamento)
  • subscription.active: Assinatura reativada após pagamento bem-sucedido
Melhores práticas:
  • Notifique os clientes imediatamente quando uma cobrança de mudança de plano falhar
  • Forneça instruções claras sobre como atualizar seu método de pagamento
  • Monitore eventos de webhook para rastrear o status de reativação
  • Considere implementar lógica de repetição automática para falhas temporárias de pagamento

Referência da API de Atualização do Método de Pagamento

Veja a documentação completa da API para atualizar métodos de pagamento e reativar assinaturas.

Testando Sua Implementação

Siga estas etapas para testar minuciosamente sua implementação de mudança de plano de assinatura:
1

Configurar ambiente de teste

  • Use chaves de API de teste e produtos de teste
  • Crie assinaturas de teste com diferentes tipos de plano
  • Configure o endpoint de webhook de teste
  • Configure monitoramento e registro
2

Teste diferentes modos de prorrata

  • Teste prorated_immediately com várias posições de ciclo de cobrança
  • Teste difference_immediately para upgrades e downgrades
  • Teste full_immediately para reiniciar ciclos de cobrança
  • Verifique se os cálculos de crédito estão corretos
3

Teste o manuseio de webhook

  • Verifique se todos os eventos de webhook relevantes são recebidos
  • Teste a verificação da assinatura do webhook
  • Lide com eventos de webhook duplicados de forma elegante
  • Teste cenários de falha no processamento de webhook
4

Teste cenários de erro

  • Teste com IDs de assinatura inválidos
  • Teste com métodos de pagamento expirados
  • Teste falhas de rede e timeouts
  • Teste com fundos insuficientes
5

Monitore em produção

  • Configure alertas para mudanças de plano falhadas
  • Monitore os tempos de processamento de webhook
  • Rastreie taxas de sucesso de mudanças de plano
  • Revise tickets de suporte ao cliente para problemas de mudança de plano

Tratamento de Erros

Lide com erros comuns da API de forma elegante em sua implementação:

Códigos de Status HTTP

Solicitação de mudança de plano processada com sucesso. A assinatura está sendo atualizada e o processamento de pagamento foi iniciado.
Parâmetros de solicitação inválidos. Verifique se todos os campos obrigatórios estão fornecidos e formatados corretamente.
Chave da API inválida ou ausente. Verifique se sua DODO_PAYMENTS_API_KEY está correta e possui as permissões adequadas.
ID de assinatura não encontrado ou não pertence à sua conta.
A assinatura não pode ser mudada (por exemplo, já cancelada, produto não disponível, etc.).
Ocorreu um erro no servidor. Tente a solicitação novamente após um breve atraso.

Formato de Resposta de Erro

{
  "error": {
    "code": "subscription_not_found",
    "message": "The subscription with ID 'sub_123' was not found",
    "details": {
      "subscription_id": "sub_123"
    }
  }
}

Próximos passos