אתם יכולים לייצר הכנסות מהמשחק על ידי מכירת מוצרים דיגיטליים באמצעות חיוב ב-Play. ה-SDK כולל ממשקי API להצגת מוצרים שזמינים לרכישה, להפעלת תהליך הרכישה ולעיבוד הרכישות. הקריאות לממשקי ה-API לחיוב מתבצעות באמצעות חשבון Google שבו הופעל המשחק בתוך לקוח Google Play Games, ולא נדרשים שלבי כניסה נוספים.
אם שילבתם את האפליקציה עם ספריית החיוב ב-Android Play, ממשקי ה-API של החיוב ב-Play אמורים להיות מוכרים לכם. אפשר לעשות שימוש חוזר בכל השילובים בצד השרת עם החיוב ב-Play במשחקים למחשב, כי הם זהים ב-Android ובמחשב.
דרישות מוקדמות
משלימים את הגדרת ה-SDK.
משלימים את הגדרת החיוב ב-Play.
שלב 1: שאילתות לגבי רכישות קודמות ורכישות שהושלמו מחוץ לאפליקציה
כשהאפליקציה מופעלת או כשהיא חוזרת לחזית, צריך לשלוח שאילתה לגבי רכישות. הדבר נחוץ כדי לזהות רכישות שהתרחשו מחוץ למשחק או כדי לפתוח את הגישה לרכישות שהמשתמש ביצע בעבר.
שולחים שאילתה לגבי רכישות באמצעות
BillingClient::QueryPurchases
.ממשיכים לעבד את הרכישות.
// Query for purchases when:
// - Application starts up
// - Application window re-enters the foreground
auto promise = std::make_shared<std::promise<QueryPurchasesResult>>();
billing_client.QueryPurchases([promise](QueryPurchasesResult result) {
promise->set_value(std::move(result));
});
auto query_purchases_result = promise->get_future().get();
if (query_purchases_result.ok()) {
auto purchases = query_purchases_result.value().product_purchase_details;
// Process the purchases
} else {
// Handle the error
}
שלב 2: הצגת מוצרים שזמינים לרכישה
עכשיו אתם מוכנים לשלוח שאילתה על המוצרים הזמינים ולהציג אותם למשתמשים. שליחת שאילתות לגבי פרטי המוצרים היא שלב חשוב לפני הצגת המוצרים למשתמשים, כי היא מאפשרת לקבל מידע על המוצרים שמותאם לאזור שלהם.
לפני שמציעים מוצר למכירה, צריך לוודא שהמשתמש כבר לא הבעלים של המוצר. אם למשתמש יש מוצר חד-פעמי שעדיין נמצא בהיסטוריית הרכישות שלו, צריך לנצל את המוצר לפני שהוא יוכל לקנות אותו שוב.
- שולחים שאילתה על פרטי המוצר באמצעות
BillingClient::QueryProductDetails
. מעבירים את מזהי המוצרים שרשמת ב-Google Play Console. - מריצים את ה-render של
ProductDetails
שכולל את השם המותאם לשוק המקומי ואת מחיר המבצע של המוצר. - שומרים את ההפניה ל-
offer_token
של המוצר. הקוד הזה משמש להפעלת תהליך הרכישה של המבצע.
QueryProductDetailsParams params;
params.product_ids.push_back({"example_costmetic_1", ProductType::kTypeInApp});
params.product_ids.push_back({"example_costmetic_1", ProductType::kTypeInApp});
params.product_ids.push_back({"example_battle_pass", ProductType::kTypeInApp});
auto promise = std::make_shared<std::promise<QueryProductDetailsResult>>();
billing_client.QueryProductDetails(params, [promise](QueryProductDetailsResult result) {
promise->set_value(std::move(result));
});
auto query_product_details_result = promise->get_future().get();
if (query_product_details_result.ok()) {
auto product_details = query_product_details_result.value().product_details;
// Display the available products and their offers to the user
} else {
// Handle the error
}
שלב 3: מפעילים תהליך רכישה
כשהמשתמש מראה כוונה לקנות מוצר שמוצג לו, אתם מוכנים להפעיל את תהליך הרכישה.
- מתחילים בשיחת וידאו
BillingClient::LaunchPurchaseFlow()
. מעבירים את הערך שלoffer_token
שהתקבל כששלחתם שאילתה לגבי פרטי המוצר. - אחרי השלמת הרכישה, המערכת תקרא לפונקציית ההמשך עם התוצאה.
- אם הפעולה בוצעה בהצלחה, ההמשך יכיל את הערך
ProductPurchaseDetails
. ממשיכים לעיבוד הרכישה.
LaunchPurchaseFlowParams params { product_offer.offer_token };
auto promise = std::make_shared<std::promise<LaunchPurchaseFlowResult>>();
billing_client.LaunchPurchaseFlow(params, [promise](LaunchPurchaseFlowResult result) {
promise->set_value(std::move(result));
});
// The purchase flow has started and is now in progress.
auto launch_purchase_flow_result = promise->get_future().get();
// The purchase flow has now completed.
if (launch_purchase_flow_result.ok()) {
auto purchase = launch_purchase_flow_result.value().product_purchase_details;
// Process the purchase
} else if (launch_purchase_flow_result.code() == BillingError::kUserCanceled) {
// Handle an error caused by the user canceling the purchase flow
} else {
// Handle any other error codes
}
שלב 4: עיבוד רכישה
עיבוד באמצעות שרת לקצה עורפי
במשחקים עם שרת קצה עורפי, כדי להשלים את העיבוד שולחים את הערך purchase_token
לשרת הקצה העורפי. משלימים את שאר העיבוד באמצעות ממשקי Play Billing API בצד השרת. השילוב הזה בצד השרת זהה לשילוב במשחק ל-Android ששולב עם החיוב ב-Play.
void ProcessPurchasesWithServer(std::vector<ProductPurchaseDetails> purchases) {
std::vector<std::string> purchase_tokens;
for (const auto& purchase : purchases) {
purchase_tokens.push_back(purchase.purchase_token);
}
// Send purchase tokens to backend server for processing
}
עיבוד ללא שרת עורפי
מוודאים שהתשלום של המשתמש לא בהמתנה, על ידי בדיקה של הערך של
ProductPurchaseDetails::purchase_state
שהואPurchaseState::kPurchaseStatePurchased
. אם סטטוס הרכישה הוא 'בהמתנה', צריך להודיע למשתמש שהוא צריך להשלים שלבים נוספים כדי לקבל את המוצר שרכש.מעניקים למשתמש גישה למוצר שנרכש ומעדכנים את מאגר ההרשאות של המשחק.
ברכישות של מוצרים שלא ניתנים לשימוש חוזר (מוצרים שאפשר לרכוש רק פעם אחת), צריך לבדוק אם הרכישה כבר אושרה באמצעות
ProductPurchaseDetails::is_acknowledged
.- אם הרכישה לא אושרה, צריך להודיע ל-Google על כך שהמשתמש מקבל זכאות למוצר. לשם כך, צריך להתקשר למספר
BillingClient::AcknowledgePurchase
.
- אם הרכישה לא אושרה, צריך להודיע ל-Google על כך שהמשתמש מקבל זכאות למוצר. לשם כך, צריך להתקשר למספר
ברכישות של מוצרים לשימוש חד-פעמי (מוצרים שאפשר לרכוש יותר מפעם אחת), צריך להודיע ל-Google שהמשתמש מקבל זכות לשימוש במוצר. לשם כך, צריך להתקשר למספר
BillingClient::ConsumePurchase
.
void ProcessPurchasesWithoutServer(std::vector<ProductPurchaseDetails> purchases) {
std::vector<std::string> entitled_product_ids;
for (const auto& purchase : purchases) {
auto was_successful = ProcessPurchasePurchaseWithoutServer(purchase);
if (was_successful) {
entitled_product_ids.push_back(purchase.product_id);
}
}
// Note that non-consumable products that were previously purchased may have
// been refunded. These purchases will stop being returned by
// `QueryPurchases()`. If your game has given a user access to one of these
// products storage they should be revoked.
//
// ...
}
bool ProcessPurchasePurchaseWithoutServer(ProductPurchaseDetails purchase) {
auto is_purchase_completed =
purchase.purchase_state == PurchaseState::kPurchaseStatePurchased;
if (!is_purchase_completed) {
// Notify the user that they need to take additional steps to complete
// this purchase.
return false;
}
// Determine if the product ID is associated with a consumable product.
auto is_consumable = IsConsumableProductId(purchase.product_id);
if (is_consumable) {
// Grant an entitlement to the product to the user.
// ...
// Then, notify Google by consuming the purchase.
ConsumePurchaseParams params { purchase.purchase_token };
auto promise = std::make_shared<std::promise<ConsumePurchaseResult>>();
billing_client.ConsumePurchase(params, [promise](ConsumePurchaseResult result) {
promise->set_value(std::move(result));
});
auto consume_purchase_result = promise->get_future().get();
if (!consume_purchase_result.ok()) {
// Examine the failure code & message for more details & notify user
// of failure.
// ...
return false;
}
return true;
}
// Otherwise the product is assumed to be a non-consumable.
// Grant an entitlement to the product to the user.
// ...
// Then, notify Google by acknowledging the purchase (if not already done).
if (purchase.is_acknowledged) {
return true;
}
AcknowledgePurchaseParams params { purchase.purchase_token };
auto promise = std::make_shared<std::promise<AcknowledgePurchaseResult>>();
billing_client.AcknowledgePurchase(params, [promise](AcknowledgePurchaseResult result) {
promise->set_value(std::move(result));
});
auto acknowledge_purchase_result = promise->get_future().get();
if (!acknowledge_purchase_result.ok()) {
// Examine the failure code & message for more details & notify user
// of failure.
// ...
return false;
}
return true;
}
שלב 5: בודקים את השילוב
עכשיו אתם מוכנים לבדוק את השילוב עם החיוב ב-Play. כדי לבדוק את הרישיון בשלב הפיתוח, מומלץ להשתמש בבודקי רישיונות. לבודקי הרישיון יש גישה לתשלומים לבדיקה, שמאפשרים לבצע רכישות בלי לחייב כסף אמיתי.
להוראות להגדרת בודקי רישיונות וחבילה של בדיקות ידניות, מומלץ לעיין במסמכים בנושא בדיקת השילוב של ספריית החיובים ב-Google Play.