Updated on 2026-08-14
This commit is contained in:
parent
7e3841c4ef
commit
698575606f
3 changed files with 94 additions and 96 deletions
|
|
@ -3,7 +3,11 @@ package com.tangem
|
|||
import com.tangem.commands.CommandResponse
|
||||
import com.tangem.commands.CommandSerializer
|
||||
import com.tangem.commands.SignCommandData
|
||||
import com.tangem.tasks.*
|
||||
import com.tangem.crypto.initCrypto
|
||||
import com.tangem.tasks.ScanEvent
|
||||
import com.tangem.tasks.ScanTask
|
||||
import com.tangem.tasks.Task
|
||||
import com.tangem.tasks.TaskResult
|
||||
|
||||
class CardManager(
|
||||
private val reader: CardReader,
|
||||
|
|
@ -12,30 +16,30 @@ class CardManager(
|
|||
|
||||
private val cardEnvironmentRepository = CardEnvironmentRepository(dataStorage)
|
||||
|
||||
fun scanCard(callback: (result: TaskResult) -> Unit) {
|
||||
init {
|
||||
initCrypto()
|
||||
}
|
||||
|
||||
fun scanCard(callback: (result: ScanEvent, cardEnvironment: CardEnvironment) -> Unit) {
|
||||
val task = ScanTask(cardManagerDelegate, reader)
|
||||
runTask(task, cardEnvironmentRepository.cardEnvironment, callback)
|
||||
}
|
||||
|
||||
fun sign(signCommandData: SignCommandData,
|
||||
callback: (result: TaskResult) -> Unit) {
|
||||
val task = SignTask(signCommandData, cardManagerDelegate, reader)
|
||||
runTask(task, cardEnvironmentRepository.cardEnvironment, callback)
|
||||
// val task = SignTask<SignEvent>(signCommandData, cardManagerDelegate, reader)
|
||||
// runTask(task, cardEnvironmentRepository.cardEnvironment, callback)
|
||||
}
|
||||
|
||||
fun runTask(task: Task, environment: CardEnvironment? = null,
|
||||
callback: (result: TaskResult) -> Unit) {
|
||||
task.run(environment ?: cardEnvironmentRepository.cardEnvironment) {result, returnedEnvironment ->
|
||||
//TODO: environment is kept in Repository
|
||||
cardEnvironmentRepository.cardEnvironment = returnedEnvironment
|
||||
callback.invoke(result)
|
||||
}
|
||||
fun <TaskEvent>runTask(task: Task<TaskEvent>, environment: CardEnvironment? = null,
|
||||
callback: (result: TaskEvent, cardEnvironment: CardEnvironment) -> Unit) {
|
||||
task.run(environment ?: cardEnvironmentRepository.cardEnvironment, callback)
|
||||
}
|
||||
|
||||
fun runCommand(commandSerializer: CommandSerializer<CommandResponse>,
|
||||
environment: CardEnvironment? = null,
|
||||
callback: (result: TaskResult) -> Unit) {
|
||||
val task = BasicTask<CommandResponse>(commandSerializer, cardManagerDelegate, reader)
|
||||
runTask(task, environment, callback)
|
||||
// val task = BasicTask<CommandResponse>(commandSerializer, cardManagerDelegate, reader)
|
||||
// runTask(task, environment, callback)
|
||||
}
|
||||
}
|
||||
|
|
@ -10,20 +10,12 @@ import com.tangem.crypto.verify
|
|||
sealed class ScanEvent {
|
||||
data class OnReadEvent(val result: ReadCardResponse) : ScanEvent()
|
||||
data class OnVerifyEvent(val verified: Boolean) : ScanEvent()
|
||||
class OnUserCancelledEvent() : ScanEvent()
|
||||
object OnUserCancelledEvent : ScanEvent()
|
||||
data class Failure(val error: TaskError) : ScanEvent()
|
||||
data class Succcess(val result: Any) : ScanEvent()
|
||||
}
|
||||
|
||||
//
|
||||
//sealed class ScanResult {
|
||||
// data class ReadResult(val card: Card) : ScanResult()
|
||||
// data class VerifyResult(val verified: Boolean) : ScanResult()
|
||||
// data class Failure(val error: TaskError) : ScanResult()
|
||||
//}
|
||||
|
||||
|
||||
class ScanTask<out: ScanEvent>(delegate: CardManagerDelegate? = null, reader: CardReader) : Task<ScanEvent>(delegate, reader) {
|
||||
class ScanTask(delegate: CardManagerDelegate? = null, reader: CardReader) : Task<ScanEvent>(delegate, reader) {
|
||||
|
||||
private lateinit var readCardData: ReadCardResponse
|
||||
private lateinit var challenge: ByteArray
|
||||
|
|
@ -34,42 +26,52 @@ class ScanTask<out: ScanEvent>(delegate: CardManagerDelegate? = null, reader: Ca
|
|||
callback: (result: ScanEvent, cardEnvironment: CardEnvironment) -> Unit) {
|
||||
|
||||
val readCommand = ReadCardCommand(cardEnvironment.pin1)
|
||||
sendCommand(readCommand, cardEnvironment) {
|
||||
sendCommand(readCommand, cardEnvironment) { readCommandEvent ->
|
||||
|
||||
if (it is CommandEvent.Success) {
|
||||
readCardData = it.response as ReadCardResponse
|
||||
when (readCommandEvent) {
|
||||
is CommandEvent.Success -> {
|
||||
readCardData = readCommandEvent.response as ReadCardResponse
|
||||
|
||||
callback(ScanEvent.OnReadEvent(readCardData), cardEnvironment)
|
||||
callback(ScanEvent.OnReadEvent(readCardData), cardEnvironment)
|
||||
|
||||
if (readCardData.curve != null && readCardData.walletPublicKey != null) {
|
||||
curve = readCardData.curve!!
|
||||
walletPublickKey = readCardData.walletPublicKey!!
|
||||
} else {
|
||||
callback(ScanEvent.Failure(TaskError.CardError()), cardEnvironment)
|
||||
}
|
||||
|
||||
val checkWalletCommand = prepareCheckWalletCommand(cardEnvironment)
|
||||
|
||||
sendCommand(checkWalletCommand, cardEnvironment) { checkWalletResult ->
|
||||
delegate?.closeNfcPopup()
|
||||
|
||||
if (checkWalletResult is CommandEvent.Success) {
|
||||
val checkWalletResponse = checkWalletResult.response as CheckWalletResponse
|
||||
val verified = verify(walletPublickKey,
|
||||
challenge + checkWalletResponse.salt,
|
||||
checkWalletResponse.walletSignature,
|
||||
curve)
|
||||
if (verified) {
|
||||
callback(ScanEvent.OnVerifyEvent(true), cardEnvironment)
|
||||
} else {
|
||||
callback(ScanEvent.Failure(TaskError.VefificationFailed()), cardEnvironment)
|
||||
}
|
||||
if (readCardData.curve != null && readCardData.walletPublicKey != null) {
|
||||
curve = readCardData.curve!!
|
||||
walletPublickKey = readCardData.walletPublicKey!!
|
||||
} else {
|
||||
delegate?.closeNfcPopup()
|
||||
callback(ScanEvent.Failure(TaskError.CardError()), cardEnvironment)
|
||||
}
|
||||
|
||||
val checkWalletCommand = prepareCheckWalletCommand(cardEnvironment)
|
||||
|
||||
sendCommand(checkWalletCommand, cardEnvironment) { checkWalletEvent ->
|
||||
delegate?.closeNfcPopup()
|
||||
|
||||
when (checkWalletEvent) {
|
||||
is CommandEvent.Success -> {
|
||||
val checkWalletResponse = checkWalletEvent.response as CheckWalletResponse
|
||||
val verified = verify(walletPublickKey,
|
||||
challenge + checkWalletResponse.salt,
|
||||
checkWalletResponse.walletSignature,
|
||||
curve)
|
||||
if (verified) {
|
||||
callback(ScanEvent.OnVerifyEvent(true), cardEnvironment)
|
||||
} else {
|
||||
callback(ScanEvent.Failure(TaskError.VefificationFailed()), cardEnvironment)
|
||||
}
|
||||
}
|
||||
is CommandEvent.Failure ->
|
||||
callback(ScanEvent.Failure(checkWalletEvent.taskError), cardEnvironment)
|
||||
is CommandEvent.UserCancellation ->
|
||||
callback(ScanEvent.OnUserCancelledEvent, cardEnvironment)
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
} else {
|
||||
//TODO: Handle error
|
||||
is CommandEvent.Failure ->
|
||||
callback(ScanEvent.Failure(readCommandEvent.taskError), cardEnvironment)
|
||||
is CommandEvent.UserCancellation ->
|
||||
callback(ScanEvent.OnUserCancelledEvent, cardEnvironment)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -21,8 +21,8 @@ abstract class Task<T>(protected val delegate: CardManagerDelegate? = null, priv
|
|||
abstract fun onRun(cardEnvironment: CardEnvironment,
|
||||
callback: (result: T, cardEnvironment: CardEnvironment) -> Unit)
|
||||
|
||||
protected fun <T: CommandResponse>sendCommand(commandSerializer: CommandSerializer<T>, cardEnvironment: CardEnvironment,
|
||||
callback: (result: CommandEvent) -> Unit) {
|
||||
protected fun <T : CommandResponse> sendCommand(commandSerializer: CommandSerializer<T>, cardEnvironment: CardEnvironment,
|
||||
callback: (result: CommandEvent) -> Unit) {
|
||||
|
||||
reader.sendApdu(
|
||||
commandSerializer.serialize(cardEnvironment).toBytes()) { responseApdu ->
|
||||
|
|
@ -30,34 +30,21 @@ abstract class Task<T>(protected val delegate: CardManagerDelegate? = null, priv
|
|||
when (responseApdu.status) {
|
||||
Status.ProcessCompleted, Status.Pin1Changed, Status.Pin2Changed, Status.PinsChanged
|
||||
-> {
|
||||
val responseData = commandSerializer.deserialize(cardEnvironment, responseApdu)
|
||||
|
||||
if (responseData == null) {
|
||||
|
||||
} else {
|
||||
callback(
|
||||
CommandEvent.Success(responseData)
|
||||
)
|
||||
try {
|
||||
val responseData = commandSerializer.deserialize(cardEnvironment, responseApdu)
|
||||
callback(CommandEvent.Success(responseData as T))
|
||||
} catch (error: TaskError) {
|
||||
callback(CommandEvent.Failure(error))
|
||||
}
|
||||
|
||||
}
|
||||
Status.InvalidParams -> TODO()
|
||||
Status.ErrorProcessingCommand -> TODO()
|
||||
Status.InvalidState -> TODO()
|
||||
Status.InvalidParams -> callback(CommandEvent.Failure(TaskError.InvalidParams()))
|
||||
Status.ErrorProcessingCommand -> callback(CommandEvent.Failure(TaskError.ErrorProcessingCommand()))
|
||||
Status.InvalidState -> callback(CommandEvent.Failure(TaskError.InvalidState()))
|
||||
|
||||
Status.InsNotSupported -> TODO()
|
||||
Status.NeedEnctryption -> TODO()
|
||||
Status.NeedPause -> TODO()
|
||||
Status.InsNotSupported -> callback(CommandEvent.Failure(TaskError.InsNotSupported()))
|
||||
Status.NeedEncryption -> callback(CommandEvent.Failure(TaskError.NeedEncryption()))
|
||||
Status.NeedPause -> callback(CommandEvent.Failure(TaskError.NeedPause()))
|
||||
}
|
||||
|
||||
// val parsedApdu = responseApdu.getTlvData()
|
||||
// if (parsedApdu == null) callback.invoke(TaskResult.Error(CardError()))
|
||||
// else if (!parsedApdu.statusCompleted()) {
|
||||
// callback.invoke(TaskResult.Error(CardError(parsedApdu.status.code)))
|
||||
// } else {
|
||||
// val response = commandSerializer.deserialize(parsedApdu)
|
||||
// callback.invoke(response)
|
||||
// }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -65,12 +52,18 @@ abstract class Task<T>(protected val delegate: CardManagerDelegate? = null, priv
|
|||
sealed class TaskError : Exception() {
|
||||
class UnknownStatus(sw: Int) : TaskError()
|
||||
class MappingError : TaskError()
|
||||
|
||||
class ErrorProcessingCommand : TaskError()
|
||||
class InvalidState : TaskError()
|
||||
class InsNotSupported : TaskError()
|
||||
class InvalidParams : TaskError()
|
||||
class NeedEncryption : TaskError()
|
||||
class NeedPause : TaskError()
|
||||
|
||||
class VefificationFailed : TaskError()
|
||||
class CardError : TaskError()
|
||||
class ReaderError() : TaskError()
|
||||
class SerializeCommandError() : TaskError()
|
||||
}
|
||||
|
||||
sealed class TaskResult {
|
||||
|
|
@ -80,23 +73,22 @@ sealed class TaskResult {
|
|||
}
|
||||
|
||||
|
||||
|
||||
class BasicTask<T: CommandResponse>(
|
||||
private val commandSerializer: CommandSerializer<CommandResponse>,
|
||||
delegate: CardManagerDelegate? = null,
|
||||
reader: CardReader) : Task(delegate, reader) {
|
||||
|
||||
override fun onRun(cardEnvironment: CardEnvironment,
|
||||
callback: (result: TaskResult, cardEnvironment: CardEnvironment) -> Unit) {
|
||||
sendCommand(commandSerializer, cardEnvironment) {
|
||||
callback.invoke(it, updateEnvironment())
|
||||
}
|
||||
}
|
||||
|
||||
private fun updateEnvironment(): CardEnvironment {
|
||||
//TODO: set logic of changing CardEnvironment when needed
|
||||
return CardEnvironment()
|
||||
}
|
||||
}
|
||||
//class BasicTask<T: CommandResponse>(
|
||||
// private val commandSerializer: CommandSerializer<CommandResponse>,
|
||||
// delegate: CardManagerDelegate? = null,
|
||||
// reader: CardReader) : Task(delegate, reader) {
|
||||
//
|
||||
// override fun onRun(cardEnvironment: CardEnvironment,
|
||||
// callback: (result: TaskResult, cardEnvironment: CardEnvironment) -> Unit) {
|
||||
// sendCommand(commandSerializer, cardEnvironment) {
|
||||
// callback.invoke(it, updateEnvironment())
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// private fun updateEnvironment(): CardEnvironment {
|
||||
// //TODO: set logic of changing CardEnvironment when needed
|
||||
// return CardEnvironment()
|
||||
// }
|
||||
//}
|
||||
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue