Sunucu tarafı doğrulama (SSV) geri çağırmalarını doğrulama

Sunucu tarafı doğrulama geri çağırmaları, Google tarafından genişletilen ve kullanıcı tarafından ödüllü veya ödüllü geçiş reklamıyla etkileşimde bulunması karşılığında ödüllendirilmesi gerektiğini bildirmek için harici bir sisteme gönderilen sorgu parametreleridir. Ödüllü SSV (sunucu tarafı doğrulaması) geri çağırmaları, kullanıcıları ödüllendirmek için istemci taraflı geri çağırmaların adres sahteciliğine karşı ekstra bir koruma katmanı sağlar.

Bu kılavuzda, geri çağırmadaki sorgu parametrelerinin meşru değerler olduğundan emin olmak için Tink Java Uygulamaları üçüncü taraf şifreleme kitaplığı kullanılarak ödüllü SSV geri çağırmalarını nasıl doğrulayacağınız gösterilmektedir. Tink bu kılavuzun amaçları doğrultusunda kullanılsa da ECDSA'yı destekleyen üçüncü taraf kitaplıkları kullanabilirsiniz. Sunucunuzu AdMob kullanıcı arayüzündeki test aracı ile de test edebilirsiniz.

Java'yı ilkbaharda başlatmayı kullanan tam olarak çalışan bu örneğe göz atın.

Ön koşullar

Tink Java Apps kitaplığındaki RewardedAdsVerifier'ı kullanma

Tink Java Apps GitHub deposu, ödüllü bir SSV geri çağırmasını doğrulamak için gereken kodu azaltmak üzere bir RewardedAdsVerifier yardımcı sınıfı içerir. Bu sınıfı kullandığınızda geri çağırma URL'sini aşağıdaki kodla doğrulayabilirsiniz.

RewardedAdsVerifier verifier = new RewardedAdsVerifier.Builder()
    .fetchVerifyingPublicKeysWith(
        RewardedAdsVerifier.KEYS_DOWNLOADER_INSTANCE_PROD)
    .build();
String rewardUrl = ...;
verifier.verify(rewardUrl);

verify() yöntemi bir istisna oluşturmadan yürütülürse geri çağırma URL'si başarıyla doğrulanmıştır. Kullanıcıyı ödüllendirme bölümünde, kullanıcıların ne zaman ödüllendirilmesi gerektiğiyle ilgili en iyi uygulamalar açıklanmaktadır. Bu sınıf tarafından ödüllü SSV geri çağırmalarını doğrulama adımlarının dökümü için Ödüllü SSV doğrulaması manuel olarak yapılır bölümünü okuyabilirsiniz.

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ğerler aşağıda listelenmiştir. Parametreler alfabetik olarak gönderilir.

Parametre Adı Açıklama Örnek değer
reklam_ağı Bu reklamı gerçekleştiren 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
reklam_birimi Ödüllü reklamı istemek için kullanılan AdMob reklam birimi kimliği. 2747237135
özel_veriler tarafından sağlanan özel veri dizesi.

Uygulama tarafından hiçbir özel veri dizesi sağlanmazsa bu sorgu parametresi değeri SSV geri çağırmasında yer almaz.

SAMPLE_CUSTOM_DATA_STRING
anahtar_kimliği SSV geri çağırmasını doğrulamak için kullanılacak anahtar. Bu değer, AdMob anahtar sunucusu tarafından sağlanan bir ortak anahtarla eşlenir. 1234567890
ödül_tutarı Ödül tutarı, reklam birimi ayarlarında belirtildiği şekilde. 5
ödül_öğesi Öğeyi, reklam birimi ayarlarında belirtildiği şekilde ödüllendirin. para
signature AdMob tarafından oluşturulan SSV geri çağırmasının imzası. MEUCIQCLJS_s4ia_sN06HqzeW7Wc3nhZi4RlW3qV0oO-6AIYdQIgGJEh-rzKreO-paNDbSCzWGMtmgJHYYW9k2_icM9LFMY
timestamp Kullanıcının Ems zamanı olarak ödüllendirildiği zaman damgası (ms). 1507770365237823
transaction_id AdMob tarafından oluşturulan her ödül hibe etkinliği için benzersiz on altılık kodlanmış tanımlayıcı. 18fa792de1bca816048293fc71035638
user_id SetUserId.

