Updated on 2026-08-14
This commit is contained in:
parent
616386c345
commit
b81ea5cf6e
9 changed files with 133 additions and 59 deletions
|
|
@ -9,6 +9,7 @@ import com.tangem.domain.pay.DataForReceiveFactory
|
|||
import com.tangem.domain.pay.repository.CardDetailsRepository
|
||||
import com.tangem.domain.pay.repository.KycRepository
|
||||
import com.tangem.domain.pay.repository.OnboardingRepository
|
||||
import com.tangem.domain.pay.usecase.ProduceTangemPayInitialDataUseCase
|
||||
import com.tangem.domain.pay.usecase.TangemPayIssueOrderUseCase
|
||||
import com.tangem.domain.pay.usecase.TangemPayMainScreenCustomerInfoUseCase
|
||||
import com.tangem.domain.tangempay.repository.TangemPayTxHistoryRepository
|
||||
|
|
@ -52,6 +53,14 @@ internal interface TangemPayDataModule {
|
|||
return TangemPayMainScreenCustomerInfoUseCase(repository = repository)
|
||||
}
|
||||
|
||||
@Provides
|
||||
@Singleton
|
||||
fun provideProduceTangemPayInitialDataUseCase(
|
||||
repository: OnboardingRepository,
|
||||
): ProduceTangemPayInitialDataUseCase {
|
||||
return ProduceTangemPayInitialDataUseCase(repository = repository)
|
||||
}
|
||||
|
||||
@Provides
|
||||
@Singleton
|
||||
fun provideTangemPayIssueOrderUseCase(repository: OnboardingRepository): TangemPayIssueOrderUseCase {
|
||||
|
|
|
|||
|
|
@ -2,12 +2,14 @@ package com.tangem.data.pay.repository
|
|||
|
||||
import arrow.core.Either
|
||||
import com.tangem.core.error.UniversalError
|
||||
import com.tangem.data.pay.util.TangemPayWalletsManager
|
||||
import com.tangem.datasource.api.common.response.getOrThrow
|
||||
import com.tangem.datasource.api.pay.TangemPayApi
|
||||
import com.tangem.datasource.api.pay.models.request.DeeplinkValidityRequest
|
||||
import com.tangem.datasource.api.pay.models.request.OrderRequest
|
||||
import com.tangem.datasource.api.pay.models.response.CustomerMeResponse
|
||||
import com.tangem.datasource.local.visa.TangemPayStorage
|
||||
import com.tangem.domain.pay.datasource.TangemPayAuthDataSource
|
||||
import com.tangem.domain.pay.model.CustomerInfo
|
||||
import com.tangem.domain.pay.model.CustomerInfo.CardInfo
|
||||
import com.tangem.domain.pay.model.CustomerInfo.ProductInstance
|
||||
|
|
@ -27,6 +29,8 @@ internal class DefaultOnboardingRepository @Inject constructor(
|
|||
private val tangemPayApi: TangemPayApi,
|
||||
private val requestHelper: TangemPayRequestPerformer,
|
||||
private val tangemPayStorage: TangemPayStorage,
|
||||
private val authDataSource: TangemPayAuthDataSource,
|
||||
private val tangemPayWalletsManager: TangemPayWalletsManager,
|
||||
) : OnboardingRepository {
|
||||
|
||||
override suspend fun validateDeeplink(link: String): Either<UniversalError, Boolean> {
|
||||
|
|
@ -38,6 +42,31 @@ internal class DefaultOnboardingRepository @Inject constructor(
|
|||
}
|
||||
}
|
||||
|
||||
override suspend fun isTangemPayInitialDataProduced(): Boolean {
|
||||
val walletId = tangemPayWalletsManager.getDefaultWalletForTangemPay().walletId
|
||||
val customerWalletAddress = tangemPayStorage.getCustomerWalletAddress(walletId) ?: return false
|
||||
tangemPayStorage.getAuthTokens(customerWalletAddress) ?: return false
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
override suspend fun produceInitialData() {
|
||||
val wallet = tangemPayWalletsManager.getDefaultWalletForTangemPay()
|
||||
val initialCredentials = authDataSource.produceInitialCredentials(cardId = wallet.cardId)
|
||||
.fold(
|
||||
ifLeft = { error -> error("Can not produce initial data: ${error.message}") },
|
||||
ifRight = { it },
|
||||
)
|
||||
tangemPayStorage.storeCustomerWalletAddress(
|
||||
userWalletId = wallet.walletId,
|
||||
customerWalletAddress = initialCredentials.customerWalletAddress,
|
||||
)
|
||||
tangemPayStorage.storeAuthTokens(
|
||||
customerWalletAddress = initialCredentials.customerWalletAddress,
|
||||
tokens = initialCredentials.authTokens,
|
||||
)
|
||||
}
|
||||
|
||||
override suspend fun getCustomerInfo(): Either<UniversalError, CustomerInfo> {
|
||||
return requestHelper.runWithErrorLogs(TAG) {
|
||||
val result = requestHelper.request { authHeader ->
|
||||
|
|
@ -85,7 +114,7 @@ internal class DefaultOnboardingRepository @Inject constructor(
|
|||
override suspend fun createOrder(): Either<UniversalError, Unit> = withContext(dispatcherProvider.io) {
|
||||
requestHelper.runWithErrorLogs(TAG) {
|
||||
val walletAddress = requestHelper.getCustomerWalletAddress()
|
||||
val result = requestHelper.requestWithPersistedToken { authHeader ->
|
||||
val result = requestHelper.request { authHeader ->
|
||||
tangemPayApi.createOrder(authHeader, body = OrderRequest(walletAddress))
|
||||
}.result ?: error("Create order result is null")
|
||||
|
||||
|
|
@ -129,7 +158,7 @@ internal class DefaultOnboardingRepository @Inject constructor(
|
|||
}
|
||||
|
||||
private suspend fun getCustomerInfoWithPersistedToken(): CustomerInfo {
|
||||
val result = requestHelper.requestWithPersistedToken { authHeader ->
|
||||
val result = requestHelper.request { authHeader ->
|
||||
tangemPayApi.getCustomerMe(authHeader)
|
||||
}.result
|
||||
return getCustomerInfo(result)
|
||||
|
|
|
|||
|
|
@ -63,15 +63,6 @@ internal class TangemPayRequestPerformer @Inject constructor(
|
|||
)
|
||||
}
|
||||
|
||||
suspend fun <T : Any> requestWithPersistedToken(requestBlock: suspend (header: String) -> ApiResponse<T>): T =
|
||||
withContext(dispatchers.io) {
|
||||
performRequest(
|
||||
requestBlock = requestBlock,
|
||||
getTokens = { getAccessTokensIfSaved() ?: error("Cannot get saved access tokens") },
|
||||
refreshTokens = ::refreshAuthTokens,
|
||||
)
|
||||
}
|
||||
|
||||
private suspend fun <T : Any> performRequest(
|
||||
requestBlock: suspend (header: String) -> ApiResponse<T>,
|
||||
getTokens: (suspend () -> VisaAuthTokens),
|
||||
|
|
@ -128,40 +119,20 @@ internal class TangemPayRequestPerformer @Inject constructor(
|
|||
}
|
||||
|
||||
private suspend fun getAccessTokens(): VisaAuthTokens {
|
||||
return getAccessTokensIfSaved() ?: fetchTokens()
|
||||
}
|
||||
|
||||
private suspend fun getAccessTokensIfSaved(): VisaAuthTokens? {
|
||||
return tangemPayStorage.getAuthTokens(getCustomerWalletAddress())
|
||||
}
|
||||
|
||||
private suspend fun fetchTokens(): VisaAuthTokens {
|
||||
val wallet = tangemPayWalletsManager.getDefaultWalletForTangemPay()
|
||||
val initialCredentials = authDataSource.produceInitialCredentials(cardId = wallet.cardId)
|
||||
.getOrThrowWithMessage("Can not produce initial data:")
|
||||
tangemPayStorage.storeCustomerWalletAddress(
|
||||
userWalletId = wallet.walletId,
|
||||
customerWalletAddress = initialCredentials.customerWalletAddress,
|
||||
)
|
||||
tangemPayStorage.storeAuthTokens(
|
||||
customerWalletAddress = initialCredentials.customerWalletAddress,
|
||||
tokens = initialCredentials.authTokens,
|
||||
)
|
||||
return initialCredentials.authTokens
|
||||
val walletAddress = getCustomerWalletAddress()
|
||||
val tokens = tangemPayStorage.getAuthTokens(walletAddress) ?: error("Auth tokens are not stored")
|
||||
return tokens
|
||||
}
|
||||
|
||||
private suspend fun refreshAuthTokens(): VisaAuthTokens {
|
||||
val customerWalletAddress = getCustomerWalletAddress()
|
||||
val refreshToken = getAccessTokens().refreshToken.value
|
||||
val tokens = authDataSource.refreshAuthTokens(refreshToken).getOrThrowWithMessage("Cannot refresh tokens:")
|
||||
val tokens = authDataSource.refreshAuthTokens(refreshToken)
|
||||
.fold(
|
||||
ifLeft = { error -> error("Cannot refresh tokens: ${error.message}") },
|
||||
ifRight = { it },
|
||||
)
|
||||
tangemPayStorage.storeAuthTokens(customerWalletAddress, tokens)
|
||||
return tokens
|
||||
}
|
||||
|
||||
private fun <A : Throwable, B> Either<A, B>.getOrThrowWithMessage(message: String): B {
|
||||
return this.fold(
|
||||
ifLeft = { error -> throw IllegalStateException("$message ${error.message}") },
|
||||
ifRight = { it },
|
||||
)
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue