إثبات الملكية من جهة الخادم

طلبات معاودة الاتصال لعملية تحقّق من جهة الخادم هي طلبات عناوين URL، مع توسيع معلمات طلب البحث من قِبل Google، وترسلها Google إلى نظام خارجي لإعلامه بأنّه يجب مكافأة المستخدم على التفاعل مع إعلان مقابل مكافأة أو إعلان بيني مقابل مكافأة. توفر عمليات التحقّق من جهة الخادم للإعلانات مقابل مكافأة مستوى إضافيًا من الحماية من انتحال طلبات معاودة الاتصال من جهة العميل لمكافأة المستخدمين.

يوضّح هذا الدليل كيفية التحقّق من طلبات معاودة الاتصال لإثبات الملكية من جهة الخادم للإعلانات مقابل مكافأة باستخدام مكتبة التشفير التابعة لجهة خارجية Tink Java Apps لضمان أنّ معامِلات طلب البحث في طلب معاودة الاتصال هي قيم مشروعة. على الرغم من استخدام Tink لأغراض هذا الدليل، يمكنك استخدام أي مكتبة تابعة لجهة خارجية تتوافق مع خوارزمية ECDSA. يمكنك أيضًا اختبار الخادم باستخدام أداة الاختبار في واجهة مستخدم AdMob.

.

المتطلبات الأساسية

استخدام RewardedAdsVerifier من مكتبة Tink Java Apps

يتضمّن مستودع Tink Java Apps على GitHub فئة مساعد RewardedAdsVerifier لتقليل الرمز البرمجي المطلوب للتحقّق من طلب معاودة الاتصال لإثبات الملكية من جهة الخادم للإعلانات مقابل مكافأة. يتيح لك استخدام هذه الفئة التحقّق من عنوان URL لطلب معاودة الاتصال باستخدام الرمز البرمجي التالي.

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

إذا تم تنفيذ طريقة verify() بدون ظهور استثناء، يعني ذلك أنّه تم التحقّق من عنوان URL لطلب معاودة الاتصال بنجاح. يوضّح قسم مكافأة المستخدمين أفضل الممارسات المتعلّقة بموعد مكافأة المستخدمين. للاطّلاع على تفاصيل الخطوات التي تتّبعها هذه الفئة للتحقّق من طلبات معاودة الاتصال لإثبات الملكية من جهة الخادم للإعلانات مقابل مكافأة، يمكنك الاطّلاع على قسم التحقّق اليدوي من طلبات معاودة الاتصال لإثبات الملكية من جهة الخادم للإعلانات مقابل مكافأة.

معامِلات طلب معاودة الاتصال لإثبات الملكية من جهة الخادم

تحتوي طلبات معاودة الاتصال لعملية التحقّق من جهة الخادم على معلمات طلب البحث التي تصف التفاعل مع الإعلان مقابل مكافأة. في ما يلي أسماء المعامِلات وأوصافها وأمثلة على قيمها. يتم إرسال المعامِلات بترتيب أبجدي.

اسم المَعلمة الوصف مثال على القيمة
ad_network معرّف مصدر الإعلان للمصدر الذي عرض هذا الإعلان ترد أسماء مصادر الإعلانات المقابلة لقيم المعرّفات في قسم معرّفات مصادر الإعلانات. 1953547073528090325
ad_unit رقم تعريف الوحدة الإعلانية على AdMob الذي تم استخدامه لطلب الإعلان مقابل مكافأة 2747237135
custom_data سلسلة البيانات المخصّصة كما يقدّمها customData.

إذا لم يقدّم التطبيق سلسلة بيانات مخصّصة، لن تظهر قيمة معلَمة طلب البحث هذه في طلب معاودة الاتصال لإثبات الملكية من جهة الخادم.

SAMPLE_CUSTOM_DATA_STRING
key_id المفتاح الذي سيتم استخدامه للتحقّق من طلب معاودة الاتصال لإثبات الملكية من جهة الخادم ترتبط هذه القيمة بمفتاح عام يقدّمه خادم مفاتيح AdMob. 1234567890
reward_amount مبلغ المكافأة كما هو محدّد في إعدادات الوحدة الإعلانية 5
reward_item عنصر المكافأة كما هو محدّد في إعدادات الوحدة الإعلانية عملات معدنية
signature توقيع طلب معاودة الاتصال لإثبات الملكية من جهة الخادم الذي أنشأته AdMob MEUCIQCLJS_s4ia_sN06HqzeW7Wc3nhZi4RlW3qV0oO-6AIYdQIgGJEh-rzKreO-paNDbSCzWGMtmgJHYYW9k2_icM9LFMY
timestamp الطابع الزمني لوقت مكافأة المستخدم بتنسيق وقت Epoch بالملّي ثانية 1507770365237823
transaction_id المعرّف الفريد المرمّز بنظام العدّ السداسي العشري لكل حدث من أحداث منح المكافآت التي أنشأتها AdMob 18fa792de1bca816048293fc71035638
user_id معرّف المستخدم كما يقدّمه userId.

إذا لم يقدّم التطبيق معرّف مستخدم، لن تظهر معلَمة طلب البحث هذه في طلب معاودة الاتصال لإثبات الملكية من جهة الخادم.

1234567

معرّفات مصادر الإعلانات

أسماء مصادر الإعلانات وأرقام تعريفها

اسم مصدر الإعلان رقم تعريف مصدر الإعلان
Ad Generation (عرض أسعار)1477265452970951479
شبكة AdMob5450213213286189855
العرض الإعلاني بدون انقطاع في شبكة AdMob1215381445328257950
AppLovin1063618907739174004
AppLovin (عرض أسعار)1328079684332308356
Bidease (عرض أسعار)3670825090829827805
BidMachine (عرض أسعار)7943972370566394673
Chartboost2873236629771172317
‫Chocolate Platform (عرض أسعار)6432849193975106527
حدث مخصّص18351550913290782395
‫DT Exchange*

* قبل 21 سبتمبر 2022، كانت هذه الشبكة تُعرف باسم "Fyber Marketplace".

2179455223494392917
‫DT Exchange (عرض أسعار)8189833498765234879
‫Equativ (عرض أسعار)*

* قبل 12 يناير 2023، كانت هذه الشبكة تُعرف باسم "Smart Adserver".

5970199210771591442
‫Fluct (عرض أسعار)8419777862490735710
i-mobile5208827440166355534
‫Improve Digital (عرض أسعار)159382223051638006
‫Index Exchange (عرض أسعار)4100650709078789802
InMobi7681903010231960328
‫InMobi (حزمة تطوير البرامج) (عرض أسعار)8468954295581492586
‫InMobi Exchange (عرض أسعار)5264320421916134407
ironSource Ads6925240245545091930
‫ironSource Ads (عرض أسعار)1643326773739866623
‫Liftoff Monetize*

* قبل 30 يناير 2023، كانت هذه الشبكة تُعرف باسم "Vungle".

1953547073528090325
‫Liftoff Monetize (عرض أسعار)*

* قبل 30 يناير 2023، كانت هذه الشبكة تُعرف باسم "Vungle (عرض أسعار)".

4692500501762622185
‫LY Ads Network3025503711505004547
‫LY Ads Network (عرض أسعار)2615812619460460513
‫Magnite DV+ (عرض أسعار)3993193775968767067
maio7505118203095108657
‫Media.net (عرض أسعار)2127936450554446159
الإعلانات الترويجية المشتركة التي تعتمد على التوسّط6060308706800320801
‫Meta Audience Network*

* قبل 6 يونيو 2022، كانت هذه الشبكة تُعرف باسم "Facebook Audience Network".

10568273599589928883
‫Meta Audience Network (عرض أسعار)*

* قبل 6 يونيو 2022، كانت هذه الشبكة تُعرف باسم "Facebook Audience Network (عرض أسعار)".

11198165126854996598
Mintegral1357746574408896200
‫Mintegral (عرض أسعار)6250601289653372374
‫Mobfox (عرض أسعار)3086513548163922365
‫MobileFuse (عرض أسعار)7303547408604090310
‫Moloco Ads SDK (عرض أسعار)8267622065755668722
myTarget8450873672465271579
‫Nativo (عرض أسعار)3240503836211327896
‫Nexxen (عرض أسعار)*

* قبل 1 مايو 2024، كانت هذه الشبكة تُعرف باسم "UnrulyX".

