From b1835ea4e877ceb3c10abcbf2c128a9a035a01ef Mon Sep 17 00:00:00 2001 From: myvfpx Date: Tue, 24 Sep 2019 10:21:37 +0800 Subject: [PATCH] =?UTF-8?q?=E6=B7=BB=E5=8A=A0=E8=BA=AB=E4=BB=BD=E8=AF=81?= =?UTF-8?q?=E5=8F=B7=E5=B0=BE=E6=95=B0=E9=AA=8C=E8=AF=81=E8=A7=84=E5=88=99?= =?UTF-8?q?,=E6=B7=BB=E5=8A=A0=E9=93=B6=E8=A1=8C=E5=8D=A1=E5=8F=B7?= =?UTF-8?q?=E9=AA=8C=E8=AF=81=E8=A7=84=E5=88=99?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- util/gvalid/gvalid_check.go | 56 ++++++++++++++++++++++- util/gvalid/gvalid_message.go | 1 + util/gvalid/gvalid_unit_basic_all_test.go | 16 ++++++- 3 files changed, 70 insertions(+), 3 deletions(-) diff --git a/util/gvalid/gvalid_check.go b/util/gvalid/gvalid_check.go index 7eb393add..2ceaacc0e 100644 --- a/util/gvalid/gvalid_check.go +++ b/util/gvalid/gvalid_check.go @@ -66,6 +66,7 @@ var ( "password3": {}, "postcode": {}, "id-number": {}, + "luhn": {}, "qq": {}, "ip": {}, "ipv4": {}, @@ -315,7 +316,13 @@ func Check(value interface{}, rules string, msgs interface{}, params ...interfac (^[1-9]\d{5}(18|19|([23]\d))\d{2}((0[1-9])|(10|11|12))(([0-2][1-9])|10|20|30|31)\d{3}[0-9Xx]$)|(^[1-9]\d{5}\d{2}((0[1-9])|(10|11|12))(([0-2][1-9])|10|20|30|31)\d{3}$) */ case "id-number": - match = gregex.IsMatchString(`(^[1-9]\d{5}(18|19|([23]\d))\d{2}((0[1-9])|(10|11|12))(([0-2][1-9])|10|20|30|31)\d{3}[0-9Xx]$)|(^[1-9]\d{5}\d{2}((0[1-9])|(10|11|12))(([0-2][1-9])|10|20|30|31)\d{3}$)`, val) + match = checkIDNumber(val) + // match = gregex.IsMatchString(`(^[1-9]\d{5}(18|19|([23]\d))\d{2}((0[1-9])|(10|11|12))(([0-2][1-9])|10|20|30|31)\d{3}[0-9Xx]$)|(^[1-9]\d{5}\d{2}((0[1-9])|(10|11|12))(([0-2][1-9])|10|20|30|31)\d{3}$)`, val) + + // LUHN规则(银行卡号验证规则) + case "luhn": + match = checkLuHn(val) + println(match) // 通用帐号规则(字母开头,只能包含字母、数字和下划线,长度在6~18之间) case "passport": @@ -650,3 +657,50 @@ func checkSize(value, ruleKey, ruleVal string, customMsgMap map[string]string) s } return msg } + +// 身份证号验证 +func checkIDNumber(value string) bool { + value = strings.ToUpper(strings.TrimSpace(value)) + // 18位长检测 + if len(value) != 18 { + return false + } + // 加权因子 + weightFactor := [...]int{7, 9, 10, 5, 8, 4, 2, 1, 6, 3, 7, 9, 10, 5, 8, 4, 2} + // 校验码 + checkCode := [...]byte{'1', '0', 'X', '9', '8', '7', '6', '5', '4', '3', '2'} + last := value[17] + num := 0 + for i := 0; i < 17; i++ { + tmp, err := strconv.Atoi(string(value[i])) + if err != nil { + return false + } + num = num + tmp*weightFactor[i] + } + resisue := num % 11 + if checkCode[resisue] != last { + return false + } + + return gregex.IsMatchString(`(^[1-9]\d{5}(18|19|([23]\d))\d{2}((0[1-9])|(10|11|12))(([0-2][1-9])|10|20|30|31)\d{3}[0-9Xx]$)|(^[1-9]\d{5}\d{2}((0[1-9])|(10|11|12))(([0-2][1-9])|10|20|30|31)\d{3}$)`, value) +} + +// LuHn算法验证(银行卡号校验算法) +func checkLuHn(value string) bool { + var sum = 0 + var nDigits = len(value) + var parity = nDigits % 2 + + for i := 0; i < nDigits; i++ { + var digit = int(value[i] - 48) + if i%2 == parity { + digit *= 2 + if digit > 9 { + digit -= 9 + } + } + sum += digit + } + return sum%10 == 0 +} diff --git a/util/gvalid/gvalid_message.go b/util/gvalid/gvalid_message.go index 8b926c1c6..601fe701f 100644 --- a/util/gvalid/gvalid_message.go +++ b/util/gvalid/gvalid_message.go @@ -26,6 +26,7 @@ var defaultMessages = map[string]string{ "password3": "密码格式不合法,密码格式为任意6-18位的可见字符,必须包含大小写字母、数字和特殊字符", "postcode": "邮政编码不正确", "id-number": "身份证号码不正确", + "luhn": "银行卡号不正确", "qq": "QQ号码格式不正确", "ip": "IP地址格式不正确", "ipv4": "IPv4地址格式不正确", diff --git a/util/gvalid/gvalid_unit_basic_all_test.go b/util/gvalid/gvalid_unit_basic_all_test.go index 500caa8dc..58726dd97 100755 --- a/util/gvalid/gvalid_unit_basic_all_test.go +++ b/util/gvalid/gvalid_unit_basic_all_test.go @@ -389,12 +389,24 @@ func Test_IDNumber(t *testing.T) { err5 := gvalid.Check(val5, rule, nil) gtest.AssertNE(err1, nil) gtest.AssertNE(err2, nil) - gtest.Assert(err3, nil) - gtest.Assert(err4, nil) + gtest.AssertNE(err3, nil) + gtest.AssertNE(err4, nil) gtest.Assert(err5, nil) }) } +func Test_LuHn(t *testing.T) { + gtest.Case(t, func() { + rule := "luhn" + val1 := "6230514630000424470" + val2 := "6230514630000424473" + err1 := gvalid.Check(val1, rule, nil) + err2 := gvalid.Check(val2, rule, nil) + gtest.AssertNE(err1, nil) + gtest.Assert(err2, nil) + }) +} + func Test_QQ(t *testing.T) { gtest.Case(t, func() { rule := "qq"