Todos os artigos
Playbook7 min de leitura

Três notificações de reembolso da App Store chegam depois que a Apple decide, e REFUND_REVERSED devolve a venda

A Apple envia quatro mensagens de reembolso pelo App Store Server Notifications V2, e a maioria dos apps trata apenas duas. REFUND diz para revogar, REFUND_DECLINED significa manter a venda, e REFUND_REVERSED devolve a venda e pede que você restaure o que retirou. Aqui está o que cada uma exige.

Um smartphone mostrando um recibo de pagamento ao lado de um envelope devolvido e uma única moeda, ilustrando as notificações de reembolso da App Store que a Apple envia depois de decidir um reembolso

Principais conclusões

  • A Apple envia quatro mensagens relacionadas a reembolso pelo App Store Server Notifications V2. CONSUMPTION_REQUEST pede suas evidências, e REFUND, REFUND_DECLINED e REFUND_REVERSED informam o resultado depois que a Apple já decidiu.
  • Uma notificação REFUND significa que a App Store reembolsou a transação. Ela traz revocationDate e revocationReason, e é seu sinal para revogar o direito ligado àquela única transação, não a todas as compras daquele produto.
  • revocationReason tem dois valores. 1 significa que o reembolso foi concedido por causa de um problema com seu produto, e 0 significa que foi concedido por outro motivo. O valor de problema é um sinal de qualidade que vale registrar e acompanhar por tendência.
  • REFUND_DECLINED significa que a Apple recusou o reembolso do cliente. Você mantém a venda e não muda nada, o que só é seguro se você não revogou o acesso antes de a decisão ser definitiva.
  • REFUND_REVERSED significa que a Apple reverteu um reembolso que havia concedido antes, geralmente depois de o cliente contestá-lo. Os campos de revogação somem da transação, e a própria instrução da Apple é que, se você revogou conteúdo, precisa restabelecê-lo.
  • Responda às quatro notificações com HTTP 200. Se seu servidor caiu e perdeu uma, o endpoint Get Refund History permite consultar transações reembolsadas por id de transação e reconciliar.
  • Um reembolso de um período de assinatura passado nem sempre significa que o acesso deve terminar. Se um período pago mais recente ainda está ativo, revogar na transação antiga corta um cliente que está em dia.

A Apple decide seu reembolso e depois continua falando. Uma vez definido o resultado, a App Store envia ao seu servidor uma de três notificações de reembolso da App Store, e cada uma pede uma ação diferente. Um REFUND diz que o dinheiro se foi e que você deve retirar o acesso. Um REFUND_DECLINED diz que o cliente perdeu o pedido e que você mantém a venda. Um REFUND_REVERSED diz que a Apple desfez um reembolso que já havia concedido, então a venda é sua de novo e você precisa devolver o que tiver retirado. A maioria dos apps implementa a primeira e ignora em silêncio as outras duas. É assim que um cliente pagante acaba bloqueado de algo pelo qual pagou.

Essas três são separadas de CONSUMPTION_REQUEST, a única mensagem de reembolso que pede uma resposta. As notificações pós-decisão não querem discussão. Elas querem um HTTP 200 e a mudança certa no acesso do cliente. Aqui está o que cada uma significa, os campos exatos que carregam os fatos, e onde o dinheiro vaza quando você as trata errado.

As quatro notificações de reembolso, e qual delas espera resposta

O App Store Server Notifications V2 é um único fluxo. Você o aponta para uma URL e a Apple envia todos os tipos de notificação para ele, então você já recebe as quatro mensagens de reembolso, tratando-as ou não. Quatro dos tipos envolvem reembolsos, e só um deles é uma pergunta.

NotificaçãoO que a Apple está dizendoSua açãoResposta esperada
CONSUMPTION_REQUESTUm cliente pediu reembolso e a Apple quer seus dadosSend Consumption Information em até 12 horasSim, dados reais
REFUNDA App Store reembolsou a transaçãoRevogue o direito daquela transaçãoNão, HTTP 200
REFUND_DECLINEDA App Store recusou o reembolsoMantenha o acesso, não mude nadaNão, HTTP 200
REFUND_REVERSEDA Apple reverteu um reembolso que havia concedidoRestabeleça o conteúdo que você revogouNão, HTTP 200

O que uma notificação REFUND realmente diz a você

REFUND dispara quando a App Store reembolsou com sucesso uma transação a um cliente. Aplica-se a todos os tipos de compra: um consumível, um não consumível, uma assinatura com renovação automática e uma assinatura sem renovação. A transação assinada dentro da notificação agora carrega dois campos que não tinha antes do reembolso, e esses dois campos contam a história toda.

revocationDate e revocationReason carregam os fatos

revocationDate é o horário UNIX, em milissegundos, em que a App Store reembolsou a transação ou a revogou. revocationReason informa a categoria do reembolso, e assume exatamente dois valores.

