Updated on 2026-08-14
This commit is contained in:
parent
19fb8f2bcd
commit
ecdb72e55c
58 changed files with 1082 additions and 346 deletions
|
|
@ -1,5 +0,0 @@
|
|||
package com.tangem.domain.visa.model
|
||||
|
||||
data class ActivationOrder(
|
||||
val hash: String,
|
||||
)
|
||||
|
|
@ -1,6 +0,0 @@
|
|||
package com.tangem.domain.visa.model
|
||||
|
||||
data class SignedActivationOrder(
|
||||
val activationOrder: ActivationOrder,
|
||||
val signature: String,
|
||||
)
|
||||
|
|
@ -4,6 +4,7 @@ enum class VisaActivationError(val message: String) {
|
|||
BlockedForActivation("Card is blocked for activation"),
|
||||
InvalidActivationState("Invalid activation state"),
|
||||
WrongCard("Wrong card tapped"),
|
||||
WrongRemoteState("Wrong remote state"),
|
||||
MissingWallet("Missing wallet"),
|
||||
MissingRootOTP("Missing root OTP"),
|
||||
}
|
||||
|
|
@ -8,26 +8,6 @@ import kotlinx.serialization.Serializable
|
|||
@JsonClass(generateAdapter = true)
|
||||
data class VisaActivationInput(
|
||||
@Json(name = "cardId") val cardId: String,
|
||||
@Json(name = "cardPublicKey") val cardPublicKey: ByteArray,
|
||||
@Json(name = "cardPublicKey") val cardPublicKey: String,
|
||||
@Json(name = "isAccessCodeSet") val isAccessCodeSet: Boolean,
|
||||
) {
|
||||
override fun equals(other: Any?): Boolean {
|
||||
if (this === other) return true
|
||||
if (javaClass != other?.javaClass) return false
|
||||
|
||||
other as VisaActivationInput
|
||||
|
||||
if (cardId != other.cardId) return false
|
||||
if (!cardPublicKey.contentEquals(other.cardPublicKey)) return false
|
||||
if (isAccessCodeSet != other.isAccessCodeSet) return false
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
override fun hashCode(): Int {
|
||||
var result = cardId.hashCode()
|
||||
result = 31 * result + cardPublicKey.contentHashCode()
|
||||
result = 31 * result + isAccessCodeSet.hashCode()
|
||||
return result
|
||||
}
|
||||
}
|
||||
)
|
||||
|
|
@ -1,9 +1,51 @@
|
|||
package com.tangem.domain.visa.model
|
||||
|
||||
import com.squareup.moshi.*
|
||||
import kotlinx.serialization.Serializable
|
||||
|
||||
@Serializable
|
||||
enum class VisaActivationRemoteState {
|
||||
sealed class VisaActivationRemoteState {
|
||||
|
||||
@Serializable
|
||||
data class CardWalletSignatureRequired(
|
||||
val request: VisaCardWalletDataToSignRequest,
|
||||
) : VisaActivationRemoteState()
|
||||
|
||||
@Serializable
|
||||
data class CustomerWalletSignatureRequired(
|
||||
val request: VisaCardWalletDataToSignRequest,
|
||||
) : VisaActivationRemoteState()
|
||||
|
||||
@Serializable
|
||||
data object PaymentAccountDeploying : VisaActivationRemoteState()
|
||||
|
||||
@Serializable
|
||||
data object WaitingPinCode : VisaActivationRemoteState()
|
||||
|
||||
@Serializable
|
||||
data object WaitingForActivationFinishing : VisaActivationRemoteState()
|
||||
|
||||
@Serializable
|
||||
data object Activated : VisaActivationRemoteState()
|
||||
|
||||
@Serializable
|
||||
data object BlockedForActivation : VisaActivationRemoteState()
|
||||
|
||||
companion object {
|
||||
val jsonAdapter: VisaActivationRemoteState_JsonAdapter = VisaActivationRemoteState_JsonAdapter()
|
||||
}
|
||||
}
|
||||
|
||||
@Suppress("ClassNaming")
|
||||
class VisaActivationRemoteState_Json(
|
||||
@Json(name = "type") val type: VisaActivationRemoteState_Type,
|
||||
@Json(name = "request") val request: VisaCardWalletDataToSignRequest? = null,
|
||||
)
|
||||
|
||||
@Suppress("ClassNaming")
|
||||
// do not rename
|
||||
@JsonClass(generateAdapter = false)
|
||||
enum class VisaActivationRemoteState_Type {
|
||||
CardWalletSignatureRequired,
|
||||
CustomerWalletSignatureRequired,
|
||||
PaymentAccountDeploying,
|
||||
|
|
@ -11,4 +53,51 @@ enum class VisaActivationRemoteState {
|
|||
WaitingForActivationFinishing,
|
||||
Activated,
|
||||
BlockedForActivation,
|
||||
}
|
||||
|
||||
@Suppress("ClassNaming")
|
||||
class VisaActivationRemoteState_JsonAdapter {
|
||||
|
||||
@FromJson
|
||||
fun fromJson(value: VisaActivationRemoteState_Json): VisaActivationRemoteState {
|
||||
return when (value.type) {
|
||||
VisaActivationRemoteState_Type.CardWalletSignatureRequired ->
|
||||
VisaActivationRemoteState.CardWalletSignatureRequired(value.request!!)
|
||||
VisaActivationRemoteState_Type.CustomerWalletSignatureRequired ->
|
||||
VisaActivationRemoteState.CustomerWalletSignatureRequired(value.request!!)
|
||||
VisaActivationRemoteState_Type.PaymentAccountDeploying -> VisaActivationRemoteState.PaymentAccountDeploying
|
||||
VisaActivationRemoteState_Type.WaitingPinCode -> VisaActivationRemoteState.WaitingPinCode
|
||||
VisaActivationRemoteState_Type.WaitingForActivationFinishing ->
|
||||
VisaActivationRemoteState.WaitingForActivationFinishing
|
||||
VisaActivationRemoteState_Type.Activated -> VisaActivationRemoteState.Activated
|
||||
VisaActivationRemoteState_Type.BlockedForActivation -> VisaActivationRemoteState.BlockedForActivation
|
||||
}
|
||||
}
|
||||
|
||||
@ToJson
|
||||
fun toJson(value: VisaActivationRemoteState): VisaActivationRemoteState_Json {
|
||||
return when (value) {
|
||||
is VisaActivationRemoteState.CardWalletSignatureRequired ->
|
||||
VisaActivationRemoteState_Json(
|
||||
type = VisaActivationRemoteState_Type.CardWalletSignatureRequired,
|
||||
request = value.request,
|
||||
)
|
||||
is VisaActivationRemoteState.CustomerWalletSignatureRequired ->
|
||||
VisaActivationRemoteState_Json(
|
||||
type = VisaActivationRemoteState_Type.CustomerWalletSignatureRequired,
|
||||
request = value.request,
|
||||
)
|
||||
is VisaActivationRemoteState.PaymentAccountDeploying ->
|
||||
VisaActivationRemoteState_Json(VisaActivationRemoteState_Type.PaymentAccountDeploying)
|
||||
is VisaActivationRemoteState.WaitingPinCode ->
|
||||
VisaActivationRemoteState_Json(VisaActivationRemoteState_Type.WaitingPinCode)
|
||||
is VisaActivationRemoteState.WaitingForActivationFinishing ->
|
||||
VisaActivationRemoteState_Json(VisaActivationRemoteState_Type.WaitingForActivationFinishing)
|
||||
is VisaActivationRemoteState.Activated -> VisaActivationRemoteState_Json(
|
||||
VisaActivationRemoteState_Type.Activated,
|
||||
)
|
||||
is VisaActivationRemoteState.BlockedForActivation ->
|
||||
VisaActivationRemoteState_Json(VisaActivationRemoteState_Type.BlockedForActivation)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -14,4 +14,8 @@ data class VisaAuthTokens(
|
|||
@Serializable
|
||||
@JvmInline
|
||||
value class RefreshToken(val value: String)
|
||||
}
|
||||
|
||||
fun VisaAuthTokens.getAuthHeader(): String {
|
||||
return "Bearer $accessToken"
|
||||
}
|
||||
|
|
@ -1,7 +1,9 @@
|
|||
package com.tangem.domain.visa.model
|
||||
|
||||
import com.squareup.moshi.FromJson
|
||||
import com.squareup.moshi.Json
|
||||
import com.squareup.moshi.adapters.PolymorphicJsonAdapterFactory
|
||||
import com.squareup.moshi.JsonClass
|
||||
import com.squareup.moshi.ToJson
|
||||
import kotlinx.serialization.Serializable
|
||||
|
||||
@Serializable
|
||||
|
|
@ -9,19 +11,19 @@ sealed class VisaCardActivationStatus {
|
|||
|
||||
@Serializable
|
||||
data class Activated(
|
||||
@Json(name = "visaAuthTokens") val visaAuthTokens: VisaAuthTokens,
|
||||
val visaAuthTokens: VisaAuthTokens,
|
||||
) : VisaCardActivationStatus()
|
||||
|
||||
@Serializable
|
||||
data class ActivationStarted(
|
||||
@Json(name = "activationInput") val activationInput: VisaActivationInput,
|
||||
@Json(name = "authTokens") val authTokens: VisaAuthTokens,
|
||||
@Json(name = "remoteState") val remoteState: VisaActivationRemoteState,
|
||||
val activationInput: VisaActivationInput,
|
||||
val authTokens: VisaAuthTokens,
|
||||
val remoteState: VisaActivationRemoteState,
|
||||
) : VisaCardActivationStatus()
|
||||
|
||||
@Serializable
|
||||
data class NotStartedActivation(
|
||||
@Json(name = "activationInput") val activationInput: VisaActivationInput,
|
||||
val activationInput: VisaActivationInput,
|
||||
) : VisaCardActivationStatus()
|
||||
|
||||
@Serializable
|
||||
|
|
@ -31,11 +33,70 @@ sealed class VisaCardActivationStatus {
|
|||
data object RefreshTokenExpired : VisaCardActivationStatus()
|
||||
|
||||
companion object {
|
||||
val jsonAdapter: PolymorphicJsonAdapterFactory<VisaCardActivationStatus>
|
||||
get() = PolymorphicJsonAdapterFactory.of(VisaCardActivationStatus::class.java, "type")
|
||||
.withSubtype(Activated::class.java, "Activated")
|
||||
.withSubtype(ActivationStarted::class.java, "ActivationStarted")
|
||||
.withSubtype(NotStartedActivation::class.java, "NotStartedActivation")
|
||||
.withDefaultValue(Blocked)
|
||||
val jsonAdapter: VisaCardActivationStatus_JsonAdapter = VisaCardActivationStatus_JsonAdapter()
|
||||
}
|
||||
}
|
||||
|
||||
@Suppress("ClassNaming")
|
||||
class VisaCardActivationStatus_Json(
|
||||
@Json(name = "type") val type: VisaCardActivationStatus_Type,
|
||||
@Json(name = "activationInput") val activationInput: VisaActivationInput? = null,
|
||||
@Json(name = "authTokens") val authTokens: VisaAuthTokens? = null,
|
||||
@Json(name = "remoteState") val remoteState: VisaActivationRemoteState? = null,
|
||||
)
|
||||
|
||||
// do not rename instances
|
||||
@Suppress("ClassNaming")
|
||||
@JsonClass(generateAdapter = false)
|
||||
enum class VisaCardActivationStatus_Type {
|
||||
Activated,
|
||||
ActivationStarted,
|
||||
NotStartedActivation,
|
||||
Blocked,
|
||||
RefreshTokenExpired,
|
||||
}
|
||||
|
||||
@Suppress("ClassNaming")
|
||||
class VisaCardActivationStatus_JsonAdapter {
|
||||
|
||||
@FromJson
|
||||
fun fromJson(value: VisaCardActivationStatus_Json): VisaCardActivationStatus {
|
||||
return when (value.type) {
|
||||
VisaCardActivationStatus_Type.Activated -> VisaCardActivationStatus.Activated(value.authTokens!!)
|
||||
VisaCardActivationStatus_Type.ActivationStarted -> VisaCardActivationStatus.ActivationStarted(
|
||||
value.activationInput!!,
|
||||
value.authTokens!!,
|
||||
value.remoteState!!,
|
||||
)
|
||||
VisaCardActivationStatus_Type.NotStartedActivation -> VisaCardActivationStatus.NotStartedActivation(
|
||||
value.activationInput!!,
|
||||
)
|
||||
VisaCardActivationStatus_Type.Blocked -> VisaCardActivationStatus.Blocked
|
||||
VisaCardActivationStatus_Type.RefreshTokenExpired -> VisaCardActivationStatus.RefreshTokenExpired
|
||||
}
|
||||
}
|
||||
|
||||
@ToJson
|
||||
fun toJson(value: VisaCardActivationStatus): VisaCardActivationStatus_Json {
|
||||
return when (value) {
|
||||
is VisaCardActivationStatus.Activated -> VisaCardActivationStatus_Json(
|
||||
VisaCardActivationStatus_Type.Activated,
|
||||
authTokens = value.visaAuthTokens,
|
||||
)
|
||||
is VisaCardActivationStatus.ActivationStarted -> VisaCardActivationStatus_Json(
|
||||
VisaCardActivationStatus_Type.ActivationStarted,
|
||||
value.activationInput,
|
||||
value.authTokens,
|
||||
value.remoteState,
|
||||
)
|
||||
is VisaCardActivationStatus.NotStartedActivation -> VisaCardActivationStatus_Json(
|
||||
VisaCardActivationStatus_Type.NotStartedActivation,
|
||||
activationInput = value.activationInput,
|
||||
)
|
||||
is VisaCardActivationStatus.Blocked -> VisaCardActivationStatus_Json(VisaCardActivationStatus_Type.Blocked)
|
||||
is VisaCardActivationStatus.RefreshTokenExpired -> VisaCardActivationStatus_Json(
|
||||
VisaCardActivationStatus_Type.RefreshTokenExpired,
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,6 @@
|
|||
package com.tangem.domain.visa.model
|
||||
|
||||
data class VisaCardId(
|
||||
val cardId: String,
|
||||
val cardPublicKey: String,
|
||||
)
|
||||
|
|
@ -0,0 +1,13 @@
|
|||
package com.tangem.domain.visa.model
|
||||
|
||||
import com.squareup.moshi.Json
|
||||
import com.squareup.moshi.JsonClass
|
||||
import kotlinx.serialization.Serializable
|
||||
|
||||
@Serializable
|
||||
@JsonClass(generateAdapter = true)
|
||||
data class VisaCardWalletDataToSignRequest(
|
||||
@Json(name = "orderId") val orderId: String,
|
||||
@Json(name = "customer_id") val customerId: String,
|
||||
@Json(name = "customer_wallet_address") val customerWalletAddress: String,
|
||||
)
|
||||
|
|
@ -0,0 +1,12 @@
|
|||
package com.tangem.domain.visa.model
|
||||
|
||||
import com.squareup.moshi.Json
|
||||
import com.squareup.moshi.JsonClass
|
||||
import kotlinx.serialization.Serializable
|
||||
|
||||
@Serializable
|
||||
@JsonClass(generateAdapter = true)
|
||||
data class VisaCustomerWalletDataToSignRequest(
|
||||
@Json(name = "orderId") val orderId: String,
|
||||
@Json(name = "card_wallet_address") val cardWalletAddress: String,
|
||||
)
|
||||
|
|
@ -1,11 +1,10 @@
|
|||
package com.tangem.domain.visa.model
|
||||
|
||||
import kotlinx.serialization.SerialName
|
||||
import kotlinx.serialization.Serializable
|
||||
|
||||
@Serializable
|
||||
data class VisaDataForApprove(
|
||||
@SerialName("customerWalletCardId") val customerWalletCardId: String?,
|
||||
@SerialName("targetAddress") val targetAddress: String,
|
||||
@SerialName("approveHash") val approveHash: String,
|
||||
val customerWalletCardId: String?,
|
||||
val targetAddress: String,
|
||||
val dataToSign: VisaDataToSignByCustomerWallet,
|
||||
)
|
||||
|
|
@ -0,0 +1,15 @@
|
|||
package com.tangem.domain.visa.model
|
||||
|
||||
data class VisaDataToSignByCardWallet(
|
||||
val request: VisaCardWalletDataToSignRequest,
|
||||
val hashToSign: String,
|
||||
)
|
||||
|
||||
fun VisaDataToSignByCardWallet.sign(cardWalletAddress: String, rootOTP: String, otpCounter: Int, signature: String) =
|
||||
VisaSignedActivationDataByCardWallet(
|
||||
dataToSign = this,
|
||||
cardWalletAddress = cardWalletAddress,
|
||||
rootOTP = rootOTP,
|
||||
otpCounter = otpCounter,
|
||||
signature = signature,
|
||||
)
|
||||
|
|
@ -0,0 +1,16 @@
|
|||
package com.tangem.domain.visa.model
|
||||
|
||||
import kotlinx.serialization.Serializable
|
||||
|
||||
@Serializable
|
||||
data class VisaDataToSignByCustomerWallet(
|
||||
val request: VisaCustomerWalletDataToSignRequest,
|
||||
val hashToSign: String,
|
||||
)
|
||||
|
||||
fun VisaDataToSignByCustomerWallet.sign(signature: String, customerWalletAddress: String) =
|
||||
VisaSignedDataByCustomerWallet(
|
||||
dataToSign = this,
|
||||
customerWalletAddress = customerWalletAddress,
|
||||
signature = signature,
|
||||
)
|
||||
|
|
@ -1,4 +0,0 @@
|
|||
package com.tangem.domain.visa.model
|
||||
|
||||
@JvmInline
|
||||
value class VisaRootOTP(val value: String)
|
||||
|
|
@ -0,0 +1,9 @@
|
|||
package com.tangem.domain.visa.model
|
||||
|
||||
class VisaSignedActivationDataByCardWallet(
|
||||
val dataToSign: VisaDataToSignByCardWallet,
|
||||
val cardWalletAddress: String,
|
||||
val rootOTP: String,
|
||||
val otpCounter: Int,
|
||||
val signature: String,
|
||||
)
|
||||
|
|
@ -0,0 +1,7 @@
|
|||
package com.tangem.domain.visa.model
|
||||
|
||||
data class VisaSignedDataByCustomerWallet(
|
||||
val dataToSign: VisaDataToSignByCustomerWallet,
|
||||
val customerWalletAddress: String,
|
||||
val signature: String,
|
||||
)
|
||||
|
|
@ -1,7 +1,6 @@
|
|||
package com.tangem.domain.visa.repository
|
||||
|
||||
import com.tangem.domain.visa.model.ActivationOrder
|
||||
import com.tangem.domain.visa.model.VisaActivationRemoteState
|
||||
import com.tangem.domain.visa.model.*
|
||||
|
||||
interface VisaActivationRepository {
|
||||
|
||||
|
|
@ -9,9 +8,17 @@ interface VisaActivationRepository {
|
|||
|
||||
suspend fun getActivationRemoteStateLongPoll(): VisaActivationRemoteState
|
||||
|
||||
suspend fun getActivationOrderToSign(): ActivationOrder
|
||||
suspend fun getCardWalletAcceptanceData(request: VisaCardWalletDataToSignRequest): VisaDataToSignByCardWallet
|
||||
|
||||
suspend fun getCustomerWalletAcceptanceData(
|
||||
request: VisaCustomerWalletDataToSignRequest,
|
||||
): VisaDataToSignByCustomerWallet
|
||||
|
||||
suspend fun activateCard(signedData: VisaSignedActivationDataByCardWallet)
|
||||
|
||||
suspend fun approveByCustomerWallet(signedData: VisaSignedDataByCustomerWallet)
|
||||
|
||||
interface Factory {
|
||||
fun create(cardId: String): VisaActivationRepository
|
||||
fun create(cardId: VisaCardId): VisaActivationRepository
|
||||
}
|
||||
}
|
||||
|
|
@ -8,7 +8,7 @@ interface VisaAuthRepository {
|
|||
|
||||
suspend fun getCardAuthChallenge(cardId: String, cardPublicKey: String): VisaAuthChallenge.Card
|
||||
|
||||
suspend fun getCustomerWalletAuthChallenge(cardId: String, walletPublicKey: String): VisaAuthChallenge.Wallet
|
||||
suspend fun getCardWalletAuthChallenge(cardWalletAddress: String): VisaAuthChallenge.Wallet
|
||||
|
||||
suspend fun getAccessTokens(signedChallenge: VisaAuthSignedChallenge): VisaAuthTokens
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue