Bei serverseitigen Callbacks für die Überprüfung handelt es sich um URL-Anfragen mit von Google erweiterten Suchparametern, die von Google an ein externes System gesendet werden, um darüber zu informieren, dass Nutzer für die Interaktion mit einer Interstitial-Anzeige mit Prämie oder Anzeigen mit Prämie eine Prämie erhalten sollen. Callbacks für die serverseitige Überprüfung von Anzeigen mit Prämie bieten einen zusätzlichen Schutz vor Spoofing clientseitiger Callbacks, um Nutzer zu belohnen.
In diesem Leitfaden erfahren Sie, wie Sie SSV-Callbacks mit Prämie mithilfe der kryptografischen Bibliothek eines Drittanbieters mit Tink Java Apps verifizieren, damit die Abfrageparameter im Callback legitime Werte sind. Obwohl Tink für die Zwecke dieser Anleitung verwendet wird, können Sie jede Drittanbieterbibliothek verwenden, die ECDSA unterstützt. Sie können Ihren Server auch mit dem Testtool in der AdMob-Benutzeroberfläche testen.
Dieses voll funktionsfähige Beispiel, in dem Java-Springboot verwendet wird
Voraussetzungen
Sie können Anzeigen mit Prämie mitVersion 11.6.0 oder höher des Google Mobile Ads SDK in Ihre mobile App einbinden.
Aktivieren Sie für Ihren Anzeigenblock die serverseitige Überprüfung mit Prämie.
RewardAdsVerifier aus der Tink Java Apps-Bibliothek verwenden
Das GitHub-Repository für Tink-Java-Apps enthält eine RewardedAdsVerifier
-Hilfsklasse, mit der sich der Code für die Prüfung eines SSV-Callbacks mit Prämie reduzieren lässt.
Mithilfe dieser Klasse können Sie eine Rückruf-URL mit dem folgenden Code verifizieren.
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 sind Best Practices dazu aufgeführt, wann Nutzer eine Prämie erhalten sollten. Eine Aufschlüsselung der Schritte, die von dieser Klasse ausgeführt werden, um SSV-Callbacks mit Prämie zu überprüfen, finden Sie im Abschnitt Manuelle Überprüfung von SSV-Callbacks mit Prämie.
Callback-Parameter für SSV
Callbacks für die serverseitige Überprüfung enthalten Abfrageparameter, die die Interaktion mit Anzeigen mit Prämie beschreiben. Parameternamen, Beschreibungen und Beispielwerte sind unten aufgeführt. Parameter werden in alphabetischer Reihenfolge gesendet.
Parametername | Beschreibung | Beispielwert |
---|---|---|
ad_network | Die ID der Anzeigenquelle der Anzeigenquelle, über die diese Anzeige ausgeliefert wurde. Die Namen von Anzeigenquellen, die den ID-Werten entsprechen, sind im Abschnitt Kennungen der Anzeigenquelle aufgeführt. | 1953547073528090325 |
ad_unit | Die ID des AdMob-Anzeigenblocks, über den die Anzeige mit Prämie angefordert wurde. | 2747237135 |
custom_data | Benutzerdefinierter Datenstring wie bereitgestellt von
setCustomData
.
Wenn von der Anwendung kein benutzerdefinierter Datenstring bereitgestellt wird, ist dieser Abfrageparameterwert nicht im SSV-Callback vorhanden. |
SAMPLE_CUSTOM_DATA_STRING |
key_id | Schlüssel, der zur Bestätigung des Rückrufs der SSV verwendet werden soll. Dieser Wert ist 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 gemäß den Angaben in den Anzeigenblockeinstellungen. | Münzen |
Signatur | Signatur für SSV-Rückruf, der von AdMob generiert wird. | MEUCIQCLJS_s4ia_sN06HqzeW7Wc3nhZi4RlW3qV0oO-6AIYdQIgGJEh-rzKreO-paNDbSCzWGMtmgJHYYW9k2_icM9LFMY |
timestamp | Zeitstempel in ms, der angibt, wann der Nutzer eine Prämie erhalten hat. | 1507770365237823 |
transaction_id | Eindeutige hex-codierte Kennung für jedes von AdMob generierte Prämien-Grant-Ereignis. | 18fa792de1bca816048293fc71035638 |
user_id | Nutzer-ID von
setUserId .
Wenn von der Anwendung keine Nutzerkennung bereitgestellt wird, ist dieser Abfrageparameter nicht im SSV-Callback vorhanden. |
1234567 |
Anzeigenquellen-IDs
Namen und IDs der Anzeigenquellen
Name der Anzeigenquelle | Anzeigenquelle-ID |
---|---|
Aarki (Bidding) | 5240798063227064260 |
Anzeigengenerierung (Bidding) | 1477265452970951479 |
AdColony | 15586990674969969776 |
AdColony (kein SDK) (Bidding) | 4600416542059544716 |
AdColony (Bidding) | 6895345910719072481 |
AdFalcon | 3528208921554210682 |
AdMob-Werbenetzwerk | 5450213213286189855 |
ADResult | 10593873382626181482 |
AMoAd | 17253994435944008978 |
Applovin | 1063618907739174004 |
Applovin (Bidding) | 1328079684332308356 |
Chartboost | 2873236629771172317 |
Plattform für Schokolade (Bidding) | 6432849193975106527 |
Kanalübergreifend (MdotM) | 9372067028804390441 |
Benutzerdefiniertes Ereignis | 18351550913290782395 |
DT Exchange* * Vor dem 21. September 2022 hieß dieses Netzwerk „Fyber Marketplace“. | 2179455223494392917 |
EMX (Bidding) | 8497809869790333482 |
Schwankungen (Gebote) | 8419777862490735710 |
Schneegestöber | 3376427960656545613 |
Fyber* * Diese Anzeigenquelle wird für bisherige Berichte verwendet. | 4839637394546996422 |
i-mobile | 5208827440166355534 |
Digitale Werbung optimieren (Gebote) | 159382223051638006 |
Index Exchange (Bidding) | 4100650709078789802 |
InMobi | 7681903010231960328 |
InMobi (Bidding) | 6325663098072678541 |
IronSource | 6925240245545091930 |
ironSource Ads (Bidding) | 1643326773739866623 |
Leadbolt | 2899150749497968595 |
LG U+AD | 18298738678491729107 |
LINE-Werbenetzwerk | 3025503711505004547 |
maio | 7505118203095108657 |
Mai (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 | 8079529624516381459 |
MobFox (Bidding) | 3086513548163922365 |
MoPub (eingestellt) | 10872986198578383917 |
myTarget | 8450873672465271579 |
Nend | 9383070032774777750 |
Nexxen (Bidding)* * Vor dem 1. Mai 2024 hieß dieses Netzwerk „UnrulyX“. | 2831998725945605450 |
ONE by AOL (Millennial Media) | 6101072188699264581 |
ONE by AOL (Nexage) | 3224789793037044399 |
OneTag-Anzeigenplattform (Bidding) | 4873891452523427499 |
OpenX (Bidding) | 4918705482605678398 |
Pangle (Bidding) | 3525379893916449117 |
PubMatic (Bidding) | 3841544486172445473 |
Reservierungskampagne | 7068401028668408324 |
RhythmOne (Gebote) | 2831998725945605450 |
Rubicon (Bidding) | 3993193775968767067 |
SK Planet | 734341340207269415 |
Sharethrough (Bidding) | 5247944089976324188 |
Smaato (Bidding) | 3362360112145450544 |
Equativ (Gebote)* * Vor dem 12. Januar 2023 hieß dieses Netzwerk „Smart Adserver“. | 5970199210771591442 |
Sonobi (Bidding) | 3270984106996027150 |
Tapjoy | 7295217276740746030 |
TapJoy (Bidding) | 4692500501762622178 |
Tencent GDT | 7007906637038700218 |
TripleLift (Gebote) | 8332676245392738510 |
Unity-Anzeigen | 4970775877303683148 |
Unity Ads (Bidding) | 7069338991535737586 |
Logo: Verizon Media | 7360851262951344112 |
Verve-Gruppe (Bidding) | 5013176581647059185 |
Vpon | 1940957084538325905 |
Liftoff – Monetarisieren* * Vor dem 30. Januar 2023 hieß dieses Netzwerk „Vungle“. | 1953547073528090325 |
Liftoff Monetarisieren (Bidding)* * Vor dem 30. Januar 2023 hieß dieses Netzwerk „Vungle (Bidding)“. | 4692500501762622185 |
Yieldmo (Bidding) | 4193081836471107579 |
YieldOne (Gebote) | 3154533971590234104 |
Zecken | 5506531810221735863 |
Belohnen der Nutzenden
Bei der Entscheidung, wann ein Nutzer belohnt wird, ist es wichtig, ein ausgewogenes Verhältnis zwischen Nutzererfahrung und Validierung der Belohnung zu haben. Bei serverseitigen Callbacks kann es zu Verzögerungen kommen, bevor externe Systeme erreicht werden. Daher wird empfohlen, den clientseitigen Callback zu verwenden, um den Nutzer sofort zu belohnen, während bei serverseitigen Callbacks alle Prämien geprüft werden. Dieser Ansatz sorgt für eine gute Nutzerfreundlichkeit und sorgt gleichzeitig dafür, dass die gewährten Prämien gültig bleiben.
Bei Anwendungen, bei denen die Gültigkeit der Prämie jedoch von entscheidender Bedeutung ist (z. B. die Prämie wirkt sich auf die In-Game-Ökonomie Ihrer App aus) und bei denen Verzögerungen bei der Vergabe von Prämien akzeptabel sind, ist es am besten, auf den verifizierten serverseitigen Callback zu warten.
Benutzerdefinierte Daten
Apps, die zusätzliche Daten in serverseitigen Bestätigungs-Callbacks erfordern, sollten die Funktion für benutzerdefinierte Daten von Anzeigen mit Prämie verwenden. Jeder Stringwert, der für ein Objekt für Anzeigen mit Prämie festgelegt wurde, wird 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 Codebeispiel wird gezeigt, wie die Optionen für die serverseitige Überprüfung festgelegt werden, nachdem die Anzeige mit Prämie geladen wurde.
Java
RewardedAd.load(MainActivity.this, "ca-app-pub-3940256099942544/5354046379", 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, "ca-app-pub-3940256099942544/5354046379", 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 die Anzeige ausgeliefert wird.
Manuelle Überprüfung der SSV mit Prämie
Im Folgenden sind die Schritte aufgeführt, die von der Klasse RewardedAdsVerifier
ausgeführt werden, um eine SSV mit Prämie zu prüfen. Obwohl die enthaltenen Code-Snippets in Java geschrieben sind und die Tink-Bibliothek des Drittanbieters nutzen, können diese Schritte von Ihnen in der Sprache Ihrer Wahl implementiert werden. Verwenden Sie dazu eine beliebige Drittanbieterbibliothek, die ECDSA unterstützt.
Öffentliche Schlüssel abrufen
Wenn Sie einen SSV-Callback mit Prämie bestätigen möchten, benötigen Sie einen von AdMob bereitgestellten öffentlichen Schlüssel.
Auf dem AdMob-Schlüsselserver finden Sie eine Liste der öffentlichen Schlüssel, mit denen die SSV-Callbacks mit Prämie validiert werden können. Die Liste der öffentlichen Schlüssel wird als JSON-Darstellung in 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=="
},
],
}
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 Variable 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();
}
Beachten Sie, dass öffentliche Schlüssel regelmäßig rotiert werden. Sie werden per E-Mail über eine bevorstehende Rotation informiert. Wenn Sie öffentliche Schlüssel im Cache speichern, sollten Sie die Schlüssel nach Erhalt dieser E-Mail aktualisieren.
Sobald 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;
}
Inhalte überprüfen lassen
Die letzten beiden Abfrageparameter von SSV-Callbacks mit Prämie sind immer signature
und key_id,
in dieser Reihenfolge. Die verbleibenden Abfrageparameter geben den zu überprüfenden Inhalt an. Angenommen, Sie haben AdMob so konfiguriert, dass Callbacks für Prämien 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 bestätigende Inhalt hervorgehoben wird.
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 von 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 von Callback-URL abrufen
Verwenden Sie den Wert queryString
aus dem vorherigen Schritt, um die Abfrageparameter signature
und key_id
aus der Callback-URL wie unten gezeigt zu parsen:
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
der Callback-URL, um den öffentlichen Schlüssel aus dieser Zuordnung zu erhalten. Überprüfen Sie dann die Signatur mit diesem öffentlichen Schlüssel. Diese Schritte werden unten in der Methode verify
beschrieben.
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 verifiziert.
Häufig gestellte Fragen
- Kann ich den vom AdMob-Schlüsselserver bereitgestellten öffentlichen Schlüssel im Cache speichern?
- Wir empfehlen, den vom AdMob-Schlüsselbund bereitgestellten öffentlichen Schlüssel im Cache zu speichern, um die Anzahl der Vorgänge zum Validieren von SSV-Callbacks zu reduzieren. 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?
- Öffentliche Schlüssel, die vom AdMob-Schlüsselserver bereitgestellt werden, werden nach einem variablen Zeitplan rotiert. Damit die Überprüfung von SSV-Callbacks weiterhin wie gewünscht 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 für den Erfolgsstatus
HTTP 200 OK
. Wenn Ihr Server nicht erreichbar ist oder nicht die erwartete Antwort zurückgibt, versucht Google noch einmal, SSV-Rückrufe bis zu fünfmal in 1-Sekunden-Intervallen zu senden. - Wie kann ich überprüfen, ob SSV-Rückrufe von Google stammen?
- Mit dem umgekehrten DNS-Lookup können Sie prüfen, ob SSV-Callbacks von Google stammen.