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 interstitiellen Anzeige mit Prämie belohnt werden soll. Serverseitige Überprüfungs-Callbacks für Anzeigen mit Prämie bieten einen zusätzlichen Schutz vor Spoofing von clientseitigen Callbacks, um Nutzern Prämien zu gewähren.
In diesem Leitfaden erfahren Sie, wie Sie mit der kryptografischen Drittanbieterbibliothek Tink Java Apps SSV-Callbacks für Anzeigen mit Prämie prüfen, um sicherzustellen, dass die Abfrageparameter im Callback gültige Werte sind. In dieser Anleitung 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.
RewardedAdsVerifier aus der Tink Java Apps-Bibliothek verwenden
Das GitHub-Repository Tink Java Apps enthält eine RewardedAdsVerifier
-Hilfsklasse, um den Code zur Bestätigung eines SSV-Callbacks mit Prämie zu reduzieren.
Mit dieser Klasse kannst du eine Rückruf-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 verify()
-Methode ausgeführt wird, ohne dass eine Ausnahme ausgelöst wird, wurde die Rückruf-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 mit Prämie ausgeführt werden, finden Sie im Abschnitt Manuelle Überprüfung von SSV-Callbacks mit Prämie.
SSV-Callback-Parameter
Callbacks zur serverseitigen Überprüfung enthalten Abfrageparameter, die die Interaktion mit der Anzeige mit Prämie beschreiben. Parameternamen, Beschreibungen und Beispielwerte finden Sie unten. Die Parameter werden in alphabetischer Reihenfolge gesendet.
Parametername | Beschreibung | Beispielwert |
---|---|---|
ad_network | Anzeigenquellen-ID der Anzeigenquelle, über die diese Anzeige ausgeliefert wurde. Die Namen der Anzeigenquellen, die den ID-Werten entsprechen, sind im Abschnitt Anzeigenquellen-IDs 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 die App keinen benutzerdefinierten Datenstring bereitstellt, ist dieser Suchparameterwert nicht im SSV-Callback enthalten. |
SAMPLE_CUSTOM_DATA_STRING |
key_id | Schlüssel zur Bestätigung des SSV-Callbacks. Dieser Wert wird einem öffentlichen Schlüssel zugeordnet, der vom AdMob-Schlüsselserver bereitgestellt wird. | 1234567890 |
reward_amount | Prämienbetrag gemäß den Anzeigenblockeinstellungen. | 5 |
reward_item | Prämienartikel, wie in den Anzeigenblockeinstellungen angegeben. | Münzen |
Signatur | Von AdMob generierte Signatur für den SSV-Callback. | MEUCIQCLJS_s4ia_sN06HqzeW7Wc3nhZi4RlW3qV0oO-6AIYdQIgGJEh-rzKreO-paNDbSCzWGMtmgJHYYW9k2_icM9LFMY |
timestamp | Zeitstempel für die Prämie in Epoch-Zeit in Millisekunden. | 1507770365237823 |
transaction_id | Eindeutige hexadezimal codierte Kennung für jedes von AdMob generierte Ereignis vom Typ „Belohnung gewähren“. | 18fa792de1bca816048293fc71035638 |
user_id | Nutzer-ID, wie von userIdentifier angegeben.
Wenn die App keine Nutzer-ID angibt, ist dieser Abfrageparameter nicht im SSV-Callback enthalten. |
1234567 |
Anzeigenquellen-IDs
Namen und IDs der Anzeigenquellen
Name der Anzeigenquelle | Anzeigenquellen-ID |
---|---|
Aarki (Gebote) | 5240798063227064260 |
Anzeigenerstellung (Gebote) | 1477265452970951479 |
AdColony | 15586990674969969776 |
AdColony (ohne SDK) (Gebote) | 4600416542059544716 |
AdColony (Gebote) | 6895345910719072481 |
AdFalcon | 3528208921554210682 |
AdMob-Werbenetzwerk | 5450213213286189855 |
Vermittlungsabfolge im AdMob-Werbenetzwerk | 1215381445328257950 |
ADResult | 10593873382626181482 |
AMoAd | 17253994435944008978 |
AppLovin | 1063618907739174004 |
Applovin (Gebotsfunktion) | 1328079684332308356 |
Chartboost | 2873236629771172317 |
Chocolate Platform (Gebote) | 6432849193975106527 |
CrossChannel (MdotM) | 9372067028804390441 |
Benutzerdefiniertes Ereignis | 18351550913290782395 |
DT Exchange* * Bis zum 21. September 2022 hieß dieses Netzwerk „Fyber Marketplace“. | 2179455223494392917 |
EMX (Gebote) | 8497809869790333482 |
Fluct (Gebote) | 8419777862490735710 |
Flurry | 3376427960656545613 |
Fyber* * Diese Anzeigenquelle wird für Verlaufsberichte verwendet. | 4839637394546996422 |
i-mobile | 5208827440166355534 |
Improve Digital (Gebote) | 159382223051638006 |
Index Exchange (Gebote) | 4100650709078789802 |
InMobi | 7681903010231960328 |
InMobi (Gebote) | 6325663098072678541 |
InMobi Exchange (Gebote) | 5264320421916134407 |
IronSource | 6925240245545091930 |
ironSource Ads (Gebote) | 1643326773739866623 |
Leadbolt | 2899150749497968595 |
LG U+AD | 18298738678491729107 |
LINE Ads Network | 3025503711505004547 |
maio | 7505118203095108657 |
maio (Gebote) | 1343336733822567166 |
Media.net (Gebote) | 2127936450554446159 |
Vermittelte hausinterne Anzeigen | 6060308706800320801 |
Meta Audience Network* * Bis zum 6. Juni 2022 hieß dieses Netzwerk „Facebook Audience Network“. | 10568273599589928883 |
Meta Audience Network (Gebote) * Bis zum 6. Juni 2022 hieß dieses Netzwerk „Facebook Audience Network (Gebote)“. | 11198165126854996598 |
Mintegral | 1357746574408896200 |
Mintegral (Gebote) | 6250601289653372374 |
MobFox | 8079529624516381459 |
MobFox (Gebote) | 3086513548163922365 |
MoPub (eingestellt) | 10872986198578383917 |
myTarget | 8450873672465271579 |
Nend | 9383070032774777750 |
Nexxen (Gebote)* * Bis zum 1. Mai 2024 hieß dieses Netzwerk „UnrulyX“. | 2831998725945605450 |
ONE by AOL (Millennial Media) | 6101072188699264581 |
ONE by AOL (Nexage) | 3224789793037044399 |
OneTag Exchange (Gebote) | 4873891452523427499 |
OpenX (Gebote) | 4918705482605678398 |
Pangle | 4069896914521993236 |
Pangle (Gebote) | 3525379893916449117 |
PubMatic (Gebote) | 3841544486172445473 |
Reservierungskampagne | 7068401028668408324 |
RhythmOne (Gebote) | 2831998725945605450 |
Rubicon (Gebote) | 3993193775968767067 |
SK planet | 734341340207269415 |
Sharethrough (Bidding) | 5247944089976324188 |
Smaato (Gebote) | 3362360112145450544 |
Equativ (Gebote)* * Bis zum 12. Januar 2023 hieß dieses Netzwerk „Smart Adserver“. | 5970199210771591442 |
Sonobi (Gebote) | 3270984106996027150 |
Tapjoy | 7295217276740746030 |
Tapjoy (Gebote) | 4692500501762622178 |
Tencent GDT | 7007906637038700218 |
TripleLift (Gebote) | 8332676245392738510 |
Unity Ads | 4970775877303683148 |
Unity Ads (Gebote) | 7069338991535737586 |
Verizon Media | 7360851262951344112 |
Verve Group (Gebote) | 5013176581647059185 |
Vpon | 1940957084538325905 |
Liftoff Monetize* * Bis zum 30. Januar 2023 hieß dieses Netzwerk „Vungle“. | 1953547073528090325 |
Liftoff Monetize (Gebote)* * Bis zum 30. Januar 2023 hieß dieses Netzwerk „Vungle (Gebote)“. | 4692500501762622185 |
Yieldmo (Gebote) | 4193081836471107579 |
YieldOne (Gebote) | 3154533971590234104 |
Zucks | 5506531810221735863 |
Nutzer belohnen
Bei der Entscheidung, wann ein Nutzer belohnt werden soll, ist es wichtig, die Nutzerfreundlichkeit und die Validierung von Prämien in Einklang zu bringen. Bei serverseitigen Callbacks kann es zu Verzögerungen kommen, bevor externe Systeme erreicht werden. Daher empfehlen wir, den clientseitigen Callback zu verwenden, um dem Nutzer sofort eine Prämie zu gewähren, und alle Prämien nach Erhalt der serverseitigen Callbacks zu validieren. 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 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 am besten, auf den bestätigten serverseitigen Rückruf zu warten.
Benutzerdefinierte Daten
Für Apps, die in Callbacks für die serverseitige Überprüfung zusätzliche Daten benötigen, sollte die Funktion für benutzerdefinierte Daten von Anzeigen mit Prämie verwendet werden. Alle Stringwerte, die für ein Objekt mit Anzeigen 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 Abfrageparameters custom_data
nicht im SSV-Callback enthalten.
Im folgenden Beispiel werden die SSV-Optionen festgelegt, nachdem die Anzeige mit Prämie geladen wurde:
Swift
GADRewardedAd.load(withAdUnitID:"AD_UNIT_ID", request: request, completionHandler: { [self] ad, error in if let error != error { rewardedAd = ad let options = GADServerSideVerificationOptions() 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 von Anzeigen mit Prämie mit SSV
Im Folgenden werden die Schritte beschrieben, die die RewardedAdsVerifier
-Klasse ausführt, um eine SSV mit Prämie zu bestätigen. Die enthaltenen Code-Snippets sind zwar in Java und nutzen die Drittanbieterbibliothek Tink, diese Schritte können jedoch in der Sprache Ihrer Wahl mit einer beliebigen Drittanbieterbibliothek implementiert werden, die ECDSA unterstützt.
Öffentliche Schlüssel abrufen
Zur Bestätigung eines SSV-Callbacks für Anzeigen mit Prämie benötigen Sie einen öffentlichen Schlüssel von AdMob.
Eine Liste der öffentlichen Schlüssel, die zum Validieren 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 ähnlichen 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=="
},
],
}
Um die öffentlichen Schlüssel abzurufen, stellen Sie eine Verbindung zum AdMob-Schlüsselserver her und laden Sie die Schlüssel herunter. 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 werden per E-Mail über eine bevorstehende Rotation informiert. Wenn Sie öffentliche Schlüssel im Cache speichern, sollten Sie diese nach Erhalt dieser E-Mail aktualisieren.
Nachdem die öffentlichen Schlüssel abgerufen wurden, müssen sie geparst werden. Die folgende parsePublicKeysJson
-Methode nimmt einen JSON-String wie im Beispiel oben 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 Abfrageparameter von SSV-Callbacks mit Prämie sind immer signature
und key_id,
in dieser Reihenfolge. Mit den verbleibenden Abfrageparametern wird der zu überprüfende Inhalt angegeben. 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 mit Prämie, bei dem der zu verifizierende 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 verifizierende Inhalt aus einer Rückruf-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
Parse mit dem Wert queryString
aus dem vorherigen Schritt die Abfrageparameter signature
und key_id
aus der Callback-URL, wie unten dargestellt:
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. Verwende die Zuordnung, die von der Methode parsePublicKeysJson
zurückgegeben wird, und den Parameter key_id
aus der Rückruf-URL, um den öffentlichen Schlüssel aus dieser Zuordnung abzurufen. Verifizieren Sie dann die Signatur mit diesem öffentlichen Schlüssel. Diese Schritte werden unten in der verify
-Methode 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 ausgeführt wird, ohne dass eine Ausnahme ausgelöst 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 zur Validierung von SSV-Callbacks zu reduzieren. Öffentliche Schlüssel werden jedoch regelmäßig rotiert und sollten nicht länger als 24 Stunden im Cache gespeichert werden.
- Wie oft werden die vom AdMob-Schlüsselserver bereitgestellten öffentlichen Schlüssel rotiert?
- Die vom AdMob-Schlüsselserver bereitgestellten öffentlichen Schlüssel werden in einem variablen Zeitplan rotiert. Damit die Überprüfung 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 einen Antwortcode mit dem Status
HTTP 200 OK
. Wenn Ihr Server nicht erreichbar ist oder nicht die erwartete Antwort liefert, versucht Google bis zu fünfmal, SSV-Callbacks im Abstand von einer Sekunde zu senden. - Wie kann ich überprüfen, ob SSV-Callbacks von Google stammen?
- Verwenden Sie den umgekehrten DNS-Lookup, um zu prüfen, ob SSV-Callbacks von Google stammen.