|
|
package biz
|
|
|
|
|
|
import (
|
|
|
"context"
|
|
|
"database/sql"
|
|
|
"github.com/go-kratos/kratos/v2/errors"
|
|
|
"github.com/golang-jwt/jwt/v4"
|
|
|
"gorm.io/gorm"
|
|
|
"regexp"
|
|
|
"strings"
|
|
|
"time"
|
|
|
)
|
|
|
|
|
|
const SecretKey = "driver secret key"
|
|
|
|
|
|
// 司机业务逻辑
|
|
|
type DriverBiz struct {
|
|
|
DI DriverInterface
|
|
|
}
|
|
|
|
|
|
// 司机表模型
|
|
|
type Driver struct {
|
|
|
// 基础模型
|
|
|
gorm.Model
|
|
|
// 业务模型
|
|
|
DriverWork
|
|
|
// 关联部分
|
|
|
}
|
|
|
|
|
|
// 司机的业务模型
|
|
|
type DriverWork struct {
|
|
|
Telephone string `gorm:"type:varchar(16);uniqueIndex;" json:"telephone"`
|
|
|
Token sql.NullString `gorm:"type:varchar(2047);" json:"token"`
|
|
|
Status sql.NullString `gorm:"type:enum('out', 'in', 'listen', 'stop');" json:"status"`
|
|
|
Name sql.NullString `gorm:"type:varchar(255);index;" json:"name"`
|
|
|
IdNumber sql.NullString `gorm:"type:char(18);uniqueIndex;" json:"id_number"`
|
|
|
IdImageA sql.NullString `gorm:"type:varchar(255);" json:"id_image_a"`
|
|
|
LicenseImageA sql.NullString `gorm:"type:varchar(255);" json:"license_image_a"`
|
|
|
LicenseImageB sql.NullString `gorm:"type:varchar(255);" json:"license_image_b"`
|
|
|
DistinctCode sql.NullString `gorm:"type:varchar(16);index;" json:"distinct_code"`
|
|
|
TelephoneBak sql.NullString `gorm:"type:varchar(16);index;" json:"telephone_bak"`
|
|
|
AuditAt sql.NullTime `gorm:"index;" json:"audit_at"`
|
|
|
}
|
|
|
|
|
|
// 司机状态常量
|
|
|
const DriverStatusOut = "out"
|
|
|
const DriverStatusIn = "in"
|
|
|
const DriverStatusListen = "listen"
|
|
|
const DriverStatusStop = "stop"
|
|
|
const DriverTokenLife = 1 * 30 * 24 * 3600
|
|
|
|
|
|
// 司机相关的资源操作接口
|
|
|
type DriverInterface interface {
|
|
|
GetVerifyCode(context.Context, string) (string, error)
|
|
|
FetchVerifyCode(context.Context, string) (string, error)
|
|
|
FetchInfoByTel(context.Context, string) (*Driver, error)
|
|
|
InitDriverInfo(context.Context, string) (*Driver, error)
|
|
|
GetSavedVerifyCode(context.Context, string) (string, error)
|
|
|
SaveToken(context.Context, string, string) error
|
|
|
GetToken(context.Context, string) (string, error)
|
|
|
}
|
|
|
|
|
|
// DriverBiz 构造器
|
|
|
func NewDriverBiz(di DriverInterface) *DriverBiz {
|
|
|
return &DriverBiz{
|
|
|
DI: di,
|
|
|
}
|
|
|
}
|
|
|
|
|
|
// 验证登录信息方法
|
|
|
func (db *DriverBiz) CheckLogin(ctx context.Context, tel, verifyCode string) (string, error) {
|
|
|
// 验证验证码是否正确
|
|
|
code, err := db.DI.GetSavedVerifyCode(ctx, tel)
|
|
|
if err != nil {
|
|
|
return "", err
|
|
|
}
|
|
|
if verifyCode != code {
|
|
|
return "", errors.New(1, "verify code error", "'")
|
|
|
}
|
|
|
|
|
|
// 生成token
|
|
|
token, err := generateJWT(tel)
|
|
|
if err != nil {
|
|
|
return "", err
|
|
|
}
|
|
|
|
|
|
// 存储到driver表中
|
|
|
if err := db.DI.SaveToken(ctx, tel, token); err != nil {
|
|
|
return "", err
|
|
|
}
|
|
|
|
|
|
// 返回token
|
|
|
return token, nil
|
|
|
}
|
|
|
|
|
|
// 生成JWT
|
|
|
func generateJWT(tel string) (string, error) {
|
|
|
// 构建token类型
|
|
|
claims := jwt.RegisteredClaims{
|
|
|
Issuer: "LaomaDJ",
|
|
|
Subject: "driver authentication",
|
|
|
Audience: []string{"driver"},
|
|
|
ExpiresAt: jwt.NewNumericDate(time.Now().Add(DriverTokenLife * time.Second)),
|
|
|
NotBefore: nil,
|
|
|
IssuedAt: jwt.NewNumericDate(time.Now()),
|
|
|
ID: tel,
|
|
|
}
|
|
|
token := jwt.NewWithClaims(jwt.SigningMethodHS256, claims)
|
|
|
|
|
|
// 签名
|
|
|
// 生成token字符串
|
|
|
tokenString, err := token.SignedString([]byte(SecretKey))
|
|
|
if err != nil {
|
|
|
return "", err
|
|
|
}
|
|
|
|
|
|
return tokenString, nil
|
|
|
}
|
|
|
|
|
|
// 比对验证码是否一致
|
|
|
|
|
|
// 将司机信息入库
|
|
|
func (db *DriverBiz) InitDriverInfo(ctx context.Context, tel string) (*Driver, error) {
|
|
|
// 校验验证码(略)
|
|
|
// 司机是否已经注册的校验(略)?
|
|
|
// 司机是否在黑名单中校验(略)?
|
|
|
//
|
|
|
if tel == "" {
|
|
|
return nil, errors.New(1, "telephone is empty", "")
|
|
|
}
|
|
|
|
|
|
return db.DI.InitDriverInfo(ctx, tel)
|
|
|
}
|
|
|
|
|
|
// 实现获取验证码的业务逻辑
|
|
|
func (db *DriverBiz) GetVerifyCode(ctx context.Context, tel string) (string, error) {
|
|
|
// 一,校验手机号
|
|
|
pattern := `^(13\d|14[01456879]|15[0-35-9]|16[2567]|17[0-8]|18\d|19[0-35-9])\d{8}$`
|
|
|
regexpPattern := regexp.MustCompile(pattern)
|
|
|
if !regexpPattern.MatchString(tel) {
|
|
|
return "", errors.New(200, "DRIVER", "driver telephone error")
|
|
|
}
|
|
|
// 二,调用data/获取验证码
|
|
|
return db.DI.GetVerifyCode(ctx, tel)
|
|
|
}
|
|
|
|
|
|
func (db *DriverBiz) CheckVerifyCode(ctx context.Context, tel, code string) bool {
|
|
|
// 一,校验手机号
|
|
|
pattern := `^(13\d|14[01456879]|15[0-35-9]|16[2567]|17[0-8]|18\d|19[0-35-9])\d{8}$`
|
|
|
regexpPattern := regexp.MustCompile(pattern)
|
|
|
if !regexpPattern.MatchString(tel) {
|
|
|
return false
|
|
|
}
|
|
|
|
|
|
code = strings.TrimSpace(code)
|
|
|
if len(code) == 0 {
|
|
|
return false
|
|
|
}
|
|
|
|
|
|
verifyCode, err := db.DI.FetchVerifyCode(ctx, tel)
|
|
|
if err != nil {
|
|
|
return false
|
|
|
}
|
|
|
if verifyCode == code {
|
|
|
return true
|
|
|
}
|
|
|
|
|
|
return false
|
|
|
}
|
|
|
|
|
|
func (db *DriverBiz) GetInfoByTel(ctx context.Context, tel string) (*Driver, error) {
|
|
|
driver, err := db.DI.FetchInfoByTel(ctx, tel)
|
|
|
if err != nil {
|
|
|
return nil, err
|
|
|
}
|
|
|
return driver, nil
|
|
|
}
|