Lệnh gọi lại xác minh phía máy chủ là các yêu cầu URL, với tham số truy vấn do Google mở rộng, được Google gửi tới một hệ thống bên ngoài để thông báo rằng một người dùng cần được thưởng vì đã tương tác với một quảng cáo có tặng thưởng hoặc quảng cáo xen kẽ có tặng thưởng. Lệnh gọi lại SSV (xác minh phía máy chủ) dành cho quảng cáo có tặng thưởng cung cấp thêm một lớp bảo vệ giúp ngăn chặn tình trạng giả mạo lệnh gọi lại phía máy khách để trao thưởng cho người dùng.
Hướng dẫn này giúp bạn hiểu cách xác minh lệnh gọi lại SSV dành cho quảng cáo có tặng thưởng bằng cách sử dụng Ứng dụng Java của Tink (một thư viện mật mã bên thứ ba) để đảm bảo rằng tham số truy vấn trong lệnh gọi lại là giá trị hợp lệ. Mặc dù chúng tôi sử dụng Tink cho các mục đích của hướng dẫn này, nhưng bạn có thể sử dụng bất kỳ thư viện bên thứ ba nào có hỗ trợ ECDSA. Bạn cũng có thể kiểm tra máy chủ của mình bằng công cụ kiểm tra trong giao diện người dùng AdMob.
Điều kiện tiên quyết
- Bật tính năng xác minh phía máy chủ dành cho quảng cáo có tặng thưởng trên đơn vị quảng cáo của bạn.
Sử dụng RewardedAdsVerifier trong thư viện Ứng dụng Java của Tink
Kho lưu trữ Ứng dụng Java của Tink trên GitHub bao gồm một lớp trình trợ giúp RewardedAdsVerifier
nhằm rút gọn đoạn mã cần thiết để xác minh lệnh gọi lại SSV dành cho quảng cáo có tặng thưởng.
Khi sử dụng lớp này, bạn có thể xác minh URL của lệnh gọi lại bằng mã sau.
RewardedAdsVerifier verifier = new RewardedAdsVerifier.Builder()
.fetchVerifyingPublicKeysWith(
RewardedAdsVerifier.KEYS_DOWNLOADER_INSTANCE_PROD)
.build();
String rewardUrl = ...;
verifier.verify(rewardUrl);
Nếu không phát sinh trường hợp ngoại lệ trong quá trình thực thi phương thức verify()
, thì URL của lệnh gọi lại đã được xác minh thành công. Mục Trao thưởng cho người dùng trình bày một cách chi tiết các phương pháp hay nhất về thời điểm trao thưởng cho người dùng. Để biết thông tin chi tiết về các bước mà lớp này sẽ thực hiện để xác minh lệnh gọi lại SSV dành cho quảng cáo có tặng thưởng, bạn có thể tìm hiểu trong mục Quy trình xác minh SSV dành cho quảng cáo có tặng thưởng theo cách thủ công.
Các tham số gọi lại SSV
Lệnh gọi lại xác minh phía máy chủ chứa các tham số truy vấn mô tả hoạt động tương tác với quảng cáo có tặng thưởng. Bạn có thể xem danh sách liệt kê tên tham số, nội dung mô tả và giá trị mẫu ở bên dưới. Các tham số được gửi theo thứ tự bảng chữ cái.
Tên thông số | Mô tả | Giá trị mẫu |
---|---|---|
ad_network | Giá trị nhận dạng nguồn quảng cáo cho nguồn quảng cáo đã thực hiện quảng cáo này. Bạn có thể xem danh sách tên nguồn quảng cáo tương ứng với giá trị mã nhận dạng trong phần Giá trị nhận dạng nguồn quảng cáo. | 1953547073528090325 |
ad_unit | Mã đơn vị quảng cáo AdMob được dùng để yêu cầu quảng cáo có tặng thưởng. | 2747237135 |
key_id | Khoá được sử dụng để xác minh lệnh gọi lại SSV. Giá trị này liên kết đến khoá công khai do máy chủ khoá AdMob cung cấp. | 1234567890 |
reward_amount | Số tiền thưởng như được chỉ định trong chế độ cài đặt đơn vị quảng cáo. | 5 |
reward_item | Phần thưởng như được chỉ định trong chế độ cài đặt đơn vị quảng cáo. | xu |
Chữ ký | Chữ ký cho lệnh gọi lại SSV do AdMob tạo ra. | MEUCIQCLJS_s4ia_sN06HqzeW7Wc3nhZi4RlW3qV0oO-6AIYdQIgGJEh-rzKreO-paNDbSCzWGMtmgJHYYW9k2_icM9LFMY |
dấu thời gian | Dấu thời gian về thời điểm người dùng được tặng thưởng dưới dạng Epoch time tính bằng mili giây. | 1507770365237823 |
transaction_id | Giá trị nhận dạng được mã hoá hex duy nhất cho từng sự kiện cấp phần thưởng do AdMob tạo ra. | 18fa792de1bca816048293fc71035638 |
user_id | Giá trị nhận dạng người dùng do SetUserId cung cấp.
Nếu ứng dụng không cung cấp giá trị nhận dạng người dùng, thông số truy vấn này sẽ không xuất hiện trong lệnh gọi lại SSV. |
1234567 |
Giá trị nhận dạng nguồn quảng cáo
Tên và mã nhận dạng nguồn quảng cáo
Tên nguồn quảng cáo | Mã nguồn quảng cáo |
---|---|
Aarki (đặt giá thầu) | 5240798063227064260 |
Ad Generation (đặt giá thầu) | 1477265452970951479 |
AdColony | 15586990674969969776 |
AdColony (không phải SDK) (đặt giá thầu) | 4600416542059544716 |
AdColony (đặt giá thầu) | 6895345910719072481 |
AdFalcon | 3528208921554210682 |
Mạng AdMob | 5450213213286189855 |
Thác nước trên Mạng AdMob | 1215381445328257950 |
ADResult | 10593873382626181482 |
AMoAd | 17253994435944008978 |
Applovin | 1063618907739174004 |
Applovin (đặt giá thầu) | 1328079684332308356 |
Chartboost | 2873236629771172317 |
Chocolate Platform (đặt giá thầu) | 6432849193975106527 |
CrossChannel (MdotM) | 9372067028804390441 |
Sự kiện tuỳ chỉnh | 18351550913290782395 |
DT Exchange* * Trước ngày 21 tháng 9 năm 2022, mạng này được gọi là "Fyber Marketplace". | 2179455223494392917 |
EMX (đặt giá thầu) | 8497809869790333482 |
Fluct (đặt giá thầu) | 8419777862490735710 |
Flurry | 3376427960656545613 |
Fyber* * Nguồn quảng cáo này được dùng để báo cáo dữ liệu trong quá khứ. | 4839637394546996422 |
i-mobile | 5208827440166355534 |
Improve Digital (đặt giá thầu) | 159382223051638006 |
Index Exchange (đặt giá thầu) | 4100650709078789802 |
InMobi | 7681903010231960328 |
InMobi (đặt giá thầu) | 6325663098072678541 |
InMobi Exchange (đặt giá thầu) | 5264320421916134407 |
IronSource | 6925240245545091930 |
ironSource Ads (đặt giá thầu) | 1643326773739866623 |
Leadbolt | 2899150749497968595 |
LG U+AD | 18298738678491729107 |
LINE Ads Network | 3025503711505004547 |
maio | 7505118203095108657 |
maio (đặt giá thầu) | 1343336733822567166 |
Media.net (đặt giá thầu) | 2127936450554446159 |
Quảng cáo tự quảng bá đã dàn xếp | 6060308706800320801 |
Meta Audience Network* * Trước ngày 6 tháng 6 năm 2022, mạng này được gọi là "Facebook Audience Network". | 10568273599589928883 |
Meta Audience Network (đặt giá thầu)* * Trước ngày 6 tháng 6 năm 2022, mạng này được gọi là "Facebook Audience Network (đặt giá thầu)". | 11198165126854996598 |
Mintegral | 1357746574408896200 |
Mintegral (đặt giá thầu) | 6250601289653372374 |
MobFox | 8079529624516381459 |
MobFox (đặt giá thầu) | 3086513548163922365 |
MoPub (đã ngừng hoạt động) | 10872986198578383917 |
myTarget | 8450873672465271579 |
Nend | 9383070032774777750 |
Nexxen (đặt giá thầu)* * Trước ngày 1 tháng 5 năm 2024, mạng này được gọi là "UnrulyX". | 2831998725945605450 |
ONE by AOL (Millennial Media) | 6101072188699264581 |
ONE by AOL (Nexage) | 3224789793037044399 |
OneTag Exchange (đặt giá thầu) | 4873891452523427499 |
OpenX (đặt giá thầu) | 4918705482605678398 |
Pangle | 4069896914521993236 |
Pangle (đặt giá thầu) | 3525379893916449117 |
PubMatic (đặt giá thầu) | 3841544486172445473 |
Chiến dịch đặt trước | 7068401028668408324 |
RhythmOne (đặt giá thầu) | 2831998725945605450 |
Rubicon (đặt giá thầu) | 3993193775968767067 |
SK planet | 734341340207269415 |
Sharethrough (đặt giá thầu) | 5247944089976324188 |
Smaato (đặt giá thầu) | 3362360112145450544 |
Equativ (đặt giá thầu)* * Trước ngày 12 tháng 1 năm 2023, mạng này được gọi là "Smart AdServer". | 5970199210771591442 |
Sonobi (đặt giá thầu) | 3270984106996027150 |
Tapjoy | 7295217276740746030 |
Tapjoy (đặt giá thầu) | 4692500501762622178 |
Tencent GDT | 7007906637038700218 |
TripleLift (đặt giá thầu) | 8332676245392738510 |
Unity Ads | 4970775877303683148 |
Unity Ads (đặt giá thầu) | 7069338991535737586 |
Verizon Media | 7360851262951344112 |
Verve Group (đặt giá thầu) | 5013176581647059185 |
Vpon | 1940957084538325905 |
Liftoff Monetize* * Trước ngày 30 tháng 1 năm 2023, mạng này được gọi là "Vungle". | 1953547073528090325 |
Liftoff Monetize (đặt giá thầu)* * Trước ngày 30 tháng 1 năm 2023, mạng này được gọi là "Vungle (đặt giá thầu)". | 4692500501762622185 |
Yieldmo (đặt giá thầu) | 4193081836471107579 |
YieldOne (đặt giá thầu) | 3154533971590234104 |
Zucks | 5506531810221735863 |
Thưởng cho người dùng
Điều quan trọng là phải cân bằng trải nghiệm người dùng và xác thực phần thưởng khi quyết định thời điểm tặng thưởng cho người dùng. Các lệnh gọi lại phía máy chủ có thể bị trì hoãn trước khi tiếp cận các hệ thống bên ngoài. Do đó, phương pháp đề xuất hay nhất là sử dụng lệnh gọi lại phía máy khách để tặng thưởng cho người dùng ngay lập tức, trong khi thực hiện xác thực trên tất cả các phần thưởng khi nhận được lệnh gọi lại phía máy chủ. Phương pháp này mang lại trải nghiệm người dùng tốt trong khi vẫn đảm bảo tính hợp lệ của các phần thưởng được cấp.
Tuy nhiên, đối với những ứng dụng mà trong đó tính hợp lệ của phần thưởng là điều rất quan trọng (ví dụ: phần thưởng ảnh hưởng đến hoạt động kinh tế trong trò chơi của ứng dụng) và tình trạng chậm trễ trong việc cấp phần thưởng có thể chấp nhận được, thì việc đợi lệnh gọi lại từ phía máy chủ được xác minh có thể là giải pháp tốt nhất.
Dữ liệu tùy chỉnh
Những ứng dụng cần có thêm dữ liệu trong lệnh gọi lại của cơ chế xác minh phía máy chủ nên sử dụng tính năng dữ liệu tuỳ chỉnh của quảng cáo có tặng thưởng. Bất kỳ giá trị chuỗi nào được đặt cho đối tượng quảng cáo có tặng thưởng đều sẽ được truyền đến tham số truy vấn custom_data
cho lệnh gọi lại của SSV. Nếu bạn không đặt giá trị dữ liệu tuỳ chỉnh, thì giá trị tham số truy vấn custom_data
sẽ không hiển thị trong lệnh gọi lại của SSV.
Mã mẫu sau đây minh hoạ cách đặt các lựa chọn của SSV sau khi quảng cáo có tặng thưởng được tải.
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);
});
}
Nếu muốn đặt chuỗi phần thưởng tuỳ chỉnh, bạn phải thực hiện việc này trước khi hiển thị quảng cáo.
Xác minh SSV dành cho quảng cáo có tặng thưởng theo cách thủ công
Bạn có thể xem các bước mà lớp RewardedAdsVerifier
sẽ thực hiện để xác minh SSV dành cho quảng cáo có tặng thưởng bên dưới. Mặc dù đoạn mã được sử dụng nằm trong Java và sử dụng thư viện Tink của bên thứ ba, nhưng bạn có thể triển khai các bước này theo ngôn ngữ mà mình muốn bằng cách sử dụng bất kỳ thư viện bên thứ ba nào có hỗ trợ ECDSA.
Tìm nạp khoá công khai
Để xác minh lệnh gọi lại SSV dành cho quảng cáo có tặng thưởng, bạn cần có khoá công khai do AdMob cung cấp.
Bạn có thể tìm nạp danh sách khoá công khai mà hệ thống dùng để xác thực lệnh gọi lại SSV dành cho quảng cáo có tặng thưởng từ máy chủ khoá AdMob. Danh sách khoá công khai được cung cấp dưới dạng một JSON có định dạng tương tự như sau:
{
"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=="
},
],
}
Để truy xuất khoá công khai, hãy kết nối với máy chủ khoá AdMob và tải khoá xuống. Mã sau đây giúp bạn hoàn thành công việc này và lưu phép biểu diễn JSON của các khoá đó vào biến 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();
}
Xin lưu ý rằng các khoá công khai được xoay vòng thường xuyên. Chúng tôi sẽ gửi email cho bạn để thông báo về việc xoay vòng sắp tới. Nếu đang lưu khóa công khai vào bộ nhớ đệm, bạn nên cập nhật các khoá đó khi nhận được email này.
Sau khi tìm nạp, các khoá công khai phải được phân tích cú pháp. Phương thức parsePublicKeysJson
dưới đây sẽ lấy chuỗi JSON (như ví dụ ở trên) làm dữ liệu nhập và tạo mối liên kết từ giá trị key_id
đến khoá công khai. Các khoá này sẽ được đóng gói dưới dạng đối tượng ECPublicKey
trong thư viện 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;
}
Lấy nội dung cần xác minh
2 tham số truy vấn cuối cùng của lệnh gọi lại SSV dành cho quảng cáo có tặng thưởng luôn có thứ tự là signature
và key_id,
. Các tham số truy vấn còn lại chỉ định nội dung cần xác minh. Giả sử bạn đã định cấu hình để AdMob gửi lệnh gọi lại phần thưởng đến https://www.myserver.com/mypath
. Đoạn mã sau đây là một ví dụ về lệnh gọi lại SSV dành cho quảng cáo có tặng thưởng, trong đó in đậm nội dung cần xác minh.
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
Mã dưới đây minh hoạ cách phân tích cú pháp nội dung cần được xác minh từ URL gọi lại dưới dạng mảng byte 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"));
Nhận chữ ký và key_id từ URL gọi lại
Sử dụng giá trị queryString
từ bước trước, phân tích cú pháp thông số truy vấn signature
và key_id
của URL gọi lại như bên dưới:
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()));
Thực hiện quy trình xác minh
Bước cuối cùng là xác minh nội dung của URL gọi lại bằng khoá công khai phù hợp. Hãy lấy mối liên kết mà phương thức parsePublicKeysJson
trả về và sử dụng thông số key_id
của URL gọi lại để nhận khoá công khai từ mối liên kết đó. Sau đó, hãy xác minh chữ ký bằng cách sử dụng khoá công khai đó. Bạn có thể xem các bước này bên dưới trong phương thức 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);
}
}
Nếu không phát sinh trường hợp ngoại lệ trong quá trình thực thi phương thức này, thì URL gọi lại đã được xác minh thành công.
Câu hỏi thường gặp
- Tôi có thể lưu khóa công khai do máy chủ khoá AdMob cung cấp vào bộ nhớ đệm không?
- Bạn nên lưu khóa công khai do máy chủ khoá AdMob cung cấp vào bộ nhớ đệm nhằm giảm số lượng thao tác mà bạn phải thực hiện để xác thực lệnh gọi lại SSV. Tuy nhiên, xin lưu ý rằng hệ thống sẽ thường xuyên xoay vòng các khoá công khai, do đó, bạn chỉ nên lưu các khoá công khai vào bộ nhớ đệm trong thời gian không quá 24 giờ.
- Tần suất xoay vòng của các khoá công khai do máy chủ khoá AdMob cung cấp như thế nào?
- Các khoá công khai do máy chủ khoá AdMob cung cấp được xoay vòng theo lịch biểu không cố định. Để đảm bảo rằng quy trình xác minh lệnh gọi lại SSV vẫn hoạt động bình thường, bạn chỉ nên lưu các khoá công khai vào bộ nhớ đệm trong thời gian không quá 24 giờ.
- Điều gì sẽ xảy ra nếu tôi không thể truy cập vào máy chủ?
- Google dự kiến sử dụng mã phản hồi trạng thái thành công
HTTP 200 OK
cho lệnh gọi lại SSV. Nếu bạn không thể truy cập vào máy chủ hoặc máy chủ không phản hồi như dự kiến, Google sẽ thử gửi lại các lệnh gọi lại SSV tối đa 5 lần trong khoảng thời gian một giây. - Làm cách nào để tôi có thể xác minh rằng các lệnh gọi lại SSV là của Google?
- Bạn có thể sử dụng công cụ tra cứu DNS ngược để xác minh rằng các lệnh gọi lại SSV là của Google.