2831998725945605450
‫OneTag Exchange (عرض أسعار)4873891452523427499
‫OpenX (عرض أسعار)4918705482605678398
Pangle4069896914521993236
‫Pangle KR SDK (عرض أسعار)12171279046073404914
‫Pangle ROW SDK (عرض أسعار)3525379893916449117
‫Pangle US SDK (عرض أسعار)15999446638585856012
‫PubMatic (عرض أسعار)3841544486172445473
حزمة تطوير البرامج (SDK) الخاصة بمنصة PubMatic OpenWrap7702975372504485373
حزمة SDK الخاصة بمنصة PubMatic OpenWrap (عرض أسعار)1234567890123456789
حملة قائمة على الحجز7068401028668408324
‫Rise (عرض أسعار)6816468518946650043
‫Sharethrough (عرض أسعار)5247944089976324188
‫Smaato (عرض أسعار)3362360112145450544
‫Sonobi (عرض أسعار)3270984106996027150
‫TripleLift (عرض أسعار)8332676245392738510
Unity Ads4970775877303683148
‫Unity Ads (عرض أسعار)7069338991535737586
‫Verve Group (عرض أسعار)5013176581647059185
Vpon1940957084538325905
‫Yieldmo (عرض أسعار)4193081836471107579
‫YieldOne (عرض أسعار)3154533971590234104
Zucks5506531810221735863

مكافأة المستخدم

من المهم تحقيق التوازن بين تجربة المستخدم والتحقّق من صحة المكافأة عند تحديد موعد مكافأة المستخدم. قد تواجه طلبات معاودة الاتصال من جهة الخادم تأخيرات قبل الوصول إلى الأنظمة الخارجية. لذلك، ننصحك باستخدام طلب معاودة الاتصال من جهة العميل لمكافأة المستخدم على الفور، مع إجراء عملية التحقّق من صحة جميع المكافآت عند تلقّي طلبات معاودة الاتصال من جهة الخادم. يوفّر هذا النهج تجربة جيدة للمستخدم مع ضمان صحة المكافآت الممنوحة.

مع ذلك، بالنسبة إلى التطبيقات التي تكون فيها صحة المكافأة أمرًا بالغ الأهمية (على سبيل المثال، إذا كانت المكافأة تؤثر في الاقتصاد داخل اللعبة في تطبيقك) وكانت التأخيرات في منح المكافآت مقبولة، قد يكون الانتظار إلى حين تلقّي طلب معاودة الاتصال من جهة الخادم الذي تم التحقّق منه هو أفضل نهج.

البيانات المخصّصة

يجب أن تستخدم التطبيقات التي تتطلّب بيانات إضافية في طلبات معاودة الاتصال لعملية تحقّق من جهة الخادم ميزة البيانات المخصّصة للإعلانات مقابل مكافأة. يتم تمرير أي قيمة سلسلة يتم ضبطها على عنصر إعلان مقابل مكافأة إلى معلَمة طلب البحث custom_data في طلب معاودة الاتصال لإثبات الملكية من جهة الخادم. إذا لم يتم ضبط قيمة بيانات مخصّصة، لن تظهر قيمة معلَمة طلب البحث custom_data في طلب معاودة الاتصال لإثبات الملكية من جهة الخادم.

يضبط المثال التالي خيارات طلب معاودة الاتصال لإثبات الملكية من جهة الخادم بعد تحميل الإعلان مقابل مكافأة:

RewardedAd.load(
  adUnitId: "_adUnitId",
  request: AdRequest(),
  rewardedAdLoadCallback: RewardedAdLoadCallback(
    onAdLoaded: (ad) {
      ServerSideVerificationOptions _options =
          ServerSideVerificationOptions(
            customData: 'SAMPLE_CUSTOM_DATA_STRING',
          );
      ad.setServerSideOptions(_options);
      _rewardedAd = ad;
    },
    onAdFailedToLoad: (error) {},
  ),
);

استبدِل SAMPLE_CUSTOM_DATA_STRING ببياناتك المخصّصة.

إذا أردت ضبط سلسلة المكافأة المخصّصة، عليك إجراء ذلك قبل عرض الإعلان.

التحقّق اليدوي من طلب معاودة الاتصال لإثبات الملكية من جهة الخادم للإعلانات مقابل مكافأة

