From 7e3a2eca0940fadbe0069bc44767294d013598af Mon Sep 17 00:00:00 2001 From: Arseni Date: Mon, 13 Apr 2026 14:01:38 +0300 Subject: [PATCH] =?UTF-8?q?feat:=20support=20full=20MIR=20BIN=20range=2022?= =?UTF-8?q?00=E2=80=932204?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- example/pubspec.lock | 44 +++++++-------- .../credit_card_number_input_formatter.dart | 18 +++++++ pubspec.lock | 42 +++++++-------- test/flutter_multi_formatter_test.dart | 53 +++++++++++++++++++ 4 files changed, 114 insertions(+), 43 deletions(-) diff --git a/example/pubspec.lock b/example/pubspec.lock index 8eff00d..e228244 100644 --- a/example/pubspec.lock +++ b/example/pubspec.lock @@ -37,10 +37,10 @@ packages: dependency: transitive description: name: characters - sha256: f71061c654a3380576a52b451dd5532377954cf9dbd272a78fc8479606670803 + sha256: faf38497bda5ead2a8c7615f4f7939df04333478bf32e4173fcb06d428b5716b url: "https://pub.dev" source: hosted - version: "1.4.0" + version: "1.4.1" clock: dependency: transitive description: @@ -77,10 +77,10 @@ packages: dependency: transitive description: name: fake_async - sha256: "6a95e56b2449df2273fd8c45a662d6947ce1ebb7aafe80e550a3f68297f3cacc" + sha256: "5368f224a74523e8d2e7399ea1638b37aecfca824a3cc4dfdf77bf1fa905ac44" url: "https://pub.dev" source: hosted - version: "1.3.2" + version: "1.3.3" flutter: dependency: "direct main" description: flutter @@ -92,7 +92,7 @@ packages: path: ".." relative: true source: path - version: "2.13.0" + version: "2.13.10" flutter_test: dependency: "direct dev" description: flutter @@ -102,50 +102,50 @@ packages: dependency: transitive description: name: leak_tracker - sha256: c35baad643ba394b40aac41080300150a4f08fd0fd6a10378f8f7c6bc161acec + sha256: "33e2e26bdd85a0112ec15400c8cbffea70d0f9c3407491f672a2fad47915e2de" url: "https://pub.dev" source: hosted - version: "10.0.8" + version: "11.0.2" leak_tracker_flutter_testing: dependency: transitive description: name: leak_tracker_flutter_testing - sha256: f8b613e7e6a13ec79cfdc0e97638fddb3ab848452eff057653abd3edba760573 + sha256: "1dbc140bb5a23c75ea9c4811222756104fbcd1a27173f0c34ca01e16bea473c1" url: "https://pub.dev" source: hosted - version: "3.0.9" + version: "3.0.10" leak_tracker_testing: dependency: transitive description: name: leak_tracker_testing - sha256: "6ba465d5d76e67ddf503e1161d1f4a6bc42306f9d66ca1e8f079a47290fb06d3" + sha256: "8d5a2d49f4a66b49744b23b018848400d23e54caf9463f4eb20df3eb8acb2eb1" url: "https://pub.dev" source: hosted - version: "3.0.1" + version: "3.0.2" matcher: dependency: transitive description: name: matcher - sha256: dc58c723c3c24bf8d3e2d3ad3f2f9d7bd9cf43ec6feaa64181775e60190153f2 + sha256: "12956d0ad8390bbcc63ca2e1469c0619946ccb52809807067a7020d57e647aa6" url: "https://pub.dev" source: hosted - version: "0.12.17" + version: "0.12.18" material_color_utilities: dependency: transitive description: name: material_color_utilities - sha256: f7142bb1154231d7ea5f96bc7bde4bda2a0945d2806bb11670e30b850d56bdec + sha256: "9c337007e82b1889149c82ed242ed1cb24a66044e30979c44912381e9be4c48b" url: "https://pub.dev" source: hosted - version: "0.11.1" + version: "0.13.0" meta: dependency: transitive description: name: meta - sha256: e3641ec5d63ebf0d9b41bd43201a66e3fc79a65db5f61fc181f04cd27aab950c + sha256: "23f08335362185a5ea2ad3a4e597f1375e78bce8a040df5c600c8d3552ef2394" url: "https://pub.dev" source: hosted - version: "1.16.0" + version: "1.17.0" path: dependency: transitive description: @@ -203,10 +203,10 @@ packages: dependency: transitive description: name: test_api - sha256: fb31f383e2ee25fbbfe06b40fe21e1e458d14080e3c67e7ba0acfde4df4e0bbd + sha256: "93167629bfc610f71560ab9312acdda4959de4df6fac7492c89ff0d3886f6636" url: "https://pub.dev" source: hosted - version: "0.7.4" + version: "0.7.9" typed_data: dependency: transitive description: @@ -219,10 +219,10 @@ packages: dependency: transitive description: name: vector_math - sha256: "80b3257d1492ce4d091729e3a67a60407d227c27241d6927be0130c98e741803" + sha256: d530bd74fea330e6e364cda7a85019c434070188383e1cd8d9777ee586914c5b url: "https://pub.dev" source: hosted - version: "2.1.4" + version: "2.2.0" vm_service: dependency: transitive description: @@ -232,5 +232,5 @@ packages: source: hosted version: "14.3.1" sdks: - dart: ">=3.7.0-0 <4.0.0" + dart: ">=3.9.0-0 <4.0.0" flutter: ">=3.18.0-18.0.pre.54" diff --git a/lib/formatters/credit_card_number_input_formatter.dart b/lib/formatters/credit_card_number_input_formatter.dart index df3a4bc..0a4e176 100644 --- a/lib/formatters/credit_card_number_input_formatter.dart +++ b/lib/formatters/credit_card_number_input_formatter.dart @@ -414,6 +414,24 @@ class _CardSystemDatas { 'numberMask': '0000 0000 0000 0000', 'numDigits': 16, }, + { + 'system': CardSystem.MIR, + 'systemCode': '2201', + 'numberMask': '0000 0000 0000 0000', + 'numDigits': 16, + }, + { + 'system': CardSystem.MIR, + 'systemCode': '2202', + 'numberMask': '0000 0000 0000 0000', + 'numDigits': 16, + }, + { + 'system': CardSystem.MIR, + 'systemCode': '2203', + 'numberMask': '0000 0000 0000 0000', + 'numDigits': 16, + }, { 'system': CardSystem.MIR, 'systemCode': '2204', diff --git a/pubspec.lock b/pubspec.lock index d536cee..88abbea 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -37,10 +37,10 @@ packages: dependency: transitive description: name: characters - sha256: f71061c654a3380576a52b451dd5532377954cf9dbd272a78fc8479606670803 + sha256: faf38497bda5ead2a8c7615f4f7939df04333478bf32e4173fcb06d428b5716b url: "https://pub.dev" source: hosted - version: "1.4.0" + version: "1.4.1" clock: dependency: transitive description: @@ -77,10 +77,10 @@ packages: dependency: transitive description: name: fake_async - sha256: "6a95e56b2449df2273fd8c45a662d6947ce1ebb7aafe80e550a3f68297f3cacc" + sha256: "5368f224a74523e8d2e7399ea1638b37aecfca824a3cc4dfdf77bf1fa905ac44" url: "https://pub.dev" source: hosted - version: "1.3.2" + version: "1.3.3" flutter: dependency: "direct main" description: flutter @@ -95,50 +95,50 @@ packages: dependency: transitive description: name: leak_tracker - sha256: c35baad643ba394b40aac41080300150a4f08fd0fd6a10378f8f7c6bc161acec + sha256: "33e2e26bdd85a0112ec15400c8cbffea70d0f9c3407491f672a2fad47915e2de" url: "https://pub.dev" source: hosted - version: "10.0.8" + version: "11.0.2" leak_tracker_flutter_testing: dependency: transitive description: name: leak_tracker_flutter_testing - sha256: f8b613e7e6a13ec79cfdc0e97638fddb3ab848452eff057653abd3edba760573 + sha256: "1dbc140bb5a23c75ea9c4811222756104fbcd1a27173f0c34ca01e16bea473c1" url: "https://pub.dev" source: hosted - version: "3.0.9" + version: "3.0.10" leak_tracker_testing: dependency: transitive description: name: leak_tracker_testing - sha256: "6ba465d5d76e67ddf503e1161d1f4a6bc42306f9d66ca1e8f079a47290fb06d3" + sha256: "8d5a2d49f4a66b49744b23b018848400d23e54caf9463f4eb20df3eb8acb2eb1" url: "https://pub.dev" source: hosted - version: "3.0.1" + version: "3.0.2" matcher: dependency: transitive description: name: matcher - sha256: dc58c723c3c24bf8d3e2d3ad3f2f9d7bd9cf43ec6feaa64181775e60190153f2 + sha256: "12956d0ad8390bbcc63ca2e1469c0619946ccb52809807067a7020d57e647aa6" url: "https://pub.dev" source: hosted - version: "0.12.17" + version: "0.12.18" material_color_utilities: dependency: transitive description: name: material_color_utilities - sha256: f7142bb1154231d7ea5f96bc7bde4bda2a0945d2806bb11670e30b850d56bdec + sha256: "9c337007e82b1889149c82ed242ed1cb24a66044e30979c44912381e9be4c48b" url: "https://pub.dev" source: hosted - version: "0.11.1" + version: "0.13.0" meta: dependency: transitive description: name: meta - sha256: e3641ec5d63ebf0d9b41bd43201a66e3fc79a65db5f61fc181f04cd27aab950c + sha256: "23f08335362185a5ea2ad3a4e597f1375e78bce8a040df5c600c8d3552ef2394" url: "https://pub.dev" source: hosted - version: "1.16.0" + version: "1.17.0" path: dependency: transitive description: @@ -196,10 +196,10 @@ packages: dependency: transitive description: name: test_api - sha256: fb31f383e2ee25fbbfe06b40fe21e1e458d14080e3c67e7ba0acfde4df4e0bbd + sha256: "93167629bfc610f71560ab9312acdda4959de4df6fac7492c89ff0d3886f6636" url: "https://pub.dev" source: hosted - version: "0.7.4" + version: "0.7.9" typed_data: dependency: transitive description: @@ -212,10 +212,10 @@ packages: dependency: transitive description: name: vector_math - sha256: "80b3257d1492ce4d091729e3a67a60407d227c27241d6927be0130c98e741803" + sha256: d530bd74fea330e6e364cda7a85019c434070188383e1cd8d9777ee586914c5b url: "https://pub.dev" source: hosted - version: "2.1.4" + version: "2.2.0" vm_service: dependency: transitive description: @@ -225,5 +225,5 @@ packages: source: hosted version: "14.3.1" sdks: - dart: ">=3.7.0-0 <4.0.0" + dart: ">=3.9.0-0 <4.0.0" flutter: ">=3.18.0-18.0.pre.54" diff --git a/test/flutter_multi_formatter_test.dart b/test/flutter_multi_formatter_test.dart index b28e54a..8530040 100644 --- a/test/flutter_multi_formatter_test.dart +++ b/test/flutter_multi_formatter_test.dart @@ -3,6 +3,59 @@ import 'package:flutter_test/flutter_test.dart'; import '../lib/flutter_multi_formatter.dart'; void main() { + group('MIR cards', () { + const mirSamples = [ + '2200000000000004', + '2201000000000003', + '2202000000000002', + '2203000000000001', + '2204000000000000', + ]; + + test('should detect MIR system for supported 2200-2204 prefixes', () { + for (final cardNumber in mirSamples) { + final cardSystemData = getCardSystemData(cardNumber); + + expect(cardSystemData, isNotNull); + expect(cardSystemData!.system, CardSystem.MIR); + expect(cardSystemData.systemCode, cardNumber.substring(0, 4)); + } + }); + + test('should validate MIR numbers for supported 2200-2204 prefixes', () { + for (final cardNumber in mirSamples) { + expect( + isCardNumberValid( + cardNumber: cardNumber, + checkLength: true, + ), + isTrue, + ); + } + }); + + test('should format MIR numbers for supported 2200-2204 prefixes', () { + final formatter = CreditCardNumberInputFormatter(); + + for (final cardNumber in mirSamples) { + final formatted = formatter + .formatEditUpdate( + const TextEditingValue(text: ''), + TextEditingValue(text: cardNumber), + ) + .text; + + expect( + formatted, + '${cardNumber.substring(0, 4)} ' + '${cardNumber.substring(4, 8)} ' + '${cardNumber.substring(8, 12)} ' + '${cardNumber.substring(12, 16)}', + ); + } + }); + }); + test( 'should use the philippines land line mask (shorter one) when partially entering a number', () {