Callbacks für serverseitige Überprüfungen validieren

Callbacks für die serverseitige Überprüfung sind URL-Anfragen mit Suchparametern die von Google an ein externes System gesendet werden, darüber informieren, dass ein Nutzer für die Interaktion mit einer Interstitial-Anzeige mit Prämie. Callbacks für die serverseitige Überprüfung von Anzeigen mit Prämie bieten zusätzlichen Schutz vor Spoofing clientseitiger Callbacks. um Nutzer zu belohnen.

In diesem Leitfaden erfahren Sie, wie Sie Callbacks für die serverseitige Überprüfung von Anzeigen mit Prämie mithilfe der Methode Tink Java Apps (Drittanbieter) Kryptografiebibliothek verwenden, um sicherzustellen, dass die Abfrageparameter im Callback korrekt sind. und legitime Werte. Obwohl Tink für die Zwecke dieses Leitfadens verwendet wird, können Sie Sie können eine beliebige Bibliothek von Drittanbietern verwenden, die ECDSA: Sie können Ihren Server auch mit der Testfunktion auf der AdMob-Benutzeroberfläche.

Sehen Sie sich diese voll funktionsfähige Beispiel mit dem Java-Spring-Boot.

Vorbereitung

„RewardAdsVerifier“ aus der Bibliothek für Tink-Java-Apps verwenden

GitHub-Repository für Tink Java Apps enthält ein RewardedAdsVerifier Hilfsklasse verwenden, um den Code zu reduzieren, der zur Bestätigung eines SSV-Rückrufs für Anzeigen mit Prämie erforderlich ist. Mit dieser Klasse können Sie eine Callback-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, Die URL wurde bestätigt. Die Option Belohnen für den Nutzer finden Sie Best Practices dazu, wann Nutzer Prämien erhalten sollten. Für eine Aufschlüsselung der Schritte, die in diesem Kurs ausgeführt wurden, um SSV-Rückrufe mit Prämie zu bestätigen Weitere Informationen zur manuellen Bestätigung SSV.

SSV-Callback-Parameter

Callbacks für die serverseitige Überprüfung enthalten Suchparameter, die die Interaktion mit einer Anzeige mit Prämie. Parameternamen, Beschreibungen und Beispielwerte (siehe unten). Parameter werden in alphabetischer Reihenfolge gesendet.

Parametername Beschreibung Beispielwert
ad_network Die Kennung der Anzeigenquelle, von der die Anzeige ausgeliefert wurde. Anzeigenquelle werden die Namen, die ID-Werten entsprechen, in der Spalte Ad Quellenkennzeichnungen. 1953547073528090325
ad_unit Die ID des AdMob-Anzeigenblocks, der für die Anfrage der Anzeige mit Prämie verwendet wurde. 2747237135
custom_data Benutzerdefinierter Datenstring wie bereitgestellt von <ph type="x-smartling-placeholder"></ph> setCustomData

Wenn von der App kein benutzerdefinierter Datenstring bereitgestellt wird, wird dieser Suchparameter ist im SSV-Callback nicht vorhanden.

SAMPLE_CUSTOM_DATA_STRING
key_id Schlüssel, der zur Überprüfung des SSV-Rückrufs verwendet wird. Dieser Wert ist einem öffentlichen Schlüssel zugeordnet die vom AdMob-Schlüsselserver bereitgestellt werden. 1234567890
reward_amount Prämienbetrag, der in den Einstellungen für den Anzeigenblock angegeben ist. 5
reward_item Prämienartikel entsprechend der Angabe in den Anzeigenblockeinstellungen. Münzen
Signatur Signatur für den SSV-Callback, der von AdMob generiert wurde. MEUCIQCLJS_s4ia_sN06HqzeW7Wc3nhZi4RlW3qV0oO-6AIYdQIgGJEh-rzKreO-paNDbSCzWGMtmgJHYYW9k2_icM9LFMY
timestamp Zeitstempel für den Zeitpunkt, zu dem der Nutzer eine Prämie erhalten hat, als Epochenzeit in ms. 1507770365237823
transaction_id Eindeutige hexadezimal-codierte Kennung für jedes von AdMob generierte Prämiengewährungsereignis. 18fa792de1bca816048293fc71035638
user_id Nutzer-ID wie bereitgestellt von setUserId

Wenn die App keine Nutzerkennung bereitstellt, wird dieser Suchparameter im SSV-Callback vorhanden sein müssen.

1234567

IDs der Anzeigenquellen

Namen und IDs von Anzeigenquellen