في ما يلي الخطوات التي تتّبعها فئة RewardedAdsVerifier للتحقّق من طلب معاودة الاتصال لإثبات الملكية من جهة الخادم للإعلانات مقابل مكافأة. على الرغم من أنّ مقتطفات الرموز البرمجية المضمّنة مكتوبة بلغة Java و تستخدِم مكتبة Tink التابعة لجهة خارجية، يمكنك تنفيذ هذه الخطوات باللغة التي تختارها، باستخدام أي مكتبة تابعة لجهة خارجية تتوافق مع ECDSA.

جلب المفاتيح العامة

للتحقّق من طلب معاودة الاتصال لإثبات الملكية من جهة الخادم للإعلانات مقابل مكافأة، تحتاج إلى مفتاح عام يقدّمه AdMob.

يمكن جلب قائمة بالمفاتيح العامة التي سيتم استخدامها للتحقّق من صحة طلبات معاودة الاتصال لإثبات الملكية من جهة الخادم للإعلانات مقابل مكافأة من خادم مفاتيح 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;
}

الحصول على المحتوى الذي سيتم التحقّق منه

آخر معلَمتَي طلب بحث في طلبات معاودة الاتصال لإثبات الملكية من جهة الخادم للإعلانات مقابل مكافأة هما دائمًا signature و key_id, بهذا الترتيب. تحدّد معامِلات طلب البحث المتبقية المحتوى الذي سيتم التحقّق منه. لنفترض أنّك ضبطت AdMob لإرسال طلبات معاودة الاتصال بالمكافأة إلى https://www.myserver.com/mypath. يعرض المقتطف أدناه مثالاً على طلب معاودة الاتصال لإثبات الملكية من جهة الخادم للإعلانات مقابل مكافأة مع تمييز المحتوى الذي سيتم التحقّق منه.

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

يوضّح الرمز البرمجي أدناه كيفية تحليل المحتوى الذي سيتم التحقّق منه من عنوان 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 مؤقتًا لتقليل عدد العمليات المطلوبة للتحقّق من صحة طلبات معاودة الاتصال لإثبات الملكية من جهة الخادم. مع ذلك، يُرجى العِلم أنّه يتم تغيير المفاتيح العامة بانتظام ويجب عدم تخزينها مؤقتًا لأكثر من 24 ساعة.
ما هو معدّل تغيير المفاتيح العامة التي يقدّمها خادم مفاتيح AdMob؟
يتم تغيير المفاتيح العامة التي يقدّمها خادم مفاتيح AdMob وفقًا لجدول زمني متغيّر. لضمان استمرار عمل التحقّق من صحة طلبات معاودة الاتصال لإثبات الملكية من جهة الخادم على النحو المطلوب، يجب عدم تخزين المفاتيح العامة مؤقتًا لأكثر من 24 ساعة.
ماذا يحدث إذا تعذّر الوصول إلى الخادم؟
تتوقّع Google رمز استجابة لحالة النجاح HTTP 200 OK لطلبات معاودة الاتصال لإثبات الملكية من جهة الخادم. إذا تعذّر الوصول إلى الخادم أو لم يقدّم الاستجابة المتوقّعة، ستعيد Google محاولة إرسال طلبات معاودة الاتصال لإثبات الملكية من جهة الخادم حتى خمس مرّات على فترات زمنية مدّتها ثانية واحدة.
كيف يمكنني التأكّد من أنّ طلبات معاودة الاتصال لإثبات الملكية من جهة الخادم واردة من Google؟
استخدِم بحث نظام أسماء النطاقات العكسي للتأكّد من أنّ طلبات معاودة الاتصال لإثبات الملكية من جهة الخادم واردة من Google.

إنّ محتوى هذه الصفحة مرخّص بموجب ترخيص Creative Commons Attribution 4.0‏ ما لم يُنصّ على خلاف ذلك، ونماذج الرموز مرخّصة بموجب ترخيص Apache 2.0‏. للاطّلاع على التفاصيل، يُرجى مراجعة سياسات موقع Google Developers‏. إنّ Java هي علامة تجارية مسجَّلة لشركة Oracle و/أو شركائها التابعين.

تاريخ التعديل الأخير: 2026-09-09 (حسب التوقيت العالمي المتفَّق عليه)