diff --git a/app/build.gradle b/app/build.gradle
index a168b150927ee68a3a1c91b224464313dba0c1c3..0ee765ad9d6a1c0668f71fb5339a0dbaf5ee0d7b 100644
--- a/app/build.gradle
+++ b/app/build.gradle
@@ -79,20 +79,17 @@ dependencies {
     //Kotlin
     implementation "androidx.core:core-ktx:1.8.0"
 
-    //Lifecycle
-    def lifecycle_version = "2.5.0"
-    implementation "androidx.lifecycle:lifecycle-livedata-ktx:$lifecycle_version"
-    implementation "androidx.lifecycle:lifecycle-viewmodel-ktx:$lifecycle_version"
+    //androidx
+    implementation "androidx.lifecycle:lifecycle-livedata-ktx:$rootProject.ext.androidx_version"
+    implementation "androidx.lifecycle:lifecycle-viewmodel-ktx:$rootProject.ext.androidx_version"
+    implementation "androidx.navigation:navigation-fragment-ktx:$rootProject.ext.androidx_version"
+    implementation "androidx.navigation:navigation-ui-ktx:$rootProject.ext.androidx_version"
 
     //Koin
     def koin_version = "3.2.0"
     implementation "io.insert-koin:koin-core:$koin_version"
     implementation "io.insert-koin:koin-android:$koin_version"
 
-    //Navigation
-    implementation "androidx.navigation:navigation-fragment-ktx:$rootProject.ext.nav_version"
-    implementation "androidx.navigation:navigation-ui-ktx:$rootProject.ext.nav_version"
-
     //ViewBinding
     implementation 'com.github.kirich1409:viewbindingpropertydelegate-noreflection:1.5.6'
 
@@ -114,10 +111,13 @@ dependencies {
     //ExoPlayer
     implementation 'com.google.android.exoplayer:exoplayer:2.18.1'
 
-    //Firebase crash reports for gplay flavor
+    //Firebase crash reports
     gplayImplementation 'com.google.firebase:firebase-crashlytics-ktx:18.2.12'
     gplayImplementation 'com.google.firebase:firebase-analytics-ktx:21.1.0'
 
+    //Subscriptions
+    gplayImplementation 'com.android.billingclient:billing-ktx:5.0.0'
+
     //test
     testImplementation 'junit:junit:4.13.2'
     androidTestImplementation 'androidx.test.ext:junit:1.1.3'
diff --git a/app/src/fdroid/java/org/futo/circles/subscriptions/SubscriptionManagerProvider.kt b/app/src/fdroid/java/org/futo/circles/subscriptions/SubscriptionManagerProvider.kt
new file mode 100644
index 0000000000000000000000000000000000000000..6d68ea0a6a81e895668ec274ccce593d21f7f5c8
--- /dev/null
+++ b/app/src/fdroid/java/org/futo/circles/subscriptions/SubscriptionManagerProvider.kt
@@ -0,0 +1,13 @@
+package org.futo.circles.subscriptions
+
+import android.app.Activity
+import org.futo.circles.R
+
+object SubscriptionManagerProvider : SubscriptionProvider {
+
+    override fun getManager(
+        activity: Activity,
+        itemPurchaseListener: ItemPurchasedListener
+    ): SubscriptionManager =
+        throw IllegalStateException(activity.getString(R.string.flavour_does_not_support_subscriptions))
+}
\ No newline at end of file
diff --git a/app/src/gplay/java/org/futo/circles/subscriptions/SubscriptionManagerProvider.kt b/app/src/gplay/java/org/futo/circles/subscriptions/SubscriptionManagerProvider.kt
new file mode 100644
index 0000000000000000000000000000000000000000..370d6496b69a405a359530a1928577a214ca4ee4
--- /dev/null
+++ b/app/src/gplay/java/org/futo/circles/subscriptions/SubscriptionManagerProvider.kt
@@ -0,0 +1,12 @@
+package org.futo.circles.subscriptions
+
+import android.app.Activity
+import org.futo.circles.subscriptions.google.GoogleSubscriptionsManager
+
+object SubscriptionManagerProvider : SubscriptionProvider {
+
+    override fun getManager(
+        activity: Activity,
+        itemPurchaseListener: ItemPurchasedListener
+    ): SubscriptionManager = GoogleSubscriptionsManager(activity, itemPurchaseListener)
+}
\ No newline at end of file
diff --git a/app/src/gplay/java/org/futo/circles/subscriptions/google/GoogleSubscriptionsManager.kt b/app/src/gplay/java/org/futo/circles/subscriptions/google/GoogleSubscriptionsManager.kt
new file mode 100644
index 0000000000000000000000000000000000000000..f8e8330d3260bf6a6329f4d114c142a87063682c
--- /dev/null
+++ b/app/src/gplay/java/org/futo/circles/subscriptions/google/GoogleSubscriptionsManager.kt
@@ -0,0 +1,154 @@
+package org.futo.circles.subscriptions.google
+
+import android.app.Activity
+import androidx.appcompat.app.AppCompatActivity
+import androidx.lifecycle.DefaultLifecycleObserver
+import androidx.lifecycle.LifecycleOwner
+import com.android.billingclient.api.*
+import com.android.billingclient.api.BillingClient.BillingResponseCode.*
+import kotlinx.coroutines.suspendCancellableCoroutine
+import org.futo.circles.R
+import org.futo.circles.extensions.Response
+import org.futo.circles.extensions.onBG
+import org.futo.circles.model.SubscriptionListItem
+import org.futo.circles.subscriptions.ItemPurchasedListener
+import org.futo.circles.subscriptions.SubscriptionManager
+import kotlin.coroutines.resume
+
+class GoogleSubscriptionsManager(
+    private val activity: Activity,
+    private val itemPurchasedListener: ItemPurchasedListener
+) : SubscriptionManager {
+
+
+    private val purchasesUpdatedListener =
+        PurchasesUpdatedListener { billingResult, purchases ->
+            purchases?.let {
+                if (billingResult.responseCode == OK)
+                    itemPurchasedListener.onItemPurchased(
+                        purchases.lastOrNull()?.originalJson ?: ""
+                    )
+                else itemPurchasedListener.onPurchaseFailed(billingResult.responseCode)
+            }
+        }
+
+    private val client = BillingClient.newBuilder(activity)
+        .setListener(purchasesUpdatedListener)
+        .enablePendingPurchases()
+        .build()
+
+
+    init {
+        (activity as? AppCompatActivity)?.lifecycle?.addObserver(object : DefaultLifecycleObserver {
+            override fun onDestroy(owner: LifecycleOwner) {
+                client.endConnection()
+                super.onDestroy(owner)
+            }
+        })
+    }
+
+    override suspend fun getDetails(productIds: List<String>): Response<List<SubscriptionListItem>> =
+        when (val code =
+            client.isFeatureSupported(BillingClient.FeatureType.SUBSCRIPTIONS).responseCode) {
+            OK -> queryDetails(productIds).toSubscriptionListItemsResponse(activity.applicationContext)
+            SERVICE_DISCONNECTED, SERVICE_UNAVAILABLE, BILLING_UNAVAILABLE -> onBG {
+                tryConnectAndDo { queryDetails(productIds).toSubscriptionListItemsResponse(activity.applicationContext) }
+            }
+            else -> getErrorResponseForCode(code)
+        }
+
+
+    override suspend fun purchaseProduct(productId: String): Response<Unit> {
+        val detailsResponse = queryDetails(listOf(productId))
+        val productDetails =
+            (detailsResponse as? Response.Success)?.data?.firstOrNull { it.productId == productId }
+                ?: return getErrorResponseForCode(ERROR)
+
+        return when (val code = client
+            .isFeatureSupported(BillingClient.FeatureType.SUBSCRIPTIONS).responseCode) {
+            OK -> purchase(productDetails)
+            SERVICE_DISCONNECTED, SERVICE_UNAVAILABLE, BILLING_UNAVAILABLE -> onBG {
+                tryConnectAndDo { purchase(productDetails) }
+            }
+            ITEM_ALREADY_OWNED -> Response.Success(Unit)
+            else -> getErrorResponseForCode(code)
+        }
+    }
+
+    private suspend inline fun <T> tryConnectAndDo(action: () -> Response<T>): Response<T> =
+        when (val connectResult = client.tryConnect()) {
+            is Response.Success -> if (connectResult.data) action()
+            else getErrorResponseForCode(SERVICE_DISCONNECTED)
+            is Response.Error -> connectResult
+        }
+
+
+    private suspend fun BillingClient.tryConnect(): Response<Boolean> =
+        suspendCancellableCoroutine { continuation ->
+            startConnection(object : BillingClientStateListener {
+                override fun onBillingSetupFinished(billingResult: com.android.billingclient.api.BillingResult) {
+                    if (continuation.isCancelled || continuation.isCompleted) return
+                    continuation.resume(
+                        when (billingResult.responseCode) {
+                            OK -> Response.Success(true)
+                            else -> getErrorResponseForCode(billingResult.responseCode)
+                        }
+                    )
+                }
+
+                override fun onBillingServiceDisconnected() {
+                    if (continuation.isCancelled || continuation.isCompleted) return
+                    continuation.resume(getErrorResponseForCode(SERVICE_DISCONNECTED))
+                }
+            })
+        }
+
+    private suspend fun queryDetails(productIds: List<String>): Response<List<ProductDetails>> {
+        val params = QueryProductDetailsParams.newBuilder()
+            .setProductList(productIds.map {
+                QueryProductDetailsParams.Product.newBuilder()
+                    .setProductId(it)
+                    .setProductType(BillingClient.ProductType.SUBS)
+                    .build()
+            })
+
+        val productDetailsResult = onBG { client.queryProductDetails(params.build()) }
+
+        return if (productDetailsResult.billingResult.responseCode == OK) {
+            productDetailsResult.productDetailsList?.filter { productIds.contains(it.productId) }
+                ?.takeIf { it.isNotEmpty() }
+                ?.let { Response.Success(data = it) }
+                ?: getErrorResponseForCode(code = ERROR)
+        } else {
+            getErrorResponseForCode(productDetailsResult.billingResult.responseCode)
+        }
+    }
+
+    private fun purchase(productDetails: ProductDetails): Response<Unit> {
+        val productDetailsParamsList = listOf(
+            BillingFlowParams.ProductDetailsParams.newBuilder()
+                .setProductDetails(productDetails)
+                .build()
+        )
+
+        val billingFlowParams = BillingFlowParams.newBuilder()
+            .setProductDetailsParamsList(productDetailsParamsList)
+            .build()
+
+        return when (val code =
+            client.launchBillingFlow(activity, billingFlowParams).responseCode) {
+            OK -> Response.Success(Unit)
+            else -> getErrorResponseForCode(code)
+        }
+    }
+
+    private fun getErrorResponseForCode(code: Int) = when (code) {
+        FEATURE_NOT_SUPPORTED -> Response.Error(activity.getString(R.string.feature_not_supported))
+        SERVICE_DISCONNECTED, SERVICE_UNAVAILABLE, BILLING_UNAVAILABLE -> Response.Error(activity.getString(R.string.service_unavailable))
+        ITEM_UNAVAILABLE -> Response.Error(activity.getString(R.string.item_unavailable))
+        USER_CANCELED -> Response.Error(activity.getString(R.string.user_canceled))
+        ITEM_NOT_OWNED -> Response.Error(activity.getString(R.string.item_not_owned))
+        DEVELOPER_ERROR -> Response.Error(activity.getString(R.string.developer_error))
+        else -> Response.Error(activity.getString(R.string.purchase_failed_format, code))
+    }
+}
\ No newline at end of file
diff --git a/app/src/gplay/java/org/futo/circles/subscriptions/google/ProductDetailsMapping.kt b/app/src/gplay/java/org/futo/circles/subscriptions/google/ProductDetailsMapping.kt
new file mode 100644
index 0000000000000000000000000000000000000000..29d5a9f50c68bbf2544bd1aef8d9967e2c17bf27
--- /dev/null
+++ b/app/src/gplay/java/org/futo/circles/subscriptions/google/ProductDetailsMapping.kt
@@ -0,0 +1,28 @@
+package org.futo.circles.subscriptions.google
+
+import android.content.Context
+import com.android.billingclient.api.ProductDetails
+import org.futo.circles.extensions.Response
+import org.futo.circles.model.SubscriptionListItem
+import org.futo.circles.subscriptions.formatIsoPeriod
+
+fun ProductDetails.toSubscriptionListItem(context: Context): SubscriptionListItem {
+    val productOffer =
+        subscriptionOfferDetails?.last()?.pricingPhases?.pricingPhaseList?.last()
+
+    return SubscriptionListItem(
+        id = productId,
+        name = name,
+        description = description,
+        price = productOffer?.formattedPrice ?: "",
+        duration = productOffer?.billingPeriod?.formatIsoPeriod(context) ?: ""
+    )
+}
+
+fun Response<List<ProductDetails>>.toSubscriptionListItemsResponse(context: Context): Response<List<SubscriptionListItem>> =
+    when (val response = this) {
+        is Response.Success -> Response.Success(response.data.map {
+            it.toSubscriptionListItem(context)
+        })
+        is Response.Error -> response
+    }
\ No newline at end of file
diff --git a/app/src/main/java/org/futo/circles/core/Constants.kt b/app/src/main/java/org/futo/circles/core/Constants.kt
index b6c5ad8b05fe5b89ee83d63722751142640ff20a..eaff532c22140cf34e025fe08957be7fd9189c0a 100644
--- a/app/src/main/java/org/futo/circles/core/Constants.kt
+++ b/app/src/main/java/org/futo/circles/core/Constants.kt
@@ -2,7 +2,8 @@ package org.futo.circles.core
 
 const val FILE_PROVIDER_AUTHORITY_PREFIX = ".provider"
 
-const val REGISTRATION_TOKEN_KEY_PREFIX = "login.registration_token"
+const val REGISTRATION_TOKEN_KEY_PREFIX = "registration_token"
+const val REGISTRATION_SUBSCRIPTION_KEY_PREFIX = "subscription.google"
 
 const val TERMS_URL_EXTENSION = "_matrix/consent"
 const val VALIDATION_TOKEN_SUBMIT_URL_PREFIX = "_matrix/identity/api/v1/validate/email/submitToken"
diff --git a/app/src/main/java/org/futo/circles/di/DataSourceModule.kt b/app/src/main/java/org/futo/circles/di/DataSourceModule.kt
index c33c38e6683924e83dd13eef53d1992268699f7f..b44ca7940aab3a09488440fb1e46e55b90c979eb 100644
--- a/app/src/main/java/org/futo/circles/di/DataSourceModule.kt
+++ b/app/src/main/java/org/futo/circles/di/DataSourceModule.kt
@@ -31,6 +31,7 @@ import org.futo.circles.feature.sign_up.SignUpDataSource
 import org.futo.circles.feature.sign_up.setup_circles.SetupCirclesDataSource
 import org.futo.circles.feature.sign_up.setup_profile.SetupProfileDataSource
 import org.futo.circles.feature.sign_up.sign_up_type.SelectSignUpTypeDataSource
+import org.futo.circles.feature.sign_up.subscription_stage.SubscriptionStageDataSource
 import org.futo.circles.feature.sign_up.terms.AcceptTermsDataSource
 import org.futo.circles.feature.sign_up.validate_email.ValidateEmailDataSource
 import org.futo.circles.feature.sign_up.validate_token.ValidateTokenDataSource
@@ -92,4 +93,5 @@ val dataSourceModule = module {
     factory { UserOptionsDataSource() }
     factory { (userId: String) -> UserDataSource(get(), userId) }
     single { PickDeviceMediaDataSource(get()) }
+    factory { SubscriptionStageDataSource(get()) }
 }
\ No newline at end of file
diff --git a/app/src/main/java/org/futo/circles/di/UiModule.kt b/app/src/main/java/org/futo/circles/di/UiModule.kt
index fb43d9535d3fe0aebaa5aff01f779c5fd4b30963..e68fdd6476efeff7c1f4c8bb2c1af778d6bf3294 100644
--- a/app/src/main/java/org/futo/circles/di/UiModule.kt
+++ b/app/src/main/java/org/futo/circles/di/UiModule.kt
@@ -28,6 +28,7 @@ import org.futo.circles.feature.sign_up.SignUpViewModel
 import org.futo.circles.feature.sign_up.setup_circles.SetupCirclesViewModel
 import org.futo.circles.feature.sign_up.setup_profile.SetupProfileViewModel
 import org.futo.circles.feature.sign_up.sign_up_type.SelectSignUpTypeViewModel
+import org.futo.circles.feature.sign_up.subscription_stage.SubscriptionStageViewModel
 import org.futo.circles.feature.sign_up.terms.AcceptTermsViewModel
 import org.futo.circles.feature.sign_up.validate_email.ValidateEmailViewModel
 import org.futo.circles.feature.sign_up.validate_token.ValidateTokenViewModel
@@ -102,4 +103,5 @@ val uiModule = module {
     viewModel { (isVideoAvailable: Boolean) ->
         PickDeviceMediaViewModel(isVideoAvailable, get())
     }
+    viewModel { SubscriptionStageViewModel(get()) }
 }
\ No newline at end of file
diff --git a/app/src/main/java/org/futo/circles/feature/sign_up/SignUpDataSource.kt b/app/src/main/java/org/futo/circles/feature/sign_up/SignUpDataSource.kt
index e237053c929544f27067409a7d662d77d1113847..ab7447e322916a8f891df8adacb039ca801d20eb 100644
--- a/app/src/main/java/org/futo/circles/feature/sign_up/SignUpDataSource.kt
+++ b/app/src/main/java/org/futo/circles/feature/sign_up/SignUpDataSource.kt
@@ -6,6 +6,7 @@ import kotlinx.coroutines.async
 import kotlinx.coroutines.awaitAll
 import kotlinx.coroutines.coroutineScope
 import org.futo.circles.R
+import org.futo.circles.core.REGISTRATION_SUBSCRIPTION_KEY_PREFIX
 import org.futo.circles.core.REGISTRATION_TOKEN_KEY_PREFIX
 import org.futo.circles.core.SingleEventLiveData
 import org.futo.circles.core.matrix.pass_phrase.create.CreatePassPhraseDataSource
@@ -18,7 +19,7 @@ import org.matrix.android.sdk.api.auth.registration.RegistrationResult
 import org.matrix.android.sdk.api.auth.registration.Stage
 import org.matrix.android.sdk.api.session.Session
 
-enum class NavigationEvents { TokenValidation, AcceptTerm, ValidateEmail }
+enum class NavigationEvents { TokenValidation, Subscription, AcceptTerm, ValidateEmail }
 
 class SignUpDataSource(
     private val context: Context,
@@ -37,6 +38,8 @@ class SignUpDataSource(
         private set
 
     var currentHomeServerUrl: String = ""
+        private set
+
     private var passphrase: String = ""
     private var userName: String = ""
 
@@ -44,7 +47,8 @@ class SignUpDataSource(
         stages: List<Stage>,
         name: String,
         password: String,
-        homeServerUrl: String
+        homeServerUrl: String,
+        isSubscription: Boolean
     ) {
         currentStage = null
         stagesToComplete.clear()
@@ -52,7 +56,7 @@ class SignUpDataSource(
         passphrase = password
         currentHomeServerUrl = homeServerUrl
 
-        stagesToComplete.addAll(stages.filter { it.mandatory })
+        setupStages(stages, isSubscription)
         navigateToNextStage()
     }
 
@@ -66,6 +70,16 @@ class SignUpDataSource(
         subtitleLiveData.postValue("")
     }
 
+    private fun setupStages(stages: List<Stage>, isSubscription: Boolean) {
+        val otherStages = stages.filterIsInstance<Stage.Other>()
+        val firstStage = otherStages.firstOrNull {
+            if (isSubscription) it.type.endsWith(REGISTRATION_SUBSCRIPTION_KEY_PREFIX)
+            else it.type.endsWith(REGISTRATION_TOKEN_KEY_PREFIX)
+        } ?: throw IllegalArgumentException(context.getString(R.string.wrong_signup_config))
+        stagesToComplete.add(firstStage)
+        stagesToComplete.addAll(stages.filter { it.mandatory })
+    }
+
     private suspend fun finishRegistration(session: Session) = createResult {
         MatrixInstanceProvider.matrix.authenticationService().reset()
         MatrixSessionProvider.awaitForSessionStart(session)
@@ -103,11 +117,11 @@ class SignUpDataSource(
 
     private fun handleStageOther(type: String): NavigationEvents =
         if (type.endsWith(REGISTRATION_TOKEN_KEY_PREFIX)) NavigationEvents.TokenValidation
+        else if (type.endsWith(REGISTRATION_SUBSCRIPTION_KEY_PREFIX)) NavigationEvents.Subscription
         else throw IllegalArgumentException(
             context.getString(R.string.not_supported_stage_format, type)
         )
 
-
     private fun updatePageSubtitle() {
         val size = stagesToComplete.size
         val number = getCurrentStageIndex() + 1
@@ -115,5 +129,7 @@ class SignUpDataSource(
         subtitleLiveData.postValue(subtitle)
     }
 
-
+    companion object {
+        const val TYPE_PARAM_KEY = "type"
+    }
 }
\ No newline at end of file
diff --git a/app/src/main/java/org/futo/circles/feature/sign_up/SignUpFragment.kt b/app/src/main/java/org/futo/circles/feature/sign_up/SignUpFragment.kt
index 4138c330639ed11dbde2058e23631c37c0548fae..ffa334408ae71fe1e96af5df887f9bbca046ad13 100644
--- a/app/src/main/java/org/futo/circles/feature/sign_up/SignUpFragment.kt
+++ b/app/src/main/java/org/futo/circles/feature/sign_up/SignUpFragment.kt
@@ -57,6 +57,7 @@ class SignUpFragment : Fragment(R.layout.sign_up_fragment), BackPressOwner {
     private fun handleNavigation(event: NavigationEvents) {
         val directionId = when (event) {
             NavigationEvents.TokenValidation -> R.id.to_validateToken
+            NavigationEvents.Subscription -> R.id.to_subscriptions
             NavigationEvents.AcceptTerm -> R.id.to_acceptTerms
             NavigationEvents.ValidateEmail -> R.id.to_validateEmail
         }
diff --git a/app/src/main/java/org/futo/circles/feature/sign_up/sign_up_type/SelectSignUpTypeDataSource.kt b/app/src/main/java/org/futo/circles/feature/sign_up/sign_up_type/SelectSignUpTypeDataSource.kt
index 9cdb9cfe8b7d138d5f7da19e010ebe996bccda1d..63752002be30deadb01b432397237ca477424dec 100644
--- a/app/src/main/java/org/futo/circles/feature/sign_up/sign_up_type/SelectSignUpTypeDataSource.kt
+++ b/app/src/main/java/org/futo/circles/feature/sign_up/sign_up_type/SelectSignUpTypeDataSource.kt
@@ -21,7 +21,12 @@ class SelectSignUpTypeDataSource(
         signUpDataSource.clearSubtitle()
     }
 
-    suspend fun startNewRegistration(name: String, password: String, domain: String) =
+    suspend fun startNewRegistration(
+        name: String,
+        password: String,
+        domain: String,
+        isSubscription: Boolean
+    ) =
         createResult {
             val homeServerUrl = HomeServerUtils.getHomeServerUrlFromDomain(domain)
             authService.cancelPendingLoginOrRegistration()
@@ -39,7 +44,8 @@ class SelectSignUpTypeDataSource(
                         it.flowResult.missingStages,
                         name,
                         password,
-                        homeServerUrl
+                        homeServerUrl,
+                        isSubscription
                     )
                 }
         }
diff --git a/app/src/main/java/org/futo/circles/feature/sign_up/sign_up_type/SelectSignUpTypeFragment.kt b/app/src/main/java/org/futo/circles/feature/sign_up/sign_up_type/SelectSignUpTypeFragment.kt
index a1f11d72578e481db9713b9385c7b1b106d0fc5c..0f4512417d049486528f704f012c12ede0da505f 100644
--- a/app/src/main/java/org/futo/circles/feature/sign_up/sign_up_type/SelectSignUpTypeFragment.kt
+++ b/app/src/main/java/org/futo/circles/feature/sign_up/sign_up_type/SelectSignUpTypeFragment.kt
@@ -26,15 +26,13 @@ class SelectSignUpTypeFragment : Fragment(R.layout.select_sign_up_type_fragment)
         viewModel.clearSubtitle()
         setupViews()
         setupObservers()
-
     }
 
     private fun setupViews() {
-        setAlwaysDisabledViews(listOf(binding.btnSubscription))
         with(binding) {
             groupSubscription.setIsVisible(BuildConfig.IS_SUBSCRIPTIONS_ENABLED)
-            tilUserName.editText?.doAfterTextChanged { setTokenButtonEnabled() }
-            tilPassword.editText?.doAfterTextChanged { setTokenButtonEnabled() }
+            tilUserName.editText?.doAfterTextChanged { setSignupButtonsEnabled() }
+            tilPassword.editText?.doAfterTextChanged { setSignupButtonsEnabled() }
             btnToken.setOnClickListener {
                 startLoading(btnToken)
                 viewModel.startSignUp(
@@ -43,6 +41,15 @@ class SelectSignUpTypeFragment : Fragment(R.layout.select_sign_up_type_fragment)
                     tvServerDomain.text.toString()
                 )
             }
+            btnSubscription.setOnClickListener {
+                startLoading(btnSubscription)
+                viewModel.startSignUp(
+                    tilUserName.getText(),
+                    tilPassword.getText(),
+                    tvServerDomain.text.toString(),
+                    true
+                )
+            }
             serverLocationGroup.setOnCheckedChangeListener { _, checkedId ->
                 tvServerDomain.text = when (checkedId) {
                     btnUS.id -> BuildConfig.US_SERVER_DOMAIN
@@ -58,8 +65,10 @@ class SelectSignUpTypeFragment : Fragment(R.layout.select_sign_up_type_fragment)
         viewModel.startSignUpEventLiveData.observeResponse(this)
     }
 
-    private fun setTokenButtonEnabled() {
-        binding.btnToken.isEnabled = binding.tilUserName.editText?.text?.isNotEmpty() == true &&
+    private fun setSignupButtonsEnabled() {
+        val isEnabled = binding.tilUserName.editText?.text?.isNotEmpty() == true &&
                 binding.tilPassword.editText?.text?.isNotEmpty() == true
+        binding.btnToken.isEnabled = isEnabled
+        binding.btnSubscription.isEnabled = isEnabled
     }
 }
\ No newline at end of file
diff --git a/app/src/main/java/org/futo/circles/feature/sign_up/sign_up_type/SelectSignUpTypeViewModel.kt b/app/src/main/java/org/futo/circles/feature/sign_up/sign_up_type/SelectSignUpTypeViewModel.kt
index e9874360b86cd2cf0f16988f9959f1d3316a6a70..3979b0544d8d015f005da5688ab1a9cd7362e2ca 100644
--- a/app/src/main/java/org/futo/circles/feature/sign_up/sign_up_type/SelectSignUpTypeViewModel.kt
+++ b/app/src/main/java/org/futo/circles/feature/sign_up/sign_up_type/SelectSignUpTypeViewModel.kt
@@ -11,10 +11,15 @@ class SelectSignUpTypeViewModel(
 
     val startSignUpEventLiveData = SingleEventLiveData<Response<Unit?>>()
 
-    fun startSignUp(name: String, password: String, serverDomain: String) {
+    fun startSignUp(
+        name: String,
+        password: String,
+        serverDomain: String,
+        isSubscription: Boolean = false
+    ) {
         launchBg {
             startSignUpEventLiveData.postValue(
-                dataSource.startNewRegistration(name, password, serverDomain)
+                dataSource.startNewRegistration(name, password, serverDomain, isSubscription)
             )
         }
     }
diff --git a/app/src/main/java/org/futo/circles/feature/sign_up/subscription_stage/SubscriptionStageDataSource.kt b/app/src/main/java/org/futo/circles/feature/sign_up/subscription_stage/SubscriptionStageDataSource.kt
new file mode 100644
index 0000000000000000000000000000000000000000..3c79e48171a2f8527d2fbf8afd271237346aa9c4
--- /dev/null
+++ b/app/src/main/java/org/futo/circles/feature/sign_up/subscription_stage/SubscriptionStageDataSource.kt
@@ -0,0 +1,45 @@
+package org.futo.circles.feature.sign_up.subscription_stage
+
+import org.futo.circles.extensions.Response
+import org.futo.circles.extensions.createResult
+import org.futo.circles.feature.sign_up.SignUpDataSource
+import org.futo.circles.feature.sign_up.SignUpDataSource.Companion.TYPE_PARAM_KEY
+import org.futo.circles.provider.MatrixInstanceProvider
+import org.matrix.android.sdk.api.auth.registration.RegistrationResult
+import org.matrix.android.sdk.api.auth.registration.Stage
+
+class SubscriptionStageDataSource(
+    private val signUpDataSource: SignUpDataSource
+) {
+
+    private val wizard by lazy {
+        MatrixInstanceProvider.matrix.authenticationService().getRegistrationWizard()
+    }
+
+    suspend fun validateSubscriptionReceipt(receipt: String): Response<RegistrationResult> {
+        val type = (signUpDataSource.currentStage as? Stage.Other)?.type ?: ""
+
+        val result = createResult {
+            wizard.registrationCustom(
+                mapOf(
+                    TYPE_PARAM_KEY to type,
+                    PRODUCT_PARAM_KEY to receipt
+                )
+            )
+        }
+
+        (result as? Response.Success)?.let { signUpDataSource.stageCompleted(result.data) }
+        return result
+    }
+
+    fun getProductIdsList() = ((signUpDataSource.currentStage as? Stage.Other)
+        ?.params?.get(PRODUCT_IDS_KEY) as? List<*>)
+        ?.map { it.toString() }
+        ?: emptyList()
+
+
+    companion object {
+        private const val PRODUCT_PARAM_KEY = "product"
+        private const val PRODUCT_IDS_KEY = "productIds"
+    }
+}
\ No newline at end of file
diff --git a/app/src/main/java/org/futo/circles/feature/sign_up/subscription_stage/SubscriptionStageFragment.kt b/app/src/main/java/org/futo/circles/feature/sign_up/subscription_stage/SubscriptionStageFragment.kt
new file mode 100644
index 0000000000000000000000000000000000000000..76cec72b3b5aff978d28645e7576204e55c255b3
--- /dev/null
+++ b/app/src/main/java/org/futo/circles/feature/sign_up/subscription_stage/SubscriptionStageFragment.kt
@@ -0,0 +1,66 @@
+package org.futo.circles.feature.sign_up.subscription_stage
+
+import android.os.Bundle
+import android.view.View
+import by.kirich1409.viewbindingdelegate.viewBinding
+import org.futo.circles.R
+import org.futo.circles.core.fragment.ParentBackPressOwnerFragment
+import org.futo.circles.databinding.SubscriptionStageFragmentBinding
+import org.futo.circles.extensions.observeResponse
+import org.futo.circles.extensions.showError
+import org.futo.circles.feature.sign_up.subscription_stage.list.SubscriptionsAdapter
+import org.futo.circles.subscriptions.ItemPurchasedListener
+import org.futo.circles.subscriptions.SubscriptionManagerProvider
+import org.koin.androidx.viewmodel.ext.android.viewModel
+
+class SubscriptionStageFragment :
+    ParentBackPressOwnerFragment(R.layout.subscription_stage_fragment) {
+
+    private val binding by viewBinding(SubscriptionStageFragmentBinding::bind)
+    private val viewModel by viewModel<SubscriptionStageViewModel>()
+
+    private val subscriptionManager by lazy {
+        SubscriptionManagerProvider.getManager(
+            requireActivity(), object : ItemPurchasedListener {
+                override fun onItemPurchased(purchase: String) {
+                    viewModel.validateSubscriptionReceipt(purchase)
+                }
+
+                override fun onPurchaseFailed(errorCode: Int) {
+                    showError(getString(R.string.purchase_failed_format, errorCode))
+                }
+            }
+        )
+    }
+
+    private val listAdapter by lazy {
+        SubscriptionsAdapter(onItemClicked = { id -> onSubscriptionSelected(id) })
+    }
+
+    override fun onCreate(savedInstanceState: Bundle?) {
+        super.onCreate(savedInstanceState)
+        viewModel.loadSubscriptionsList(subscriptionManager)
+    }
+
+    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
+        super.onViewCreated(view, savedInstanceState)
+        setupViews()
+        setupObservers()
+    }
+
+    private fun setupViews() {
+        binding.rvSubscriptions.adapter = listAdapter
+    }
+
+    private fun setupObservers() {
+        viewModel.subscribeLiveData.observeResponse(this)
+        viewModel.purchaseLiveData.observeResponse(this)
+        viewModel.subscriptionsListLiveData.observeResponse(this, success = {
+            listAdapter.submitList(it)
+        })
+    }
+
+    private fun onSubscriptionSelected(productId: String) {
+        viewModel.purchaseProduct(subscriptionManager, productId)
+    }
+}
\ No newline at end of file
diff --git a/app/src/main/java/org/futo/circles/feature/sign_up/subscription_stage/SubscriptionStageViewModel.kt b/app/src/main/java/org/futo/circles/feature/sign_up/subscription_stage/SubscriptionStageViewModel.kt
new file mode 100644
index 0000000000000000000000000000000000000000..b0da6cb95836f02976e75e41ff34f3faf7123ffb
--- /dev/null
+++ b/app/src/main/java/org/futo/circles/feature/sign_up/subscription_stage/SubscriptionStageViewModel.kt
@@ -0,0 +1,39 @@
+package org.futo.circles.feature.sign_up.subscription_stage
+
+import androidx.lifecycle.MutableLiveData
+import androidx.lifecycle.ViewModel
+import org.futo.circles.core.SingleEventLiveData
+import org.futo.circles.extensions.Response
+import org.futo.circles.extensions.launchBg
+import org.futo.circles.extensions.launchUi
+import org.futo.circles.model.SubscriptionListItem
+import org.futo.circles.subscriptions.SubscriptionManager
+import org.matrix.android.sdk.api.auth.registration.RegistrationResult
+
+class SubscriptionStageViewModel(
+    private val dataSource: SubscriptionStageDataSource
+) : ViewModel() {
+
+    val subscribeLiveData = SingleEventLiveData<Response<RegistrationResult>>()
+    val purchaseLiveData = SingleEventLiveData<Response<Unit>>()
+    val subscriptionsListLiveData = MutableLiveData<Response<List<SubscriptionListItem>>>()
+
+    fun validateSubscriptionReceipt(receipt: String) {
+        launchBg {
+            subscribeLiveData.postValue(dataSource.validateSubscriptionReceipt(receipt))
+        }
+    }
+
+    fun loadSubscriptionsList(subscriptionManager: SubscriptionManager) {
+        launchBg {
+            subscriptionsListLiveData.postValue(subscriptionManager.getDetails(dataSource.getProductIdsList()))
+        }
+    }
+
+    fun purchaseProduct(subscriptionManager: SubscriptionManager, productId: String) {
+        launchUi {
+            purchaseLiveData.postValue(subscriptionManager.purchaseProduct(productId))
+        }
+    }
+
+}
\ No newline at end of file
diff --git a/app/src/main/java/org/futo/circles/feature/sign_up/subscription_stage/list/SubscriptionViewHolder.kt b/app/src/main/java/org/futo/circles/feature/sign_up/subscription_stage/list/SubscriptionViewHolder.kt
new file mode 100644
index 0000000000000000000000000000000000000000..d8c4f7d891b3823acb9c317641e20a0b54fcd98d
--- /dev/null
+++ b/app/src/main/java/org/futo/circles/feature/sign_up/subscription_stage/list/SubscriptionViewHolder.kt
@@ -0,0 +1,32 @@
+package org.futo.circles.feature.sign_up.subscription_stage.list
+
+import android.view.ViewGroup
+import androidx.recyclerview.widget.RecyclerView
+import org.futo.circles.core.list.ViewBindingHolder
+import org.futo.circles.databinding.SubscriptionListItemBinding
+import org.futo.circles.extensions.onClick
+import org.futo.circles.model.SubscriptionListItem
+
+
+class SubscriptionViewHolder(
+    parent: ViewGroup,
+    private val onSubscriptionClicked: (Int) -> Unit
+) : RecyclerView.ViewHolder(inflate(parent, SubscriptionListItemBinding::inflate)) {
+
+    private companion object : ViewBindingHolder
+
+    private val binding = baseBinding as SubscriptionListItemBinding
+
+    init {
+        onClick(itemView) { position -> onSubscriptionClicked(position) }
+    }
+
+    fun bind(data: SubscriptionListItem) {
+        with(binding) {
+            tvName.text = data.name
+            tvDetails.text = data.description
+            tvPrice.text = data.price
+            tvDuration.text = data.duration
+        }
+    }
+}
\ No newline at end of file
diff --git a/app/src/main/java/org/futo/circles/feature/sign_up/subscription_stage/list/SubscriptionsAdapter.kt b/app/src/main/java/org/futo/circles/feature/sign_up/subscription_stage/list/SubscriptionsAdapter.kt
new file mode 100644
index 0000000000000000000000000000000000000000..3c0ec03f2c76c7f7100bfda6c1ada78a2c57e28a
--- /dev/null
+++ b/app/src/main/java/org/futo/circles/feature/sign_up/subscription_stage/list/SubscriptionsAdapter.kt
@@ -0,0 +1,23 @@
+package org.futo.circles.feature.sign_up.subscription_stage.list
+
+import android.view.ViewGroup
+import org.futo.circles.core.list.BaseRvAdapter
+import org.futo.circles.model.SubscriptionListItem
+
+class SubscriptionsAdapter(
+    private val onItemClicked: (id: String) -> Unit
+) : BaseRvAdapter<SubscriptionListItem, SubscriptionViewHolder>(
+    DefaultIdEntityCallback()
+) {
+
+    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): SubscriptionViewHolder =
+        SubscriptionViewHolder(
+            parent = parent,
+            onSubscriptionClicked = { position -> onItemClicked(getItem(position).id) }
+        )
+
+    override fun onBindViewHolder(holder: SubscriptionViewHolder, position: Int) {
+        holder.bind(getItem(position))
+    }
+
+}
\ No newline at end of file
diff --git a/app/src/main/java/org/futo/circles/feature/sign_up/validate_token/ValidateTokenDataSource.kt b/app/src/main/java/org/futo/circles/feature/sign_up/validate_token/ValidateTokenDataSource.kt
index 43864d482ee842cffa9944e49f29f1e958809508..861c4bee47717f3520addfed10d80e832b0e4f6a 100644
--- a/app/src/main/java/org/futo/circles/feature/sign_up/validate_token/ValidateTokenDataSource.kt
+++ b/app/src/main/java/org/futo/circles/feature/sign_up/validate_token/ValidateTokenDataSource.kt
@@ -3,6 +3,7 @@ package org.futo.circles.feature.sign_up.validate_token
 import org.futo.circles.extensions.Response
 import org.futo.circles.extensions.createResult
 import org.futo.circles.feature.sign_up.SignUpDataSource
+import org.futo.circles.feature.sign_up.SignUpDataSource.Companion.TYPE_PARAM_KEY
 import org.futo.circles.provider.MatrixInstanceProvider
 import org.matrix.android.sdk.api.auth.registration.RegistrationResult
 import org.matrix.android.sdk.api.auth.registration.Stage
@@ -21,8 +22,8 @@ class ValidateTokenDataSource(
         val result = createResult {
             wizard.registrationCustom(
                 mapOf(
-                    "type" to type,
-                    "token" to token
+                    TYPE_PARAM_KEY to type,
+                    TOKEN_PARAM_KEY to token
                 )
             )
         }
@@ -31,4 +32,8 @@ class ValidateTokenDataSource(
 
         return result
     }
+
+    companion object {
+        private const val TOKEN_PARAM_KEY = "token"
+    }
 }
\ No newline at end of file
diff --git a/app/src/main/java/org/futo/circles/model/SubscriptionListItem.kt b/app/src/main/java/org/futo/circles/model/SubscriptionListItem.kt
new file mode 100644
index 0000000000000000000000000000000000000000..fc3f1aa8b889be369dd45fcbd2ad175e04bf377d
--- /dev/null
+++ b/app/src/main/java/org/futo/circles/model/SubscriptionListItem.kt
@@ -0,0 +1,11 @@
+package org.futo.circles.model
+
+import org.futo.circles.core.list.IdEntity
+
+data class SubscriptionListItem(
+    override val id: String,
+    val name: String,
+    val description: String,
+    val price: String,
+    val duration: String
+) : IdEntity<String>
\ No newline at end of file
diff --git a/app/src/main/java/org/futo/circles/subscriptions/IsoPeriod.kt b/app/src/main/java/org/futo/circles/subscriptions/IsoPeriod.kt
new file mode 100644
index 0000000000000000000000000000000000000000..d9f9b2fb60d866a631034241bb1ec8e0a2cb84a0
--- /dev/null
+++ b/app/src/main/java/org/futo/circles/subscriptions/IsoPeriod.kt
@@ -0,0 +1,22 @@
+package org.futo.circles.subscriptions
+
+import android.content.Context
+import org.futo.circles.R
+
+fun String.formatIsoPeriod(context: Context): String = toDurationNumberPairs()
+    .joinToString(separator = " ") { (number, duration) ->
+        context.resources.getQuantityString(
+            when (duration) {
+                "D" -> R.plurals.days
+                "W" -> R.plurals.weeks
+                "M" -> R.plurals.months
+                "Y" -> R.plurals.years
+
+                else -> R.plurals.days
+            }, number, number
+        )
+    }
+
+private fun String.toDurationNumberPairs() = removePrefix("P")
+    .chunked(2)
+    .map { it[0].toString().toInt() to it[1].toString() }
\ No newline at end of file
diff --git a/app/src/main/java/org/futo/circles/subscriptions/ItemPurchasedListener.kt b/app/src/main/java/org/futo/circles/subscriptions/ItemPurchasedListener.kt
new file mode 100644
index 0000000000000000000000000000000000000000..ceebad92d08050369c92a3bb168f6c92ed4ab380
--- /dev/null
+++ b/app/src/main/java/org/futo/circles/subscriptions/ItemPurchasedListener.kt
@@ -0,0 +1,10 @@
+package org.futo.circles.subscriptions
+
+
+interface ItemPurchasedListener {
+
+    fun onItemPurchased(purchase: String)
+
+    fun onPurchaseFailed(errorCode: Int)
+
+}
\ No newline at end of file
diff --git a/app/src/main/java/org/futo/circles/subscriptions/SubscriptionManager.kt b/app/src/main/java/org/futo/circles/subscriptions/SubscriptionManager.kt
new file mode 100644
index 0000000000000000000000000000000000000000..648fb89c546a7bc23f4e3917f45fc7ded101fa07
--- /dev/null
+++ b/app/src/main/java/org/futo/circles/subscriptions/SubscriptionManager.kt
@@ -0,0 +1,12 @@
+package org.futo.circles.subscriptions
+
+import org.futo.circles.extensions.Response
+import org.futo.circles.model.SubscriptionListItem
+
+interface SubscriptionManager {
+
+    suspend fun getDetails(productIds: List<String>): Response<List<SubscriptionListItem>>
+
+    suspend fun purchaseProduct(productId: String): Response<Unit>
+
+}
\ No newline at end of file
diff --git a/app/src/main/java/org/futo/circles/subscriptions/SubscriptionProvider.kt b/app/src/main/java/org/futo/circles/subscriptions/SubscriptionProvider.kt
new file mode 100644
index 0000000000000000000000000000000000000000..1fe9597c832b6ef02cb47fa8f1a739f2507595b5
--- /dev/null
+++ b/app/src/main/java/org/futo/circles/subscriptions/SubscriptionProvider.kt
@@ -0,0 +1,12 @@
+package org.futo.circles.subscriptions
+
+import android.app.Activity
+
+interface SubscriptionProvider {
+
+    fun getManager(
+        activity: Activity,
+        itemPurchaseListener: ItemPurchasedListener
+    ): SubscriptionManager
+
+}
\ No newline at end of file
diff --git a/app/src/main/res/layout/select_sign_up_type_fragment.xml b/app/src/main/res/layout/select_sign_up_type_fragment.xml
index 63715b29ed568c875bb6c47af622a87817bbab71..77d3e6de40c9de257f55e48d35fba84414c44445 100644
--- a/app/src/main/res/layout/select_sign_up_type_fragment.xml
+++ b/app/src/main/res/layout/select_sign_up_type_fragment.xml
@@ -129,7 +129,7 @@
         android:layout_width="0dp"
         android:layout_height="wrap_content"
         android:gravity="center"
-        android:text="@string/already_have_a_circles_token"
+        android:text="@string/already_have_a_token"
         app:layout_constraintBottom_toTopOf="@id/btnToken"
         app:layout_constraintEnd_toEndOf="parent"
         app:layout_constraintStart_toStartOf="parent"
@@ -170,44 +170,27 @@
         android:layout_width="0dp"
         android:layout_height="wrap_content"
         android:gravity="center"
-        android:text="@string/create_a_circles_subscription"
+        android:text="@string/create_a_subscription"
         app:layout_constraintBottom_toTopOf="@id/btnSubscription"
         app:layout_constraintEnd_toEndOf="parent"
         app:layout_constraintStart_toStartOf="parent"
         app:layout_constraintTop_toBottomOf="@id/tvOr" />
 
-    <com.google.android.material.button.MaterialButton
+    <org.futo.circles.view.LoadingButton
         android:id="@+id/btnSubscription"
-        style="@style/AccentButtonStyle"
         android:layout_width="0dp"
         android:layout_height="wrap_content"
         android:layout_marginTop="8dp"
         android:enabled="false"
-        android:text="@string/new_circles_subscription"
-        app:layout_constraintBottom_toTopOf="@id/tvSubscriptionUnavailable"
-        app:layout_constraintEnd_toEndOf="parent"
-        app:layout_constraintStart_toStartOf="parent"
-        app:layout_constraintTop_toBottomOf="@id/tvSubscriptionTitle" />
-
-    <TextView
-        android:id="@+id/tvSubscriptionUnavailable"
-        style="@style/footNote"
-        android:layout_width="0dp"
-        android:layout_height="wrap_content"
-        android:layout_marginTop="8dp"
-        android:gravity="center"
-        android:text="@string/new_paid_circles_subscriptions_are_currently_unavailable"
-        app:drawableStartCompat="@drawable/ic_error"
-        app:drawableTint="@color/inactive_menu_icon_color"
+        android:text="@string/choose_a_subscription"
         app:layout_constraintBottom_toBottomOf="parent"
         app:layout_constraintEnd_toEndOf="parent"
         app:layout_constraintStart_toStartOf="parent"
-        app:layout_constraintTop_toBottomOf="@id/btnSubscription" />
-
+        app:layout_constraintTop_toBottomOf="@id/tvSubscriptionTitle" />
 
     <androidx.constraintlayout.widget.Group
         android:id="@+id/groupSubscription"
         android:layout_width="0dp"
         android:layout_height="0dp"
-        app:constraint_referenced_ids="tvOr,tvSubscriptionTitle,btnSubscription,tvSubscriptionUnavailable" />
+        app:constraint_referenced_ids="tvOr,tvSubscriptionTitle,btnSubscription" />
 </androidx.constraintlayout.widget.ConstraintLayout>
\ No newline at end of file
diff --git a/app/src/main/res/layout/subscription_list_item.xml b/app/src/main/res/layout/subscription_list_item.xml
new file mode 100644
index 0000000000000000000000000000000000000000..acb06f4a3a7407e352859aaf3bf0f1c886c9237c
--- /dev/null
+++ b/app/src/main/res/layout/subscription_list_item.xml
@@ -0,0 +1,82 @@
+<?xml version="1.0" encoding="utf-8"?>
+<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:app="http://schemas.android.com/apk/res-auto"
+    xmlns:tools="http://schemas.android.com/tools"
+    android:layout_width="match_parent"
+    android:layout_height="wrap_content"
+    android:background="?selectableItemBackground"
+    android:clickable="true"
+    android:focusable="true"
+    android:padding="4dp">
+
+
+    <com.google.android.material.imageview.ShapeableImageView
+        android:id="@+id/ivIcon"
+        android:layout_width="@dimen/group_icon_size"
+        android:layout_height="@dimen/group_icon_size"
+        android:scaleType="centerCrop"
+        android:src="@mipmap/ic_launcher"
+        app:layout_constraintBottom_toBottomOf="parent"
+        app:layout_constraintStart_toStartOf="parent"
+        app:layout_constraintTop_toTopOf="parent"
+        app:shapeAppearanceOverlay="@style/ShapeAppearanceOverlay.App.GroupIconRadius" />
+
+
+    <TextView
+        android:id="@+id/tvName"
+        style="@style/title2"
+        android:layout_width="0dp"
+        android:layout_height="wrap_content"
+        android:layout_marginStart="8dp"
+        android:ellipsize="end"
+        android:lines="1"
+        app:layout_constraintBottom_toTopOf="@id/tvPrice"
+        app:layout_constraintEnd_toEndOf="parent"
+        app:layout_constraintStart_toEndOf="@id/ivIcon"
+        app:layout_constraintTop_toTopOf="@id/ivIcon"
+        tools:text="texsdt" />
+
+
+    <TextView
+        android:id="@+id/tvPrice"
+        style="@style/subheadline"
+        android:layout_width="0dp"
+        android:layout_height="wrap_content"
+        android:layout_marginTop="4dp"
+        android:ellipsize="end"
+        android:lines="1"
+        app:layout_constraintBottom_toTopOf="@id/tvDuration"
+        app:layout_constraintEnd_toEndOf="parent"
+        app:layout_constraintStart_toStartOf="@id/tvName"
+        app:layout_constraintTop_toBottomOf="@id/tvName"
+        tools:text="texsdt" />
+
+    <TextView
+        android:id="@+id/tvDuration"
+        style="@style/subheadline"
+        android:layout_width="0dp"
+        android:layout_height="wrap_content"
+        android:layout_marginTop="4dp"
+        android:ellipsize="end"
+        android:lines="1"
+        app:layout_constraintBottom_toTopOf="@id/tvDetails"
+        app:layout_constraintEnd_toEndOf="parent"
+        app:layout_constraintStart_toStartOf="@id/tvName"
+        app:layout_constraintTop_toBottomOf="@id/tvPrice"
+        tools:text="texsdt" />
+
+    <TextView
+        android:id="@+id/tvDetails"
+        style="@style/subheadline"
+        android:layout_width="0dp"
+        android:layout_height="wrap_content"
+        android:layout_marginTop="4dp"
+        android:ellipsize="end"
+        android:lines="1"
+        app:layout_constraintBottom_toBottomOf="@id/ivIcon"
+        app:layout_constraintEnd_toEndOf="parent"
+        app:layout_constraintStart_toStartOf="@id/tvName"
+        app:layout_constraintTop_toBottomOf="@id/tvDuration"
+        tools:text="texsdt" />
+
+</androidx.constraintlayout.widget.ConstraintLayout>
\ No newline at end of file
diff --git a/app/src/main/res/layout/subscription_stage_fragment.xml b/app/src/main/res/layout/subscription_stage_fragment.xml
new file mode 100644
index 0000000000000000000000000000000000000000..b8bbd8e9665850a4647798aa0b33e3238d62d570
--- /dev/null
+++ b/app/src/main/res/layout/subscription_stage_fragment.xml
@@ -0,0 +1,48 @@
+<?xml version="1.0" encoding="utf-8"?>
+<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:app="http://schemas.android.com/apk/res-auto"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent">
+
+    <androidx.constraintlayout.widget.Guideline
+        android:id="@+id/guidelineLogo"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:orientation="horizontal"
+        app:layout_constraintGuide_percent="0.35" />
+
+    <org.futo.circles.view.CirclesLogoView
+        android:id="@+id/ivLogo"
+        android:layout_width="0dp"
+        android:layout_height="0dp"
+        android:layout_marginHorizontal="35dp"
+        android:layout_marginTop="24dp"
+        app:layout_constraintBottom_toTopOf="@id/guidelineLogo"
+        app:layout_constraintEnd_toEndOf="parent"
+        app:layout_constraintStart_toStartOf="parent"
+        app:layout_constraintTop_toTopOf="parent" />
+
+    <TextView
+        android:id="@+id/tvSubscriptionTitle"
+        style="@style/title2"
+        android:layout_width="0dp"
+        android:layout_height="wrap_content"
+        android:gravity="center"
+        android:text="@string/subscriptions"
+        app:layout_constraintEnd_toEndOf="parent"
+        app:layout_constraintStart_toStartOf="parent"
+        app:layout_constraintTop_toBottomOf="@id/guidelineLogo"
+        app:layout_constraintVertical_bias="0.3"
+        app:layout_constraintVertical_chainStyle="packed" />
+
+    <androidx.recyclerview.widget.RecyclerView
+        android:id="@+id/rvSubscriptions"
+        android:layout_width="0dp"
+        android:layout_height="0dp"
+        app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager"
+        app:layout_constraintBottom_toBottomOf="parent"
+        app:layout_constraintEnd_toEndOf="parent"
+        app:layout_constraintStart_toStartOf="parent"
+        app:layout_constraintTop_toBottomOf="@id/tvSubscriptionTitle" />
+
+</androidx.constraintlayout.widget.ConstraintLayout>
\ No newline at end of file
diff --git a/app/src/main/res/navigation/sign_up_nav_graph.xml b/app/src/main/res/navigation/sign_up_nav_graph.xml
index 872fd83f131647257234fd492b96b47a0f010635..9f1cd8081aa68b0be2b93206c632334cfd4d1b85 100644
--- a/app/src/main/res/navigation/sign_up_nav_graph.xml
+++ b/app/src/main/res/navigation/sign_up_nav_graph.xml
@@ -17,29 +17,34 @@
         android:id="@+id/to_acceptTerms"
         app:destination="@id/acceptTermsFragment" />
 
+    <action
+        android:id="@+id/to_subscriptions"
+        app:destination="@id/subscriptionStageFragment" />
+
     <fragment
         android:id="@+id/selectSignUpTypeFragment"
         android:name="org.futo.circles.feature.sign_up.sign_up_type.SelectSignUpTypeFragment"
-        android:label="SelectSignUpTypeFragment"
         tools:layout="@layout/select_sign_up_type_fragment" />
 
     <fragment
         android:id="@+id/validateTokenFragment"
         android:name="org.futo.circles.feature.sign_up.validate_token.ValidateTokenFragment"
-        android:label="ValidateTokenFragment"
         tools:layout="@layout/validate_token_fragment" />
 
     <fragment
         android:id="@+id/validateEmailFragment"
         android:name="org.futo.circles.feature.sign_up.validate_email.ValidateEmailFragment"
-        android:label="CreateAccountFragment"
         tools:layout="@layout/validate_email_fragment" />
 
     <fragment
         android:id="@+id/acceptTermsFragment"
         android:name="org.futo.circles.feature.sign_up.terms.AcceptTermsFragment"
-        android:label="AcceptTermsFragment"
         tools:layout="@layout/accept_terms_fragment" />
 
+    <fragment
+        android:id="@+id/subscriptionStageFragment"
+        android:name="org.futo.circles.feature.sign_up.subscription_stage.SubscriptionStageFragment"
+        tools:layout="@layout/subscription_stage_fragment" />
+
 
 </navigation>
\ No newline at end of file
diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml
index bf2a97bca53551c8ed29f632b134e1db5e35977a..b1d65db39d8c7660650621947a0a88438628c49f 100644
--- a/app/src/main/res/values/strings.xml
+++ b/app/src/main/res/values/strings.xml
@@ -57,11 +57,10 @@
     <string name="group_updated">Group updated</string>
     <string name="circle_updated">Circle updated</string>
     <string name="gallery_updated">Gallery updated</string>
-    <string name="already_have_a_circles_token">Already have a Circles token?</string>
+    <string name="already_have_a_token">Already have a token?</string>
     <string name="sign_up_with_token">Sign up with token</string>
-    <string name="new_circles_subscription">New Circles subscription</string>
-    <string name="new_paid_circles_subscriptions_are_currently_unavailable">New paid Circles subscriptions are currently unavailable</string>
-    <string name="create_a_circles_subscription">Create a Circles subscription</string>
+    <string name="choose_a_subscription">Choose a subscription</string>
+    <string name="create_a_subscription">Create a subscription</string>
     <string name="or">Or</string>
     <string name="validate_your_token">Validate your token</string>
     <string name="validate_token">Validate token</string>
@@ -238,6 +237,17 @@
     <string name="enable_cross_signing">Enable Cross Signing</string>
     <string name="enable_cross_signing_message">Confirm auth to enable cross signing</string>
     <string name="device_media">Device media</string>
+    <string name="subscriptions">Subscriptions</string>
+    <string name="wrong_signup_config">Wrong signup config!</string>
+    <string name="item_already_owned">Item already owned</string>
+    <string name="purchase_failed_format">Purchase failed with code %d</string>
+    <string name="feature_not_supported">Feature is not supported</string>
+    <string name="service_unavailable">Service unavailable</string>
+    <string name="item_unavailable">Item is unavailable</string>
+    <string name="user_canceled">User canceled</string>
+    <string name="item_not_owned">Item is not owned</string>
+    <string name="developer_error">Developer error</string>
+    <string name="flavour_does_not_support_subscriptions">This flavour does not support subscriptions</string>
 
     <string-array name="report_categories">
         <item>@string/crude_language</item>
@@ -268,4 +278,30 @@
         <item quantity="one">Show %d reply</item>
         <item quantity="other">Show %d replies</item>
     </plurals>
+
+
+    <plurals name="days">
+        <item quantity="one">%1$d day</item>
+        <item quantity="many">%1$d days</item>
+        <item quantity="other">%1$d days</item>
+    </plurals>
+
+    <plurals name="weeks">
+        <item quantity="one">%1$d week</item>
+        <item quantity="many">%1$d weeks</item>
+        <item quantity="other">%1$d weeks</item>
+    </plurals>
+
+    <plurals name="months">
+        <item quantity="one">%1$d month</item>
+        <item quantity="many">%1$d months</item>
+        <item quantity="other">%1$d months</item>
+    </plurals>
+
+    <plurals name="years">
+        <item quantity="one">%1$d year</item>
+        <item quantity="many">%1$d years</item>
+        <item quantity="other">%1$d years</item>
+    </plurals>
+
 </resources>
\ No newline at end of file
diff --git a/build.gradle b/build.gradle
index f225addfa13a29495b5940f048be1626fad4ddb8..ef170973ee5403feec32de90c6a7838a4a65ff3b 100644
--- a/build.gradle
+++ b/build.gradle
@@ -4,7 +4,7 @@ buildscript {
         kotlin_version = '1.7.0'
         minSdkVersion = 24
         sdkVersion = 32
-        nav_version = "2.5.0"
+        androidx_version = "2.5.1"
     }
     repositories {
         google()
@@ -13,7 +13,7 @@ buildscript {
     dependencies {
         classpath 'com.android.tools.build:gradle:7.2.1'
         classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
-        classpath "androidx.navigation:navigation-safe-args-gradle-plugin:$nav_version"
+        classpath "androidx.navigation:navigation-safe-args-gradle-plugin:$androidx_version"
         classpath 'com.google.gms:google-services:4.3.13'
         classpath 'com.google.firebase:firebase-crashlytics-gradle:2.9.1'
     }