Verifica le notifiche server dell'App Store prima di agire su un rimborso, perché chiunque può inviare richieste al tuo URL di webhook
Una notifica di rimborso è solo una richiesta HTTPS finché non ne controlli la firma. Ecco come verificare le notifiche server dell'App Store e i messaggi RTDN di Google Play, che cosa firma ciascuno store e quanto ti costa un rimborso falsificato o respinto per errore.

Punti chiave
- Apple invia ogni notifica server dell'App Store della versione 2 come signedPayload, una JSON Web Signature composta da tre parti in Base64URL: un header, un payload e una firma.
- L'header JWS di una notifica server dell'App Store contiene una catena di certificati x5c di tre certificati: un certificato foglia di firma, un intermedio Apple con l'estensione Apple Worldwide Developer Relations 1.2.840.113635.100.6.2.1 e una radice Apple.
- La App Store Server Library di Apple verifica le notifiche con un SignedDataVerifier che controlla la catena di certificati, il bundle ID, l'ambiente e, in produzione, l'appAppleId, e può verificare online la revoca dei certificati.
- Le notifiche in tempo reale per sviluppatori di Google Play non sono firmate da Google Play. In una sottoscrizione push, Pub/Sub può allegare un token OpenID Connect firmato nell'header Authorization, e il tuo server ne controlla la firma, l'audience e i claim relativi all'email.
- Google afferma che una RTDN ti dice soltanto che lo stato di un acquisto è cambiato, quindi la risposta sicura a qualsiasi notifica di rimborso è confermarla con la Google Play Developer API prima di revocare l'accesso.
- Apple invia le notifiche server dell'App Store dalla sottorete 17.0.0.0/8, ma una lista di IP consentiti restringe soltanto chi può raggiungere il tuo endpoint. È la firma a dimostrare che il messaggio proviene da Apple.
- Un verificatore che respinge per errore messaggi autentici costa quanto uno che accetta falsificazioni, perché un CONSUMPTION_REQUEST scartato ha una finestra di risposta di 12 ore e una revisione di chargeback di Google Play ne ha 24.
Chiunque conosca il tuo URL di webhook può inviargli un rimborso. È la scomoda verità dietro ogni notifica server dell'App Store e ogni notifica in tempo reale per sviluppatori di Google Play: finché non la verifichi, il messaggio è soltanto un POST HTTPS con dentro un po' di JSON. Se il tuo server revoca un abbonamento, ritira crediti o banna un account perché una richiesta diceva REFUND, hai consegnato quel potere a chiunque sappia scrivere un comando curl.
Entrambi gli store ti danno un modo per verificare. Apple firma la notifica stessa, quindi puoi verificare le notifiche server dell'App Store con il solo certificato radice di Apple. Google Play segue una strada diversa. Il messaggio non è firmato, ma la consegna di Pub/Sub può esserlo, e Google ti chiede comunque di confermare ogni modifica con la sua API. Ecco che cosa dimostra ciascuno e quanto costa sbagliare in un senso o nell'altro.
Che cosa firma davvero ciascuno store
| Domanda | App Store Server Notifications V2 | Google Play RTDN |
|---|---|---|
| Il messaggio stesso è firmato? | Sì, signedPayload è un JWS | No, il campo data è JSON codificato in base64 |
| Che cosa dimostra il mittente | Catena di certificati x5c fino a una radice Apple | Token OIDC di Pub/Sub in push, o il tuo pull autenticato |
| Oggetti firmati annidati | signedTransactionInfo e signedRenewalInfo, ciascuno con il proprio JWS | Nessuno |
| Campi da confrontare con la tua app | bundleId, appAppleId, environment | packageName |
| Rete di origine | 17.0.0.0/8, sandbox e produzione | Google Cloud Pub/Sub |
| Confermare prima di agire | Facoltativo, i dati firmati fanno fede | Obbligatorio, Google chiede di chiamare la Developer API |
| Trasporto | HTTPS, TLS 1.2 o successivo | Push HTTPS, o pull tramite libreria client |
Come verificare le notifiche server dell'App Store
La documentazione di Apple descrive il signedPayload come una stringa di tre componenti codificati in Base64URL e separati da punti: un header, un payload e una firma, firmata secondo la specifica JSON Web Signature. Decodificare il payload è facile. Fidarsene richiede quattro controlli.
- Leggi l'array x5c dall'header decodificato. Apple ne documenta l'ordine: prima il certificato con la chiave di firma, poi un certificato intermedio Apple, poi un certificato radice Apple.
- Convalida la catena rispetto a una radice Apple che hai scaricato tu stesso dal sito PKI di Apple, in pratica Apple Root CA - G3. Non fidarti mai della radice arrivata dentro il messaggio, perché un falsario può metterci qualsiasi certificato.
- Verifica che l'intermedio abbia l'estensione Apple Worldwide Developer Relations, 1.2.840.113635.100.6.2.1, poi verifica la firma JWS con la chiave pubblica del certificato foglia.
- Confronta i dati decodificati con la tua app: bundleId, appAppleId in produzione ed environment. Una firma Apple valida sull'app di un altro sviluppatore, o su un acquisto sandbox che arriva al tuo endpoint di produzione, continua a non essere il tuo rimborso.
Poi ripeti tutto per ciò che c'è dentro. L'oggetto data contiene signedTransactionInfo e signedRenewalInfo, e ciascuno è un JWS separato con la propria catena x5c. Un handler di REFUND che verifica la busta ma legge la transazione senza verificarla ha lasciato una falla nel mezzo.
Usa la libreria di Apple invece di scriverla da te
Apple pubblica la App Store Server Library per Swift, Java, Python e Node. Il suo SignedDataVerifier riceve i tuoi certificati radice, un flag per i controlli online, l'ambiente, il tuo bundle ID e, per la produzione, il tuo appAppleId. Il codice sorgente Node mostra che cosa impone: esattamente tre certificati nella catena, l'estensione foglia Apple 1.2.840.113635.100.6.11.1 e l'estensione dell'intermedio, le date di validità dei certificati, e bundle ID, ID dell'app e ambiente corrispondenti. Con i controlli online attivi, chiede anche al responder OCSP se i certificati foglia e intermedio sono stati revocati.

