Serverseitige Überprüfungs-Callbacks sind URL-Anfragen mit von Google erweiterten Abfrageparametern, die von Google an ein externes System gesendet werden, um es darüber zu informieren, dass ein Nutzer für die Interaktion mit einer Anzeige mit Prämie oder einer Interstitial-Anzeige mit Prämie belohnt werden sollte. Serverseitige Überprüfungs-Callbacks für Anzeigen mit Prämie bieten eine zusätzliche Schutzebene gegen das Spoofing von clientseitigen Überprüfungs-Callbacks, um Nutzer zu belohnen.
In diesem Leitfaden erfahren Sie, wie Sie serverseitige Überprüfungs-Callbacks für Anzeigen mit Prämie mit der kryptografischen Drittanbieterbibliothek „Tink Java Apps“ überprüfen können, um sicherzustellen, dass die Abfrageparameter im Callback legitime Werte sind. ECDSA Sie können Ihren Server auch mit dem Testtool in der AdMob-Benutzeroberfläche testen.
Beispiel für serverseitige Überprüfung für Anzeigen mit Prämie mit Java Spring Boot
Vorbereitung
- Aktivieren Sie die serverseitige Überprüfung für Anzeigen mit Prämie für Ihren Anzeigenblock.
RewardedAdsVerifier aus der Tink Java Apps-Bibliothek verwenden
Das Tink Java Apps GitHub-Repository
enthält die
RewardedAdsVerifier
Hilfsklasse, um den Code zu reduzieren, der zum Überprüfen eines serverseitigen Überprüfungs-Callbacks für Anzeigen mit Prämie erforderlich ist.
Mit dieser Klasse können Sie eine Callback-URL mit dem folgenden Code überprüfen.
RewardedAdsVerifier verifier = new RewardedAdsVerifier.Builder()
.fetchVerifyingPublicKeysWith(
RewardedAdsVerifier.KEYS_DOWNLOADER_INSTANCE_PROD)
.build();
String rewardUrl = ...;
verifier.verify(rewardUrl);
Wenn die Methode verify() ohne Ausnahme ausgeführt wird, wurde die Callback-URL erfolgreich überprüft. Im Abschnitt Nutzer belohnen
finden Sie Best Practices dazu, wann Nutzer belohnt werden sollten. Eine
Aufschlüsselung der Schritte, die von dieser Klasse zum Überprüfen serverseitiger Überprüfungs-Callbacks für Anzeigen mit Prämie ausgeführt werden,
finden Sie im Abschnitt Manuelle Überprüfung serverseitiger Überprüfungs-Callbacks für Anzeigen mit Prämie.
Parameter für serverseitige Überprüfungs-Callbacks
Serverseitige Überprüfungs-Callbacks enthalten Abfrageparameter, die die Interaktion mit der Anzeige mit Prämie beschreiben. Parametername, Beschreibung und Beispielwerte sind unten aufgeführt. Parameter werden in alphabetischer Reihenfolge gesendet.
| Parametername | Beschreibung | Beispielwert |
|---|---|---|
| ad_network | ID der Anzeigenquelle für die Anzeigenquelle, die diese Anzeige bereitgestellt hat. Namen der Anzeigenquelle , die den ID-Werten entsprechen, sind im Abschnitt IDs der Anzeigenquelle aufgeführt. | 1953547073528090325 |
| ad_unit | AdMob-Anzeigenblock-ID, die zum Anfordern der Anzeige mit Prämie verwendet wurde. | 2747237135 |
| custom_data | Benutzerdefinierter Datenstring, wie von
setCustomData bereitgestellt.
Wenn von der App kein benutzerdefinierter Datenstring bereitgestellt wird, ist dieser Abfrageparameter Wert nicht im serverseitigen Überprüfungs-Callback vorhanden. |
SAMPLE_CUSTOM_DATA_STRING |
| key_id | Schlüssel, der zum Überprüfen des serverseitigen Überprüfungs-Callbacks verwendet werden soll. Dieser Wert wird einem öffentlichen Schlüssel zugeordnet, der vom AdMob-Schlüsselserver bereitgestellt wird. | 1234567890 |
| reward_amount | Prämienbetrag, wie in den Anzeigenblockeinstellungen angegeben. | 5 |
| reward_item | Prämienartikel, wie in den Anzeigenblockeinstellungen angegeben. | coins |
| signature | Signatur für den serverseitigen Überprüfungs-Callback, die von AdMob generiert wurde. | MEUCIQCLJS_s4ia_sN06HqzeW7Wc3nhZi4RlW3qV0oO-6AIYdQIgGJEh-rzKreO-paNDbSCzWGMtmgJHYYW9k2_icM9LFMY |
| timestamp | Zeitstempel, wann der Nutzer belohnt wurde, als Epoch-Zeit in Millisekunden. | 1507770365237823 |
| transaction_id | Eindeutige hexadezimal codierte ID für jedes Ereignis der Prämiengewährung, das von AdMob generiert wurde. | 18fa792de1bca816048293fc71035638 |
| user_id | Nutzer-ID, wie von
setUserId bereitgestellt.
Wenn von der App keine Nutzer-ID bereitgestellt wird, ist dieser Abfrageparameter nicht im serverseitigen Überprüfungs-Callback vorhanden. |
1234567 |
IDs der Anzeigenquellen
Namen und IDs der Anzeigenquellen
| Name der Anzeigenquelle | ID der Anzeigenquelle |
|---|---|
| Ad Generation (Bidding) | 1477265452970951479 |
| AdColony | 15586990674969969776 |
| AdColony (Bidding) | 6895345910719072481 |
| AdFalcon | 3528208921554210682 |
| AdMob-Werbenetzwerk | 5450213213286189855 |
| AdMob-Werbenetzwerk-Vermittlungsabfolge | 1215381445328257950 |
| AppLovin | 1063618907739174004 |
| AppLovin (Bidding) | 1328079684332308356 |
| Chartboost | 2873236629771172317 |
| Chocolate Platform (Bidding) | 6432849193975106527 |
| Benutzerdefiniertes Ereignis | 18351550913290782395 |
| DT Exchange* * Vor dem 21. September 2022 hieß dieses Netzwerk „Fyber Marketplace“. | 2179455223494392917 |
| Equativ (Bidding)* * Vor dem 12. Januar 2023 hieß dieses Netzwerk „Smart Adserver“. | 5970199210771591442 |
| Fluct (Bidding) | 8419777862490735710 |
| Flurry | 3376427960656545613 |
| Fyber* * Diese Anzeigenquelle wird für Berichte vom Typ „Bisherige Daten“ verwendet. | 4839637394546996422 |
| i-mobile | 5208827440166355534 |
| Improve Digital (Bidding) | 159382223051638006 |
| Index Exchange (Bidding) | 4100650709078789802 |
| InMobi | 7681903010231960328 |
| InMobi (Bidding) | 6325663098072678541 |
| InMobi Exchange (Bidding) | 5264320421916134407 |
| IronSource | 6925240245545091930 |
| ironSource Ads (Bidding) | 1643326773739866623 |
| Leadbolt | 2899150749497968595 |
| Liftoff Monetize* * Vor dem 30. Januar 2023 hieß dieses Netzwerk „Vungle“. | 1953547073528090325 |
| Liftoff Monetize (Bidding)* * Vor dem 30. Januar 2023 hieß dieses Netzwerk „Vungle (Bidding)“. | 4692500501762622185 |
| LG U+AD | 18298738678491729107 |
| LINE Ads Network | 3025503711505004547 |
| Magnite DV+ (Bidding) | 3993193775968767067 |
| maio | 7505118203095108657 |
| maio (Bidding) | 1343336733822567166 |
| Media.net (Bidding) | 2127936450554446159 |
| Vermittelte hausinterne Anzeigen | 6060308706800320801 |
| Meta Audience Network* * Vor dem 6. Juni 2022 hieß dieses Netzwerk „Facebook Audience Network“. | 10568273599589928883 |
| Meta Audience Network (Bidding)* * Vor dem 6. Juni 2022 hieß dieses Netzwerk „Facebook Audience Network (Bidding)“. | 11198165126854996598 |
| Mintegral | 1357746574408896200 |
| Mintegral (Bidding) | 6250601289653372374 |
| MobFox (Bidding) | 3086513548163922365 |
| MoPub (eingestellt) | 10872986198578383917 |
| myTarget | 8450873672465271579 |
| Nend | 9383070032774777750 |
| Nexxen (Bidding)* * Vor dem 1. Mai 2024 hieß dieses Netzwerk „UnrulyX“. | 2831998725945605450 |
| OneTag Exchange (Bidding) | 4873891452523427499 |
| OpenX (Bidding) | 4918705482605678398 |
| Pangle | 4069896914521993236 |
| Pangle (Bidding) | 3525379893916449117 |
| PubMatic (Bidding) | 3841544486172445473 |
| Reservierungskampagne | 7068401028668408324 |
| SK planet | 734341340207269415 |
| Sharethrough (Bidding) | 5247944089976324188 |
| Smaato (Bidding) | 3362360112145450544 |
| Sonobi (Bidding) | 3270984106996027150 |
| Tapjoy | 7295217276740746030 |
| Tapjoy (Bidding) | 4692500501762622178 |
| Tencent GDT | 7007906637038700218 |
| TripleLift (Bidding) | 8332676245392738510 |
| Unity Ads | 4970775877303683148 |
| Unity Ads (Bidding) | 7069338991535737586 |
| Verve Group (Bidding) | 5013176581647059185 |
| Vpon | 1940957084538325905 |
| Yieldmo (Bidding) | 4193081836471107579 |
| YieldOne (Bidding) | 3154533971590234104 |
| Zucks | 5506531810221735863 |
Nutzer belohnen
Beim Festlegen, wann ein Nutzer belohnt werden soll, ist es wichtig, ein Gleichgewicht zwischen Nutzerfreundlichkeit und Überprüfung der Prämie zu finden. Bei serverseitigen Überprüfungs-Callbacks kann es zu Verzögerungen kommen, bevor sie externe Systeme erreichen. Daher empfiehlt es sich, den clientseitigen Überprüfungs-Callback zu verwenden, um den Nutzer sofort zu belohnen, und gleichzeitig alle Prämien nach Erhalt der serverseitigen Überprüfungs-Callbacks zu überprüfen. Dieser Ansatz bietet eine gute Nutzerfreundlichkeit und gewährleistet gleichzeitig die Gültigkeit der gewährten Prämien.
Bei Anwendungen, bei denen die Gültigkeit der Prämie entscheidend ist (z. B. wenn die Prämie die In-Game-Wirtschaft Ihrer App beeinflusst) und Verzögerungen bei der Gewährung von Prämien akzeptabel sind, ist es möglicherweise am besten, auf den überprüften serverseitigen Überprüfungs-Callback zu warten.
Benutzerdefinierte Daten
Apps, die zusätzliche Daten in serverseitigen Überprüfungs-Callbacks benötigen, sollten die Funktion für benutzerdefinierte Daten von Anzeigen mit Prämie verwenden. Jeder Stringwert, der für ein Anzeigenobjekt mit Prämie festgelegt wurde, wird an den Abfrageparameter custom_data des serverseitigen Überprüfungs-Callbacks übergeben. Wenn kein benutzerdefinierter Datenwert festgelegt ist, ist der Abfrageparameterwert custom_data nicht im serverseitigen Überprüfungs-Callback vorhanden.
Im folgenden Beispiel werden die Optionen für die serverseitige Überprüfung festgelegt, nachdem die Anzeige mit Prämie geladen wurde:
Java
RewardedAd.load(MainActivity.this, "AD_UNIT_ID", new AdRequest.Builder().build(), new RewardedAdLoadCallback() { @Override public void onAdLoaded(RewardedAd ad) { Log.d(TAG, "Ad was loaded."); rewardedAd = ad; ServerSideVerificationOptions options = new ServerSideVerificationOptions .Builder() .setCustomData("SAMPLE_CUSTOM_DATA_STRING") .build(); rewardedAd.setServerSideVerificationOptions(options); } @Override public void onAdFailedToLoad(LoadAdError loadAdError) { Log.d(TAG, loadAdError.toString()); rewardedAd = null; } });
Kotlin
RewardedAd.load(this, "AD_UNIT_ID", AdRequest.Builder().build(), object : RewardedAdLoadCallback() { override fun onAdLoaded(ad: RewardedAd) { Log.d(TAG, "Ad was loaded.") rewardedInterstitialAd = ad val options = ServerSideVerificationOptions.Builder() .setCustomData("SAMPLE_CUSTOM_DATA_STRING") .build() rewardedAd.setServerSideVerificationOptions(options) } override fun onAdFailedToLoad(adError: LoadAdError) { Log.d(TAG, adError?.toString()) rewardedAd = null } })
Wenn Sie den benutzerdefinierten Prämienstring festlegen möchten, müssen Sie dies tun, bevor Sie die Anzeige präsentieren.
und muss möglicherweise decodiert werden, wenn er aus dem serverseitigen Überprüfungs-Callback geparst wird.Manuelle Überprüfung serverseitiger Überprüfungs-Callbacks für Anzeigen mit Prämie
Die Schritte, die von der Klasse RewardedAdsVerifier zum Überprüfen eines serverseitigen Überprüfungs-Callbacks für Anzeigen mit Prämie ausgeführt werden, sind unten aufgeführt. Obwohl die enthaltenen Code-Snippets in Java geschrieben sind und
die Drittanbieterbibliothek Tink verwenden, können Sie diese Schritte in
der Sprache Ihrer Wahl mit jeder Drittanbieterbibliothek implementieren, die
ECDSA unterstützt.
Öffentliche Schlüssel abrufen
Zum Überprüfen eines serverseitigen Überprüfungs-Callbacks für Anzeigen mit Prämie benötigen Sie einen öffentlichen Schlüssel, der von AdMob bereitgestellt wird.
Eine Liste der öffentlichen Schlüssel, die zum Überprüfen der serverseitigen Überprüfungs-Callbacks für Anzeigen mit Prämie verwendet werden sollen, kann vom AdMob-Schlüssel server abgerufen werden. Die Liste der öffentlichen Schlüssel wird als JSON-Darstellung mit einem ähnlichen Format wie das folgende bereitgestellt:
{
"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=="
},
],
}
Rufen Sie die öffentlichen Schlüssel ab, indem Sie eine Verbindung zum AdMob-Schlüsselserver herstellen und die Schlüssel herunterladen. Mit dem folgenden Code wird diese Aufgabe ausgeführt und die JSON-Darstellung der Schlüssel in der Variablen data gespeichert.
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();
}
Öffentliche Schlüssel werden regelmäßig rotiert. Sie erhalten eine E‑Mail, um Sie über eine bevorstehende Rotation zu informieren. Wenn Sie öffentliche Schlüssel im Cache speichern, sollten Sie die Schlüssel aktualisieren, nachdem Sie diese E‑Mail erhalten haben.
Nachdem die öffentlichen Schlüssel abgerufen wurden, müssen sie geparst werden. Die Methode parsePublicKeysJson unten verwendet einen JSON-String wie im obigen Beispiel als Eingabe und erstellt eine Zuordnung von key_id-Werten zu öffentlichen Schlüsseln, die als ECPublicKey-Objekte aus der Tink-Bibliothek gekapselt sind.
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;
}
Zu überprüfenden Inhalt abrufen
Die letzten beiden Abfrageparameter von serverseitigen Überprüfungs-Callbacks für Anzeigen mit Prämie sind immer signature
und key_id, in dieser Reihenfolge. Die übrigen Abfrageparameter geben den zu überprüfenden Inhalt an. Angenommen, Sie haben AdMob so konfiguriert, dass Überprüfungs-Callbacks für Anzeigen mit Prämie an https://www.myserver.com/mypath gesendet werden. Das Snippet unten zeigt ein Beispiel für einen serverseitigen Überprüfungs-Callback für Anzeigen mit Prämie, wobei der zu überprüfende Inhalt hervorgehoben ist.
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
Der folgende Code zeigt, wie der zu überprüfende Inhalt aus einer Callback-URL als UTF-8-Byte-Array geparst wird.
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"));
Signatur und key_id aus der Callback-URL abrufen
Parsen Sie mit dem Wert queryString aus dem vorherigen Schritt die Abfrageparameter signature und key_id aus der Callback-URL, wie unten gezeigt:
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()));
Überprüfung durchführen
Im letzten Schritt wird der Inhalt der Callback-URL mit dem entsprechenden öffentlichen Schlüssel überprüft. Nehmen Sie die Zuordnung, die von der Methode parsePublicKeysJson zurückgegeben wurde, und verwenden Sie den Parameter key_id aus der Callback-URL, um den öffentlichen Schlüssel aus dieser Zuordnung abzurufen. Überprüfen Sie dann die Signatur mit diesem öffentlichen Schlüssel. Diese Schritte werden unten in der Methode verify veranschaulicht.
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);
}
}
Wenn die Methode ohne Ausnahme ausgeführt wird, wurde die Callback-URL erfolgreich überprüft.
FAQ
- Kann ich den öffentlichen Schlüssel im Cache speichern, der vom AdMob-Schlüsselserver bereitgestellt wird?
- Wir empfehlen, den öffentlichen Schlüssel im Cache zu speichern, der vom AdMob-Schlüsselserver bereitgestellt wird, um die Anzahl der Vorgänge zu reduzieren, die zum Überprüfen serverseitiger Überprüfungs-Callbacks erforderlich sind. Öffentliche Schlüssel werden jedoch regelmäßig rotiert und sollten nicht länger als 24 Stunden im Cache gespeichert werden.
- Wie oft werden die öffentlichen Schlüssel rotiert, die vom AdMob-Schlüsselserver bereitgestellt werden?
- Öffentliche Schlüssel, die vom AdMob-Schlüsselserver bereitgestellt werden, werden nach einem variablen Zeitplan rotiert. Damit die Überprüfung serverseitiger Überprüfungs-Callbacks weiterhin wie vorgesehen funktioniert, sollten öffentliche Schlüssel nicht länger als 24 Stunden im Cache gespeichert werden.
- Was passiert, wenn mein Server nicht erreichbar ist?
- Google erwartet für serverseitige Überprüfungs-Callbacks den Antwortcode
HTTP 200 OK. Wenn Ihr Server nicht erreichbar ist oder nicht die erwartete Antwort liefert, versucht Google bis zu fünf Mal, serverseitige Überprüfungs-Callbacks in Abständen von einer Sekunde zu senden. - Wie kann ich überprüfen, ob serverseitige Überprüfungs-Callbacks von Google stammen?
- Verwenden Sie den umgekehrten DNS-Lookup, um zu überprüfen, ob serverseitige Überprüfungs-Callbacks von Google stammen.