Wywołania zwrotne po stronie serwera to żądania adresów URL z rozwiniętymi parametrami zapytań, które są wysyłane przez Google do systemów zewnętrznych, aby powiadomić użytkowników, że powinni otrzymać nagrodę za interakcję z reklamą pełnoekranową z nagrodą. Wywołania zwrotne z nagrodą SSV (weryfikacja po stronie serwera) zapewniają dodatkową warstwę ochrony przed podszywaniem się po stronie klienta w celu wynagrodzenia użytkowników.
W tym przewodniku pokazujemy, jak zweryfikować wywołania zwrotne SSV z nagrodą za pomocą biblioteki kryptograficznej Tink innej firmy, aby mieć pewność, że parametry zapytania w wywołaniach zwrotnych są prawidłowe. Mimo że Tink jest używany na potrzeby tego przewodnika, możesz używać dowolnej biblioteki innej firmy, 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, używając wiosennego rozruchu Java.
Wymagania wstępne
Zintegruj reklamy z nagrodą z aplikacją mobilną za pomocą pakietu SDK do reklam mobilnych Google w wersji11.6.0 lub nowszej.
Włącz weryfikację po stronie serwera z nagrodą w swojej jednostce reklamowej.
Korzystanie z reklamy RewardedAdsVerifier od Tink
Repozytorium Tink na GitHubie zawiera klasę pomocniczą RewardedAdsVerifier
, która zmniejsza kod wymagany do weryfikacji wywołania zwrotnego SSV.
Użycie tej klasy do obsługi biblioteki kryptograficznej Tink innej firmy pozwala zweryfikować URL wywołania zwrotnego za pomocą poniższego kodu.
RewardedAdsVerifier verifier = new RewardedAdsVerifier.Builder()
.fetchVerifyingPublicKeysWith(
RewardedAdsVerifier.KEYS_DOWNLOADER_INSTANCE_PROD)
.build();
String rewardUrl = ...;
verifier.verify(rewardUrl);
Jeśli metoda verify()
uruchamia się bez zgłaszania wyjątku, adres URL wywołania zwrotnego został zweryfikowany. W sekcji Nagroda dla użytkownika znajdziesz sprawdzone metody, które określają, kiedy należy nagradzać użytkowników. Informacje o czynnościach, które wykonuje się w ramach tej klasy, by zweryfikować wywołania zwrotne SSV z nagrodą, znajdziesz w sekcji Weryfikacja manualna w przypadku reklam SSV.
Parametry wywołania zwrotnego SSV
Wywołania zwrotne po stronie serwera zawierają parametry zapytania opisujące interakcję z reklamą z nagrodą. Nazwy, opisy i przykładowe wartości parametrów znajdziesz poniżej. Parametry są przesyłane w kolejności alfabetycznej.
Nazwa parametru | Opis | Przykładowa wartość |
---|---|---|
sieć_reklamowa | Identyfikator źródła reklam, które wypełniło tę reklamę. Nazwy źródeł reklam odpowiadające wartościom identyfikatora są wymienione w sekcji Identyfikatory źródła 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 dostarczy niestandardowego ciągu danych, wartość tego parametru zapytania nie będzie podana w wywołaniu 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 | Element nagrody jest określony w ustawieniach jednostki reklamowej. | monety |
podpis | Podpis wywołania zwrotnego SSV wygenerowanego przez AdMob. | MEUCIQCLJS_s4ia_sN06HqzeW7Wc3nhZi4RlW3qV0oO-6AIYdQIgGJEh-rzKreO-paNDbSCzWGMtmgJHYYW9k2_icM9LFMY |
sygnatura czasowa | Sygnatura czasowa momentu, w którym użytkownik miał otrzymać nagrodę w czasach epoki (w ms). | 1507770365237823 |
transaction_id | Unikalny zakodowany szesnastkowo identyfikator każdego zdarzenia przyznania nagrody wygenerowany 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 SSV. |
1234567 |
Identyfikatory źródeł reklam
Nazwy i identyfikatory źródeł reklam
Nazwa źródła reklamy | Identyfikator źródła reklam |
---|---|
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 |
AD wyniku | 10593873382626181482 |
ReklamaMoMo | 17253994435944008978 |
AppLovin | 1063618907739174004 |
Applovin (określanie stawek) | 1328079684332308356 |
Grafboost | 2873236629771172317 |
Czekolada z platformą (określanie stawek) | 6432849193975106527 |
W różnych kanałach (MdotM) | 9372067028804390441 |
Zdarzenie niestandardowe | 18351550913290782395 |
DT Exchange Przed 21 września 2022 roku ta sieć nazywała się „Fyber”. | 4839637394546996422 |
Wahania (określanie stawek) | 8419777862490735710 |
Pochmurno | 3376427960656545613 |
i-mobile | 5208827440166355534 |
Ulepszanie rozwiązań cyfrowych (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 Przed 6 czerwca 2022 roku ta sieć nosiła nazwę „Facebook Audience Network”. | 10568273599589928883 |
Meta Audience Network (określanie stawek) Przed 6 czerwca 2022 roku ta sieć nosiła nazwę „Facebook Audience Network (bidding)”. | 11198165126854996598 |
MobFox | 8079529624516381459 |
MoPub (wycofane) | 10872986198578383917 |
mój_cel | 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 rezerwacją | 7068401028668408324 |
RhythmOne (określanie stawek) | 2831998725945605450 |
Rubicon (określanie stawek) | 3993193775968767067 |
Planeta K | 734341340207269415 |
Udostępnianie (określanie stawek) | 5247944089976324188 |
Smaato (określanie stawek) | 3362360112145450544 |
Equativ (określanie stawek)* * Do 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 |
Zakończenie zarabiania* * Do 30 stycznia 2023 roku ta sieć nazywała się „Vungle”. | 1953547073528090325 |
Rozpoczęcie zarabiania (określanie stawek)* * Do 30 stycznia 2023 roku ta sieć nazywała się „Vungle”. | 4692500501762622185 |
Yieldmo (określanie stawek) | 4193081836471107579 |
YieldOne (określanie stawek) | 3154533971590234104 |
Zucki | 5506531810221735863 |
Nagradzanie użytkowników
Podczas podejmowania decyzji o nagrodzie należy wziąć pod uwagę równowagę między wrażeniami użytkowników a weryfikacją nagród. Wywołania zwrotne po stronie serwera mogą być opóźnione przed dotarciem do systemów zewnętrznych. Dlatego zalecamy stosowanie metody zwrotnej po stronie klienta w celu natychmiastowego nagradzania użytkownika i sprawdzania wszystkich nagród po otrzymaniu wywołań po stronie serwera. Takie podejście zapewnia użytkownikom dobre wrażenia, a jednocześnie powoduje, że przyznane nagrody są prawidłowe.
W przypadku aplikacji, których ważność jest ważna (np. nagroda ma wpływ na gospodarkę w aplikacji), a jej opóźnienia w realizacji nagród są dozwolone.
Dane niestandardowe
Aplikacje, które wymagają dodatkowych danych w wywołaniach weryfikacji po stronie serwera, powinny korzystać z niestandardowej funkcji danych z reklamami 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, wartość parametru zapytania custom_data
nie będzie podana w wywołaniu zwrotnym SSV.
Poniższy przykładowy kod pokazuje, jak ustawić opcje weryfikacji po wyświetleniu 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.
Weryfikacja ręczna w przypadku reklam SSV
Czynności wykonywane w klasie RewardedAdsVerifier
w celu weryfikacji reklamy TrueView z nagrodą są opisane poniżej. Uwzględnione fragmenty kodu są w języku Java i korzystają z biblioteki Tink firmy zewnętrznej, ale możesz wykonać te kroki w wybranym przez siebie języku, używając dowolnej biblioteki zewnętrznej, która obsługuje ECDSA.
Pobieranie kluczy publicznych
Aby zweryfikować wywołanie zwrotne SSV z nagrodą, musisz mieć klucz publiczny udostępniony przez AdMob.
Lista kluczy publicznych, które mają służyć do weryfikowania wywołań zwrotnych SSV z nagrodą, można pobrać z serwera kluczy AdMob. Lista kluczy publicznych jest wyświetlana 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. Poniższy 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();
}
Klucze publiczne są regularnie poddawane rotacji. Otrzymasz e-maila z informacją o zbliżającym się rotacji. Jeśli przechowujesz w pamięci podręcznej klucze publiczne, musisz zaktualizować klucze po otrzymaniu tego e-maila.
Po pobraniu kluczy publicznych muszą zostać przeanalizowane. Metoda parsePublicKeysJson
poniżej wykorzystuje ciąg JSON (jak w przykładzie powyżej) i tworzy mapowanie z wartości key_id
do kluczy publicznych, które są przekształcane w 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;
}
Pobierz treści do weryfikacji
Ostatnie 2 parametry zapytania z wywołaniem SSV z nagrodą to zawsze signature
i key_id,
w tej kolejności. Pozostałe parametry zapytania określają zawartość strony, która ma zostać zweryfikowana. Załóżmy, że masz skonfigurowane w AdMob wysyłanie wywołań zwrotnych do https://www.myserver.com/mypath
. Fragment kodu poniżej pokazuje przykładowego wywołania zwrotnego reklamy z nagrodą 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ć treść do weryfikacji z adresu URL wywołania zwrotnego jako tablicę 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"));
Uzyskiwanie podpisu i klucza_identyfikatora z adresu URL wywołania zwrotnego
Korzystając z wartości queryString
z poprzedniego kroku, przeanalizuj parametry zapytania signature
i key_id
z adresu URL wywołania zwrotnego, 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ę
Na koniec należy zweryfikować treść adresu URL wywołania zwrotnego za pomocą odpowiedniego klucza publicznego. Zmapuj zwracane dane z metody parsePublicKeysJson
i użyj parametru key_id
z adresu URL wywołania zwrotnego, aby uzyskać klucz publiczny z tego mapowania. Następnie sprawdź podpis przy użyciu tego klucza publicznego. Podane niżej kroki zostały przedstawione 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 działa bez wyjątku, adres URL wywołania zwrotnego został zweryfikowany.
Najczęstsze pytania
- Czy mogę buforować klucz publiczny udostępniony przez serwer kluczy AdMob?
- Zalecamy przechowywanie w pamięci podręcznej klucza publicznego podanego przez serwer kluczy AdMob, aby zmniejszyć liczbę 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ą aktualizowane klucze publiczne dostarczane przez serwer kluczy AdMob?
- Klucze publiczne udostępnione przez serwer kluczy AdMob są poddawane rotacji zgodnie ze harmonogramem. Aby sprawdzić, czy wywołania zwrotne usługi SSV nadal działają 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 zostanie połączony?
- Google spodziewa się
HTTP 200 OK
kodu odpowiedzi stanu wywołania zwrotnego SSV. Jeśli nie uda się nawiązać połączenia z serwerem lub nie uzyskasz oczekiwanej odpowiedzi, Google ponownie spróbuje wysłać wywołanie zwrotne SSV maksymalnie 5-krotnie w sekundach. - Jak sprawdzić, czy wywołania zwrotne usługi SSV pochodzą od Google?
- Użyj odwrotnego wyszukiwania DNS, aby sprawdzić, czy wywołania zwrotne SSV pochodzą od Google.