business.go 3.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161
  1. package validator
  2. import (
  3. "regexp"
  4. "strconv"
  5. "strings"
  6. "unicode"
  7. )
  8. // isValidChineseMobile 验证中国手机号
  9. func isValidChineseMobile(mobile string) bool {
  10. // 中国手机号: 1 + (3-9) + 9位数字
  11. pattern := `^1[3-9]\d{9}$`
  12. matched, _ := regexp.MatchString(pattern, mobile)
  13. return matched
  14. }
  15. // isValidChineseIDCard 验证中国身份证号
  16. func isValidChineseIDCard(idCard string) bool {
  17. // 支持15位和18位
  18. if len(idCard) != 15 && len(idCard) != 18 {
  19. return false
  20. }
  21. if len(idCard) == 18 {
  22. return isValid18IDCard(idCard)
  23. }
  24. // 15位身份证验证(旧版)
  25. pattern := `^\d{15}$`
  26. matched, _ := regexp.MatchString(pattern, idCard)
  27. return matched
  28. }
  29. // isValid18IDCard 验证18位身份证
  30. func isValid18IDCard(idCard string) bool {
  31. // 基本格式验证: 6位地区码 + 8位出生日期 + 3位顺序码 + 1位校验码
  32. pattern := `^\d{17}[\dXx]$`
  33. matched, _ := regexp.MatchString(pattern, idCard)
  34. if !matched {
  35. return false
  36. }
  37. // 校验位验证(简化版)
  38. // 权重因子
  39. weights := []int{7, 9, 10, 5, 8, 4, 2, 1, 6, 3, 7, 9, 10, 5, 8, 4, 2}
  40. // 校验码
  41. checkCodes := []string{"1", "0", "X", "9", "8", "7", "6", "5", "4", "3", "2"}
  42. sum := 0
  43. for i := 0; i < 17; i++ {
  44. digit, _ := strconv.Atoi(string(idCard[i]))
  45. sum += digit * weights[i]
  46. }
  47. checkCode := checkCodes[sum%11]
  48. lastChar := strings.ToUpper(string(idCard[17]))
  49. return checkCode == lastChar
  50. }
  51. // isValidChineseName 验证中文姓名
  52. func isValidChineseName(name string) bool {
  53. if name == "" {
  54. return false
  55. }
  56. // 长度检查: 2-20个字符
  57. runeCount := len([]rune(name))
  58. if runeCount < 2 || runeCount > 20 {
  59. return false
  60. }
  61. // 检查是否包含中文字符
  62. hasChinese := false
  63. for _, r := range name {
  64. if unicode.Is(unicode.Han, r) {
  65. hasChinese = true
  66. }
  67. }
  68. if !hasChinese {
  69. return false
  70. }
  71. // 允许中文、·(间隔号,用于少数民族姓名)
  72. pattern := `^[\p{Han}·]+$`
  73. matched, _ := regexp.MatchString(pattern, name)
  74. return matched
  75. }
  76. // isValidChinesePostcode 验证中国邮政编码
  77. func isValidChinesePostcode(postcode string) bool {
  78. // 中国邮政编码: 6位数字
  79. pattern := `^\d{6}$`
  80. matched, _ := regexp.MatchString(pattern, postcode)
  81. return matched
  82. }
  83. // isValidUSCC 验证统一社会信用代码
  84. func isValidUSCC(uscc string) bool {
  85. // 统一社会信用代码: 18位
  86. if len(uscc) != 18 {
  87. return false
  88. }
  89. // 基本格式验证
  90. pattern := `^[0-9A-HJ-NPQRTUWXY]{2}\d{6}[0-9A-HJ-NPQRTUWXY]{10}$`
  91. matched, _ := regexp.MatchString(pattern, uscc)
  92. if !matched {
  93. return false
  94. }
  95. // TODO: 添加校验位算法验证
  96. return true
  97. }
  98. // isValidBankCard 验证银行卡号(Luhn 算法)
  99. func isValidBankCard(cardNumber string) bool {
  100. // 移除空格
  101. cardNumber = strings.ReplaceAll(cardNumber, " ", "")
  102. // 长度检查: 13-19位
  103. if len(cardNumber) < 13 || len(cardNumber) > 19 {
  104. return false
  105. }
  106. // 必须全是数字
  107. for _, r := range cardNumber {
  108. if !unicode.IsDigit(r) {
  109. return false
  110. }
  111. }
  112. // Luhn 算法验证
  113. return luhnCheck(cardNumber)
  114. }
  115. // luhnCheck Luhn 算法校验
  116. func luhnCheck(cardNumber string) bool {
  117. sum := 0
  118. alternate := false
  119. // 从右往左遍历
  120. for i := len(cardNumber) - 1; i >= 0; i-- {
  121. digit, _ := strconv.Atoi(string(cardNumber[i]))
  122. if alternate {
  123. digit *= 2
  124. if digit > 9 {
  125. digit -= 9
  126. }
  127. }
  128. sum += digit
  129. alternate = !alternate
  130. }
  131. return sum%10 == 0
  132. }