From 982b90d423a06b226a175de7067a182640ebb0d3 Mon Sep 17 00:00:00 2001 From: Alex Hart Date: Thu, 5 Sep 2024 13:46:55 -0300 Subject: [PATCH] Add BillingDependencies and shared implementation. --- .../ApplicationDependencyProvider.java | 2 +- .../GooglePlayBillingDependencies.kt | 25 +++++++++++++++++ .../java/org/signal/billing/BillingFactory.kt | 4 +-- .../java/org/signal/billing/BillingApiImpl.kt | 12 +++++--- .../java/org/signal/billing/BillingFactory.kt | 6 ++-- .../core/util/billing/BillingDependencies.kt | 28 +++++++++++++++++++ 6 files changed, 67 insertions(+), 10 deletions(-) create mode 100644 app/src/main/java/org/thoughtcrime/securesms/dependencies/GooglePlayBillingDependencies.kt create mode 100644 core-util/src/main/java/org/signal/core/util/billing/BillingDependencies.kt diff --git a/app/src/main/java/org/thoughtcrime/securesms/dependencies/ApplicationDependencyProvider.java b/app/src/main/java/org/thoughtcrime/securesms/dependencies/ApplicationDependencyProvider.java index 4f6ba3d066..ffc691c6c9 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/dependencies/ApplicationDependencyProvider.java +++ b/app/src/main/java/org/thoughtcrime/securesms/dependencies/ApplicationDependencyProvider.java @@ -452,7 +452,7 @@ public class ApplicationDependencyProvider implements AppDependencies.Provider { @Override public @NonNull BillingApi provideBillingApi() { - return BillingFactory.create(context, RemoteConfig.messageBackups()); + return BillingFactory.create(GooglePlayBillingDependencies.INSTANCE, RemoteConfig.messageBackups()); } @Override diff --git a/app/src/main/java/org/thoughtcrime/securesms/dependencies/GooglePlayBillingDependencies.kt b/app/src/main/java/org/thoughtcrime/securesms/dependencies/GooglePlayBillingDependencies.kt new file mode 100644 index 0000000000..4cbd52472d --- /dev/null +++ b/app/src/main/java/org/thoughtcrime/securesms/dependencies/GooglePlayBillingDependencies.kt @@ -0,0 +1,25 @@ +/* + * Copyright 2024 Signal Messenger, LLC + * SPDX-License-Identifier: AGPL-3.0-only + */ + +package org.thoughtcrime.securesms.dependencies + +import android.content.Context +import org.signal.core.util.billing.BillingDependencies + +/** + * Dependency object for Google Play Billing. + */ +object GooglePlayBillingDependencies : BillingDependencies { + + override val context: Context get() = AppDependencies.application + + override suspend fun getProductId(): String { + return "backup" // TODO [message-backups] This really shouldn't be hardcoded into the app. + } + + override suspend fun getBasePlanId(): String { + return "monthly" // TODO [message-backups] This really shouldn't be hardcoded into the app. + } +} diff --git a/app/src/website/java/org/signal/billing/BillingFactory.kt b/app/src/website/java/org/signal/billing/BillingFactory.kt index 18809b1927..91974fe66c 100644 --- a/app/src/website/java/org/signal/billing/BillingFactory.kt +++ b/app/src/website/java/org/signal/billing/BillingFactory.kt @@ -1,14 +1,14 @@ package org.signal.billing -import android.content.Context import org.signal.core.util.billing.BillingApi +import org.signal.core.util.billing.BillingDependencies /** * Website builds do not support google play billing. */ object BillingFactory { @JvmStatic - fun create(context: Context, isBackupsAvailable: Boolean): BillingApi { + fun create(billingDependencies: BillingDependencies, isBackupsAvailable: Boolean): BillingApi { return BillingApi.Empty } } diff --git a/billing/src/main/java/org/signal/billing/BillingApiImpl.kt b/billing/src/main/java/org/signal/billing/BillingApiImpl.kt index 7947109691..05f26e0387 100644 --- a/billing/src/main/java/org/signal/billing/BillingApiImpl.kt +++ b/billing/src/main/java/org/signal/billing/BillingApiImpl.kt @@ -6,7 +6,6 @@ package org.signal.billing import android.app.Activity -import android.content.Context import com.android.billingclient.api.BillingClient import com.android.billingclient.api.BillingClient.BillingResponseCode import com.android.billingclient.api.BillingClient.ProductType @@ -37,6 +36,7 @@ import kotlinx.coroutines.flow.update import kotlinx.coroutines.launch import kotlinx.coroutines.withContext import org.signal.core.util.billing.BillingApi +import org.signal.core.util.billing.BillingDependencies import org.signal.core.util.logging.Log /** @@ -46,7 +46,7 @@ import org.signal.core.util.logging.Log * Care should be taken here to ensure only one instance of this exists at a time. */ internal class BillingApiImpl( - context: Context + private val billingDependencies: BillingDependencies ) : BillingApi { companion object { @@ -74,7 +74,7 @@ internal class BillingApiImpl( } } - private val billingClient: BillingClient = BillingClient.newBuilder(context) + private val billingClient: BillingClient = BillingClient.newBuilder(billingDependencies.context) .setListener(purchasesUpdatedListener) .enablePendingPurchases( PendingPurchasesParams.newBuilder() @@ -98,6 +98,7 @@ internal class BillingApiImpl( override suspend fun queryProducts() { val products = queryProductsInternal() + Log.d(TAG, "Retrieved products with result: $products") } override suspend fun queryPurchases() { @@ -106,6 +107,7 @@ internal class BillingApiImpl( .build() val purchases = doOnConnectionReady { + Log.d(TAG, "Querying purchases.") billingClient.queryPurchasesAsync(param) } @@ -143,6 +145,7 @@ internal class BillingApiImpl( doOnConnectionReady { withContext(Dispatchers.Main) { + Log.d(TAG, "Launching billing flow.") billingClient.launchBillingFlow(activity, billingFlowParams) } } @@ -159,7 +162,7 @@ internal class BillingApiImpl( private suspend fun queryProductsInternal(): ProductDetailsResult { val productList = listOf( QueryProductDetailsParams.Product.newBuilder() - .setProductId("") // TODO [message-backups] where does the product id come from? + .setProductId(billingDependencies.getProductId()) .setProductType(ProductType.SUBS) .build() ) @@ -170,6 +173,7 @@ internal class BillingApiImpl( return withContext(Dispatchers.IO) { doOnConnectionReady { + Log.d(TAG, "Querying product details.") billingClient.queryProductDetails(params) } } diff --git a/billing/src/main/java/org/signal/billing/BillingFactory.kt b/billing/src/main/java/org/signal/billing/BillingFactory.kt index 925826b5ef..5f0ffb0c96 100644 --- a/billing/src/main/java/org/signal/billing/BillingFactory.kt +++ b/billing/src/main/java/org/signal/billing/BillingFactory.kt @@ -5,17 +5,17 @@ package org.signal.billing -import android.content.Context import org.signal.core.util.billing.BillingApi +import org.signal.core.util.billing.BillingDependencies /** * Play billing factory. Returns empty implementation if message backups are not enabled. */ object BillingFactory { @JvmStatic - fun create(context: Context, isBackupsAvailable: Boolean): BillingApi { + fun create(billingDependencies: BillingDependencies, isBackupsAvailable: Boolean): BillingApi { return if (isBackupsAvailable) { - BillingApiImpl(context) + BillingApiImpl(billingDependencies) } else { BillingApi.Empty } diff --git a/core-util/src/main/java/org/signal/core/util/billing/BillingDependencies.kt b/core-util/src/main/java/org/signal/core/util/billing/BillingDependencies.kt new file mode 100644 index 0000000000..c70e110944 --- /dev/null +++ b/core-util/src/main/java/org/signal/core/util/billing/BillingDependencies.kt @@ -0,0 +1,28 @@ +/* + * Copyright 2024 Signal Messenger, LLC + * SPDX-License-Identifier: AGPL-3.0-only + */ + +package org.signal.core.util.billing + +import android.content.Context + +/** + * Provides a dependency model by which the billing api can request different resources. + */ +interface BillingDependencies { + /** + * Application context + */ + val context: Context + + /** + * Get the product id from the donations configuration object. + */ + suspend fun getProductId(): String + + /** + * Get the base plan id from the donations configuration object. + */ + suspend fun getBasePlanId(): String +}