Ad source name Ad source ID
Aarki (bidding)5240798063227064260
Ad Generation (bidding)1477265452970951479
AdColony15586990674969969776
AdColony (non-SDK) (bidding)4600416542059544716
AdColony (bidding)6895345910719072481
AdFalcon3528208921554210682
AdMob Network5450213213286189855
AdMob Network Waterfall1215381445328257950
ADResult10593873382626181482
AMoAd17253994435944008978
Applovin1063618907739174004
Applovin (bidding)1328079684332308356
Chartboost2873236629771172317
Chocolate Platform (bidding)6432849193975106527
CrossChannel (MdotM)9372067028804390441
Custom Event18351550913290782395
DT Exchange*
* Prior to September 21, 2022, this network was called "Fyber Marketplace".
2179455223494392917
EMX (bidding)8497809869790333482
Fluct (bidding)8419777862490735710
Flurry3376427960656545613
Fyber*
* This ad source is used for historical reporting.
4839637394546996422
i-mobile5208827440166355534
Improve Digital (bidding)159382223051638006
Index Exchange (bidding)4100650709078789802
InMobi7681903010231960328
InMobi (bidding)6325663098072678541
InMobi Exchange (bidding)5264320421916134407
IronSource6925240245545091930
ironSource Ads (bidding)1643326773739866623
Leadbolt2899150749497968595
LG U+AD18298738678491729107
LINE Ads Network3025503711505004547
maio7505118203095108657
maio (bidding)1343336733822567166
Media.net (bidding)2127936450554446159
Mediated house ads6060308706800320801
Meta Audience Network*
* Prior to June 6, 2022, this network was called "Facebook Audience Network".
10568273599589928883
Meta Audience Network (bidding)*
* Prior to June 6, 2022, this network was called "Facebook Audience Network (bidding)".
11198165126854996598
Mintegral1357746574408896200
Mintegral (bidding)6250601289653372374
MobFox8079529624516381459
MobFox (bidding)3086513548163922365
MoPub (deprecated)10872986198578383917
myTarget8450873672465271579
Nend9383070032774777750
Nexxen (bidding)*

* Prior to May 1, 2024, this network was called "UnrulyX".

2831998725945605450
ONE by AOL (Millennial Media)6101072188699264581
ONE by AOL (Nexage)3224789793037044399
OneTag Exchange (bidding)4873891452523427499
OpenX (bidding)4918705482605678398
Pangle4069896914521993236
Pangle (bidding)3525379893916449117
PubMatic (bidding)3841544486172445473
Reservation campaign7068401028668408324
RhythmOne (bidding)2831998725945605450
Rubicon (bidding)3993193775968767067
SK planet734341340207269415
Sharethrough (bidding)5247944089976324188
Smaato (bidding)3362360112145450544
Equativ (bidding)*

* Prior to January 12, 2023, this network was called "Smart Adserver".

5970199210771591442
Sonobi (bidding)3270984106996027150
Tapjoy7295217276740746030
Tapjoy (bidding)4692500501762622178
Tencent GDT7007906637038700218
TripleLift (bidding)8332676245392738510
Unity Ads4970775877303683148
Unity Ads (bidding)7069338991535737586
Verizon Media7360851262951344112
Verve Group (bidding)5013176581647059185
Vpon1940957084538325905
Liftoff Monetize*

* Prior to January 30, 2023, this network was called "Vungle".

1953547073528090325
Liftoff Monetize (bidding)*

* Prior to January 30, 2023, this network was called "Vungle (bidding)".

4692500501762622185
Yieldmo (bidding)4193081836471107579
YieldOne (bidding)3154533971590234104
Zucks5506531810221735863

Nutzer belohnen

Es ist wichtig, bei der Entscheidung ein Gleichgewicht zwischen User Experience und Validierung der Prämie zu finden. wann Nutzende belohnen sollen. Bei serverseitigen Callbacks kann es vor dem externe Systeme zu erreichen. Daher empfiehlt es sich, den clientseitigen Callback, um den Nutzer sofort zu belohnen, während Überprüfung aller Prämien nach Erhalt von serverseitigen Callbacks. Dieses eine gute User Experience bietet und gleichzeitig die Gültigkeit der gewährten Prämien.

