From 336ec4a1edb9bb6ec5d59fe8b9c0cdfc1daf2db2 Mon Sep 17 00:00:00 2001 From: Tangem Date: Fri, 3 Jul 2020 16:21:33 +0300 Subject: [PATCH] Updated on 2026-08-14 --- .../src/main/java/com/tangem/CardSession.kt | 16 +++++----- .../java/com/tangem/SessionEnvironment.kt | 29 +++++++++++++------ .../java/com/tangem/SessionViewDelegate.kt | 2 +- .../src/main/java/com/tangem/TangemSdk.kt | 22 +++++--------- .../main/java/com/tangem/commands/Command.kt | 3 +- ...dValuesService.kt => CardValuesStorage.kt} | 4 +-- .../ChangePinTask.kt} | 25 +++++++++++++--- .../java/com/tangem/tasks/CreateWalletTask.kt | 1 + .../main/java/com/tangem/tasks/ScanTask.kt | 3 +- .../DefaultSessionViewDelegate.kt | 2 +- 10 files changed, 65 insertions(+), 42 deletions(-) rename tangem-core/src/main/java/com/tangem/common/{CardValuesService.kt => CardValuesStorage.kt} (93%) rename tangem-core/src/main/java/com/tangem/{commands/ChangePinCommand.kt => tasks/ChangePinTask.kt} (77%) diff --git a/tangem-core/src/main/java/com/tangem/CardSession.kt b/tangem-core/src/main/java/com/tangem/CardSession.kt index 8c67cffd39..a55d4757d2 100644 --- a/tangem-core/src/main/java/com/tangem/CardSession.kt +++ b/tangem-core/src/main/java/com/tangem/CardSession.kt @@ -1,6 +1,8 @@ package com.tangem -import com.tangem.commands.* +import com.tangem.commands.CommandResponse +import com.tangem.commands.OpenSessionCommand +import com.tangem.commands.ReadCommand import com.tangem.common.CompletionResult import com.tangem.common.PinCode import com.tangem.common.apdu.CommandApdu @@ -9,6 +11,7 @@ import com.tangem.common.extensions.calculateSha256 import com.tangem.common.extensions.getType import com.tangem.crypto.EncryptionHelper import com.tangem.crypto.pbkdf2Hash +import com.tangem.tasks.PinType import kotlinx.coroutines.* import kotlinx.coroutines.flow.* @@ -19,6 +22,8 @@ interface CardSessionRunnable { val performPreflightRead: Boolean + val requiresPin2: Boolean + /** * The starting point for custom business logic. * Implement this interface and use [TangemSdk.startSessionWithRunnable] to run. @@ -28,10 +33,6 @@ interface CardSessionRunnable { fun run(session: CardSession, callback: (result: CompletionResult) -> Unit) } -interface CardSessionStoppedListener { - fun onSessionStopped(environment: SessionEnvironment) -} - enum class CardSessionState { Inactive, Active @@ -64,7 +65,6 @@ class CardSession( ) { var connectedTag: TagType? = null - var sessionStoppedListener: CardSessionStoppedListener? = null /** * True if some operation is still in progress. @@ -96,7 +96,7 @@ class CardSession( return } - if ((runnable as? Command)?.requiresPin2 == true && environment.pin2 == null) { + if (runnable.requiresPin2 && environment.pin2 == null) { viewDelegate.onSessionStarted(cardId) viewDelegate.onPinRequested(PinType.Pin2) { environment.pin2 = PinCode(it) @@ -231,7 +231,7 @@ class CardSession( } private fun stopSession() { - sessionStoppedListener?.onSessionStopped(environment) + environment.saveCardValues() reader.stopSession() state = CardSessionState.Inactive scope.cancel() diff --git a/tangem-core/src/main/java/com/tangem/SessionEnvironment.kt b/tangem-core/src/main/java/com/tangem/SessionEnvironment.kt index 322d25f057..295995337e 100644 --- a/tangem-core/src/main/java/com/tangem/SessionEnvironment.kt +++ b/tangem-core/src/main/java/com/tangem/SessionEnvironment.kt @@ -2,7 +2,7 @@ package com.tangem import com.tangem.commands.Card import com.tangem.commands.EllipticCurve -import com.tangem.common.CardValuesService +import com.tangem.common.CardValuesStorage import com.tangem.common.PinCode import com.tangem.common.TerminalKeysService import com.tangem.crypto.CryptoUtils.generatePublicKey @@ -12,14 +12,25 @@ import com.tangem.crypto.CryptoUtils.generatePublicKey * Contains data relating to a Tangem card. It is used in constructing all the commands, * and commands can return modified [SessionEnvironment]. * - * @property card Current card, read by preflight [com.tangem.commands.ReadCommand]. - * @property terminalKeys generated terminal keys used in Linked Terminal feature. + * @param cardId Card ID, if it is known before tapping the card. + * @property config sets a number of parameters for communication with Tangem cards. + * @param terminalKeysService is used to retrieve terminal keys used in Linked Terminal feature. + * @param cardValuesStorage is used to save and retrieve some values relating to a particular card. + * + * @property pin1 An access Code, required to get access to a card. A default value is set in [Config] + * @property pin2 A code, required to perform particular operations with a card. A default value is set in [Config] + * @property terminalKeys generated terminal keys used in Linked Terminal feature + * @property cardFilter a property that defines types of card that this SDK will be able to interact with + * @property handleErrors if true, the SDK parses internal card errors into concrete [TangemSdkError] + * @property encryptionMode preferred [EncryptionMode] for interaction with cards + * @property encryptionKey is used for encrypted communication with a card + * */ class SessionEnvironment( cardId: String?, private val config: Config, - private val terminalKeysService: TerminalKeysService?, - private val cardValuesService: CardValuesService? + terminalKeysService: TerminalKeysService?, + private val cardValuesStorage: CardValuesStorage? ) { var pin1: PinCode? @@ -46,7 +57,7 @@ class SessionEnvironment( encryptionMode = config.encryptionMode - val cardValues = cardId?.let { cardValuesService?.getValues(cardId) } + val cardValues = cardId?.let { cardValuesStorage?.getValues(cardId) } cardVerification = cardValues?.cardVerification ?: VerificationState.NotVerified cardValidation = cardValues?.cardValidation ?: VerificationState.NotVerified @@ -68,7 +79,7 @@ class SessionEnvironment( } fun restoreCardValues() { - val cardValues = this.card?.cardId?.let { cardValuesService?.getValues(it) } + val cardValues = this.card?.cardId?.let { cardValuesStorage?.getValues(it) } cardVerification = cardValues?.cardVerification ?: VerificationState.NotVerified cardValidation = cardValues?.cardValidation ?: VerificationState.NotVerified codeVerification = cardValues?.codeVerification ?: VerificationState.NotVerified @@ -85,7 +96,7 @@ class SessionEnvironment( card?.cardId?.let { cardId -> TangemSdk.pin2[cardId] = pin2 } } - cardValuesService?.saveValues(this) + cardValuesStorage?.saveValues(this) } } @@ -106,5 +117,5 @@ class KeyPair(val publicKey: ByteArray, val privateKey: ByteArray) { } enum class VerificationState { - Passed, Offline, Failed, NotVerified + Passed, Offline, Failed, NotVerified, Cancelled } \ No newline at end of file diff --git a/tangem-core/src/main/java/com/tangem/SessionViewDelegate.kt b/tangem-core/src/main/java/com/tangem/SessionViewDelegate.kt index 3405c7c676..a62716454b 100644 --- a/tangem-core/src/main/java/com/tangem/SessionViewDelegate.kt +++ b/tangem-core/src/main/java/com/tangem/SessionViewDelegate.kt @@ -1,6 +1,6 @@ package com.tangem -import com.tangem.commands.PinType +import com.tangem.tasks.PinType /** * Allows interaction with users and shows visual elements. diff --git a/tangem-core/src/main/java/com/tangem/TangemSdk.kt b/tangem-core/src/main/java/com/tangem/TangemSdk.kt index 266301b737..834933b1c2 100644 --- a/tangem-core/src/main/java/com/tangem/TangemSdk.kt +++ b/tangem-core/src/main/java/com/tangem/TangemSdk.kt @@ -11,12 +11,14 @@ import com.tangem.commands.personalization.entities.Issuer import com.tangem.commands.personalization.entities.Manufacturer import com.tangem.commands.verifycard.VerifyCardCommand import com.tangem.commands.verifycard.VerifyCardResponse -import com.tangem.common.CardValuesDbService +import com.tangem.common.CardValuesDbStorage import com.tangem.common.CompletionResult import com.tangem.common.PinCode import com.tangem.common.TerminalKeysService import com.tangem.crypto.CryptoUtils +import com.tangem.tasks.ChangePinTask import com.tangem.tasks.CreateWalletTask +import com.tangem.tasks.PinType import com.tangem.tasks.ScanTask /** @@ -369,7 +371,7 @@ class TangemSdk( pin: ByteArray? = null, initialMessage: Message? = null, callback: (result: CompletionResult) -> Unit) { - val command = ChangePinCommand(PinType.Pin1, pin) + val command = ChangePinTask(PinType.Pin1, pin) startSessionWithRunnable(command, cardId, initialMessage, callback) } @@ -377,7 +379,7 @@ class TangemSdk( pin: ByteArray? = null, initialMessage: Message? = null, callback: (result: CompletionResult) -> Unit) { - val command = ChangePinCommand(PinType.Pin2, pin) + val command = ChangePinTask(PinType.Pin2, pin) startSessionWithRunnable(command, cardId, initialMessage, callback) } @@ -385,7 +387,7 @@ class TangemSdk( pin: ByteArray? = null, initialMessage: Message? = null, callback: (result: CompletionResult) -> Unit) { - val command = ChangePinCommand(PinType.Pin3, pin) + val command = ChangePinTask(PinType.Pin3, pin) startSessionWithRunnable(command, cardId, initialMessage, callback) } @@ -407,18 +409,9 @@ class TangemSdk( runnable: CardSessionRunnable, cardId: String? = null, initialMessage: Message? = null, callback: (result: CompletionResult) -> Unit) { val cardSession = CardSession(buildEnvironment(cardId), reader, viewDelegate, cardId, initialMessage) - addSessionStoppedListener(cardSession) Thread().run { cardSession.startWithRunnable(runnable, callback) } } - private fun addSessionStoppedListener(session: CardSession) { - session.sessionStoppedListener = object : CardSessionStoppedListener { - override fun onSessionStopped(environment: SessionEnvironment) { - environment.saveCardValues() - } - } - } - /** * Allows running a custom bunch of commands in one [CardSession] with lightweight closure syntax. * Tangem SDK will start a card session and perform preflight [ReadCommand]. @@ -434,7 +427,6 @@ class TangemSdk( fun startSession(cardId: String? = null, initialMessage: Message? = null, callback: (session: CardSession, error: TangemSdkError?) -> Unit) { val cardSession = CardSession(buildEnvironment(cardId), reader, viewDelegate, cardId, initialMessage) - addSessionStoppedListener(cardSession) Thread().run { cardSession.start(callback = callback) } } @@ -448,7 +440,7 @@ class TangemSdk( private fun buildEnvironment(cardId: String?): SessionEnvironment { return SessionEnvironment( - cardId, config, terminalKeysService, CardValuesDbService(sqlDriver) + cardId, config, terminalKeysService, CardValuesDbStorage(sqlDriver) ) } diff --git a/tangem-core/src/main/java/com/tangem/commands/Command.kt b/tangem-core/src/main/java/com/tangem/commands/Command.kt index 27abf365a7..c5b5925cc8 100644 --- a/tangem-core/src/main/java/com/tangem/commands/Command.kt +++ b/tangem-core/src/main/java/com/tangem/commands/Command.kt @@ -6,6 +6,7 @@ import com.tangem.common.PinCode import com.tangem.common.apdu.* import com.tangem.common.extensions.toInt import com.tangem.common.tlv.TlvTag +import com.tangem.tasks.PinType interface ApduSerializable { @@ -39,7 +40,7 @@ interface CommandResponse abstract class Command : ApduSerializable, CardSessionRunnable { override val performPreflightRead: Boolean = true - open val requiresPin2: Boolean = false + override val requiresPin2: Boolean = false override fun run(session: CardSession, callback: (result: CompletionResult) -> Unit) { Log.i("Command", "Initializing ${this::class.java.simpleName}") diff --git a/tangem-core/src/main/java/com/tangem/common/CardValuesService.kt b/tangem-core/src/main/java/com/tangem/common/CardValuesStorage.kt similarity index 93% rename from tangem-core/src/main/java/com/tangem/common/CardValuesService.kt rename to tangem-core/src/main/java/com/tangem/common/CardValuesStorage.kt index 80e26859e4..7976bab5aa 100644 --- a/tangem-core/src/main/java/com/tangem/common/CardValuesService.kt +++ b/tangem-core/src/main/java/com/tangem/common/CardValuesStorage.kt @@ -7,7 +7,7 @@ import com.tangem.CardValuesEntityQueries import com.tangem.Database import com.tangem.SessionEnvironment -interface CardValuesService { +interface CardValuesStorage { fun saveValues(environment: SessionEnvironment) @@ -15,7 +15,7 @@ interface CardValuesService { } -class CardValuesDbService(driver: SqlDriver) : CardValuesService { +class CardValuesDbStorage(driver: SqlDriver) : CardValuesStorage { private val cardValuesQueries: CardValuesEntityQueries diff --git a/tangem-core/src/main/java/com/tangem/commands/ChangePinCommand.kt b/tangem-core/src/main/java/com/tangem/tasks/ChangePinTask.kt similarity index 77% rename from tangem-core/src/main/java/com/tangem/commands/ChangePinCommand.kt rename to tangem-core/src/main/java/com/tangem/tasks/ChangePinTask.kt index 641fb6e3d2..4a8519d548 100644 --- a/tangem-core/src/main/java/com/tangem/commands/ChangePinCommand.kt +++ b/tangem-core/src/main/java/com/tangem/tasks/ChangePinTask.kt @@ -1,8 +1,11 @@ -package com.tangem.commands +package com.tangem.tasks import com.tangem.CardSession import com.tangem.CardSessionRunnable +import com.tangem.SessionEnvironment import com.tangem.SessionViewDelegate +import com.tangem.commands.SetPinCommand +import com.tangem.commands.SetPinResponse import com.tangem.common.CompletionResult import com.tangem.common.PinCode import com.tangem.common.extensions.calculateSha256 @@ -17,15 +20,16 @@ enum class PinType { ; } -class ChangePinCommand( +class ChangePinTask( private val pinType: PinType, private val pin: ByteArray? = null ) : CardSessionRunnable { override val performPreflightRead = true + override val requiresPin2 = false override fun run(session: CardSession, callback: (result: CompletionResult) -> Unit) { session.scope.launch { - val pin = this@ChangePinCommand.pin + val pin = this@ChangePinTask.pin ?: requestNewPin(pinType, session.viewDelegate).calculateSha256() runSetPin(pin, session, callback) } @@ -61,7 +65,12 @@ class ChangePinCommand( } } val command = SetPinCommand(pin1, pin2, pin3) - command.run(session, callback) + command.run(session) { result -> + when (result) { + is CompletionResult.Success -> savePin(pin, session.environment) + is CompletionResult.Failure -> callback(result) + } + } } private suspend fun requestPin(pinType: PinType, viewDelegate: SessionViewDelegate): String = @@ -78,5 +87,13 @@ class ChangePinCommand( } } + private fun savePin(pin: ByteArray, environment: SessionEnvironment) { + when (pinType) { + PinType.Pin1 -> environment.pin1 = PinCode(pin, false) + PinType.Pin2 -> environment.pin2 = PinCode(pin, false) + PinType.Pin3 -> {} + } + } + } \ No newline at end of file diff --git a/tangem-core/src/main/java/com/tangem/tasks/CreateWalletTask.kt b/tangem-core/src/main/java/com/tangem/tasks/CreateWalletTask.kt index 317134af60..126ca73514 100644 --- a/tangem-core/src/main/java/com/tangem/tasks/CreateWalletTask.kt +++ b/tangem-core/src/main/java/com/tangem/tasks/CreateWalletTask.kt @@ -12,6 +12,7 @@ import com.tangem.common.CompletionResult class CreateWalletTask : CardSessionRunnable { override val performPreflightRead = true + override val requiresPin2 = false override fun run(session: CardSession, callback: (result: CompletionResult) -> Unit) { val curve = session.environment.card?.curve diff --git a/tangem-core/src/main/java/com/tangem/tasks/ScanTask.kt b/tangem-core/src/main/java/com/tangem/tasks/ScanTask.kt index 512171113f..4a3cfcadb5 100644 --- a/tangem-core/src/main/java/com/tangem/tasks/ScanTask.kt +++ b/tangem-core/src/main/java/com/tangem/tasks/ScanTask.kt @@ -16,6 +16,7 @@ import com.tangem.common.CompletionResult internal class ScanTask : CardSessionRunnable { override val performPreflightRead = false + override val requiresPin2 = false override fun run(session: CardSession, callback: (result: CompletionResult) -> Unit) { @@ -31,6 +32,7 @@ internal class ScanTask : CardSessionRunnable { is CompletionResult.Success -> { val card = readResult.data session.environment.card = card + session.environment.restoreCardValues() if (session.environment.pin1 != null && session.environment.pin2 != null) { val checkPinCommand = SetPinCommand(session.environment.pin1!!.value, session.environment.pin2!!.value) checkPinCommand.run(session) { result -> @@ -39,7 +41,6 @@ internal class ScanTask : CardSessionRunnable { session.environment.pin2 = null } } - session.environment.restoreCardValues() runCheckWalletIfNeeded(card, session, callback) } } else { diff --git a/tangem-sdk/src/main/java/com/tangem/tangem_sdk_new/DefaultSessionViewDelegate.kt b/tangem-sdk/src/main/java/com/tangem/tangem_sdk_new/DefaultSessionViewDelegate.kt index b2bbd8afe0..662f286147 100644 --- a/tangem-sdk/src/main/java/com/tangem/tangem_sdk_new/DefaultSessionViewDelegate.kt +++ b/tangem-sdk/src/main/java/com/tangem/tangem_sdk_new/DefaultSessionViewDelegate.kt @@ -2,9 +2,9 @@ package com.tangem.tangem_sdk_new import androidx.fragment.app.FragmentActivity import com.tangem.* -import com.tangem.commands.PinType import com.tangem.tangem_sdk_new.nfc.NfcReader import com.tangem.tangem_sdk_new.ui.NfcSessionDialog +import com.tangem.tasks.PinType /** * Default implementation of [SessionViewDelegate].