Tích hợp Thư viện Google Play Billing vào ứng dụng

Kiếm tiền từ trò chơi của bạn bằng cách bán sản phẩm kỹ thuật số thông qua Play Billing. SDK cung cấp các API để hiển thị các sản phẩm có thể mua, bắt đầu quy trình mua và xử lý giao dịch mua. Các lệnh gọi đến các API hệ thống thanh toán này được thực hiện bằng Tài khoản Google đã chạy trò chơi bên trong ứng dụng Google Play Games và không yêu cầu thêm bước đăng nhập nào.

Nếu bạn đã tích hợp với thư viện Android Play Billing, thì các API Play Billing này sẽ trông quen thuộc. Các trò chơi dành cho máy tính có thể sử dụng lại mọi tính năng tích hợp phía máy chủ với Play Billing vì các tính năng này giống nhau trên cả Android và máy tính.

Điều kiện tiên quyết

Bước 1: Truy vấn các giao dịch mua trước đó và giao dịch mua hoàn tất bên ngoài ứng dụng

Khi ứng dụng khởi động hoặc khi ứng dụng quay lại nền trước, hãy truy vấn giao dịch mua. Điều này là cần thiết để phát hiện các giao dịch mua xảy ra bên ngoài trò chơi của bạn hoặc để mở khoá quyền truy cập vào các giao dịch mua mà người dùng đã thực hiện trước đó.

  1. Truy vấn về giao dịch mua bằng BillingClient::QueryPurchases.

  2. Tiếp tục bằng cách xử lý các giao dịch mua.

// 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
}

Bước 2: Hiển thị các sản phẩm có thể mua

Bạn có thể truy vấn các sản phẩm mà mình hiện có và cho người dùng thấy các sản phẩm đó. Truy vấn thông tin chi tiết về sản phẩm là một bước quan trọng trước khi hiển thị sản phẩm cho người dùng vì việc truy vấn này sẽ trả về thông tin sản phẩm đã bản địa hoá.

Trước khi chào bán một sản phẩm, hãy kiểm tra để đảm bảo rằng người dùng chưa sở hữu sản phẩm đó. Nếu người dùng có một sản phẩm tiêu dùng vẫn còn trong nhật ký mua hàng, thì bạn phải tiêu thụ sản phẩm đó trước khi họ có thể mua lại.

  1. Truy vấn thông tin chi tiết về sản phẩm bằng cách sử dụng BillingClient::QueryProductDetails. Truyền vào các mã sản phẩm mà bạn đã đăng ký trong Google Play Console.
  2. Kết xuất ProductDetails, trong đó có tên được bản địa hoá và giá ưu đãi của sản phẩm.
  3. Duy trì tham chiếu đến offer_token của sản phẩm. Phương thức này dùng để bắt đầu quy trình mua cho ưu đãi.
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
}

Bước 3: Bắt đầu quy trình mua

Khi người dùng cho thấy ý định mua một sản phẩm mà bạn đã cho họ thấy, bạn đã sẵn sàng bắt đầu quy trình mua hàng.

  1. Bắt đầu bằng cách gọi BillingClient::LaunchPurchaseFlow(). Truyền vào offer_token thu được khi truy vấn thông tin chi tiết về sản phẩm.
  2. Sau khi giao dịch mua hoàn tất, hàm tiếp tục sẽ được gọi cùng với kết quả.
  3. Nếu thành công, phần tiếp tục sẽ chứa một ProductPurchaseDetails. Tiếp tục bằng cách xử lý giao dịch mua.
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
}

Bước 4: Xử lý giao dịch mua

Xử lý bằng máy chủ phụ trợ

Đối với các trò chơi có máy chủ phụ trợ, hãy hoàn tất quá trình xử lý bằng cách gửi purchase_token đến máy chủ phụ trợ. Hoàn tất phần xử lý còn lại bằng cách sử dụng API Play Billing phía máy chủ. Cách tích hợp phía máy chủ này giống như cách thực hiện cho một trò chơi Android đã tích hợp với 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
}

Xử lý mà không cần máy chủ phụ trợ

  1. Đảm bảo khoản thanh toán của người dùng không đang chờ xử lý bằng cách kiểm tra xem ProductPurchaseDetails::purchase_state có phải là PurchaseState::kPurchaseStatePurchased hay không. Nếu trạng thái mua hàng đang chờ xử lý, hãy thông báo cho người dùng rằng họ cần hoàn tất các bước bổ sung thì mới có thể nhận được sản phẩm đã mua.

  2. Cấp cho người dùng quyền truy cập vào sản phẩm đã mua và cập nhật bộ nhớ quyền của trò chơi.

  3. Đối với các giao dịch mua sản phẩm không phải hàng tiêu dùng (những sản phẩm chỉ có thể mua một lần), hãy kiểm tra xem giao dịch mua đã được xác nhận hay chưa bằng cách sử dụng ProductPurchaseDetails::is_acknowledged.

    1. Nếu giao dịch mua chưa được xác nhận, hãy thông báo cho Google rằng người dùng đang được cấp quyền sử dụng sản phẩm bằng cách gọi BillingClient::AcknowledgePurchase.
  4. Đối với giao dịch mua sản phẩm tiêu dùng (những sản phẩm có thể mua nhiều lần), hãy thông báo cho Google rằng người dùng đang được cấp quyền đối với sản phẩm bằng cách gọi 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;
}

Bước 5: Kiểm thử quá trình tích hợp

Giờ thì bạn đã sẵn sàng kiểm thử việc tích hợp với Play Billing. Để kiểm thử trong giai đoạn phát triển, bạn nên tận dụng tính năng nhân viên kiểm thử được cấp phép. Nhân viên kiểm thử được cấp phép có quyền truy cập vào các khoản thanh toán dùng cho mục đích kiểm thử để tránh việc bị tính phí như trong các giao dịch mua thực tế.

Để biết hướng dẫn về cách thiết lập trình kiểm thử giấy phép và bộ kiểm thử thủ công, bạn nên xem tài liệu về cách kiểm thử quá trình tích hợp Thư viện Google Play Billing.