Монетизируйте свою игру, продавая цифровые продукты с помощью Play Billing. SDK предлагает API-интерфейсы для отображения продуктов, доступных для покупки, запуска процесса покупки и обработки покупок. Вызовы этих API-интерфейсов биллинга выполняются с использованием учетной записи Google, которая запустила игру, внутри клиента Google Play Games и не требуют каких-либо дополнительных действий для входа.
Если вы выполнили интеграцию с библиотекой Android Play Billing , эти API Play Billing должны выглядеть знакомо. Любую серверную интеграцию с Play Billing можно повторно использовать в играх для ПК, поскольку они одинаковы как для Android, так и для ПК.
Предварительные условия
Завершите настройку SDK .
Прочтите обзор платежной системы Google Play .
Завершите настройку платежной системы 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. - Отобразите
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
на свой внутренний сервер. Завершите оставшуюся часть обработки с помощью серверных API биллинга Play . Эта интеграция на стороне сервера такая же, как и для игры для Android, интегрированной с Play Billing.
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 Billing. Для тестирования на этапе разработки мы рекомендуем использовать тестеры лицензий . Тестировщики лицензий имеют доступ к тестовым платежам, позволяющим избежать взимания реальных денег за покупки.
Инструкции по настройке тестеров лицензий и набору ручных тестов мы рекомендуем просмотреть в документации по тестированию интеграции с Библиотекой выставления счетов Google Play .