Les rappels de validation côté serveur sont des requêtes d'URL, avec des paramètres de requête développés par Google, qui sont envoyées par Google à un système externe pour l'informer qu'un utilisateur doit être récompensé pour avoir interagi avec une annonce vidéo avec récompense ou une annonce interstitielle avec récompense. Les rappels de validation côté serveur pour les annonces avec récompense offrent une protection supplémentaire contre l'usurpation des rappels côté client pour récompenser les utilisateurs.
Ce guide vous explique comment valider les rappels SSV avec récompense à l'aide de la bibliothèque cryptographique tierce Tink Java Apps pour vous assurer que les paramètres de requête du rappel sont des valeurs légitimes. Bien que Tink soit utilisé dans ce guide, vous pouvez utiliser n'importe quelle bibliothèque tierce compatible avec ECDSA. Vous pouvez également tester votre serveur avec l'outil de test dans l'UI AdMob.
Prérequis
- Activez la validation côté serveur des récompenses sur votre bloc d'annonces.
Utiliser RewardedAdsVerifier à partir de la bibliothèque Tink Java Apps
Le dépôt GitHub Tink Java Apps inclut une classe d'assistance RewardedAdsVerifier
pour réduire le code requis pour valider un rappel SSV avec récompense.
Cette classe vous permet de valider une URL de rappel avec le code suivant.
RewardedAdsVerifier verifier = new RewardedAdsVerifier.Builder()
.fetchVerifyingPublicKeysWith(
RewardedAdsVerifier.KEYS_DOWNLOADER_INSTANCE_PROD)
.build();
String rewardUrl = ...;
verifier.verify(rewardUrl);
Si la méthode verify()
s'exécute sans générer d'exception, l'URL de rappel a été validée. La section Récompenser l'utilisateur décrit les bonnes pratiques concernant le moment où les utilisateurs doivent être récompensés. Pour obtenir une description détaillée des étapes effectuées par cette classe pour valider les rappels SSV avec récompense, vous pouvez consulter la section Validation manuelle des rappels SSV avec récompense.
Paramètres de rappel SSV
Les rappels de validation côté serveur contiennent des paramètres de requête qui décrivent l'interaction avec l'annonce avec récompense. Vous trouverez ci-dessous les noms, les descriptions et des exemples de valeurs pour ces paramètres. Les paramètres sont envoyés par ordre alphabétique.
Nom du paramètre | Description | Exemple de valeur |
---|---|---|
ad_network | Identifiant de la source d'annonce qui a diffusé cette annonce. Les noms des sources d'annonces correspondant aux valeurs d'ID sont listés dans la section Identifiants des sources d'annonces. | 1953547073528090325 |
ad_unit | ID du bloc d'annonces AdMob utilisé pour demander l'annonce avec récompense. | 2747237135 |
custom_data | Chaîne de données personnalisée fournie par
ServerSideVerificationOptions::custom_data .
Si l'application ne fournit aucune chaîne de données personnalisées, la valeur de ce paramètre de requête ne sera pas présente dans le rappel SSV. |
SAMPLE_CUSTOM_DATA_STRING |
key_id | Clé à utiliser pour valider le rappel SSV. Cette valeur correspond à une clé publique fournie par le serveur de clés AdMob. | 1234567890 |
reward_amount | Montant de la récompense spécifié dans les paramètres du bloc d'annonces. | 5 |
reward_item | Récompense spécifiée dans les paramètres du bloc d'annonces. | pièces |
signature | Signature pour le rappel SSV généré par AdMob. | MEUCIQCLJS_s4ia_sN06HqzeW7Wc3nhZi4RlW3qV0oO-6AIYdQIgGJEh-rzKreO-paNDbSCzWGMtmgJHYYW9k2_icM9LFMY |
timestamp | Code temporel (en ms) indiquant la date et l'heure auxquelles l'utilisateur a reçu la récompense. | 1507770365237823 |
transaction_id | Identifiant unique encodé en hexadécimal pour chaque événement d'attribution de récompense généré par AdMob. | 18fa792de1bca816048293fc71035638 |
user_id | Identifiant utilisateur fourni par ServerSideVerificationOptions::user_id .
Si l'application ne fournit aucun identifiant utilisateur, ce paramètre de requête ne sera pas présent dans le rappel SSV. |
1234567 |
Identifiants de sources d'annonces
Noms et ID des sources d'annonces
Nom de la source de l'annonce | ID de la source d'annonce |
---|---|
Ad Generation (enchères) | 1477265452970951479 |
AdColony | 15586990674969969776 |
AdColony (enchères) | 6895345910719072481 |
AdFalcon | 3528208921554210682 |
Réseau AdMob | 5450213213286189855 |
Cascade d'annonces du réseau AdMob | 1215381445328257950 |
Applovin | 1063618907739174004 |
Applovin (enchères) | 1328079684332308356 |
Chartboost | 2873236629771172317 |
Chocolate Platform (enchères) | 6432849193975106527 |
Événement personnalisé | 18351550913290782395 |
DT Exchange* * Avant le 21 septembre 2022, ce réseau s'appelait "Fyber Marketplace". | 2179455223494392917 |
Equativ (enchères)* * Avant le 12 janvier 2023, ce réseau s'appelait "Smart Adserver". | 5970199210771591442 |
Fluct (enchères) | 8419777862490735710 |
Flurry | 3376427960656545613 |
Fyber* * Cette source d'annonces est utilisée pour les rapports historiques. | 4839637394546996422 |
i-mobile | 5208827440166355534 |
Improve Digital (enchères) | 159382223051638006 |
Index Exchange (enchères) | 4100650709078789802 |
InMobi | 7681903010231960328 |
InMobi (enchères) | 6325663098072678541 |
InMobi Exchange (enchères) | 5264320421916134407 |
IronSource | 6925240245545091930 |
ironSource Ads (enchères) | 1643326773739866623 |
Leadbolt | 2899150749497968595 |
Liftoff Monetize* * Avant le 30 janvier 2023, ce réseau s'appelait "Vungle". | 1953547073528090325 |
Liftoff Monetize (enchères)* * Avant le 30 janvier 2023, ce réseau s'appelait "Vungle (enchères)". | 4692500501762622185 |
LG U+AD | 18298738678491729107 |
LINE Ads Network | 3025503711505004547 |
Magnite DV+ (enchères) | 3993193775968767067 |
maio | 7505118203095108657 |
maio (enchères) | 1343336733822567166 |
Media.net (enchères) | 2127936450554446159 |
Auto-promotions par médiation | 6060308706800320801 |
Meta Audience Network* * Avant le 6 juin 2022, ce réseau s'appelait "Facebook Audience Network". | 10568273599589928883 |
Meta Audience Network (enchères)* * Avant le 6 juin 2022, ce réseau s'appelait "Facebook Audience Network (enchères)". | 11198165126854996598 |
Mintegral | 1357746574408896200 |
Mintegral (enchères) | 6250601289653372374 |
MobFox (enchères) | 3086513548163922365 |
MoPub (obsolète) | 10872986198578383917 |
myTarget | 8450873672465271579 |
Nend | 9383070032774777750 |
Nexxen (enchères)* * Avant le 1er mai 2024, ce réseau s'appelait "UnrulyX". | 2831998725945605450 |
OneTag Exchange (enchères) | 4873891452523427499 |
OpenX (enchères) | 4918705482605678398 |
Pangle | 4069896914521993236 |
Pangle (enchères) | 3525379893916449117 |
PubMatic (enchères) | 3841544486172445473 |
Campagne par réservation | 7068401028668408324 |
SK planet | 734341340207269415 |
Sharethrough (enchères) | 5247944089976324188 |
Smaato (enchères) | 3362360112145450544 |
Sonobi (enchères) | 3270984106996027150 |
Tapjoy | 7295217276740746030 |
Tapjoy (enchères) | 4692500501762622178 |
Tencent GDT | 7007906637038700218 |
TripleLift (enchères) | 8332676245392738510 |
Unity Ads | 4970775877303683148 |
Unity Ads (enchères) | 7069338991535737586 |
Verve Group (enchères) | 5013176581647059185 |
Vpon | 1940957084538325905 |
Yieldmo (enchères) | 4193081836471107579 |
YieldOne (enchères) | 3154533971590234104 |
Zucks | 5506531810221735863 |
Récompenser l'utilisateur
Il est important de trouver le bon équilibre entre l'expérience utilisateur et la validation des récompenses lorsque vous décidez quand récompenser un utilisateur. Les rappels côté serveur peuvent être retardés avant d'atteindre les systèmes externes. Par conséquent, la bonne pratique recommandée consiste à utiliser le rappel côté client pour récompenser immédiatement l'utilisateur, tout en effectuant la validation de toutes les récompenses à la réception des rappels côté serveur. Cette approche offre une bonne expérience utilisateur tout en garantissant la validité des récompenses accordées.
Toutefois, pour les applications où la validité des récompenses est essentielle (par exemple, si la récompense affecte l'économie du jeu dans votre application) et où les retards dans l'attribution des récompenses sont acceptables, il peut être préférable d'attendre le rappel côté serveur validé.
Données personnalisées
Les applications qui nécessitent des données supplémentaires dans les rappels de validation côté serveur doivent utiliser la fonctionnalité de données personnalisées des annonces avec récompense. Toute valeur de chaîne définie sur un objet d'annonce avec récompense est transmise au paramètre de requête custom_data
du rappel SSV. Si aucune valeur de données personnalisée n'est définie, la valeur du paramètre de requête custom_data
ne sera pas présente dans le rappel SSV.
L'exemple de code suivant montre comment définir des données personnalisées sur un objet d'annonce avec récompense avant de demander une annonce.
firebase::gma::RewardedAd* rewarded_ad; rewarded_ad = new firebase::gma::RewardedAd(); firebase::gma::RewardedAd::ServerSideVerificationOptions options; options.custom_data = "SAMPLE_CUSTOM_DATA_STRING"; rewarded_ad->SetServerSideVerificationOptions(options);
Si vous souhaitez définir la chaîne de récompense personnalisée, vous devez le faire avant d'afficher l'annonce.
Validation manuelle des SSV avec récompense
Les étapes effectuées par la classe RewardedAdsVerifier
pour valider un SSV récompensé sont décrites ci-dessous. Bien que les extraits de code inclus soient en Java et utilisent la bibliothèque tierce Tink, vous pouvez implémenter ces étapes dans la langue de votre choix, en utilisant n'importe quelle bibliothèque tierce compatible avec ECDSA.
Récupérer les clés publiques
Pour valider un rappel SSV avec récompense, vous avez besoin d'une clé publique fournie par AdMob.
Une liste de clés publiques à utiliser pour valider les rappels SSV avec récompense peut être récupérée à partir du serveur de clés AdMob. La liste des clés publiques est fournie sous forme de représentation JSON avec un format semblable à celui-ci :
{
"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=="
},
],
}
Pour récupérer les clés publiques, connectez-vous au serveur de clés AdMob et téléchargez les clés. Le code suivant effectue cette tâche et enregistre la représentation JSON des clés dans la variable 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();
}
Notez que les clés publiques sont régulièrement alternées. Vous recevrez un e-mail vous informant d'une rotation à venir. Si vous mettez en cache des clés publiques, vous devez les mettre à jour dès que vous recevez cet e-mail.
Une fois les clés publiques récupérées, elles doivent être analysées. La méthode parsePublicKeysJson
ci-dessous prend en entrée une chaîne JSON, comme l'exemple ci-dessus, et crée un mappage des valeurs key_id
aux clés publiques, qui sont encapsulées en tant qu'objets ECPublicKey
de la bibliothèque 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;
}
Obtenir du contenu à valider
Les deux derniers paramètres de requête des rappels SSV avec récompense sont toujours signature
et key_id,
, dans cet ordre. Les autres paramètres de requête spécifient le contenu à valider. Imaginons que vous ayez configuré AdMob pour envoyer des rappels de récompense à https://www.myserver.com/mypath
. L'extrait ci-dessous montre un exemple de rappel SSV avec récompense, le contenu à valider étant mis en évidence.
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
Le code ci-dessous montre comment analyser le contenu à vérifier à partir d'une URL de rappel en tant que tableau d'octets 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"));
Obtenir la signature et l'ID de clé à partir de l'URL de rappel
À l'aide de la valeur queryString
de l'étape précédente, analysez les paramètres de requête signature
et key_id
de l'URL de rappel, comme indiqué ci-dessous :
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()));
Effectuer la validation
La dernière étape consiste à valider le contenu de l'URL de rappel avec la clé publique appropriée. Prenez le mappage renvoyé par la méthode parsePublicKeysJson
et utilisez le paramètre key_id
de l'URL de rappel pour obtenir la clé publique à partir de ce mappage. Validez ensuite la signature avec cette clé publique. Ces étapes sont illustrées ci-dessous dans la méthode 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);
}
}
Si la méthode s'exécute sans générer d'exception, l'URL de rappel a été validée.
Questions fréquentes
- Puis-je mettre en cache la clé publique fournie par le serveur de clés AdMob ?
- Nous vous recommandons de mettre en cache la clé publique fournie par le serveur de clés AdMob afin de réduire le nombre d'opérations nécessaires pour valider les rappels SSV. Toutefois, notez que les clés publiques sont régulièrement remplacées et ne doivent pas être mises en cache pendant plus de 24 heures.
- À quelle fréquence les clés publiques fournies par le serveur de clés AdMob sont-elles alternées ?
- Les clés publiques fournies par le serveur de clés AdMob sont renouvelées selon un calendrier variable. Pour que la validation des rappels SSV continue de fonctionner comme prévu, les clés publiques ne doivent pas être mises en cache pendant plus de 24 heures.
- Que se passe-t-il si mon serveur est inaccessible ?
- Google attend un code de réponse d'état de réussite
HTTP 200 OK
pour les rappels SSV. Si votre serveur est inaccessible ou ne fournit pas la réponse attendue, Google tentera à nouveau d'envoyer des rappels SSV jusqu'à cinq fois à intervalles d'une seconde. - Comment puis-je vérifier que les rappels SSV proviennent de Google ?
- Utilisez la résolution DNS inverse pour vérifier que les rappels SSV proviennent de Google.