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.

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ção | O que a Apple está dizendo | Sua ação | Resposta esperada |
|---|---|---|---|
| CONSUMPTION_REQUEST | Um cliente pediu reembolso e a Apple quer seus dados | Send Consumption Information em até 12 horas | Sim, dados reais |
| REFUND | A App Store reembolsou a transação | Revogue o direito daquela transação | Não, HTTP 200 |
| REFUND_DECLINED | A App Store recusou o reembolso | Mantenha o acesso, não mude nada | Não, HTTP 200 |
| REFUND_REVERSED | A Apple reverteu um reembolso que havia concedido | Restabeleça o conteúdo que você revogou | Nã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.
| revocationReason | Significado da Apple | Como interpretar |
|---|---|---|
| 1 | O reembolso foi concedido por causa de um problema com o produto | Um sinal de qualidade ou de entrega. Registre, acompanhe a tendência e procure um padrão em um produto ou uma build |
| 0 | O reembolso foi concedido por outro motivo | Um 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.

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
Toda solicitação de reembolso da Apple agora vem com um motivo, e o consumptionRequestReason é como você o lê
Desde a WWDC24, todo CONSUMPTION_REQUEST da Apple carrega um consumptionRequestReason, o motivo declarado pelo próprio cliente para querer o reembolso. São cinco valores, de UNINTENDED_PURCHASE a LEGAL, e cada um deve mudar o que você envia de volta dentro da sua janela de 12 hours. Veja como ler cada um deles.
A revisão de estorno do Google Play te dá 24 horas para reagir, veja o que enviar
Quando um banco reverte uma cobrança do Google Play, o Google envia ao seu servidor uma PendingRefundReviewNotification e inicia um relógio de 24 horas. Responda por meio da ReviewRefund API com uma preferência de reembolso e evidências de consumo reais, ou a disputa é decidida sem você. Aqui está todo o fluxo, campo por campo.