240 lines
6.3 KiB
Go
240 lines
6.3 KiB
Go
package biz
|
|
|
|
import (
|
|
"context"
|
|
"encoding/json"
|
|
"fmt"
|
|
"github.guxuan/haibei/internal/config"
|
|
"github.guxuan/haibei/pkg/cachex"
|
|
"github.guxuan/haibei/pkg/jwtx"
|
|
"github.guxuan/haibei/pkg/logging"
|
|
"go.uber.org/zap"
|
|
"math/rand"
|
|
"strconv"
|
|
"time"
|
|
|
|
"github.guxuan/haibei/internal/mods/customer/dal"
|
|
"github.guxuan/haibei/internal/mods/customer/schema"
|
|
"github.guxuan/haibei/pkg/errors"
|
|
"github.guxuan/haibei/pkg/util"
|
|
)
|
|
|
|
const (
|
|
REGISTER_SMS_CODE = "REGISTER_SMS_CODE"
|
|
CHECK_SMS_CODE = "CHECK_SMS_CODE"
|
|
)
|
|
|
|
// Defining the `Customer` business logic.
|
|
type Customer struct {
|
|
Cache cachex.Cacher
|
|
Trans *util.Trans
|
|
CustomerDAL *dal.Customer
|
|
Auth jwtx.Auther
|
|
}
|
|
|
|
func (a *Customer) Login(ctx context.Context, formItem *schema.CustomerLoginForm) (*schema.CustomerLoginToken, error) {
|
|
ctx = logging.NewTag(ctx, logging.TagKeyAppLogin)
|
|
|
|
// get user info
|
|
user, err := a.CustomerDAL.GetByWxSign(ctx, formItem.WxSign, schema.CustomerQueryOptions{})
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
if user == nil {
|
|
customer := &schema.Customer{}
|
|
customer.WxSign = formItem.WxSign
|
|
err := a.CustomerDAL.Create(ctx, customer)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
user = customer
|
|
}
|
|
userID := fmt.Sprintf("%d", user.ID)
|
|
var subject jwtx.JwtSubject
|
|
subject.ID = userID
|
|
subject.Typer = "APP"
|
|
marshal, err := json.Marshal(subject)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
// generate token
|
|
ctx = logging.NewUserID(ctx, userID)
|
|
|
|
userCache := util.UserCache{RoleIDs: []string{}}
|
|
err = a.Cache.Set(ctx, config.CacheNSForUser, userID, userCache.String(),
|
|
time.Duration(config.C.Dictionary.UserCacheExp)*time.Hour)
|
|
if err != nil {
|
|
logging.Context(ctx).Error("Failed to set cache", zap.Error(err))
|
|
}
|
|
logging.Context(ctx).Info("Login success", zap.String("WxSign", formItem.WxSign))
|
|
reload, err := a.genCustomerToken(ctx, string(marshal))
|
|
reload.Phone = user.Phone
|
|
return reload, err
|
|
}
|
|
func (a *Customer) BindPhone(ctx context.Context, formItem *schema.CustomerBindPhoneForm) (bool, error) {
|
|
userID := util.FromUserID(ctx)
|
|
num, err := strconv.ParseUint(fmt.Sprintf("%s", userID), 10, 64)
|
|
if err != nil {
|
|
fmt.Println("转换错误:", err)
|
|
return false, err
|
|
}
|
|
userIDNum := uint(num)
|
|
code, b, err := a.Cache.Get(ctx, REGISTER_SMS_CODE, formItem.Phone)
|
|
if err != nil {
|
|
return false, err
|
|
}
|
|
if !b {
|
|
return false, errors.NotFound("", "验证码过期!")
|
|
}
|
|
if code != formItem.Code {
|
|
return false, errors.NotFound("", "验证码失败!")
|
|
}
|
|
get, err := a.CustomerDAL.Get(ctx, userIDNum, schema.CustomerQueryOptions{})
|
|
if err != nil || get == nil {
|
|
return false, err
|
|
}
|
|
get.Phone = formItem.Phone
|
|
get.Avatar = formItem.Avatar
|
|
err = a.CustomerDAL.Update(ctx, get)
|
|
if err != nil {
|
|
return false, err
|
|
}
|
|
return true, nil
|
|
}
|
|
|
|
func (a *Customer) SendSms(ctx context.Context, phone string) (string, error) {
|
|
code := generateVerificationCode()
|
|
exists, err := a.Cache.Exists(ctx, REGISTER_SMS_CODE, phone)
|
|
if err != nil {
|
|
return "", err
|
|
}
|
|
if exists {
|
|
return "", errors.NotFound("", "验证码不能重复获取 等待90秒")
|
|
}
|
|
err = sendVerificationCode(phone, code)
|
|
if err != nil {
|
|
return "", err
|
|
}
|
|
err = a.Cache.Set(ctx, REGISTER_SMS_CODE, phone, code, 90*time.Second)
|
|
if err != nil {
|
|
return "", err
|
|
}
|
|
return code, nil
|
|
|
|
}
|
|
func sendVerificationCode(phone, code string) error {
|
|
// 这里应该是调用短信服务商的API发送短信
|
|
// 这里只是模拟
|
|
fmt.Printf("向手机号 %s 发送验证码: %s\n", phone, code)
|
|
return nil
|
|
}
|
|
func generateVerificationCode() string {
|
|
rand.Seed(time.Now().UnixNano())
|
|
return fmt.Sprintf("%06d", rand.Intn(1000000))
|
|
}
|
|
func (a *Customer) genCustomerToken(ctx context.Context, suject string) (*schema.CustomerLoginToken, error) {
|
|
token, err := a.Auth.GenerateToken(ctx, suject)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
tokenBuf, err := token.EncodeToJSON()
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
logging.Context(ctx).Info("Generate user token", zap.Any("token", string(tokenBuf)))
|
|
|
|
return &schema.CustomerLoginToken{
|
|
AccessToken: token.GetAccessToken(),
|
|
TokenType: token.GetTokenType(),
|
|
ExpiresAt: token.GetExpiresAt(),
|
|
}, nil
|
|
}
|
|
|
|
// Query customers from the data access object based on the provided parameters and options.
|
|
func (a *Customer) Query(ctx context.Context, params schema.CustomerQueryParam) (*schema.CustomerQueryResult, error) {
|
|
params.Pagination = true
|
|
|
|
result, err := a.CustomerDAL.Query(ctx, params, schema.CustomerQueryOptions{
|
|
QueryOptions: util.QueryOptions{
|
|
OrderFields: []util.OrderByParam{
|
|
{Field: "created_at", Direction: util.DESC},
|
|
},
|
|
},
|
|
})
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
return result, nil
|
|
}
|
|
|
|
// Get the specified customer from the data access object.
|
|
func (a *Customer) Get(ctx context.Context, id uint) (*schema.Customer, error) {
|
|
customer, err := a.CustomerDAL.Get(ctx, id)
|
|
if err != nil {
|
|
return nil, err
|
|
} else if customer == nil {
|
|
return nil, errors.NotFound("", "Customer not found")
|
|
}
|
|
return customer, nil
|
|
}
|
|
|
|
// Create a new customer in the data access object.
|
|
func (a *Customer) Create(ctx context.Context, formItem *schema.CustomerForm) (*schema.Customer, error) {
|
|
customer := &schema.Customer{}
|
|
|
|
if err := formItem.FillTo(customer); err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
err := a.Trans.Exec(ctx, func(ctx context.Context) error {
|
|
if err := a.CustomerDAL.Create(ctx, customer); err != nil {
|
|
return err
|
|
}
|
|
return nil
|
|
})
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
return customer, nil
|
|
}
|
|
|
|
// Update the specified customer in the data access object.
|
|
func (a *Customer) Update(ctx context.Context, id uint, formItem *schema.CustomerForm) error {
|
|
customer, err := a.CustomerDAL.Get(ctx, id)
|
|
if err != nil {
|
|
return err
|
|
} else if customer == nil {
|
|
return errors.NotFound("", "Customer not found")
|
|
}
|
|
|
|
if err := formItem.FillTo(customer); err != nil {
|
|
return err
|
|
}
|
|
customer.UpdatedAt = time.Now()
|
|
|
|
return a.Trans.Exec(ctx, func(ctx context.Context) error {
|
|
if err := a.CustomerDAL.Update(ctx, customer); err != nil {
|
|
return err
|
|
}
|
|
return nil
|
|
})
|
|
}
|
|
|
|
// Delete the specified customer from the data access object.
|
|
func (a *Customer) Delete(ctx context.Context, id uint) error {
|
|
exists, err := a.CustomerDAL.Exists(ctx, id)
|
|
if err != nil {
|
|
return err
|
|
} else if !exists {
|
|
return errors.NotFound("", "Customer not found")
|
|
}
|
|
|
|
return a.Trans.Exec(ctx, func(ctx context.Context) error {
|
|
if err := a.CustomerDAL.Delete(ctx, id); err != nil {
|
|
return err
|
|
}
|
|
return nil
|
|
})
|
|
}
|