Skip to content

Commit

Permalink
Fix OfferingsParser exceptions being swallowed (#1228)
Browse files Browse the repository at this point in the history
  • Loading branch information
vegaro authored and tonidero committed Oct 31, 2023
1 parent a145323 commit 6adab9b
Show file tree
Hide file tree
Showing 3 changed files with 70 additions and 41 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,8 @@ internal class PurchasesFactory(
val sharedPreferencesForETags = ETagManager.initializeSharedPreferences(context)
val eTagManager = ETagManager(sharedPreferencesForETags)

val dispatcher = Dispatcher(service ?: createDefaultExecutor(), runningIntegrationTests)
val dispatcher = Dispatcher(createDefaultExecutor(), runningIntegrationTests)
val backendDispatcher = Dispatcher(service ?: createDefaultExecutor(), runningIntegrationTests)
val diagnosticsDispatcher = Dispatcher(createDiagnosticsExecutor(), runningIntegrationTests)

var diagnosticsFileHelper: DiagnosticsFileHelper? = null
Expand All @@ -102,10 +103,10 @@ internal class PurchasesFactory(
val signingManager = SigningManager(signatureVerificationMode, appConfig, apiKey)

val httpClient = HTTPClient(appConfig, eTagManager, diagnosticsTracker, signingManager)
val backendHelper = BackendHelper(apiKey, dispatcher, appConfig, httpClient)
val backendHelper = BackendHelper(apiKey, backendDispatcher, appConfig, httpClient)
val backend = Backend(
appConfig,
dispatcher,
backendDispatcher,
diagnosticsDispatcher,
httpClient,
backendHelper,
Expand All @@ -124,7 +125,7 @@ internal class PurchasesFactory(

val subscriberAttributesPoster = SubscriberAttributesPoster(backendHelper)

val attributionFetcher = AttributionFetcherFactory.createAttributionFetcher(store, dispatcher)
val attributionFetcher = AttributionFetcherFactory.createAttributionFetcher(store, backendDispatcher)

val subscriberAttributesCache = SubscriberAttributesCache(cache)

Expand Down Expand Up @@ -183,7 +184,7 @@ internal class PurchasesFactory(
appConfig,
cache,
billing,
dispatcher,
backendDispatcher,
identityManager,
postTransactionWithProductDetailsHelper,
)
Expand Down Expand Up @@ -218,7 +219,7 @@ internal class PurchasesFactory(
val offeringsManager = OfferingsManager(
offeringsCache,
backend,
OfferingsFactory(billing, offeringParser),
OfferingsFactory(billing, offeringParser, dispatcher),
)

log(LogIntent.DEBUG, ConfigureStrings.DEBUG_ENABLED)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,19 +5,23 @@ import com.revenuecat.purchases.ProductType
import com.revenuecat.purchases.PurchasesError
import com.revenuecat.purchases.PurchasesErrorCode
import com.revenuecat.purchases.common.BillingAbstract
import com.revenuecat.purchases.common.Dispatcher
import com.revenuecat.purchases.common.LogIntent
import com.revenuecat.purchases.common.OfferingParser
import com.revenuecat.purchases.common.log
import com.revenuecat.purchases.models.StoreProduct
import com.revenuecat.purchases.strings.OfferingStrings
import kotlinx.serialization.SerializationException
import org.json.JSONException
import org.json.JSONObject

internal class OfferingsFactory(
private val billing: BillingAbstract,
private val offeringParser: OfferingParser,
private val dispatcher: Dispatcher,
) {

@SuppressWarnings("TooGenericExceptionCaught")
fun createOfferings(
offeringsJSON: JSONObject,
onError: (PurchasesError) -> Unit,
Expand All @@ -34,18 +38,35 @@ internal class OfferingsFactory(
)
} else {
getStoreProductsById(allRequestedProductIdentifiers, { productsById ->
logMissingProducts(allRequestedProductIdentifiers, productsById)
try {
logMissingProducts(allRequestedProductIdentifiers, productsById)

val offerings = offeringParser.createOfferings(offeringsJSON, productsById)
if (offerings.all.isEmpty()) {
onError(
PurchasesError(
PurchasesErrorCode.ConfigurationError,
OfferingStrings.CONFIGURATION_ERROR_PRODUCTS_NOT_FOUND,
),
)
} else {
onSuccess(offerings)
val offerings = offeringParser.createOfferings(offeringsJSON, productsById)
if (offerings.all.isEmpty()) {
onError(
PurchasesError(
PurchasesErrorCode.ConfigurationError,
OfferingStrings.CONFIGURATION_ERROR_PRODUCTS_NOT_FOUND,
),
)
} else {
onSuccess(offerings)
}
} catch (error: Exception) {
when (error) {
is JSONException, is SerializationException -> {
log(
LogIntent.RC_ERROR,
OfferingStrings.JSON_EXCEPTION_ERROR.format(error.localizedMessage),
)
onError(
PurchasesError(
PurchasesErrorCode.UnexpectedBackendResponseError,
error.localizedMessage,
),
)
} else -> throw error
}
}
}, { error ->
onError(error)
Expand Down Expand Up @@ -87,27 +108,31 @@ internal class OfferingsFactory(
ProductType.SUBS,
productIds,
{ subscriptionProducts ->
val productsById = subscriptionProducts
.groupBy { subProduct -> subProduct.purchasingData.productId }
.toMutableMap()
val subscriptionIds = productsById.keys
dispatcher.enqueue(command = {
val productsById = subscriptionProducts
.groupBy { subProduct -> subProduct.purchasingData.productId }
.toMutableMap()
val subscriptionIds = productsById.keys

val inAppProductIds = productIds - subscriptionIds
if (inAppProductIds.isNotEmpty()) {
billing.queryProductDetailsAsync(
ProductType.INAPP,
inAppProductIds,
{ inAppProducts ->
productsById.putAll(inAppProducts.map { it.purchasingData.productId to listOf(it) })
onCompleted(productsById)
},
{
onError(it)
},
)
} else {
onCompleted(productsById)
}
val inAppProductIds = productIds - subscriptionIds
if (inAppProductIds.isNotEmpty()) {
billing.queryProductDetailsAsync(
ProductType.INAPP,
inAppProductIds,
{ inAppProducts ->
dispatcher.enqueue(command = {
productsById.putAll(inAppProducts.map { it.purchasingData.productId to listOf(it) })
onCompleted(productsById)
})
},
{
onError(it)
},
)
} else {
onCompleted(productsById)
}
})
},
{
onError(it)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import com.revenuecat.purchases.ProductType
import com.revenuecat.purchases.PurchasesError
import com.revenuecat.purchases.PurchasesErrorCode
import com.revenuecat.purchases.common.BillingAbstract
import com.revenuecat.purchases.common.Dispatcher
import com.revenuecat.purchases.common.GoogleOfferingParser
import com.revenuecat.purchases.common.OfferingParser
import com.revenuecat.purchases.models.StoreProduct
Expand All @@ -14,6 +15,7 @@ import com.revenuecat.purchases.utils.ONE_OFFERINGS_INAPP_PRODUCT_RESPONSE
import com.revenuecat.purchases.utils.ONE_OFFERINGS_RESPONSE
import com.revenuecat.purchases.utils.STUB_OFFERING_IDENTIFIER
import com.revenuecat.purchases.utils.STUB_PRODUCT_IDENTIFIER
import com.revenuecat.purchases.utils.SyncDispatcher
import com.revenuecat.purchases.utils.stubINAPPStoreProduct
import com.revenuecat.purchases.utils.stubStoreProduct
import com.revenuecat.purchases.utils.stubSubscriptionOption
Expand Down Expand Up @@ -43,17 +45,18 @@ class OfferingsFactoryTest {

private lateinit var billing: BillingAbstract
private lateinit var offeringParser: OfferingParser

private lateinit var dispatcher: Dispatcher
private lateinit var offeringsFactory: OfferingsFactory

@Before
fun setUp() {
billing = mockk()
offeringParser = GoogleOfferingParser()

dispatcher = SyncDispatcher()
offeringsFactory = OfferingsFactory(
billing = billing,
offeringParser = offeringParser
billing,
offeringParser,
dispatcher
)
}

Expand Down

0 comments on commit 6adab9b

Please sign in to comment.