credit_card_info 0.1.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 ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: 7e1751e3d0337ae28f147917b8091ea6a4413a8e5c8e4fc0f73cab67e717415f
4
+ data.tar.gz: ec9285e450f14ec6dea2141f8e5218ce46119acd1e23fe66ac9400cc18755d14
5
+ SHA512:
6
+ metadata.gz: 5dcabba34c37dc559488a2d8d24f1f91621fb89c044c0806efb82571ef12f926f48f83d843928b65728692c0256a1346c68e7ac97c98ae70f101f527041fd2c3
7
+ data.tar.gz: 3461a76e7c6d17574ad2765e7c196f9a1992fda4fc73e97ab0f804d06d075f703c09ccacea6c989a02e70230e0c1c6e23e2459288dda8da395e6edddbe40d6a8
data/CHANGELOG.md ADDED
@@ -0,0 +1,5 @@
1
+ ## [Unreleased]
2
+
3
+ ## [0.1.0] - 2022-03-11
4
+
5
+ - Initial release
data/Gemfile ADDED
@@ -0,0 +1,12 @@
1
+ # frozen_string_literal: true
2
+
3
+ source "https://rubygems.org"
4
+
5
+ # Specify your gem's dependencies in credit-card-info.gemspec
6
+ gemspec
7
+
8
+ group :development, :test do
9
+ gem "rake", "~> 13.0"
10
+ gem "rubocop", "~> 1.11.0"
11
+ gem "rubocop-performance", "~> 1.10"
12
+ end
data/Gemfile.lock ADDED
@@ -0,0 +1,53 @@
1
+ PATH
2
+ remote: .
3
+ specs:
4
+ credit_card_info (0.1.0)
5
+ credit_card_bins (~> 0.0.1)
6
+ dry-configurable (>= 0.13)
7
+
8
+ GEM
9
+ remote: https://rubygems.org/
10
+ specs:
11
+ ast (2.4.2)
12
+ concurrent-ruby (1.1.9)
13
+ credit_card_bins (0.0.3)
14
+ dry-configurable (0.14.0)
15
+ concurrent-ruby (~> 1.0)
16
+ dry-core (~> 0.6)
17
+ dry-core (0.7.1)
18
+ concurrent-ruby (~> 1.0)
19
+ parallel (1.21.0)
20
+ parser (3.1.1.0)
21
+ ast (~> 2.4.1)
22
+ rainbow (3.1.1)
23
+ rake (13.0.6)
24
+ regexp_parser (2.2.1)
25
+ rexml (3.2.5)
26
+ rubocop (1.11.0)
27
+ parallel (~> 1.10)
28
+ parser (>= 3.0.0.0)
29
+ rainbow (>= 2.2.2, < 4.0)
30
+ regexp_parser (>= 1.8, < 3.0)
31
+ rexml
32
+ rubocop-ast (>= 1.2.0, < 2.0)
33
+ ruby-progressbar (~> 1.7)
34
+ unicode-display_width (>= 1.4.0, < 3.0)
35
+ rubocop-ast (1.16.0)
36
+ parser (>= 3.1.1.0)
37
+ rubocop-performance (1.13.3)
38
+ rubocop (>= 1.7.0, < 2.0)
39
+ rubocop-ast (>= 0.4.0)
40
+ ruby-progressbar (1.11.0)
41
+ unicode-display_width (2.1.0)
42
+
43
+ PLATFORMS
44
+ x86_64-linux
45
+
46
+ DEPENDENCIES
47
+ credit_card_info!
48
+ rake (~> 13.0)
49
+ rubocop (~> 1.11.0)
50
+ rubocop-performance (~> 1.10)
51
+
52
+ BUNDLED WITH
53
+ 2.2.15
data/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright © 2022 credit_card_info
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,80 @@
1
+ # CreditCardInfo
2
+
3
+ The Issuer Identification Number (IIN), previously known as Bank Identification Number (BIN) is the first six numbers of a credit card.
4
+ These identify the institution that issued the card to the card holder and
5
+ provide useful information about the card that can help make your payments flow smarter.
6
+
7
+ Uses two data providers:
8
+ * First bincodes.com API (require registration and api key).
9
+ * Second 'credit_card_bins' gem data.
10
+
11
+
12
+ ## Installation
13
+
14
+ Add this line to your application's Gemfile:
15
+
16
+ ```ruby
17
+ gem 'credit_card_info'
18
+ ```
19
+
20
+ And then execute:
21
+
22
+ $ bundle install
23
+
24
+ Or install it yourself as:
25
+
26
+ $ gem install credit_card_info
27
+
28
+
29
+ ## Configuration
30
+
31
+ ```ruby
32
+ CreditCardInfo::Config.configure do |config|
33
+ config.bincodes.api_key = "your_api_key"
34
+ config.bincodes.api_url = "https://api.bincodes.com"
35
+
36
+ # class for make HttpRequests
37
+ config.bincodes.http_klass = Net::HTTP
38
+ # set timeout for api request (10 by default)
39
+ config.bincodes.timeout = 10
40
+
41
+
42
+ # set cache provider class, Rails.cache by default when using in Rails application
43
+ config.cache.provider = Rails.cache
44
+ # set cache keys lifeitime, default is 31 day
45
+ config.cache.ttl = 2678400
46
+ # set cache keys prefix, result key will be prefix:bin
47
+ config.cache.key_prefix = "ccinfo"
48
+
49
+ # also you can use custom logger instance, default is Rails.logger for Rails apps, and stdout for others
50
+ config.logger = Logger.new($stdout)
51
+ end
52
+ ```
53
+
54
+ ## Usage
55
+
56
+ You just need make call:
57
+
58
+ ```ruby
59
+ bin = '515735'
60
+ CreditCardInfo.fetch(bin)
61
+ # {
62
+ # bin: "515735",
63
+ # bank: "CITIBANK, N.A.",
64
+ # card: "MASTERCARD",
65
+ # type: "CREDIT",
66
+ # level: "WORLD CARD",
67
+ # country: "United States",
68
+ # countrycode: "US"
69
+ # }
70
+ ```
71
+
72
+ By default that call will be search firstly via bincodes.com, and if find nothing will search via `credit_card_bins` gem.
73
+
74
+ ## Contributing
75
+
76
+ 1. Fork it
77
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
78
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
79
+ 4. Push to the branch (`git push origin my-new-feature`)
80
+ 5. Create a new Pull Request
data/Rakefile ADDED
@@ -0,0 +1,4 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "bundler/gem_tasks"
4
+ task default: %i[]
data/bin/console ADDED
@@ -0,0 +1,15 @@
1
+ #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
3
+
4
+ require "bundler/setup"
5
+ require "credit_card_info"
6
+
7
+ # You can add fixtures and/or initialization code here to make experimenting
8
+ # with your gem easier. You can also use a different console, if you like.
9
+
10
+ # (If you use this, don't forget to add pry to your Gemfile!)
11
+ # require "pry"
12
+ # Pry.start
13
+
14
+ require "irb"
15
+ IRB.start(__FILE__)
@@ -0,0 +1,30 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "lib/credit_card_info/version"
4
+
5
+ Gem::Specification.new do |s|
6
+ s.name = "credit_card_info"
7
+ s.version = CreditCardInfo::VERSION
8
+ s.authors = ["Alexey Zhuravlev"]
9
+ s.email = ["alexey.g.zhuravlev@gmail.com"]
10
+ s.summary = "Find credit card info by BIN(IIN)"
11
+ s.description = <<-DESC
12
+ Fetch credit card info from www.bincodes.com with configurable fallback to https://github.com/hugolantaume/credit_card_bins data.
13
+ Also provides caching results for decreasing bincodesAPI request count/
14
+ DESC
15
+
16
+ s.license = "MIT"
17
+ s.homepage = "https://github.com/azhuravlev/credit_card_info"
18
+
19
+ s.metadata["allowed_push_host"] = "https://rubygems.org"
20
+
21
+ s.required_ruby_version = ">= 2.7"
22
+
23
+ s.add_dependency "credit_card_bins", "~> 0.0.1"
24
+ s.add_dependency "dry-configurable", ">= 0.13"
25
+
26
+ s.files = `find *`.split("\n").uniq.sort.reject(&:empty?)
27
+ s.test_files = `find spec/*`.split("\n")
28
+ s.executables = []
29
+ s.require_paths = ["lib"]
30
+ end
@@ -0,0 +1,15 @@
1
+ # frozen_string_literal: true
2
+
3
+ module CreditCardInfo
4
+ class Cache
5
+ def self.fetch(code, &block)
6
+ return yield unless config.provider
7
+
8
+ config.provider.fetch("#{config.key_prefix}:#{code}", expires_in: config.ttl, &block)
9
+ end
10
+
11
+ def self.config
12
+ CreditCardInfo.config.cache
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,25 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "logger"
4
+ require "dry-configurable"
5
+
6
+ module CreditCardInfo
7
+ class Config
8
+ extend Dry::Configurable
9
+
10
+ setting :bincodes do
11
+ setting :api_key, default: ""
12
+ setting :api_url, default: "https://api.bincodes.com"
13
+ setting :timeout, default: 10
14
+ setting :http_klass, default: Net::HTTP
15
+ end
16
+
17
+ setting :cache do
18
+ setting :provider, default: defined?(Rails) ? Rails.cache : nil
19
+ setting :ttl, default: 2678400 # 31 days
20
+ setting :key_prefix, default: "ccinfo"
21
+ end
22
+
23
+ setting :logger, default: defined?(Rails) ? Rails.logger : Logger.new($stdout)
24
+ end
25
+ end
@@ -0,0 +1,45 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "net/http"
4
+ require "uri"
5
+ require "json"
6
+
7
+ module CreditCardInfo
8
+ module Providers
9
+ class Bincodes
10
+ def self.fetch(code)
11
+ uri = URI("#{config.api_url}/bin/json/#{config.api_key}/#{code}")
12
+
13
+ http = config.http_klass.new(uri.host, uri.port)
14
+ http.use_ssl = true
15
+ http.read_timeout = config.timeout
16
+
17
+ request = Net::HTTP::Get.new(uri)
18
+ response = http.start { |h| h.request(request) }
19
+
20
+ parse_response(response)
21
+ rescue StandardError => e
22
+ CreditCardInfo::Response.new(error: { code: e.class, message: e.message })
23
+ end
24
+
25
+ def self.parse_response(response)
26
+ unless response.is_a?(Net::HTTPSuccess)
27
+ return CreditCardInfo::Response.new(error: { code: response.code,
28
+ message: "Unexpected error from bincodes api" })
29
+ end
30
+
31
+ data = JSON.parse(response.body, symbolize_names: true)
32
+
33
+ CreditCardInfo::Response.new(data: data).tap do |res|
34
+ res.error = { code: data[:error], message: data[:message] } if data[:error]
35
+ end
36
+ rescue JSONError => e
37
+ CreditCardInfo::Response.new(error: { code: e.class, message: "Invalid data from bincodes api: #{body}" })
38
+ end
39
+
40
+ def self.config
41
+ CreditCardInfo.config.bincodes
42
+ end
43
+ end
44
+ end
45
+ end
@@ -0,0 +1,26 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "credit_card_bins"
4
+
5
+ module CreditCardInfo
6
+ module Providers
7
+ class CreditCardBins
8
+ def self.fetch(code)
9
+ bin = CreditCardBin.new(code)
10
+ CreditCardInfo::Response.new(
11
+ data: {
12
+ bin: bin.bin,
13
+ bank: bin.issuer,
14
+ card: bin.brand,
15
+ type: bin.type,
16
+ level: bin.category,
17
+ country: bin.data.dig("country", "name"),
18
+ countrycode: bin.data.dig("country", "alpha_2")
19
+ }
20
+ )
21
+ rescue StandardError => e
22
+ CreditCardInfo::Response.new(error: { code: e.class, message: e.message })
23
+ end
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,23 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "providers/bincodes"
4
+ require_relative "providers/credit_card_bins"
5
+
6
+ module CreditCardInfo
7
+ module Proxy
8
+ # @return [Hash, NilClass] bin description
9
+ def self.fetch(code)
10
+ bincode_response = Providers::Bincodes.fetch(code)
11
+ return bincode_response.data if bincode_response.valid?
12
+
13
+ bincode_response.log_error
14
+
15
+ card_bins_response = Providers::CreditCardBins.fetch(code)
16
+ return card_bins_response.data if card_bins_response.valid?
17
+
18
+ card_bins_response.log_error
19
+
20
+ nil
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,30 @@
1
+ # frozen_string_literal: true
2
+
3
+ module CreditCardInfo
4
+ Response = Struct.new(:error, :data, keyword_init: true)
5
+ INFO_METHODS = %i[
6
+ bin
7
+ bank
8
+ card
9
+ type
10
+ level
11
+ country
12
+ countrycode
13
+ ].freeze
14
+
15
+ class Response
16
+ INFO_METHODS.each do |m|
17
+ define_method(m) { data.fetch(m, "") }
18
+ end
19
+
20
+ def valid?
21
+ error.nil?
22
+ end
23
+
24
+ def log_error
25
+ return unless CreditCardInfo.logger
26
+
27
+ CreditCardInfo.logger.warn "Wrong response: error_code=#{error[:code]} error_message=#{error[:message]}"
28
+ end
29
+ end
30
+ end
@@ -0,0 +1,5 @@
1
+ # frozen_string_literal: true
2
+
3
+ module CreditCardInfo
4
+ VERSION = "0.1.0"
5
+ end
@@ -0,0 +1,29 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "credit_card_info/proxy"
4
+ require "credit_card_info/cache"
5
+ require "credit_card_info/config"
6
+ require "credit_card_info/response"
7
+ require "credit_card_info/version"
8
+
9
+ module CreditCardInfo
10
+ class Error < StandardError; end
11
+
12
+ def self.config
13
+ @config ||= Config.config
14
+ end
15
+
16
+ def self.fetch(value)
17
+ code = extract_bin(value)
18
+ Cache.fetch(code) { Proxy.fetch(code) }
19
+ end
20
+
21
+ def self.logger
22
+ @logger ||= config.logger
23
+ end
24
+
25
+ # @return [String] first 5 digits of credit card number i.e. BIN
26
+ def self.extract_bin(value)
27
+ value.to_s.delete("\s")[0..5]
28
+ end
29
+ end
metadata ADDED
@@ -0,0 +1,90 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: credit_card_info
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Alexey Zhuravlev
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2022-03-14 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: credit_card_bins
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: 0.0.1
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: 0.0.1
27
+ - !ruby/object:Gem::Dependency
28
+ name: dry-configurable
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: '0.13'
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ">="
39
+ - !ruby/object:Gem::Version
40
+ version: '0.13'
41
+ description: |2
42
+ Fetch credit card info from www.bincodes.com with configurable fallback to https://github.com/hugolantaume/credit_card_bins data.
43
+ Also provides caching results for decreasing bincodesAPI request count/
44
+ email:
45
+ - alexey.g.zhuravlev@gmail.com
46
+ executables: []
47
+ extensions: []
48
+ extra_rdoc_files: []
49
+ files:
50
+ - CHANGELOG.md
51
+ - Gemfile
52
+ - Gemfile.lock
53
+ - LICENSE
54
+ - README.md
55
+ - Rakefile
56
+ - bin/console
57
+ - credit_card_info.gemspec
58
+ - lib/credit_card_info.rb
59
+ - lib/credit_card_info/cache.rb
60
+ - lib/credit_card_info/config.rb
61
+ - lib/credit_card_info/providers/bincodes.rb
62
+ - lib/credit_card_info/providers/credit_card_bins.rb
63
+ - lib/credit_card_info/proxy.rb
64
+ - lib/credit_card_info/response.rb
65
+ - lib/credit_card_info/version.rb
66
+ homepage: https://github.com/azhuravlev/credit_card_info
67
+ licenses:
68
+ - MIT
69
+ metadata:
70
+ allowed_push_host: https://rubygems.org
71
+ post_install_message:
72
+ rdoc_options: []
73
+ require_paths:
74
+ - lib
75
+ required_ruby_version: !ruby/object:Gem::Requirement
76
+ requirements:
77
+ - - ">="
78
+ - !ruby/object:Gem::Version
79
+ version: '2.7'
80
+ required_rubygems_version: !ruby/object:Gem::Requirement
81
+ requirements:
82
+ - - ">="
83
+ - !ruby/object:Gem::Version
84
+ version: '0'
85
+ requirements: []
86
+ rubygems_version: 3.1.6
87
+ signing_key:
88
+ specification_version: 4
89
+ summary: Find credit card info by BIN(IIN)
90
+ test_files: []