使用 Play 帳款服務銷售數位產品,為遊戲創造收益。SDK 提供 API,可顯示可購買的產品、啟動購買流程,以及處理購買交易。系統會使用在 Google Play Games 用戶端啟動遊戲的 Google 帳戶,呼叫這些結帳系統 API,且不需要任何額外的登入步驟。
如果您已整合 Android Play 帳款服務程式庫,這些 Play 帳款服務 API 應該會讓您感到熟悉。任何與 Play 帳款服務的伺服器端整合作業,都可以由電腦遊戲重複使用,因為 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 管理中心註冊的產品 ID。 - 轉譯
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 完成剩餘的處理作業。這項伺服器端整合作業與已整合 Play 帳款服務的 Android 遊戲相同。
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
確認是否已確認購買交易。- 如果尚未收到購買交易的確認,請呼叫
BillingClient::AcknowledgePurchase
,通知 Google 使用者已取得產品授權。
- 如果尚未收到購買交易的確認,請呼叫
如果是消費性產品 (可重複購買的產品),請呼叫
BillingClient::ConsumePurchase
,通知 Google 使用者已取得產品授權。
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 帳款服務程式庫整合的說明文件。