عمليات معاودة الاتصال لعملية التحقّق من جهة الخادم هي طلبات عناوين URL، مع معلمات طلب البحث التي توسّعها Google، والتي ترسلها Google إلى نظام خارجي لإعلامه بأنّه يجب مكافأة المستخدم على التفاعل مع "إعلان مقابل مكافأة" أو "إعلان بيني مقابل مكافأة". توفّر عمليات معاودة الاتصال من جهة الخادم (SSV) للإعلانات التي تضم مكافأة طبقة إضافية من الحماية ضد انتحال عمليات معاودة الاتصال من جهة العميل لمكافأة المستخدمين.
يوضّح لك هذا الدليل كيفية التحقّق من عمليات معاودة الاتصال من جهة الخادم (SSV) لـ "الإعلانات مقابل مكافأة" باستخدام مكتبة التشفير التابعة لجهة خارجية Tink Java Apps لضمان أنّ مَعلمات طلب البحث في عملية معاودة الاتصال هي قيم مشروعة. على الرغم من استخدام Tink لأغراض هذا الدليل، لديك خيار استخدام أي مكتبة تابعة لجهة خارجية تتيح استخدام ECDSA. يمكنك أيضًا اختبار الخادم باستخدام أداة الاختبار في واجهة مستخدم AdMob.
المتطلبات الأساسية
- فعِّل عملية التحقّق من جهة الخادم للإعلانات مقابل مكافأة في وحدتك الإعلانية.
استخدام RewardedAdsVerifier من مكتبة تطبيقات Tink Java
يتضمّن مستودع GitHub تطبيقات Tink Java فئة مساعدة RewardedAdsVerifier لتقليل الرمز البرمجي المطلوب للتحقّق من طلب معاودة الاتصال للتحقّق من جانب الخادم (SSV) بمكافأة.
يتيح لك استخدام هذه الفئة التحقّق من عنوان 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 | سلسلة بيانات مخصّصة يوفّرها
customRewardString.
إذا لم يوفّر التطبيق سلسلة بيانات مخصّصة، لن تظهر قيمة مَعلمة طلب البحث هذه في طلب معاودة الاتصال للتحقّق من صحة الخادم. |
SAMPLE_CUSTOM_DATA_STRING |
| key_id | المفتاح الذي سيتم استخدامه للتحقّق من معاودة الاتصال من خلال ميزة "التحقّق من صحة العرض". تتوافق هذه القيمة مع مفتاح عام يوفّره خادم مفاتيح AdMob. | 1234567890 |
| reward_amount | مبلغ المكافأة كما هو محدّد في إعدادات الوحدة الإعلانية | 5 |
| reward_item | عنصر المكافأة كما هو محدّد في إعدادات الوحدة الإعلانية | عملات معدنية |
| التوقيع | توقيع لعملية معاودة الاتصال للتحقّق من صحة عرض الإعلانات من إنشاء AdMob | MEUCIQCLJS_s4ia_sN06HqzeW7Wc3nhZi4RlW3qV0oO-6AIYdQIgGJEh-rzKreO-paNDbSCzWGMtmgJHYYW9k2_icM9LFMY |
| timestamp | الطابع الزمني لوقت حصول المستخدم على المكافأة بتنسيق Epoch بالمللي ثانية | 1507770365237823 |
| transaction_id | معرّف فريد بترميز سداسي عشري لكل حدث منح مكافأة ينشئه AdMob. | 18fa792de1bca816048293fc71035638 |
| user_id | معرّف المستخدم كما هو مقدَّم من قِبل
userIdentifier.
إذا لم يقدّم التطبيق معرّف مستخدم، لن تظهر معلَمة طلب البحث هذه في معاودة الاتصال للتحقّق من صحة عرض الإعلان على الجهاز فقط. |
1234567 |
معرّفات مصادر الإعلانات
أسماء مصادر الإعلانات وأرقام تعريفها
| اسم مصدر الإعلان | رقم تعريف مصدر الإعلان |
|---|---|
| Ad Generation (عروض الأسعار) | 1477265452970951479 |
| شبكة AdMob | 5450213213286189855 |
| العرض الإعلاني بدون انقطاع في "شبكة AdMob" | 1215381445328257950 |
| AppLovin | 1063618907739174004 |
| AppLovin (عروض أسعار) | 1328079684332308356 |
| Bidease (عروض أسعار) | 3670825090829827805 |
| BidMachine (عروض أسعار) | 7943972370566394673 |
| Chartboost | 2873236629771172317 |
| Chocolate Platform (عروض الأسعار) | 6432849193975106527 |
| حدث مخصّص | 18351550913290782395 |
| DT Exchange* * قبل 21 سبتمبر 2022، كانت هذه الشبكة تُعرف باسم "Fyber Marketplace". | 2179455223494392917 |
| DT Exchange (عروض الأسعار) | 8189833498765234879 |
| Equativ (عرض أسعار)* * قبل 12 يناير 2023، كانت هذه الشبكة تُعرف باسم "Smart Adserver". | 5970199210771591442 |
| Fluct (bidding) | 8419777862490735710 |
| i-mobile | 5208827440166355534 |
| Improve Digital (عروض الأسعار) | 159382223051638006 |
| Index Exchange (عروض الأسعار) | 4100650709078789802 |
| InMobi | 7681903010231960328 |
| InMobi (حزمة تطوير البرامج) (عروض أسعار) | 8468954295581492586 |
| InMobi Exchange (عروض أسعار) | 5264320421916134407 |
| ironSource Ads | 6925240245545091930 |
| ironSource Ads (عروض الأسعار) | 1643326773739866623 |
| Liftoff Monetize* * قبل 30 يناير 2023، كانت هذه الشبكة تُعرف باسم "Vungle". | 1953547073528090325 |
| Liftoff Monetize (عروض الأسعار)* * قبل 30 يناير 2023، كانت هذه الشبكة تُعرف باسم "Vungle (عروض الأسعار)". | 4692500501762622185 |
| LY Ads Network | 3025503711505004547 |
| شبكة إعلانات LY (عروض الأسعار) | 2615812619460460513 |
| Magnite DV+ (عروض الأسعار) | 3993193775968767067 |
| maio | 7505118203095108657 |
| 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 (عروض أسعار) | 3086513548163922365 |
| MobileFuse (عروض أسعار) | 7303547408604090310 |
| حزمة تطوير البرامج (SDK) لعرض الإعلانات من Moloco (عروض الأسعار) | 8267622065755668722 |
| myTarget | 8450873672465271579 |
| Nativo (عروض أسعار) | 3240503836211327896 |
| Nexxen (عروض الأسعار)* * قبل 1 مايو 2024، كانت هذه الشبكة تُعرف باسم "UnrulyX". | 2831998725945605450 |
| OneTag Exchange (عروض الأسعار) | 4873891452523427499 |
| OpenX (عرض أسعار) | 4918705482605678398 |
| Pangle | 4069896914521993236 |
| حزمة تطوير البرامج (SDK) لـ Pangle KR (عرض أسعار) | 12171279046073404914 |
| Pangle ROW SDK (عروض الأسعار) | 3525379893916449117 |
| Pangle US SDK (عروض الأسعار) | 15999446638585856012 |
| PubMatic (عروض أسعار) | 3841544486172445473 |
| حزمة تطوير البرامج (SDK) الخاصة بمنصة PubMatic OpenWrap | 7702975372504485373 |
| حزمة تطوير البرامج (SDK) الخاصة بمنصة PubMatic OpenWrap (عروض الأسعار) | 1234567890123456789 |
| حملة قائمة على الحجز | 7068401028668408324 |
| Rise (عروض الأسعار) | 6816468518946650043 |
| Sharethrough (عروض الأسعار) | 5247944089976324188 |
| Smaato (عروض أسعار) | 3362360112145450544 |
| Sonobi (عروض أسعار) | 3270984106996027150 |
| TripleLift (عروض أسعار) | 8332676245392738510 |
| Unity Ads | 4970775877303683148 |
| Unity Ads (عروض أسعار) | 7069338991535737586 |
| Verve Group (عروض الأسعار) | 5013176581647059185 |
| Vpon | 1940957084538325905 |
| Yieldmo (عروض الأسعار) | 4193081836471107579 |
| YieldOne (عروض أسعار) | 3154533971590234104 |
| Zucks | 5506531810221735863 |
مكافأة المستخدم
من المهم تحقيق التوازن بين تجربة المستخدم والتحقّق من صحة المكافأة عند تحديد وقت منح المكافأة للمستخدم. قد تتأخر عمليات معاودة الاتصال من جهة الخادم قبل الوصول إلى الأنظمة الخارجية. لذلك، فإن أفضل الممارسات الموصى بها هي استخدام عملية الاستدعاء من جهة العميل لمكافأة المستخدم على الفور، أثناء إجراء التحقق من صحة جميع المكافآت عند استلام عمليات الاستدعاء من جهة الخادم. يوفّر هذا النهج تجربة جيدة للمستخدم مع ضمان صلاحية المكافآت الممنوحة.
ومع ذلك، بالنسبة إلى التطبيقات التي تكون فيها صلاحية المكافأة أمرًا بالغ الأهمية (على سبيل المثال، تؤثر المكافأة في اقتصاد اللعبة داخل التطبيق) ويكون التأخير في منح المكافآت مقبولاً، قد يكون انتظار معاودة الاتصال التي تم التحقّق منها من جهة الخادم هو أفضل نهج.
البيانات المخصّصة
يجب أن تستخدم التطبيقات التي تتطلّب بيانات إضافية في عمليات معاودة الاتصال الخاصة بعملية التحقّق من جهة الخادم ميزة البيانات المخصّصة في "الإعلانات مقابل مكافأة". يتم تمرير أي قيمة سلسلة تم ضبطها على عنصر "إعلان مقابل مكافأة" إلى مَعلمة طلب البحث custom_data لطلب معاودة الاتصال من خلال ميزة SSV. في حال عدم ضبط قيمة بيانات مخصّصة، لن تظهر قيمة مَعلمة طلب البحث custom_data في طلب معاودة الاتصال للتحقّق من صحة الخادم.
يضبط المثال التالي خيارات التحقّق من جهة الخادم بعد تحميل الإعلان مقابل مكافأة:
Swift
RewardedAd.load(with:"AD_UNIT_ID", request: request, completionHandler: { [self] ad, error in if let error != error { rewardedAd = ad let options = ServerSideVerificationOptions() options.customRewardString = "SAMPLE_CUSTOM_DATA_STRING" rewardedAd.serverSideVerificationOptions = options } })
Objective-C
GADRequest *request = [GADRequest request]; [GADRewardedAd loadWithAdUnitID:@"AD_UNIT_ID" request:request completionHandler:^(GADRewardedAd *ad, NSError *error) { if (error) { // Handle Error return; } self.rewardedAd = ad; GADServerSideVerificationOptions *options = [[GADServerSideVerificationOptions alloc] init]; options.customRewardString = @"SAMPLE_CUSTOM_DATA_STRING"; ad.serverSideVerificationOptions = options; }];
التحقّق يدويًا من ميزة "التحقّق من جهة الخادم" (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;
}
الحصول على محتوى للتحقّق منه
تكون آخر مَعلمتَي طلب بحث لعمليات معاودة الاتصال من خلال ميزة "التحقّق من صحة عرض الإعلان" للإعلانات التي تضم مكافآت دائمًا 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 مؤقتًا لتقليل عدد العمليات المطلوبة للتحقّق من صحة عمليات معاودة الاتصال للتحقّق من صحة العرض من جهة الخادم. ومع ذلك، يُرجى العِلم أنّه يتم تدوير المفاتيح العامة بانتظام ولا يجب تخزينها مؤقتًا لأكثر من 24 ساعة.
- ما هو معدّل تكرار تبديل المفاتيح العامة التي يوفّرها خادم مفاتيح AdMob؟
- يتم استبدال المفاتيح العامة التي يوفّرها خادم مفاتيح AdMob وفقًا لجدول زمني متغيّر. لضمان استمرار عمل عمليات التحقّق من عمليات معاودة الاتصال للتحقّق من جانب الخادم على النحو المنشود، يجب عدم تخزين المفاتيح العامة مؤقتًا لأكثر من 24 ساعة.
- ماذا يحدث إذا تعذّر الوصول إلى الخادم؟
- تتوقّع Google تلقّي رمز استجابة الحالة
HTTP 200 OKالذي يشير إلى نجاح عمليات معاودة الاتصال للتحقّق من صحة الخادم. إذا تعذّر الوصول إلى الخادم أو لم يقدّم الاستجابة المتوقّعة، ستعيد Google محاولة إرسال عمليات معاودة الاتصال للتحقّق من صحة الجلسة حتى خمس مرات على فترات زمنية مدتها ثانية واحدة. - كيف يمكنني التحقّق من أنّ عمليات معاودة الاتصال لعمليات التحقّق من صحة الخادم واردة من Google؟
- استخدِم بحث نظام أسماء النطاقات العكسي للتحقّق من أنّ عمليات معاودة الاتصال للتحقّق من صحة عرض الإعلانات على مستوى الخادم صادرة من Google.