1
0
mirror of https://github.com/duke-git/lancet.git synced 2026-02-04 12:52:28 +08:00

feat: add IsChineseHMPassport

This commit is contained in:
dudaodong
2025-08-21 14:13:43 +08:00
parent 9f0ad2354a
commit 7d4b9510a2
5 changed files with 209 additions and 83 deletions

View File

@@ -1,51 +1,51 @@
-----BEGIN rsa private key-----
MIIJKQIBAAKCAgEAt8K0R1gvIA4MAX0lpFtVhcZQaGd5/4I2W+LESIO/7o1PWh2L
odghN4OFF0Wfg+/TBZXXAfzCH5MlLtu7w89fee/vLMUpRqTxIR26pybgKKi3RUEQ
b69PMuq8fFEpNwYc5n+rFNg531Jn/qylDnMSpfTn2qHNrLUnMOMR+hnAh3yBJpAx
61V/8BlFuCUx/99r3uZY0xKA7Hr7OlEvCsvguAzHhPPnhTf37zsiebpoWluTadq9
XO2XfBKcIb/MXzOhb+fR9mqJ3ajy8xGhtI3HQK1wfjF1c/uzyatjDHfzpCTF00v6
k3pEH646sHJjgzCs+ZT4wXZU2YiIyrFpr64RvpBaERXBjBe2jlEC9fKnFCYfkBSW
3oYHi1Mh5C7DW/ttzKBjVyS8sBF2L9X+PoRJQNH7yp4kED18XQwrzuLaJ8xJzQNn
vVjWxzPeXngmX+CIIlNCt3zc2hLPTteqbpmKVuZusrSz4O8d6Qqwo4ofhj/gz67v
31lsrOCOc5tkuXRfikUHGbEOE7S2zfSlh2wAsgSX/LjQZH6WHyZqLJIVTcrccouZ
DkCBbQhuGJMTA2VOUZkKPB8RJ8Fw3su/ge9Ndig8YNSAjbWFFSFl1tyncWuadS04
6IXVLF80a/z66i8OOQ6D/uUjGWWKIbUFp/w3hOlLNXLCnCRV/LJ1L4UmzusCAwEA
AQKCAgABLU9h1CK8Ecr2oGlHWB6NA14yz6lCv1VlmXgzHLQepJqZJN2AhmBMn4+I
GocXdxSLb2FcARDhX8KJCv+5P5UEZ7ENQNvElsS8Nu6zBmHA11DfD9ow/5s5sMOL
CCr7cjU16fD1e7hmG2sdkekvRIqveCtWzg4KKMjhPnKNh5LlfFQ7kwiH4vubw+sB
5taN+udEVx/2dIkNVE7bs0Pib+shdMqyw0XWUit8EloxNgHPkYzKIfK0Wl72dC5T
5a2QVVb1mrNH8d7yqALOFwZjObPIpfgCYy2T2DwszHjLGzfYyJoL6JYbuFAPuVoy
A7oVYN0z1PlFtuI3HL5l9KB75tBsEhmU9GBrf/GzjkgogW0OOcKbZ1yDxRrSWzVy
AJ2yu18EB1KiSbhV7K0XS2BlGSXzYnGg8Ok3q5HMJ1lWdJ5oFLzWariXXA4L0cca
7gu+Zc3cp2tSNOBHTcrYuIZKjWKoCDmrOsQ5fTcmczLXzWlEqwj7ZTLNLrhRYSiB
FjLc+U2oLvP+DsUu6H2gkbtssu3o23vgzb+lAN9Ics5W0NvLt9EQpbr+3ZTSo2Np
/S8QlFWm0sSuHF/fYCgFQMVu8qKxopWbzomYq0s/IQIS0J6JaqHXLcEXoOddRuqa
NTzG1J3Km6bM3Qf+6Fz0GBaTDxhcQIJhpn0SbruHJgFafu3AaQKCAQEA4yK2FIO9
Xd6cycpCU6uuwpIm63yjYCFU9W3XLhXh3LBeKfmgOL/0QNMnpdLuZX1UssEBLfw0
FMeqWIK9InC72HPsnn92GvkVu7snrquulR1mhNYZbouRLjLg85tyiC2ouJXcb4hx
eV2xbU8UK/GIL0j+x0ZMXCTe3dmHupixjnQj/eXmXDNk68upYK2ncwjsBH1EafgT
5+rcQ3SVRACoQUJtWpbI2BqfSsNj9LNc+hMH22dy5Nyzu77UmCnbJv+xddrGTKrX
ixcpd6Nz9uiFpq/kghbTLhFGrj+wF8KAFS1spRabDwcdDrc3ZrXOtlM71JC/Z4kF
SJJDXv/cnnitowKCAQEAzxzlFS3dI//jtwF/FLBZ+Y8EtxE00FxoO/TkiAaw54nl
86kx1lKdo9KjuRHLob6wTDq8Lg0zPCjsd9aP9W6V1+mp8Dcf/9bmFfmtfwLEWqXA
0ZcmV3L7UN8er/LX6tA9GfcDGAbztvtvh50ALgS3pNxYl0jSKHVh0LAD3T/r58/H
4/CrUHAxjiWXlQym+nzAfsq2qlXqLrIZdpglkSiQEBD8WeeKj1vLO9DGWLw1fjhT
Ta7vXxdkqAsS993zA46YJj+zXVNRpV47rzS4taMCEYVXcjr0t7NxUiKKRNsvnpdV
+HnICbVSdN+GXVqihqCFdJ55AoK4IkS4siYAF7ReGQKCAQEA2QeIza9XmUMls1bU
65gHQ5ldIPQWM7uFr4GF814rU7EeOKNyKeeYnvxkTPlwm38XGDp9QxBSP2zNYweB
a1Am3VtfQ89s7bcFwjzBXRBkn8zY8aKV6F/pmCg7c+oblO1z4vQnDldkfeA9scG2
94oxY2UvNQAB5KXCYl8BZxWRyxlEbs1mwMDG9NvEe0FS2AM1adC8Nzk45Agw8S+L
lM+/9aNgVAfx3zQI8uoiL2XXOIhIoKeHTBFql8Fu5/pOkkQNsBwcEJPJovi9wbho
DQv+8Nfu0zK2FLWjQMpQG1PZCOM/hbtE7CYS6MW+ZSDhZKvBZonsqiRt7Pr87uAy
USXkWwKCAQBIDBcszO2Wrld6vAyHF+nUxImxXUzwBpVD9ibhouI7SV8y6fKqSccI
zCekI6qgs4MEoZIAuxrNnLbV4U/m4vdBSsmRBLwe9ZTIpDhUbJP9rJds0ZXG6fq+
4T79mg6+Yn4+4Ay1eQWi68iadmUvnPh9YyF2TyC8bkj+nZxahPf9hexVQM13h+/V
MQKQGPylOmyELuRoUMbMQ6xT8w1ud5vV2vLOG5u5zwbd4fx9tcsuA04HQgmHHM4p
HuEUVKNK43nOJG6y0l8ela9RfZebp/76NVZ8KEIk/Uk4d0d+OHlSQ/bmHwcVSXxL
p85H/1V2W7TRIqeZ1ftUAG/3mPyDQn1RAoIBAQCW2zoLgqqd7qjij6rR5iOffLwb
cjOBSLbWC9xyizoeMDtelqK5E+iGBWIxkpotZcfVvOfTcO6IBHqVUDDGGMzkuMSM
LsCXkOS/qYWJD1a1xyjT+GjjfLUwuhW/AYSJ/98VFiHaEvbofvt30+lMUIP565kr
ycTIL+OAiqMXTI9GpDhQDCN4lVLDUHBw6YIemzLtfhXCxKmfWYglyLtWry0CT2hX
SVuY0fg4dEL2T1Oieq8L3iVnL37LJhp23G1xJqFsctPahrQ5HaF1b/B6R71cHLDa
T2gLjPvkOf5zJpvsUtoPBY8wUpyRpeKIilrRs6XqRDQtEGEsPR/btSxWL0T1
MIIJKAIBAAKCAgEAxBXtNRZ18uz+ujnKC/CB6bYjOHn0++xX1tbqRoRfP4VP01R/
k9d28sI9cqQa9Oqo3TPehKAyR4m3p9ZJ+pOgNLpe7QEPWSGqIvPILRqS/4NnnjBu
KvRHRTqiQwiuzTo/BBTxJCtF028Q7yRKmloEdtrdFryqsZmTrtMIvaNneTa/Bnx3
3s4vfAm76wNKF5li0AN7NsmKfWjOG7/f29qp9rTJEBnCIKImrwTFY9BWrx83LPDA
Uq8tpn8zevEe0c/42yZNlBprea4FIdZs8A/3gDZE7kltYjdybox0XWjR9znWPLmH
3De+1xJ0woJ53f3jYDJ3REwmm8+sX26FIT3WPN/ksVgHsoaj2IZ3MaEkxf4E4GEp
9sMSP8b+ans/B5gmcZi2pO8nx/ASVlxCthUSaK92CsoKHzqTotaZ+/dt689qT4zu
qUWZpnlLIUKd0t1G485S8km15GgPcMY5vXe13i8dmsxVRIjgYclSClKCnDBTTAV5
GUSPnanPU4N0dlKpO0UxzILixaw227yw7zDy+rQ8ixchQ+ROQ6I4bdced7FuVXfE
Aa2gVuzm3uZ1J/xDnV6xwLYye2SitlzAL0wA/mFAF6koSa6+MYV+tzdPta2Xkw9x
mO3a5PKwhCvOUbEMBJfLI2GPAfTuPh1LH4MZqFUgzYHUiBCI21N3kMVPGAUCAwEA
AQKCAgBV6jGL4DJ/5P1bRTTU9GVHrKlT9oOz2gNGu9XcXeWJ5HRsaQqZEYApr5fS
4jp5c1PX0AFAZRyCocHZhRfW9dXtJHexKpS5/fkY5W2g7ZLY54+ADUJICc4sdBti
eax1eX7g3/gkW911XaWy0ljptmVcWlsiujmkJWFC6W5cAPu2bZlXUzQGaJr/oxg2
SbOuEWPtNolHIRlQB5q/J9wC7ZUo5l9ucYrQV5vRdaqzKDbC9k9rnnT2BZFf8T3y
MTHKxnAIPYkiSk0q/Gd9QwFqUeSkxaKAMaX+scKu01WtE99jjnDjHHt9ruMsQwbr
rtWMwdBddt8xCpikDmM9USR9wyVZtC6ARo8DBZGdua+Le76IN6hvxoux3qEsZyzf
WJj1kE9KOd+FAGfaXr7R2LKZpdbDF1bRkZWarxiYipZU+jSO+T4Ml9Rgb+qeU/H5
C6G0zP16N6WGumhaPE7tqGjIFq1MYdq35elQkHFeVQ+jp/deLlzNl2Icfpnk4bLf
2LBU/7LInSDtA5s+AOin3wgNcVrsY9tmMlt07aG9CO7aVrLMIQsdiR+w5b8/Pu5X
nrmAWHMaHLQ6b2vuVhMxcgZGjRS0meNH93js0vxsyt6VNrEmxk3/qD8Y17YEVqLD
ZMUqbKi2l4QO4mAPyioylE+lUtW7RRiDkUvPW4d5q8ZKVNbS5QKCAQEA7Pyg1EFX
ylFc1sz6w4ZTyRwLyYb+PMuB251Q5gNotnYkf0ruHMrQR4zHqB8eOci9dqV4NADH
HfTCKNlMQ4L6fAdZByTMXZhXLq9Y2xMUkLk2YRxIb+ES/rGFJ4bY7tOUPoN1StAR
SpwHkA0icJgi8AqWDuil5CqVsBVpYdt6DA68law2CPrna8c5xG0YaO/tdH4j4bek
5ckOxU6YOpidpHt3h6pfSJ7HcZeH2j+zmfqDCcjdRZWMv+ntB23ooHEDi7/rGjQK
E3t5svnP+eC4arTiuYr+CrUCbNNEqGyRuy8O+UrAWFjwo7+BsiUZvg9HOERBu/Yy
YK/omoLgeurGAwKCAQEA09E/FlRJxhQi81QwpjOv2oV3dtwxmwxh9wdtGvMDiCVM
q3+kB3agmtynVzY/53roejVi8tVSVBjwW+KxWzKjGwP7XVl1KpeeKwmAlk3tzUud
LFAqoa7DH6C2n/zScRFntxtrTCSiqJ32DHYseHwKK4wjCfmtirh21vNAlfmcdr9d
h+FJzPv1JQQU6EfdS2/Bz36NUHty7POSHCZiUKvOKLw2K2SjQ6u+KPtReZ+9s/Zv
pJmD4YeZrDAjdsqikuRLMLjZat3HjiBVh5VjAdviYwSVsdq4Y7BIs//f3b3HnHgb
w+dmADmkI7lcWkv6UXsw/XI+f2Y9uo5cnXGgFOPvVwKCAQAECRlEBAjWrSQDlGIA
ylzK4+tfdykFKAICF1+1SwGRedmNQV1kqB972G3d8wm0ujJfvtmZKRo67FwSDgE6
dRSG4Ckn8fx464swhFPjByQmgsDmTnD9VrvYEnXOAoHXL0sq9Vod+AUTXCzUyyR2
/mA57jQ39MY+aGs8IGE3BWHCqs2TTudsp7khILdfHOx5fPxyK2O5CEOKli3mNjxp
YwfsMR4L9V7CAdIroQTzNnp8eMOaew0pji5jZjxfEAQSF1qUGqSKQbCaPFQKNC7S
dn0tc/8YYcGJtSNhbweQRqkEovyCSj+UQY93el9fBTq2/dOcpazo4nxhIR2449mm
vjC5AoIBAF6glkyFb0fcaxjFvc4iPSekhJBHIqofyAwx9x4Y/rTt5Oig50imSG2m
seOWSspA8GbYPtI5VsRXN9n01kLlxlQlXUCA3IUgovqbDiUXv2r9osPPNJxylJ0m
kS+8JM96dRkqWK71lu05VFiQ2qEg2PJHcsfcERlt+zlgBrR5hNrP9xrjHLNExGm6
/xQeNtCiprTp1nvkCp2s2tNUmotrlXhBTPnpxb5PlW59iBKLuJYTPCEOrAovKAny
n4VMVYDGGIk1q3vAhIwMCem+ZTLJZsPRooaILePrNy+i2gIX7HsMdWr5j2n+VkPX
ZVi5pKSOIn63cRA9Psp/GwUDY/6xLZUCggEBAMOy/fy6eeGy9kGizn6j+68Rg29+
qCE2CVXLeFU9VpRnO6oSL5dWGEoEtjs6rgPUs7yWPb0c7u9LH93ba20xMFl1MStK
LQMdYJcVtShMplJzW0NeoWK3pnT+1GfAmzGM69ZF8NAbRYuh68fwe/xanr8SrbBS
EszhoAz5Ei7jEiWFWBCsm6MAs0wa4n2emyD2XJSTjqRULfaZwN5yThjbZ09QZ4Bq
HfhMenWPMa+QZpiEEHebXczlULFQcOO0QXx+VfuGIiYk+UDPhUuN1E/KqhOuqR34
f1tU3jwqz9fQ6VHH2hP/+jmEre/9E1D9c3EImqgT0wNR/gMTNtQ0t0Js2Xk=
-----END rsa private key-----

View File

@@ -1,14 +1,14 @@
-----BEGIN rsa public key-----
MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAt8K0R1gvIA4MAX0lpFtV
hcZQaGd5/4I2W+LESIO/7o1PWh2LodghN4OFF0Wfg+/TBZXXAfzCH5MlLtu7w89f
ee/vLMUpRqTxIR26pybgKKi3RUEQb69PMuq8fFEpNwYc5n+rFNg531Jn/qylDnMS
pfTn2qHNrLUnMOMR+hnAh3yBJpAx61V/8BlFuCUx/99r3uZY0xKA7Hr7OlEvCsvg
uAzHhPPnhTf37zsiebpoWluTadq9XO2XfBKcIb/MXzOhb+fR9mqJ3ajy8xGhtI3H
QK1wfjF1c/uzyatjDHfzpCTF00v6k3pEH646sHJjgzCs+ZT4wXZU2YiIyrFpr64R
vpBaERXBjBe2jlEC9fKnFCYfkBSW3oYHi1Mh5C7DW/ttzKBjVyS8sBF2L9X+PoRJ
QNH7yp4kED18XQwrzuLaJ8xJzQNnvVjWxzPeXngmX+CIIlNCt3zc2hLPTteqbpmK
VuZusrSz4O8d6Qqwo4ofhj/gz67v31lsrOCOc5tkuXRfikUHGbEOE7S2zfSlh2wA
sgSX/LjQZH6WHyZqLJIVTcrccouZDkCBbQhuGJMTA2VOUZkKPB8RJ8Fw3su/ge9N
dig8YNSAjbWFFSFl1tyncWuadS046IXVLF80a/z66i8OOQ6D/uUjGWWKIbUFp/w3
hOlLNXLCnCRV/LJ1L4UmzusCAwEAAQ==
MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAxBXtNRZ18uz+ujnKC/CB
6bYjOHn0++xX1tbqRoRfP4VP01R/k9d28sI9cqQa9Oqo3TPehKAyR4m3p9ZJ+pOg
NLpe7QEPWSGqIvPILRqS/4NnnjBuKvRHRTqiQwiuzTo/BBTxJCtF028Q7yRKmloE
dtrdFryqsZmTrtMIvaNneTa/Bnx33s4vfAm76wNKF5li0AN7NsmKfWjOG7/f29qp
9rTJEBnCIKImrwTFY9BWrx83LPDAUq8tpn8zevEe0c/42yZNlBprea4FIdZs8A/3
gDZE7kltYjdybox0XWjR9znWPLmH3De+1xJ0woJ53f3jYDJ3REwmm8+sX26FIT3W
PN/ksVgHsoaj2IZ3MaEkxf4E4GEp9sMSP8b+ans/B5gmcZi2pO8nx/ASVlxCthUS
aK92CsoKHzqTotaZ+/dt689qT4zuqUWZpnlLIUKd0t1G485S8km15GgPcMY5vXe1
3i8dmsxVRIjgYclSClKCnDBTTAV5GUSPnanPU4N0dlKpO0UxzILixaw227yw7zDy
+rQ8ixchQ+ROQ6I4bdced7FuVXfEAa2gVuzm3uZ1J/xDnV6xwLYye2SitlzAL0wA
/mFAF6koSa6+MYV+tzdPta2Xkw9xmO3a5PKwhCvOUbEMBJfLI2GPAfTuPh1LH4MZ
qFUgzYHUiBCI21N3kMVPGAUCAwEAAQ==
-----END rsa public key-----

