«بازخوانهای درستیسنجی سمت سرور» درخواستهای نشانی وب با پارامترهای پُرسمان هستند که Google آنها را ازهم باز میکند و برای سیستم خارجی ارسال میکند تا به آن اطلاع دهد که کاربر باید برای تعامل با آگهی ویدیویی پاداشدار یا آگهی بینابینی پاداشدار پاداش دریافت کند. بازخوانهای SSV (درستیسنجی سمت سرور) پاداشدار لایه محافظتی اضافهای دربرابر جعل بازخوانهای سمت کارخواه برای پاداش دادن به کاربران ارائه میدهند.
این راهنما به شما نشان میدهد که چگونه بااستفاده از کتابخانه رمزنگاری شخص ثالث Tink Java Apps، فراخوانهای برگشتی SSV پاداشدار را درستیسنجی کنید تا مطمئن شوید که پارامترهای پُرسمان در فراخوان برگشتی مقادیر قانونی هستند. اگرچه از Tink برای اهداف این راهنما استفاده میشود، شما این گزینه را دارید که از هر کتابخانه طرف سومی که از ECDSA پشتیبانی میکند استفاده کنید. همچنین میتوانید سرورتان را با ابزار آزمایش در میانای کاربری AdMob آزمایش کنید.
پیشنیازها
- درستیسنجی پاداشدار سمت سرور را در واحد آگهیتان فعال کنید.
از RewardedAdsVerifier از کتابخانه Tink Java Apps استفاده کنید
مخزن GitHub برنامههای Tink Java شامل
RewardedAdsVerifier
کلاس کمکی برای کاهش کد موردنیاز برای درستیسنجی کردن برگشتی SSV پاداشدار است.
بااستفاده از این کلاس میتوانید نشانی وب بازگشت تماس را با کد زیر درستیسنجی کنید.
RewardedAdsVerifier verifier = new RewardedAdsVerifier.Builder()
.fetchVerifyingPublicKeysWith(
RewardedAdsVerifier.KEYS_DOWNLOADER_INSTANCE_PROD)
.build();
String rewardUrl = ...;
verifier.verify(rewardUrl);
اگر روش verify() بدون ایجاد استثنا اجرا شود، نشانی وب فراخوان با موفقیت تأیید شده است. بخش پاداش دادن به کاربر
روالهای مطلوب را درباره زمان پاداش دادن به کاربران بهتفصیل شرح میدهد. برای
تفکیک مراحل انجامشده توسط این کلاس برای درستیسنجی بازخوانیهای SSV پاداشدار،
میتوانید بخش درستیسنجی دستی SSV
پاداشدار را بخوانید.
پارامترهای فراخوانی SSV
فراخوانیهای برگشتی درستیسنجی سمت سرور حاوی پارامترهای پُرسمانی است که تعامل آگهی پاداشدار را شرح میدهد. نام، شرح، و مقدار نمونه پارامترها در زیر فهرست شده است. پارامترها بهترتیب حروف الفبا ارسال میشوند.
| نام پارامتر | شرح | مقدار نمونه |
|---|---|---|
| ad_network | شناسه منبع آگهی برای منبع آگهیای که این آگهی را برآورده کرده است. نامهای منبع آگهی متناظر با مقادیر شناسه در بخش شناسههای منبع آگهی فهرست شدهاند. | 1953547073528090325 |
| ad_unit | شناسه واحد تبلیغات AdMob که برای درخواست آگهی پاداشدار استفاده شده است. | 2747237135 |
| custom_data | رشته دادههای سفارشی ارائهشده توسط
customData.
اگر رشته داده سفارشی توسط برنامه ارائه نشود، این مقدار پارامتر پُرسمان در بازخوان SSV وجود نخواهد داشت. |
SAMPLE_CUSTOM_DATA_STRING |
| key_id | کلیدی که برای تأیید فراخوانی SSV استفاده میشود. این مقدار به کلید عمومی ارائهشده توسط سرور کلید AdMob نگاشت میشود. | 1234567890 |
| reward_amount | مقدار پاداش همانطور که در تنظیمات واحد آگهی مشخص شده است. | 5 |
| reward_item | مورد پاداش همانطور که در تنظیمات واحد آگهی مشخص شده است. | سکه |
| امضا | امضای SSV callback تولیدشده توسط AdMob. | MEUCIQCLJS_s4ia_sN06HqzeW7Wc3nhZi4RlW3qV0oO-6AIYdQIgGJEh-rzKreO-paNDbSCzWGMtmgJHYYW9k2_icM9LFMY |
| مُهر زمان | مهر زمان پاداش گرفتن کاربر بهصورت زمان Epoch برحسب میلیثانیه. | 1507770365237823 |
| transaction_id | شناسه یکتای کدگذاریشده با هگز برای هر رویداد اعطای پاداش تولیدشده توسط AdMob. | 18fa792de1bca816048293fc71035638 |
| user_id | شناسه کاربر ارائهشده توسط
userId.
اگر شناسه کاربری توسط برنامه ارائه نشود، این پارامتر پُرسمان در فراخوانی SSV وجود نخواهد داشت. |
1234567 |
شناسههای منبع آگهی
نامها و شناسههای منبع آگهی
| نام منبع آگهی | شناسه منبع آگهی |
|---|---|
| Ad Generation (پیشنهاد قیمت) | 1477265452970951479 |
| شبکه AdMob | 5450213213286189855 |
| آبشار شبکه AdMob | 1215381445328257950 |
| AppLovin | 1063618907739174004 |
| AppLovin (پیشنهاد قیمت) | 1328079684332308356 |
| Bidease (پیشنهاد قیمت) | 3670825090829827805 |
| BidMachine (پیشنهاد قیمت) | 7943972370566394673 |
| Chartboost | 2873236629771172317 |
| Chocolate Platform (مناقصه) | 6432849193975106527 |
| رویداد سفارشی | 18351550913290782395 |
| DT Exchange* * قبلاز ۲۱ سپتامبر ۲۰۲۲، این شبکه «Fyber Marketplace» نامیده میشد. | 2179455223494392917 |
| DT Exchange (پیشنهاد قیمت) | 8189833498765234879 |
| Equativ (bidding)* * پیشاز ۱۲ ژانویه ۲۰۲۳، این شبکه «Smart Adserver» نام داشت. | 5970199210771591442 |
| نوسان (پیشنهاد قیمت دادن) | 8419777862490735710 |
| i-mobile | 5208827440166355534 |
| Improve Digital (پیشنهاد قیمت) | 159382223051638006 |
| Index Exchange (پیشنهاد قیمت) | 4100650709078789802 |
| InMobi | 7681903010231960328 |
| InMobi (کیت توسعه نرمافزار) (پیشنهاد قیمت) | 8468954295581492586 |
| InMobi Exchange (پیشنهاد قیمت) | 5264320421916134407 |
| ironSource Ads | 6925240245545091930 |
| ironSource Ads (bidding) | 1643326773739866623 |
| Liftoff Monetize* * پیشاز ۳۰ ژانویه ۲۰۲۳، این شبکه «Vungle» نام داشت. | 1953547073528090325 |
| Liftoff Monetize (مناقصه)* * قبلاز ۳۰ ژانویه ۲۰۲۳، این شبکه «Vungle (پیشنهاد قیمت)» نامیده میشد. | 4692500501762622185 |
| LY Ads Network | 3025503711505004547 |
| LY Ads Network (bidding) | 2615812619460460513 |
| Magnite DV+ (bidding) | 3993193775968767067 |
| maio | 7505118203095108657 |
| Media.net (bidding) | 2127936450554446159 |
| آگهیهای خانهای میانجیگریشده | 6060308706800320801 |
| Meta Audience Network* * قبلاز ۶ ژوئن ۲۰۲۲، این شبکه «شبکه مخاطبان Facebook» نامیده میشد. | 10568273599589928883 |
| شبکه مخاطبان Meta (پیشنهاد قیمت)* * پیشاز ۶ ژوئن ۲۰۲۲، این شبکه «Facebook Audience Network (bidding)» نام داشت. | 11198165126854996598 |
| Mintegral | 1357746574408896200 |
| Mintegral (پیشنهاد قیمت) | 6250601289653372374 |
| Mobfox (پیشنهاد قیمت) | 3086513548163922365 |
| MobileFuse (bidding) | 7303547408604090310 |
| کیت توسعه نرمافزار آگهیهای Moloco (پیشنهاد قیمت) | 8267622065755668722 |
| myTarget | 8450873672465271579 |
| Nativo (پیشنهاد قیمت دادن) | 3240503836211327896 |
| Nexxen (bidding)* * قبلاز ۱ مه ۲۰۲۴، این شبکه «UnrulyX» نامیده میشد. | 2831998725945605450 |
| OneTag Exchange (bidding) | 4873891452523427499 |
| OpenX (bidding) | 4918705482605678398 |
| Pangle | 4069896914521993236 |
| کیت توسعه نرمافزار Pangle KR (پیشنهاد قیمت) | 12171279046073404914 |
| Pangle ROW SDK (bidding) | 3525379893916449117 |
| کیت توسعه نرمافزار Pangle US (پیشنهاد قیمت) | 15999446638585856012 |
| PubMatic (پیشنهاد قیمت) | 3841544486172445473 |
| PubMatic OpenWrap SDK | 7702975372504485373 |
| کیت توسعه نرمافزار PubMatic OpenWrap (پیشنهاد قیمت) | 1234567890123456789 |
| پویش مدل رزرو | 7068401028668408324 |
| افزایش (پیشنهاد قیمت) | 6816468518946650043 |
| Sharethrough (پیشنهاد قیمت) | 5247944089976324188 |
| Smaato (پیشنهاد قیمت) | 3362360112145450544 |
| Sonobi (bidding) | 3270984106996027150 |
| TripleLift (پیشنهاد قیمت) | 8332676245392738510 |
| Unity Ads | 4970775877303683148 |
| Unity Ads (پیشنهاد قیمت) | 7069338991535737586 |
| گروه Verve (پیشنهاد قیمت) | 5013176581647059185 |
| Vpon | 1940957084538325905 |
| Yieldmo (پیشنهاد قیمت) | 4193081836471107579 |
| YieldOne (پیشنهاد قیمت) | 3154533971590234104 |
| زاکس | 5506531810221735863 |
پاداش دادن به کاربر
هنگام تصمیمگیری درباره زمان پاداش دادن به کاربر، مهم است که بین تجربه کاربری و اعتبارسنجی پاداش تعادل برقرار کنید. فراخوانیهای برگشتی سمت سرور ممکن است قبلاز رسیدن به سیستمهای خارجی با تأخیر مواجه شوند. بنابراین، بهترین روش توصیهشده این است که از فراخوانی برگشتی سمت کارخواه برای پاداش دادن فوری به کاربر استفاده کنید، و درعینحال اعتبارسنجی همه پاداشها را پساز دریافت فراخوانیهای برگشتی سمت سرور انجام دهید. این رویکرد تجربه کاربری خوبی ارائه میدهد و درعینحال اعتبار پاداشهای اعطاشده را تضمین میکند.
بااینحال، برای برنامههایی که اعتبار پاداش در آنها حیاتی است (برای مثال، پاداش بر اقتصاد درونبازی برنامهتان تأثیر میگذارد) و تأخیر در اعطای پاداش قابلقبول است، انتظار برای فراخوانی برگشتی تأییدشده سمت سرور ممکن است بهترین رویکرد باشد.
دادههای سفارشی
برنامههایی که در بازخوانیهای درستیسنجی سمت سرور به دادههای اضافی نیاز دارند باید از
ویژگی دادههای سفارشی آگهیهای پاداشدار استفاده کنند. هر مقدار رشتهای که روی یک شیء آگهی پاداشدار تنظیم شده باشد، به پارامتر پُرسمان custom_data در برگشت تماس SSV منتقل میشود. اگر مقدار داده سفارشی تنظیم نشده باشد، مقدار پارامتر پُرسمان custom_data در
بازخوانی SSV وجود نخواهد داشت.
مثال زیر گزینههای SSV را پساز بار شدن آگهی پاداشدار تنظیم میکند:
SAMPLE_CUSTOM_DATA_STRING را با دادههای سفارشی خودتان جایگزین کنید.
اگر میخواهید رشته پاداش سفارشی را تنظیم کنید، باید این کار را قبلاز نمایش آگهی انجام دهید.
درستیسنجی دستی «درستیسنجی سمت سرور» پاداشدار
مراحل انجامشده توسط کلاس RewardedAdsVerifier برای درستیسنجی SSV پاداشدار در زیر شرح داده شده است. اگرچه قطعه کدهای گنجاندهشده به زبان Java هستند و از کتابخانه شخص ثالث Tink استفاده میکنند، میتوانید این مراحل را به زبان انتخابی خودتان و بااستفاده از هر کتابخانه شخص ثالثی که از ECDSA پشتیبانی میکند پیادهسازی کنید.
واکشی کلیدهای عمومی
برای درستیسنجی کردن برگشت تماس SSV پاداشدار، به کلید عمومی ارائهشده توسط AdMob نیاز دارید.
فهرست کلیدهای عمومی که برای اعتبارسنجی بازخوانیهای SSV پاداشدار استفاده میشود را میتوان از سرور کلید AdMob واکشی کرد. فهرست کلیدهای عمومی بهصورت نمایش JSON با قالبی مشابه با موارد زیر ارائه میشود:
{
"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=="
},
],
}
برای بازیابی کلیدهای عمومی، به سرور کلید AdMob متصل شوید و کلیدها را بارگیری کنید. کد زیر این کار را انجام میدهد و نمایش JSON کلیدها را در متغیر 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();
}
توجه داشته باشید که کلیدهای عمومی بهطور منظم چرخش میکنند. ایمیلی دریافت خواهید کرد که شما را از چرخش آتی مطلع میکند. اگر کلیدهای عمومی را ذخیره میکنید، باید کلیدها را پساز دریافت این ایمیل بهروز کنید.
وقتی کلیدهای عمومی واکشی شدند، باید تجزیه شوند. روش
parsePublicKeysJson در زیر رشته JSON را، مانند مثال بالا، بهعنوان ورودی میگیرد و نگاشت را از مقادیر key_id به کلیدهای عمومی ایجاد میکند،
که بهعنوان اشیای ECPublicKey از کتابخانه 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;
}
دریافت محتوا برای درستیسنجی
دو پارامتر پُرسمان آخرِ برگشتهای تماس SSV پاداشدار همیشه signature
و key_id, به همین ترتیب هستند. پارامترهای پُرسمان باقیمانده محتوایی را که باید درستیسنجی شود مشخص میکنند. فرض کنیم AdMob را پیکربندی کردهاید تا برگشتیهای پاداش را به
https://www.myserver.com/mypath ارسال کند. قطعه کد زیر نمونهای از بازخوانی SSV پاداشدار را نشان میدهد که محتوای قابلتأیید در آن برجسته شده است.
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
کد زیر نشان میدهد که چگونه محتوای موردتأیید را از نشانی وب فراخوان بهعنوان آرایه بایت 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"));
دریافت امضا و key_id از نشانی وب پاسخ تماس
بااستفاده از مقدار queryString از مرحله قبلی، پارامترهای پُرسمان signature و
key_id را از نشانی وب بازگشت تماس تجزیه کنید، همانطور که در زیر نشان داده شده است:
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()));
انجام درستیسنجی
مرحله نهایی درستیسنجی محتوای نشانی وب فراخوانی با کلید عمومی مناسب است. نگاشت برگرداندهشده از روش
parsePublicKeysJson را بگیرید و از پارامتر key_id از نشانی وب
فراخوانی برگشتی استفاده کنید تا کلید عمومی را از آن نگاشت دریافت کنید. سپس امضا را با آن کلید عمومی درستیسنجی میکند. این مراحل در روش 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);
}
}
اگر روش بدون ایجاد استثنا اجرا شود، نشانی وب برگشتی با موفقیت درستیسنجی شده است.
پرسشگان
- آیا میتوانم کلید عمومی ارائهشده توسط سرور کلید AdMob را در حافظه نهان ذخیره کنم؟
- توصیه میکنیم کلید عمومی ارائهشده توسط سرور کلید AdMob را ذخیره کنید تا تعداد عملیات موردنیاز برای اعتبارسنجی بازخوانیهای SSV کاهش یابد. بااینحال، توجه داشته باشید که کلیدهای عمومی بهطور منظم چرخش میکنند و نباید بیشتر از ۲۴ ساعت در حافظه نهان ذخیره شوند.
- کلیدهای عمومی ارائهشده توسط سرور کلید AdMob هر چند وقت یکبار چرخش میکنند؟
- کلیدهای عمومی ارائهشده توسط سرور کلید AdMob در یک برنامه زمانی متغیر چرخانده میشوند. برای اطمینان از اینکه درستیسنجی فراخوانیهای SSV همچنان طبق انتظار کار میکند، کلیدهای عمومی نباید بیشتر از ۲۴ ساعت ذخیره موقت شوند.
- اگر سرور من دردسترس نباشد چه اتفاقی میافتد؟
- Google انتظار دارد کد پاسخ وضعیت موفقیت
HTTP 200 OKرا برای فراخوانیهای SSV دریافت کند. اگر سرورتان دردسترس نباشد یا پاسخ موردانتظار را ارائه ندهد، Google تا پنج بار در فواصل یک ثانیهای تلاش میکند تا برگشتیهای SSV را ارسال کند. - چگونه میتوانم درستیسنجی کنم که بازخوانهای SSV از Google میآیند؟
- از جستجوی ساناد معکوس برای تأیید اینکه تماسهای برگشتی SSV از Google منشأ میگیرند استفاده کنید.