diff options
| author | Jonatan Rhodin <jonatan.rhodin@mullvad.net> | 2023-11-16 11:08:21 +0100 |
|---|---|---|
| committer | Jonatan Rhodin <jonatan.rhodin@mullvad.net> | 2023-11-16 11:08:21 +0100 |
| commit | 04c6609948a770aed30491c66c4c6d779bc71c92 (patch) | |
| tree | 4184b4e7a8c8ebfe8c4273e9f472779ee8f7bae9 /android/lib/payment | |
| parent | 67710f3e2ef57ecbe60c1bcb444ab047f11f79a5 (diff) | |
| parent | c8c896bc00b6b23ffaaf3a8708f03efb3ab3a0f2 (diff) | |
| download | mullvadvpn-04c6609948a770aed30491c66c4c6d779bc71c92.tar.xz mullvadvpn-04c6609948a770aed30491c66c4c6d779bc71c92.zip | |
Merge branch 'google-play-in-app-purchases-droid-277'
Diffstat (limited to 'android/lib/payment')
12 files changed, 171 insertions, 0 deletions
diff --git a/android/lib/payment/build.gradle.kts b/android/lib/payment/build.gradle.kts new file mode 100644 index 0000000000..23f945b4f9 --- /dev/null +++ b/android/lib/payment/build.gradle.kts @@ -0,0 +1,44 @@ +plugins { + id(Dependencies.Plugin.androidLibraryId) + id(Dependencies.Plugin.kotlinAndroidId) +} + +android { + namespace = "net.mullvad.mullvadvpn.lib.payment" + compileSdk = Versions.Android.compileSdkVersion + + defaultConfig { + minSdk = Versions.Android.minSdkVersion + testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner" + } + + compileOptions { + sourceCompatibility = JavaVersion.VERSION_17 + targetCompatibility = JavaVersion.VERSION_17 + } + + kotlinOptions { + jvmTarget = Versions.jvmTarget + } + + lint { + lintConfig = file("${rootProject.projectDir}/config/lint.xml") + abortOnError = true + warningsAsErrors = true + } + + packaging { + resources { + pickFirsts += setOf( + // Fixes packaging error caused by: jetified-junit-* + "META-INF/LICENSE.md", + "META-INF/LICENSE-notice.md" + ) + } + } +} + +dependencies { + implementation(Dependencies.Kotlin.stdlib) + implementation(Dependencies.KotlinX.coroutinesAndroid) +} diff --git a/android/lib/payment/src/main/AndroidManifest.xml b/android/lib/payment/src/main/AndroidManifest.xml new file mode 100644 index 0000000000..b2d3ea1235 --- /dev/null +++ b/android/lib/payment/src/main/AndroidManifest.xml @@ -0,0 +1,2 @@ +<?xml version="1.0" encoding="utf-8"?> +<manifest xmlns:android="http://schemas.android.com/apk/res/android" /> diff --git a/android/lib/payment/src/main/kotlin/net/mullvad/mullvadvpn/lib/payment/PaymentProvider.kt b/android/lib/payment/src/main/kotlin/net/mullvad/mullvadvpn/lib/payment/PaymentProvider.kt new file mode 100644 index 0000000000..431b406dc0 --- /dev/null +++ b/android/lib/payment/src/main/kotlin/net/mullvad/mullvadvpn/lib/payment/PaymentProvider.kt @@ -0,0 +1,3 @@ +package net.mullvad.mullvadvpn.lib.payment + +@JvmInline value class PaymentProvider(val paymentRepository: PaymentRepository?) diff --git a/android/lib/payment/src/main/kotlin/net/mullvad/mullvadvpn/lib/payment/PaymentRepository.kt b/android/lib/payment/src/main/kotlin/net/mullvad/mullvadvpn/lib/payment/PaymentRepository.kt new file mode 100644 index 0000000000..73fd0c061d --- /dev/null +++ b/android/lib/payment/src/main/kotlin/net/mullvad/mullvadvpn/lib/payment/PaymentRepository.kt @@ -0,0 +1,20 @@ +package net.mullvad.mullvadvpn.lib.payment + +import android.app.Activity +import kotlinx.coroutines.flow.Flow +import net.mullvad.mullvadvpn.lib.payment.model.PaymentAvailability +import net.mullvad.mullvadvpn.lib.payment.model.ProductId +import net.mullvad.mullvadvpn.lib.payment.model.PurchaseResult +import net.mullvad.mullvadvpn.lib.payment.model.VerificationResult + +interface PaymentRepository { + + fun purchaseProduct( + productId: ProductId, + activityProvider: () -> Activity + ): Flow<PurchaseResult> + + fun verifyPurchases(): Flow<VerificationResult> + + fun queryPaymentAvailability(): Flow<PaymentAvailability> +} diff --git a/android/lib/payment/src/main/kotlin/net/mullvad/mullvadvpn/lib/payment/ProductIds.kt b/android/lib/payment/src/main/kotlin/net/mullvad/mullvadvpn/lib/payment/ProductIds.kt new file mode 100644 index 0000000000..8754968891 --- /dev/null +++ b/android/lib/payment/src/main/kotlin/net/mullvad/mullvadvpn/lib/payment/ProductIds.kt @@ -0,0 +1,5 @@ +package net.mullvad.mullvadvpn.lib.payment + +object ProductIds { + const val OneMonth = "one_month" +} diff --git a/android/lib/payment/src/main/kotlin/net/mullvad/mullvadvpn/lib/payment/model/PaymentAvailability.kt b/android/lib/payment/src/main/kotlin/net/mullvad/mullvadvpn/lib/payment/model/PaymentAvailability.kt new file mode 100644 index 0000000000..012237d825 --- /dev/null +++ b/android/lib/payment/src/main/kotlin/net/mullvad/mullvadvpn/lib/payment/model/PaymentAvailability.kt @@ -0,0 +1,25 @@ +package net.mullvad.mullvadvpn.lib.payment.model + +sealed interface PaymentAvailability { + data object Loading : PaymentAvailability + + data class ProductsAvailable(val products: List<PaymentProduct>) : PaymentAvailability + + data object ProductsUnavailable : PaymentAvailability + + data object NoProductsFounds : PaymentAvailability + + sealed interface Error : PaymentAvailability { + data object BillingUnavailable : Error + + data object ServiceUnavailable : Error + + data object FeatureNotSupported : Error + + data object DeveloperError : Error + + data object ItemUnavailable : Error + + data class Other(val exception: Throwable) : Error + } +} diff --git a/android/lib/payment/src/main/kotlin/net/mullvad/mullvadvpn/lib/payment/model/PaymentProduct.kt b/android/lib/payment/src/main/kotlin/net/mullvad/mullvadvpn/lib/payment/model/PaymentProduct.kt new file mode 100644 index 0000000000..8945453d37 --- /dev/null +++ b/android/lib/payment/src/main/kotlin/net/mullvad/mullvadvpn/lib/payment/model/PaymentProduct.kt @@ -0,0 +1,7 @@ +package net.mullvad.mullvadvpn.lib.payment.model + +data class PaymentProduct( + val productId: ProductId, + val price: ProductPrice, + val status: PaymentStatus? +) diff --git a/android/lib/payment/src/main/kotlin/net/mullvad/mullvadvpn/lib/payment/model/PaymentStatus.kt b/android/lib/payment/src/main/kotlin/net/mullvad/mullvadvpn/lib/payment/model/PaymentStatus.kt new file mode 100644 index 0000000000..37574249a6 --- /dev/null +++ b/android/lib/payment/src/main/kotlin/net/mullvad/mullvadvpn/lib/payment/model/PaymentStatus.kt @@ -0,0 +1,6 @@ +package net.mullvad.mullvadvpn.lib.payment.model + +enum class PaymentStatus { + PENDING, + VERIFICATION_IN_PROGRESS +} diff --git a/android/lib/payment/src/main/kotlin/net/mullvad/mullvadvpn/lib/payment/model/ProductId.kt b/android/lib/payment/src/main/kotlin/net/mullvad/mullvadvpn/lib/payment/model/ProductId.kt new file mode 100644 index 0000000000..f14fefab28 --- /dev/null +++ b/android/lib/payment/src/main/kotlin/net/mullvad/mullvadvpn/lib/payment/model/ProductId.kt @@ -0,0 +1,3 @@ +package net.mullvad.mullvadvpn.lib.payment.model + +@JvmInline value class ProductId(val value: String) diff --git a/android/lib/payment/src/main/kotlin/net/mullvad/mullvadvpn/lib/payment/model/ProductPrice.kt b/android/lib/payment/src/main/kotlin/net/mullvad/mullvadvpn/lib/payment/model/ProductPrice.kt new file mode 100644 index 0000000000..5dc90db5fb --- /dev/null +++ b/android/lib/payment/src/main/kotlin/net/mullvad/mullvadvpn/lib/payment/model/ProductPrice.kt @@ -0,0 +1,3 @@ +package net.mullvad.mullvadvpn.lib.payment.model + +@JvmInline value class ProductPrice(val value: String) diff --git a/android/lib/payment/src/main/kotlin/net/mullvad/mullvadvpn/lib/payment/model/PurchaseResult.kt b/android/lib/payment/src/main/kotlin/net/mullvad/mullvadvpn/lib/payment/model/PurchaseResult.kt new file mode 100644 index 0000000000..f5b89bffe6 --- /dev/null +++ b/android/lib/payment/src/main/kotlin/net/mullvad/mullvadvpn/lib/payment/model/PurchaseResult.kt @@ -0,0 +1,34 @@ +package net.mullvad.mullvadvpn.lib.payment.model + +sealed interface PurchaseResult { + data object FetchingProducts : PurchaseResult + + data object FetchingObfuscationId : PurchaseResult + + data object BillingFlowStarted : PurchaseResult + + data object VerificationStarted : PurchaseResult + + sealed interface Completed : PurchaseResult { + data object Success : Completed + + data object Cancelled : Completed + + // This ends our part of the purchase flow. The rest is handled by Google and the api. + data object Pending : Completed + } + + sealed interface Error : PurchaseResult { + data class NoProductFound(val productId: ProductId) : Error + + data class FetchProductsError(val productId: ProductId, val exception: Throwable?) : Error + + data class TransactionIdError(val productId: ProductId, val exception: Throwable?) : Error + + data class BillingError(val exception: Throwable?) : Error + + data class VerificationError(val exception: Throwable?) : Error + } + + fun isTerminatingState(): Boolean = this is Completed || this is Error +} diff --git a/android/lib/payment/src/main/kotlin/net/mullvad/mullvadvpn/lib/payment/model/VerificationResult.kt b/android/lib/payment/src/main/kotlin/net/mullvad/mullvadvpn/lib/payment/model/VerificationResult.kt new file mode 100644 index 0000000000..725ea0af68 --- /dev/null +++ b/android/lib/payment/src/main/kotlin/net/mullvad/mullvadvpn/lib/payment/model/VerificationResult.kt @@ -0,0 +1,19 @@ +package net.mullvad.mullvadvpn.lib.payment.model + +sealed interface VerificationResult { + data object FetchingUnfinishedPurchases : VerificationResult + + data object VerificationStarted : VerificationResult + + // No verification was needed as there is no purchases to verify + data object NothingToVerify : VerificationResult + + data object Success : VerificationResult + + // Generic error, add more cases as needed + sealed interface Error : VerificationResult { + data class BillingError(val exception: Throwable?) : Error + + data class VerificationError(val exception: Throwable?) : Error + } +} |
