عمليات استدعاء إثبات الملكية من جانب الخادم هي طلبات عناوين URL، مع مَعلمات طلب البحث بواسطة Google، والتي ترسلها Google إلى نظام خارجي وإشعاره بأنه ينبغي أن يحصل المستخدم على مكافأة مقابل التفاعل مع إعلان إعلان بيني يضم مكافأة طلبات معاودة الاتصال الخاصة بميزة "إثبات الملكية من جهة الخادم" بمكافأة توفير طبقة حماية إضافية ضد انتحال المكالمات من جهة العميل لمكافأة المستخدمين.
يوضح لك هذا الدليل كيفية التحقّق من استدعاءات SSV بمكافأة باستخدام Tink Java Apps التابعة لجهات خارجية للتأكد من أن معاملات الاستعلام في عملية الاستدعاء القيم المشروعة. ورغم استخدام Tink لأغراض هذا الدليل، يمكنك استخدام أي مكتبة تابعة لجهة خارجية ECDSA: يمكنك أيضًا اختبار خادمك باستخدام أداة الاختبار في واجهة مستخدم AdMob.
تحقق من هذا البرنامج الذي يعمل بشكل كامل مثال باستخدام حذاء الربيع لـ Java.
المتطلبات الأساسية
دمج الإعلانات بمكافأة في تطبيق للأجهزة الجوّالة مع الإصدار 3.12.0 أو إصدار أحدث من المكوّن الإضافي Unity لإعلانات 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 |
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 |
معرّفات مصادر الإعلانات
أسماء مصادر الإعلانات وأرقام تعريفها
广告来源名称 | 广告来源 ID |
---|---|
Aarki(出价) | 5240798063227064260 |
Ad Generation(出价) | 1477265452970951479 |
AdColony | 15586990674969969776 |
AdColony(非 SDK)(出价) | 4600416542059544716 |
AdColony(出价) | 6895345910719072481 |
AdFalcon | 3528208921554210682 |
AdMob 广告联盟 | 5450213213286189855 |
AdMob 广告联盟广告瀑布流 | 1215381445328257950 |
ADResult | 10593873382626181482 |
AMoAd | 17253994435944008978 |
AppLovin | 1063618907739174004 |
AppLovin(出价) | 1328079684332308356 |
Chartboost | 2873236629771172317 |
Chocolate Platform(出价) | 6432849193975106527 |
跨渠道 (MdotM) | 9372067028804390441 |
自定义事件 | 18351550913290782395 |
DT Exchange* * 在 2022 年 9 月 21 日之前,该广告联盟称为“Fyber Marketplace”。 | 2179455223494392917 |
EMX(出价) | 8497809869790333482 |
Fluct(出价) | 8419777862490735710 |
小风 | 3376427960656545613 |
Fyber* * 此广告来源用于生成历史报告。 | 4839637394546996422 |
i-mobile | 5208827440166355534 |
优化数字化(出价) | 159382223051638006 |
Index Exchange(出价) | 4100650709078789802 |
InMobi | 7681903010231960328 |
InMobi(出价) | 6325663098072678541 |
InMobi Exchange(出价) | 5264320421916134407 |
IronSource | 6925240245545091930 |
ironSource Ads(出价) | 1643326773739866623 |
Leadbolt | 2899150749497968595 |
LG U+AD | 18298738678491729107 |
LINE 广告联盟 | 3025503711505004547 |
maio | 7505118203095108657 |
maio(出价) | 1343336733822567166 |
Media.net(出价) | 2127936450554446159 |
参与中介的自家广告 | 6060308706800320801 |
Meta Audience Network* * 在 2022 年 6 月 6 日之前,该广告联盟称为“Facebook Audience Network”。 | 10568273599589928883 |
Meta Audience Network(出价)* * 在 2022 年 6 月 6 日之前,该广告联盟称为“Facebook Audience Network(出价)”。 | 11198165126854996598 |
Mintegral | 1357746574408896200 |
Mintegral(出价) | 6250601289653372374 |
MobFox | 8079529624516381459 |
MobFox(出价) | 3086513548163922365 |
MoPub(已弃用) | 10872986198578383917 |
myTarget | 8450873672465271579 |
Nend | 9383070032774777750 |
Nexxen(出价)* * 在 2024 年 5 月 1 日之前,该广告联盟称为“UnrulyX”。 | 2831998725945605450 |
ONE by AOL (Millennial Media) | 6101072188699264581 |
ONE by AOL (Nexage) | 3224789793037044399 |
OneTag Exchange(出价) | 4873891452523427499 |
OpenX(出价) | 4918705482605678398 |
邦格尔 | 4069896914521993236 |
Pangle(出价) | 3525379893916449117 |
PubMatic(出价) | 3841544486172445473 |
预订型广告系列 | 7068401028668408324 |
RhythmOne(出价) | 2831998725945605450 |
Rubicon(出价) | 3993193775968767067 |
SK 星球 | 734341340207269415 |
Sharethrough(出价) | 5247944089976324188 |
Smaato(出价) | 3362360112145450544 |
Equativ(出价)* * 在 2023 年 1 月 12 日之前,该广告联盟称为“Smart Adserver”。 | 5970199210771591442 |
Sonobi(出价) | 3270984106996027150 |
Tapjoy | 7295217276740746030 |
Tapjoy(出价) | 4692500501762622178 |
Tencent GDT | 7007906637038700218 |
TripleLift(出价) | 8332676245392738510 |
Unity 广告 | 4970775877303683148 |
Unity Ads(出价) | 7069338991535737586 |
Verizon Media | 7360851262951344112 |
Verve Group(出价) | 5013176581647059185 |
Vpon | 1940957084538325905 |
Liftoff Monetize* * 在 2023 年 1 月 30 日之前,该广告联盟称为“Vungle”。 | 1953547073528090325 |
Liftoff Monetize(出价)* * 在 2023 年 1 月 30 日之前,该广告联盟称为“Vungle(出价)”。 | 4692500501762622185 |
Yieldmo(出价) | 4193081836471107579 |
YieldOne(出价) | 3154533971590234104 |
Zucks | 5506531810221735863 |
مكافأة المستخدم
من المهم تحقيق التوازن بين تجربة المستخدم ومكافأة التحقق من الصحة عند اتخاذ القرار ومتى يتم مكافأة المستخدم. قد تواجه عمليات معاودة الاتصال من جهة الخادم تأخيرات قبل الوصول إلى الأنظمة الخارجية. وبالتالي، فإن أفضل ممارسة موصى بها هي استخدام معاودة الاتصال من جانب العميل لمكافأة المستخدم على الفور، أثناء إجراء التحقق من جميع المكافآت عند استلام استدعاءات من جانب الخادم. هذا النمط تجربة مستخدم جيدة مع ضمان صلاحية والمكافآت.
ومع ذلك، بالنسبة إلى التطبيقات التي تكون فيها صلاحية المكافأة أمرًا بالغ الأهمية (على سبيل المثال، تؤثر المكافآت في اقتصاد تطبيقك داخل اللعبة) ويحدث تأخير في منح المكافآت. مقبول، فقد يكون انتظار معاودة الاتصال التي تم التحقق منها من جانب الخادم هو الأفضل الخاص بك.
البيانات المخصّصة
يجب استخدام التطبيقات التي تتطلب بيانات إضافية في عمليات معاودة الاتصال لإثبات الملكية من جهة الخادم
ميزة البيانات المخصّصة للإعلانات التي تضم مكافأة. أي قيمة سلسلة تمّ تحديدها على إعلان يضم مكافأة
يتم تمرير الكائن إلى معلَمة طلب البحث custom_data
لمعاودة اتصال SSV. إذا كانت الإجابة "لا"
البيانات المخصّصة، ولن يتم تغيير قيمة معلَمة طلب البحث custom_data
الموجودة في معاودة اتصال SSV.
يوضح نموذج التعليمة البرمجية التالي كيفية تعيين خيارات SSV بعد تم تحميل إعلان يضم مكافأة.
private void LoadRewardedAd(string adUnitId)
{
// Send the request to load the ad.
AdRequest adRequest = new AdRequest();
RewardedAd.Load(adUnitId, adRequest, (RewardedAd rewardedAd, LoadAdError error) =>
{
// If the operation failed with a reason.
if (error != null)
{
Debug.LogError("Rewarded ad failed to load an ad with error : " + error);
return;
}
var options = new ServerSideVerificationOptions
.Builder()
.SetCustomData("SAMPLE_CUSTOM_DATA_STRING")
.Build()
rewardedAd.SetServerSideVerificationOptions(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;
}
طلب التحقق من المحتوى
دائمًا ما تكون آخر مَعلمتَي طلب بحث لاستدعاءات 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.