Uygulama tarafından hiçbir kullanıcı tanımlayıcısı sağlanmazsa bu sorgu parametresi SSV geri çağırması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 (teklifli sistem)1477265452970951479
AdColony15586990674969969776
AdColony (SDK dışı) (teklifli sistem)4600416542059544716
AdColony (teklifli sistem)6895345910719072481
AdFalcon3528208921554210682
AdMob Ağı5450213213286189855
ADSonuç10593873382626181482
AMoAd17253994435944008978
Aşk1063618907739174004
Applovin (teklifli sistem)1328079684332308356
Liste grafiği2873236629771172317
Çikolata Platformu (teklifli sistem)6432849193975106527
Kanallar Arası (MdotM)9372067028804390441
Özel Etkinlik18351550913290782395
DT Exchange*
* Bu ağ, 21 Eylül 2022'den önce "Fyber Marketplace" olarak adlandırılıyordu.
2179455223494392917
Değişken (teklifli sistem)8419777862490735710
Hafif kar yağışı3376427960656545613
Fyber*
* Bu reklam kaynağı, geçmiş raporlaması için kullanılır.
4839637394546996422
i-mobile5208827440166355534
Dijital Ortamı İyileştirme (teklifli sistem)159382223051638006
Dizin Borsası (teklifli sistem)4100650709078789802
InMobi7681903010231960328
InMobi (teklifli sistem)6325663098072678541
DemirKaynak6925240245545091930
Leadbolt2899150749497968595
LG U+REKLAM18298738678491729107
Maio7505118203095108657
maio (teklifli sistem)1343336733822567166
Media.net (teklifli sistem)2127936450554446159
Uyumlulaştırılmış kurum reklamları6060308706800320801
Meta Audience Network*
* 6 Haziran 2022'den önce bu ağa "Facebook Audience Network" adı veriliyordu.
10568273599589928883
Meta Audience Network (bidding)*
* 6 Haziran 2022'den önce bu ağa "Facebook Audience Network (teklifli sistem)" adı veriliyordu.
11198165126854996598
MobFox8079529624516381459
MoPub (kullanımdan kaldırıldı)10872986198578383917
myTarget8450873672465271579
Nend9383070032774777750
ONE by AOL (Millennial Media)6101072188699264581
ONE by AOL (Nexage)3224789793037044399
OpenX (teklifli sistem)4918705482605678398
Pangle (teklifli sistem)3525379893916449117
PubMatic (teklifli sistem)3841544486172445473
Rezervasyon kampanyası7068401028668408324
RhythmOne (teklifli sistem)2831998725945605450
Rubicon (teklifli sistem)3993193775968767067
SK gezegeni734341340207269415
Paylaşım (teklifli sistem)5247944089976324188
Smaato (teklifli sistem)3362360112145450544
Equativ (teklifli sistem)*

* 12 Ocak 2023'ten önce bu ağa "Akıllı Reklam Sunucusu" adı veriliyordu.

5970199210771591442
Sonobi (teklifli sistem)3270984106996027150
Tapjoy7295217276740746030
Tapjoy (teklifli sistem)4692500501762622178
Tencent GDT7007906637038700218
TripleLift (teklifli sistem)8332676245392738510
Unity Reklamları4970775877303683148
UnrulyX (teklifli sistem)2831998725945605450
Verizon Media7360851262951344112
VPN1940957084538325905
Ödülden Para Kazanma*

* 30 Ocak 2023'ten önce bu ağa "Vungle" adı veriliyordu.

1953547073528090325
Liftoff Para Kazanma (teklifli sistem)*

* 30 Ocak 2023'ten önce bu ağa "Vungle (teklifli sistem)" adı veriliyordu.

4692500501762622185
Yieldmo (teklifli sistem)4193081836471107579
YieldOne (teklifli sistem)3154533971590234104
Zucks5506531810221735863

Kullanıcıyı ödüllendirme

Kullanıcıyı ne zaman ödüllendireceğinize karar verirken kullanıcı deneyimi ile ödülün doğrulanması önemlidir. Sunucu tarafında geri çağırmalarda harici sistemlere ulaşmadan önce gecikmeler yaşanabilir. Bu nedenle önerilen en iyi uygulama, kullanıcıyı hemen ödüllendirmek için istemci taraflı geri çağırmayı kullanmak ve sunucu tarafı geri çağırmaları alındığında tüm ödüller üzerinde doğrulama gerçekleştirmektir. Bu yaklaşım, hem iyi bir kullanıcı deneyimi sağlar hem de verilen ödüllerin geçerliliğini sağlar.

Ancak ödülün geçerliliğinin kritik düzeyde olduğu (örneğin, ödül uygulamanızın oyun içi ekonomisini etkilediği) ve ödül vermedeki gecikmelerin kabul edilebilir olduğu uygulamalar için doğrulanmış sunucu tarafı geri çağırmanın beklemesi en iyi yaklaşım olabilir.

Özel veriler

