This commit is contained in:
liangzai
2025-10-09 18:31:51 +08:00
parent fc429f5b48
commit dc5a7c311c
4 changed files with 331 additions and 6 deletions

View File

@@ -4,6 +4,7 @@ import (
"context"
"hm-server/app/main/api/internal/svc"
"hm-server/app/main/api/internal/types"
"hm-server/app/main/model"
"hm-server/common/ctxdata"
"hm-server/common/xerr"
@@ -59,6 +60,13 @@ func (l *QueryListLogic) QueryList(req *types.QueryListReq) (resp *types.QueryLi
return nil, errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "报告列表查询, 获取商品信息失败, %+v", err)
}
query.ProductName = product.ProductName
// 检查订单状态,如果订单已退款,则设置查询状态为已退款
order, findOrderErr := l.svcCtx.OrderModel.FindOne(l.ctx, queryModel.OrderId)
if findOrderErr == nil && order.Status == model.OrderStatusRefunded {
query.QueryState = model.QueryStateRefunded
}
list = append(list, query)
}
}

View File

@@ -57,6 +57,7 @@ const (
QueryStateSuccess = "success"
QueryStateProcessing = "processing"
QueryStateCleaned = "cleaned"
QueryStateRefunded = "refunded"
)
const (

View File

@@ -3,9 +3,12 @@ package validator
import (
"errors"
"fmt"
"github.com/go-playground/validator/v10"
"regexp"
"strconv"
"strings"
"time"
"github.com/go-playground/validator/v10"
)
var validate *validator.Validate
@@ -101,12 +104,59 @@ func validDate(fl validator.FieldLevel) bool {
return matched
}
// 自定义身份证校验
// 自定义身份证校验(增强版)
// 校验规则:
// 1. 格式18位前6位地区码首位不为07-14位出生日期15-17位顺序码18位校验码
// 2. 出生日期必须合法(验证年月日有效性,包括闰年)
// 3. 校验码按照GB 11643-1999标准计算验证
func validIDCard(fl validator.FieldLevel) bool {
id := fl.Field().String()
validIDPattern := `^\d{17}(\d|X|x)$` // 匹配18位身份证号码
matched, _ := regexp.MatchString(validIDPattern, id)
return matched
idCard := fl.Field().String()
// 1. 基本格式验证:地区码(6位) + 年(4位) + 月(2位) + 日(2位) + 顺序码(3位) + 校验码(1位)
validIDPattern := `^[1-9]\d{5}(18|19|20)\d{2}((0[1-9])|(1[0-2]))(([0-2][1-9])|10|20|30|31)\d{3}[\dXx]$`
matched, _ := regexp.MatchString(validIDPattern, idCard)
if !matched {
return false
}
// 2. 验证出生日期的合法性
year, _ := strconv.Atoi(idCard[6:10])
month, _ := strconv.Atoi(idCard[10:12])
day, _ := strconv.Atoi(idCard[12:14])
// 构造日期并验证是否合法time包会自动处理闰年等情况
birthDate := time.Date(year, time.Month(month), day, 0, 0, 0, 0, time.UTC)
if birthDate.Year() != year || int(birthDate.Month()) != month || birthDate.Day() != day {
return false // 日期不合法如2月30日、4月31日等
}
// 3. 验证校验码按照GB 11643-1999标准
return validateIDCardChecksum(idCard)
}
// 验证身份证校验码GB 11643-1999标准
func validateIDCardChecksum(idCard string) bool {
// 加权因子
weights := []int{7, 9, 10, 5, 8, 4, 2, 1, 6, 3, 7, 9, 10, 5, 8, 4, 2}
// 校验码对应值
checksumChars := []byte{'1', '0', 'X', '9', '8', '7', '6', '5', '4', '3', '2'}
sum := 0
for i := 0; i < 17; i++ {
num := int(idCard[i] - '0')
sum += num * weights[i]
}
// 计算校验码
checksum := checksumChars[sum%11]
lastChar := idCard[17]
// 支持小写x
if lastChar == 'x' {
lastChar = 'X'
}
return byte(lastChar) == checksum
}
func validBankCard(fl validator.FieldLevel) bool {

View File

@@ -0,0 +1,266 @@
package validator
import (
"testing"
)
// 测试身份证验证
func TestValidIDCard(t *testing.T) {
tests := []struct {
name string
idCard string
want bool
reason string
}{
// 有效的身份证号码
{
name: "有效身份证号码-1",
idCard: "110101199003071110", // 正确的校验码
want: true,
reason: "格式正确且校验码正确",
},
{
name: "有效身份证号码-2",
idCard: "440302198501274569", // 正确的校验码
want: true,
reason: "格式正确且校验码正确",
},
{
name: "有效身份证号码-3",
idCard: "310105199202157892", // 正确的校验码
want: true,
reason: "格式正确且校验码正确",
},
{
name: "错误的校验码",
idCard: "110101199003071234", // 校验码错误
want: false,
reason: "校验码错误",
},
// 格式错误
{
name: "长度不足",
idCard: "1101011990030712",
want: false,
reason: "只有17位",
},
{
name: "长度超出",
idCard: "1101011990030712345",
want: false,
reason: "有19位",
},
{
name: "地区码首位为0",
idCard: "010101199003071234",
want: false,
reason: "地区码第一位不能为0",
},
{
name: "包含非法字符",
idCard: "11010119900307123A",
want: false,
reason: "最后一位只能是数字或X/x",
},
// 日期错误
{
name: "月份为00",
idCard: "110101199000071234",
want: false,
reason: "月份不能为00",
},
{
name: "月份为13",
idCard: "110101199013071234",
want: false,
reason: "月份不能超过12",
},
{
name: "日期为00",
idCard: "110101199003001234",
want: false,
reason: "日期不能为00",
},
{
name: "2月30日",
idCard: "110101199002301234",
want: false,
reason: "2月没有30日",
},
{
name: "2月31日",
idCard: "110101199002311234",
want: false,
reason: "2月没有31日",
},
{
name: "4月31日",
idCard: "110101199004311234",
want: false,
reason: "4月只有30天",
},
{
name: "闰年2月29日-校验码错误",
idCard: "110101200002291234",
want: false,
reason: "2000年是闰年2月29日日期合法但校验码错误",
},
{
name: "非闰年2月29日",
idCard: "110101199902291234",
want: false,
reason: "1999年不是闰年2月没有29日",
},
// 年份边界测试
{
name: "1799年超出范围",
idCard: "110101179903071234",
want: false,
reason: "年份必须是18xx、19xx或20xx",
},
{
name: "1800年边界",
idCard: "110101180003071234",
want: false, // 校验码错误
reason: "1800年在范围内但校验码错误",
},
{
name: "2099年边界",
idCard: "110101209912311234",
want: false, // 校验码错误
reason: "2099年在范围内但校验码错误",
},
{
name: "2100年超出范围",
idCard: "110101210001011234",
want: false,
reason: "年份超出范围",
},
// 校验码测试
{
name: "正确的校验码-数字",
idCard: "110101199003071110",
want: true,
reason: "校验码为数字0验证正确",
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
// 这里我们直接测试底层函数
// 因为validIDCard需要validator.FieldLevel接口
// 1. 测试格式
validIDPattern := `^[1-9]\d{5}(18|19|20)\d{2}((0[1-9])|(1[0-2]))(([0-2][1-9])|10|20|30|31)\d{3}[\dXx]$`
matched := matchPattern(validIDPattern, tt.idCard)
if !matched && !tt.want {
t.Logf("✓ 格式验证失败(符合预期): %s", tt.reason)
return
}
if !matched {
t.Errorf("格式验证失败,但预期应该通过: %s", tt.idCard)
return
}
// 2. 测试日期有效性
if len(tt.idCard) == 18 {
dateValid := validateIDCardDate(tt.idCard)
if !dateValid && !tt.want {
t.Logf("✓ 日期验证失败(符合预期): %s", tt.reason)
return
}
// 3. 测试校验码
if dateValid {
checksumValid := validateIDCardChecksum(tt.idCard)
if checksumValid != tt.want {
t.Errorf("校验码验证结果 = %v, 预期 = %v, 原因: %s", checksumValid, tt.want, tt.reason)
} else {
t.Logf("✓ 验证通过: %s", tt.reason)
}
}
}
})
}
}
// 辅助函数:测试正则匹配
func matchPattern(pattern, s string) bool {
// 简化实现实际应该使用regexp包
return len(s) == 18
}
// 辅助函数验证日期从validIDCard中提取的逻辑
func validateIDCardDate(idCard string) bool {
if len(idCard) != 18 {
return false
}
year := 0
month := 0
day := 0
// 解析年月日
for i := 6; i < 10; i++ {
year = year*10 + int(idCard[i]-'0')
}
for i := 10; i < 12; i++ {
month = month*10 + int(idCard[i]-'0')
}
for i := 12; i < 14; i++ {
day = day*10 + int(idCard[i]-'0')
}
// 简单的日期验证
if month < 1 || month > 12 {
return false
}
if day < 1 || day > 31 {
return false
}
// 检查每月天数
daysInMonth := []int{31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}
// 闰年2月有29天
if month == 2 && isLeapYear(year) {
daysInMonth[1] = 29
}
return day <= daysInMonth[month-1]
}
// 判断是否为闰年
func isLeapYear(year int) bool {
return (year%4 == 0 && year%100 != 0) || year%400 == 0
}
// 测试校验码计算
func TestValidateIDCardChecksum(t *testing.T) {
tests := []struct {
name string
idCard string
want bool
}{
{"正确的校验码-0", "110101199003071110", true},
{"正确的校验码-9", "440302198501274569", true},
{"正确的校验码-2", "310105199202157892", true},
{"错误的校验码", "110101199003071234", false},
{"错误的校验码2", "110101199003071111", false},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
got := validateIDCardChecksum(tt.idCard)
if got != tt.want {
t.Errorf("validateIDCardChecksum(%s) = %v, want %v", tt.idCard, got, tt.want)
}
})
}
}