package auth import ( "context" "database/sql" "encoding/hex" "math/rand" "strconv" "time" "qnc-server/app/user/cmd/api/internal/svc" "qnc-server/app/user/cmd/api/internal/types" "qnc-server/app/user/model" "qnc-server/common/xerr" "qnc-server/pkg/core/aliyun/cloudauth" "qnc-server/pkg/lzkit/crypto" "github.com/pkg/errors" "github.com/zeromicro/go-zero/core/logx" "github.com/zeromicro/go-zero/core/stores/sqlx" ) type InitFaceVerifyLogic struct { logx.Logger ctx context.Context svcCtx *svc.ServiceContext } func NewInitFaceVerifyLogic(ctx context.Context, svcCtx *svc.ServiceContext) *InitFaceVerifyLogic { return &InitFaceVerifyLogic{ Logger: logx.WithContext(ctx), ctx: ctx, svcCtx: svcCtx, } } // 生成带前缀的随机OuterOrderNo(阿里云人脸验证单号) func genOuterOrderNo() string { prefix := "FACE_" timestamp := time.Now().UnixNano() randNum := rand.Intn(1000000) return prefix + strconv.FormatInt(timestamp, 10) + strconv.Itoa(randNum) } func (l *InitFaceVerifyLogic) InitFaceVerify(req *types.InitFaceVerifyReq) (resp *types.InitFaceVerifyResp, err error) { order, err := l.svcCtx.OrderModel.FindOneByOrderNo(l.ctx, req.OrderNo) if err != nil { return nil, errors.Wrapf(xerr.NewErrCode(xerr.DB_ERROR), "查询订单失败: %v", err) } if order.Status != "paid" { return nil, errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "订单未支付") } authorization, err := l.svcCtx.AuthorizationModel.FindOneByOrderId(l.ctx, order.Id) if err != nil { return nil, errors.Wrapf(xerr.NewErrCode(xerr.DB_ERROR), "查询授权信息失败: %v", err) } if authorization.Status != "pending" { return nil, errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "授权信息状态不正确") } key, decodeErr := hex.DecodeString(l.svcCtx.Config.Encrypt.SecretKey) if decodeErr != nil { return nil, errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "查询授权信息失败: %v", decodeErr) } if authorization.GrantType == "face" { authorizationFaceBuilder := l.svcCtx.AuthorizationFaceModel.SelectBuilder(). Where("authorization_id = ? AND status = ? AND certify_id != '' AND certify_url != ''", authorization.Id, model.AuthorizationStatusPending). OrderBy("create_time DESC"). Limit(1) existingFaces, err := l.svcCtx.AuthorizationFaceModel.FindAll(l.ctx, authorizationFaceBuilder, "") if err != nil { return nil, errors.Wrapf(xerr.NewErrCode(xerr.DB_ERROR), "查询人脸认证记录失败: %v", err) } if len(existingFaces) > 0 { // 如果存在记录,直接返回最新的认证信息 return &types.InitFaceVerifyResp{ CertifyId: existingFaces[0].CertifyId, CertifyUrl: existingFaces[0].CertifyUrl, }, nil } } outerOrderNo := genOuterOrderNo() name, err := crypto.AesDecrypt(authorization.TargetName, key) if err != nil { return nil, errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "解密姓名失败: %v", err) } idCard, err := crypto.AesDecrypt(authorization.TargetIdcard, key) if err != nil { return nil, errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "解密身份证号失败: %v", err) } initFaceVerifyResp, err := l.svcCtx.CloudAuthService.InitFaceVerify(cloudauth.InitFaceVerifyParam{ OuterOrderNo: outerOrderNo, CertName: string(name), CertNo: string(idCard), MetaInfo: req.MetaInfo, }) if err != nil { return nil, errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "初始化人脸认证失败: %v", err) } err = l.svcCtx.AuthorizationModel.Trans(l.ctx, func(ctx context.Context, session sqlx.Session) error { authorization.AuthType = sql.NullInt64{ Int64: req.AuthType, Valid: true, } _, err = l.svcCtx.AuthorizationModel.Update(l.ctx, session, authorization) if err != nil { return err } authorizationFace := &model.AuthorizationFace{ AuthorizationId: authorization.Id, CertifyId: initFaceVerifyResp.CertifyId, CertifyUrl: initFaceVerifyResp.CertifyUrl, Status: model.AuthorizationStatusPending, CertifyUrlExpireAt: time.Now().Add(time.Minute * 30), OuterOrderNo: outerOrderNo, } _, err = l.svcCtx.AuthorizationFaceModel.Insert(l.ctx, session, authorizationFace) if err != nil { return err } return nil }) if err != nil { return nil, errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "更新授权信息失败: %v", err) } return &types.InitFaceVerifyResp{ CertifyId: initFaceVerifyResp.CertifyId, CertifyUrl: initFaceVerifyResp.CertifyUrl, }, nil }