diff --git a/app/src/main/java/org/futo/circles/subscriptions/SubscriptionManager.kt b/app/src/main/java/org/futo/circles/subscriptions/SubscriptionManager.kt
index 307a1b3f8ddc99527ff6357a7058b975b5d2773c..648fb89c546a7bc23f4e3917f45fc7ded101fa07 100644
--- a/app/src/main/java/org/futo/circles/subscriptions/SubscriptionManager.kt
+++ b/app/src/main/java/org/futo/circles/subscriptions/SubscriptionManager.kt
@@ -1,9 +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>): BillingResult<List<SubscriptionData>>
+    suspend fun getDetails(productIds: List<String>): Response<List<SubscriptionListItem>>
 
-    suspend fun purchaseProduct(productId: String): BillingResult<String>
+    suspend fun purchaseProduct(productId: String): Response<Unit>
 
 }
\ No newline at end of file
diff --git a/app/src/main/java/org/futo/circles/subscriptions/google/GoogleSubscriptionsManager.kt b/app/src/main/java/org/futo/circles/subscriptions/google/GoogleSubscriptionsManager.kt
index d13876c797262f6da529c168aa542accac37523b..f8e8330d3260bf6a6329f4d114c142a87063682c 100644
--- a/app/src/main/java/org/futo/circles/subscriptions/google/GoogleSubscriptionsManager.kt
+++ b/app/src/main/java/org/futo/circles/subscriptions/google/GoogleSubscriptionsManager.kt
@@ -1,30 +1,33 @@
 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.subscriptions.BillingResult
-import org.futo.circles.subscriptions.SubscriptionData
+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: AppCompatActivity,
-    private val itemPurchasedListener: GoogleItemPurchasedListener
+    private val activity: Activity,
+    private val itemPurchasedListener: ItemPurchasedListener
 ) : SubscriptionManager {
 
-    private val subscriptionsList =
-        arrayListOf("subscriptions_names_here!")
 
     private val purchasesUpdatedListener =
         PurchasesUpdatedListener { billingResult, purchases ->
             purchases?.let {
                 if (billingResult.responseCode == OK)
-                    itemPurchasedListener.onItemPurchased(purchases)
+                    itemPurchasedListener.onItemPurchased(
+                        purchases.lastOrNull()?.originalJson ?: ""
+                    )
                 else itemPurchasedListener.onPurchaseFailed(billingResult.responseCode)
             }
         }
@@ -36,7 +39,7 @@ class GoogleSubscriptionsManager(
 
 
     init {
-        activity.lifecycle.addObserver(object : DefaultLifecycleObserver {
+        (activity as? AppCompatActivity)?.lifecycle?.addObserver(object : DefaultLifecycleObserver {
             override fun onDestroy(owner: LifecycleOwner) {
                 client.endConnection()
                 super.onDestroy(owner)
@@ -44,70 +47,65 @@ class GoogleSubscriptionsManager(
         })
     }
 
-    override suspend fun getDetails() = when (val code =
-        client.isFeatureSupported(BillingClient.FeatureType.SUBSCRIPTIONS).responseCode) {
-
-        OK -> queryDetails()
-        FEATURE_NOT_SUPPORTED -> BillingResult.FeatureNotSupported
-        SERVICE_DISCONNECTED, SERVICE_UNAVAILABLE, BILLING_UNAVAILABLE -> onBG {
-            tryConnectAndDo { queryDetails() }
+    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)
         }
-        DEVELOPER_ERROR -> BillingResult.Failure(DEVELOPER_ERROR)
-        else -> BillingResult.Failure(code = code)
-    }
 
 
-    override suspend fun purchaseProduct(productDetails: ProductDetails): BillingResult<String> =
-        when (val code = client
+    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)
-            FEATURE_NOT_SUPPORTED -> BillingResult.FeatureNotSupported
             SERVICE_DISCONNECTED, SERVICE_UNAVAILABLE, BILLING_UNAVAILABLE -> onBG {
                 tryConnectAndDo { purchase(productDetails) }
             }
-            ITEM_ALREADY_OWNED -> BillingResult.Success("Already purchased")
-            ITEM_UNAVAILABLE, USER_CANCELED, ITEM_NOT_OWNED -> BillingResult.Failure(
-                ITEM_UNAVAILABLE
-            )
-            DEVELOPER_ERROR -> BillingResult.Failure(DEVELOPER_ERROR)
-            ERROR -> BillingResult.Failure(ERROR)
-            else -> BillingResult.Failure(code = code)
+            ITEM_ALREADY_OWNED -> Response.Success(Unit)
+            else -> getErrorResponseForCode(code)
         }
+    }
 
-
-    private suspend inline fun <T> tryConnectAndDo(action: () -> BillingResult<T>): BillingResult<T> =
+    private suspend inline fun <T> tryConnectAndDo(action: () -> Response<T>): Response<T> =
         when (val connectResult = client.tryConnect()) {
-            is BillingResult.Success -> if (connectResult.data) action() else BillingResult.NotConnected
-            is BillingResult.Failure -> connectResult
-            is BillingResult.FeatureNotSupported -> connectResult
-            is BillingResult.NotConnected -> connectResult
+            is Response.Success -> if (connectResult.data) action()
+            else getErrorResponseForCode(SERVICE_DISCONNECTED)
+            is Response.Error -> connectResult
         }
 
 
-    private suspend fun BillingClient.tryConnect(): BillingResult<Boolean> =
+    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 -> BillingResult.Success(true)
-                            SERVICE_DISCONNECTED -> BillingResult.NotConnected
-                            else -> BillingResult.Failure(billingResult.responseCode)
+                            OK -> Response.Success(true)
+                            else -> getErrorResponseForCode(billingResult.responseCode)
                         }
                     )
                 }
 
                 override fun onBillingServiceDisconnected() {
                     if (continuation.isCancelled || continuation.isCompleted) return
-                    continuation.resume(BillingResult.NotConnected)
+                    continuation.resume(getErrorResponseForCode(SERVICE_DISCONNECTED))
                 }
             })
         }
 
