Todos os artigos
Análise aprofundada8 min de leitura

Verifique as notificações do servidor da App Store antes de agir sobre um reembolso, porque qualquer pessoa pode enviar dados para a sua URL de webhook

Uma notificação de reembolso é apenas uma requisição HTTPS até você conferir a assinatura. Veja como verificar as notificações do servidor da App Store e as mensagens RTDN do Google Play, o que cada loja assina e quanto custa um reembolso forjado ou rejeitado por engano.

Um carimbo de lacre de latão e um envelope lacrado ao lado de um notebook sobre uma mesa sob a luz quente de um abajur, uma imagem de por que verificar as notificações do servidor da App Store antes de confiar nelas

Principais conclusões

  • A Apple envia cada notificação do servidor da App Store da versão 2 como um signedPayload, uma JSON Web Signature com três partes em Base64URL: um cabeçalho, um payload e uma assinatura.
  • O cabeçalho JWS de uma notificação do servidor da App Store traz uma cadeia de certificados x5c com três certificados: um certificado folha de assinatura, um intermediário da Apple com a extensão Apple Worldwide Developer Relations 1.2.840.113635.100.6.2.1 e uma raiz da Apple.
  • A App Store Server Library da Apple verifica as notificações com um SignedDataVerifier que confere a cadeia de certificados, o bundle ID, o ambiente e, em produção, o appAppleId, e pode consultar online a revogação de certificados.
  • As notificações do desenvolvedor em tempo real do Google Play não são assinadas pelo Google Play. Em uma assinatura push, o Pub/Sub pode anexar um token OpenID Connect assinado no cabeçalho Authorization, e o seu servidor confere a assinatura, o público e as claims de email desse token.
  • O Google afirma que uma RTDN apenas informa que o estado de uma compra mudou, então a resposta segura a qualquer notificação de reembolso é confirmá-la com a Google Play Developer API antes de revogar o acesso.
  • A Apple envia as notificações do servidor da App Store a partir da sub-rede 17.0.0.0/8, mas uma lista de IPs permitidos só restringe quem consegue alcançar o seu endpoint. É a assinatura que prova que a mensagem veio da Apple.
  • Um verificador que rejeita por engano mensagens legítimas custa tanto quanto um que aceita falsificações, porque um CONSUMPTION_REQUEST descartado tem um prazo de resposta de 12 horas e uma análise de chargeback do Google Play tem 24 horas.

Qualquer pessoa que descubra a sua URL de webhook pode enviar um reembolso para ela. Esse é o fato incômodo por trás de toda notificação do servidor da App Store e de toda notificação do desenvolvedor em tempo real do Google Play: até você verificá-la, a mensagem é só um POST HTTPS com algum JSON dentro. Se o seu servidor revoga uma assinatura, retira créditos ou bane uma conta porque uma requisição dizia REFUND, você entregou esse poder a qualquer um capaz de escrever um comando curl.

As duas lojas oferecem uma forma de conferir. A Apple assina a própria notificação, então você pode verificar as notificações do servidor da App Store usando apenas o certificado raiz da Apple. O Google Play segue outro caminho. A mensagem não é assinada, mas a entrega do Pub/Sub pode ser, e o Google pede de qualquer forma que você confirme cada mudança com a API dele. Veja o que cada uma prova e quanto custa errar em qualquer das duas direções.

O que cada loja realmente assina

PerguntaApp Store Server Notifications V2Google Play RTDN
A própria mensagem é assinada?Sim, o signedPayload é um JWSNão, o campo data é JSON codificado em base64
O que prova o remetenteCadeia de certificados x5c até uma raiz da AppleToken OIDC do Pub/Sub no push, ou o seu próprio pull autenticado
Objetos assinados aninhadossignedTransactionInfo e signedRenewalInfo, cada um com o próprio JWSNenhum
Campos a conferir com o seu appbundleId, appAppleId, environmentpackageName
Rede de origem17.0.0.0/8, sandbox e produçãoGoogle Cloud Pub/Sub
Confirmar antes de agirOpcional, os dados assinados são o registroObrigatório, o Google manda chamar a Developer API
TransporteHTTPS, TLS 1.2 ou posteriorPush HTTPS, ou pull via biblioteca de cliente

Como verificar as notificações do servidor da App Store