View File

@@ -27,21 +27,22 @@ var (
urlMatcher *regexp.Regexp = regexp.MustCompile(`^((ftp|http|https?):\/\/)?(\S+(:\S*)?@)?((([1-9]\d?|1\d\d|2[01]\d|22[0-3])(\.(1?\d{1,2}|2[0-4]\d|25[0-5])){2}(?:\.([0-9]\d?|1\d\d|2[0-4]\d|25[0-4]))|(([a-zA-Z0-9]+([-\.][a-zA-Z0-9]+)*)|((www\.)?))?(([a-z\x{00a1}-\x{ffff}0-9]+-?-?)*[a-z\x{00a1}-\x{ffff}0-9]+)(?:\.([a-z\x{00a1}-\x{ffff}]{2,}))?))(:(\d{1,5}))?((\/|\?|#)[^\s]*)?$`)
dnsMatcher *regexp.Regexp = regexp.MustCompile(`^(?:[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?\.)+[a-zA-Z]{2,}$`)
// emailMatcher *regexp.Regexp = regexp.MustCompile(`^[a-z0-9._%+\-]+@[a-z0-9.\-]+\.[a-z]{2,4}$`)
emailMatcher *regexp.Regexp = regexp.MustCompile(`\w+(-+.\w+)*@\w+(-.\w+)*.\w+(-.\w+)*`)
chineseMobileMatcher *regexp.Regexp = regexp.MustCompile(`^1(?:3\d|4[4-9]|5[0-35-9]|6[67]|7[013-8]|8\d|9\d)\d{8}$`)
chineseIdMatcher *regexp.Regexp = regexp.MustCompile(`([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{2}[0-9Xx])`)
chineseMatcher *regexp.Regexp = regexp.MustCompile("[\u4e00-\u9fa5]")
chinesePhoneMatcher *regexp.Regexp = regexp.MustCompile(`\d{3}-\d{8}|\d{4}-\d{7}|\d{4}-\d{8}`)
creditCardMatcher *regexp.Regexp = regexp.MustCompile(`^(?:4[0-9]{12}(?:[0-9]{3})?|5[1-5][0-9]{14}|(222[1-9]|22[3-9][0-9]|2[3-6][0-9]{2}|27[01][0-9]|2720)[0-9]{12}|6(?:011|5[0-9][0-9])[0-9]{12}|3[47][0-9]{13}|3(?:0[0-5]|[68][0-9])[0-9]{11}|(?:2131|1800|35\\d{3})\\d{11}|6[27][0-9]{14})$`)
base64Matcher *regexp.Regexp = regexp.MustCompile(`^(?:[A-Za-z0-9+\\/]{4})*(?:[A-Za-z0-9+\\/]{2}==|[A-Za-z0-9+\\/]{3}=|[A-Za-z0-9+\\/]{4})$`)
base64URLMatcher *regexp.Regexp = regexp.MustCompile(`^([A-Za-z0-9_-]{4})*([A-Za-z0-9_-]{2}(==)?|[A-Za-z0-9_-]{3}=?)?$`)
binMatcher *regexp.Regexp = regexp.MustCompile(`^(0b)?[01]+$`)
hexMatcher *regexp.Regexp = regexp.MustCompile(`^(#|0x|0X)?[0-9a-fA-F]+$`)
visaMatcher *regexp.Regexp = regexp.MustCompile(`^4[0-9]{12}(?:[0-9]{3})?$`)
masterCardMatcher *regexp.Regexp = regexp.MustCompile(`^5[1-5][0-9]{14}$`)
americanExpressMatcher *regexp.Regexp = regexp.MustCompile(`^3[47][0-9]{13}$`)
unionPayMatcher *regexp.Regexp = regexp.MustCompile(`^62[0-5]\\d{13,16}$`)
chinaUnionPayMatcher *regexp.Regexp = regexp.MustCompile(`^62[0-9]{14,17}$`)
emailMatcher *regexp.Regexp = regexp.MustCompile(`\w+(-+.\w+)*@\w+(-.\w+)*.\w+(-.\w+)*`)
chineseMobileMatcher *regexp.Regexp = regexp.MustCompile(`^1(?:3\d|4[4-9]|5[0-35-9]|6[67]|7[013-8]|8\d|9\d)\d{8}$`)
chineseIdMatcher *regexp.Regexp = regexp.MustCompile(`([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{2}[0-9Xx])`)
chineseMatcher *regexp.Regexp = regexp.MustCompile("[\u4e00-\u9fa5]")
chinesePhoneMatcher *regexp.Regexp = regexp.MustCompile(`\d{3}-\d{8}|\d{4}-\d{7}|\d{4}-\d{8}`)
creditCardMatcher *regexp.Regexp = regexp.MustCompile(`^(?:4[0-9]{12}(?:[0-9]{3})?|5[1-5][0-9]{14}|(222[1-9]|22[3-9][0-9]|2[3-6][0-9]{2}|27[01][0-9]|2720)[0-9]{12}|6(?:011|5[0-9][0-9])[0-9]{12}|3[47][0-9]{13}|3(?:0[0-5]|[68][0-9])[0-9]{11}|(?:2131|1800|35\\d{3})\\d{11}|6[27][0-9]{14})$`)
base64Matcher *regexp.Regexp = regexp.MustCompile(`^(?:[A-Za-z0-9+\\/]{4})*(?:[A-Za-z0-9+\\/]{2}==|[A-Za-z0-9+\\/]{3}=|[A-Za-z0-9+\\/]{4})$`)
base64URLMatcher *regexp.Regexp = regexp.MustCompile(`^([A-Za-z0-9_-]{4})*([A-Za-z0-9_-]{2}(==)?|[A-Za-z0-9_-]{3}=?)?$`)
binMatcher *regexp.Regexp = regexp.MustCompile(`^(0b)?[01]+$`)
hexMatcher *regexp.Regexp = regexp.MustCompile(`^(#|0x|0X)?[0-9a-fA-F]+$`)
visaMatcher *regexp.Regexp = regexp.MustCompile(`^4[0-9]{12}(?:[0-9]{3})?$`)
masterCardMatcher *regexp.Regexp = regexp.MustCompile(`^5[1-5][0-9]{14}$`)
americanExpressMatcher *regexp.Regexp = regexp.MustCompile(`^3[47][0-9]{13}$`)
unionPayMatcher *regexp.Regexp = regexp.MustCompile(`^62[0-5]\\d{13,16}$`)
chinaUnionPayMatcher *regexp.Regexp = regexp.MustCompile(`^62[0-9]{14,17}$`)
chineseHMPassportMatcher *regexp.Regexp = regexp.MustCompile(`^[CM]\d{8}$`)
)
var passportMatcher = map[string]*regexp.Regexp{
@@ -601,14 +602,55 @@ func IsAmericanExpress(v string) bool {
// IsUnionPay check if a give string is a valid union pay nubmer or not.
// Play: https://go.dev/play/p/CUHPEwEITDf
func IsUnionPay(v string) bool {
return unionPayMatcher.MatchString(v)
func IsUnionPay(cardNo string) bool {
if len(cardNo) < 16 || len(cardNo) > 19 {
return false
}
matched, _ := regexp.MatchString(`^\d+$`, cardNo)
if !matched {
return false
}
if len(cardNo) < 3 {
return false
}
prefix := cardNo[:3]
prefixNum, err := strconv.Atoi(prefix)
if err != nil {
return false
}
if prefixNum < 620 || prefixNum > 625 {
return false
}
return true
}
// IsChinaUnionPay check if a give string is a valid china union pay nubmer or not.
// Play: https://go.dev/play/p/yafpdxLiymu
func IsChinaUnionPay(v string) bool {
return chinaUnionPayMatcher.MatchString(v)
func IsChinaUnionPay(cardNo string) bool {
return chinaUnionPayMatcher.MatchString(cardNo)
}
// luhnCheck checks if the credit card number is valid using the Luhn algorithm.
func luhnCheck(card string) bool {
var sum int
alt := false
for i := len(card) - 1; i >= 0; i-- {
n := int(card[i] - '0')
if alt {
n *= 2
if n > 9 {
n -= 9
}
}
sum += n
alt = !alt
}
return sum%10 == 0
}
// IsPassport checks if the passport number is valid for a given country.
@@ -621,3 +663,10 @@ func IsPassport(passport, country string) bool {
return false
}
// IsChineseHMPassport checks if the string is a valid Chinese Hong Kong and Macau Travel Permit number.
// Chinese Hong Kong and Macau Travel Permit format: C or M + 8 digits (e.g., C12345678, M12345678).
// Play: https://go.dev/play/p/TODO
func IsChineseHMPassport(hmPassport string) bool {
return chineseHMPassportMatcher.MatchString(hmPassport)
}

View File

@@ -701,3 +701,24 @@ func ExampleIsPassport() {
// true
// false
}
func ExampleIsChineseHMPassport() {
result1 := IsChineseHMPassport("C12345678")
result2 := IsChineseHMPassport("C00000000")
result3 := IsChineseHMPassport("M12345678")
result4 := IsChineseHMPassport("c12345678")
result5 := IsChineseHMPassport("C1234567")
fmt.Println(result1)
fmt.Println(result2)
fmt.Println(result3)
fmt.Println(result4)
fmt.Println(result5)
// Output:
// true
// true
// true
// false
// false
}

View File

@@ -933,7 +933,7 @@ func TestIsUnionPay(t *testing.T) {
t.Parallel()
assert := internal.NewAssert(t, "TestIsUnionPay")
assert.Equal(true, IsUnionPay("6221263430109903"))
assert.Equal(true, IsUnionPay("6228480402564890"))
assert.Equal(false, IsUnionPay("3782822463100007"))
}
@@ -941,8 +941,25 @@ func TestIsChinaUnionPay(t *testing.T) {
t.Parallel()
assert := internal.NewAssert(t, "TestIsChinaUnionPay")
assert.Equal(true, IsChinaUnionPay("6250941006528599"))
assert.Equal(false, IsChinaUnionPay("3782822463100007"))
tests := []struct {
cardNumber string
expected bool
}{
{"6228480420000000000", true},
{"6214830000000000", true},
{"6230580000000000000", true},
{"6259640000000000000", true},
{"6260000000000000000", true},
{"6288888888888888", true},
// 非银联前缀
{"4123456789012345", false},
{"3528000000000000", false},
}
for _, tt := range tests {
assert.Equal(tt.expected, IsChinaUnionPay(tt.cardNumber))
}
}
func TestIsAlphaNumeric(t *testing.T) {
@@ -1000,3 +1017,42 @@ func TestIsPassport(t *testing.T) {
assert.Equal(tt.expected, IsPassport(tt.passport, tt.countryCode))
}
}
func TestIsChineseHMPassport(t *testing.T) {
t.Parallel()
assert := internal.NewAssert(t, "TestIsChineseHMPassport")
tests := []struct {
input string
expected bool
}{
{"C12345678", true},
{"C00000000", true},
{"C99999999", true},
{"M12345678", true}, // M prefix
{"M00000000", true}, // M prefix
{"M99999999", true}, // M prefix
{"c12345678", false}, // lowercase c
{"m12345678", false}, // lowercase m
{"C1234567", false}, // 7 digits
{"M1234567", false}, // 7 digits with M
{"C123456789", false}, // 9 digits
{"M123456789", false}, // 9 digits with M
{"C1234567a", false}, // contains letter
{"M1234567a", false}, // contains letter with M
{"D12345678", false}, // starts with D
{"12345678", false}, // no prefix
{"CC12345678", false}, // double C
{"MM12345678", false}, // double M
{"C 12345678", false}, // contains space
{"M 12345678", false}, // contains space with M
{"C12345-678", false}, // contains dash
{"M12345-678", false}, // contains dash with M
{"", false},
}
for _, tt := range tests {
assert.Equal(tt.expected, IsChineseHMPassport(tt.input))
}
}