I callback di verifica lato server sono richieste URL, con parametri di query espansi da Google, che vengono inviati da Google a un sistema esterno per comunicare che un utente deve ricevere un premio per l'interazione con un annuncio con premio o un annuncio interstitial con premio. I callback di verifica lato server degli annunci con premio forniscono un ulteriore livello di protezione contro lo spoofing dei callback lato client per premiare gli utenti.
Questa guida mostra come verificare i callback di verifica lato server degli annunci con premio utilizzando la libreria di crittografia di terze parti Tink Java Apps per assicurarti che i parametri di query nel callback siano valori legittimi. Sebbene Tink venga utilizzato ai fini di questa guida, hai la possibilità di utilizzare qualsiasi libreria di terze parti che supporti ECDSA. Puoi anche testare il tuo server con lo strumento di testing tool nell'interfaccia utente di AdMob.
Prerequisiti
Utilizzare RewardedAdsVerifier dalla libreria Tink Java Apps
Il repository GitHub di Tink Java Apps
include una
RewardedAdsVerifier
classe helper per ridurre il codice necessario per verificare un callback di verifica lato server degli annunci con premio.
L'utilizzo di questa classe ti consente di verificare un URL di callback con il seguente codice.
RewardedAdsVerifier verifier = new RewardedAdsVerifier.Builder()
.fetchVerifyingPublicKeysWith(
RewardedAdsVerifier.KEYS_DOWNLOADER_INSTANCE_PROD)
.build();
String rewardUrl = ...;
verifier.verify(rewardUrl);
Se il metodo verify() viene eseguito senza generare un'eccezione, l'URL di callback è stato verificato correttamente. La sezione Premiare l'utente
descrive le best practice relative al momento in cui gli utenti devono ricevere un premio. Per un'
analisi dettagliata dei passaggi eseguiti da questa classe per verificare i callback SSV con premio,
puoi leggere la sezione Verifica manuale degli SSV con premio.
Parametri di callback di verifica lato server
I callback di verifica lato server contengono parametri di query che descrivono l'interazione con l'annuncio con premio. Di seguito sono elencati i nomi dei parametri, le descrizioni e i valori di esempio. I parametri vengono inviati in ordine alfabetico.
| Nome parametro | Descrizione | Valore di esempio |
|---|---|---|
| ad_network | Identificatore dell'origine annuncio per l'origine annuncio che ha soddisfatto questo annuncio. I nomi delle origini annuncio corrispondenti ai valori ID sono elencati nella sezione Identificatori delle origini annuncio. | 1953547073528090325 |
| ad_unit | ID unità pubblicitaria AdMob utilizzato per richiedere l'annuncio con premio. | 2747237135 |
| key_id | Chiave da utilizzare per verificare il callback di verifica lato server. Questo valore viene mappato a una chiave pubblica fornita dal server delle chiavi di AdMob. | 1234567890 |
| reward_amount | Importo del premio specificato nelle impostazioni dell'unità pubblicitaria. | 5 |
| reward_item | Articolo premio specificato nelle impostazioni dell'unità pubblicitaria. | monete |
| signature | Firma per il callback di verifica lato server generato da AdMob. | MEUCIQCLJS_s4ia_sN06HqzeW7Wc3nhZi4RlW3qV0oO-6AIYdQIgGJEh-rzKreO-paNDbSCzWGMtmgJHYYW9k2_icM9LFMY |
| timestamp | Timestamp del momento in cui l'utente ha ricevuto il premio in tempo Epoch in ms. | 1507770365237823 |
| transaction_id | Identificatore univoco codificato in esadecimale per ogni evento di concessione del premio generato da AdMob. | 18fa792de1bca816048293fc71035638 |
| user_id | Identificatore utente fornito da
SetUserId.
Se l'app non fornisce un identificatore utente, questo parametro di query non sarà presente nel callback di verifica lato server. |
1234567 |
Identificatori delle origini annuncio
Nomi e ID delle origini annuncio
| Nome origine annuncio | ID origine annuncio |
|---|---|
| Ad Generation (offerte) | 1477265452970951479 |
| AdColony | 15586990674969969776 |
| AdColony (offerte) | 6895345910719072481 |
| AdFalcon | 3528208921554210682 |
| Rete AdMob | 5450213213286189855 |
| Struttura a cascata della Rete AdMob | 1215381445328257950 |
| AppLovin | 1063618907739174004 |
| AppLovin (offerte) | 1328079684332308356 |
| Chartboost | 2873236629771172317 |
| Chocolate Platform (offerte) | 6432849193975106527 |
| Evento personalizzato | 18351550913290782395 |
| DT Exchange* * Prima del 21 settembre 2022, questa rete si chiamava "Fyber Marketplace". | 2179455223494392917 |
| Equativ (offerte)* * Prima del 12 gennaio 2023, questa rete si chiamava "Smart Adserver". | 5970199210771591442 |
| Fluct (offerte) | 8419777862490735710 |
| Turbine | 3376427960656545613 |
| Fyber* * Questa origine annuncio viene utilizzata per i report storici. | 4839637394546996422 |
| i-mobile | 5208827440166355534 |
| Improve Digital (offerte) | 159382223051638006 |
| Index Exchange (offerte) | 4100650709078789802 |
| InMobi | 7681903010231960328 |
| InMobi (offerte) | 6325663098072678541 |
| InMobi Exchange (offerte) | 5264320421916134407 |
| IronSource | 6925240245545091930 |
| ironSource Ads (offerte) | 1643326773739866623 |
| Leadbolt | 2899150749497968595 |
| Liftoff Monetize* * Prima del 30 gennaio 2023, questa rete si chiamava "Vungle". | 1953547073528090325 |
| Liftoff Monetize (offerte)* * Prima del 30 gennaio 2023, questa rete si chiamava "Vungle (asta)". | 4692500501762622185 |
| LG U+AD | 18298738678491729107 |
| LINE Ads Network | 3025503711505004547 |
| Magnite DV+ (offerte) | 3993193775968767067 |
| maio | 7505118203095108657 |
| maio (offerte) | 1343336733822567166 |
| Media.net (offerte) | 2127936450554446159 |
| Annunci autopromozionali mediati | 6060308706800320801 |
| Audience Network di Meta* * Prima del 6 giugno 2022, questa rete si chiamava "Facebook Audience Network". | 10568273599589928883 |
| Audience Network di Meta (offerte)* * Prima del 6 giugno 2022, questa rete si chiamava "Facebook Audience Network (offerte)". | 11198165126854996598 |
| Mintegral | 1357746574408896200 |
| Mintegral (offerte) | 6250601289653372374 |
| MobFox (offerte) | 3086513548163922365 |
| MoPub (deprecato) | 10872986198578383917 |
| myTarget | 8450873672465271579 |
| Nend | 9383070032774777750 |
| Nexxen (offerte)* * Prima del 1° maggio 2024, questa rete si chiamava "UnrulyX". | 2831998725945605450 |
| OneTag Exchange (offerte) | 4873891452523427499 |
| OpenX (offerte) | 4918705482605678398 |
| Pangle | 4069896914521993236 |
| Pangle (offerte) | 3525379893916449117 |
| PubMatic (offerte) | 3841544486172445473 |
| Campagna basata su prenotazione | 7068401028668408324 |
| SK planet | 734341340207269415 |
| Sharethrough (offerte) | 5247944089976324188 |
| Smaato (offerte) | 3362360112145450544 |
| Sonobi (offerte) | 3270984106996027150 |
| Tapjoy | 7295217276740746030 |
| Tapjoy (offerte) | 4692500501762622178 |
| Tencent GDT | 7007906637038700218 |
| TripleLift (offerte) | 8332676245392738510 |
| Unity Ads | 4970775877303683148 |
| Unity Ads (offerte) | 7069338991535737586 |
| Verve Group (offerte) | 5013176581647059185 |
| Vpon | 1940957084538325905 |
| Yieldmo (offerte) | 4193081836471107579 |
| YieldOne (offerte) | 3154533971590234104 |
| Zucks | 5506531810221735863 |
Premiare l'utente
Quando decidi quando premiare un utente, è importante bilanciare l'esperienza utente e la convalida del premio. I callback lato server potrebbero subire ritardi prima di raggiungere i sistemi esterni. Pertanto, la best practice consigliata è utilizzare il callback lato client per premiare immediatamente l'utente, eseguendo la convalida di tutti i premi al ricevimento dei callback lato server. Questo approccio offre una buona esperienza utente, garantendo al contempo la validità dei premi concessi.
Tuttavia, per le applicazioni in cui la validità del premio è fondamentale (ad esempio, il premio influisce sull'economia in-game dell'app) e i ritardi nella concessione dei premi sono accettabili, l'approccio migliore potrebbe essere attendere il callback lato server verificato.
Dati personalizzati
Le app che richiedono dati aggiuntivi nei callback di verifica lato server devono utilizzare la funzionalità dei dati personalizzati degli annunci con premio. Qualsiasi valore stringa impostato su un oggetto annuncio con premio viene passato al parametro di query custom_data del callback di verifica lato server. Se non viene impostato alcun valore di dati personalizzati, il valore del parametro di query custom_data non sarà presente nel callback di verifica lato server.
Il seguente esempio di codice mostra come impostare le opzioni di verifica lato server dopo il caricamento dell'annuncio con premio:
private void LoadRewardedAd(string adUnitId)
{
// Send the request to load the ad.
AdRequest adRequest = new AdRequest();
RewardedAd.Load(adUnitId, adRequest, (RewardedAd rewardedAd, LoadAdError error) =>
{
// If the operation failed with a reason.
if (error != null)
{
Debug.LogError("Rewarded ad failed to load an ad with error : " + error);
return;
}
var options = new ServerSideVerificationOptions
.Builder()
.SetCustomData("SAMPLE_CUSTOM_DATA_STRING")
.Build()
rewardedAd.SetServerSideVerificationOptions(options);
});
}
Se vuoi impostare la stringa del premio personalizzata, devi farlo prima di mostrare l'annuncio.
Verifica manuale della verifica lato server degli annunci con premio
Di seguito sono descritti i passaggi eseguiti dalla classe RewardedAdsVerifier per verificare un SSV con premio. Sebbene gli snippet di codice inclusi siano in Java e
utilizzino la libreria di terze parti Tink, puoi implementare questi passaggi nel
linguaggio di tua scelta, utilizzando qualsiasi libreria di terze parti che supporti
ECDSA.
Recuperare le chiavi pubbliche
Per verificare un callback di verifica lato server degli annunci con premio, devi disporre di una chiave pubblica fornita da AdMob.
È possibile recuperare un elenco di chiavi pubbliche da utilizzare per convalidare i callback di verifica lato server degli annunci con premio da l server delle chiavi di AdMob. L'elenco delle chiavi pubbliche viene fornito come rappresentazione JSON con un formato simile al seguente:
{
"keys": [
{
keyId: 1916455855,
pem: "-----BEGIN PUBLIC KEY-----\nMF...YTPcw==\n-----END PUBLIC KEY-----"
base64: "MFkwEwYHKoZIzj0CAQYI...ltS4nzc9yjmhgVQOlmSS6unqvN9t8sqajRTPcw=="
},
{
keyId: 3901585526,
pem: "-----BEGIN PUBLIC KEY-----\nMF...aDUsw==\n-----END PUBLIC KEY-----"
base64: "MFYwEAYHKoZIzj0CAQYF...4akdWbWDCUrMMGIV27/3/e7UuKSEonjGvaDUsw=="
},
],
}
Per recuperare le chiavi pubbliche, connettiti al server delle chiavi di AdMob e scarica le chiavi. Il seguente codice esegue questa attività e salva la rappresentazione JSON delle chiavi nella variabile data.
String url = ...;
NetHttpTransport httpTransport = new NetHttpTransport.Builder().build();
HttpRequest httpRequest =
httpTransport.createRequestFactory().buildGetRequest(new GenericUrl(url));
HttpResponse httpResponse = httpRequest.execute();
if (httpResponse.getStatusCode() != HttpStatusCodes.STATUS_CODE_OK) {
throw new IOException("Unexpected status code = " + httpResponse.getStatusCode());
}
String data;
InputStream contentStream = httpResponse.getContent();
try {
InputStreamReader reader = new InputStreamReader(contentStream, UTF_8);
data = readerToString(reader);
} finally {
contentStream.close();
}
Tieni presente che le chiavi pubbliche vengono ruotate regolarmente. Riceverai un'email per informarti di una rotazione imminente. Se memorizzi nella cache le chiavi pubbliche, devi aggiornarle al ricevimento di questa email.
Una volta recuperate, le chiavi pubbliche devono essere analizzate. Il metodo parsePublicKeysJson riportato di seguito accetta come input una stringa JSON, come l'esempio riportato sopra, e crea una mappatura dai valori key_id alle chiavi pubbliche, che vengono incapsulate come oggetti ECPublicKey dalla libreria Tink.
private static Map<Integer, ECPublicKey> parsePublicKeysJson(String publicKeysJson)
throws GeneralSecurityException {
Map<Integer, ECPublicKey> publicKeys = new HashMap<>();
try {
JSONArray keys = new JSONObject(publicKeysJson).getJSONArray("keys");
for (int i = 0; i < keys.length(); i++) {
JSONObject key = keys.getJSONObject(i);
publicKeys.put(
key.getInt("keyId"),
EllipticCurves.getEcPublicKey(Base64.decode(key.getString("base64"))));
}
} catch (JSONException e) {
throw new GeneralSecurityException("failed to extract trusted signing public keys", e);
}
if (publicKeys.isEmpty()) {
throw new GeneralSecurityException("No trusted keys are available.");
}
return publicKeys;
}
Recuperare i contenuti da verificare
Gli ultimi due parametri di query dei callback di verifica lato server degli annunci con premio sono sempre signature
e key_id, in questo ordine. I parametri di query rimanenti specificano i contenuti da verificare. Supponiamo che tu abbia configurato AdMob per inviare i callback dei premi a https://www.myserver.com/mypath. Lo snippet riportato di seguito mostra un esempio di callback di verifica lato server degli annunci con premio con i contenuti da verificare evidenziati.
https://www.myserver.com/path?ad_network=54...55&ad_unit=12345678&reward_amount=10&reward_item=coins ×tamp=150777823&transaction_id=12...DEF&user_id=1234567&signature=ME...Z1c&key_id=1268887
Il codice riportato di seguito mostra come analizzare i contenuti da verificare da un URL di callback come array di byte UTF-8.
public static final String SIGNATURE_PARAM_NAME = "signature=";
...
URI uri;
try {
uri = new URI(rewardUrl);
} catch (URISyntaxException ex) {
throw new GeneralSecurityException(ex);
}
String queryString = uri.getQuery();
int i = queryString.indexOf(SIGNATURE_PARAM_NAME);
if (i == -1) {
throw new GeneralSecurityException("needs a signature query parameter");
}
byte[] queryParamContentData =
queryString
.substring(0, i - 1)
// i - 1 instead of i because of & in the query string
.getBytes(Charset.forName("UTF-8"));
Recuperare la firma e key_id dall'URL di callback
Utilizzando il valore queryString del passaggio precedente, analizza i parametri di query signature e key_id dall'URL di callback come mostrato di seguito:
public static final String KEY_ID_PARAM_NAME = "key_id=";
...
String sigAndKeyId = queryString.substring(i);
i = sigAndKeyId.indexOf(KEY_ID_PARAM_NAME);
if (i == -1) {
throw new GeneralSecurityException("needs a key_id query parameter");
}
String sig =
sigAndKeyId.substring(
SIGNATURE_PARAM_NAME.length(), i - 1 /* i - 1 instead of i because of & */);
int keyId = Integer.valueOf(sigAndKeyId.substring(i + KEY_ID_PARAM_NAME.length()));
Eseguire la verifica
Il passaggio finale consiste nel verificare i contenuti dell'URL di callback con la chiave pubblica appropriata. Prendi la mappatura restituita dal metodo parsePublicKeysJson e utilizza il parametro key_id dall'URL di callback per ottenere la chiave pubblica da quella mappatura. Quindi verifica la firma con quella chiave pubblica. Questi passaggi sono illustrati di seguito nel metodo verify.
private void verify(final byte[] dataToVerify, int keyId, final byte[] signature)
throws GeneralSecurityException {
Map<Integer, ECPublicKey> publicKeys = parsePublicKeysJson();
if (publicKeys.containsKey(keyId)) {
foundKeyId = true;
ECPublicKey publicKey = publicKeys.get(keyId);
EcdsaVerifyJce verifier = new EcdsaVerifyJce(publicKey, HashType.SHA256, EcdsaEncoding.DER);
verifier.verify(signature, dataToVerify);
} else {
throw new GeneralSecurityException("cannot find verifying key with key ID: " + keyId);
}
}
Se il metodo viene eseguito senza generare un'eccezione, l'URL di callback è stato verificato correttamente.
Domande frequenti
- Posso memorizzare nella cache la chiave pubblica fornita dal server delle chiavi di AdMob?
- Ti consigliamo di memorizzare nella cache la chiave pubblica fornita dal server delle chiavi di AdMob per ridurre il numero di operazioni necessarie per convalidare i callback di verifica lato server. Tuttavia, tieni presente che le chiavi pubbliche vengono ruotate regolarmente e non devono essere memorizzate nella cache per più di 24 ore.
- Con quale frequenza vengono ruotate le chiavi pubbliche fornite dal server delle chiavi di AdMob?
- Le chiavi pubbliche fornite dal server delle chiavi di AdMob vengono ruotate in base a una pianificazione variabile. Per garantire che la verifica dei callback di verifica lato server continui a funzionare come previsto, le chiavi pubbliche non devono essere memorizzate nella cache per più di 24 ore.
- Cosa succede se il mio server non è raggiungibile?
- Google si aspetta un codice di risposta di successo
HTTP 200 OKper i callback di verifica lato server. Se il tuo server non è raggiungibile o non fornisce la risposta prevista, Google tenterà di inviare nuovamente i callback di verifica lato server fino a cinque volte a intervalli di un secondo. - Come faccio a verificare che i callback di verifica lato server provengano da Google?
- Utilizza la ricerca DNS inversa per verificare che i callback di verifica lato server provengano da Google.