Callbacks zur serverseitigen Überprüfung sind URL-Anfragen, deren Suchparameter von Google erweitert werden. Sie werden von Google an ein externes System gesendet, 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. Callbacks für die serverseitige Überprüfung (SSV) für Anzeigen mit Prämie bieten zusätzlichen Schutz vor dem Spoofing von clientseitigen Callbacks, mit denen Nutzer belohnt werden.
In diesem Leitfaden wird beschrieben, wie Sie SSV-Callbacks für Prämien mithilfe der Tink Java Apps-Kryptografiebibliothek von Drittanbietern überprüfen, um sicherzustellen, dass die Abfrageparameter im Callback gültige Werte sind. Obwohl Tink in dieser Anleitung verwendet wird, können Sie auch eine beliebige 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 Bestätigung von Prämien für Ihren Anzeigenblock.
RewardedAdsVerifier aus der Tink Java Apps-Bibliothek verwenden
Das GitHub-Repository Tink Java Apps enthält die Hilfsklasse RewardedAdsVerifier
, mit der der Code reduziert wird, der zum Überprüfen eines SSV-Rückrufs für Prämien 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 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 zum Überprüfen von SSV-Callbacks für Anzeigen mit Prämie ausgeführt werden, finden Sie im Abschnitt Manuelle Überprüfung von SSV für Anzeigen mit Prämie.
SSV-Callback-Parameter
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. Parameter werden in alphabetischer Reihenfolge gesendet.
Parametername | Beschreibung | Beispielwert |
---|---|---|
ad_network | Anzeigenquellen-ID für die Anzeigenquelle, über die diese Anzeige bereitgestellt wurde. Namen von Anzeigenquellen, die 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
ServerSideVerificationOptions::custom_data bereitgestellt.
Wenn von der App kein benutzerdefinierter Datenstring bereitgestellt wird, ist dieser Abfrageparameterwert nicht im SSV-Callback enthalten. |
SAMPLE_CUSTOM_DATA_STRING |
key_id | Schlüssel zur Überprüfung des SSV-Rückrufs. Dieser Wert entspricht einem öffentlichen Schlüssel, 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. | Münzen |
Signatur | Signatur für den SSV-Callback, der von AdMob generiert wird. | MEUCIQCLJS_s4ia_sN06HqzeW7Wc3nhZi4RlW3qV0oO-6AIYdQIgGJEh-rzKreO-paNDbSCzWGMtmgJHYYW9k2_icM9LFMY |
timestamp | Zeitstempel für den Zeitpunkt, zu dem der Nutzer belohnt wurde, als Epochenzeit in Millisekunden. | 1507770365237823 |
transaction_id | Eindeutige hexadezimale Kennung für jedes Ereignis zur Gewährung von Prämien, das von AdMob generiert wird. | 18fa792de1bca816048293fc71035638 |
user_id | Nutzer-ID, die von ServerSideVerificationOptions::user_id bereitgestellt wird.
Wenn von der App keine Nutzer-ID angegeben wird, ist dieser Abfrageparameter nicht im SSV-Callback vorhanden. |
1234567 |
Anzeigenquellen-IDs
Namen und IDs von Anzeigenquellen
Name der Anzeigenquelle | ID der Anzeigenquelle |
---|---|
Anzeigenerstellung (Gebote) | 1477265452970951479 |
AdColony | 15586990674969969776 |
AdColony (Gebote) | 6895345910719072481 |
AdFalcon | 3528208921554210682 |
AdMob-Werbenetzwerk | 5450213213286189855 |
Vermittlungsabfolge im AdMob-Werbenetzwerk | 1215381445328257950 |
AppLovin | 1063618907739174004 |
AppLovin (Bidding) | 1328079684332308356 |
Chartboost | 2873236629771172317 |
Chocolate Platform (Gebote) | 6432849193975106527 |
Benutzerdefiniertes Ereignis | 18351550913290782395 |
DT Exchange* * Vor dem 21. September 2022 hieß dieses Netzwerk „Fyber Marketplace“. | 2179455223494392917 |
Equativ (Gebote)* * Vor dem 12. Januar 2023 hieß dieses Netzwerk „Smart Adserver“. | 5970199210771591442 |
Fluct (Gebote) | 8419777862490735710 |
Flurry | 3376427960656545613 |
Fyber* * Diese Anzeigenquelle wird für die Berichterstellung verwendet. | 4839637394546996422 |
i-mobile | 5208827440166355534 |
Improve Digital (Gebote) | 159382223051638006 |
Index Exchange (Gebote) | 4100650709078789802 |
InMobi | 7681903010231960328 |
InMobi (Bidding) | 6325663098072678541 |
InMobi Exchange (Gebote) | 5264320421916134407 |
IronSource | 6925240245545091930 |
ironSource Ads (Gebote) | 1643326773739866623 |
Leadbolt | 2899150749497968595 |
Liftoff Monetize* * Vor dem 30. Januar 2023 hieß dieses Netzwerk „Vungle“. | 1953547073528090325 |
Liftoff Monetize (Gebote)* * Vor dem 30. Januar 2023 hieß dieses Netzwerk „Vungle (Bidding)“. | 4692500501762622185 |
LG U+AD | 18298738678491729107 |
LINE Ads Network | 3025503711505004547 |
Magnite DV+ (Gebote) | 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 (Gebote)* * Vor dem 6. Juni 2022 hieß dieses Netzwerk „Facebook Audience Network (Gebote)“. | 11198165126854996598 |
Mintegral | 1357746574408896200 |
Mintegral (Bidding) | 6250601289653372374 |
MobFox (Bidding) | 3086513548163922365 |
MoPub (eingestellt) | 10872986198578383917 |
myTarget | 8450873672465271579 |
Nend | 9383070032774777750 |
Nexxen (Gebote)* * Vor dem 1. Mai 2024 hieß dieses Netzwerk „UnrulyX“. | 2831998725945605450 |
OneTag Exchange (Gebote) | 4873891452523427499 |
OpenX (Bidding) | 4918705482605678398 |
Pangle | 4069896914521993236 |
Pangle (Bidding) | 3525379893916449117 |
PubMatic (Gebote) | 3841544486172445473 |
Reservierungskampagne | 7068401028668408324 |
SK planet | 734341340207269415 |
Sharethrough (Bidding) | 5247944089976324188 |
Smaato (Bidding) | 3362360112145450544 |
Sonobi (Bidding) | 3270984106996027150 |
Tapjoy | 7295217276740746030 |
Tapjoy (Bidding) | 4692500501762622178 |
Tencent GDT | 7007906637038700218 |
TripleLift (Gebote) | 8332676245392738510 |
Unity Ads | 4970775877303683148 |
Unity Ads (Gebote) | 7069338991535737586 |
Verve Group (Gebote) | 5013176581647059185 |
Vpon | 1940957084538325905 |
Yieldmo (Bidding) | 4193081836471107579 |
YieldOne (Bidding) | 3154533971590234104 |
Zucks | 5506531810221735863 |
Nutzer belohnen
Bei der Entscheidung, wann ein Nutzer belohnt werden soll, ist es wichtig, ein Gleichgewicht zwischen Nutzerfreundlichkeit und der Validierung von Prämien 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 serverseitiger Callbacks zu validieren. Dieser Ansatz bietet eine gute Nutzererfahrung und gewährleistet gleichzeitig die Gültigkeit der gewährten Prämien.
Bei Anwendungen, bei denen die Gültigkeit von Belohnungen entscheidend ist (z. B. wenn die Belohnung sich auf die In-Game-Wirtschaft Ihrer App auswirkt) und Verzögerungen bei der Gewährung von Belohnungen akzeptabel sind, ist es möglicherweise am besten, auf den bestätigten serverseitigen Callback zu warten.
Benutzerdefinierte Daten
Apps, für die zusätzliche Daten in serverseitigen Überprüfungs-Callbacks erforderlich sind, sollten die Funktion für benutzerdefinierte Daten von Anzeigen mit Prämie verwenden. Alle Stringwerte, die für ein Objekt für 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 custom_data
-Abfrageparameters nicht im SSV-Callback enthalten.
Im folgenden Codebeispiel wird gezeigt, wie Sie benutzerdefinierte Daten für ein Objekt für eine Prämie festlegen, bevor Sie eine Anzeige anfordern.
firebase::gma::RewardedAd* rewarded_ad; rewarded_ad = new firebase::gma::RewardedAd(); firebase::gma::RewardedAd::ServerSideVerificationOptions options; options.custom_data = "SAMPLE_CUSTOM_DATA_STRING"; rewarded_ad->SetServerSideVerificationOptions(options);
Wenn Sie den benutzerdefinierten Prämienstring festlegen möchten, müssen Sie das tun, bevor die Anzeige ausgeliefert wird.
Manuelle Überprüfung von SSV-Prämien
Die Schritte, die von der Klasse RewardedAdsVerifier
ausgeführt werden, um eine SSV mit Prämie zu bestätigen, sind unten aufgeführt. Die enthaltenen Code-Snippets sind zwar in Java geschrieben und nutzen die Tink-Drittanbieterbibliothek, aber Sie können diese Schritte in der Sprache Ihrer Wahl implementieren und dabei eine beliebige Drittanbieterbibliothek verwenden, die ECDSA unterstützt.
Öffentliche Schlüssel abrufen
Um einen SSV-Callback für Prämien zu überprüfen, benötigen Sie einen öffentlichen Schlüssel von AdMob.
Eine Liste der öffentlichen Schlüssel, die zum Validieren der SSV-Callbacks für Prämien verwendet werden, kann vom AdMob-Schlüsselserver abgerufen werden. Die Liste der öffentlichen Schlüssel wird als JSON-Darstellung mit einem Format ähnlich 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=="
},
],
}
Stellen Sie eine Verbindung zum AdMob-Schlüsselserver her und laden Sie die Schlüssel herunter, um die öffentlichen Schlüssel abzurufen. 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, in der Sie über eine bevorstehende Rotation informiert werden. 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 parsePublicKeysJson
-Methode unten verwendet einen JSON-String, z. B. das 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;
}
Zu überprüfende Inhalte erhalten
Die letzten beiden Abfrageparameter von SSV-Callbacks für Prämien 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 Snippet unten zeigt ein Beispiel für einen SSV-Callback für Belohnungen. Der zu überprüfende Inhalt ist hervorgehoben.
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 bestätigende 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 queryString
-Wert 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 müssen Sie den Inhalt der Callback-URL mit dem entsprechenden öffentlichen Schlüssel bestätigen. Nehmen Sie die von der Methode parsePublicKeysJson
zurückgegebene Zuordnung und verwenden Sie den Parameter key_id
aus der Callback-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 ohne 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. Ö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 unregelmäßigen Abständen 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 OK
für den Erfolgsstatus. Wenn Ihr Server nicht erreicht werden kann 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?
- Mit dem umgekehrten DNS-Lookup können Sie überprüfen, ob SSV-Callbacks von Google stammen.