diff --git a/api-tester/src/customEntitlementComputation/kotlin/com/revenuecat/apitester/java/PurchasesAPI.java b/api-tester/src/customEntitlementComputation/kotlin/com/revenuecat/apitester/java/PurchasesAPI.java index 991676573..b24c94f4a 100644 --- a/api-tester/src/customEntitlementComputation/kotlin/com/revenuecat/apitester/java/PurchasesAPI.java +++ b/api-tester/src/customEntitlementComputation/kotlin/com/revenuecat/apitester/java/PurchasesAPI.java @@ -2,9 +2,7 @@ import android.content.Context; -import com.revenuecat.purchases.EntitlementVerificationMode; import com.revenuecat.purchases.Purchases; -import com.revenuecat.purchases.PurchasesConfiguration; import java.util.concurrent.ExecutorService; @@ -13,12 +11,7 @@ final class PurchasesAPI { static void checkConfiguration(final Context context, final ExecutorService executorService) { - PurchasesConfiguration build = new PurchasesConfiguration.Builder(context, "", "") - .service(executorService) - .entitlementVerificationMode(EntitlementVerificationMode.INFORMATIONAL) - .build(); - - Purchases.configure(build); + Purchases.configureInCustomEntitlementsComputationMode(context, "", ""); } static void check(final Purchases purchases) { diff --git a/api-tester/src/customEntitlementComputation/kotlin/com/revenuecat/apitester/kotlin/PurchasesAPI.kt b/api-tester/src/customEntitlementComputation/kotlin/com/revenuecat/apitester/kotlin/PurchasesAPI.kt index 7e8b8f6cf..4bddff228 100644 --- a/api-tester/src/customEntitlementComputation/kotlin/com/revenuecat/apitester/kotlin/PurchasesAPI.kt +++ b/api-tester/src/customEntitlementComputation/kotlin/com/revenuecat/apitester/kotlin/PurchasesAPI.kt @@ -1,26 +1,16 @@ package com.revenuecat.apitester.kotlin import android.content.Context -import com.revenuecat.purchases.EntitlementVerificationMode import com.revenuecat.purchases.Purchases -import com.revenuecat.purchases.PurchasesConfiguration -import com.revenuecat.purchases.models.BillingFeature -import java.util.concurrent.ExecutorService @Suppress("unused", "UNUSED_VARIABLE", "EmptyFunctionBlock") private class PurchasesAPI { @Suppress("ForbiddenComment") - fun checkConfiguration(context: Context, executorService: ExecutorService) { - val features: List = ArrayList() + fun checkConfiguration(context: Context) { val configured: Boolean = Purchases.isConfigured - val build = PurchasesConfiguration.Builder(context, apiKey = "", appUserID = "") - .service(executorService) - .entitlementVerificationMode(EntitlementVerificationMode.INFORMATIONAL) - .build() - - Purchases.configure(build) + Purchases.configureInCustomEntitlementsComputationMode(context, apiKey = "", appUserID = "") } fun check(purchases: Purchases) { diff --git a/api-tester/src/defaults/java/com/revenuecat/apitester/java/PurchasesAPI.java b/api-tester/src/defaults/java/com/revenuecat/apitester/java/PurchasesAPI.java index 6e34859f0..219850429 100644 --- a/api-tester/src/defaults/java/com/revenuecat/apitester/java/PurchasesAPI.java +++ b/api-tester/src/defaults/java/com/revenuecat/apitester/java/PurchasesAPI.java @@ -96,19 +96,11 @@ static void check(final Purchases purchases, final Map attribute } static void checkConfiguration(final Context context, - final ExecutorService executorService) { + final ExecutorService executorService, + final PurchasesConfiguration purchasesConfiguration) { final boolean configured = Purchases.isConfigured(); - PurchasesConfiguration build = new PurchasesConfiguration.Builder(context, "") - .appUserID("") - .observerMode(true) - .observerMode(false) - .service(executorService) - .diagnosticsEnabled(true) - .entitlementVerificationMode(EntitlementVerificationMode.INFORMATIONAL) - .build(); - - Purchases.configure(build); + Purchases.configure(purchasesConfiguration); final boolean debugLogs = Purchases.getDebugLogsEnabled(); } diff --git a/api-tester/src/defaults/kotlin/com/revenuecat/apitester/kotlin/PurchasesAPI.kt b/api-tester/src/defaults/kotlin/com/revenuecat/apitester/kotlin/PurchasesAPI.kt index 4fb7900de..b22ff6259 100644 --- a/api-tester/src/defaults/kotlin/com/revenuecat/apitester/kotlin/PurchasesAPI.kt +++ b/api-tester/src/defaults/kotlin/com/revenuecat/apitester/kotlin/PurchasesAPI.kt @@ -3,7 +3,6 @@ package com.revenuecat.apitester.kotlin import android.content.Context import com.revenuecat.purchases.CacheFetchPolicy import com.revenuecat.purchases.CustomerInfo -import com.revenuecat.purchases.EntitlementVerificationMode import com.revenuecat.purchases.ExperimentalPreviewRevenueCatPurchasesAPI import com.revenuecat.purchases.Purchases import com.revenuecat.purchases.PurchasesConfiguration @@ -135,21 +134,15 @@ private class PurchasesAPI { } @Suppress("ForbiddenComment") - fun checkConfiguration(context: Context, executorService: ExecutorService) { + fun checkConfiguration( + context: Context, + executorService: ExecutorService, + purchasesConfiguration: PurchasesConfiguration, + ) { val features: List = ArrayList() val configured: Boolean = Purchases.isConfigured - val build = PurchasesConfiguration.Builder(context, apiKey = "") - .appUserID("") - .observerMode(true) - .observerMode(false) - .service(executorService) - .diagnosticsEnabled(true) - .entitlementVerificationMode(EntitlementVerificationMode.INFORMATIONAL) - .informationalVerificationModeAndDiagnosticsEnabled(true) - .build() - - Purchases.configure(build) + Purchases.configure(purchasesConfiguration) Purchases.debugLogsEnabled = true } diff --git a/api-tester/src/main/java/com/revenuecat/apitester/java/PurchasesCommonAPI.java b/api-tester/src/main/java/com/revenuecat/apitester/java/PurchasesCommonAPI.java index 177cfbf37..1c8a620aa 100644 --- a/api-tester/src/main/java/com/revenuecat/apitester/java/PurchasesCommonAPI.java +++ b/api-tester/src/main/java/com/revenuecat/apitester/java/PurchasesCommonAPI.java @@ -125,6 +125,15 @@ static void checkConfiguration(final Context context, Purchases.setProxyURL(new URL("")); final URL proxyURL = Purchases.getProxyURL(); + PurchasesConfiguration build = new PurchasesConfiguration.Builder(context, "") + .appUserID("") + .observerMode(true) + .observerMode(false) + .service(executorService) + .diagnosticsEnabled(true) + .entitlementVerificationMode(EntitlementVerificationMode.INFORMATIONAL) + .build(); + final Purchases instance = Purchases.getSharedInstance(); } diff --git a/api-tester/src/main/java/com/revenuecat/apitester/kotlin/PurchasesCommonAPI.kt b/api-tester/src/main/java/com/revenuecat/apitester/kotlin/PurchasesCommonAPI.kt index 6cfb47d53..cfd18f9a8 100644 --- a/api-tester/src/main/java/com/revenuecat/apitester/kotlin/PurchasesCommonAPI.kt +++ b/api-tester/src/main/java/com/revenuecat/apitester/kotlin/PurchasesCommonAPI.kt @@ -3,6 +3,7 @@ package com.revenuecat.apitester.kotlin import android.app.Activity import android.content.Context import com.revenuecat.purchases.CustomerInfo +import com.revenuecat.purchases.EntitlementVerificationMode import com.revenuecat.purchases.ExperimentalPreviewRevenueCatPurchasesAPI import com.revenuecat.purchases.LogHandler import com.revenuecat.purchases.LogLevel @@ -12,6 +13,7 @@ import com.revenuecat.purchases.ProductType import com.revenuecat.purchases.PurchaseParams import com.revenuecat.purchases.PurchaseResult import com.revenuecat.purchases.Purchases +import com.revenuecat.purchases.PurchasesConfiguration import com.revenuecat.purchases.PurchasesError import com.revenuecat.purchases.awaitOfferings import com.revenuecat.purchases.awaitPurchase @@ -28,6 +30,7 @@ import com.revenuecat.purchases.models.StoreTransaction import com.revenuecat.purchases.models.SubscriptionOption import com.revenuecat.purchases.purchaseWith import java.net.URL +import java.util.concurrent.ExecutorService @OptIn(ExperimentalPreviewRevenueCatPurchasesAPI::class) @Suppress("unused", "UNUSED_VARIABLE", "EmptyFunctionBlock") @@ -136,7 +139,7 @@ private class PurchasesCommonAPI { } @Suppress("ForbiddenComment") - fun checkConfiguration(context: Context) { + fun checkConfiguration(context: Context, executorService: ExecutorService) { val features: List = ArrayList() val configured: Boolean = Purchases.isConfigured @@ -149,6 +152,16 @@ private class PurchasesCommonAPI { Purchases.proxyURL = URL("") val url: URL? = Purchases.proxyURL + val build: PurchasesConfiguration = PurchasesConfiguration.Builder(context, apiKey = "") + .appUserID("") + .observerMode(true) + .observerMode(false) + .service(executorService) + .diagnosticsEnabled(true) + .entitlementVerificationMode(EntitlementVerificationMode.INFORMATIONAL) + .informationalVerificationModeAndDiagnosticsEnabled(true) + .build() + val instance: Purchases = Purchases.sharedInstance } diff --git a/examples/CustomEntitlementComputationSample/app/src/main/java/com/revenuecat/sample/MainApplication.kt b/examples/CustomEntitlementComputationSample/app/src/main/java/com/revenuecat/sample/MainApplication.kt index 1bb78000a..10225a673 100644 --- a/examples/CustomEntitlementComputationSample/app/src/main/java/com/revenuecat/sample/MainApplication.kt +++ b/examples/CustomEntitlementComputationSample/app/src/main/java/com/revenuecat/sample/MainApplication.kt @@ -3,7 +3,6 @@ package com.revenuecat.sample import android.app.Application import com.revenuecat.purchases.LogLevel import com.revenuecat.purchases.Purchases -import com.revenuecat.purchases.PurchasesConfiguration import com.revenuecat.sample.data.Constants class MainApplication : Application() { @@ -26,12 +25,10 @@ class MainApplication : Application() { - An appUserID is required when doing a custom entitlement computation implementation. Read more about Identifying Users here: https://docs.revenuecat.com/docs/user-ids */ - val builder = PurchasesConfiguration.Builder( + Purchases.configureInCustomEntitlementsComputationMode( this, Constants.GOOGLE_API_KEY, Constants.defaultAppUserID ) - - Purchases.configure(builder.build()) } } diff --git a/purchases/src/customEntitlementComputation/kotlin/com/revenuecat/purchases/Purchases.kt b/purchases/src/customEntitlementComputation/kotlin/com/revenuecat/purchases/Purchases.kt index 3b6c3d9d9..56a725c29 100644 --- a/purchases/src/customEntitlementComputation/kotlin/com/revenuecat/purchases/Purchases.kt +++ b/purchases/src/customEntitlementComputation/kotlin/com/revenuecat/purchases/Purchases.kt @@ -224,16 +224,24 @@ class Purchases internal constructor( /** * Configures an instance of the Purchases SDK with a specified API key. The instance will * be set as a singleton. You should access the singleton instance using [Purchases.sharedInstance] - * @param configuration: the [PurchasesConfiguration] object you wish to use to configure [Purchases]. + * @param context: the Application context object of your Application. + * @param apiKey: the API Key for your app. Obtained from the RevenueCat dashboard. + * @param appUserID: a unique id for identifying the user. * @return An instantiated `[Purchases] object that has been set as a singleton. */ @JvmStatic - fun configure( - configuration: PurchasesConfiguration, + fun configureInCustomEntitlementsComputationMode( + context: Context, + apiKey: String, + appUserID: String, ): Purchases { if (isConfigured) { infoLog(ConfigureStrings.INSTANCE_ALREADY_EXISTS) } + val configuration = PurchasesConfiguration.Builder(context, apiKey) + .appUserID(appUserID) + .dangerousSettings(DangerousSettings(customEntitlementComputation = true)) + .build() return PurchasesFactory().createPurchases( configuration, platformInfo, diff --git a/purchases/src/customEntitlementComputation/kotlin/com/revenuecat/purchases/PurchasesConfiguration.kt b/purchases/src/customEntitlementComputation/kotlin/com/revenuecat/purchases/PurchasesConfiguration.kt deleted file mode 100644 index 08b23a71e..000000000 --- a/purchases/src/customEntitlementComputation/kotlin/com/revenuecat/purchases/PurchasesConfiguration.kt +++ /dev/null @@ -1,85 +0,0 @@ -package com.revenuecat.purchases - -import android.content.Context -import java.util.concurrent.ExecutorService - -open class PurchasesConfiguration(builder: Builder) { - - val context: Context - val apiKey: String - val appUserID: String - val observerMode: Boolean - val service: ExecutorService? - internal val store: Store - internal val diagnosticsEnabled: Boolean - val dangerousSettings: DangerousSettings - val verificationMode: EntitlementVerificationMode - - init { - this.context = builder.context - this.apiKey = builder.apiKey - this.appUserID = builder.appUserID - this.observerMode = builder.observerMode - this.service = builder.service - this.store = builder.store - this.diagnosticsEnabled = builder.diagnosticsEnabled - this.verificationMode = builder.verificationMode - this.dangerousSettings = builder.dangerousSettings - } - - open class Builder( - @get:JvmSynthetic internal val context: Context, - @get:JvmSynthetic internal val apiKey: String, - @get:JvmSynthetic internal val appUserID: String, - ) { - @set:JvmSynthetic @get:JvmSynthetic - internal var observerMode: Boolean = false - - @set:JvmSynthetic @get:JvmSynthetic - internal var service: ExecutorService? = null - - @set:JvmSynthetic @get:JvmSynthetic - internal var store: Store = Store.PLAY_STORE - - @set:JvmSynthetic @get:JvmSynthetic - internal var diagnosticsEnabled: Boolean = false - - @set:JvmSynthetic @get:JvmSynthetic - internal var verificationMode: EntitlementVerificationMode = EntitlementVerificationMode.default - - @set:JvmSynthetic @get:JvmSynthetic - internal var dangerousSettings: DangerousSettings = DangerousSettings(customEntitlementComputation = true) - - fun service(service: ExecutorService) = apply { - this.service = service - } - - /** - * Sets the [EntitlementVerificationMode] to perform signature verification of requests to the - * RevenueCat backend. - * - * When changing from [EntitlementVerificationMode.DISABLED] to other modes, the SDK will clear the - * CustomerInfo cache. - * This means users will need to connect to the internet to get their entitlements back. - * - * The result of the verification can be obtained from [EntitlementInfos.verification] or - * [EntitlementInfo.verification]. - * - * Default mode is disabled. Please see https://rev.cat/trusted-entitlements for more info. - */ - fun entitlementVerificationMode(verificationMode: EntitlementVerificationMode) = apply { - this.verificationMode = verificationMode - } - - /** - * Only use a Dangerous Setting if suggested by RevenueCat support team. - */ - fun dangerousSettings(dangerousSettings: DangerousSettings) = apply { - this.dangerousSettings = dangerousSettings.copy(customEntitlementComputation = true) - } - - open fun build(): PurchasesConfiguration { - return PurchasesConfiguration(this) - } - } -} diff --git a/purchases/src/defaults/kotlin/com/revenuecat/purchases/PurchasesConfiguration.kt b/purchases/src/main/kotlin/com/revenuecat/purchases/PurchasesConfiguration.kt similarity index 100% rename from purchases/src/defaults/kotlin/com/revenuecat/purchases/PurchasesConfiguration.kt rename to purchases/src/main/kotlin/com/revenuecat/purchases/PurchasesConfiguration.kt diff --git a/purchases/src/testDefaults/kotlin/com/revenuecat/purchases/PurchasesConfigurationTest.kt b/purchases/src/test/java/com/revenuecat/purchases/PurchasesConfigurationTest.kt similarity index 100% rename from purchases/src/testDefaults/kotlin/com/revenuecat/purchases/PurchasesConfigurationTest.kt rename to purchases/src/test/java/com/revenuecat/purchases/PurchasesConfigurationTest.kt diff --git a/purchases/src/testCustomEntitlementComputation/kotlin/com/revenuecat/purchases/PurchasesConfigurationTest.kt b/purchases/src/testCustomEntitlementComputation/kotlin/com/revenuecat/purchases/PurchasesConfigurationTest.kt deleted file mode 100644 index 4da7f7320..000000000 --- a/purchases/src/testCustomEntitlementComputation/kotlin/com/revenuecat/purchases/PurchasesConfigurationTest.kt +++ /dev/null @@ -1,66 +0,0 @@ -package com.revenuecat.purchases - -import android.content.Context -import androidx.test.ext.junit.runners.AndroidJUnit4 -import io.mockk.mockk -import org.assertj.core.api.Assertions.assertThat -import org.junit.Before -import org.junit.Test -import org.junit.runner.RunWith -import java.util.concurrent.ExecutorService - -@RunWith(AndroidJUnit4::class) -class PurchasesConfigurationTest { - - private val apiKey = "test-api-key" - private val appUserId = "test-app-user-id" - - private lateinit var context: Context - - private lateinit var builder: PurchasesConfiguration.Builder - - @Before - fun setup() { - context = mockk() - - builder = PurchasesConfiguration.Builder(context, apiKey, appUserId) - } - - @Test - fun `PurchasesConfiguration has expected default parameters`() { - val purchasesConfiguration = builder.build() - assertThat(purchasesConfiguration.apiKey).isEqualTo(apiKey) - assertThat(purchasesConfiguration.context).isEqualTo(context) - assertThat(purchasesConfiguration.appUserID).isEqualTo(appUserId) - assertThat(purchasesConfiguration.observerMode).isFalse - assertThat(purchasesConfiguration.service).isNull() - assertThat(purchasesConfiguration.store).isEqualTo(Store.PLAY_STORE) - assertThat(purchasesConfiguration.diagnosticsEnabled).isFalse - assertThat(purchasesConfiguration.verificationMode).isEqualTo(EntitlementVerificationMode.DISABLED) - assertThat(purchasesConfiguration.dangerousSettings) - .isEqualTo(DangerousSettings(autoSyncPurchases = true, customEntitlementComputation = true)) - } - - @Test - fun `PurchasesConfiguration sets service correctly`() { - val serviceMock: ExecutorService = mockk() - val purchasesConfiguration = builder.service(serviceMock).build() - assertThat(purchasesConfiguration.service).isEqualTo(serviceMock) - } - - @Test - fun `PurchasesConfiguration sets informational mode correctly`() { - val purchasesConfiguration = builder.entitlementVerificationMode( - EntitlementVerificationMode.INFORMATIONAL, - ).build() - assertThat(purchasesConfiguration.verificationMode).isEqualTo(EntitlementVerificationMode.INFORMATIONAL) - } - - @Test - fun `PurchasesConfiguration sets dangerous settings correctly`() { - val dangerousSettings = DangerousSettings(autoSyncPurchases = false) - val purchasesConfiguration = builder.dangerousSettings(dangerousSettings).build() - assertThat(purchasesConfiguration.dangerousSettings.autoSyncPurchases).isFalse - assertThat(purchasesConfiguration.dangerousSettings.customEntitlementComputation).isTrue - } -} diff --git a/purchases/src/testCustomEntitlementComputation/kotlin/com/revenuecat/purchases/PurchasesConfigureTest.kt b/purchases/src/testCustomEntitlementComputation/kotlin/com/revenuecat/purchases/PurchasesConfigureTest.kt index 16f1a5392..0515d2499 100644 --- a/purchases/src/testCustomEntitlementComputation/kotlin/com/revenuecat/purchases/PurchasesConfigureTest.kt +++ b/purchases/src/testCustomEntitlementComputation/kotlin/com/revenuecat/purchases/PurchasesConfigureTest.kt @@ -21,7 +21,7 @@ internal class PurchasesConfigureTest : BasePurchasesTest() { fun `Setting platform info sets it in the AppConfig when configuring the SDK`() { val expected = PlatformInfo("flavor", "version") Purchases.platformInfo = expected - Purchases.configure(PurchasesConfiguration.Builder(mockContext, "api", "appUserId").build()) + Purchases.configureInCustomEntitlementsComputationMode(mockContext, "api", "appUserId") assertThat(Purchases.sharedInstance.purchasesOrchestrator.appConfig.platformInfo).isEqualTo(expected) } @@ -29,7 +29,15 @@ internal class PurchasesConfigureTest : BasePurchasesTest() { fun `Setting proxy URL info sets it in the HttpClient when configuring the SDK`() { val expected = URL("https://a-proxy.com") Purchases.proxyURL = expected - Purchases.configure(PurchasesConfiguration.Builder(mockContext, "api", "appUserId").build()) + Purchases.configureInCustomEntitlementsComputationMode(mockContext, "api", "appUserId") assertThat(Purchases.sharedInstance.purchasesOrchestrator.appConfig.baseURL).isEqualTo(expected) } + + @Test + fun `Configuring in custom entitlements mode enables dangerous setting`() { + Purchases.configureInCustomEntitlementsComputationMode(mockContext, "api", "appUserId") + assertThat( + Purchases.sharedInstance.purchasesOrchestrator.appConfig.dangerousSettings.customEntitlementComputation + ).isTrue + } }