revocationReasonSignificado da AppleComo interpretar
1O reembolso foi concedido por causa de um problema com o produtoUm sinal de qualidade ou de entrega. Registre, acompanhe a tendência e procure um padrão em um produto ou uma build
0O reembolso foi concedido por outro motivoUm reembolso comum. Revogue o direito e siga em frente

A presença de um revocationDate em uma transação é, por si só, o alerta. Se você buscar uma transação mais tarde e ela tiver um revocationDate, aquela compra foi reembolsada, com ou sem notificação. Leia o motivo junto para que uma onda de reembolsos de valor 1 em um único lançamento não passe despercebida como ruído.

Revogue por transação, não por produto

A armadilha aqui é revogar demais. Um REFUND nomeia uma transação. Ele não diz para desativar todas as compras que o cliente já fez daquele id de produto. A própria orientação da Apple é verificar qual acesso o cliente ainda mantém antes de cortar qualquer coisa, porque os direitos se sobrepõem. O caso clássico é uma assinatura: um reembolso recai sobre a renovação do mês passado enquanto a renovação deste mês está ativa e totalmente paga. Revogue no produto e você acabou de cortar um cliente atual e pagante por um reembolso de um período que já terminou.

REFUND_DECLINED significa que você já venceu, então não desfaça isso

REFUND_DECLINED chega quando a App Store recusou o pedido de reembolso do cliente. O cliente pediu, a Apple disse não, e você mantém a venda. À primeira vista não há nada a fazer, e esse é o ponto. O erro que essa notificação expõe é outro: revogar o acesso cedo demais.

Se seu código reage ao CONSUMPTION_REQUEST retirando o acesso do cliente antes de a Apple decidir, um REFUND_DECLINED é o momento em que essa decisão explode. A Apple ficou com seu dinheiro, e você bloqueou um cliente cujo reembolso foi negado. Esse cliente agora paga por um produto que não pode usar, abre um chamado de suporte e se lembra disso. A correção é uma regra, não um recurso: revogue no REFUND, nunca no pedido. REFUND_DECLINED é simplesmente a Apple confirmando que a revogação antecipada teria sido a decisão errada.

REFUND_REVERSED é a notificação que devolve dinheiro a você

REFUND_REVERSED é a que quase ninguém trata, e é a que devolve dinheiro a você. A Apple a envia quando reverte um reembolso que havia concedido antes, normalmente depois de o cliente contestar esse reembolso. Os campos de revogação que um REFUND adicionou à transação são removidos de novo, então a compra volta a constar como paga. A Apple resume o trabalho do desenvolvedor em uma linha: se seu app revogou conteúdo ou serviços em razão do reembolso relacionado, precisa restabelecê-los. Aplica-se a qualquer tipo de compra, de um consumível a uma assinatura com renovação automática.

O problema de semanas depois

A pergunta real que os desenvolvedores levantam, nos próprios fóruns da Apple, é o momento. Um REFUND_REVERSED pode chegar semanas depois do REFUND original, muito depois de um período de assinatura ter expirado. Você restaura o acesso então? Restabeleça o que a transação de fato concede, limitado ao que aquela transação cobre. Para um consumível ou um não consumível, ligue o desbloqueio de novo. Para um período de assinatura que já passou, você não está distribuindo tempo novo, está corrigindo o registro para que o histórico do cliente fique preciso e qualquer direito que ainda seja válido volte a ficar ativo. Restaure a transação específica, e sua lógica de sobreposição decide o que está ativo no momento.

Uma moeda sendo recolocada ao lado de um smartphone, ilustrando um reembolso revertido da App Store que restaura a venda ao desenvolvedor

Onde está o dinheiro em acertar isso

Cada uma dessas notificações corresponde a um número real, e o custo de tratá-la mal não é apenas o preço da venda.

REFUND: pare de pagar para atender um cliente reembolsado

O preço da venda se foi no momento em que REFUND chega. O que você ainda pode controlar é o custo de continuar entregando. A cada hora que um direito reembolsado permanece ativo, você continua gastando com aquilo que o cliente não paga mais: computação, chamadas à API do modelo, armazenamento e qualquer pagamento a criador ou parceiro ligado ao uso dele. Revogar prontamente no REFUND para esse contador. Ignorar a notificação significa que você financia um produto para alguém que a loja já ressarciu.

REFUND_DECLINED: não transforme uma vitória em um reembolso de boa vontade

Quando você revoga cedo e o reembolso é recusado depois, você manteve a venda no papel e a perdeu na prática. O cliente que pagou não consegue usar o produto, então você herda uma conversa de suporte e, muitas vezes, um reembolso discricionário para consertar. Isso é pagar duas vezes por uma venda que nunca esteve em risco. Tratar REFUND_DECLINED corretamente não custa nada, que é exatamente por que deixar o acesso intacto até o REFUND é a regra mais barata que você pode adotar.