-    private suspend fun queryDetails(): BillingResult<List<SubscriptionData>> {
+    private suspend fun queryDetails(productIds: List<String>): Response<List<ProductDetails>> {
         val params = QueryProductDetailsParams.newBuilder()
-            .setProductList(subscriptionsList.map {
+            .setProductList(productIds.map {
                 QueryProductDetailsParams.Product.newBuilder()
                     .setProductId(it)
                     .setProductType(BillingClient.ProductType.SUBS)
@@ -117,17 +115,16 @@ class GoogleSubscriptionsManager(
         val productDetailsResult = onBG { client.queryProductDetails(params.build()) }
 
         return if (productDetailsResult.billingResult.responseCode == OK) {
-            productDetailsResult.productDetailsList?.filter { subscriptionsList.contains(it.productId) }
-                ?.map { SubscriptionData(it) }
+            productDetailsResult.productDetailsList?.filter { productIds.contains(it.productId) }
                 ?.takeIf { it.isNotEmpty() }
-                ?.let { BillingResult.Success(data = it) }
-                ?: BillingResult.Failure(code = ERROR)
+                ?.let { Response.Success(data = it) }
+                ?: getErrorResponseForCode(code = ERROR)
         } else {
-            BillingResult.Failure(code = productDetailsResult.billingResult.responseCode)
+            getErrorResponseForCode(productDetailsResult.billingResult.responseCode)
         }
     }
 
-    private fun purchase(productDetails: ProductDetails): BillingResult<String> {
+    private fun purchase(productDetails: ProductDetails): Response<Unit> {
         val productDetailsParamsList = listOf(
             BillingFlowParams.ProductDetailsParams.newBuilder()
                 .setProductDetails(productDetails)
@@ -140,8 +137,18 @@ class GoogleSubscriptionsManager(
 
         return when (val code =
             client.launchBillingFlow(activity, billingFlowParams).responseCode) {
-            OK -> BillingResult.Success("Started")
-            else -> BillingResult.Failure(code = code)
+            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/main/res/values/strings.xml b/app/src/main/res/values/strings.xml
index 07c92ff2861a2a54fdb870e235aa7e234a8fc9e3..1b3739751cea610cd50a40a4e2d089a4246ee2bd 100644
--- a/app/src/main/res/values/strings.xml
+++ b/app/src/main/res/values/strings.xml
@@ -239,6 +239,14 @@
     <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-array name="report_categories">
         <item>@string/crude_language</item>