id_validator 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: 4ab0ebe883bfc647be492fdbc4fd3b80e35a4a33e2a9f3d9a97802ac4e8e99c4
4
+ data.tar.gz: 84e81d6823a9aaf1ed12ffa4d1ecb0a35d54ea4c46a96a1aaf46dabb608ba280
5
+ SHA512:
6
+ metadata.gz: 35bc2b3ba1e7deb4d2340d9ad83cbf1e924a5e06917ca77f2e1cb9660ec8c1d3648a68a230955b9ebeb3a1ec56e5adcbfcba6444453a02f4b74efc512ed96938
7
+ data.tar.gz: 0f77b4441b862d41b6f55d5b9bfc6801d39f986c8273ca1559fff747e849020a1a8bab19dca7481882bd385095c78a76d0d6ee6ea4b934601dcdf8274d2e5113
data/.gitignore ADDED
@@ -0,0 +1,9 @@
1
+ /.bundle/
2
+ /.yardoc
3
+ /_yardoc/
4
+ /coverage/
5
+ /doc/
6
+ /pkg/
7
+ /spec/reports/
8
+ /tmp/
9
+ /.idea/
data/.idea/vcs.xml ADDED
@@ -0,0 +1,6 @@
1
+ <?xml version="1.0" encoding="UTF-8"?>
2
+ <project version="4">
3
+ <component name="VcsDirectoryMappings">
4
+ <mapping directory="$PROJECT_DIR$" vcs="Git" />
5
+ </component>
6
+ </project>
data/.travis.yml ADDED
@@ -0,0 +1,12 @@
1
+ sudo: false
2
+ language: ruby
3
+ rvm:
4
+ - 2.5.1
5
+ - 2.4.4
6
+ - 2.3.6
7
+ before_install:
8
+ - gem install bundler
9
+
10
+ install:
11
+ - bundle install
12
+
@@ -0,0 +1,74 @@
1
+ # Contributor Covenant Code of Conduct
2
+
3
+ ## Our Pledge
4
+
5
+ In the interest of fostering an open and welcoming environment, we as
6
+ contributors and maintainers pledge to making participation in our project and
7
+ our community a harassment-free experience for everyone, regardless of age, body
8
+ size, disability, ethnicity, gender identity and expression, level of experience,
9
+ nationality, personal appearance, race, religion, or sexual identity and
10
+ orientation.
11
+
12
+ ## Our Standards
13
+
14
+ Examples of behavior that contributes to creating a positive environment
15
+ include:
16
+
17
+ * Using welcoming and inclusive language
18
+ * Being respectful of differing viewpoints and experiences
19
+ * Gracefully accepting constructive criticism
20
+ * Focusing on what is best for the community
21
+ * Showing empathy towards other community members
22
+
23
+ Examples of unacceptable behavior by participants include:
24
+
25
+ * The use of sexualized language or imagery and unwelcome sexual attention or
26
+ advances
27
+ * Trolling, insulting/derogatory comments, and personal or political attacks
28
+ * Public or private harassment
29
+ * Publishing others' private information, such as a physical or electronic
30
+ address, without explicit permission
31
+ * Other conduct which could reasonably be considered inappropriate in a
32
+ professional setting
33
+
34
+ ## Our Responsibilities
35
+
36
+ Project maintainers are responsible for clarifying the standards of acceptable
37
+ behavior and are expected to take appropriate and fair corrective action in
38
+ response to any instances of unacceptable behavior.
39
+
40
+ Project maintainers have the right and responsibility to remove, edit, or
41
+ reject comments, commits, code, wiki edits, issues, and other contributions
42
+ that are not aligned to this Code of Conduct, or to ban temporarily or
43
+ permanently any contributor for other behaviors that they deem inappropriate,
44
+ threatening, offensive, or harmful.
45
+
46
+ ## Scope
47
+
48
+ This Code of Conduct applies both within project spaces and in public spaces
49
+ when an individual is representing the project or its community. Examples of
50
+ representing a project or community include using an official project e-mail
51
+ address, posting via an official social media account, or acting as an appointed
52
+ representative at an online or offline event. Representation of a project may be
53
+ further defined and clarified by project maintainers.
54
+
55
+ ## Enforcement
56
+
57
+ Instances of abusive, harassing, or otherwise unacceptable behavior may be
58
+ reported by contacting the project team at lanyuejin1108@gmail.com. All
59
+ complaints will be reviewed and investigated and will result in a response that
60
+ is deemed necessary and appropriate to the circumstances. The project team is
61
+ obligated to maintain confidentiality with regard to the reporter of an incident.
62
+ Further details of specific enforcement policies may be posted separately.
63
+
64
+ Project maintainers who do not follow or enforce the Code of Conduct in good
65
+ faith may face temporary or permanent repercussions as determined by other
66
+ members of the project's leadership.
67
+
68
+ ## Attribution
69
+
70
+ This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4,
71
+ available at [http://contributor-covenant.org/version/1/4][version]
72
+
73
+ [homepage]: http://contributor-covenant.org
74
+ [version]: http://contributor-covenant.org/version/1/4/
data/Gemfile ADDED
@@ -0,0 +1,6 @@
1
+ source "https://rubygems.org"
2
+
3
+ git_source(:github) {|repo_name| "https://github.com/#{repo_name}" }
4
+
5
+ # Specify your gem's dependencies in id_validator.gemspec
6
+ gemspec
data/Gemfile.lock ADDED
@@ -0,0 +1,22 @@
1
+ PATH
2
+ remote: .
3
+ specs:
4
+ id_validator (0.1.0)
5
+
6
+ GEM
7
+ remote: https://rubygems.org/
8
+ specs:
9
+ minitest (5.11.3)
10
+ rake (10.5.0)
11
+
12
+ PLATFORMS
13
+ ruby
14
+
15
+ DEPENDENCIES
16
+ bundler (~> 1.16)
17
+ id_validator!
18
+ minitest (~> 5.0)
19
+ rake (~> 10.0)
20
+
21
+ BUNDLED WITH
22
+ 1.16.1
data/README.md ADDED
@@ -0,0 +1,122 @@
1
+ [![Build Status](https://travis-ci.com/renyijiu/id_validator.svg?branch=master)](https://travis-ci.com/renyijiu/id_validator)
2
+
3
+
4
+ # IdValidator
5
+
6
+ **中华人民共和国居民身份证** 、**中华人民共和国港澳居民居住证** 以及 **中华人民共和国台湾居民居住证** 号码验证工具(Ruby
7
+ 版)支持 15 位与 18 位号码。
8
+
9
+ - [JavaScript 版本](https://github.com/mc-zone/IDValidator)
10
+ - [PHP 版本](https://github.com/jxlwqq/id-validator)
11
+ - [Python 版本](https://github.com/jxlwqq/id-validator.py)
12
+
13
+ ## 安装
14
+
15
+ 将下列代码增加到对应项目的Gemfile中:
16
+
17
+ ```ruby
18
+ gem 'id_validator'
19
+ ```
20
+
21
+ 然后执行下列命令:
22
+
23
+ $ bundle
24
+
25
+ 或者,直接安装对应的gem包使用:
26
+
27
+ $ gem install id_validator
28
+
29
+ ## 使用
30
+
31
+ `440308199901101512` 和 `610104620927690`
32
+
33
+ 示例大陆居民身份证均为随机生成的假数据,如有看雷同,请联系删除。
34
+
35
+ `810000199408230021` 和 `830000199201300022`
36
+
37
+ 示例港澳台居民居住证为北京市公安局公布的居住证样式号码。
38
+
39
+ ### 验证身份证合法性
40
+
41
+ 验证身份证合法性,合法返回 `true`, 不合法返回 `false`
42
+
43
+ ```ruby
44
+ IdValidator.is_valid?('440308199901101512') # => true, 大陆居民身份证 18 位
45
+ IdValidator.is_valid?('610104620927690') # => true, 大陆居民身份证 15 位
46
+ IdValidator.is_valid?('810000199408230021') # => true, 港澳居民身份证 18 位
47
+ IdValidator.is_valid?('830000199201300022') # => true, 台湾居民身份证 18 位
48
+ ```
49
+
50
+ ### 获取身份证号信息
51
+
52
+ 当身份证号合法时,返回分析信息(地区、出生日期、星座、生肖、性别、校验码),不合法时返回 `false`
53
+
54
+
55
+ ```ruby
56
+
57
+ IdValidator.get_info('440308199901101512') # 大陆居民身份证 18 位
58
+ IdValidator.get_info('610104620927690') # 大陆居民身份证 15 位
59
+
60
+ ```
61
+ 返回信息格式如下:
62
+
63
+ ```ruby
64
+ {
65
+ :address_code => "440308", # 地址码
66
+ :address => "广东省深圳市盐田区", # 地址信息
67
+ :abandoned => false, # 地址码是否已经废弃
68
+ :birthday_code => "1999-01-10", # 出生日期
69
+ :constellation => "摩羯座", # 星座
70
+ :chinese_zodiac => "卯兔", # 生肖
71
+ :sex => 1, # 性别,0:女性,1:男性
72
+ :length => 18, # 号码长度
73
+ :check_bit=>"2" # 校验码
74
+ }
75
+ ```
76
+
77
+ > 注:判断地址码是否废弃的依据是[中华人民共和国行政区划代码历史数据集](https://github.com/jxlwqq/address-code-of-china) ,本数据集的采集源来自:[中华人民共和国民政部](http://www.mca.gov.cn/article/sj/xzqh//1980/) ,每年更新一次。本数据集采用 csv 格式存储,方便大家进行数据分析或者开发其他语言的版本。
78
+
79
+ ### 生成可通过校验的假数据
80
+
81
+ ```ruby
82
+ IdValidator.fake_id(eighteen = true, address = nil, birthday = nil, sex = nil)
83
+
84
+ IdValidator.fake_id # 18位 身份证
85
+ IdValidator.fake_id(false) # 15位 身份证
86
+ IdValidator.fake_id(true, '上海市') # 18位 上海市居民身份证
87
+ IdValidator.fake_id(true, '南山区', '1993') # 18位 出生于 1993年 广东省深圳市南山区身份证
88
+ IdValidator.fake_id(true, '江苏省', '199301') # 18位 出生于 1993年01月 江苏省身份证
89
+ IdValidator.fake_id(true, '厦门市', '19930101', 1) # 18位 出生于 1993年01月01日 福建省厦门市男性身份证
90
+ IdValidator.fake_id(true, '台湾省', '20131010', 0) # 18位 出生于 2013年10月10日 台湾省女性身份证
91
+ IdValidator.fake_id(true, '香港特别行政区', '20131010', 0) # 18位 出生于 2013年10月10日 香港特别行政区女性身份证
92
+ ```
93
+
94
+ ### 身份证升级
95
+
96
+ 15 位号码升级为 18 位
97
+ ```ruby
98
+ IdValidator.upgrade_id('610104620927690')
99
+ => "610104196209276908"
100
+ ```
101
+
102
+ ## 参考资料
103
+
104
+ - [中华人民共和国公民身份号码](https://zh.wikipedia.org/wiki/中华人民共和国公民身份号码)
105
+
106
+ - [中华人民共和国民政部:行政区划代码](http://www.mca.gov.cn/article/sj/xzqh/)
107
+
108
+ - [中华人民共和国行政区划代码历史数据集](https://github.com/jxlwqq/address-code-of-china)
109
+
110
+ - [国务院办公厅关于印发《港澳台居民居住证申领发放办法》的通知](http://www.gov.cn/zhengce/content/2018-08/19/content_5314865.htm)
111
+
112
+ - [港澳台居民居住证](https://zh.wikipedia.org/wiki/港澳台居民居住证)
113
+
114
+ ## 如何贡献
115
+
116
+ 1. Fork it
117
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
118
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
119
+ 4. Push to the branch (`git push origin my-new-feature`)
120
+ 5. Create new Pull Request
121
+
122
+ 欢迎贡献相关代码或是提交你的使用反馈👏,另外请记得为你的代码编写测试。
data/Rakefile ADDED
@@ -0,0 +1,10 @@
1
+ require "bundler/gem_tasks"
2
+ require "rake/testtask"
3
+
4
+ Rake::TestTask.new(:test) do |t|
5
+ t.libs << "test"
6
+ t.libs << "lib"
7
+ t.test_files = FileList["test/**/*_test.rb"]
8
+ end
9
+
10
+ task :default => :test
data/bin/console ADDED
@@ -0,0 +1,14 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require "bundler/setup"
4
+ require "id_validator"
5
+
6
+ # You can add fixtures and/or initialization code here to make experimenting
7
+ # with your gem easier. You can also use a different console, if you like.
8
+
9
+ # (If you use this, don't forget to add pry to your Gemfile!)
10
+ # require "pry"
11
+ # Pry.start
12
+
13
+ require "irb"
14
+ IRB.start(__FILE__)
data/bin/setup ADDED
@@ -0,0 +1,8 @@
1
+ #!/usr/bin/env bash
2
+ set -euo pipefail
3
+ IFS=$'\n\t'
4
+ set -vx
5
+
6
+ bundle install
7
+
8
+ # Do any other automated setup that you need to do here
@@ -0,0 +1,26 @@
1
+
2
+ lib = File.expand_path("../lib", __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require "id_validator/version"
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = "id_validator"
8
+ spec.version = IdValidator::VERSION
9
+ spec.authors = ["renyijiu"]
10
+ spec.email = ["lanyuejin1108@gmail.com"]
11
+
12
+ spec.summary = %q{Chinese Mainland Personal ID Card Validation.}
13
+ spec.description = %q{A Ruby Gem For Chinese Mainland Personal ID Card Validation}
14
+ spec.homepage = "https://github.com/renyijiu/id_validator"
15
+
16
+ spec.files = `git ls-files -z`.split("\x0").reject do |f|
17
+ f.match(%r{^(test|spec|features)/})
18
+ end
19
+ spec.bindir = "bin"
20
+ spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
21
+ spec.require_paths = ["lib"]
22
+
23
+ spec.add_development_dependency "bundler", "~> 1.16"
24
+ spec.add_development_dependency "rake", "~> 10.0"
25
+ spec.add_development_dependency "minitest", "~> 5.0"
26
+ end
@@ -0,0 +1,229 @@
1
+ module IdValidator
2
+ module Concern
3
+ module Func
4
+ extend self
5
+
6
+ # 检测出生日期, example: '20181015'
7
+ def check_birthday(birthday)
8
+ return false if birthday.to_s.length != 8
9
+ date = Date.parse(birthday.to_s) rescue nil
10
+
11
+ return false if date.nil?
12
+ return false if date.year < 1800 || date > Date.today
13
+
14
+ true
15
+ end
16
+
17
+ # 格式化出生日期
18
+ def format_birthday_code(birthday_code)
19
+ "#{birthday_code[0..3]}-#{birthday_code[4..5]}-#{birthday_code[6..7]}"
20
+ end
21
+
22
+ # 格式化地址栏
23
+ def format_address_info(address_info)
24
+ "#{address_info[:province]}#{address_info[:city]}#{address_info[:district]}"
25
+ end
26
+
27
+ # 随意获取一个符合要求的地址码
28
+ def get_random_address_code(reg)
29
+ keys = IdValidator::Config.address_info.keys.shuffle
30
+
31
+ keys.find { |key| key.to_s =~ reg }.to_s
32
+ end
33
+
34
+ # 字符串填充
35
+ def get_str_pad(str, length = 2, character = '0', right = true)
36
+ str = str.to_s
37
+ return str if length <= str.length
38
+
39
+ frequency = length - str.length
40
+ right ? (str + character.to_s * frequency) : (character.to_s * frequency + str)
41
+ end
42
+
43
+ # 随机获取一个符合条件的数字
44
+ def get_random_right_num(num, min, max)
45
+ return num if (min..max).member?(num)
46
+
47
+ rand(min..max)
48
+ end
49
+
50
+ # 随意生成一个生日
51
+ def get_random_birthday_code
52
+ Time.at(rand * Time.now.to_i).strftime('%Y%m%d')
53
+ end
54
+ end
55
+
56
+ module Helper
57
+ # 获取身份证信息
58
+ def get_id_argument(id_card)
59
+ id_card = id_card.to_s.upcase
60
+
61
+ if id_card.length == 18
62
+ {
63
+ body: id_card[0...17],
64
+ address_code: id_card[0...6],
65
+ birthday_code: id_card[6...14],
66
+ order_code: id_card[14...17],
67
+ check_bit: id_card[17],
68
+ type: 18
69
+ }
70
+ else
71
+ {
72
+ body: id_card,
73
+ address_code: id_card[0...6],
74
+ birthday_code: '19' + id_card[6...12],
75
+ order_code: id_card[12...15],
76
+ check_bit: '',
77
+ type: 15
78
+ }
79
+ end
80
+ end
81
+
82
+ # 获取地址信息
83
+ def get_address_info(address_code)
84
+ address_code_hash = IdValidator::Config.address_info
85
+ abandoned_address_code_hash = IdValidator::Config.abandoned_address_code
86
+
87
+ province_address_code = "#{address_code[0...2]}0000".to_i
88
+ city_address_code = "#{address_code[0...4]}00".to_i
89
+
90
+ province = address_code_hash[province_address_code] || abandoned_address_code_hash[province_address_code]
91
+
92
+ if address_code[0].to_i != 8
93
+ city = address_code_hash[city_address_code] || abandoned_address_code_hash[city_address_code]
94
+ district = address_code_hash[address_code.to_i] ||abandoned_address_code_hash[address_code.to_i]
95
+ else
96
+ city = nil
97
+ district = nil
98
+ end
99
+
100
+ {
101
+ province: province,
102
+ city: city,
103
+ district: district
104
+ }
105
+ end
106
+
107
+ # 获取星座信息
108
+ def get_constellation(birthday_code)
109
+ date = Date.parse(birthday_code.to_s)
110
+
111
+ month = date.month
112
+ day = date.day
113
+ constellation = IdValidator::Config.constellation
114
+
115
+ start_day = constellation[month][:start_date].split('-').last.to_i
116
+ if day < start_day
117
+ tmp_month = month - 1 == 0 ? 12 : month - 1
118
+
119
+ constellation[tmp_month][:name]
120
+ else
121
+ constellation[month][:name]
122
+ end
123
+ end
124
+
125
+ # 获取生肖信息
126
+ def get_chinese_zodiac(birthday_code)
127
+ # 1900为子鼠
128
+ index = (birthday_code[0...4].to_i - 1900) % 12
129
+
130
+ IdValidator::Config.chinese_zodiac[index]
131
+ end
132
+
133
+ # 检查地址码
134
+ def check_address_code(address_code)
135
+ address_info = get_address_info(address_code.to_s)
136
+ return false if address_info[:province].nil?
137
+
138
+ true
139
+ end
140
+
141
+ # 检查出生日期
142
+ def check_birthday_code(birthday_code)
143
+ return false unless Func.check_birthday(birthday_code.to_s)
144
+
145
+ true
146
+ end
147
+
148
+ # 检查顺序码
149
+ def check_order_code(order_code)
150
+ return false if order_code.length != 3
151
+
152
+ true
153
+ end
154
+
155
+ # 检查是否已经废弃
156
+ def check_is_abandoned(address_code)
157
+ address = IdValidator::Config.abandoned_address_code.fetch(address_code.to_i, nil)
158
+
159
+ !address.nil?
160
+ end
161
+
162
+ # 生成校验码
163
+ def generate_check_bit(body)
164
+ body = body.to_s.reverse
165
+ return nil if body.length != 17
166
+
167
+ body_sum = 0
168
+ weight = (2..18).map{ |a| 2**(a - 1) % 11 }
169
+ weight.each_with_index{ |w, i| body_sum += body[i].to_i * w }
170
+
171
+ check_bit = (12 - (body_sum % 11)) % 11
172
+ check_bit < 10 ? check_bit.to_s : 'X'
173
+ end
174
+
175
+ # 生成地址码
176
+ def generate_address_code(address)
177
+ key = IdValidator::Config.address_info.key(address).to_s
178
+
179
+ case
180
+ when key.empty?
181
+ reg = %r(^\d{4}(?!00)\d{2}$)
182
+ return Func.get_random_address_code(reg)
183
+ when key[0] == '8'
184
+ return key
185
+ when key =~ /^\d{2}0000$/
186
+ reg = %r(^#{key[0..1]}\d{2}(?!00)\d{2}$)
187
+ return Func.get_random_address_code(reg)
188
+ when key =~ /^\d{4}00$/
189
+ reg = %r(^#{key[0..3]}(?!00)\d{2}$)
190
+ return Func.get_random_address_code(reg)
191
+ else
192
+ return key.to_s
193
+ end
194
+ end
195
+
196
+ # 生成生日信息
197
+ def generate_birthday_code(birthday)
198
+ return birthday if Func.check_birthday(birthday)
199
+ birthday = Func.get_str_pad(birthday.to_s, 8)
200
+
201
+ year = Func.get_random_right_num(birthday[0..3].to_i, 1900, Time.now.year - 1)
202
+ month = Func.get_random_right_num(birthday[4..5].to_i, 1, 12)
203
+ day = Func.get_random_right_num(birthday[6..7], 1, 28)
204
+
205
+ year = Func.get_str_pad(year.to_s, 4)
206
+ month = Func.get_str_pad(month.to_s, 2, '0', false)
207
+ day = Func.get_str_pad(day.to_s, 2, '0', false)
208
+ result = year + month + day
209
+
210
+ if Func.check_birthday(result)
211
+ result
212
+ else
213
+ Func.get_random_birthday_code
214
+ end
215
+ end
216
+
217
+ # 生成顺序码
218
+ def generate_order_code(sex)
219
+ order_code = rand(1..999)
220
+
221
+ order_code = order_code % 2 == 0 ? order_code : order_code - 1 if sex == 0
222
+ order_code = order_code % 2 == 0 ? order_code - 1 : order_code if sex == 1
223
+
224
+ Func.get_str_pad(order_code, 3, '0', false)
225
+ end
226
+
227
+ end
228
+ end
229
+ end