creditcard-identifier 2.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/README.md +153 -0
- data/lib/creditcard_identifier/brands.rb +80 -0
- data/lib/creditcard_identifier/brands_detailed.rb +524 -0
- data/lib/creditcard_identifier.rb +192 -0
- metadata +77 -0
checksums.yaml
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
---
|
|
2
|
+
SHA256:
|
|
3
|
+
metadata.gz: 2971d1554919d8eaf0fd916f87d9003cee3aae39d07e0b6f6de388d19eff31f1
|
|
4
|
+
data.tar.gz: c51129f59758f48b10b24f1e7f7f2d6ee336b62aa8e91fceed7ead69d1005fcb
|
|
5
|
+
SHA512:
|
|
6
|
+
metadata.gz: 0b831eb2196ceab513b4b2e77907abd454d14cfb13052dc0e14eea01ad964bfff247f13fdfb382bb0f9bb210c0409721853f02e414a6c05cf6dea8c87c030df0
|
|
7
|
+
data.tar.gz: 10f73f531f751c2f48f347daed4b1d2f726cd19495ae579d4a80b6d40e5b4ea6a2f8b694f17f80d6d46bb8327a1530a936743e86382b5453d92de98ab3559e6e
|
data/README.md
ADDED
|
@@ -0,0 +1,153 @@
|
|
|
1
|
+
# Credit Card Identifier - Ruby Library
|
|
2
|
+
|
|
3
|
+
Ruby library for credit card BIN validation using bin-cc data.
|
|
4
|
+
|
|
5
|
+
## Installation
|
|
6
|
+
|
|
7
|
+
Add this line to your application's Gemfile:
|
|
8
|
+
|
|
9
|
+
```ruby
|
|
10
|
+
gem 'creditcard-identifier'
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
And then execute:
|
|
14
|
+
|
|
15
|
+
```bash
|
|
16
|
+
bundle install
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
Or install it yourself as:
|
|
20
|
+
|
|
21
|
+
```bash
|
|
22
|
+
gem install creditcard-identifier
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
## Usage
|
|
26
|
+
|
|
27
|
+
### Module-level Functions
|
|
28
|
+
|
|
29
|
+
```ruby
|
|
30
|
+
require 'creditcard_identifier'
|
|
31
|
+
|
|
32
|
+
# Identify card brand
|
|
33
|
+
brand = CreditcardIdentifier.find_brand('4012001037141112')
|
|
34
|
+
puts brand # 'visa'
|
|
35
|
+
|
|
36
|
+
# Check if card is supported
|
|
37
|
+
supported = CreditcardIdentifier.supported?('4012001037141112')
|
|
38
|
+
puts supported # true
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
### Using the Validator Class
|
|
42
|
+
|
|
43
|
+
```ruby
|
|
44
|
+
require 'creditcard_identifier'
|
|
45
|
+
|
|
46
|
+
validator = CreditcardIdentifier::Validator.new
|
|
47
|
+
|
|
48
|
+
# Identify brand
|
|
49
|
+
brand = validator.find_brand('4012001037141112')
|
|
50
|
+
puts brand # 'visa'
|
|
51
|
+
|
|
52
|
+
# Check if supported
|
|
53
|
+
supported = validator.supported?('4012001037141112')
|
|
54
|
+
puts supported # true
|
|
55
|
+
|
|
56
|
+
# Validate CVV
|
|
57
|
+
valid = validator.validate_cvv('123', 'visa')
|
|
58
|
+
puts valid # true
|
|
59
|
+
|
|
60
|
+
# Get brand info
|
|
61
|
+
info = validator.get_brand_info('visa')
|
|
62
|
+
puts info['regexpBin']
|
|
63
|
+
|
|
64
|
+
# List all brands
|
|
65
|
+
brands = validator.list_brands
|
|
66
|
+
puts brands # ['elo', 'diners', 'visa', ...]
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
## API
|
|
70
|
+
|
|
71
|
+
### Module Methods
|
|
72
|
+
|
|
73
|
+
#### `CreditcardIdentifier.find_brand(card_number)`
|
|
74
|
+
Identify the credit card brand.
|
|
75
|
+
|
|
76
|
+
**Parameters:**
|
|
77
|
+
- `card_number` (String): The credit card number
|
|
78
|
+
|
|
79
|
+
**Returns:** (String, nil) Brand name (e.g., 'visa', 'mastercard') or nil if not found
|
|
80
|
+
|
|
81
|
+
#### `CreditcardIdentifier.supported?(card_number)`
|
|
82
|
+
Check if the card number is supported.
|
|
83
|
+
|
|
84
|
+
**Parameters:**
|
|
85
|
+
- `card_number` (String): The credit card number
|
|
86
|
+
|
|
87
|
+
**Returns:** (Boolean) true if supported, false otherwise
|
|
88
|
+
|
|
89
|
+
### Validator Class
|
|
90
|
+
|
|
91
|
+
#### `initialize(data_path = nil)`
|
|
92
|
+
Initialize validator with brand data.
|
|
93
|
+
|
|
94
|
+
**Parameters:**
|
|
95
|
+
- `data_path` (String, nil): Path to brands.json. If nil, uses bundled data.
|
|
96
|
+
|
|
97
|
+
#### `find_brand(card_number)`
|
|
98
|
+
Identify the credit card brand.
|
|
99
|
+
|
|
100
|
+
**Parameters:**
|
|
101
|
+
- `card_number` (String): The credit card number
|
|
102
|
+
|
|
103
|
+
**Returns:** (String, nil) Brand name or nil if not found
|
|
104
|
+
|
|
105
|
+
#### `supported?(card_number)`
|
|
106
|
+
Check if card number is supported.
|
|
107
|
+
|
|
108
|
+
**Parameters:**
|
|
109
|
+
- `card_number` (String): The credit card number
|
|
110
|
+
|
|
111
|
+
**Returns:** (Boolean) true if supported, false otherwise
|
|
112
|
+
|
|
113
|
+
#### `validate_cvv(cvv, brand_name)`
|
|
114
|
+
Validate CVV for a specific brand.
|
|
115
|
+
|
|
116
|
+
**Parameters:**
|
|
117
|
+
- `cvv` (String): CVV code
|
|
118
|
+
- `brand_name` (String): Brand name (e.g., 'visa', 'mastercard')
|
|
119
|
+
|
|
120
|
+
**Returns:** (Boolean) true if valid, false otherwise
|
|
121
|
+
|
|
122
|
+
#### `get_brand_info(brand_name)`
|
|
123
|
+
Get information about a specific brand.
|
|
124
|
+
|
|
125
|
+
**Parameters:**
|
|
126
|
+
- `brand_name` (String): Brand name
|
|
127
|
+
|
|
128
|
+
**Returns:** (Hash, nil) Brand information or nil if not found
|
|
129
|
+
|
|
130
|
+
#### `list_brands`
|
|
131
|
+
List all supported brands.
|
|
132
|
+
|
|
133
|
+
**Returns:** (Array<String>) List of brand names
|
|
134
|
+
|
|
135
|
+
## Data Source
|
|
136
|
+
|
|
137
|
+
This library uses the BIN data from the [bin-cc project](https://github.com/renatovico/bin-cc).
|
|
138
|
+
|
|
139
|
+
The data is bundled with the gem, and can be updated by installing a newer version.
|
|
140
|
+
|
|
141
|
+
## Development
|
|
142
|
+
|
|
143
|
+
After checking out the repo, run `bundle install` to install dependencies.
|
|
144
|
+
|
|
145
|
+
Run tests with:
|
|
146
|
+
|
|
147
|
+
```bash
|
|
148
|
+
ruby test/test_validator.rb
|
|
149
|
+
```
|
|
150
|
+
|
|
151
|
+
## License
|
|
152
|
+
|
|
153
|
+
MIT
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
# Auto-generated by bin-cc build - DO NOT EDIT
|
|
4
|
+
# Generated: 2026-01-11T20:12:36.612Z
|
|
5
|
+
|
|
6
|
+
module CreditcardIdentifier
|
|
7
|
+
# Credit card brand data
|
|
8
|
+
BRANDS = [
|
|
9
|
+
{
|
|
10
|
+
name: "amex",
|
|
11
|
+
priority_over: [],
|
|
12
|
+
regexp_bin: /\A(3[47])/,
|
|
13
|
+
regexp_full: /\A(?=.{15}$)(?:3[47])[0-9]*\z/,
|
|
14
|
+
regexp_cvv: /\A\d{4}\z/,
|
|
15
|
+
},
|
|
16
|
+
{
|
|
17
|
+
name: "diners",
|
|
18
|
+
priority_over: [],
|
|
19
|
+
regexp_bin: /\A(3(?:0[0-5]|[68][0-9]))/,
|
|
20
|
+
regexp_full: /\A(?=.{14}$)(?:3(?:0[0-5]|[68][0-9]))[0-9]*\z/,
|
|
21
|
+
regexp_cvv: /\A\d{3}\z/,
|
|
22
|
+
},
|
|
23
|
+
{
|
|
24
|
+
name: "elo",
|
|
25
|
+
priority_over: ["visa", "aura", "discover", "banesecard"],
|
|
26
|
+
regexp_bin: /\A(401178|401179|431274|438935|451416|457393|457631|457632|504175|627780|636297|636368|(506699|5067[0-6]\d|50677[0-8])|(50900\d|5090[1-9]\d|509[1-9]\d{2})|65003[1-3]|(65003[5-9]|65004\d|65005[0-1])|(65040[5-9]|6504[1-3]\d)|(65048[5-9]|65049\d|6505[0-2]\d|65053[0-8])|(65054[1-9]|6505[5-8]\d|65059[0-8])|(65070\d|65071[0-8])|6507(2[0-7])|6509[0-9]|(65165[2-9]|6516[6-7]\d)|(65500\d|65501\d)|(65502[1-9]|6550[3-4]\d|65505[0-8]))/,
|
|
27
|
+
regexp_full: /\A(?=.{16}$)(?:401178|401179|431274|438935|451416|457393|457631|457632|504175|627780|636297|636368|(506699|5067[0-6]\d|50677[0-8])|(50900\d|5090[1-9]\d|509[1-9]\d{2})|65003[1-3]|(65003[5-9]|65004\d|65005[0-1])|(65040[5-9]|6504[1-3]\d)|(65048[5-9]|65049\d|6505[0-2]\d|65053[0-8])|(65054[1-9]|6505[5-8]\d|65059[0-8])|(65070\d|65071[0-8])|6507(2[0-7])|6509[0-9]|(65165[2-9]|6516[6-7]\d)|(65500\d|65501\d)|(65502[1-9]|6550[3-4]\d|65505[0-8]))[0-9]*\z/,
|
|
28
|
+
regexp_cvv: /\A\d{3}\z/,
|
|
29
|
+
},
|
|
30
|
+
{
|
|
31
|
+
name: "jcb",
|
|
32
|
+
priority_over: [],
|
|
33
|
+
regexp_bin: /\A((?:2131|1800|35))/,
|
|
34
|
+
regexp_full: /\A(?=.{16}$)(?:(?:2131|1800|35))[0-9]*\z/,
|
|
35
|
+
regexp_cvv: /\A\d{3}\z/,
|
|
36
|
+
},
|
|
37
|
+
{
|
|
38
|
+
name: "mastercard",
|
|
39
|
+
priority_over: [],
|
|
40
|
+
regexp_bin: /\A(5[1-5]|2[2-7][0-2][0-9])/,
|
|
41
|
+
regexp_full: /\A(?=.{16}$)(?:5[1-5]|2[2-7][0-2][0-9])[0-9]*\z/,
|
|
42
|
+
regexp_cvv: /\A\d{3}\z/,
|
|
43
|
+
},
|
|
44
|
+
{
|
|
45
|
+
name: "aura",
|
|
46
|
+
priority_over: [],
|
|
47
|
+
regexp_bin: /\A(50)/,
|
|
48
|
+
regexp_full: /\A(?=.{16,19}$)(?:50)[0-9]*\z/,
|
|
49
|
+
regexp_cvv: /\A\d{3}\z/,
|
|
50
|
+
},
|
|
51
|
+
{
|
|
52
|
+
name: "banesecard",
|
|
53
|
+
priority_over: ["discover"],
|
|
54
|
+
regexp_bin: /\A(636117|637473|637470|637472|650725|650046|650591|651668|651679)/,
|
|
55
|
+
regexp_full: /\A(?=.{16}$)(?:636117|637473|637470|637472|650725|650046|650591|651668|651679)[0-9]*\z/,
|
|
56
|
+
regexp_cvv: /\A\d{3}\z/,
|
|
57
|
+
},
|
|
58
|
+
{
|
|
59
|
+
name: "visa",
|
|
60
|
+
priority_over: [],
|
|
61
|
+
regexp_bin: /\A(4|6367)/,
|
|
62
|
+
regexp_full: /\A(?=.{13,16}$)(?:4|6367)[0-9]*\z/,
|
|
63
|
+
regexp_cvv: /\A\d{3}\z/,
|
|
64
|
+
},
|
|
65
|
+
{
|
|
66
|
+
name: "discover",
|
|
67
|
+
priority_over: ["hipercard"],
|
|
68
|
+
regexp_bin: /\A(6011|622|64|65)/,
|
|
69
|
+
regexp_full: /\A(?=.{16}$)(?:6011|622|64|65)[0-9]*\z/,
|
|
70
|
+
regexp_cvv: /\A\d{4}\z/,
|
|
71
|
+
},
|
|
72
|
+
{
|
|
73
|
+
name: "hipercard",
|
|
74
|
+
priority_over: [],
|
|
75
|
+
regexp_bin: /\A(38|60)/,
|
|
76
|
+
regexp_full: /\A(?=.{16,19}$)(?:38|60)[0-9]*\z/,
|
|
77
|
+
regexp_cvv: /\A\d{3}\z/,
|
|
78
|
+
},
|
|
79
|
+
].freeze
|
|
80
|
+
end
|
|
@@ -0,0 +1,524 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
# Auto-generated by bin-cc build - DO NOT EDIT
|
|
4
|
+
# Generated: 2026-01-11T20:12:36.612Z
|
|
5
|
+
|
|
6
|
+
module CreditcardIdentifier
|
|
7
|
+
# Credit card brand data (detailed)
|
|
8
|
+
BRANDS_DETAILED = [
|
|
9
|
+
{
|
|
10
|
+
scheme: "amex",
|
|
11
|
+
brand: "American Express",
|
|
12
|
+
type: "credit",
|
|
13
|
+
number: {
|
|
14
|
+
lengths: [15],
|
|
15
|
+
luhn: true
|
|
16
|
+
},
|
|
17
|
+
cvv: {
|
|
18
|
+
length: 4
|
|
19
|
+
},
|
|
20
|
+
patterns: [
|
|
21
|
+
{
|
|
22
|
+
bin: "^3[47]",
|
|
23
|
+
length: [15],
|
|
24
|
+
luhn: true,
|
|
25
|
+
cvv_length: 4
|
|
26
|
+
},
|
|
27
|
+
],
|
|
28
|
+
countries: ["GLOBAL"],
|
|
29
|
+
metadata: { "sourceFile" => "amex.json" },
|
|
30
|
+
priority_over: [],
|
|
31
|
+
bins: []
|
|
32
|
+
},
|
|
33
|
+
{
|
|
34
|
+
scheme: "diners",
|
|
35
|
+
brand: "Diners Club",
|
|
36
|
+
type: "credit",
|
|
37
|
+
number: {
|
|
38
|
+
lengths: [14],
|
|
39
|
+
luhn: true
|
|
40
|
+
},
|
|
41
|
+
cvv: {
|
|
42
|
+
length: 3
|
|
43
|
+
},
|
|
44
|
+
patterns: [
|
|
45
|
+
{
|
|
46
|
+
bin: "^3(?:0[0-5]|[68][0-9])",
|
|
47
|
+
length: [14],
|
|
48
|
+
luhn: true,
|
|
49
|
+
cvv_length: 3
|
|
50
|
+
},
|
|
51
|
+
],
|
|
52
|
+
countries: ["GLOBAL"],
|
|
53
|
+
metadata: { "sourceFile" => "diners.json" },
|
|
54
|
+
priority_over: [],
|
|
55
|
+
bins: []
|
|
56
|
+
},
|
|
57
|
+
{
|
|
58
|
+
scheme: "elo",
|
|
59
|
+
brand: "Elo",
|
|
60
|
+
type: "credit",
|
|
61
|
+
number: {
|
|
62
|
+
lengths: [16],
|
|
63
|
+
luhn: true
|
|
64
|
+
},
|
|
65
|
+
cvv: {
|
|
66
|
+
length: 3
|
|
67
|
+
},
|
|
68
|
+
patterns: [
|
|
69
|
+
{
|
|
70
|
+
bin: "^401178|^401179|^431274|^438935|^451416|^457393|^457631|^457632|^504175",
|
|
71
|
+
length: [16],
|
|
72
|
+
luhn: true,
|
|
73
|
+
cvv_length: 3
|
|
74
|
+
},
|
|
75
|
+
{
|
|
76
|
+
bin: "^627780|^636297|^636368",
|
|
77
|
+
length: [16],
|
|
78
|
+
luhn: true,
|
|
79
|
+
cvv_length: 3
|
|
80
|
+
},
|
|
81
|
+
{
|
|
82
|
+
bin: "^(506699|5067[0-6]\\d|50677[0-8])",
|
|
83
|
+
length: [16],
|
|
84
|
+
luhn: true,
|
|
85
|
+
cvv_length: 3
|
|
86
|
+
},
|
|
87
|
+
{
|
|
88
|
+
bin: "^(50900\\d|5090[1-9]\\d|509[1-9]\\d{2})",
|
|
89
|
+
length: [16],
|
|
90
|
+
luhn: true,
|
|
91
|
+
cvv_length: 3
|
|
92
|
+
},
|
|
93
|
+
{
|
|
94
|
+
bin: "^65003[1-3]",
|
|
95
|
+
length: [16],
|
|
96
|
+
luhn: true,
|
|
97
|
+
cvv_length: 3
|
|
98
|
+
},
|
|
99
|
+
{
|
|
100
|
+
bin: "^(65003[5-9]|65004\\d|65005[0-1])",
|
|
101
|
+
length: [16],
|
|
102
|
+
luhn: true,
|
|
103
|
+
cvv_length: 3
|
|
104
|
+
},
|
|
105
|
+
{
|
|
106
|
+
bin: "^(65040[5-9]|6504[1-3]\\d)",
|
|
107
|
+
length: [16],
|
|
108
|
+
luhn: true,
|
|
109
|
+
cvv_length: 3
|
|
110
|
+
},
|
|
111
|
+
{
|
|
112
|
+
bin: "^(65048[5-9]|65049\\d|6505[0-2]\\d|65053[0-8])",
|
|
113
|
+
length: [16],
|
|
114
|
+
luhn: true,
|
|
115
|
+
cvv_length: 3
|
|
116
|
+
},
|
|
117
|
+
{
|
|
118
|
+
bin: "^(65054[1-9]|6505[5-8]\\d|65059[0-8])",
|
|
119
|
+
length: [16],
|
|
120
|
+
luhn: true,
|
|
121
|
+
cvv_length: 3
|
|
122
|
+
},
|
|
123
|
+
{
|
|
124
|
+
bin: "^(65070\\d|65071[0-8])",
|
|
125
|
+
length: [16],
|
|
126
|
+
luhn: true,
|
|
127
|
+
cvv_length: 3
|
|
128
|
+
},
|
|
129
|
+
{
|
|
130
|
+
bin: "^6507(2[0-7])",
|
|
131
|
+
length: [16],
|
|
132
|
+
luhn: true,
|
|
133
|
+
cvv_length: 3
|
|
134
|
+
},
|
|
135
|
+
{
|
|
136
|
+
bin: "^6509[0-9]",
|
|
137
|
+
length: [16],
|
|
138
|
+
luhn: true,
|
|
139
|
+
cvv_length: 3
|
|
140
|
+
},
|
|
141
|
+
{
|
|
142
|
+
bin: "^(65165[2-9]|6516[6-7]\\d)",
|
|
143
|
+
length: [16],
|
|
144
|
+
luhn: true,
|
|
145
|
+
cvv_length: 3
|
|
146
|
+
},
|
|
147
|
+
{
|
|
148
|
+
bin: "^(65500\\d|65501\\d)",
|
|
149
|
+
length: [16],
|
|
150
|
+
luhn: true,
|
|
151
|
+
cvv_length: 3
|
|
152
|
+
},
|
|
153
|
+
{
|
|
154
|
+
bin: "^(65502[1-9]|6550[3-4]\\d|65505[0-8])",
|
|
155
|
+
length: [16],
|
|
156
|
+
luhn: true,
|
|
157
|
+
cvv_length: 3
|
|
158
|
+
},
|
|
159
|
+
],
|
|
160
|
+
countries: ["BR"],
|
|
161
|
+
metadata: { "sourceFile" => "elo.json" },
|
|
162
|
+
priority_over: ["visa", "aura", "discover", "banesecard"],
|
|
163
|
+
bins: []
|
|
164
|
+
},
|
|
165
|
+
{
|
|
166
|
+
scheme: "jcb",
|
|
167
|
+
brand: "JCB",
|
|
168
|
+
type: "credit",
|
|
169
|
+
number: {
|
|
170
|
+
lengths: [16],
|
|
171
|
+
luhn: true
|
|
172
|
+
},
|
|
173
|
+
cvv: {
|
|
174
|
+
length: 3
|
|
175
|
+
},
|
|
176
|
+
patterns: [
|
|
177
|
+
{
|
|
178
|
+
bin: "^(?:2131|1800|35)",
|
|
179
|
+
length: [16],
|
|
180
|
+
luhn: true,
|
|
181
|
+
cvv_length: 3
|
|
182
|
+
},
|
|
183
|
+
],
|
|
184
|
+
countries: ["GLOBAL"],
|
|
185
|
+
metadata: { "sourceFile" => "jcb.json" },
|
|
186
|
+
priority_over: [],
|
|
187
|
+
bins: []
|
|
188
|
+
},
|
|
189
|
+
{
|
|
190
|
+
scheme: "mastercard",
|
|
191
|
+
brand: "Mastercard",
|
|
192
|
+
type: "credit",
|
|
193
|
+
number: {
|
|
194
|
+
lengths: [16],
|
|
195
|
+
luhn: true
|
|
196
|
+
},
|
|
197
|
+
cvv: {
|
|
198
|
+
length: 3
|
|
199
|
+
},
|
|
200
|
+
patterns: [
|
|
201
|
+
{
|
|
202
|
+
bin: "^5[1-5]",
|
|
203
|
+
length: [16],
|
|
204
|
+
luhn: true,
|
|
205
|
+
cvv_length: 3
|
|
206
|
+
},
|
|
207
|
+
{
|
|
208
|
+
bin: "^2[2-7][0-2][0-9]",
|
|
209
|
+
length: [16],
|
|
210
|
+
luhn: true,
|
|
211
|
+
cvv_length: 3
|
|
212
|
+
},
|
|
213
|
+
],
|
|
214
|
+
countries: ["GLOBAL"],
|
|
215
|
+
metadata: { "sourceFile" => "mastercard.json" },
|
|
216
|
+
priority_over: [],
|
|
217
|
+
bins: []
|
|
218
|
+
},
|
|
219
|
+
{
|
|
220
|
+
scheme: "aura",
|
|
221
|
+
brand: "Aura",
|
|
222
|
+
type: "credit",
|
|
223
|
+
number: {
|
|
224
|
+
lengths: [16, 17, 18, 19],
|
|
225
|
+
luhn: true
|
|
226
|
+
},
|
|
227
|
+
cvv: {
|
|
228
|
+
length: 3
|
|
229
|
+
},
|
|
230
|
+
patterns: [
|
|
231
|
+
{
|
|
232
|
+
bin: "^50",
|
|
233
|
+
length: [16, 17, 18, 19],
|
|
234
|
+
luhn: true,
|
|
235
|
+
cvv_length: 3
|
|
236
|
+
},
|
|
237
|
+
],
|
|
238
|
+
countries: ["BR"],
|
|
239
|
+
metadata: { "sourceFile" => "aura.json" },
|
|
240
|
+
priority_over: [],
|
|
241
|
+
bins: []
|
|
242
|
+
},
|
|
243
|
+
{
|
|
244
|
+
scheme: "banesecard",
|
|
245
|
+
brand: "BaneseCard",
|
|
246
|
+
type: "credit",
|
|
247
|
+
number: {
|
|
248
|
+
lengths: [16],
|
|
249
|
+
luhn: true
|
|
250
|
+
},
|
|
251
|
+
cvv: {
|
|
252
|
+
length: 3
|
|
253
|
+
},
|
|
254
|
+
patterns: [
|
|
255
|
+
{
|
|
256
|
+
bin: "^636117",
|
|
257
|
+
length: [16],
|
|
258
|
+
luhn: true,
|
|
259
|
+
cvv_length: 3
|
|
260
|
+
},
|
|
261
|
+
{
|
|
262
|
+
bin: "^637473",
|
|
263
|
+
length: [16],
|
|
264
|
+
luhn: true,
|
|
265
|
+
cvv_length: 3
|
|
266
|
+
},
|
|
267
|
+
{
|
|
268
|
+
bin: "^637470",
|
|
269
|
+
length: [16],
|
|
270
|
+
luhn: true,
|
|
271
|
+
cvv_length: 3
|
|
272
|
+
},
|
|
273
|
+
{
|
|
274
|
+
bin: "^637472",
|
|
275
|
+
length: [16],
|
|
276
|
+
luhn: true,
|
|
277
|
+
cvv_length: 3
|
|
278
|
+
},
|
|
279
|
+
{
|
|
280
|
+
bin: "^650725",
|
|
281
|
+
length: [16],
|
|
282
|
+
luhn: true,
|
|
283
|
+
cvv_length: 3
|
|
284
|
+
},
|
|
285
|
+
{
|
|
286
|
+
bin: "^650046",
|
|
287
|
+
length: [16],
|
|
288
|
+
luhn: true,
|
|
289
|
+
cvv_length: 3
|
|
290
|
+
},
|
|
291
|
+
{
|
|
292
|
+
bin: "^650591",
|
|
293
|
+
length: [16],
|
|
294
|
+
luhn: true,
|
|
295
|
+
cvv_length: 3
|
|
296
|
+
},
|
|
297
|
+
{
|
|
298
|
+
bin: "^651668",
|
|
299
|
+
length: [16],
|
|
300
|
+
luhn: true,
|
|
301
|
+
cvv_length: 3
|
|
302
|
+
},
|
|
303
|
+
{
|
|
304
|
+
bin: "^651679",
|
|
305
|
+
length: [16],
|
|
306
|
+
luhn: true,
|
|
307
|
+
cvv_length: 3
|
|
308
|
+
},
|
|
309
|
+
],
|
|
310
|
+
countries: ["BR"],
|
|
311
|
+
metadata: { "sourceFile" => "banesecard.json" },
|
|
312
|
+
priority_over: ["discover"],
|
|
313
|
+
bins: []
|
|
314
|
+
},
|
|
315
|
+
{
|
|
316
|
+
scheme: "visa",
|
|
317
|
+
brand: "Visa",
|
|
318
|
+
type: "credit",
|
|
319
|
+
number: {
|
|
320
|
+
lengths: [13, 16],
|
|
321
|
+
luhn: true
|
|
322
|
+
},
|
|
323
|
+
cvv: {
|
|
324
|
+
length: 3
|
|
325
|
+
},
|
|
326
|
+
patterns: [
|
|
327
|
+
{
|
|
328
|
+
bin: "^4",
|
|
329
|
+
length: [13, 16],
|
|
330
|
+
luhn: true,
|
|
331
|
+
cvv_length: 3
|
|
332
|
+
},
|
|
333
|
+
{
|
|
334
|
+
bin: "^6367",
|
|
335
|
+
length: [16],
|
|
336
|
+
luhn: true,
|
|
337
|
+
cvv_length: 3
|
|
338
|
+
},
|
|
339
|
+
],
|
|
340
|
+
countries: ["GLOBAL"],
|
|
341
|
+
metadata: { "sourceFile" => ["visa/base.json", "visa/bins-br-1.json", "visa/bins-br-2.json"] },
|
|
342
|
+
priority_over: [],
|
|
343
|
+
bins: [
|
|
344
|
+
{
|
|
345
|
+
bin: "491441",
|
|
346
|
+
type: "CREDIT",
|
|
347
|
+
category: nil,
|
|
348
|
+
issuer: "BANCO PROSPER, S.A.",
|
|
349
|
+
countries: ["BR"]
|
|
350
|
+
},
|
|
351
|
+
{
|
|
352
|
+
bin: "491440",
|
|
353
|
+
type: "CREDIT",
|
|
354
|
+
category: nil,
|
|
355
|
+
issuer: "BANCO PROSPER, S.A.",
|
|
356
|
+
countries: ["BR"]
|
|
357
|
+
},
|
|
358
|
+
{
|
|
359
|
+
bin: "491439",
|
|
360
|
+
type: "CREDIT",
|
|
361
|
+
category: nil,
|
|
362
|
+
issuer: "BANCO PROSPER, S.A.",
|
|
363
|
+
countries: ["BR"]
|
|
364
|
+
},
|
|
365
|
+
{
|
|
366
|
+
bin: "491423",
|
|
367
|
+
type: "CREDIT",
|
|
368
|
+
category: nil,
|
|
369
|
+
issuer: "BANCO DO ESTADO DO RIO GRANDE DO SUL S.A. (BANRISUL S.A.)",
|
|
370
|
+
countries: ["BR"]
|
|
371
|
+
},
|
|
372
|
+
{
|
|
373
|
+
bin: "491416",
|
|
374
|
+
type: "CREDIT",
|
|
375
|
+
category: "CLASSIC",
|
|
376
|
+
issuer: "BANCO DO ESTADO DO PARANA",
|
|
377
|
+
countries: ["BR"]
|
|
378
|
+
},
|
|
379
|
+
{
|
|
380
|
+
bin: "491415",
|
|
381
|
+
type: "CREDIT",
|
|
382
|
+
category: "CLASSIC",
|
|
383
|
+
issuer: "BANCO DO ESTADO DO PARANA",
|
|
384
|
+
countries: ["BR"]
|
|
385
|
+
},
|
|
386
|
+
{
|
|
387
|
+
bin: "491414",
|
|
388
|
+
type: "CREDIT",
|
|
389
|
+
category: "GOLD",
|
|
390
|
+
issuer: "BANCO DO ESTADO DO PARANA",
|
|
391
|
+
countries: ["BR"]
|
|
392
|
+
},
|
|
393
|
+
{
|
|
394
|
+
bin: "491413",
|
|
395
|
+
type: "CREDIT",
|
|
396
|
+
category: "CLASSIC",
|
|
397
|
+
issuer: "BANCO DO ESTADO DO RIO GRANDE DO SUL S/A",
|
|
398
|
+
countries: ["BR"]
|
|
399
|
+
},
|
|
400
|
+
{
|
|
401
|
+
bin: "491412",
|
|
402
|
+
type: "CREDIT",
|
|
403
|
+
category: "CLASSIC",
|
|
404
|
+
issuer: "BANCO DO ESTADO DO RIO GRANDE DO SUL S/A",
|
|
405
|
+
countries: []
|
|
406
|
+
},
|
|
407
|
+
{
|
|
408
|
+
bin: "491411",
|
|
409
|
+
type: "CREDIT",
|
|
410
|
+
category: "GOLD",
|
|
411
|
+
issuer: "BANCO DO ESTADO DO RIO GRANDE DO SUL S/A",
|
|
412
|
+
countries: []
|
|
413
|
+
},
|
|
414
|
+
{
|
|
415
|
+
bin: "491402",
|
|
416
|
+
type: "CREDIT",
|
|
417
|
+
category: nil,
|
|
418
|
+
issuer: "BANCO DO ESTADO DO RIO GRANDE DO SUL S.A. (BANRISUL S.A.)",
|
|
419
|
+
countries: []
|
|
420
|
+
},
|
|
421
|
+
{
|
|
422
|
+
bin: "491316",
|
|
423
|
+
type: "CREDIT",
|
|
424
|
+
category: "CLASSIC",
|
|
425
|
+
issuer: "BANCO SANTANDER BRASIL, S.A.",
|
|
426
|
+
countries: []
|
|
427
|
+
},
|
|
428
|
+
{
|
|
429
|
+
bin: "491315",
|
|
430
|
+
type: "CREDIT",
|
|
431
|
+
category: "CLASSIC",
|
|
432
|
+
issuer: "BANCO SANTANDER, S.A.",
|
|
433
|
+
countries: []
|
|
434
|
+
},
|
|
435
|
+
{
|
|
436
|
+
bin: "491314",
|
|
437
|
+
type: "CREDIT",
|
|
438
|
+
category: "GOLD",
|
|
439
|
+
issuer: "BANCO SANTANDER, S.A.",
|
|
440
|
+
countries: []
|
|
441
|
+
},
|
|
442
|
+
{
|
|
443
|
+
bin: "491256",
|
|
444
|
+
type: "CREDIT",
|
|
445
|
+
category: "PLATINUM",
|
|
446
|
+
issuer: "BANCO PANAMERICANO, S.A.",
|
|
447
|
+
countries: []
|
|
448
|
+
},
|
|
449
|
+
]
|
|
450
|
+
},
|
|
451
|
+
{
|
|
452
|
+
scheme: "discover",
|
|
453
|
+
brand: "Discover",
|
|
454
|
+
type: "credit",
|
|
455
|
+
number: {
|
|
456
|
+
lengths: [16],
|
|
457
|
+
luhn: true
|
|
458
|
+
},
|
|
459
|
+
cvv: {
|
|
460
|
+
length: 4
|
|
461
|
+
},
|
|
462
|
+
patterns: [
|
|
463
|
+
{
|
|
464
|
+
bin: "^6011",
|
|
465
|
+
length: [16],
|
|
466
|
+
luhn: true,
|
|
467
|
+
cvv_length: 4
|
|
468
|
+
},
|
|
469
|
+
{
|
|
470
|
+
bin: "^622",
|
|
471
|
+
length: [16],
|
|
472
|
+
luhn: true,
|
|
473
|
+
cvv_length: 4
|
|
474
|
+
},
|
|
475
|
+
{
|
|
476
|
+
bin: "^64",
|
|
477
|
+
length: [16],
|
|
478
|
+
luhn: true,
|
|
479
|
+
cvv_length: 4
|
|
480
|
+
},
|
|
481
|
+
{
|
|
482
|
+
bin: "^65",
|
|
483
|
+
length: [16],
|
|
484
|
+
luhn: true,
|
|
485
|
+
cvv_length: 4
|
|
486
|
+
},
|
|
487
|
+
],
|
|
488
|
+
countries: ["US"],
|
|
489
|
+
metadata: { "sourceFile" => "discover.json" },
|
|
490
|
+
priority_over: ["hipercard"],
|
|
491
|
+
bins: []
|
|
492
|
+
},
|
|
493
|
+
{
|
|
494
|
+
scheme: "hipercard",
|
|
495
|
+
brand: "Hipercard",
|
|
496
|
+
type: "credit",
|
|
497
|
+
number: {
|
|
498
|
+
lengths: [16, 19],
|
|
499
|
+
luhn: true
|
|
500
|
+
},
|
|
501
|
+
cvv: {
|
|
502
|
+
length: 3
|
|
503
|
+
},
|
|
504
|
+
patterns: [
|
|
505
|
+
{
|
|
506
|
+
bin: "^38",
|
|
507
|
+
length: [19],
|
|
508
|
+
luhn: true,
|
|
509
|
+
cvv_length: 3
|
|
510
|
+
},
|
|
511
|
+
{
|
|
512
|
+
bin: "^60",
|
|
513
|
+
length: [16],
|
|
514
|
+
luhn: true,
|
|
515
|
+
cvv_length: 3
|
|
516
|
+
},
|
|
517
|
+
],
|
|
518
|
+
countries: ["BR"],
|
|
519
|
+
metadata: { "sourceFile" => "hipercard.json" },
|
|
520
|
+
priority_over: [],
|
|
521
|
+
bins: []
|
|
522
|
+
},
|
|
523
|
+
].freeze
|
|
524
|
+
end
|
|
@@ -0,0 +1,192 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require_relative 'creditcard_identifier/brands'
|
|
4
|
+
require_relative 'creditcard_identifier/brands_detailed'
|
|
5
|
+
|
|
6
|
+
##
|
|
7
|
+
# Credit Card BIN Validator
|
|
8
|
+
#
|
|
9
|
+
# This module provides credit card validation using bin-cc data.
|
|
10
|
+
module CreditcardIdentifier
|
|
11
|
+
VERSION = '2.0.0'
|
|
12
|
+
|
|
13
|
+
##
|
|
14
|
+
# Credit card validator using bin-cc data.
|
|
15
|
+
class Validator
|
|
16
|
+
attr_reader :brands, :brands_detailed
|
|
17
|
+
|
|
18
|
+
##
|
|
19
|
+
# Initialize validator with brand data
|
|
20
|
+
def initialize
|
|
21
|
+
@brands = BRANDS
|
|
22
|
+
@brands_detailed = BRANDS_DETAILED
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
##
|
|
26
|
+
# Identify the credit card brand
|
|
27
|
+
#
|
|
28
|
+
# @param card_number [String] Credit card number
|
|
29
|
+
# @param detailed [Boolean] If true, returns detailed brand info
|
|
30
|
+
# @return [Hash, nil] Brand hash or nil if not found
|
|
31
|
+
def find_brand(card_number, detailed: false)
|
|
32
|
+
return nil if card_number.nil? || card_number.empty?
|
|
33
|
+
|
|
34
|
+
brand = @brands.find do |b|
|
|
35
|
+
b[:regexp_full].match?(card_number)
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
return nil unless brand
|
|
39
|
+
|
|
40
|
+
if detailed
|
|
41
|
+
detailed_brand = @brands_detailed.find { |b| b[:scheme] == brand[:name] }
|
|
42
|
+
if detailed_brand
|
|
43
|
+
# Find the specific pattern that matched
|
|
44
|
+
matched_pattern = detailed_brand[:patterns]&.find do |p|
|
|
45
|
+
Regexp.new(p[:bin]).match?(card_number)
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
# Find the specific bin that matched (if bins exist)
|
|
49
|
+
bin_prefix = card_number[0, 6]
|
|
50
|
+
matched_bin = detailed_brand[:bins]&.find do |b|
|
|
51
|
+
bin_prefix.start_with?(b[:bin]) || b[:bin] == bin_prefix
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
# Return without the full bins array
|
|
55
|
+
result = detailed_brand.reject { |k, _| k == :bins }
|
|
56
|
+
result[:matched_pattern] = matched_pattern
|
|
57
|
+
result[:matched_bin] = matched_bin
|
|
58
|
+
return result
|
|
59
|
+
end
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
brand
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
##
|
|
66
|
+
# Check if card number is supported
|
|
67
|
+
#
|
|
68
|
+
# @param card_number [String] Credit card number
|
|
69
|
+
# @return [Boolean] true if supported, false otherwise
|
|
70
|
+
def supported?(card_number)
|
|
71
|
+
!find_brand(card_number).nil?
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
##
|
|
75
|
+
# Validate CVV for a specific brand
|
|
76
|
+
#
|
|
77
|
+
# @param cvv [String] CVV code
|
|
78
|
+
# @param brand_or_name [String, Hash] Brand name or brand object from find_brand
|
|
79
|
+
# @return [Boolean] true if valid, false otherwise
|
|
80
|
+
def validate_cvv(cvv, brand_or_name)
|
|
81
|
+
return false if cvv.nil? || cvv.empty?
|
|
82
|
+
|
|
83
|
+
# Handle brand object (Hash)
|
|
84
|
+
if brand_or_name.is_a?(Hash)
|
|
85
|
+
# Handle detailed brand object
|
|
86
|
+
if brand_or_name[:cvv] && brand_or_name[:cvv][:length]
|
|
87
|
+
expected_length = brand_or_name[:cvv][:length]
|
|
88
|
+
return cvv.match?(/^\d{#{expected_length}}$/)
|
|
89
|
+
end
|
|
90
|
+
# Handle simplified brand object
|
|
91
|
+
if brand_or_name[:regexp_cvv]
|
|
92
|
+
return brand_or_name[:regexp_cvv].match?(cvv)
|
|
93
|
+
end
|
|
94
|
+
# Handle brand name from object
|
|
95
|
+
brand_name = brand_or_name[:name] || brand_or_name[:scheme]
|
|
96
|
+
if brand_name
|
|
97
|
+
brand = @brands.find { |b| b[:name] == brand_name }
|
|
98
|
+
return brand&.dig(:regexp_cvv)&.match?(cvv) || false
|
|
99
|
+
end
|
|
100
|
+
return false
|
|
101
|
+
end
|
|
102
|
+
|
|
103
|
+
# Handle brand name (String)
|
|
104
|
+
brand = @brands.find { |b| b[:name] == brand_or_name }
|
|
105
|
+
return false if brand.nil?
|
|
106
|
+
|
|
107
|
+
brand[:regexp_cvv].match?(cvv)
|
|
108
|
+
end
|
|
109
|
+
|
|
110
|
+
##
|
|
111
|
+
# Get information about a specific brand
|
|
112
|
+
#
|
|
113
|
+
# @param brand_name [String] Brand name (e.g., 'visa', 'mastercard')
|
|
114
|
+
# @return [Hash, nil] Brand hash or nil if not found
|
|
115
|
+
def get_brand_info(brand_name)
|
|
116
|
+
@brands.find { |b| b[:name] == brand_name }
|
|
117
|
+
end
|
|
118
|
+
|
|
119
|
+
##
|
|
120
|
+
# Get detailed information about a specific brand
|
|
121
|
+
#
|
|
122
|
+
# @param scheme [String] Scheme name (e.g., 'visa', 'mastercard')
|
|
123
|
+
# @return [Hash, nil] Detailed brand hash or nil if not found
|
|
124
|
+
def get_brand_info_detailed(scheme)
|
|
125
|
+
@brands_detailed.find { |b| b[:scheme] == scheme }
|
|
126
|
+
end
|
|
127
|
+
|
|
128
|
+
##
|
|
129
|
+
# List all supported brands
|
|
130
|
+
#
|
|
131
|
+
# @return [Array<String>] List of brand names
|
|
132
|
+
def list_brands
|
|
133
|
+
@brands.map { |b| b[:name] }
|
|
134
|
+
end
|
|
135
|
+
end
|
|
136
|
+
|
|
137
|
+
# Module-level convenience methods
|
|
138
|
+
class << self
|
|
139
|
+
##
|
|
140
|
+
# Get or create the singleton validator instance
|
|
141
|
+
#
|
|
142
|
+
# @return [Validator] The validator instance
|
|
143
|
+
def validator
|
|
144
|
+
@validator ||= Validator.new
|
|
145
|
+
end
|
|
146
|
+
|
|
147
|
+
##
|
|
148
|
+
# Get all brand data
|
|
149
|
+
#
|
|
150
|
+
# @return [Array<Hash>] List of brand hashes
|
|
151
|
+
def brands
|
|
152
|
+
BRANDS
|
|
153
|
+
end
|
|
154
|
+
|
|
155
|
+
##
|
|
156
|
+
# Get all detailed brand data
|
|
157
|
+
#
|
|
158
|
+
# @return [Array<Hash>] List of detailed brand hashes
|
|
159
|
+
def brands_detailed
|
|
160
|
+
BRANDS_DETAILED
|
|
161
|
+
end
|
|
162
|
+
|
|
163
|
+
##
|
|
164
|
+
# Identify the credit card brand
|
|
165
|
+
#
|
|
166
|
+
# @param card_number [String] Credit card number
|
|
167
|
+
# @param detailed [Boolean] If true, returns detailed brand info
|
|
168
|
+
# @return [Hash, nil] Brand hash or nil if not found
|
|
169
|
+
def find_brand(card_number, detailed: false)
|
|
170
|
+
validator.find_brand(card_number, detailed: detailed)
|
|
171
|
+
end
|
|
172
|
+
|
|
173
|
+
##
|
|
174
|
+
# Check if card number is supported
|
|
175
|
+
#
|
|
176
|
+
# @param card_number [String] Credit card number
|
|
177
|
+
# @return [Boolean] true if supported, false otherwise
|
|
178
|
+
def supported?(card_number)
|
|
179
|
+
validator.supported?(card_number)
|
|
180
|
+
end
|
|
181
|
+
|
|
182
|
+
##
|
|
183
|
+
# Validate CVV for a specific brand
|
|
184
|
+
#
|
|
185
|
+
# @param cvv [String] CVV code
|
|
186
|
+
# @param brand_or_name [String, Hash] Brand name or brand object
|
|
187
|
+
# @return [Boolean] true if valid, false otherwise
|
|
188
|
+
def validate_cvv(cvv, brand_or_name)
|
|
189
|
+
validator.validate_cvv(cvv, brand_or_name)
|
|
190
|
+
end
|
|
191
|
+
end
|
|
192
|
+
end
|
metadata
ADDED
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
|
2
|
+
name: creditcard-identifier
|
|
3
|
+
version: !ruby/object:Gem::Version
|
|
4
|
+
version: 2.0.0
|
|
5
|
+
platform: ruby
|
|
6
|
+
authors:
|
|
7
|
+
- Renato Viço
|
|
8
|
+
autorequire:
|
|
9
|
+
bindir: bin
|
|
10
|
+
cert_chain: []
|
|
11
|
+
date: 2026-01-11 00:00:00.000000000 Z
|
|
12
|
+
dependencies:
|
|
13
|
+
- !ruby/object:Gem::Dependency
|
|
14
|
+
name: minitest
|
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
|
16
|
+
requirements:
|
|
17
|
+
- - "~>"
|
|
18
|
+
- !ruby/object:Gem::Version
|
|
19
|
+
version: '5.0'
|
|
20
|
+
type: :development
|
|
21
|
+
prerelease: false
|
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
23
|
+
requirements:
|
|
24
|
+
- - "~>"
|
|
25
|
+
- !ruby/object:Gem::Version
|
|
26
|
+
version: '5.0'
|
|
27
|
+
- !ruby/object:Gem::Dependency
|
|
28
|
+
name: rake
|
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
|
30
|
+
requirements:
|
|
31
|
+
- - "~>"
|
|
32
|
+
- !ruby/object:Gem::Version
|
|
33
|
+
version: '13.0'
|
|
34
|
+
type: :development
|
|
35
|
+
prerelease: false
|
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
37
|
+
requirements:
|
|
38
|
+
- - "~>"
|
|
39
|
+
- !ruby/object:Gem::Version
|
|
40
|
+
version: '13.0'
|
|
41
|
+
description: A Ruby library for credit card BIN validation and brand identification
|
|
42
|
+
email: []
|
|
43
|
+
executables: []
|
|
44
|
+
extensions: []
|
|
45
|
+
extra_rdoc_files: []
|
|
46
|
+
files:
|
|
47
|
+
- README.md
|
|
48
|
+
- lib/creditcard_identifier.rb
|
|
49
|
+
- lib/creditcard_identifier/brands.rb
|
|
50
|
+
- lib/creditcard_identifier/brands_detailed.rb
|
|
51
|
+
homepage: https://github.com/renatovico/bin-cc
|
|
52
|
+
licenses:
|
|
53
|
+
- MIT
|
|
54
|
+
metadata:
|
|
55
|
+
homepage_uri: https://github.com/renatovico/bin-cc
|
|
56
|
+
source_code_uri: https://github.com/renatovico/bin-cc
|
|
57
|
+
documentation_uri: https://github.com/renatovico/bin-cc/tree/master/libs/ruby
|
|
58
|
+
post_install_message:
|
|
59
|
+
rdoc_options: []
|
|
60
|
+
require_paths:
|
|
61
|
+
- lib
|
|
62
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
|
63
|
+
requirements:
|
|
64
|
+
- - ">="
|
|
65
|
+
- !ruby/object:Gem::Version
|
|
66
|
+
version: 2.5.0
|
|
67
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
68
|
+
requirements:
|
|
69
|
+
- - ">="
|
|
70
|
+
- !ruby/object:Gem::Version
|
|
71
|
+
version: '0'
|
|
72
|
+
requirements: []
|
|
73
|
+
rubygems_version: 3.5.22
|
|
74
|
+
signing_key:
|
|
75
|
+
specification_version: 4
|
|
76
|
+
summary: Credit card BIN validation using bin-cc data
|
|
77
|
+
test_files: []
|