blog_backend_api/vendor/git.jiaxianghudong.com/go/utils/verifier.go

253 lines
5.5 KiB
Go
Raw Normal View History

2019-01-28 03:19:49 +00:00
package utils
import (
"reflect"
"regexp"
"strings"
"net/http"
"strconv"
"time"
"math"
)
// IsIDCard 检查是否是身份证
func IsIDCard(str string, args ...bool) bool {
if m, _ := regexp.MatchString("^(?:[\\dxX]{15}|[\\dxX]{18})$", str); !m {
return false
}
areaMap := map[int]string{
11 : "北京",
12 : "天津",
13 : "河北",
14 : "山西",
15 : "内蒙古",
21 : "辽宁",
22 : "吉林",
23 : "黑龙江",
31 : "上海",
32 : "江苏",
33 : "浙江",
34 : "安徽",
35 : "福建",
36 : "江西",
37 : "山东",
41 : "河南",
42 : "湖北",
43 : "湖南",
44 : "广东",
45 : "广西",
46 : "海南",
50 : "重庆",
51 : "四川",
52 : "贵州",
53 : "云南",
54 : "西藏",
61 : "陕西",
62 : "甘肃",
63 : "青海",
64 : "宁夏",
65 : "新疆",
71 : "台湾",
81 : "香港",
82 : "澳门",
91 : "国外",
}
allowLen15 := true
if len(args) == 1 {
allowLen15 = args[0]
}
province := Atoi(Substr(str, 0, 2))
if _, ok := areaMap[province]; !ok {
return false
}
//如果是15位身份证
if len(str) == 15 && allowLen15 {
// 如果身份证顺序码是996 997 998 999这些是为百岁以上老人的特殊编码
code := Substr(str, 12, 3)
if code == "996" || code == "997" || code == "998" || code == "999" {
str = Substr(str, 0, 6) + "18" + Substr(str, 6, 9)
} else {
str = Substr(str, 0, 6) + "19" + Substr(str, 6, 9)
}
str += idcardVerifyNumber(str)
}
if len(str) != 18 || !checkIdcardFormat(str) {
return false
}
return idcardVerifyNumber(Substr(str, 0, 17)) == strings.ToUpper(Substr(str, 17, 1))
}
// checkIdcardFormat 检查身份证号码的格式
// 针对近期出现身份证号码使用210000000000000000注册的用户
// 验证地区码(3-6位)以及生日(6-14)位
func checkIdcardFormat(str string) bool {
code := Atoi(Substr(str, 3, 3))
if code == 0 {
return false
}
if len(str) == 18 {
birthYear := Atoi(Substr(str, 6, 4))
birthMonth := Atoi(Substr(str, 10, 2))
birthDay := Atoi(Substr(str, 10, 2))
if birthYear < 1900 || (birthMonth == 0 || birthMonth > 12) || (birthDay == 0 || birthDay > 31) {
return false
}
return true
}
return false
}
// idcardVerifyNumber 计算身份证校验码根据国家标准GB 11643-1999
func idcardVerifyNumber(str string) string {
if len(str) != 17 {
return ""
}
//加权因子
factor := []int{7, 9, 10, 5, 8, 4, 2, 1, 6, 3, 7, 9, 10, 5, 8, 4, 2}
//校验码对应值
verifyNumberList := []string{"1", "0", "X", "9", "8", "7", "6", "5", "4", "3", "2"}
checkSum := 0
for i, l := 0, len(str); i < l; i++ {
checkSum += Atoi(Substr(str, i, 1)) * factor[i]
}
checkSum = checkSum % 11
return verifyNumberList[checkSum]
}
// 是否为空
func IsEmpty(val interface{}) (b bool) {
defer func() {
if err := recover(); err != nil {
b = true
}
}()
v := reflect.ValueOf(val)
switch v.Kind() {
case reflect.Bool:
b = (val.(bool) == false)
case reflect.String:
b = (val.(string) == "")
case reflect.Array:
fallthrough
case reflect.Slice:
fallthrough
case reflect.Map:
b = (v.Len() == 0)
default:
b = (v.Interface() == reflect.ValueOf(0).Interface() || v.Interface() == reflect.ValueOf(0.0).Interface())
}
return b
}
// 判断是否正确的ip地址
func IsIp(ip string) bool {
ips := strings.Split(ip, ".")
if len(ips) != 4 {
return false
}
for _, v := range ips {
i := Atoi(v, -1)
if i < 0 || i > 255 {
return false
}
}
return true
}
//检测是否为手机设备
func IsMobileDevice(r *http.Request) bool {
agent := r.UserAgent()
if strings.Contains(agent,"iPhone") || strings.Contains(agent,"iPad") || strings.Contains(agent,"iOS") || strings.Contains(agent,"Android") {
return true;
}
return false;
}
// 检查字符串是否为纯数字组成
func IsNumStr(s string) bool {
if _, err := strconv.Atoi(s); err == nil {
return true
}
return false
}
// 检查字符串是否为纯数字组成
func IsLongNumStr(s string) bool {
if m, _ := regexp.MatchString("^\\d+$", s); m {
return true
}
return false
}
// IsMobileNum 检查是否是手机号
func IsMobileNum(str string) bool {
if m, _ := regexp.MatchString("^((13[\\d])|(147)|(15[\\d])|17[\\d]|(18[\\d]))[0-9]{8}$", str); m {
return true
}
return false
}
// IsVersionStr 检查字符串是否是一个版本格式
func IsVersionStr(str string) bool {
return IsVersion(str, "{2}")
}
// IsVersion 检查字符串是否是一个版本格式
func IsVersion(str string, length ...string) bool {
vL := "{1,3}"
if len(length) == 1 {
vL = length[0]
}
if m, _ := regexp.MatchString("^\\d+(?:\\.\\d+)" + vL + "$", str); m {
return true
}
return false
}
// IsDeviceCode 检查字符串是否是一个机器码
func IsDeviceCode(str string) bool {
if m, _ := regexp.MatchString("^[a-zA-Z0-9]{40}$", str); m {
return true
}
return false
}
// RegexpOK 检查字符串被正则匹配
func RegexpOK(pattern, str string) bool {
if m, _ := regexp.MatchString(pattern, str); m {
return true
}
return false
}
// DiffDay 比较两个日志间隔的天数
// 第1个日期小于第2个日期时返回正数
// 第1个日期大于第2个日期时返回负数
func DiffDay(t1, t2 string, fm ...string) (int, error) {
format := "2006-01-02"
if len(fm) == 1 {
format = fm[0]
}
tm1, err := time.ParseInLocation(format, t1, time.Local)
if err != nil {
return 0, err
}
tm2, err := time.ParseInLocation(format, t2, time.Local)
if err != nil {
return 0, err
}
hour := tm2.Sub(tm1).Hours()
if -24 >= hour || hour >= 24 {
return int(math.Ceil(hour / 24)), nil
}
return 0, nil
}