A documentação da Apple descreve o signedPayload como uma string de três componentes codificados em Base64URL separados por pontos: um cabeçalho, um payload e uma assinatura, assinada de acordo com a especificação JSON Web Signature. Decodificar o payload é fácil. Confiar nele exige quatro verificações.

  • Leia o array x5c do cabeçalho decodificado. A Apple documenta a ordem: primeiro o certificado com a chave de assinatura, depois um certificado intermediário da Apple e então um certificado raiz da Apple.
  • Valide essa cadeia contra uma raiz da Apple que você mesmo baixou do site de PKI da Apple, na prática a Apple Root CA - G3. Nunca confie na raiz que chegou dentro da mensagem, porque um falsificador pode colocar qualquer certificado ali.
  • Confirme que o intermediário traz a extensão Apple Worldwide Developer Relations, 1.2.840.113635.100.6.2.1, e então verifique a assinatura JWS com a chave pública do certificado folha.
  • Confira os dados decodificados com o seu app: bundleId, appAppleId em produção e environment. Uma assinatura válida da Apple no app de outro desenvolvedor, ou em uma compra de sandbox que chega ao seu endpoint de produção, continua não sendo o seu reembolso.

Depois, faça tudo de novo com o que está dentro. O objeto data contém signedTransactionInfo e signedRenewalInfo, e cada um é um JWS separado com a própria cadeia x5c. Um handler de REFUND que verifica o envelope mas lê a transação sem verificá-la deixou uma brecha no meio do caminho.

Use a biblioteca da Apple em vez de escrever a sua

A Apple publica a App Store Server Library para Swift, Java, Python e Node. O SignedDataVerifier dela recebe os seus certificados raiz, uma flag de verificações online, o ambiente, o seu bundle ID e, para produção, o seu appAppleId. O código-fonte em Node mostra o que ela exige: exatamente três certificados na cadeia, a extensão de folha da Apple 1.2.840.113635.100.6.11.1 e a extensão do intermediário, as datas de validade dos certificados, e bundle ID, ID do app e ambiente correspondentes. Com as verificações online ativadas, ela também pergunta ao respondedor OCSP se os certificados folha e intermediário foram revogados.

Uma lupa de joalheiro sobre um certificado de papel com um selo em relevo em uma mesa de madeira, o tipo de inspeção minuciosa que uma mensagem de reembolso merece antes de você confiar nela

Uma lista de IPs permitidos é suficiente?

Não. A Apple diz que, se o seu servidor precisar de uma lista de permitidos, você deve adicionar a sub-rede 17.0.0.0/8, e isso vale tanto para sandbox quanto para produção. Isso reduz o ruído. Não prova que uma mensagem é legítima, e deixa de funcionar assim que a rede da Apple muda de um jeito que você não ficou sabendo. Mantenha a verificação de assinatura como o verdadeiro controle.

Como verificar as notificações de reembolso do Google Play

O Google Play publica as mensagens RTDN em um tópico do Pub/Sub que pertence a você, e somente a conta de serviço google-play-developer-notifications@system.gserviceaccount.com deve ter o papel de publicador do Pub/Sub nele. A sua assinatura então entrega as mensagens de uma de duas formas, e cada uma tem a própria prova.

  • Assinatura pull: o seu servidor abre uma conexão autenticada com o Pub/Sub e busca as mensagens. Não há endpoint público, então não há nada para um estranho enviar dados.
  • Assinatura push com autenticação ativada: o Pub/Sub assina um JSON Web Token e o envia no cabeçalho Authorization como token Bearer. O guia do Google manda validar a assinatura do token e conferir se as claims de email e de público correspondem aos valores que você configurou, e o código de exemplo também exige que email_verified seja true. O token pode ter até uma hora de idade.
  • Assinatura push sem autenticação: qualquer coisa que alcance a URL pode enviar uma mensagem com formato de RTDN.

Por que o Google quer que você confirme com a API

Mesmo uma RTDN perfeitamente autenticada não conta a história toda. O guia de configuração do Google diz claramente que essas notificações informam apenas que o estado de uma compra mudou e que você precisa chamar a Google Play Developer API para obter o status completo. Para uma voidedPurchaseNotification, isso significa localizar a compra na Voided Purchases API, ou buscar o estado atual dela, antes de revogar qualquer coisa. A chamada à API é autenticada com a sua própria conta de serviço, então a resposta dela é algo que um falsificador não consegue forjar.

Quanto custa em dinheiro um reembolso forjado ou rejeitado

Uma notificação de reembolso forjada em que você confia custa um cliente pagante. Você bloqueia alguém cujo dinheiro ainda está com você, essa pessoa abre um chamado no suporte, e algumas vão até a loja pedir o reembolso que o seu sistema já fingiu conceder. Uma compra ou renovação forjada custa no sentido oposto: você entrega processamento de GPU, chamadas pagas a APIs de terceiros, armazenamento e repasses a criadores em troca de uma receita que nunca existiu.