REFUND_REVERSED: a pior combinação é o cliente ficar sem o dinheiro e sem o acesso ao mesmo tempo

Ignore REFUND_REVERSED e você chega ao pior resultado possível. Você foi pago, e o cliente não tem nada. Ele já contatou o banco uma vez para reverter o reembolso, e uma pessoa bloqueada de um produto pelo qual agora é cobrada é uma pessoa com boa chance de contatar o banco uma segunda vez. Essa próxima contestação pode virar um chargeback de cartão, que é final por parte do banco e custa mais do que a venda jamais custou. Restabelecer o acesso assim que REFUND_REVERSED chega é o seguro mais barato de todo o fluxo de reembolso.

O que implementar

O tratamento é pequeno quando o modelo está certo. Indexe os direitos pelo id de transação para que cada notificação aponte para uma compra. No CONSUMPTION_REQUEST, envie seus dados em até 12 horas. No REFUND, revogue aquela transação. No REFUND_DECLINED, não faça nada. No REFUND_REVERSED, restabeleça. Retorne HTTP 200 rápido em todas elas e faça a mudança de acesso no seu próprio tempo.

Para a lacuna que as notificações deixam, use o endpoint Get Refund History. Se seu servidor caiu durante uma interrupção e perdeu um REFUND, chame a busca de reembolso da App Store Server API para um id de transação, em /inApps/v2/refund/lookup/{transactionId}, e leia de volta as transações assinadas com seus revocationDate e revocationReason. Ele reconcilia uma transação por vez e pagina pelas compras reembolsadas de um cliente, então um webhook perdido não vira um direito configurado errado de forma permanente.

Esta é a parte que o RefundHalt executa por você. Ele escuta os quatro tipos, revoga no REFUND, mantém o acesso intacto no REFUND_DECLINED, e restabelece automaticamente no REFUND_REVERSED, cada um indexado à transação exata. Um reembolso revertido não fica numa fila enquanto um cliente pagante permanece bloqueado, e um recusado nunca dispara uma revogação que você teria de desfazer.

Perguntas frequentes

Qual é a diferença entre REFUND e REFUND_REVERSED?
REFUND significa que a App Store reembolsou uma transação e você deve revogar aquele direito, enquanto REFUND_REVERSED significa que a Apple desfez um reembolso que havia concedido e você deve restabelecer o conteúdo que revogou. As duas formam um par: uma compra pode ir para REFUND e depois, se a contestação do cliente for revertida, para REFUND_REVERSED. Indexe suas mudanças de acesso pelo id de transação para que cada notificação aja sobre a compra certa.
Preciso enviar algo de volta para uma notificação REFUND?
Não. Você responde a REFUND, REFUND_DECLINED e REFUND_REVERSED com um HTTP 200 e sem corpo. Só o CONSUMPTION_REQUEST pede que você envie dados, e faz isso pelo endpoint Send Consumption Information em até 12 horas. As outras três são a Apple relatando uma decisão, não fazendo uma pergunta.
O que devo fazer quando recebo uma notificação REFUND_DECLINED?
Nada muda, porque o reembolso do cliente foi negado e você mantém a venda. A única forma de REFUND_DECLINED gerar trabalho é se você revogou o acesso cedo demais, antes de a Apple decidir. Revogue no REFUND em vez de no CONSUMPTION_REQUEST, e um REFUND_DECLINED vira uma confirmação de que o acesso foi corretamente deixado intacto.
Devo restaurar o acesso quando REFUND_REVERSED chega semanas depois do reembolso?
Sim, restabeleça o direito que aquela transação específica concede. A Apple afirma que, se seu app revogou conteúdo por causa do reembolso relacionado, precisa restabelecê-lo. Para um consumível ou não consumível, ligue o desbloqueio de novo. Para um período de assinatura que já expirou, você está corrigindo o registro, não concedendo tempo novo, então sua lógica de sobreposição ainda decide o que está ativo no momento.
Como eu capturo uma notificação de reembolso que meu servidor perdeu?
Use o endpoint Get Refund History da App Store Server API, que consulta as transações reembolsadas de um cliente por id de transação em /inApps/v2/refund/lookup/{transactionId}. Ele retorna transações assinadas com revocationDate e revocationReason, então após uma interrupção você pode reconciliar o acesso sem esperar por uma notificação que já disparou. Ele lida com um id de transação por chamada e pagina pelas compras reembolsadas do cliente.

Fontes e leituras adicionais

RefundHalt

O piloto automático de reembolsos para App Store e Google Play

Continue lendo

A próxima solicitação de reembolso já está a caminho.

Configure a RefundHalt no tempo que você levaria para ler mais um e-mail de suporte sobre um reembolso que não conseguiu contestar.