Bei Anwendungen, bei denen die Gültigkeit von Prämien entscheidend ist (z. B. hat Auswirkungen auf die In-Game-Ökonomie Ihrer App. Außerdem kann es zu Verzögerungen bei der Vergabe von Prämien kommen. akzeptabel ist, warten Sie am besten auf den verifizierten serverseitigen Rückruf. Ansatz.

Benutzerdefinierte Daten

Apps, die zusätzliche Daten in Callbacks zur serverseitigen Überprüfung benötigen, sollten Folgendes verwenden: die Funktion für benutzerdefinierte Daten von Anzeigen mit Prämie. Beliebiger Stringwert, der in einer Anzeige mit Prämie festgelegt ist wird an den custom_data-Abfrageparameter des SSV-Callbacks übergeben. Falls nein festgelegt ist, ist der Wert des Suchparameters custom_data nicht gleich im SSV-Callback vorhanden sind.

Im folgenden Codebeispiel wird gezeigt, wie die SSV-Optionen nach dem Anzeige mit Prämie wurde geladen.

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 vor der Anzeige tun der Anzeige.

Manuelle Bestätigung der SSV mit Prämie

Die Schritte, die von der Klasse „RewardedAdsVerifier“ ausgeführt werden, um eine Prämie zu bestätigen Die serverseitige Überprüfung wird im Folgenden beschrieben. Die enthaltenen Code-Snippets sind zwar in Java, die Tink-Drittanbieterbibliothek nutzen, können Sie diese Schritte in der Sprache Ihrer Wahl. Verwenden Sie dazu eine Drittanbieterbibliothek, die ECDSA:

Öffentliche Schlüssel abrufen

Zum Bestätigen eines Callbacks für eine SSV mit Prämie benötigen Sie einen von AdMob bereitgestellten öffentlichen Schlüssel.

Eine Liste mit öffentlichen Schlüsseln, mit denen die SSV-Callbacks mit Prämie validiert werden können aus dem AdMob-Schlüssel Server. 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 zum Abrufen der öffentlichen Schlüssel eine Verbindung zum AdMob-Schlüsselserver her und laden Sie den Schlüssel. Der folgende Code führt diese Aufgabe durch und speichert die JSON-Datei Darstellung der Schlüssel für die Variable 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();
}

Beachten Sie, dass öffentliche Schlüssel regelmäßig rotiert werden. Sie werden per E-Mail darüber informiert. eine bevorstehende Rotation. Wenn Sie öffentliche Schlüssel im Cache speichern, sollten Sie erhalten Sie nach Erhalt dieser E-Mail die Schlüssel.

Sobald die öffentlichen Schlüssel abgerufen wurden, müssen sie geparst werden. Die Für die Methode parsePublicKeysJson unten wird ein JSON-String wie im Beispiel verwendet 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 bestätigen lassen

Die letzten beiden Suchparameter von SSV-Callbacks mit Prämie sind immer signature und key_id, in dieser Reihenfolge. Die verbleibenden Suchparameter geben den Inhalt an, noch nicht bestätigt werden. Angenommen, Sie haben AdMob so konfiguriert, dass Rückrufe für Prämien https://www.myserver.com/mypath Das Snippet unten zeigt ein Beispiel für eine Anzeige mit Prämie SSV-Rückruf mit hervorgehobenem Inhalt

https://www.myserver.com/path?ad_network=54...55&ad_unit=12345678&reward_amount=10&reward_item=coins
&timestamp=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 einem -Callback-URL als UTF-8-Byte-Array.

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 Callback-URL abrufen

Mit dem Wert queryString aus dem vorherigen Schritt parsen Sie signature und key_id-Abfrageparameter 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()));

Überprüfung durchführen

Der letzte Schritt besteht darin, den Inhalt der Callback-URL mit der Methode entsprechenden öffentlichen Schlüssel. Nehmen Sie die Zuordnung, die vom parsePublicKeysJson-Methode und verwenden Sie den key_id-Parameter aus dem Callback. URL zum Abrufen des öffentlichen Schlüssels aus dieser Zuordnung. Bestätigen Sie dann die Signatur mit diesen ö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);
  }
}

Wird die Methode ohne Ausnahme ausgeführt, lautete die Callback-URL: wurde bestätigt.

FAQ

Kann ich den vom AdMob-Schlüsselserver bereitgestellten öffentlichen Schlüssel im Cache speichern?
Wir empfehlen, den vom AdMob-Schlüssel bereitgestellten öffentlichen Schlüssel im Cache zu speichern Server, um die Anzahl der Vorgänge zur Validierung der SSV-Datei zu reduzieren Callbacks angegeben werden. Beachten Sie jedoch, dass öffentliche Schlüssel regelmäßig rotiert werden und nicht länger als 24 Stunden im Cache gespeichert werden.
Wie oft werden die vom AdMob-Schlüsselserver bereitgestellten öffentlichen Schlüssel rotiert?
Vom AdMob-Schlüsselserver bereitgestellte öffentliche Schlüssel werden für eine Variable rotiert ein. Um sicherzustellen, dass SSV-Rückrufe weiterhin funktionieren, sollten öffentliche Schlüssel nicht länger als 24 Stunden im Cache gespeichert werden.
Was passiert, wenn mein Server nicht erreichbar ist?
Google erwartet einen Erfolgsstatusantwortcode für die serverseitige Überprüfung von HTTP 200 OK Callbacks angegeben werden. Wenn Ihr Server nicht erreichbar ist oder nicht den erwarteten antwortet, versucht Google bis zu fünfmal ein-Sekunden-Intervall.
Wie kann ich prüfen, ob SSV-Rückrufe von Google stammen?
Mit dem umgekehrten DNS-Lookup können Sie prüfen, ob die SSV-Rückrufe von Google stammen.