서버 측 확인 콜백은 쿼리 매개변수가 포함된 URL 요청입니다. 외부 시스템으로 전송되어 사용자가 보상형 광고나 보상형 전면 광고 보상형 SSV (서버 측 확인) 콜백 클라이언트 측 콜백 스푸핑에 대한 추가 보호 계층 제공 사용자에게 보상을 제공합니다
이 가이드에는 Tink Java 앱 서드 파티 암호화 라이브러리를 추가하여 콜백의 쿼리 매개변수가 적법한 가치를 배제할 수 있습니다. 이 가이드에서는 Tink를 사용하지만 다음 옵션을 사용할 수 있습니다. Google에서 지원하는 서드 파티 라이브러리 사용 ECDSA 또한 gcloud 명령어를 사용하여 도구를 사용하세요.
이 슬라이드에서 완전히 작동하는 예 Java Spring-boot를 사용하는 것이 좋습니다
기본 요건
보상형 광고를 모바일 앱을 <ph type="x-smartling-placeholder"></ph> Google 모바일 광고 SDK v11.6.0 이상
보상형 서버 측 서버 측 사용 설정 인증을 해야 합니다.
Tink Java 앱 라이브러리에서 RewardedAdsVerifier 사용
Tink Java 앱 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 | 이 광고를 처리한 광고 소스의 광고 소스 식별자입니다. 광고 소스 ID 값에 해당하는 이름은 소스 식별자 섹션을 참조하세요. | 1953547073528090325 |
ad_unit | 보상형 광고를 요청할 때 사용된 AdMob 광고 단위 ID입니다. | 2747237135 |
custom_data | 다음에서 제공하는 맞춤 데이터 문자열:
<ph type="x-smartling-placeholder"></ph>
setCustomData
.
앱에서 맞춤 데이터 문자열을 제공하지 않으면 이 쿼리 매개변수가 값은 SSV 콜백에 존재하지 않습니다. |
SAMPLE_CUSTOM_DATA_STRING |
key_id | SSV 콜백을 인증하는 데 사용되는 키입니다. 이 값은 공개 키에 매핑됩니다. AdMob 키 서버에서 제공합니다. | 1234567890 |
reward_amount | 광고 단위 설정에 지정된 보상 금액입니다. | 5 |
reward_item | 광고 단위 설정에 지정된 대로 보상을 제공합니다. | 동전 |
서명 | AdMob에서 생성한 SSV 콜백 서명입니다. | MEUCIQCLJS_s4ia_sN06HqzeW7Wc3nhZi4RlW3qV0oO-6AIYdQIgGJEh-rzKreO-paNDbSCzWGMtmgJHYYW9k2_icM9LFMY |
타임스탬프 | 사용자가 보상을 받은 시간의 타임스탬프입니다(에포크 시간(밀리초)). | 1507770365237823 |
transaction_id | AdMob에서 생성된 각 보상 이벤트의 고유한 16진수 코드 식별자입니다. | 18fa792de1bca816048293fc71035638 |
user_id | 다음에서 제공한 사용자 식별자:
setUserId
앱에서 사용자 식별자를 제공하지 않으면 이 쿼리 매개변수는 SSV 콜백에 있어야 합니다 |
1234567 |
광고 소스 식별자
광고 소스 이름 및 ID
广告来源名称 | 广告来源 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 |
사용자에게 보상 제공
결정을 내릴 때 사용자 경험과 보상 검증의 균형을 맞추는 것이 중요합니다. 사용자에게 보상을 제공하는 시기를 기대할 수 있습니다 서버 측 콜백은 15일 전에 외부 시스템에 접근하는 것입니다. 따라서 가장 좋은 방법은 클라이언트 측 콜백을 호출하여 사용자에게 즉시 보상을 제공하는 동시에 서버 측 콜백 수신 시 모든 보상에 대한 유효성 검사도 할 수 있어야 합니다. 이 허용 여부의 유효성을 보장하면서 우수한 사용자 경험을 제공합니다. 있습니다.
그러나 보상 유효성이 중요한 애플리케이션 (예: 영향을 미치고 리워드 제공이 지연되면 확인된 서버 측 콜백을 기다리는 것이 가장 좋을 수 있습니다. 접근하는 것입니다.
맞춤 데이터
서버 측 확인 콜백에서 추가 데이터가 필요한 앱은
보상형 광고의 맞춤 데이터 기능입니다. 보상형 광고에 설정된 모든 문자열 값
객체가 SSV 콜백의 custom_data
쿼리 매개변수에 전달됩니다. 답이 '아니요'인 경우
맞춤 데이터 값이 설정되면 custom_data
쿼리 매개변수 값이
SSV 콜백에 있어야 합니다
다음 코드 샘플은 표시됩니다.
자바
RewardedAd.load(MainActivity.this, "ca-app-pub-3940256099942544/5354046379", new AdRequest.Builder().build(), new RewardedAdLoadCallback() { @Override public void onAdLoaded(RewardedAd ad) { Log.d(TAG, "Ad was loaded."); rewardedAd = ad; ServerSideVerificationOptions options = new ServerSideVerificationOptions .Builder() .setCustomData("SAMPLE_CUSTOM_DATA_STRING") .build(); rewardedAd.setServerSideVerificationOptions(options); } @Override public void onAdFailedToLoad(LoadAdError loadAdError) { Log.d(TAG, loadAdError.toString()); rewardedAd = null; } });
Kotlin
RewardedAd.load(this, "ca-app-pub-3940256099942544/5354046379", AdRequest.Builder().build(), object : RewardedAdLoadCallback() { override fun onAdLoaded(ad: RewardedAd) { Log.d(TAG, "Ad was loaded.") rewardedInterstitialAd = ad val options = ServerSideVerificationOptions.Builder() .setCustomData("SAMPLE_CUSTOM_DATA_STRING") .build() rewardedAd.setServerSideVerificationOptions(options) } override fun onAdFailedToLoad(adError: LoadAdError) { Log.d(TAG, adError?.toString()) rewardedAd = null } })
맞춤 보상 문자열을 설정하려면 태그를 표시하기 전에 설정해야 합니다. 합니다.
보상형 SSV의 수동 확인
RewardedAdsVerifier
클래스가 보상형 광고를 확인하기 위해 수행한 단계
SSV는 아래에 설명되어 있습니다. 포함된 코드 스니펫은 Java와
Tink 서드 파티 라이브러리를 활용하면
지원하는 서드 파티 라이브러리를 사용하여 원하는 언어로
ECDSA
공개 키 가져오기
보상형 SSV 콜백을 인증하려면 AdMob에서 제공하는 공개 키가 필요합니다.
보상형 SSV 콜백을 확인하는 데 사용되는 공개 키의 목록은 가져온 것입니다. 있습니다. 공개 키 목록 는 다음과 유사한 형식의 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
값에서 공개 키로 매핑을 생성합니다.
이는 Tink 라이브러리의 ECPublicKey
객체로 캡슐화됩니다.
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"));
콜백 URL에서 signature 및 key_id 가져오기
이전 단계의 queryString
값을 사용하여 signature
를 파싱하고
key_id
쿼리 매개변수를 추가합니다.
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()));
인증 실행
마지막 단계는
적절한 공개 키를 만들 수 있습니다 다음에서 반환된
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이 확인되었습니다.
FAQ
- AdMob 키 서버에서 제공하는 공개 키를 캐시할 수 있나요?
- AdMob 키에서 제공하는 공개 키를 캐시하는 것이 좋습니다. SSV 검증에 필요한 작업 건수를 줄이기 위해 있습니다. 그러나 공개 키는 정기적으로 순환되므로 24시간 이상 캐시되어야 합니다.
- AdMob 키 서버에서 제공하는 공개 키는 얼마나 자주 순환되나요?
- AdMob 키 서버에서 제공하는 공개 키는 변수에서 순환됩니다. 있습니다 SSV 콜백의 인증이 공개 키를 24시간 이상 캐시해서는 안 됩니다.
- 서버에 연결할 수 없으면 어떻게 되나요?
- Google은 SSV에 대해
HTTP 200 OK
성공 상태 응답 코드를 예상합니다. 있습니다. 서버에 연결할 수 없거나 서버에서 예상했던 Google은 SSV 콜백을 5회까지 전송하려고 1초 간격입니다. - SSV 콜백이 Google에서 온 것인지 확인하려면 어떻게 해야 하나요?
- SSV 콜백이 Google에서 전송되는지 확인하려면 역방향 DNS 조회를 사용하세요.