عمليات استدعاء إثبات الملكية من جانب الخادم هي طلبات عناوين URL، مع مَعلمات طلب البحث بواسطة Google، والتي ترسلها Google إلى نظام خارجي وإشعاره بأنه ينبغي أن يحصل المستخدم على مكافأة مقابل التفاعل مع إعلان إعلان بيني يضم مكافأة طلبات معاودة الاتصال الخاصة بميزة "إثبات الملكية من جهة الخادم" بمكافأة توفير طبقة حماية إضافية ضد انتحال المكالمات من جهة العميل لمكافأة المستخدمين.
يوضح لك هذا الدليل كيفية التحقّق من استدعاءات SSV بمكافأة باستخدام Tink Java Apps التابعة لجهات خارجية للتأكد من أن معاملات الاستعلام في عملية الاستدعاء القيم المشروعة. ورغم استخدام Tink لأغراض هذا الدليل، يمكنك استخدام أي مكتبة تابعة لجهة خارجية ECDSA: يمكنك أيضًا اختبار خادمك باستخدام أداة الاختبار في واجهة مستخدم AdMob.
تحقق من هذا البرنامج الذي يعمل بشكل كامل مثال باستخدام حذاء الربيع لـ Java.
المتطلبات الأساسية
دمج الإعلانات بمكافأة في تطبيق للأجهزة الجوّالة مع الإصدار 11.6.0 أو الإصدارات الأحدث من حزمة "SDK لإعلانات Google على الأجهزة الجوّالة".
تفعيل من جهة الخادم بمكافأة التحقق على وحدتك الإعلانية.
استخدام واجهة BonusedAdsVerifier من مكتبة Tink Java Apps
مستودع Tink Java Apps في GitHub
تشتمل على
RewardedAdsVerifier
لخفض الرمز المطلوب للتحقق من معاودة اتصال SSV بمكافأة.
يتيح لك استخدام هذه الفئة إثبات ملكية عنوان URL لمعاودة الاتصال باستخدام الرمز التالي.
RewardedAdsVerifier verifier = new RewardedAdsVerifier.Builder()
.fetchVerifyingPublicKeysWith(
RewardedAdsVerifier.KEYS_DOWNLOADER_INSTANCE_PROD)
.build();
String rewardUrl = ...;
verifier.verify(rewardUrl);
إذا تم تنفيذ الطريقة verify()
بدون تقديم استثناء، سيتم تنفيذ ما يلي من خلال
تم التحقق من عنوان URL بنجاح. مكافأة المستخدم
يوضح بالتفصيل أفضل الممارسات المتعلقة بالحالات التي يجب فيها مكافأة المستخدمين. بالنسبة إلى
الخطوات التي تنفذها هذه الفئة للتحقق من استدعاءات SSV بمكافأة،
يمكنك الاطّلاع على التحقق اليدوي من الإعلانات بمكافأة
SSV.
مَعلمات معاودة الاتصال باستخدام SSV
تحتوي استدعاءات التحقق من جهة الخادم على مَعلمات طلب بحث تصف تفاعل مع إعلان يضم مكافأة تكون أسماء المَعلمات والأوصاف وأمثلة القيم الواردة أدناه. يتم إرسال المَعلمات حسب الترتيب الأبجدي.
اسم المعلمة | الوصف | مثال على القيمة |
---|---|---|
ad_network | معرّف مصدر الإعلان لمصدر الإعلان الذي عرض هذا الإعلان. مصدر الإعلان يتم سرد الأسماء المقابلة لقيم المعرّفات في جدول الإعلانات معرّفات المصادر | 1953547073528090325 |
ad_unit | رقم تعريف الوحدة الإعلانية في AdMob التي تم استخدامها لطلب الإعلان الذي يضم مكافأة. | 2747237135 |
custom_data | سلسلة البيانات المخصصة كما هي مقدّمة من
setCustomData
.
إذا لم يوفّر التطبيق أي سلسلة بيانات مخصّصة، ستكون معلَمة طلب البحث هذه. في استدعاء SSV. |
SAMPLE_CUSTOM_DATA_STRING |
key_id | المفتاح الذي سيتم استخدامه للتحقُّق من معاودة اتصال ميزة "التحقُّق بخطوتين". يتم ربط هذه القيمة بمفتاح عام. التي يقدّمها خادم مفاتيح مفاتيح AdMob. | 1234567890 |
reward_amount | مبلغ المكافأة على النحو المحدّد في إعدادات الوحدة الإعلانية | 5 |
reward_item | عنصر المكافأة على النحو المحدّد في إعدادات الوحدة الإعلانية. | عملات معدنية |
توقيع | توقيع معاودة الاتصال الخاصة بميزة "التحقُّق بخطوتين" (SSV) التي أنشأها AdMob | MEUCIQCLJS_s4ia_sN06HqzeW7Wc3nhZi4RlW3qV0oO-6AIYdQIgGJEh-rzKreO-paNDbSCzWGMtmgJHYYW9k2_icM9LFMY |
timestamp | طابع زمني لوقت مكافأة المستخدم كوقت حقبة بالمللي ثانية | 1507770365237823 |
transaction_id | معرّف فريد بترميز سداسي لكل حدث منح مكافأة تنشئه AdMob | 18fa792de1bca816048293fc71035638 |
user_id | معرّف المستخدم على النحو المقدَّم من
setUserId
وإذا لم يوفّر التطبيق معرّف المستخدم، لن يتم توفير مَعلمة طلب البحث هذه موجودة في معاودة اتصال SSV. |
1234567 |
معرّفات مصادر الإعلانات
أسماء مصادر الإعلانات وأرقام تعريفها
اسم مصدر الإعلان | رقم تعريف مصدر الإعلان |
---|---|
Aarki (عروض الأسعار) | 5240798063227064260 |
إنشاء الإعلانات (عروض الأسعار) | 1477265452970951479 |
AdColony | 15586990674969969776 |
AdColony (غير مستندة إلى حزمة تطوير البرامج (SDK)) (عروض الأسعار) | 4600416542059544716 |
AdColony (عروض الأسعار) | 6895345910719072481 |
AdFalcon | 3528208921554210682 |
شبكة AdMob | 5450213213286189855 |
العرض الإعلاني بدون انقطاع في شبكة AdMob | 1215381445328257950 |
ADResult | 10593873382626181482 |
AMoAd | 17253994435944008978 |
أبلوفين | 1063618907739174004 |
Apploin (عروض الأسعار) | 1328079684332308356 |
Chartboost | 2873236629771172317 |
منصة الشوكولاتة (عروض الأسعار) | 6432849193975106527 |
CrossChannel (MdotM) | 9372067028804390441 |
حدث مخصّص | 18351550913290782395 |
DT Exchange* * قبل 21 أيلول (سبتمبر) 2022، كان يُطلق على هذه الشبكة اسم "سوق Fyber". | 2179455223494392917 |
EMX (عروض الأسعار) | 8497809869790333482 |
متقلّب (عروض الأسعار) | 8419777862490735710 |
Flurry | 3376427960656545613 |
Fyber* * يُستخدَم مصدر الإعلان هذا في إعداد التقارير السابقة. | 4839637394546996422 |
i-mobile | 5208827440166355534 |
التحسين الرقمي (عروض الأسعار) | 159382223051638006 |
بورصة الفهرس (عروض الأسعار) | 4100650709078789802 |
InMobi | 7681903010231960328 |
InMobi (عروض الأسعار) | 6325663098072678541 |
InMobi Exchange (عروض الأسعار) | 5264320421916134407 |
IronSource | 6925240245545091930 |
إعلانات ironSource (عروض الأسعار) | 1643326773739866623 |
Leadbolt | 2899150749497968595 |
LG U+AD | 18298738678491729107 |
شبكة LINE Ads | 3025503711505004547 |
مايو | 7505118203095108657 |
مايو (عروض الأسعار) | 1343336733822567166 |
Media.net (عروض الأسعار) | 2127936450554446159 |
إعلانات للشركة نفسها المعتمَدة على التوسّط | 6060308706800320801 |
Meta Audience Network* * قبل 6 حزيران (يونيو) 2022، كان يُطلق على هذه الشبكة اسم "Facebook Audience Network". | 10568273599589928883 |
Meta Audience Network (عروض الأسعار)* * قبل 6 حزيران (يونيو) 2022، كان يُطلق على هذه الشبكة اسم "Facebook Audience Network (عروض الأسعار)". | 11198165126854996598 |
Mintegral | 1357746574408896200 |
Mintegral (عروض أسعار) | 6250601289653372374 |
MobFox | 8079529624516381459 |
MobFox (عروض الأسعار) | 3086513548163922365 |
MoPub (متوقّف نهائيًا) | 10872986198578383917 |
myTarget | 8450873672465271579 |
Nend | 9383070032774777750 |
Nexxen (عرض أسعار)* * قبل 1 مايو 2024، كان يُطلق على هذه الشبكة اسم "UnrulyX". | 2831998725945605450 |
ONE by AOL (Millennial Media) | 6101072188699264581 |
ONE by AOL (Nexage) | 3224789793037044399 |
OneTag Exchange (عروض الأسعار) | 4873891452523427499 |
OpenX (عروض الأسعار) | 4918705482605678398 |
عدسة Pangle | 4069896914521993236 |
Pangle (عروض الأسعار) | 3525379893916449117 |
PubMatic (عروض الأسعار) | 3841544486172445473 |
حملة إعلانية قائمة على الحجوزات | 7068401028668408324 |
RhythmOne (عروض الأسعار) | 2831998725945605450 |
Rubicon (عروض الأسعار) | 3993193775968767067 |
كوكب ساسكاتشوان | 734341340207269415 |
نسبة مشاركة الإعلان بالكامل (عروض الأسعار) | 5247944089976324188 |
Smaato (عروض الأسعار) | 3362360112145450544 |
Equativ (عروض الأسعار)* * قبل 12 كانون الثاني (يناير) 2023، كان يُطلق على هذه الشبكة اسم "خادم الإعلانات الذكي". | 5970199210771591442 |
Sonobi (عروض الأسعار) | 3270984106996027150 |
Tapjoy | 7295217276740746030 |
Tapjoy (عروض الأسعار) | 4692500501762622178 |
تينسنت GDT | 7007906637038700218 |
TripleLift (عروض الأسعار) | 8332676245392738510 |
إعلانات Unity | 4970775877303683148 |
Unity Ads (عروض الأسعار) | 7069338991535737586 |
شركة Verizon Media | 7360851262951344112 |
مجموعة Verve (عروض الأسعار) | 5013176581647059185 |
Vpon | 1940957084538325905 |
Liftoff Monetize* * قبل 30 كانون الثاني (يناير) 2023، كان يُطلق على هذه الشبكة اسم "Vungle". | 1953547073528090325 |
Liftoff Monetize (عروض الأسعار)* * قبل 30 كانون الثاني (يناير) 2023، كان يُطلق على هذه الشبكة اسم "التفاعل (عروض الأسعار)". | 4692500501762622185 |
الأرباح (عروض الأسعار) | 4193081836471107579 |
YieldOne (عروض الأسعار) | 3154533971590234104 |
Zucks | 5506531810221735863 |
مكافأة المستخدم
من المهم تحقيق التوازن بين تجربة المستخدم ومكافأة التحقق من الصحة عند اتخاذ القرار ومتى يتم مكافأة المستخدم. قد تواجه عمليات معاودة الاتصال من جهة الخادم تأخيرات قبل الوصول إلى الأنظمة الخارجية. وبالتالي، فإن أفضل ممارسة موصى بها هي استخدام معاودة الاتصال من جانب العميل لمكافأة المستخدم على الفور، أثناء إجراء التحقق من جميع المكافآت عند استلام استدعاءات من جانب الخادم. هذا النمط تجربة مستخدم جيدة مع ضمان صلاحية والمكافآت.
ومع ذلك، بالنسبة إلى التطبيقات التي تكون فيها صلاحية المكافأة أمرًا بالغ الأهمية (على سبيل المثال، تؤثر المكافآت في اقتصاد تطبيقك داخل اللعبة) ويحدث تأخير في منح المكافآت. مقبول، فقد يكون انتظار معاودة الاتصال التي تم التحقق منها من جانب الخادم هو الأفضل الخاص بك.
البيانات المخصّصة
يجب استخدام التطبيقات التي تتطلب بيانات إضافية في عمليات معاودة الاتصال لإثبات الملكية من جهة الخادم
ميزة البيانات المخصّصة للإعلانات التي تضم مكافأة. أي قيمة سلسلة تمّ تحديدها على إعلان يضم مكافأة
يتم تمرير الكائن إلى معلَمة طلب البحث custom_data
لمعاودة اتصال SSV. إذا كانت الإجابة "لا"
البيانات المخصّصة، ولن يتم تغيير قيمة معلَمة طلب البحث custom_data
الموجودة في معاودة اتصال SSV.
يوضح نموذج التعليمة البرمجية التالي كيفية تعيين خيارات SSV بعد تم تحميل إعلان يضم مكافأة.
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 } })
إذا كنت تريد ضبط سلسلة المكافأة المخصّصة، عليك إجراء ذلك قبل عرض الإعلان.
إثبات الملكية اليدوي لميزة "التحقّق بخطوتين" (SSV) التي تضم مكافأة
الخطوات التي ينفذها الصف 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
يوضح الرمز أدناه كيفية تحليل المحتوى للتحقق من عنوان URL لمعاودة الاتصال كمصفوفة 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 من عنوان URL لمعاودة الاتصال
باستخدام القيمة queryString
من الخطوة السابقة، حلِّل signature
key_id
مَعلمات طلب البحث من عنوان URL لمعاودة الاتصال كما هو موضّح أدناه:
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()));
إجراء عملية التحقّق
الخطوة الأخيرة هي التحقق من محتوى عنوان URL لمعاودة الاتصال باستخدام
المفتاح العام المناسب. خذ التعيين الذي تم إرجاعه من
parsePublicKeysJson
واستخدام المعلَمة key_id
من عملية معاودة الاتصال
عنوان URL المطلوب للحصول على المفتاح العام من عملية الربط هذه. ثم التحقق من التوقيع باستخدام
هذا المفتاح العام. يتم توضيح هذه الخطوات أدناه في طريقة 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);
}
}
إذا تم تنفيذ الطريقة بدون طرح استثناء، فإن عنوان URL لمعاودة الاتصال كان تم التحقق منها بنجاح.
الأسئلة الشائعة
- هل يمكنني التخزين المؤقت للمفتاح العام الذي يوفّره خادم إدارة مفاتيح AdMob؟
- ننصحك بتخزين المفتاح العام الذي يقدّمه مفتاح AdMob مؤقتًا. لخفض عدد العمليات المطلوبة للتحقق من صحة SSV مع معاودة الاتصال. ومع ذلك، يُرجى ملاحظة أنّه يتم تدوير المفاتيح العامة بانتظام ويجب عدم تدويرها تخزينه مؤقتًا لمدة تزيد عن 24 ساعة
- ما هو معدّل تكرار تبديل المفاتيح العامة التي يوفّرها خادم مفاتيح AdMob؟
- يتم تدوير المفاتيح العامة التي يوفّرها خادم مفاتيح AdMob على متغيّر. زمني للمشروع. لضمان استمرار عمل التحقُّق من عمليات معاودة الاتصال باستخدام ميزة "التحقُّق بخطوتين" المقصود، يجب ألّا يتم تخزين المفاتيح العامة مؤقتًا لمدة تزيد عن 24 ساعة.
- ماذا يحدث إذا تعذر الوصول إلى خادمي؟
- تتوقع Google رمز استجابة لحالة النجاح
HTTP 200 OK
من أجل إثبات الملكية من جانب الخادم (SSV) مع معاودة الاتصال. إذا تعذر الوصول إلى الخادم أو لم يقدم ستحاول Google إرسال استدعاءات SSV ما يصل إلى خمس مرات في فواصل مدتها ثانية واحدة - كيف يمكنني التحقّق من أنّ طلبات معاودة الاتصال من خلال ميزة إثبات الملكية (SSV) يتم إرسالها من Google؟
- يمكنك استخدام بحث نظام أسماء النطاقات العكسي للتحقّق من أنّ عمليات معاودة الاتصال بميزة SSV مصدرها Google.