如何在服务器上验证 Admob 奖励视频广告?
How to verify Admob Rewarded Video Ad on a server?
有没有办法验证服务器上的客户端 (OnAdRewarded) 是否观看了奖励视频广告?我可以与 Google Cloud Functions 进行任何集成吗?
我认为可以使用 admob admin SDK 验证客户端发送到服务器的令牌,但似乎不可能,我们只能在客户端验证广告。
暂时没有。根据我最近收集的信息,该功能已经处于封闭测试阶段一段时间了。我能找到的最后一次提及是在链接的讨论中,据推测来自 Google 的人说该功能将很快推出到 public。 post 是从 1 月 22 日开始的。
https://groups.google.com/forum/#!topic/google-admob-ads-sdk/weXTAGZfYQ8
现在可以使用 Server-Side Verification (SSV) Callbacks.
Server-side verification callbacks are URL requests, with query parameters expanded by Google, that are sent by Google to an external system to notify it that a user should be rewarded for interacting with a rewarded video ad. Rewarded video SSV (server-side verification) callbacks provide an extra layer of protection against spoofing of client-side callbacks to reward users.
如果你们在 Golang 上寻找 Admob SSV 的简单方法。
就用这个hiyali/go-lib-ssv,希望能救你一命:)
不确定这是否与 Firebase 相关,但这里有一些详细信息以防有人使用 Node / JS。您可以使用 Node 的内置 crypto
库。首先 fetch
来自 https://gstatic.com/admob/reward/verifier-keys.json
.
的可用 Google AdMob 验证程序密钥
然后您需要遍历返回的 JSON keys
数组并获取与 req.query.key_id
对应的 pem
public 密钥文件字符串您传入的 req.url
字符串的参数。
然后我们希望验证签名的“消息”是参数 ?
符号和 &signature...
字符串之间的传入 req.url
子字符串。
现在我们可以轻松验证:
const verifier = crypto.createVerify("sha256");
verifier.update(message);
if(verifier.verify(pem, req.query.signature, "base64"))
console.log("Ad was successfully verified.");
else
console.log("Ad could not be verified - quick call the cops !");
需要注意的一点是,您可能需要 unescape(...)
您的 req.url
字符串才能使用它,因为某些字符可能已被转义。我坚持了一两个小时。您可以使用例如Node 的内置 querystring
库。
我知道有点晚了,但这里有一段代码对我有帮助。对于 Node 用户,它在 javascript 中。
https://github.com/hypeben/admob-rewarded-ads-ssv
const queryString = require('query-string');
const crypto = require('crypto');
const axios = require('axios');
const GOOGLE_AD_KEY_URL = 'https://gstatic.com/admob/reward/verifier-keys.json';
/**
* Fetches the google public keys for the admob providers.
* These keys changes time to time.
*/
const getGoogleKeysMap = async () => {
let googleKeyRes = await axios.get(GOOGLE_AD_KEY_URL);
let {keys} = googleKeyRes.data;
if (!keys) {
throw new Error('No keys found from google keys');
}
/** For each of the keys array save it base 64 in decoded form in the key map */
let keyMap = {};
keys.forEach(k => {
keyMap[`${k.keyId}`] = crypto.createPublicKey(k.pem);
console.log(keyMap[`${k.keyId}`]);
});
return keyMap;
};
/**
* Verifies the callback url query params string,
* Resolves the promise if verification was successful, else fails.
* Wanna 'debug' then pass the second parameter as true.
* @param {String} queryUrl
* @param {Boolean} debug
*/
async function verify(queryUrl, debug) {
try {
if (typeof queryUrl !== "string") throw new TypeError("URL needs to be string!");
/**
* Request coming as callback from admob must contain the 'signature' and the 'user_id'.
* For more info https://developers.google.com/admob/android/rewarded-video-ssv
*/
const {signature, key_id} = queryString.parse(queryUrl);
if (!signature) {
throw new Error('No signature value exist in the URL param');
}
if(debug) {
console.debug('Signature and KeyId ---');
console.debug(signature, key_id);
// console.log('Signature and KeyId ---');
// console.log(signature, key_id);
}
let queryParamsString = queryUrl;
if (queryParamsString.indexOf('?') > -1) {
queryParamsString = queryUrl.split('?')[1];
}
if(debug) {
console.debug('Query param string ---');
// console.log('Query param string ---');
console.debug(queryParamsString);
// console.log(queryParamsString);
}
/**
* As per admob,
* The last two query parameters of rewarded video SSV callbacks are always signature and key_id, in that order.
* The remaining query parameters specify the content to be verified.
*/
let contentToVerify = queryParamsString.substring(0, queryParamsString.indexOf('signature') -1);
if(debug) {
console.debug('Content to verify ---');
// console.log(contentToVerify);
// console.log('Content to verify ---');
console.debug(contentToVerify);
}
let keyMap = await getGoogleKeysMap();
if(keyMap[`${key_id}`]) {
let publicKey = keyMap[`${key_id}`];
const verifier = crypto.createVerify('RSA-SHA256');
verifier.update(contentToVerify);
let result = verifier.verify(publicKey, signature, 'base64');
if (result) {
console.debug('Result ---');
console.debug(result);
return true;
} else {
console.debug('Failure ---');
console.debug(result);
throw new Error('Invalid Signature Supplied');
}
} else {
console.debug('Key id provided doesn\'t exist ---');
throw new Error('Key id provided doesn\'t exist in the google public keys');
}
} catch (error) {
}
}
module.exports.verify = verify;
有没有办法验证服务器上的客户端 (OnAdRewarded) 是否观看了奖励视频广告?我可以与 Google Cloud Functions 进行任何集成吗?
我认为可以使用 admob admin SDK 验证客户端发送到服务器的令牌,但似乎不可能,我们只能在客户端验证广告。
暂时没有。根据我最近收集的信息,该功能已经处于封闭测试阶段一段时间了。我能找到的最后一次提及是在链接的讨论中,据推测来自 Google 的人说该功能将很快推出到 public。 post 是从 1 月 22 日开始的。
https://groups.google.com/forum/#!topic/google-admob-ads-sdk/weXTAGZfYQ8
现在可以使用 Server-Side Verification (SSV) Callbacks.
Server-side verification callbacks are URL requests, with query parameters expanded by Google, that are sent by Google to an external system to notify it that a user should be rewarded for interacting with a rewarded video ad. Rewarded video SSV (server-side verification) callbacks provide an extra layer of protection against spoofing of client-side callbacks to reward users.
如果你们在 Golang 上寻找 Admob SSV 的简单方法。
就用这个hiyali/go-lib-ssv,希望能救你一命:)
不确定这是否与 Firebase 相关,但这里有一些详细信息以防有人使用 Node / JS。您可以使用 Node 的内置 crypto
库。首先 fetch
来自 https://gstatic.com/admob/reward/verifier-keys.json
.
然后您需要遍历返回的 JSON keys
数组并获取与 req.query.key_id
对应的 pem
public 密钥文件字符串您传入的 req.url
字符串的参数。
然后我们希望验证签名的“消息”是参数 ?
符号和 &signature...
字符串之间的传入 req.url
子字符串。
现在我们可以轻松验证:
const verifier = crypto.createVerify("sha256");
verifier.update(message);
if(verifier.verify(pem, req.query.signature, "base64"))
console.log("Ad was successfully verified.");
else
console.log("Ad could not be verified - quick call the cops !");
需要注意的一点是,您可能需要 unescape(...)
您的 req.url
字符串才能使用它,因为某些字符可能已被转义。我坚持了一两个小时。您可以使用例如Node 的内置 querystring
库。
我知道有点晚了,但这里有一段代码对我有帮助。对于 Node 用户,它在 javascript 中。 https://github.com/hypeben/admob-rewarded-ads-ssv
const queryString = require('query-string');
const crypto = require('crypto');
const axios = require('axios');
const GOOGLE_AD_KEY_URL = 'https://gstatic.com/admob/reward/verifier-keys.json';
/**
* Fetches the google public keys for the admob providers.
* These keys changes time to time.
*/
const getGoogleKeysMap = async () => {
let googleKeyRes = await axios.get(GOOGLE_AD_KEY_URL);
let {keys} = googleKeyRes.data;
if (!keys) {
throw new Error('No keys found from google keys');
}
/** For each of the keys array save it base 64 in decoded form in the key map */
let keyMap = {};
keys.forEach(k => {
keyMap[`${k.keyId}`] = crypto.createPublicKey(k.pem);
console.log(keyMap[`${k.keyId}`]);
});
return keyMap;
};
/**
* Verifies the callback url query params string,
* Resolves the promise if verification was successful, else fails.
* Wanna 'debug' then pass the second parameter as true.
* @param {String} queryUrl
* @param {Boolean} debug
*/
async function verify(queryUrl, debug) {
try {
if (typeof queryUrl !== "string") throw new TypeError("URL needs to be string!");
/**
* Request coming as callback from admob must contain the 'signature' and the 'user_id'.
* For more info https://developers.google.com/admob/android/rewarded-video-ssv
*/
const {signature, key_id} = queryString.parse(queryUrl);
if (!signature) {
throw new Error('No signature value exist in the URL param');
}
if(debug) {
console.debug('Signature and KeyId ---');
console.debug(signature, key_id);
// console.log('Signature and KeyId ---');
// console.log(signature, key_id);
}
let queryParamsString = queryUrl;
if (queryParamsString.indexOf('?') > -1) {
queryParamsString = queryUrl.split('?')[1];
}
if(debug) {
console.debug('Query param string ---');
// console.log('Query param string ---');
console.debug(queryParamsString);
// console.log(queryParamsString);
}
/**
* As per admob,
* The last two query parameters of rewarded video SSV callbacks are always signature and key_id, in that order.
* The remaining query parameters specify the content to be verified.
*/
let contentToVerify = queryParamsString.substring(0, queryParamsString.indexOf('signature') -1);
if(debug) {
console.debug('Content to verify ---');
// console.log(contentToVerify);
// console.log('Content to verify ---');
console.debug(contentToVerify);
}
let keyMap = await getGoogleKeysMap();
if(keyMap[`${key_id}`]) {
let publicKey = keyMap[`${key_id}`];
const verifier = crypto.createVerify('RSA-SHA256');
verifier.update(contentToVerify);
let result = verifier.verify(publicKey, signature, 'base64');
if (result) {
console.debug('Result ---');
console.debug(result);
return true;
} else {
console.debug('Failure ---');
console.debug(result);
throw new Error('Invalid Signature Supplied');
}
} else {
console.debug('Key id provided doesn\'t exist ---');
throw new Error('Key id provided doesn\'t exist in the google public keys');
}
} catch (error) {
}
}
module.exports.verify = verify;