Sunucu tarafı doğrulama geri çağırmaları, Google tarafından genişletilen sorgu parametrelerine sahip URL isteklerinden oluşur. Google bu istekleri, kullanıcının ödüllü veya ödüllü geçiş reklamıyla etkileşime geçtiği için ödüllendirilmesi gerektiğini bildirmek üzere harici bir sisteme gönderir. Ödüllü SSV (sunucu tarafı doğrulaması) geri çağırmaları, kullanıcılara ödül vermek için istemci tarafı geri çağırmalarının taklit edilmesine karşı ek bir koruma katmanı sağlar.
Bu kılavuzda, geri çağırmadaki sorgu parametrelerinin geçerli değerler olduğundan emin olmak için Tink Java Apps üçüncü taraf kriptografik kitaplığını kullanarak ödüllü SSV geri çağırmalarının nasıl doğrulanacağı gösterilmektedir. Bu kılavuzda Tink kullanılsa da ECDSA'yı destekleyen herhangi bir üçüncü taraf kitaplığını kullanabilirsiniz. Sunucunuzu AdMob kullanıcı arayüzündeki test aracı ile de test edebilirsiniz.
Java spring-boot kullanan Ödüllü SSV Örneği'ne göz atın.
Ön koşullar
- Reklam biriminde ödüllü sunucu tarafı doğrulamayı etkinleştirin.
Tink Java Apps kitaplığındaki RewardedAdsVerifier'ı kullanma
Tink Java Apps GitHub deposunda, ödüllü SSV geri çağırmasını doğrulamak için gereken kodu azaltan bir RewardedAdsVerifier
yardımcı sınıfı bulunur.
Bu sınıfı kullanarak aşağıdaki kodla geri çağırma URL'sini doğrulayabilirsiniz.
RewardedAdsVerifier verifier = new RewardedAdsVerifier.Builder()
.fetchVerifyingPublicKeysWith(
RewardedAdsVerifier.KEYS_DOWNLOADER_INSTANCE_PROD)
.build();
String rewardUrl = ...;
verifier.verify(rewardUrl);
verify()
yöntemi istisna oluşturmadan yürütülürse geri çağırma URL'si başarıyla doğrulanmıştır. Kullanıcıya ödül verme bölümünde, kullanıcılara ne zaman ödül verilmesi gerektiğiyle ilgili en iyi uygulamalar ayrıntılı olarak açıklanmaktadır. Ödüllü SSV geri çağırmalarını doğrulamak için bu sınıf tarafından gerçekleştirilen adımların dökümünü Ödüllü SSV'nin manuel olarak doğrulanması bölümünde bulabilirsiniz.
SSV geri çağırma parametreleri
Sunucu tarafı doğrulama geri çağırmaları, ödüllü reklam etkileşimini açıklayan sorgu parametreleri içerir. Parametre adları, açıklamaları ve örnek değerleri aşağıda listelenmiştir. Parametreler alfabetik olarak gönderilir.
Parametre Adı | Açıklama | Örnek değer |
---|---|---|
ad_network | Bu reklamı karşılayan reklam kaynağının reklam kaynağı tanımlayıcısı. Kimlik değerlerine karşılık gelen reklam kaynağı adları Reklam kaynağı tanımlayıcılar bölümünde listelenir. | 1953547073528090325 |
ad_unit | Ödüllü reklamı istemek için kullanılan AdMob reklam birimi kimliği. | 2747237135 |
custom_data |
setCustomData tarafından sağlanan özel veri dizesi.
Uygulama tarafından özel veri dizesi sağlanmazsa bu sorgu parametresi değeri SSV geri çağırma işlevinde yer almaz. |
SAMPLE_CUSTOM_DATA_STRING |
key_id | SSV geri aramasını doğrulamak için kullanılacak anahtar. Bu değer, AdMob anahtar sunucusu tarafından sağlanan bir ortak anahtarla eşlenir. | 1234567890 |
reward_amount | Reklam birimi ayarlarında belirtilen ödül tutarı. | 5 |
reward_item | Reklam birimi ayarlarında belirtildiği şekilde ödül öğesi. | para |
signature | AdMob tarafından oluşturulan SSV geri çağırması için imza. | MEUCIQCLJS_s4ia_sN06HqzeW7Wc3nhZi4RlW3qV0oO-6AIYdQIgGJEh-rzKreO-paNDbSCzWGMtmgJHYYW9k2_icM9LFMY |
timestamp | Kullanıcının ödül kazandığı zamanın zaman damgası (milisaniye cinsinden Epoch zamanı). | 1507770365237823 |
transaction_id | AdMob tarafından oluşturulan her ödül verme etkinliği için benzersiz onaltılık kodlu tanımlayıcı. | 18fa792de1bca816048293fc71035638 |
user_id | setUserId tarafından sağlanan kullanıcı tanımlayıcısı.
Uygulama tarafından kullanıcı tanımlayıcısı sağlanmazsa bu sorgu parametresi SSV geri çağırma çağrısında yer almaz. |
1234567 |
Reklam kaynağı tanımlayıcıları
Reklam kaynağı adları ve kimlikleri
Reklam kaynağı adı | Reklam kaynağı kimliği |
---|---|
Aarki (teklifli sistem) | 5240798063227064260 |
Ad Generation (teklif verme) | 1477265452970951479 |
AdColony | 15586990674969969776 |
AdColony (SDK olmayan) (teklif verme) | 4600416542059544716 |
AdColony (teklifli sistem) | 6895345910719072481 |
AdFalcon | 3528208921554210682 |
AdMob Ağı | 5450213213286189855 |
AdMob Ağı Şelalesi | 1215381445328257950 |
ADResult | 10593873382626181482 |
AMoAd | 17253994435944008978 |
Applovin | 1063618907739174004 |
Applovin (teklifli sistem) | 1328079684332308356 |
Chartboost | 2873236629771172317 |
Chocolate Platform (teklif verme) | 6432849193975106527 |
CrossChannel (MdotM) | 9372067028804390441 |
Özel Etkinlik | 18351550913290782395 |
DT Exchange* * Bu ağ, 21 Eylül 2022'den önce "Fyber Marketplace" olarak adlandırılıyordu. | 2179455223494392917 |
EMX (teklifli sistem) | 8497809869790333482 |
Fluct (teklifli sistem) | 8419777862490735710 |
Flurry | 3376427960656545613 |
Fyber* * Bu reklam kaynağı geçmiş raporlama için kullanılır. | 4839637394546996422 |
i-mobile | 5208827440166355534 |
Improve Digital (teklif verme) | 159382223051638006 |
Index Exchange (teklif verme) | 4100650709078789802 |
InMobi | 7681903010231960328 |
InMobi (teklifli sistem) | 6325663098072678541 |
InMobi Exchange (teklif verme) | 5264320421916134407 |
IronSource | 6925240245545091930 |
ironSource Ads (teklif verme) | 1643326773739866623 |
Leadbolt | 2899150749497968595 |
LG U+AD | 18298738678491729107 |
LINE Ads Ağı | 3025503711505004547 |
maio | 7505118203095108657 |
maio (teklifli sistem) | 1343336733822567166 |
Media.net (teklifli sistem) | 2127936450554446159 |
Uyumlulaştırılmış kurum reklamları | 6060308706800320801 |
Meta Audience Network* * Bu ağ, 6 Haziran 2022'den önce "Facebook Audience Network" olarak adlandırılıyordu. | 10568273599589928883 |
Meta Audience Network (teklifli sistem)* * Bu ağ, 6 Haziran 2022'den önce "Facebook Audience Network (teklifli sistem)" olarak adlandırılıyordu. | 11198165126854996598 |
Mintegral | 1357746574408896200 |
Mintegral (teklifli sistem) | 6250601289653372374 |
MobFox | 8079529624516381459 |
MobFox (teklifli sistem) | 3086513548163922365 |
MoPub (desteği sonlandırıldı) | 10872986198578383917 |
myTarget | 8450873672465271579 |
Nend | 9383070032774777750 |
Nexxen (teklifli sistem)* * Bu ağ, 1 Mayıs 2024'ten önce "UnrulyX" olarak adlandırılıyordu. | 2831998725945605450 |
ONE by AOL (Millennial Media) | 6101072188699264581 |
ONE by AOL (Nexage) | 3224789793037044399 |
OneTag Exchange (teklif verme) | 4873891452523427499 |
OpenX (teklifli sistem) | 4918705482605678398 |
Pangle | 4069896914521993236 |
Pangle (teklifli sistem) | 3525379893916449117 |
PubMatic (teklifli sistem) | 3841544486172445473 |
Rezervasyon kampanyası | 7068401028668408324 |
RhythmOne (teklifli sistem) | 2831998725945605450 |
Magnite DV+ (teklif verme) | 3993193775968767067 |
SK gezegeni | 734341340207269415 |
Sharethrough (teklifli sistem) | 5247944089976324188 |
Smaato (teklifli sistem) | 3362360112145450544 |
Equativ (teklif verme)* * 12 Ocak 2023'ten önce bu ağın adı "Akıllı Reklam Sunucusu" idi. | 5970199210771591442 |
Sonobi (teklifli sistem) | 3270984106996027150 |
Tapjoy | 7295217276740746030 |
Tapjoy (teklifli sistem) | 4692500501762622178 |
Tencent GDT | 7007906637038700218 |
TripleLift (teklifli sistem) | 8332676245392738510 |
Unity Ads | 4970775877303683148 |
Unity Ads (teklif verme) | 7069338991535737586 |
Verizon Media | 7360851262951344112 |
Verve Group (teklifli sistem) | 5013176581647059185 |
Vpon | 1940957084538325905 |
Liftoff Monetize* * Bu ağın adı 30 Ocak 2023'ten önce "Vungle" idi. | 1953547073528090325 |
Liftoff Monetize (teklif)* * 30 Ocak 2023'ten önce bu ağın adı "Vungle (teklif verme)" idi. | 4692500501762622185 |
Yieldmo (teklifli sistem) | 4193081836471107579 |
YieldOne (teklifli sistem) | 3154533971590234104 |
Zucks | 5506531810221735863 |
Kullanıcıyı ödüllendirme
Kullanıcıya ne zaman ödül verileceğine karar verirken kullanıcı deneyimi ile ödül doğrulaması arasında denge kurmak önemlidir. Sunucu tarafı geri çağırmalarda harici sistemlere ulaşmadan önce gecikmeler yaşanabilir. Bu nedenle, kullanıcıya hemen ödül vermek için istemci tarafı geri çağırma işlevini kullanmak ve sunucu tarafı geri çağırma işlevleri alındıktan sonra tüm ödüllerde doğrulama yapmak en iyi uygulama olarak önerilir. Bu yaklaşım, verilen ödüllerin geçerliliğini sağlarken iyi bir kullanıcı deneyimi sunar.
Ancak ödül geçerliliğinin kritik olduğu (örneğin, ödül uygulamanızın oyun içi ekonomisini etkiliyorsa) ve ödül vermede gecikmelerin kabul edildiği uygulamalarda, doğrulanmış sunucu tarafı geri çağırma işlevini beklemek en iyi yaklaşım olabilir.
Özel veriler
Sunucu tarafı doğrulama geri çağırmalarında ek veri gerektiren uygulamalar, ödüllü reklamların özel veri özelliğini kullanmalıdır. Ödüllü reklam nesnesinde ayarlanan tüm dize değerleri, SSV geri çağırma işlevinin custom_data
sorgu parametresine iletilir. Özel veri değeri ayarlanmazsa custom_data
sorgu parametresi değeri SSV geri çağırma işlevinde yer almaz.
Aşağıdaki örnekte, ödüllü reklam yüklendikten sonra SSV seçenekleri ayarlanmaktadır:
Java
RewardedAd.load(MainActivity.this, "AD_UNIT_ID", 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, "AD_UNIT_ID", 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 } })
Özel ödül dizesini ayarlamak istiyorsanız bunu reklamı göstermeden önce yapmanız gerekir.
Ödüllü SSV'nin manuel olarak doğrulanması
Ödüllü SSV'yi doğrulamak için RewardedAdsVerifier
sınıfı tarafından gerçekleştirilen adımlar aşağıda açıklanmıştır. Eklenen kod snippet'leri Java'dadır ve Tink üçüncü taraf kitaplığından yararlanır. Ancak bu adımları, ECDSA'yı destekleyen herhangi bir üçüncü taraf kitaplığı kullanarak istediğiniz dilde uygulayabilirsiniz.
Ortak anahtarları getirme
Ödüllü SSV geri çağırmasını doğrulamak için AdMob tarafından sağlanan bir herkese açık anahtara ihtiyacınız vardır.
Ödüllü SSV geri çağırmalarını doğrulamak için kullanılacak ortak anahtarların listesi AdMob anahtar sunucusundan alınabilir. Herkese açık anahtarların listesi, aşağıdakine benzer bir biçime sahip bir JSON gösterimi olarak sağlanır:
{
"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=="
},
],
}
Ortak anahtarları almak için AdMob anahtar sunucusuna bağlanın ve anahtarları indirin. Aşağıdaki kod bu görevi yerine getirir ve anahtarların JSON temsilini data
değişkenine kaydeder.
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();
}
Genel anahtarların düzenli olarak değiştirildiğini unutmayın. Yaklaşan bir rotasyon hakkında sizi bilgilendiren bir e-posta alırsınız. Herkese açık anahtarları önbelleğe alıyorsanız bu e-postayı aldıktan sonra anahtarları güncellemeniz gerekir.
Ortak anahtarlar getirildikten sonra ayrıştırılmalıdır. Aşağıdaki parsePublicKeysJson
yöntemi, giriş olarak yukarıdaki örnek gibi bir JSON dizesi alır ve key_id
değerlerini, Tink kitaplığındaki ECPublicKey
nesneleri olarak kapsüllenen herkese açık anahtarlarla eşler.
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;
}
Doğrulanacak içeriği alma
Ödüllü SSV geri aramalarının son iki sorgu parametresi her zaman bu sırayla signature
ve key_id,
olur. Kalan sorgu parametreleri, doğrulanacak içeriği belirtir. AdMob'u, ödül geri çağırmalarını https://www.myserver.com/mypath
adresine gönderecek şekilde yapılandırdığınızı varsayalım. Aşağıdaki snippet'te, doğrulanacak içeriğin vurgulandığı örnek bir ödüllü SSV geri çağırma işlevi gösterilmektedir.
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
Aşağıdaki kodda, doğrulanacak içeriğin bir geri çağırma URL'sinden UTF-8 bayt dizisi olarak nasıl ayrıştırılacağı gösterilmektedir.
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"));
Geri çağırma URL'sinden imza ve key_id'yi alma
Önceki adımdaki queryString
değerini kullanarak geri arama URL'sindeki signature
ve key_id
sorgu parametrelerini aşağıdaki gibi ayrıştırın:
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()));
Doğrulama yapma
Son adım, geri çağırma URL'sinin içeriğini uygun ortak anahtarla doğrulamaktır. parsePublicKeysJson
yönteminden döndürülen eşlemeyi alın ve bu eşlemeden herkese açık anahtarı almak için geri çağırma URL'sindeki key_id
parametresini kullanın. Ardından, bu ortak anahtarla imzası doğrulayın. Bu adımlar aşağıda verify
yönteminde gösterilmektedir.
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);
}
}
Yöntem istisna vermeden yürütülüyorsa geri çağırma URL'si başarıyla doğrulanmıştır.
SSS
- AdMob anahtar sunucusu tarafından sağlanan ortak anahtarı önbelleğe alabilir miyim?
- SSV geri çağırmalarının doğrulanması için gereken işlem sayısını azaltmak amacıyla AdMob anahtar sunucusu tarafından sağlanan ortak anahtarı önbelleğe almanızı öneririz. Ancak, herkese açık anahtarların düzenli olarak döndürüldüğünü ve 24 saatten uzun süre önbelleğe alınmaması gerektiğini unutmayın.
- AdMob anahtar sunucusu tarafından sağlanan ortak anahtarlar ne sıklıkta döndürülür?
- AdMob anahtar sunucusu tarafından sağlanan ortak anahtarlar, değişken bir programla döndürülür. SSV geri çağırmalarının doğrulamasının amaçlandığı gibi çalışmaya devam etmesini sağlamak için ortak anahtarlar 24 saatten uzun süre önbelleğe alınmamalıdır.
- Sunucuma ulaşılamazsa ne olur?
- Google, SSV geri çağırmalarında
HTTP 200 OK
başarı durum yanıt kodu bekler. Sunucunuza erişilemezse veya beklenen yanıtı vermezse Google, SSV geri aramalarını bir saniyelik aralıklarla beş defaya kadar göndermeyi yeniden dener. - SSV geri aramalarının Google'dan geldiğini nasıl doğrulayabilirim?
- SSV geri çağırmalarının Google'dan geldiğini doğrulamak için ters DNS araması yapın.