Callbacks zur serverseitigen Überprüfung sind URL-Anfragen mit von Google erweiterten Suchparametern, 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 eine Prämie erhalten soll. Callbacks für die serverseitige Überprüfung (Server-Side Verification, SSV) von Anzeigen mit Prämie bieten zusätzlichen Schutz vor Spoofing von clientseitigen Callbacks, um Nutzern Prämien zu gewähren.
In diesem Leitfaden wird beschrieben, wie Sie SSV-Callbacks für Anzeigen mit Prämie mithilfe der kryptografischen Drittanbieterbibliothek Tink Java Apps überprüfen, um sicherzustellen, dass die Suchparameter im Callback zulässige Werte sind. In diesem Leitfaden wird Tink verwendet. Sie können jedoch jede Drittanbieterbibliothek verwenden, die ECDSA unterstützt. Sie können Ihren Server auch mit dem Testtool in der AdMob-Benutzeroberfläche testen.
Vorbereitung
- Aktivieren Sie die serverseitige Überprüfung für Anzeigen mit Prämie für Ihren Anzeigenblock.
Verwenden Sie „RewardedAdsVerifier“ aus der Tink-Java-Apps-Bibliothek.
Das GitHub-Repository Tink Java Apps enthält die Hilfsklasse RewardedAdsVerifier, mit der sich der Code reduzieren lässt, der für die Bestätigung eines SSV-Callbacks für eine Prämie erforderlich ist.
Mit dieser Klasse können Sie eine Callback-URL mit dem folgenden Code prü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 bestätigt. Im Abschnitt Nutzer belohnen finden Sie Best Practices dazu, wann Nutzer belohnt werden sollten. Eine Aufschlüsselung der Schritte, die von dieser Klasse zur Überprüfung von SSV-Callbacks für Prämien ausgeführt werden, finden Sie im Abschnitt Manuelle Überprüfung von SSV für Prämien.
Parameter für serverseitige Callbacks
Callbacks zur serverseitigen Überprüfung enthalten Suchparameter, die die Interaktion mit der Anzeige mit Prämie beschreiben. Parameternamen, Beschreibungen und Beispielwerte sind unten aufgeführt. Die Parameter werden in alphabetischer Reihenfolge gesendet.
| Parametername | Beschreibung | Beispielwert |
|---|---|---|
| ad_network | Anzeigenquellen-ID für die Anzeigenquelle, die diese Anzeige bereitgestellt hat. Die Namen der Anzeigenquellen, die den ID-Werten entsprechen, sind im Abschnitt Kennungen für Anzeigenquellen aufgeführt. | 1953547073528090325 |
| ad_unit | Die AdMob-Anzeigenblock-ID, die zum Anfordern der Anzeige mit Prämie verwendet wurde. | 2747237135 |
| custom_data | Benutzerdefinierter Datenstring, wie von
customRewardString bereitgestellt.
Wenn von der App kein benutzerdefinierter Datenstring bereitgestellt wird, ist dieser Suchparameterwert im SSV-Callback nicht vorhanden. |
SAMPLE_CUSTOM_DATA_STRING |
| key_id | Schlüssel, der zur Überprüfung des SSV-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 Einstellungen des Anzeigenblocks angegeben. | 5 |
| reward_item | Prämienartikel, wie in den Einstellungen des Anzeigenblocks angegeben. | Münzen |
| Signatur | Signatur für den von AdMob generierten SSV-Callback. | MEUCIQCLJS_s4ia_sN06HqzeW7Wc3nhZi4RlW3qV0oO-6AIYdQIgGJEh-rzKreO-paNDbSCzWGMtmgJHYYW9k2_icM9LFMY |
| timestamp | Zeitstempel, wann der Nutzer die Prämie erhalten hat, als Epochenzeit in Millisekunden. | 1507770365237823 |
| transaction_id | Eindeutige hexadezimal codierte Kennung für jedes von AdMob generierte Ereignis, bei dem eine Prämie gewährt wird. | 18fa792de1bca816048293fc71035638 |
| user_id | Nutzer-ID, wie von userIdentifier bereitgestellt.
Wenn von der App keine Nutzer-ID bereitgestellt wird, ist dieser Suchparameter im SSV-Callback nicht vorhanden. |
1234567 |
Anzeigenquellen-IDs
Namen und IDs der Anzeigenquellen
| Name der Anzeigenquelle | Anzeigenquellen-ID |
|---|---|
| Ad Generation (Bidding) | 1477265452970951479 |
| AdMob-Werbenetzwerk | 5450213213286189855 |
| Vermittlungsabfolge im AdMob-Werbenetzwerk | 1215381445328257950 |
| AppLovin | 1063618907739174004 |
| AppLovin (Bidding) | 1328079684332308356 |
| Bidease (Bidding) | 3670825090829827805 |
| BidMachine (Bidding) | 7943972370566394673 |
| Chartboost | 2873236629771172317 |
| Chocolate Platform (Bidding) | 6432849193975106527 |
| Benutzerdefiniertes Ereignis | 18351550913290782395 |
| DT Exchange* * Vor dem 21. September 2022 hieß dieses Werbenetzwerk „Fyber Marketplace“. | 2179455223494392917 |
| DT Exchange (Bidding) | 8189833498765234879 |
| Equativ (Bidding)* * Vor dem 12. Januar 2023 hieß dieses Netzwerk „Smart Adserver“. | 5970199210771591442 |
| Fluct (Bidding) | 8419777862490735710 |
| i-mobile | 5208827440166355534 |
| Improve Digital (Bidding) | 159382223051638006 |
| Index Exchange (Bidding) | 4100650709078789802 |
| InMobi | 7681903010231960328 |
| InMobi (SDK) (Bidding) | 8468954295581492586 |
| InMobi Exchange (Bidding) | 5264320421916134407 |
| ironSource Ads | 6925240245545091930 |
| ironSource Ads (Bidding) | 1643326773739866623 |
| Liftoff Monetize* * Vor dem 30. Januar 2023 hieß dieses Netzwerk „Vungle“. | 1953547073528090325 |
| Liftoff Monetize (Bidding)* * Vor dem 30. Januar 2023 hieß dieses Werbenetzwerk „Vungle (Bidding)“. | 4692500501762622185 |
| LY Ads Network | 3025503711505004547 |
| LY Ads Werbenetzwerk (Bidding) | 2615812619460460513 |
| Magnite DV+ (Bidding) | 3993193775968767067 |
| maio | 7505118203095108657 |
| 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 |
| MobileFuse (Bidding) | 7303547408604090310 |
| Moloco Ads SDK (Bidding) | 8267622065755668722 |
| myTarget | 8450873672465271579 |
| Nativo (Bidding) | 3240503836211327896 |
| Nexxen (Bidding)* * Vor dem 1. Mai 2024 hieß dieses Werbenetzwerk „UnrulyX“. | 2831998725945605450 |
| OneTag Exchange (Bidding) | 4873891452523427499 |
| OpenX (Bidding) | 4918705482605678398 |
| Pangle | 4069896914521993236 |
| Pangle KR SDK (Gebote) | 12171279046073404914 |
| Pangle ROW SDK (Gebote) | 3525379893916449117 |
| Pangle US SDK (Gebote) | 15999446638585856012 |
| PubMatic (Bidding) | 3841544486172445473 |
| PubMatic OpenWrap SDK | 7702975372504485373 |
| PubMatic OpenWrap SDK (Bidding) | 1234567890123456789 |
| Reservierungskampagne | 7068401028668408324 |
| Rise (Gebote) | 6816468518946650043 |
| Sharethrough (Bidding) | 5247944089976324188 |
| Smaato (Bidding) | 3362360112145450544 |
| Sonobi (Bidding) | 3270984106996027150 |
| 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
Bei der Entscheidung, wann ein Nutzer eine Prämie erhalten soll, ist es wichtig, ein Gleichgewicht zwischen Nutzerfreundlichkeit und Prämienvalidierung zu finden. Bei serverseitigen Callbacks kann es zu Verzögerungen kommen, bevor sie externe Systeme erreichen. Daher wird empfohlen, den clientseitigen Callback zu verwenden, um den Nutzer sofort zu belohnen, und alle Prämien nach Erhalt der serverseitigen Callbacks zu validieren. Dieser Ansatz bietet eine gute Nutzerfreundlichkeit und sorgt gleichzeitig dafür, dass die gewährten Prämien gültig sind.
Bei Anwendungen, bei denen die Gültigkeit der Prämie entscheidend ist (z. B. wenn sich die Prämie auf die In-Game-Wirtschaft Ihrer App auswirkt) und Verzögerungen bei der Gewährung von Prämien akzeptabel sind, ist es jedoch möglicherweise am besten, auf den verifizierten serverseitigen Callback zu warten.
Benutzerdefinierte Daten
Apps, die zusätzliche Daten in Callbacks für die serverseitige Überprüfung benötigen, sollten die Funktion für benutzerdefinierte Daten von Anzeigen mit Prämie verwenden. Alle Stringwerte, die für ein Anzeigenobjekt mit Prämie festgelegt sind, werden an den Abfrageparameter custom_data des SSV-Callbacks übergeben. Wenn kein benutzerdefinierter Datenwert festgelegt ist, ist der Wert des Suchparameters custom_data im SSV-Callback nicht vorhanden.
Im folgenden Beispiel werden die SSV-Optionen festgelegt, nachdem die Anzeige mit Prämie geladen wurde:
Swift
RewardedAd.load(with:"AD_UNIT_ID", request: request, completionHandler: { [self] ad, error in if let error != error { rewardedAd = ad let options = ServerSideVerificationOptions() options.customRewardString = "SAMPLE_CUSTOM_DATA_STRING" rewardedAd.serverSideVerificationOptions = options } })
Objective-C
GADRequest *request = [GADRequest request]; [GADRewardedAd loadWithAdUnitID:@"AD_UNIT_ID" request:request completionHandler:^(GADRewardedAd *ad, NSError *error) { if (error) { // Handle Error return; } self.rewardedAd = ad; GADServerSideVerificationOptions *options = [[GADServerSideVerificationOptions alloc] init]; options.customRewardString = @"SAMPLE_CUSTOM_DATA_STRING"; ad.serverSideVerificationOptions = options; }];
Manuelle Überprüfung der serverseitigen Überprüfung für Anzeigen mit Prämie
Im Folgenden werden die Schritte beschrieben, die von der Klasse RewardedAdsVerifier ausgeführt werden, um eine SSV-Prämie zu überprüfen. Die enthaltenen Code-Snippets sind zwar in Java und nutzen die Tink-Drittanbieterbibliothek, Sie können diese Schritte jedoch in der Sprache Ihrer Wahl mit einer beliebigen Drittanbieterbibliothek implementieren, die ECDSA unterstützt.
Öffentliche Schlüssel abrufen
Wenn Sie einen SSV-Callback für eine Prämie bestätigen möchten, benötigen Sie einen öffentlichen Schlüssel von AdMob.
Eine Liste der öffentlichen Schlüssel, die zur Validierung der SSV-Callbacks für Anzeigen mit Prämie verwendet werden, kann vom AdMob-Schlüsselserver abgerufen werden. Die Liste der öffentlichen Schlüssel wird als JSON-Darstellung mit einem Format wie dem folgenden 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=="
},
],
}
Wenn Sie die öffentlichen Schlüssel abrufen möchten, stellen Sie eine Verbindung zum AdMob-Schlüsselserver her und laden Sie die Schlüssel herunter. Der folgende Code führt diese Aufgabe aus und speichert die JSON-Darstellung der Schlüssel in der Variablen 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();
}
Öffentliche Schlüssel werden regelmäßig rotiert. Sie werden per E-Mail über eine anstehende Rotation informiert. Wenn Sie öffentliche Schlüssel im Cache speichern, sollten Sie die Schlüssel nach Erhalt dieser E-Mail aktualisieren.
Nachdem die öffentlichen Schlüssel abgerufen wurden, müssen sie geparst werden. Die folgende Methode parsePublicKeysJson 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;
}
Inhalte zur Überprüfung abrufen
Die letzten beiden Suchparameter von SSV-Callbacks für Anzeigen mit Prämie sind immer signature und key_id, (in dieser Reihenfolge). Die verbleibenden Suchparameter geben den zu überprüfenden Inhalt an. Angenommen, Sie haben AdMob so konfiguriert, dass Prämien-Callbacks an https://www.myserver.com/mypath gesendet werden. Das folgende Snippet zeigt ein Beispiel für einen SSV-Callback für eine 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
Im folgenden Code wird gezeigt, 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 Suchparameter 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()));
Bestätigung durchführen
Im letzten Schritt wird der Inhalt der Callback-URL mit dem entsprechenden öffentlichen Schlüssel überprüft. Verwenden Sie die von der Methode parsePublicKeysJson zurückgegebene Zuordnung und den Parameter key_id aus der Callback-URL, um den öffentlichen Schlüssel aus dieser Zuordnung abzurufen. Anschließend wird die Signatur mit diesem öffentlichen Schlüssel verifiziert. 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 Auslösen einer Ausnahme ausgeführt wird, wurde die Callback-URL erfolgreich bestätigt.
FAQ
- Kann ich den vom AdMob-Schlüsselserver bereitgestellten öffentlichen Schlüssel im Cache speichern?
- Wir empfehlen, den vom AdMob-Schlüsselserver bereitgestellten öffentlichen Schlüssel im Cache zu speichern, um die Anzahl der Vorgänge zu reduzieren, die zum Validieren von SSV-Callbacks erforderlich sind. Beachten Sie jedoch, dass öffentliche Schlüssel regelmäßig rotiert werden und nicht länger als 24 Stunden im Cache gespeichert werden sollten.
- Wie oft werden die vom AdMob-Schlüsselserver bereitgestellten öffentlichen Schlüssel rotiert?
- Die vom AdMob-Schlüsselserver bereitgestellten öffentlichen Schlüssel werden nach einem variablen Zeitplan rotiert. Damit die Bestätigung von SSV-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 SSV-Callbacks den Antwortcode
HTTP 200 OKfür einen erfolgreichen Status. Wenn Ihr Server nicht erreichbar ist oder nicht die erwartete Antwort liefert, versucht Google bis zu fünfmal im Abstand von einer Sekunde, SSV-Callbacks zu senden. - Wie kann ich prüfen, ob SSV-Callbacks von Google stammen?
- Verwenden Sie einen umgekehrten DNS-Lookup, um zu prüfen, ob SSV-Callbacks von Google stammen.