A falha oposta é mais silenciosa e muitas vezes maior. Um verificador que rejeita mensagens legítimas, por causa de um appAppleId errado, de uma configuração de sandbox em produção ou de um certificado raiz desatualizado, descarta justamente os dois fluxos de reembolso em que as suas evidências contam. A Apple pede dados de consumo em até 12 horas após um CONSUMPTION_REQUEST. O Google dá 24 horas para responder a uma análise de chargeback via orders.reviewrefund e, para pedidos feitos após 3 de agosto de 2026, um chargeback perdido no Google Play custa o preço da compra menos a taxa de serviço do Play, mais a tarifa cobrada pelo banco do comprador.

FalhaO que aconteceQuanto custa
REFUND forjado aceitoUm cliente pagante perde o acessoTempo de suporte e um pedido de reembolso real que você provocou
Compra forjada aceitaAcesso gratuito a recursos pagosProcessamento, chamadas de API, armazenamento e repasses sem receita
CONSUMPTION_REQUEST legítimo rejeitadoA Apple decide sem os seus dadosA venda, mais tudo o que já foi gasto para entregá-la
Análise de chargeback legítima rejeitadaO Google decide sem as suas evidênciasPreço da compra e tarifas bancárias em pedidos após 3 de agosto de 2026

Não deixe um bug de verificação fazer você perder um prazo

  • Armazene a requisição bruta antes de verificá-la, para que uma mensagem rejeitada nunca se perca de verdade.
  • Gere um alerta para cada falha de verificação. Uma mensagem forjada é ruído. Todas as mensagens falhando ao mesmo tempo é um bug seu.
  • Na Apple, você pode reprocessar o que rejeitou. O Get Notification History devolve o signedPayload original dos últimos 180 dias, então corrija o verificador e passe por ele de novo os payloads armazenados ou recuperados.
  • No Google, uma análise de chargeback pendente só existe na própria notificação, então um público de push mal configurado é uma análise perdida. Teste com o Send Test Message no Play Console depois de cada mudança.

O RefundHalt verifica as notificações das duas lojas, confirma os reembolsos com as APIs das lojas antes de qualquer mudança e responde aos CONSUMPTION_REQUEST e às análises de chargeback dentro dos prazos, para que uma mensagem falsa não custe um cliente e uma verdadeira não passe despercebida.

Perguntas frequentes

Como verifico uma notificação do servidor da App Store?
Verifique o signedPayload como uma JSON Web Signature. Leia a cadeia de certificados x5c do cabeçalho, valide-a contra um certificado raiz da Apple que você baixou do site de PKI da Apple, verifique a assinatura com a chave do certificado folha e depois confira se bundleId, appAppleId e environment correspondem ao seu app. A App Store Server Library da Apple faz tudo isso no SignedDataVerifier.
Qual chave eu uso para validar as notificações do servidor da App Store?
Você não precisa de nenhuma chave do App Store Connect. A chave pública está no primeiro certificado da cadeia x5c dentro do cabeçalho JWS, e você só confia nela depois de validar a cadeia até um certificado raiz da Apple que você mesmo obteve. A sua chave de compras no app serve para chamar as APIs da Apple, não para conferir notificações.
As notificações do desenvolvedor em tempo real do Google Play são assinadas?
Não, o Google Play não assina a própria mensagem RTDN. Em uma assinatura push autenticada, o Pub/Sub envia no cabeçalho Authorization um token OpenID Connect assinado que você valida, e o Google orienta chamar a Google Play Developer API após cada notificação para obter o status completo da compra.
O meu servidor deve retornar um erro quando uma notificação falha na verificação?
Armazene primeiro a requisição bruta e depois decida. A Apple tenta reenviar uma notificação da versão 2 após uma resposta 40x ou 50x, 1, 12, 24, 48 e 72 horas depois da tentativa anterior. Se a falha for da sua própria configuração, o Get Notification History permite recuperar o signedPayload original por 180 dias e verificá-lo de novo depois da correção.
Ainda preciso verificar as notificações se eu permitir apenas a faixa de IPs da Apple?
Sim. A Apple pede que servidores com lista de permitidos aceitem a sub-rede 17.0.0.0/8, o que limita quem pode se conectar, mas não prova que uma mensagem é legítima. A assinatura JWS é a verificação que liga uma notificação à Apple e ao seu app.

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.