Skip to content

Commit

Permalink
fix: address PR comments
Browse files Browse the repository at this point in the history
  • Loading branch information
farhan-arshad-dev committed Jan 20, 2025
1 parent 1bc2d82 commit 3e7c595
Show file tree
Hide file tree
Showing 10 changed files with 51 additions and 32 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -14,14 +14,14 @@ import org.openedx.core.domain.model.EnrolledCourse
import org.openedx.core.domain.model.iap.ProductInfo
import org.openedx.core.domain.model.iap.PurchaseFlowData
import org.openedx.core.exception.iap.IAPException
import org.openedx.core.extension.decodeToLong
import org.openedx.core.extension.decodeToString
import org.openedx.core.module.billing.BillingProcessor
import org.openedx.core.module.billing.getCourseSku
import org.openedx.core.module.billing.getPriceAmount
import org.openedx.core.module.billing.getUserId
import org.openedx.core.presentation.global.AppData
import org.openedx.core.presentation.iap.IAPRequestType
import org.openedx.core.utils.EmailUtil
import org.openedx.core.utils.TimeUtils

class IAPInteractor(
private val appData: AppData,
Expand Down Expand Up @@ -115,19 +115,19 @@ class IAPInteractor(
suspend fun processUnfulfilledPurchase(
userId: Long,
enrolledCourses: List<EnrolledCourse>,
purchaseVerified: (PurchaseFlowData) -> Unit = {},
): Boolean {
verificationInitiated: (PurchaseFlowData) -> Unit = {},
): PurchaseFlowData? {
val purchases = billingProcessor.queryPurchases()
val userPurchases = purchases.filter { purchase ->
val userAccountId = purchase.accountIdentifiers?.obfuscatedAccountId?.decodeToLong()
val storeSku = purchase.accountIdentifiers?.obfuscatedProfileId?.decodeToString()
val userAccountId = purchase.getUserId()
val courseSku = purchase.getCourseSku()

userAccountId == userId && enrolledCourses.any { enrolledCourse ->
storeSku == enrolledCourse.productInfo?.courseSku
courseSku == enrolledCourse.productInfo?.courseSku
}
}
if (userPurchases.isNotEmpty()) {
userPurchases.forEach { purchase ->
userPurchases[0].let { purchase ->
val courseVerified = enrolledCourses.find { enrolledCourse ->
enrolledCourse.productInfo?.courseSku == purchase.getCourseSku()
}
Expand All @@ -143,18 +143,19 @@ class IAPInteractor(
this.price = it.getPriceAmount()
this.currencyCode = it.priceCurrencyCode
}
this.flowStartTime = TimeUtils.getCurrentTime()
}
verificationInitiated(purchaseProductFlow)
startUnfulfilledVerification(purchase)
purchaseVerified(purchaseProductFlow)
return purchaseProductFlow
}
}
return true
} else {
purchases.forEach {
purchases.subtract(userPurchases.toSet()).forEach {
billingProcessor.consumePurchase(it.purchaseToken)
}
}
return false
return null
}

private suspend fun startUnfulfilledVerification(userPurchase: Purchase) {
Expand All @@ -177,17 +178,17 @@ class IAPInteractor(

suspend fun detectUnfulfilledPurchase(
enrolledCourses: List<EnrolledCourse>,
purchaseVerified: (PurchaseFlowData) -> Unit,
onSuccess: () -> Unit,
verificationInitiated: (PurchaseFlowData) -> Unit,
onSuccess: (PurchaseFlowData) -> Unit,
onFailure: (IAPException) -> Unit,
) {
if (isIAPEnabled) {
preferencesManager.user?.id?.let { userId ->
runCatching {
processUnfulfilledPurchase(userId, enrolledCourses, purchaseVerified)
}.onSuccess {
if (it) {
onSuccess()
processUnfulfilledPurchase(userId, enrolledCourses, verificationInitiated)
}.onSuccess { purchaseFlowData ->
purchaseFlowData?.let {
onSuccess(purchaseFlowData)
}
}.onFailure {
if (it is IAPException) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,4 +4,8 @@ data class CourseEnrollments(
val enrollments: DashboardCourseList,
val configs: AppConfig,
val primary: EnrolledCourse?,
)
) {
fun hasEnrolledCourses(): Boolean {
return primary != null || enrollments.courses.isNotEmpty()
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ import kotlinx.coroutines.launch
import kotlinx.coroutines.suspendCancellableCoroutine
import kotlinx.coroutines.withContext
import org.openedx.core.domain.model.iap.ProductInfo
import org.openedx.core.extension.decodeToLong
import org.openedx.core.extension.decodeToString
import org.openedx.core.extension.encodeToString
import org.openedx.core.extension.safeResume
Expand Down Expand Up @@ -203,3 +204,7 @@ fun ProductDetails.OneTimePurchaseOfferDetails.getPriceAmount(): Double =
fun Purchase.getCourseSku(): String? {
return this.accountIdentifiers?.obfuscatedProfileId?.decodeToString()
}

fun Purchase.getUserId(): Long? {
return this.accountIdentifiers?.obfuscatedAccountId?.decodeToLong()
}
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ import org.openedx.core.utils.TimeUtils

class IAPEventLogger(
private val analytics: IAPAnalytics,
private val isSilentIAPFlow: Boolean? = null,
val isSilentIAPFlow: Boolean? = null,
var purchaseFlowData: PurchaseFlowData? = null,
) {
fun upgradeNowClickedEvent() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,9 @@ class IAPViewModel(
iapNotifier.notifier.onEach { event ->
when (event) {
is CourseDataUpdated -> {
eventLogger.upgradeSuccessEvent()
if (eventLogger.isSilentIAPFlow == null) {
eventLogger.upgradeSuccessEvent()
}
_uiMessage.emit(UIMessage.ToastMessage(resourceManager.getString(R.string.iap_success_message)))
_uiState.value = IAPUIState.CourseDataUpdated
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -286,7 +286,6 @@ class CourseContainerViewModel(
}
if (isIAPFlow) {
if (isExpiredCoursePurchase) {
eventLogger.upgradeSuccessEvent()
_uiMessage.emit(
UIMessage.ToastMessage(
resourceManager.getString(CoreR.string.iap_success_message)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -263,8 +263,8 @@ private fun DashboardGalleryView(
},
onIAPAction = onIAPAction,
)
LaunchedEffect(uiState.userCourses.enrollments.courses) {
if (uiState.userCourses.enrollments.courses.isNotEmpty()) {
LaunchedEffect(uiState.userCourses.hasEnrolledCourses()) {
if (uiState.userCourses.hasEnrolledCourses()) {
onIAPAction(IAPAction.ACTION_UNFULFILLED, null, null)
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -281,13 +281,17 @@ class DashboardGalleryViewModel(
interactor.getAllUserCourses(status = CourseStatusFilter.ALL).courses
iapInteractor.detectUnfulfilledPurchase(
enrolledCourses = enrolledCourses,
purchaseVerified = { purchaseFlowData ->
verificationInitiated = { purchaseFlowData ->
eventLogger.apply {
this.purchaseFlowData = purchaseFlowData
this.logUnfulfilledPurchaseInitiatedEvent()
}
},
onSuccess = {
onSuccess = { purchaseFlowData ->
eventLogger.apply {
this.purchaseFlowData = purchaseFlowData
eventLogger.upgradeSuccessEvent()
}
_iapUiState.tryEmit(IAPUIState.PurchasesFulfillmentCompleted)
},
onFailure = {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -321,13 +321,17 @@ class DashboardListViewModel(
interactor.getAllUserCourses(status = CourseStatusFilter.ALL).courses
iapInteractor.detectUnfulfilledPurchase(
enrolledCourses = enrolledCourses,
purchaseVerified = { purchaseFlowData ->
verificationInitiated = { purchaseFlowData ->
eventLogger.apply {
this.purchaseFlowData = purchaseFlowData
this.logUnfulfilledPurchaseInitiatedEvent()
}
},
onSuccess = {
onSuccess = { purchaseFlowData ->
eventLogger.apply {
this.purchaseFlowData = purchaseFlowData
eventLogger.upgradeSuccessEvent()
}
_iapUiState.tryEmit(IAPUIState.PurchasesFulfillmentCompleted)
},
onFailure = {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -264,16 +264,16 @@ class SettingsViewModel(
iapInteractor.processUnfulfilledPurchase(
userId,
enrolledCourses,
purchaseVerified = { purchaseFlowData ->
verificationInitiated = { purchaseFlowData ->
eventLogger.apply {
this.purchaseFlowData = purchaseFlowData
this.logUnfulfilledPurchaseInitiatedEvent()
}
})
}.onSuccess {
if (it) {
}.onSuccess { purchaseFlowData ->
purchaseFlowData?.let {
_iapUiState.emit(IAPUIState.PurchasesFulfillmentCompleted)
} else {
} ?: run {
_iapUiState.emit(IAPUIState.FakePurchasesFulfillmentCompleted)
}
}.onFailure {
Expand Down

0 comments on commit 3e7c595

Please sign in to comment.