Sunucu tarafı doğrulama geri çağırmalarında ekstra veri gerektiren uygulamalar, ödüllü reklamların özel veri özelliğini kullanmalıdır. Ödüllü reklam nesnesinde ayarlanan dize değerleri, SSV geri çağırmasının custom_data sorgu parametresine iletilir. Özel veri değeri ayarlanmazsa custom_data sorgu parametresi değeri SSV geri çağırmasında yer almaz.

Aşağıdaki kod örneği, ödüllü reklam yüklendikten sonra SSV seçeneklerinin nasıl ayarlanacağını göstermektedir.

void HandleRewardedAdLoaded(RewardedAd ad, AdFailedToLoadEventArgs error)
{
    // Create and pass the SSV options to the rewarded ad.
    var options = new ServerSideVerificationOptions
                          .Builder()
                          .SetCustomData("SAMPLE_CUSTOM_DATA_STRING")
                          .Build()
    ad.SetServerSideVerificationOptions(options);
}

Özel ödül dizesini ayarlamak istiyorsanız reklamı göstermeden önce bunu yapmanız gerekir.

Ödüllü SSV için manuel doğrulama

Ödüllü bir SSV dosyasını doğrulamak için RewardedAdsVerifier sınıfı tarafından gerçekleştirilen adımlar aşağıda özetlenmiştir. Dahil edilen kod snippet'leri Java'da olsa ve Tink üçüncü taraf kitaplığından yararlansa da bu adımları ECDSA'yı destekleyen herhangi bir üçüncü taraf kitaplığı kullanarak istediğiniz dilde uygulayabilirsiniz.

Ortak anahtarları getir

Ödüllü bir SSV çağrısını doğrulamak için AdMob tarafından sağlanan bir ortak 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 getirilebilir. Ortak anahtarlar listesi, aşağıdakine benzer bir biçimle JSON JSON dosyası biçiminde 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ıp anahtarları indirin. Aşağıdaki kod, bu görevi tamamlar ve data değişkenine anahtarların JSON gösterimini 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();
}

Ortak anahtarların düzenli olarak döndürüldüğünü unutmayın. Yaklaşan bir rotasyon hakkında sizi bilgilendirecek bir e-posta alacaksınız. Ortak 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, yukarıdaki örnek gibi bir JSON dizesini girer ve key_id değerlerinden genel anahtarlara bir eşleme oluşturur. Bu değerler, Tink kitaplığından ECPublicKey nesneleri olarak kapsüllenir.

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;
}

İçeriğinizin doğrulanmasını sağlayın

Ödüllü SSV geri çağırmalarının son iki sorgu parametresi her zaman signature ve key_id, şeklindedir. Kalan sorgu parametreleri, doğrulanacak içeriği belirtir. AdMob'u https://www.myserver.com/mypath adresine ödül geri çağırmaları gönderecek şekilde yapılandırdığınızı varsayalım. Aşağıdaki snippet'te, doğrulanacak içeriğin vurgulandığı, ödüllü örnek bir SSV geri çağırması gösterilmektedir.

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

Aşağıdaki kod, geri çağırma URL'sinden doğrulanacak içeriğin UTF-8 bayt dizisi olarak nasıl ayrıştırılacağını göstermektedir.

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 değerini alın

Önceki adımda kullandığınız queryString değerini kullanarak geri çağırma URL'sinden signature ve key_id sorgu parametrelerini aşağıda gösterildiği 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 yap

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ıp geri çağırma URL'sindeki key_id parametresini kullanarak bu eşlemeden ortak anahtarı alın. Ardından bu ortak anahtarla imzayı doğrulayın. Bu adımlar aşağıda verify yönteminde gösterilmiştir.

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 bir istisna atılmadan yürütülürse 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ı doğrulamak için gereken işlem sayısını azaltmak üzere AdMob anahtar sunucusu tarafından sağlanan ortak anahtarı önbelleğe almanızı öneririz. Ancak, ortak 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önüşümlü olarak yayınlanır?
AdMob anahtar sunucusu tarafından sağlanan ortak anahtarlar, farklı bir programa göre dönüşümlü olarak yayınlanır. SSV çağrılarının doğrulanmasının amaçlandığı şekilde çalışmaya devam etmesini sağlamak için ortak anahtarların 24 saatten uzun süre önbelleğe alınmaması gerekir.
Sunucuma ulaşılamazsa ne olur?
Google, SSV geri çağırma işlemleri için HTTP 200 OK başarı durumu yanıt kodu bekliyor. Sunucunuza ulaşılamıyorsa veya beklenen yanıt sağlanmıyorsa Google, bir saniyelik aralıklarla SSV geri çağırmalarını en fazla beş kez göndermeyi tekrar dener.
SSV geri çağırmaları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ı kullanın.