Это вообще не вопрос. Я потратил на это некоторое время, поэтому я привожу здесь шаги, необходимые для совершения покупки в приложении.
добавлены зависимости
//billing-client
implementation 'com.android.billingclient:billing:2.2.1'
implementation 'com.android.billingclient:billing-ktx:2.2.1'
добавлено разрешение в манифесте
- Создано приложение в Play Console.
- Play Console -> настройки -> Шаблон ценообразования :: добавлен шаблон ценообразования.
- Выберите Консоль формы приложения -> Присутствие в магазине -> Продукты в приложении -> Управляемые продукты -> Создать управляемый продукт.
- Для тестирования в первую очередь необходимо выпустить сборку как Alpha (с некоторым идентификатором тестовой почты, зарегистрированным в закрытом треке.)
- После успешной публикации вы можете использовать ту же сборку (возможно, потребуется тот же код версии и номер версии) ( Работает как отладка, так и выпуск ) для проверки покупки.
- Убедитесь, что идентификаторами тестовой почты являются идентификаторы google (@ gmail.com).
Вот фрагменты кода, которые я использовал для выставления счетов.
implement PurchasesUpdatedListener, on fragment or activity
Настроить BIlling Client
private fun setupBillingClient() {
billingClient = BillingClient.newBuilder(mainActivity)
.enablePendingPurchases()
.setListener(this)
.build()
billingClient.startConnection(object : BillingClientStateListener {
override fun onBillingSetupFinished(billingResult: BillingResult) {
if (billingResult.responseCode == BillingClient.BillingResponseCode.OK) {
// The BillingClient is setup
log("Setup Billing Done")
loadAllSKUs()
}
}
override fun onBillingServiceDisconnected() {
log("Failed")
}
})
}
Загрузить все Skus (идентификаторы ваших шаблонов покупок (использовать Arraylist))
private fun loadAllSKUs() = if (billingClient.isReady) {
val params = SkuDetailsParams
.newBuilder()
.setSkusList(skuList)
.setType(BillingClient.SkuType.INAPP)
.build()
billingClient.querySkuDetailsAsync(params) { billingResult, skuDetailsList ->
// Process the result.
if (billingResult.responseCode == BillingClient.BillingResponseCode.OK && skuDetailsList.isNotEmpty()) {
for (skuDetails in skuDetailsList) {
if (billingResult.responseCode == BillingClient.BillingResponseCode.OK && skuDetailsList.isNotEmpty()) {
this.skuDetailsList = skuDetailsList
}
}
}
}
} else {
log("Billing Client not ready")
}
Сделать Google Платеж
private fun invokeGooglePayPayment(skuDetails: SkuDetails) {
val billingFlowParams = BillingFlowParams
.newBuilder()
.setSkuDetails(skuDetails)
.build()
billingClient.launchBillingFlow(mainActivity, billingFlowParams)
}
Если вам нужно совершить повторную покупку для того же предмета покупки в приложении, вы можете использовать этот код,
override fun onPurchasesUpdated(
billingResult: BillingResult?,
purchases: MutableList<Purchase>?
) {
//todo remove this function only for token log
if (!purchases.isNullOrEmpty()) {
for (purchase in purchases) {
Log.e("Purchase Token" + purchase.purchaseToken, "OK")
}
}
if (billingResult?.responseCode == BillingClient.BillingResponseCode.OK && purchases != null) {
for (purchase in purchases) {
acknowledgePurchase(purchase) // do after purchase
}
} else if (billingResult?.responseCode == BillingClient.BillingResponseCode.USER_CANCELED) {
//todo
} else if (billingResult?.responseCode == BillingClient.BillingResponseCode.ITEM_ALREADY_OWNED) {
val consumeParams = ConsumeParams.newBuilder()
.setPurchaseToken("inapp:${BuildConfig.APPLICATION_ID}:${selectedSkuDetails?.sku}")
.build()
runBlocking {
CoroutineScope(Dispatchers.IO).launch {
billingClient.consumePurchase(consumeParams)
}
MainScope().launch {
invokeGooglePayPayment(selectedSkuDetails!!)
}
}
}
}