Wywołania zwrotne w ramach weryfikacji po stronie serwera to żądania adresów URL z poszerzonymi parametrami zapytań, które są wysyłane przez Google do systemów zewnętrznych i informują nas, że użytkownik powinien otrzymać nagrodę za interakcję z reklamą pełnoekranową z nagrodą. Wywołania zwrotne z nagrodą SSV (weryfikacja po stronie serwera) stanowią dodatkową warstwę ochrony przed podszywaniem się pod klienta po stronie klienta, aby nagradzać użytkowników.
W tym przewodniku pokazujemy, jak zweryfikować wywołania zwrotne SSV z nagrodą za pomocą biblioteki kryptograficznej Tink Java Apps, aby zapewnić poprawne parametry zapytania w wywołaniach zwrotnych. Mimo że na potrzeby tego przewodnika do tego celu używany jest Tink, masz możliwość korzystania z dowolnej biblioteki zewnętrznej, która obsługuje ECDSA. Możesz też przetestować serwer za pomocą narzędzia do testowania w interfejsie AdMob.
Zapoznaj się z tym w pełni działającym przykładem wykorzystującym sprężynowe oprogramowanie Java.
Wymagania wstępne
Zintegruj reklamy z nagrodą z aplikacją mobilną, używając pakietu SDK do reklam mobilnych Google w wersji11.6.0 lub nowszej.
Włącz weryfikację po stronie serwera z nagrodą w jednostce reklamowej.
Używanie funkcji RewardedAdsVerifier z biblioteki aplikacji Tink Java
Repozytorium Tink Java Apps zawiera klasę pomocniczą RewardedAdsVerifier
umożliwiającą zmniejszenie kodu wymaganego do wywołania wywołania zwrotnego reklamy z nagrodą.
Użycie tej klasy pozwala zweryfikować adres URL wywołania zwrotnego o poniższym kodzie.
RewardedAdsVerifier verifier = new RewardedAdsVerifier.Builder()
.fetchVerifyingPublicKeysWith(
RewardedAdsVerifier.KEYS_DOWNLOADER_INSTANCE_PROD)
.build();
String rewardUrl = ...;
verifier.verify(rewardUrl);
Jeśli metoda verify()
jest uruchamiana bez zgłaszania wyjątku, adres URL wywołania zwrotnego został zweryfikowany. Sekcja Nagradzanie użytkowników zawiera sprawdzone metody dotyczące tego, kiedy użytkownicy powinni otrzymać nagrodę. Zestawienie działań wykonanych w ramach tej weryfikacji pozwala zweryfikować wywołania zwrotne SSV z nagrodą. Możesz zapoznać się z sekcją Weryfikacja ręczna z nagrodą SSV.
Parametry wywołania zwrotnego SSV
Wywołania zwrotne w ramach weryfikacji po stronie serwera zawierają parametry zapytania opisujące interakcję z reklamą. Nazwy i opisy parametrów oraz przykładowe wartości są podane poniżej. Parametry są przesyłane w kolejności alfabetycznej.
Nazwa parametru | opis, | Przykładowa wartość |
---|---|---|
sieć_reklamowa | Identyfikator źródła reklamy, który ją wyświetlił. Nazwy źródeł reklam odpowiadające wartościom identyfikatora znajdziesz w sekcji Identyfikatory źródeł reklam. | 1953547073528090325 |
ad_unit, | Identyfikator jednostki reklamowej AdMob użyty do wysłania żądania reklamy z nagrodą. | 2747237135 |
dane_niestandardowe | Niestandardowy ciąg danych podany przez
setCustomData
.
Jeśli aplikacja nie poda żadnego niestandardowego ciągu danych, ta wartość parametru zapytania nie będzie występowała w wywołaniu zwrotnym SSV. |
SAMPLE_CUSTOM_DATA_STRING |
identyfikator_klucza | Klucz używany do weryfikowania wywołania zwrotnego SSV. Ta wartość jest mapowana na klucz publiczny udostępniony przez serwer kluczy AdMob. | 1234567890 |
kwota_nagrody | Kwota nagrody określona w ustawieniach jednostki reklamowej. | 5 |
element_nagrody | Nagroda, zgodnie z ustawieniami jednostki reklamowej. | monety |
podpis | Podpis wywołania zwrotnego SSV wygenerowany przez AdMob. | MEUCIQCLJS_s4ia_sN06HqzeW7Wc3nhZi4RlW3qV0oO-6AIYdQIgGJEh-rzKreO-paNDbSCzWGMtmgJHYYW9k2_icM9LFMY |
sygnatura czasowa | Sygnatura czasowa wynagrodzenia użytkownika jako czas epoki w ms. | 1507770365237823 |
transaction_id | Unikalny zakodowany szesnastkowo identyfikator każdego zdarzenia przyznania nagrody wygenerowanego przez AdMob. | 18fa792de1bca816048293fc71035638 |
user_id | Identyfikator użytkownika podany przez
setUserId .
Jeśli aplikacja nie poda identyfikatora użytkownika, ten parametr zapytania nie będzie występował w wywołaniu zwrotnym SSV. |
1234567 |
Identyfikatory źródeł reklam
Nazwy i identyfikatory źródeł reklam
Nazwa źródła reklamy | Identyfikator źródła reklamy |
---|---|
Aarki (określanie stawek) | 5240798063227064260 |
Generowanie reklam (określanie stawek) | 1477265452970951479 |
AdColony | 15586990674969969776 |
AdColony (nie SDK) (określanie stawek) | 4600416542059544716 |
AdColony (określanie stawek) | 6895345910719072481 |
AdFalcon | 3528208921554210682 |
Sieć AdMob | 5450213213286189855 |
Wynik reklamy | 10593873382626181482 |
Reklama mobilna | 17253994435944008978 |
AppLovin | 1063618907739174004 |
Applovin (określanie stawek) | 1328079684332308356 |
Chartboost, | 2873236629771172317 |
Platforma Czekoladowa (ustalanie stawek) | 6432849193975106527 |
Wielokanałowa (MdotM) | 9372067028804390441 |
Zdarzenie niestandardowe | 18351550913290782395 |
DT Exchange* * Przed 21 września 2022 roku sieć ta nosiła nazwę „Fyber Marketplace”. | 2179455223494392917 |
Wahania (określanie stawek) | 8419777862490735710 |
Ulotne | 3376427960656545613 |
Fyber* * To źródło reklam jest używane w raportach historycznych. | 4839637394546996422 |
i-mobile | 5208827440166355534 |
Ulepsz cyfrową (określanie stawek) | 159382223051638006 |
Giełda indeksowa (określanie stawek) | 4100650709078789802 |
InMobi | 7681903010231960328 |
InMobi (określanie stawek) | 6325663098072678541 |
Źródło Iron | 6925240245545091930 |
Leadbolt | 2899150749497968595 |
LG U+AD | 18298738678491729107 |
Maio | 7505118203095108657 |
maio (określanie stawek) | 1343336733822567166 |
Media.net (określanie stawek) | 2127936450554446159 |
Zapośredniczone autoreklamy | 6060308706800320801 |
Meta Audience Network* * Do 6 czerwca 2022 roku ta sieć nosiła nazwę „Facebook Audience Network”. | 10568273599589928883 |
Meta Audience Network (określanie stawek)* * Do 6 czerwca 2022 roku ta sieć nosiła nazwę „Facebook Audience Network (określanie stawek)”. | 11198165126854996598 |
MobFox | 8079529624516381459 |
MoPub (wycofane) | 10872986198578383917 |
mójcel | 8450873672465271579 |
Nend | 9383070032774777750 |
ONE by AOL (Millennial Media) | 6101072188699264581 |
ONE by AOL (Nexage) | 3224789793037044399 |
OpenX (określanie stawek) | 4918705482605678398 |
Pangle (określanie stawek) | 3525379893916449117 |
PubMatic (określanie stawek) | 3841544486172445473 |
Kampania z rezerwacjami | 7068401028668408324 |
RhythmOne (określanie stawek) | 2831998725945605450 |
Rubicon (określanie stawek) | 3993193775968767067 |
Planeta SK | 734341340207269415 |
Udział w aukcjach (określanie stawek) | 5247944089976324188 |
Smaato (określanie stawek) | 3362360112145450544 |
Równanie (określanie stawek)* * Przed 12 stycznia 2023 roku ta sieć nazywała się „Smart Adserver”. | 5970199210771591442 |
Sonobi (określanie stawek) | 3270984106996027150 |
Tapjoy | 7295217276740746030 |
Tapjoy (określanie stawek) | 4692500501762622178 |
Tencent GDT | 7007906637038700218 |
TripleLift (określanie stawek) | 8332676245392738510 |
Reklamy Unity | 4970775877303683148 |
UnrulyX (określanie stawek) | 2831998725945605450 |
Verizon Media | 7360851262951344112 |
Vpon | 1940957084538325905 |
Wzrost przychodów* * Przed 30 stycznia 2023 roku ta sieć nazywała się „Vungle”. | 1953547073528090325 |
Wzrost przychodów (określanie stawek)* * Przed 30 stycznia 2023 roku ta sieć nosiła nazwę „Vungle (określanie stawek)”. | 4692500501762622185 |
Yieldmo (określanie stawek) | 4193081836471107579 |
YieldOne (określanie stawek) | 3154533971590234104 |
Zucky | 5506531810221735863 |
Nagradzanie użytkowników
Ważne jest zachowanie równowagi między wrażeniami użytkownika a weryfikacją nagród podczas podejmowania decyzji o nagrodzie dla użytkownika. Mogą wystąpić opóźnienia w wywołaniach po stronie serwera przed uzyskaniem dostępu do systemów zewnętrznych. Z tego powodu zalecaną metodą jest używanie wywołania zwrotnego po stronie klienta w celu natychmiastowego nagradzania użytkownika, a jednocześnie sprawdzanie wszystkich nagród po otrzymaniu wywołań zwrotnych po stronie serwera. Takie podejście zapewnia użytkownikom dobre wrażenia, a jednocześnie zapewnia korzyści przyznawane nagrody.
W przypadku aplikacji, w których ważność nagrody ma kluczowe znaczenie (np. nagroda wpływa na gospodarkę gry w grze), a opóźnienia w realizacji nagród są dopuszczalne, czas oczekiwania na weryfikację po stronie serwera może być najlepszym podejściem.
Dane niestandardowe
Aplikacje, które wymagają dodatkowych danych w wywołaniach zwrotnych po stronie serwera, powinny używać funkcji danych niestandardowych reklam z nagrodą. Każda wartość ciągu ustawiona w obiekcie reklamy z nagrodą jest przekazywana do parametru zapytania custom_data
wywołania zwrotnego SSV. Jeśli nie ustawisz żadnej niestandardowej wartości danych, w wywołaniu zwrotnym SSV nie będzie wartości parametru zapytania custom_data
.
Poniższy kod pokazuje, jak ustawić opcje SSV po wczytaniu reklamy z nagrodą.
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 } })
Jeśli chcesz ustawić niestandardowy ciąg nagród, musisz to zrobić przed wyświetleniem reklamy.
Ręczna weryfikacja SSV z nagrodą
Czynności wykonywane przez klasę RewardedAdsVerifier
w celu zweryfikowania SSV z nagrodą można znaleźć poniżej. Uwzględnione fragmenty kodu są w języku Java i korzystają z biblioteki zewnętrznej Tink, ale możesz wykonać te czynności w wybranym przez siebie języku przy użyciu dowolnej biblioteki zewnętrznej, która obsługuje ECDSA.
Pobierz klucze publiczne
Aby zweryfikować wywołanie zwrotne SSV z nagrodą, potrzebujesz klucza publicznego dostarczonego przez AdMob.
Lista kluczy publicznych używanych do weryfikowania wywołań zwrotnych SSV z nagrodą można pobrać z serwera kluczy AdMob. Lista kluczy publicznych jest podana w formacie JSON w formacie podobnym do tego:
{
"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=="
},
],
}
Aby pobrać klucze publiczne, połącz się z serwerem kluczy AdMob i pobierz klucze. Ten kod wykonuje to zadanie i zapisuje przedstawienie kluczy w zmiennej JSON w zmiennej 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();
}
Pamiętaj, że klucze publiczne są regularnie rotowane. Otrzymasz e-maila z informacją o nadchodzącej rotacji. Jeśli buforujesz klucze publiczne, zaktualizuj je po otrzymaniu tego e-maila.
Po pobraniu kluczy publicznych trzeba je przeanalizować. Poniższa metoda parsePublicKeysJson
pobiera tekst w postaci ciągu JSON (jak w powyższym przykładzie) i tworzy mapowanie z wartości key_id
do kluczy publicznych, które są zamknięte jako obiekty ECPublicKey
z biblioteki Tink.
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;
}
Pobieranie treści do weryfikacji
Ostatnie 2 parametry zapytania z odwołaniami do reklam z nagrodą SSV mają zawsze wartość signature
i key_id,
w tej kolejności. Pozostałe parametry zapytania określają zawartość do zweryfikowania. Załóżmy, że masz skonfigurowane w AdMob wysyłanie wywołań zwrotnych do https://www.myserver.com/mypath
. Fragment kodu poniżej przedstawia przykładowe wywołanie zwrotne reklamy SSV z wyróżnioną treścią.
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
Poniższy kod pokazuje, jak przeanalizować zawartość weryfikowaną z adresu URL wywołania zwrotnego jako tablicę bajtową UTF-8.
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"));
Pobierz podpis i key_id z adresu URL wywołania zwrotnego
Przeanalizuj parametry zapytania signature
i key_id
z adresu URL wywołania zwrotnego, używając wartości queryString
z poprzedniego kroku, jak pokazano poniżej:
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()));
Przeprowadź weryfikację
Ostatnim krokiem jest sprawdzenie treści adresu URL wywołania zwrotnego za pomocą odpowiedniego klucza publicznego. Wykorzystaj mapowanie zwrócone w metodzie parsePublicKeysJson
i użyj parametru key_id
z adresu URL wywołania zwrotnego, aby uzyskać klucz publiczny z mapowania. Następnie zweryfikuj podpis przy użyciu tego klucza publicznego. Te kroki są pokazane poniżej w metodzie verify
.
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);
}
}
Jeśli metoda jest wykonywana bez zgłaszania wyjątku, adres URL wywołania zwrotnego został zweryfikowany.
Najczęstsze pytania
- Czy mogę zapisywać w pamięci podręcznej klucz publiczny udostępniony przez serwer kluczy AdMob?
- Zalecamy zapisywanie w pamięci podręcznej klucza publicznego dostarczonego przez serwer AdMob w celu zmniejszenia liczby operacji wymaganych do weryfikacji wywołań zwrotnych SSV. Pamiętaj jednak, że klucze publiczne są regularnie rotowane i nie powinny być przechowywane w pamięci podręcznej dłużej niż 24 godziny.
- Jak często są publikowane klucze publiczne dostarczane przez serwer kluczy AdMob?
- Klucze publiczne dostarczane przez serwer kluczy AdMob są poddawane rotacji według harmonogramu. Aby weryfikacja wywołań zwrotnych usługi SSV nadal działała zgodnie z oczekiwaniami, klucze publiczne nie powinny być przechowywane w pamięci podręcznej dłużej niż 24 godziny.
- Co się stanie, jeśli mój serwer nie będzie dostępny?
- Google oczekuje
HTTP 200 OK
kodu stanu odpowiedzi w przypadku wywołań zwrotnych SSV. Jeśli serwer nie może nawiązać połączenia lub nie wyświetla oczekiwanej odpowiedzi, Google spróbuje ponownie wysłać wywołania SSV do pięciu razy w sekundach. - Jak sprawdzić, czy wywołania zwrotne SSV pochodzą od Google?
- Aby sprawdzić, czy wywołania SSV pochodzą z Google, użyj odwrotnego wyszukiwania DNS.