Basta una lista di IP consentiti?
No. Apple dice che, se il tuo server ha bisogno di una lista di consentiti, devi aggiungere la sottorete 17.0.0.0/8, e che questo vale sia per la sandbox sia per la produzione. Così riduci il rumore. Non dimostra che un messaggio sia autentico, e smette di funzionare non appena la rete di Apple cambia in un modo di cui non sei stato informato. Mantieni il controllo della firma come vero filtro.
Come verificare le notifiche di rimborso di Google Play
Google Play pubblica i messaggi RTDN in un argomento Pub/Sub di tua proprietà, e solo l'account di servizio google-play-developer-notifications@system.gserviceaccount.com dovrebbe avere su di esso il ruolo di publisher Pub/Sub. La tua sottoscrizione consegna poi i messaggi in uno di due modi, ciascuno con la propria prova.
- Sottoscrizione pull: il tuo server apre una connessione autenticata verso Pub/Sub e recupera i messaggi. Non c'è alcun endpoint pubblico, quindi non c'è nulla a cui un estraneo possa inviare richieste.
- Sottoscrizione push con autenticazione attiva: Pub/Sub firma un JSON Web Token e lo invia nell'header Authorization come token Bearer. La guida di Google indica di convalidare la firma del token e di controllare che i claim email e audience corrispondano ai valori che hai configurato, e il suo codice di esempio richiede anche che email_verified sia true. Il token può avere fino a un'ora di età.
- Sottoscrizione push senza autenticazione: qualunque cosa raggiunga l'URL può inviare un messaggio con la forma di una RTDN.
Perché Google vuole che tu confermi con l'API
Anche una RTDN perfettamente autenticata non racconta tutta la storia. La guida di configurazione di Google afferma chiaramente che queste notifiche ti dicono soltanto che lo stato di un acquisto è cambiato e che devi chiamare la Google Play Developer API per ottenere lo stato completo. Per una voidedPurchaseNotification, ciò significa trovare l'acquisto nella Voided Purchases API, o recuperarne lo stato attuale, prima di revocare qualsiasi cosa. La chiamata all'API è autenticata con il tuo account di servizio, quindi la sua risposta non può essere contraffatta.
Quanto costa in denaro un rimborso falsificato o respinto
Una notifica di rimborso falsificata di cui ti fidi ti costa un cliente pagante. Blocchi qualcuno di cui hai ancora il denaro, questi apre un ticket di assistenza, e alcuni andranno allo store a chiedere il rimborso che il tuo sistema ha già finto di concedere. Un acquisto o un rinnovo falsificato costa nel senso opposto: fornisci calcolo GPU, chiamate a pagamento ad API di terze parti, storage e compensi ai creator a fronte di entrate mai esistite.
L'errore opposto è più silenzioso e spesso più grave. Un verificatore che respinge messaggi autentici, a causa di un appAppleId sbagliato, di un'impostazione sandbox in produzione o di un certificato radice obsoleto, scarta proprio i due flussi di rimborso in cui le tue prove contano. Apple chiede i dati di consumo entro 12 ore da un CONSUMPTION_REQUEST. Google ti concede 24 ore per rispondere a una revisione di chargeback tramite orders.reviewrefund e, per gli ordini effettuati dopo il 3 agosto 2026, un chargeback perso su Google Play ti costa il prezzo di acquisto meno la commissione di servizio di Play, più la commissione addebitata dalla banca dell'acquirente.
| Errore | Che cosa succede | Quanto costa |
|---|---|---|
| REFUND falsificato accettato | Un cliente pagante perde l'accesso | Tempo di assistenza e una vera richiesta di rimborso che hai provocato tu |
| Acquisto falsificato accettato | Accesso gratuito a funzioni a pagamento | Calcolo, chiamate API, storage e compensi senza entrate |
| CONSUMPTION_REQUEST autentico respinto | Apple decide senza i tuoi dati | La vendita, più tutto ciò che hai già speso per erogarla |
| Revisione di chargeback autentica respinta | Google decide senza le tue prove | Prezzo di acquisto e commissioni bancarie sugli ordini dopo il 3 agosto 2026 |
Non lasciare che un bug di verifica ti faccia perdere una scadenza
- Salva la richiesta grezza prima di verificarla, così un messaggio respinto non va mai perso davvero.
- Genera un avviso per ogni verifica fallita. Un messaggio falsificato è rumore. Tutti i messaggi che falliscono insieme sono un tuo bug.
- Con Apple puoi rielaborare ciò che hai respinto. Get Notification History restituisce il signedPayload originale degli ultimi 180 giorni, quindi correggi il verificatore e fagli rielaborare i payload salvati o recuperati.
- Con Google, una revisione di chargeback in sospeso esiste solo nella sua notifica, quindi un'audience push configurata male equivale a una revisione persa. Provala con Send Test Message in Play Console dopo ogni modifica.
RefundHalt verifica le notifiche di entrambi gli store, conferma i rimborsi con le API degli store prima che cambi qualsiasi cosa e risponde ai CONSUMPTION_REQUEST e alle revisioni di chargeback entro le rispettive finestre, così un messaggio falso non può costarti un cliente e uno vero non può sfuggirti.
Domande frequenti
- Come verifico una notifica server dell'App Store?
- Verifica il signedPayload come JSON Web Signature. Leggi la catena di certificati x5c dal suo header, convalidala rispetto a un certificato radice Apple scaricato dal sito PKI di Apple, verifica la firma con la chiave del certificato foglia, poi controlla che bundleId, appAppleId ed environment corrispondano alla tua app. La App Store Server Library di Apple fa tutto questo nel suo SignedDataVerifier.
- Quale chiave uso per convalidare le notifiche server dell'App Store?
- Non ti serve alcuna chiave da App Store Connect. La chiave pubblica si trova nel primo certificato della catena x5c dentro l'header JWS, e te ne fidi solo dopo aver convalidato la catena fino a un certificato radice Apple che hai ottenuto tu stesso. La tua chiave per gli acquisti in-app serve a chiamare le API di Apple, non a controllare le notifiche.
- Le notifiche in tempo reale per sviluppatori di Google Play sono firmate?
- No, Google Play non firma il messaggio RTDN stesso. In una sottoscrizione push autenticata, Pub/Sub invia nell'header Authorization un token OpenID Connect firmato che tu convalidi, e Google indica di chiamare la Google Play Developer API dopo ogni notifica per ottenere lo stato completo dell'acquisto.
- Il mio server deve restituire un errore quando una notifica non supera la verifica?
- Prima salva la richiesta grezza, poi decidi. Apple ritenta una notifica della versione 2 dopo una risposta 40x o 50x, a 1, 12, 24, 48 e 72 ore dal tentativo precedente. Se l'errore dipende dalla tua configurazione, Get Notification History ti permette di recuperare il signedPayload originale per 180 giorni e di verificarlo di nuovo una volta risolto il problema.
- Devo comunque verificare le notifiche se consento solo l'intervallo di IP di Apple?
- Sì. Apple chiede ai server con una lista di consentiti di accettare la sottorete 17.0.0.0/8, il che limita chi può connettersi ma non dimostra che un messaggio sia autentico. La firma JWS è il controllo che lega una notifica ad Apple e alla tua app.
Fonti e approfondimenti
- Apple Developer: signedPayload
- Apple Developer: JWSDecodedHeader
- Apple Developer: Enabling App Store Server Notifications
- Apple Developer: Responding to App Store Server Notifications
- Apple on GitHub: App Store Server Library (Node)
- Android Developers: Get ready (Real-time developer notifications setup)
- Google Cloud: Authentication for push subscriptions
- Play Console Help: Updates to refund protection and chargeback cost responsibility
RefundHalt
Il pilota automatico dei rimborsi per App Store e Google Play
Continua a leggere
Le richieste di rimborso eccessive possono costarti più dei rimborsi stessi, perché entrambi gli store le trattano come un segnale di qualità
La linea guida 5.6.4 di Apple indica le richieste di rimborso eccessive come segnale che un'app non rispetta gli standard di qualità, e l'accordo di distribuzione di Google le consente di rimuovere le app dei nuovi sviluppatori in base ai tassi di rimborso. Ecco cosa dice ciascuno store, quanto costa una rimozione e come restarne alla larga.
Perdere le notifiche di rimborso può costarti gli unici rimborsi che puoi contestare, ed entrambi gli store ti permettono di recuperarle se controlli in tempo
Quando il tuo server perde una notifica di rimborso, le due procedure che chiedono le tue prove si chiudono senza di te. Ecco come Apple e Google Play ritentano l'invio, fin dove puoi recuperare le notifiche di rimborso perse e dove sono i punti scoperti.