diff --git a/app/src/main/java/com/tangem/ui/fragment/VerifyCardFragment.kt b/app/src/main/java/com/tangem/ui/fragment/VerifyCardFragment.kt index 421f780cc1..1272905501 100644 --- a/app/src/main/java/com/tangem/ui/fragment/VerifyCardFragment.kt +++ b/app/src/main/java/com/tangem/ui/fragment/VerifyCardFragment.kt @@ -69,6 +69,11 @@ class VerifyCardFragment : BaseFragment(), NavigationResultListener, NfcAdapter. super.onViewCreated(view, savedInstanceState) updateViews() + val card = ctx.card + if (!card.allowSwapPIN() && !card.allowSwapPIN2() && card.forbidPurgeWallet()) { + fabMenu.hide() + } + // set listeners fabMenu.setOnClickListener { showMenu(fabMenu) } @@ -278,11 +283,6 @@ class VerifyCardFragment : BaseFragment(), NavigationResultListener, NfcAdapter. ivBlockchain.setImageResource(Blockchain.getLogoImageResource(ctx.card!!.blockchainID, ctx.card!!.tokenSymbol)) - if (ctx.card!!.isReusable!!) - tvReusable.setText(R.string.details_reusable) - else - tvReusable.setText(R.string.details_one_off_card) - var s = "" for (signingM in ctx.card!!.allowedSigningMethod) { s += if (signingM == ctx.card!!.signingMethod) { @@ -328,44 +328,6 @@ class VerifyCardFragment : BaseFragment(), NavigationResultListener, NfcAdapter. tvFirmware.text = ctx.card!!.firmwareVersion - var features = "" - - features += if (ctx.card!!.allowSwapPIN()!! && ctx.card!!.allowSwapPIN2()!!) { - getString(R.string.details_both_pins_can_be_changed) - } else if (ctx.card!!.allowSwapPIN()!!) { - getString(R.string.details_pin1_can_be_changed) - } else if (ctx.card!!.allowSwapPIN2()!!) { - getString(R.string.details_pin2_can_be_changed) - } else { - getString(R.string.details_both_pins_fixed) - } - - if (ctx.card!!.needCVC()!!) - features += getString(R.string.details_required_cvc) - - - if (ctx.card!!.supportDynamicNDEF()!!) { - features += getString(R.string.details_dynamic_ndef) - } else if (ctx.card!!.supportNDEF()!!) - features += getString(R.string.details_ndef) - - if (ctx.card!!.supportBlock()!!) - features += getString(R.string.details_blockable) - - if (ctx.card!!.supportLinkingTerminal()) { - features += getString(R.string.details_linking_card_supported) - llLinkedCard.visibility = View.VISIBLE - } - - - if (ctx.card!!.supportOnlyOneCommandAtTime()) - features += getString(R.string.details_atomic_commmands) - - if (features.endsWith("\n")) - features = features.substring(0, features.length - 1) - - tvFeatures.text = features - val textIsLinked = if (ctx.card.terminalIsLinked) { getString(R.string.details_linked_card_to_phone) } else { @@ -373,25 +335,6 @@ class VerifyCardFragment : BaseFragment(), NavigationResultListener, NfcAdapter. } tvIsLinked.text = textIsLinked - if (ctx.card!!.useDefaultPIN1()) { - imgPIN.setImageResource(R.drawable.unlock_pin1) - imgPIN.setOnClickListener { Toast.makeText(context, R.string.details_protected_by_default_pin_1, Toast.LENGTH_LONG).show() } - } else { - imgPIN.setImageResource(R.drawable.lock_pin1) - imgPIN.setOnClickListener { Toast.makeText(context, R.string.details_protected_by_user_pin_1, Toast.LENGTH_LONG).show() } - } - - if (ctx.card!!.pauseBeforePIN2 > 0 && (ctx.card!!.useDefaultPIN2()!! || !ctx.card!!.useSmartSecurityDelay())) { - imgPIN2orSecurityDelay.setImageResource(R.drawable.timer) - imgPIN2orSecurityDelay.setOnClickListener { Toast.makeText(context, String.format(getString(R.string.details_security_delay), ctx.card!!.pauseBeforePIN2 / 1000.0), Toast.LENGTH_LONG).show() } - } else if (ctx.card!!.useDefaultPIN2()!!) { - imgPIN2orSecurityDelay.setImageResource(R.drawable.unlock_pin2) - imgPIN2orSecurityDelay.setOnClickListener { Toast.makeText(context, R.string.details_protected_by_default_pin_2, Toast.LENGTH_LONG).show() } - } else { - imgPIN2orSecurityDelay.setImageResource(R.drawable.lock_pin2) - imgPIN2orSecurityDelay.setOnClickListener { Toast.makeText(context, R.string.details_protected_by_user_pin_2, Toast.LENGTH_LONG).show() } - } - if (ctx.card!!.useDevelopersFirmware()!!) { imgDeveloperVersion.setImageResource(R.drawable.ic_developer_version) imgDeveloperVersion.visibility = View.VISIBLE diff --git a/app/src/main/res/layout/fr_verify_card.xml b/app/src/main/res/layout/fr_verify_card.xml index 189186e5f5..cef381db19 100644 --- a/app/src/main/res/layout/fr_verify_card.xml +++ b/app/src/main/res/layout/fr_verify_card.xml @@ -159,32 +159,6 @@ - - - - - - - - - - - - - - - - - - - - - diff --git a/tangem-card-old/src/main/java/com/tangem/tangem_card/data/TangemCard.java b/tangem-card-old/src/main/java/com/tangem/tangem_card/data/TangemCard.java index 37da532954..7d924574a6 100644 --- a/tangem-card-old/src/main/java/com/tangem/tangem_card/data/TangemCard.java +++ b/tangem-card-old/src/main/java/com/tangem/tangem_card/data/TangemCard.java @@ -8,7 +8,6 @@ import com.tangem.tangem_card.reader.TLVList; import com.tangem.tangem_card.util.Util; import java.nio.charset.StandardCharsets; -import java.util.ArrayList; import java.util.Date; import java.util.EnumSet; @@ -359,6 +358,11 @@ public class TangemCard { return (settingsMask & SettingsMask.AllowSwapPIN2) != 0; } + public Boolean forbidPurgeWallet() { + if (settingsMask == null) return null; + return (settingsMask & SettingsMask.ForbidPurgeWallet) != 0; + } + public Boolean needCVC() { if (settingsMask == null) return null; return (settingsMask & SettingsMask.UseCVC) != 0; diff --git a/tangem-core/src/main/java/com/tangem/CardManager.kt b/tangem-core/src/main/java/com/tangem/CardManager.kt index ae2041db9e..c5a1f99e77 100644 --- a/tangem-core/src/main/java/com/tangem/CardManager.kt +++ b/tangem-core/src/main/java/com/tangem/CardManager.kt @@ -1,11 +1,11 @@ package com.tangem import com.tangem.commands.* -import com.tangem.commands.personalization.CardConfig import com.tangem.commands.personalization.DepersonalizeCommand import com.tangem.commands.personalization.DepersonalizeResponse import com.tangem.commands.personalization.PersonalizeCommand import com.tangem.commands.personalization.entities.Acquirer +import com.tangem.commands.personalization.entities.CardConfig import com.tangem.commands.personalization.entities.Issuer import com.tangem.commands.personalization.entities.Manufacturer import com.tangem.common.CardEnvironment @@ -263,17 +263,15 @@ class CardManager( * During this procedure all data exchange is encrypted. * @param config is a configuration file with all the card settings that are written on the card * during personalization. - * @param cardId this parameter will set up CID, Unique Tangem card ID. * @param issuer Issuer is a third-party team or company wishing to use Tangem cards. * @param manufacturer Tangem Card Manufacturer. * @param acquirer Acquirer is a trusted third-party company that operates proprietary * (non-EMV) POS terminal infrastructure and transaction processing back-end. */ fun personalize(config: CardConfig, - cardId: String, issuer: Issuer, manufacturer: Manufacturer, acquirer: Acquirer? = null, callback: (result: TaskEvent) -> Unit) { - val personalizationCommand = PersonalizeCommand(config, cardId, issuer, manufacturer, acquirer) + val personalizationCommand = PersonalizeCommand(config, issuer, manufacturer, acquirer) val task = SingleCommandTask(personalizationCommand) task.performPreflightRead = false runTask(task, callback = callback) diff --git a/tangem-core/src/main/java/com/tangem/commands/ReadUserDataCommand.kt b/tangem-core/src/main/java/com/tangem/commands/ReadUserDataCommand.kt index ba5954fe01..656c1750f0 100644 --- a/tangem-core/src/main/java/com/tangem/commands/ReadUserDataCommand.kt +++ b/tangem-core/src/main/java/com/tangem/commands/ReadUserDataCommand.kt @@ -9,9 +9,6 @@ import com.tangem.common.tlv.TlvMapper import com.tangem.common.tlv.TlvTag import com.tangem.tasks.TaskError -/** -[REDACTED_AUTHOR] - */ class ReadUserDataResponse( /** * CID, Unique Tangem card ID number. diff --git a/tangem-core/src/main/java/com/tangem/commands/WriteUserDataCommand.kt b/tangem-core/src/main/java/com/tangem/commands/WriteUserDataCommand.kt index 804abf6601..ac79cba45c 100644 --- a/tangem-core/src/main/java/com/tangem/commands/WriteUserDataCommand.kt +++ b/tangem-core/src/main/java/com/tangem/commands/WriteUserDataCommand.kt @@ -9,10 +9,6 @@ import com.tangem.common.tlv.TlvMapper import com.tangem.common.tlv.TlvTag import com.tangem.tasks.TaskError -/** -[REDACTED_AUTHOR] - */ - class WriteUserDataResponse( /** * CID, Unique Tangem card ID number. diff --git a/tangem-core/src/main/java/com/tangem/commands/personalization/CardConfig.kt b/tangem-core/src/main/java/com/tangem/commands/personalization/CardConfig.kt deleted file mode 100644 index 15548f9871..0000000000 --- a/tangem-core/src/main/java/com/tangem/commands/personalization/CardConfig.kt +++ /dev/null @@ -1,112 +0,0 @@ -package com.tangem.commands.personalization - -import com.tangem.commands.* - -data class NdefRecord( - val type: Type, - val value: String -) { - enum class Type { - URI, AAR, TEXT - } - - val valueInBytes: ByteArray by lazy { value.toByteArray() } -} - -/** - * It is a configuration file with all the card settings that are written on the card - * during [PersonalizeCommand]. - */ -data class CardConfig( - val issuerName: String? = null, - val acquirerName: String? = null, - val series: String? = null, - val startNumber: Long = 0, - val count: Int = 0, - val pin: String, - val pin2: String, - val pin3: String, - val hexCrExKey: String?, - val cvc: String, - val pauseBeforePin2: Int, - val smartSecurityDelay: Boolean, - val curveID: EllipticCurve, - val signingMethod: SigningMethod, - val maxSignatures: Int, - val isReusable: Boolean, - val allowSwapPin: Boolean, - val allowSwapPin2: Boolean, - val useActivation: Boolean, - val useCvc: Boolean, - val useNdef: Boolean, - val useDynamicNdef: Boolean, - val useOneCommandAtTime: Boolean, - val useBlock: Boolean, - val allowSelectBlockchain: Boolean, - val forbidPurgeWallet: Boolean, - val protocolAllowUnencrypted: Boolean, - val protocolAllowStaticEncryption: Boolean, - val protectIssuerDataAgainstReplay: Boolean, - val forbidDefaultPin: Boolean, - val disablePrecomputedNdef: Boolean, - val skipSecurityDelayIfValidatedByIssuer: Boolean, - val skipCheckPIN2andCVCIfValidatedByIssuer: Boolean, - val skipSecurityDelayIfValidatedByLinkedTerminal: Boolean, - - val restrictOverwriteIssuerDataEx: Boolean, - - val requireTerminalTxSignature: Boolean, - val requireTerminalCertSignature: Boolean, - val checkPin3onCard: Boolean, - - val createWallet: Boolean, - - val cardData: CardData, - val ndefRecords: List -) { - - fun getSettingsMask(): SettingsMask { - val builder = SettingsMaskBuilder() - - if (allowSwapPin) builder.add(Settings.AllowSwapPIN) - if (allowSwapPin2) builder.add(Settings.AllowSwapPIN2) - if (useCvc) builder.add(Settings.UseCVC) - if (isReusable) builder.add(Settings.IsReusable) - - if (useOneCommandAtTime) builder.add(Settings.UseOneCommandAtTime) - if (useNdef) builder.add(Settings.UseNdef) - if (useDynamicNdef) builder.add(Settings.UseDynamicNdef) - if (disablePrecomputedNdef) builder.add(Settings.DisablePrecomputedNdef) - - if (protocolAllowUnencrypted) builder.add(Settings.ProtocolAllowUnencrypted) - if (protocolAllowStaticEncryption) builder.add(Settings.ProtocolAllowStaticEncryption) - - if (forbidDefaultPin) builder.add(Settings.ForbidDefaultPIN) - - if (useActivation) builder.add(Settings.UseActivation) - - if (useBlock) builder.add(Settings.UseBlock) - if (smartSecurityDelay) builder.add(Settings.SmartSecurityDelay) - - if (protectIssuerDataAgainstReplay) builder.add(Settings.ProtectIssuerDataAgainstReplay) - - if (forbidPurgeWallet) builder.add(Settings.ForbidPurgeWallet) - if (allowSelectBlockchain) builder.add(Settings.AllowSelectBlockchain) - - if (skipCheckPIN2andCVCIfValidatedByIssuer) builder.add(Settings.SkipCheckPin2andCvcIfValidatedByIssuer) - if (skipSecurityDelayIfValidatedByIssuer) builder.add(Settings.SkipSecurityDelayIfValidatedByIssuer) - - if (skipSecurityDelayIfValidatedByLinkedTerminal) builder.add(Settings.SkipSecurityDelayIfValidatedByLinkedTerminal) - if (restrictOverwriteIssuerDataEx) builder.add(Settings.RestrictOverwriteIssuerDataEx) - - if (requireTerminalTxSignature) builder.add(Settings.RequireTermTxSignature) - - if (requireTerminalCertSignature) builder.add(Settings.RequireTermCertSignature) - - if (checkPin3onCard) builder.add(Settings.CheckPIN3onCard) - - return builder.build() - } - - companion object -} \ No newline at end of file diff --git a/tangem-core/src/main/java/com/tangem/commands/personalization/NdefEncoder.kt b/tangem-core/src/main/java/com/tangem/commands/personalization/NdefEncoder.kt index a034d171cb..6c6103556e 100644 --- a/tangem-core/src/main/java/com/tangem/commands/personalization/NdefEncoder.kt +++ b/tangem-core/src/main/java/com/tangem/commands/personalization/NdefEncoder.kt @@ -1,5 +1,6 @@ package com.tangem.commands.personalization +import com.tangem.commands.personalization.entities.NdefRecord import java.io.ByteArrayOutputStream import java.nio.charset.StandardCharsets diff --git a/tangem-core/src/main/java/com/tangem/commands/personalization/PersonalizeCommand.kt b/tangem-core/src/main/java/com/tangem/commands/personalization/PersonalizeCommand.kt index 848c72e5e6..035963c21a 100644 --- a/tangem-core/src/main/java/com/tangem/commands/personalization/PersonalizeCommand.kt +++ b/tangem-core/src/main/java/com/tangem/commands/personalization/PersonalizeCommand.kt @@ -3,9 +3,7 @@ package com.tangem.commands.personalization import com.tangem.commands.Card import com.tangem.commands.CardData import com.tangem.commands.CommandSerializer -import com.tangem.commands.personalization.entities.Acquirer -import com.tangem.commands.personalization.entities.Issuer -import com.tangem.commands.personalization.entities.Manufacturer +import com.tangem.commands.personalization.entities.* import com.tangem.common.CardEnvironment import com.tangem.common.apdu.CommandApdu import com.tangem.common.apdu.Instruction @@ -27,14 +25,13 @@ import com.tangem.tasks.TaskError * During this procedure all data exchange is encrypted. * @property config is a configuration file with all the card settings that are written on the card * during personalization. - * @property cardId this parameter will set up CID, Unique Tangem card ID. * @property issuer Issuer is a third-party team or company wishing to use Tangem cards. * @property manufacturer Tangem Card Manufacturer. * @property acquirer Acquirer is a trusted third-party company that operates proprietary * (non-EMV) POS terminal infrastructure and transaction processing back-end. */ class PersonalizeCommand( - private val config: CardConfig, private val cardId: String, + private val config: CardConfig, private val issuer: Issuer, private val manufacturer: Manufacturer, private val acquirer: Acquirer? = null ) : CommandSerializer() { @@ -42,8 +39,7 @@ class PersonalizeCommand( override fun serialize(cardEnvironment: CardEnvironment): CommandApdu { return CommandApdu( Instruction.Personalize, - serializePersonalizationData( - cardId, config), + serializePersonalizationData(config), encryptionKey = devPersonalizationKey ) } @@ -104,17 +100,19 @@ class PersonalizeCommand( ) } - private fun serializePersonalizationData(cardId: String, config: CardConfig): ByteArray { + private fun serializePersonalizationData(config: CardConfig): ByteArray { + val cardId = config.createCardId() ?: throw TaskError.SerializeCommandError() + val tlvBuilder = TlvBuilder() tlvBuilder.append(TlvTag.CardId, cardId) - tlvBuilder.append(TlvTag.CurveId, config.curveID) tlvBuilder.append(TlvTag.MaxSignatures, config.maxSignatures) tlvBuilder.append(TlvTag.SigningMethod, config.signingMethod) - tlvBuilder.append(TlvTag.SettingsMask, config.getSettingsMask()) + tlvBuilder.append(TlvTag.SettingsMask, config.createSettingsMask()) tlvBuilder.append(TlvTag.PauseBeforePin2, config.pauseBeforePin2 / 10) tlvBuilder.append(TlvTag.Cvc, config.cvc.toByteArray()) - if (!config.ndefRecords.isNullOrEmpty()) tlvBuilder.append(TlvTag.NdefData, serializeNdef(config.ndefRecords)) + if (!config.ndefRecords.isNullOrEmpty()) + tlvBuilder.append(TlvTag.NdefData, serializeNdef(config)) tlvBuilder.append(TlvTag.CreateWalletAtPersonalize, config.createWallet) @@ -131,15 +129,16 @@ class PersonalizeCommand( return tlvBuilder.serialize() } + private fun serializeNdef(config: CardConfig): ByteArray { + return NdefEncoder(config.ndefRecords, config.useDynamicNdef).encode() + } + private fun serializeCardData(cardId: String, cardData: CardData): ByteArray { val tlvBuilder = TlvBuilder() tlvBuilder.append(TlvTag.Batch, cardData.batchId) tlvBuilder.append(TlvTag.ProductMask, cardData.productMask) - tlvBuilder.append(TlvTag.ManufactureDateTime, cardData.manufactureDateTime) - tlvBuilder.append(TlvTag.IssuerId, issuer.id) - tlvBuilder.append(TlvTag.BlockchainId, cardData.blockchainName) if (cardData.tokenSymbol != null) { @@ -154,10 +153,6 @@ class PersonalizeCommand( return tlvBuilder.serialize() } - private fun serializeNdef(ndefRecords: List): ByteArray { - return NdefEncoder(ndefRecords, config.useDynamicNdef).encode() - } - companion object { val devPersonalizationKey = "1234".calculateSha256().copyOf(32) } diff --git a/tangem-core/src/main/java/com/tangem/commands/personalization/entities/CardConfig.kt b/tangem-core/src/main/java/com/tangem/commands/personalization/entities/CardConfig.kt new file mode 100644 index 0000000000..bc1a082237 --- /dev/null +++ b/tangem-core/src/main/java/com/tangem/commands/personalization/entities/CardConfig.kt @@ -0,0 +1,70 @@ +package com.tangem.commands.personalization.entities + +import com.tangem.commands.CardData +import com.tangem.commands.EllipticCurve +import com.tangem.commands.SigningMethod + +data class NdefRecord( + val type: Type, + val value: String +) { + enum class Type { + URI, AAR, TEXT + } + + val valueInBytes: ByteArray by lazy { value.toByteArray() } +} + +/** + * It is a configuration file with all the card settings that are written on the card + * during [PersonalizeCommand]. + */ +data class CardConfig( + val issuerName: String? = null, + val acquirerName: String? = null, + val series: String? = null, + val startNumber: Long = 0, + val count: Int = 0, + val pin: String, + val pin2: String, + val pin3: String, + val hexCrExKey: String?, + val cvc: String, + val pauseBeforePin2: Int, + val smartSecurityDelay: Boolean, + val curveID: EllipticCurve, + val signingMethod: SigningMethod, + val maxSignatures: Int, + val isReusable: Boolean, + val allowSwapPin: Boolean, + val allowSwapPin2: Boolean, + val useActivation: Boolean, + val useCvc: Boolean, + val useNdef: Boolean, + val useDynamicNdef: Boolean, + val useOneCommandAtTime: Boolean, + val useBlock: Boolean, + val allowSelectBlockchain: Boolean, + val forbidPurgeWallet: Boolean, + val protocolAllowUnencrypted: Boolean, + val protocolAllowStaticEncryption: Boolean, + val protectIssuerDataAgainstReplay: Boolean, + val forbidDefaultPin: Boolean, + val disablePrecomputedNdef: Boolean, + val skipSecurityDelayIfValidatedByIssuer: Boolean, + val skipCheckPIN2andCVCIfValidatedByIssuer: Boolean, + val skipSecurityDelayIfValidatedByLinkedTerminal: Boolean, + + val restrictOverwriteIssuerDataEx: Boolean, + + val requireTerminalTxSignature: Boolean, + val requireTerminalCertSignature: Boolean, + val checkPin3onCard: Boolean, + + val createWallet: Boolean, + + val cardData: CardData, + val ndefRecords: List +) { + companion object +} \ No newline at end of file diff --git a/tangem-core/src/main/java/com/tangem/commands/personalization/entities/CardConfigExtensions.kt b/tangem-core/src/main/java/com/tangem/commands/personalization/entities/CardConfigExtensions.kt new file mode 100644 index 0000000000..4d7895f3c4 --- /dev/null +++ b/tangem-core/src/main/java/com/tangem/commands/personalization/entities/CardConfigExtensions.kt @@ -0,0 +1,81 @@ +package com.tangem.commands.personalization.entities + +import com.tangem.commands.Settings +import com.tangem.commands.SettingsMask +import com.tangem.commands.SettingsMaskBuilder + +internal fun CardConfig.createSettingsMask(): SettingsMask { + val builder = SettingsMaskBuilder() + + if (allowSwapPin) builder.add(Settings.AllowSwapPIN) + if (allowSwapPin2) builder.add(Settings.AllowSwapPIN2) + if (useCvc) builder.add(Settings.UseCVC) + if (isReusable) builder.add(Settings.IsReusable) + + if (useOneCommandAtTime) builder.add(Settings.UseOneCommandAtTime) + if (useNdef) builder.add(Settings.UseNdef) + if (useDynamicNdef) builder.add(Settings.UseDynamicNdef) + if (disablePrecomputedNdef) builder.add(Settings.DisablePrecomputedNdef) + + if (protocolAllowUnencrypted) builder.add(Settings.ProtocolAllowUnencrypted) + if (protocolAllowStaticEncryption) builder.add(Settings.ProtocolAllowStaticEncryption) + + if (forbidDefaultPin) builder.add(Settings.ForbidDefaultPIN) + + if (useActivation) builder.add(Settings.UseActivation) + + if (useBlock) builder.add(Settings.UseBlock) + if (smartSecurityDelay) builder.add(Settings.SmartSecurityDelay) + + if (protectIssuerDataAgainstReplay) builder.add(Settings.ProtectIssuerDataAgainstReplay) + + if (forbidPurgeWallet) builder.add(Settings.ForbidPurgeWallet) + if (allowSelectBlockchain) builder.add(Settings.AllowSelectBlockchain) + + if (skipCheckPIN2andCVCIfValidatedByIssuer) builder.add(Settings.SkipCheckPin2andCvcIfValidatedByIssuer) + if (skipSecurityDelayIfValidatedByIssuer) builder.add(Settings.SkipSecurityDelayIfValidatedByIssuer) + + if (skipSecurityDelayIfValidatedByLinkedTerminal) builder.add(Settings.SkipSecurityDelayIfValidatedByLinkedTerminal) + if (restrictOverwriteIssuerDataEx) builder.add(Settings.RestrictOverwriteIssuerDataEx) + + if (requireTerminalTxSignature) builder.add(Settings.RequireTermTxSignature) + + if (requireTerminalCertSignature) builder.add(Settings.RequireTermCertSignature) + + if (checkPin3onCard) builder.add(Settings.CheckPIN3onCard) + + return builder.build() +} + +internal fun CardConfig.createCardId(): String? { + if (series == null) return null + if (startNumber <= 0 || (series.length != 2 && series.length != 4)) return null + + val Alf = "ABCDEF0123456789" + fun checkSeries(series: String): Boolean { + val containsList = series.filter { Alf.contains(it) } + return containsList.length == series.length + } + if (!checkSeries(series)) return null + + val tail = if (series.length == 2) String.format("%013d", startNumber) else String.format("%011d", startNumber) + var cardId = (series + tail).replace(" ", "") + if (cardId.length != 15 || Alf.indexOf(cardId[0]) == -1 || Alf.indexOf(cardId[1]) == -1) + return null + + cardId += "0" + val length = cardId.length + var sum = 0 + for (i in 0 until length) { + // get digits in reverse order + var digit: Int + val cDigit = cardId[length - i - 1] + digit = if (cDigit in '0'..'9') cDigit - '0' else cDigit - 'A' + + // every 2nd number multiply with 2 + if (i % 2 == 1) digit *= 2 + sum += if (digit > 9) digit - 9 else digit + } + val lunh = (10 - sum % 10) % 10 + return cardId.substring(0, 15) + String.format("%d", lunh) +} \ No newline at end of file diff --git a/tangem-demo/src/main/java/com/tangem/tangemtest/extensions/CardConfig.kt b/tangem-demo/src/main/java/com/tangem/tangemtest/extensions/CardConfig.kt index 5412ab7c15..0ef2666e1d 100644 --- a/tangem-demo/src/main/java/com/tangem/tangemtest/extensions/CardConfig.kt +++ b/tangem-demo/src/main/java/com/tangem/tangemtest/extensions/CardConfig.kt @@ -3,8 +3,8 @@ package com.tangem.tangemtest.extensions import android.app.Application import android.content.Context import com.tangem.commands.* -import com.tangem.commands.personalization.CardConfig -import com.tangem.commands.personalization.NdefRecord +import com.tangem.commands.personalization.entities.CardConfig +import com.tangem.commands.personalization.entities.NdefRecord import java.util.* fun CardConfig.Companion.init(application: Application): CardConfig {