diff options
| author | Jonatan Rhodin <jonatan.rhodin@mullvad.net> | 2024-12-02 14:00:41 +0100 |
|---|---|---|
| committer | Jonatan Rhodin <jonatan.rhodin@mullvad.net> | 2024-12-03 10:28:16 +0100 |
| commit | 41e9feafddaabc9ab42793cd4242ec5059b4136b (patch) | |
| tree | 697adf3083ff88f75f23614d7bd85a32aa74caa9 /android/lib | |
| parent | ce8c122ca8983ce72d8362c7054ec318ed80b7f4 (diff) | |
| download | mullvadvpn-41e9feafddaabc9ab42793cd4242ec5059b4136b.tar.xz mullvadvpn-41e9feafddaabc9ab42793cd4242ec5059b4136b.zip | |
Add check for empty play purchase payment token
Diffstat (limited to 'android/lib')
5 files changed, 71 insertions, 2 deletions
diff --git a/android/lib/billing/build.gradle.kts b/android/lib/billing/build.gradle.kts index 46554cf956..d9b4c4dc68 100644 --- a/android/lib/billing/build.gradle.kts +++ b/android/lib/billing/build.gradle.kts @@ -62,6 +62,9 @@ dependencies { // Management service implementation(projects.lib.daemonGrpc) + // Logger + implementation(libs.kermit) + // Test dependencies testRuntimeOnly(Dependencies.junitJupiterEngine) diff --git a/android/lib/billing/src/main/kotlin/net/mullvad/mullvadvpn/lib/billing/BillingPaymentRepository.kt b/android/lib/billing/src/main/kotlin/net/mullvad/mullvadvpn/lib/billing/BillingPaymentRepository.kt index 540a8ad929..39cc584a57 100644 --- a/android/lib/billing/src/main/kotlin/net/mullvad/mullvadvpn/lib/billing/BillingPaymentRepository.kt +++ b/android/lib/billing/src/main/kotlin/net/mullvad/mullvadvpn/lib/billing/BillingPaymentRepository.kt @@ -2,8 +2,12 @@ package net.mullvad.mullvadvpn.lib.billing import android.app.Activity import arrow.core.Either +import arrow.core.flatMap +import arrow.core.left import arrow.core.raise.either import arrow.core.raise.ensure +import arrow.core.right +import co.touchlab.kermit.Logger import com.android.billingclient.api.BillingClient.BillingResponseCode import com.android.billingclient.api.Purchase import kotlinx.coroutines.flow.Flow @@ -19,6 +23,7 @@ import net.mullvad.mullvadvpn.lib.billing.extension.toPurchaseResult import net.mullvad.mullvadvpn.lib.billing.model.BillingException import net.mullvad.mullvadvpn.lib.billing.model.PurchaseEvent import net.mullvad.mullvadvpn.lib.model.PlayPurchase +import net.mullvad.mullvadvpn.lib.model.PlayPurchaseInitError import net.mullvad.mullvadvpn.lib.model.PlayPurchasePaymentToken import net.mullvad.mullvadvpn.lib.payment.PaymentRepository import net.mullvad.mullvadvpn.lib.payment.ProductIds @@ -78,7 +83,7 @@ class BillingPaymentRepository( // Get transaction id emit(PurchaseResult.FetchingObfuscationId) val obfuscatedId: PlayPurchasePaymentToken = - initialisePurchase() + initializePurchase() .fold( { emit(PurchaseResult.Error.TransactionIdError(productId, null)) @@ -148,7 +153,15 @@ class BillingPaymentRepository( .bind() } - private suspend fun initialisePurchase() = playPurchaseRepository.initializePlayPurchase() + private suspend fun initializePurchase() = + playPurchaseRepository.initializePlayPurchase().flatMap { + if (it.value.isNotEmpty()) { + it.right() + } else { + Logger.e("PlayPurchasePaymentToken is empty") + PlayPurchaseInitError.OtherError.left() + } + } private suspend fun verifyPurchase(purchase: Purchase) = playPurchaseRepository.verifyPlayPurchase( diff --git a/android/lib/billing/src/main/kotlin/net/mullvad/mullvadvpn/lib/billing/BillingRepository.kt b/android/lib/billing/src/main/kotlin/net/mullvad/mullvadvpn/lib/billing/BillingRepository.kt index 77eaea03a6..2e9f956d07 100644 --- a/android/lib/billing/src/main/kotlin/net/mullvad/mullvadvpn/lib/billing/BillingRepository.kt +++ b/android/lib/billing/src/main/kotlin/net/mullvad/mullvadvpn/lib/billing/BillingRepository.kt @@ -2,6 +2,7 @@ package net.mullvad.mullvadvpn.lib.billing import android.app.Activity import android.content.Context +import co.touchlab.kermit.Logger import com.android.billingclient.api.BillingClient import com.android.billingclient.api.BillingClient.BillingResponseCode import com.android.billingclient.api.BillingClientStateListener @@ -124,6 +125,11 @@ class BillingRepository(context: Context) { return try { ensureConnected() + if (obfuscatedId.isEmpty()) { + Logger.e("Obfuscated id is empty") + return BillingResult.newBuilder().setResponseCode(BillingResponseCode.ERROR).build() + } + val productDetailsParamsList = listOf( BillingFlowParams.ProductDetailsParams.newBuilder() diff --git a/android/lib/billing/src/test/kotlin/net/mullvad/mullvadvpn/lib/billing/BillingPaymentRepositoryTest.kt b/android/lib/billing/src/test/kotlin/net/mullvad/mullvadvpn/lib/billing/BillingPaymentRepositoryTest.kt index 48618feb2b..d04c40029e 100644 --- a/android/lib/billing/src/test/kotlin/net/mullvad/mullvadvpn/lib/billing/BillingPaymentRepositoryTest.kt +++ b/android/lib/billing/src/test/kotlin/net/mullvad/mullvadvpn/lib/billing/BillingPaymentRepositoryTest.kt @@ -184,6 +184,32 @@ class BillingPaymentRepositoryTest { } @Test + fun `purchaseProduct should return TransactionIdError when PlayPurchasePaymentToken is empty`() = + runTest { + // Arrange + val mockProductId = ProductId("MOCK") + val mockProductDetailsResult = mockk<ProductDetailsResult>() + val mockProductDetails: ProductDetails = mockk() + every { mockProductDetails.productId } returns mockProductId.value + every { mockProductDetailsResult.billingResult.responseCode } returns + BillingResponseCode.OK + every { mockProductDetailsResult.productDetailsList } returns listOf(mockProductDetails) + coEvery { mockBillingRepository.queryProducts(listOf(mockProductId.value)) } returns + mockProductDetailsResult + coEvery { mockPlayPurchaseRepository.initializePlayPurchase() } returns + PlayPurchasePaymentToken("").right() + + // Act, Assert + paymentRepository.purchaseProduct(mockProductId, mockk()).test { + assertIs<PurchaseResult.FetchingProducts>(awaitItem()) + assertIs<PurchaseResult.FetchingObfuscationId>(awaitItem()) + val result = awaitItem() + assertIs<PurchaseResult.Error.TransactionIdError>(result) + awaitComplete() + } + } + + @Test fun `purchaseProduct should return BillingError on billing unavailable from startPurchaseFlow`() = runTest { // Arrange diff --git a/android/lib/billing/src/test/kotlin/net/mullvad/mullvadvpn/lib/billing/BillingRepositoryTest.kt b/android/lib/billing/src/test/kotlin/net/mullvad/mullvadvpn/lib/billing/BillingRepositoryTest.kt index 3313e2d91e..bce573a6b6 100644 --- a/android/lib/billing/src/test/kotlin/net/mullvad/mullvadvpn/lib/billing/BillingRepositoryTest.kt +++ b/android/lib/billing/src/test/kotlin/net/mullvad/mullvadvpn/lib/billing/BillingRepositoryTest.kt @@ -206,6 +206,27 @@ class BillingRepositoryTest { } @Test + fun `starting purchase flow with empty transaction id should return error`() = runTest { + // Arrange + val transactionId = "" + val mockProductDetails: ProductDetails = mockk(relaxed = true) + val mockActivityProvider: () -> Activity = mockk() + every { mockBillingClient.isReady } returns true + every { mockBillingClient.connectionState } returns BillingClient.ConnectionState.CONNECTED + + // Act + val result = + billingRepository.startPurchaseFlow( + mockProductDetails, + transactionId, + mockActivityProvider, + ) + + // Assert + assertEquals(BillingResponseCode.ERROR, result.responseCode) + } + + @Test fun `when billing client query purchases returns OK query purchases should return OK`() = runTest { // Arrange |
