การเรียกกลับการยืนยันฝั่งเซิร์ฟเวอร์คือคําขอ URL ที่มีพารามิเตอร์การค้นหาที่ Google ขยาย ซึ่ง Google ส่งไปยังระบบภายนอกเพื่อแจ้งให้ทราบว่าผู้ใช้ควรได้รับรางวัลจากการโต้ตอบกับโฆษณาคั่นระหว่างหน้าที่มีการให้รางวัลหรือโฆษณาคั่นระหว่างหน้าที่มีการให้รางวัล การเรียกกลับ SSV (การยืนยันฝั่งเซิร์ฟเวอร์) ที่มีรางวัลจะเพิ่มการป้องกันอีกชั้นหนึ่งเพื่อป้องกันการปลอมแปลงการเรียกกลับฝั่งไคลเอ็นต์เพื่อมอบรางวัลแก่ผู้ใช้
คู่มือนี้จะแสดงวิธียืนยันการเรียกกลับ SSV ที่มีการให้รางวัลโดยใช้ไลบรารีการเข้ารหัสของบุคคลที่สามใน Tink Java Apps เพื่อให้แน่ใจว่าพารามิเตอร์การค้นหาในการเรียกกลับเป็นค่าที่ถูกต้อง แม้ว่าคู่มือนี้จะกล่าวถึงการใช้ Tink แต่คุณมีตัวเลือกในการใช้ไลบรารีของบุคคลที่สามที่รองรับ ECDSA นอกจากนี้ คุณยังทดสอบเซิร์ฟเวอร์ด้วยเครื่องมือทดสอบใน UI ของ AdMob ได้ด้วย
ข้อกำหนดเบื้องต้น
- เปิดใช้การยืนยันฝั่งเซิร์ฟเวอร์ที่มีการให้รางวัลในหน่วยโฆษณา
ใช้ RewardedAdsVerifier จากไลบรารีแอป Java ของ Tink
ที่เก็บ GitHub ของ Tink Java Apps ประกอบด้วยคลาสตัวช่วย 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 | คีย์ที่จะใช้ยืนยันการติดต่อกลับ SSV ค่านี้จะจับคู่กับคีย์สาธารณะที่เซิร์ฟเวอร์คีย์ AdMob ระบุ | 1234567890 |
reward_amount | จํานวนรางวัลตามที่ระบุไว้ในการตั้งค่าหน่วยโฆษณา | 5 |
reward_item | ไอเทมรางวัลตามที่ระบุไว้ในการตั้งค่าหน่วยโฆษณา | เหรียญ |
ลายเซ็น | ลายเซ็นสําหรับการเรียกกลับ SSV ที่ AdMob สร้างขึ้น | MEUCIQCLJS_s4ia_sN06HqzeW7Wc3nhZi4RlW3qV0oO-6AIYdQIgGJEh-rzKreO-paNDbSCzWGMtmgJHYYW9k2_icM9LFMY |
การประทับเวลา | การประทับเวลาที่ผู้ใช้ได้รับรางวัลเป็นเวลาตามยุคสมัยในหน่วยมิลลิวินาที | 1507770365237823 |
transaction_id | ตัวระบุที่เข้ารหัสฐาน 16 ที่ไม่ซ้ำกันสําหรับกิจกรรมการให้รางวัลแต่ละรายการที่ AdMob สร้างขึ้น | 18fa792de1bca816048293fc71035638 |
user_id | ตัวระบุผู้ใช้ตามที่ SetUserId ระบุ
หากแอปไม่ได้ระบุตัวระบุผู้ใช้ พารามิเตอร์การค้นหานี้จะไม่อยู่ในการเรียกกลับ SSV |
1234567 |
ตัวระบุแหล่งที่มาของโฆษณา
ชื่อและรหัสแหล่งที่มาของโฆษณา
ชื่อแหล่งที่มาของโฆษณา | รหัสแหล่งที่มาของโฆษณา |
---|---|
Aarki (การเสนอราคา) | 5240798063227064260 |
การสร้างโฆษณา (การเสนอราคา) | 1477265452970951479 |
AdColony | 15586990674969969776 |
AdColony (ไม่ใช่ SDK) (การเสนอราคา) | 4600416542059544716 |
AdColony (การเสนอราคา) | 6895345910719072481 |
AdFalcon | 3528208921554210682 |
เครือข่าย AdMob | 5450213213286189855 |
Waterfall ของเครือข่าย AdMob | 1215381445328257950 |
ADResult | 10593873382626181482 |
AMoAd | 17253994435944008978 |
Applovin | 1063618907739174004 |
Applovin (การเสนอราคา) | 1328079684332308356 |
Chartboost | 2873236629771172317 |
Chocolate Platform (การเสนอราคา) | 6432849193975106527 |
CrossChannel (MdotM) | 9372067028804390441 |
เหตุการณ์ที่กำหนดเอง | 18351550913290782395 |
DT Exchange* * ก่อนวันที่ 21 กันยายน 2022 เครือข่ายนี้เรียกว่า "Fyber Marketplace" | 2179455223494392917 |
EMX (การเสนอราคา) | 8497809869790333482 |
Fluct (การเสนอราคา) | 8419777862490735710 |
Flurry | 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 Ads Network | 3025503711505004547 |
maio | 7505118203095108657 |
maio (การเสนอราคา) | 1343336733822567166 |
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 | 8079529624516381459 |
MobFox (การเสนอราคา) | 3086513548163922365 |
MoPub (เลิกใช้งานแล้ว) | 10872986198578383917 |
myTarget | 8450873672465271579 |
Nend | 9383070032774777750 |
Nexxen (การเสนอราคา)* * ก่อนวันที่ 1 พฤษภาคม 2024 เครือข่ายนี้ชื่อ "UnrulyX" | 2831998725945605450 |
ONE by AOL (Millennial Media) | 6101072188699264581 |
ONE by AOL (Nexage) | 3224789793037044399 |
OneTag Exchange (การเสนอราคา) | 4873891452523427499 |
OpenX (การเสนอราคา) | 4918705482605678398 |
Pangle | 4069896914521993236 |
Pangle (การเสนอราคา) | 3525379893916449117 |
PubMatic (การเสนอราคา) | 3841544486172445473 |
แคมเปญแบบจองล่วงหน้า | 7068401028668408324 |
RhythmOne (การเสนอราคา) | 2831998725945605450 |
Magnite DV+ (การเสนอราคา) | 3993193775968767067 |
ดาวเคราะห์ SK | 734341340207269415 |
Sharethrough (การเสนอราคา) | 5247944089976324188 |
Smaato (การเสนอราคา) | 3362360112145450544 |
Equativ (การเสนอราคา)* * ก่อนวันที่ 12 มกราคม 2023 เครือข่ายนี้เรียกว่า "Smart Adserver" | 5970199210771591442 |
Sonobi (การเสนอราคา) | 3270984106996027150 |
Tapjoy | 7295217276740746030 |
Tapjoy (การเสนอราคา) | 4692500501762622178 |
Tencent GDT | 7007906637038700218 |
TripleLift (การเสนอราคา) | 8332676245392738510 |
Unity Ads | 4970775877303683148 |
Unity Ads (การเสนอราคา) | 7069338991535737586 |
Verizon Media | 7360851262951344112 |
Verve Group (การเสนอราคา) | 5013176581647059185 |
Vpon | 1940957084538325905 |
Liftoff Monetize* * ก่อนวันที่ 30 มกราคม 2023 เครือข่ายนี้เรียกว่า "Vungle" | 1953547073528090325 |
Liftoff Monetize (การเสนอราคา)* * ก่อนวันที่ 30 มกราคม 2023 เครือข่ายนี้เรียกว่า "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 ระบุ
รายการคีย์สาธารณะที่จะใช้ตรวจสอบความถูกต้องของ Callback ของ 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;
}
รับการยืนยันเนื้อหา
พารามิเตอร์การค้นหา 2 รายการสุดท้ายของการเรียกกลับ 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 ของ Callback
ใช้ค่า 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 ชั่วโมงเพื่อให้การยืนยันการเรียกกลับ SSV ทำงานต่อไปได้ตามที่ต้องการ
- จะเกิดอะไรขึ้นหากเข้าถึงเซิร์ฟเวอร์ของฉันไม่ได้
- Google คาดว่าจะได้รับรหัสการตอบกลับสถานะ "สำเร็จ"
HTTP 200 OK
สำหรับ SSV callbacks หากเข้าถึงเซิร์ฟเวอร์ไม่ได้หรือไม่มีการตอบกลับตามที่คาดไว้ Google จะพยายามส่งการติดต่อกลับ SSV อีกครั้งสูงสุด 5 ครั้งโดยเว้นระยะห่าง 1 วินาที - ฉันจะยืนยันได้อย่างไรว่าการเรียกกลับ SSV มาจาก Google
- ใช้การค้นหา DNS แบบย้อนกลับเพื่อยืนยันว่าการเรียกกลับ SSV มาจาก Google