Updated on 2026-08-14
This commit is contained in:
parent
71507af6c3
commit
589805424e
9 changed files with 129 additions and 66 deletions
|
|
@ -10,6 +10,7 @@ import com.tangem.domain.models.account.PaymentAccountStatusValue
|
|||
import com.tangem.domain.models.kyc.KycStatus
|
||||
import com.tangem.domain.pay.flow.PaymentAccountStatusFetcher
|
||||
import com.tangem.domain.pay.model.CustomerInfo
|
||||
import com.tangem.domain.pay.model.OrderData
|
||||
import com.tangem.domain.pay.model.OrderStatus
|
||||
import com.tangem.domain.pay.repository.CustomerOrderRepository
|
||||
import com.tangem.domain.pay.repository.OnboardingRepository
|
||||
|
|
@ -19,7 +20,11 @@ import com.tangem.security.DeviceSecurityInfoProvider
|
|||
import com.tangem.security.isSecurityExposed
|
||||
import com.tangem.utils.coroutines.CoroutineDispatcherProvider
|
||||
import com.tangem.utils.logging.TangemLogger
|
||||
import kotlinx.coroutines.currentCoroutineContext
|
||||
import kotlinx.coroutines.delay
|
||||
import kotlinx.coroutines.isActive
|
||||
import javax.inject.Inject
|
||||
import kotlin.time.Duration.Companion.minutes
|
||||
|
||||
private const val TAG = "PaymentAccountStatusFetcher"
|
||||
|
||||
|
|
@ -144,53 +149,103 @@ internal class DefaultPaymentAccountStatusFetcher @Inject constructor(
|
|||
}
|
||||
|
||||
private suspend fun proceedWithOrderId(account: Account.Payment, orderId: String): PaymentAccountStatusValue {
|
||||
// Step 1: Check KYC status first
|
||||
val customerInfo = onboardingRepository.getCustomerInfo(account.userWalletId).fold(
|
||||
ifLeft = { error ->
|
||||
logger.e("proceedWithOrderId KYC check ${account.userWalletId} error: $error")
|
||||
return error.mapToPaymentAccountStatus()
|
||||
},
|
||||
ifRight = { it },
|
||||
)
|
||||
|
||||
logger.i("proceedWithOrderId ${account.userWalletId} kycStatus: ${customerInfo.kycStatus}")
|
||||
|
||||
when (customerInfo.kycStatus) {
|
||||
KycStatus.PENDING,
|
||||
KycStatus.INIT,
|
||||
KycStatus.REJECTED,
|
||||
-> return customerInfo.mapToPaymentAccountStatus()
|
||||
KycStatus.APPROVED -> Unit // proceed to order check
|
||||
}
|
||||
|
||||
// Step 2: Check order status
|
||||
return customerOrderRepository.getOrderData(userWalletId = account.userWalletId, orderId = orderId).fold(
|
||||
ifLeft = { error ->
|
||||
logger.e("proceedWithOrderId ${account.userWalletId} orderId: $orderId error: $error")
|
||||
error.mapToPaymentAccountStatus()
|
||||
},
|
||||
ifRight = { orderData ->
|
||||
logger.i("proceedWithOrderId $account.userWalletId: $orderId status: ${orderData.status}")
|
||||
logger.i("proceedWithOrderId ${account.userWalletId}: $orderId status: ${orderData.status}")
|
||||
when (orderData.status) {
|
||||
// Kyc is passed and user waits for order creation -> no need to get customer info
|
||||
OrderStatus.CANCELED -> handleCanceledOrder(account, orderData)
|
||||
OrderStatus.COMPLETED -> handleCompletedOrder(account)
|
||||
OrderStatus.UNKNOWN -> PaymentAccountStatusValue.Error.Unavailable
|
||||
OrderStatus.NEW,
|
||||
OrderStatus.PROCESSING,
|
||||
-> PaymentAccountStatusValue.IssuingCard(source = StatusSource.ACTUAL)
|
||||
|
||||
OrderStatus.CANCELED -> {
|
||||
onboardingRepository.getCustomerInfo(userWalletId = account.userWalletId)
|
||||
.fold(
|
||||
ifLeft = {
|
||||
PaymentAccountStatusValue.Error.CardIssueFailed(
|
||||
customerId = orderData.customerId,
|
||||
)
|
||||
},
|
||||
ifRight = { customerInfo ->
|
||||
if (customerInfo.kycStatus == KycStatus.REJECTED) {
|
||||
customerInfo.mapToPaymentAccountStatus()
|
||||
} else {
|
||||
PaymentAccountStatusValue.Error.CardIssueFailed(
|
||||
customerId = orderData.customerId,
|
||||
)
|
||||
}
|
||||
},
|
||||
)
|
||||
-> {
|
||||
paymentAccountStatusesStore.store(
|
||||
userWalletId = account.userWalletId,
|
||||
status = AccountStatus.Payment(
|
||||
account = account,
|
||||
value = PaymentAccountStatusValue.IssuingCard(source = StatusSource.ACTUAL),
|
||||
),
|
||||
)
|
||||
// Start polling for terminal state
|
||||
pollOrderStatus(account = account, orderId = orderId)
|
||||
}
|
||||
OrderStatus.COMPLETED -> {
|
||||
// Order was completed -> clear order id and get customer info
|
||||
onboardingRepository.clearOrderId(account.userWalletId)
|
||||
onboardingRepository.getCustomerInfo(userWalletId = account.userWalletId)
|
||||
.fold(
|
||||
ifLeft = { it.mapToPaymentAccountStatus() },
|
||||
ifRight = { customerInfo -> customerInfo.mapToPaymentAccountStatus() },
|
||||
)
|
||||
}
|
||||
OrderStatus.UNKNOWN -> PaymentAccountStatusValue.Error.Unavailable
|
||||
}
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
private suspend fun pollOrderStatus(account: Account.Payment, orderId: String): PaymentAccountStatusValue {
|
||||
while (currentCoroutineContext().isActive) {
|
||||
delay(1.minutes)
|
||||
|
||||
val result = customerOrderRepository.getOrderData(
|
||||
userWalletId = account.userWalletId,
|
||||
orderId = orderId,
|
||||
)
|
||||
|
||||
result.fold(
|
||||
ifLeft = { error ->
|
||||
logger.e("pollOrderStatus ${account.userWalletId} orderId: $orderId error: $error")
|
||||
// Continue polling on transient errors
|
||||
},
|
||||
ifRight = { orderData ->
|
||||
logger.i("pollOrderStatus ${account.userWalletId}: $orderId status: ${orderData.status}")
|
||||
when (orderData.status) {
|
||||
OrderStatus.CANCELED -> return handleCanceledOrder(account, orderData)
|
||||
OrderStatus.COMPLETED -> return handleCompletedOrder(account)
|
||||
OrderStatus.NEW,
|
||||
OrderStatus.PROCESSING,
|
||||
OrderStatus.UNKNOWN,
|
||||
-> Unit // Continue polling
|
||||
}
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
return PaymentAccountStatusValue.IssuingCard(source = StatusSource.ACTUAL)
|
||||
}
|
||||
|
||||
private suspend fun handleCanceledOrder(
|
||||
account: Account.Payment,
|
||||
orderData: OrderData,
|
||||
): PaymentAccountStatusValue {
|
||||
onboardingRepository.clearOrderId(account.userWalletId)
|
||||
return PaymentAccountStatusValue.Error.CardIssueFailed(orderData.customerId)
|
||||
}
|
||||
|
||||
private suspend fun handleCompletedOrder(account: Account.Payment): PaymentAccountStatusValue {
|
||||
onboardingRepository.clearOrderId(account.userWalletId)
|
||||
return onboardingRepository.getCustomerInfo(userWalletId = account.userWalletId)
|
||||
.fold(
|
||||
ifLeft = { it.mapToPaymentAccountStatus() },
|
||||
ifRight = { customerInfo -> customerInfo.mapToPaymentAccountStatus() },
|
||||
)
|
||||
}
|
||||
|
||||
private fun CustomerInfo.mapToPaymentAccountStatus(): PaymentAccountStatusValue {
|
||||
val cardInfo = this.cardInfo
|
||||
val productInstance = this.productInstance
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue