Make payments code safer#4920
Merged
geekygecko merged 3 commits intomainfrom Jan 29, 2026
Merged
Conversation
Contributor
There was a problem hiding this comment.
Pull request overview
This PR refactors the :payment module to improve type safety by separating base subscription plans and offer plans into distinct maps. The changes address design issues discovered during installment plan implementation, making the codebase safer for future development.
Changes:
- Split the single
plansmap into separatebasePlansandofferPlansmaps with stronger type constraints - Improved error handling in mapper functions to return
PaymentResultinstead of throwing exceptions - Refactored and split test cases for better clarity
Reviewed changes
Copilot reviewed 3 out of 3 changed files in this pull request and generated 2 comments.
| File | Description |
|---|---|
| modules/services/payment/src/main/kotlin/au/com/shiftyjelly/pocketcasts/payment/Data.kt | Core refactoring: separate maps for base and offer plans, improved type safety, enhanced error handling |
| modules/services/payment/src/test/kotlin/au/com/shiftyjelly/pocketcasts/payment/SubscriptionPlansTest.kt | Fixed spelling error, refactored tests into smaller focused tests, removed obsolete validation test |
| modules/services/payment/src/main/kotlin/au/com/shiftyjelly/pocketcasts/payment/PaymentResult.kt | Removed unnecessary constructor keyword from data class |
Comments suppressed due to low confidence (1)
modules/services/payment/src/main/kotlin/au/com/shiftyjelly/pocketcasts/payment/Data.kt:126
- The offerPlanKeys generation now includes keys with both offer and isInstallment=true, which violates the business rule that installment plans cannot have promotional offers. These keys will always fail to match products (due to the isValidInstallment check on line 205) and create unnecessary failure entries in the offerPlans map. The previous code explicitly filtered out installment plans before creating offer keys. Consider restoring the filter: .filter { !it.isInstallment } before the flatMap to maintain the business rule explicitly and avoid creating invalid key combinations.
private val offerPlanKeys = basePlanKeys
.flatMap { baseKey ->
SubscriptionOffer.entries.map { offer ->
baseKey.copy(offer = offer)
}
}
…cketcasts/payment/SubscriptionPlansTest.kt Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
…cketcasts/payment/Data.kt Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Contributor
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 3 out of 3 changed files in this pull request and generated 1 comment.
Comments suppressed due to low confidence (1)
modules/services/payment/src/main/kotlin/au/com/shiftyjelly/pocketcasts/payment/Data.kt:126
- The offerPlanKeys generation creates keys with isInstallment=true when copying from installment base keys, but the findOfferPlan function always creates keys with isInstallment=false (the default). This means half of the entries in the offerPlans map can never be accessed through findOfferPlan. Consider filtering out installment keys before creating offer keys to avoid storing unnecessary entries in the offerPlans map.
private val offerPlanKeys = basePlanKeys
.flatMap { baseKey ->
SubscriptionOffer.entries.map { offer ->
baseKey.copy(offer = offer)
}
}
geekygecko
approved these changes
Jan 29, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Description
When installments were being implemented I noticed that some parts of the design of the
:paymentmodule are not clear making its further development unsafe. This PR address that. The main change is that the base payments and offer payments are stored in separate maps making accessing data type-safe.Testing Instructions
Code review should be enough as the
:paymentmodule is highly covered in tests. But you can try making a purchase with the prototype or the release variant.Checklist
./gradlew spotlessApplyto automatically apply formatting/linting)modules/services/localization/src/main/res/values/strings.xmlI have tested any UI changes...