优化Docker构建流程
- 添加UPX压缩步骤减小可执行文件体积 - 使用多阶段构建减小最终镜像大小 - 更新基础镜像到最新版本
This commit is contained in:
parent
ecff68fe8c
commit
e7e3309896
@ -1,24 +0,0 @@
|
||||
name: Build image
|
||||
on: [push]
|
||||
jobs:
|
||||
build:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: http://192.168.31.55:13000/timerzz/setup-go@v4
|
||||
env:
|
||||
HTTPS_PROXY: http://192.168.31.55:10809
|
||||
with:
|
||||
go-version: '1.22.x'
|
||||
- uses: http://192.168.31.55:13000/timerzz/checkout@v4
|
||||
- uses: http://192.168.31.55:13000/timerzz/setup-ko@v0.6
|
||||
with:
|
||||
version: v0.15.4
|
||||
env:
|
||||
KO_DOCKER_REPO: 192.168.31.55:5000/kedaya/${REPO_NAME}
|
||||
HTTP_PROXY: http://192.168.31.55:10809
|
||||
HTTPS_PROXY: http://192.168.31.55:10809
|
||||
- run: ko build --bare ./cmd
|
||||
env:
|
||||
KO_DOCKER_REPO: 192.168.31.55:5000/kedaya/${REPO_NAME}
|
||||
HTTP_PROXY: http://192.168.31.55:10809
|
||||
HTTPS_PROXY: http://192.168.31.55:10809
|
38
.gitignore
vendored
Normal file
38
.gitignore
vendored
Normal file
@ -0,0 +1,38 @@
|
||||
*.o
|
||||
*.a
|
||||
*.so
|
||||
_obj
|
||||
_test
|
||||
*.[568vq]
|
||||
[568vq].out
|
||||
*.cgo1.go
|
||||
*.cgo2.c
|
||||
_cgo_defun.c
|
||||
_cgo_gotypes.go
|
||||
_cgo_export.*
|
||||
_testmain.go
|
||||
*.exe
|
||||
*.exe~
|
||||
*.test
|
||||
*.prof
|
||||
*.rar
|
||||
*.zip
|
||||
*.gz
|
||||
*.psd
|
||||
*.bmd
|
||||
*.cfg
|
||||
*.pptx
|
||||
*.log
|
||||
*nohup.out
|
||||
*settings.pyc
|
||||
*.sublime-project
|
||||
*.sublime-workspace
|
||||
!.gitkeep
|
||||
.DS_Store
|
||||
/.idea
|
||||
/.vscode
|
||||
/output
|
||||
*.local.yml
|
||||
dumped_hertz_remote_config.json
|
||||
|
||||
/cfg_dev/
|
16
.ko.yaml
16
.ko.yaml
@ -1,16 +0,0 @@
|
||||
defaultPlatforms:
|
||||
- linux/amd64
|
||||
defaultBaseImage: alpine:latest
|
||||
builds:
|
||||
- id: user
|
||||
dir: . # default is .
|
||||
main: ./cmd
|
||||
env:
|
||||
- CGO_ENABLED=0
|
||||
- GOPROXY=https://goproxy.cn,direct
|
||||
- GOPRIVATE=gitea.timerzz.com
|
||||
- GONOSUMDB=gitea.timerzz.com
|
||||
- GONOPROXY=gitea.timerzz.com
|
||||
ldflags:
|
||||
- -s -w
|
||||
- -extldflags "-static"
|
31
Dockerfile
Normal file
31
Dockerfile
Normal file
@ -0,0 +1,31 @@
|
||||
# 使用官方Golang最新版本作为构建环境
|
||||
FROM golang:latest AS builder
|
||||
|
||||
WORKDIR /app
|
||||
|
||||
# 复制项目文件
|
||||
COPY . .
|
||||
|
||||
# 构建应用
|
||||
RUN apt update && apt install -y xz-utils && CGO_ENABLED=0 GOOS=linux go build -ldflags="-s -w" -o main .
|
||||
|
||||
# upx压缩
|
||||
RUN wget -c $(curl -s https://api.github.com/repos/upx/upx/releases/latest | grep browser_download_url | grep linux |grep amd64| cut -d'"' -f4) -O - |tar --strip-components 1 -xvJf - && ./upx ./main
|
||||
|
||||
# 使用轻量级的Alpine镜像作为运行时环境
|
||||
FROM alpine:latest
|
||||
|
||||
# 安装必要的工具
|
||||
RUN apk --no-cache add ca-certificates
|
||||
|
||||
# 设置工作目录
|
||||
WORKDIR /root/
|
||||
|
||||
# 从构建阶段复制可执行文件
|
||||
COPY --from=builder /app/main .
|
||||
|
||||
# 暴露端口
|
||||
EXPOSE 80
|
||||
|
||||
# 设置容器启动命令
|
||||
CMD ["./main"]
|
94
biz/dal/db/user.go
Normal file
94
biz/dal/db/user.go
Normal file
@ -0,0 +1,94 @@
|
||||
package db
|
||||
|
||||
import (
|
||||
"errors"
|
||||
|
||||
"gitlab.com/kedaya_mp/user/biz/model/common"
|
||||
"gorm.io/gorm"
|
||||
)
|
||||
|
||||
type Scoper interface {
|
||||
Scope(db *gorm.DB) *gorm.DB
|
||||
}
|
||||
|
||||
type UserStore interface {
|
||||
Create(*common.User) (*common.User, error)
|
||||
Find(Scoper, ...string) (*common.User, error)
|
||||
Exist(Scoper) (bool, error)
|
||||
Update(*common.User, ...string) error
|
||||
AutoMigrate() error
|
||||
}
|
||||
|
||||
type userStore struct {
|
||||
db *gorm.DB
|
||||
}
|
||||
|
||||
func NewUserStore(db *gorm.DB) UserStore {
|
||||
return &userStore{db: db}
|
||||
}
|
||||
|
||||
func (s *userStore) AutoMigrate() error {
|
||||
return s.db.AutoMigrate(&common.User{})
|
||||
}
|
||||
|
||||
type FindUserQuery struct {
|
||||
ID int64
|
||||
Phone string
|
||||
WxUnionID string
|
||||
}
|
||||
|
||||
func (f *FindUserQuery) Scope(db *gorm.DB) *gorm.DB {
|
||||
if f.ID != 0 {
|
||||
db = db.Where("id = ?", f.ID)
|
||||
}
|
||||
if f.Phone != "" {
|
||||
db = db.Where("phone = ?", f.Phone)
|
||||
}
|
||||
if f.WxUnionID != "" {
|
||||
db = db.Where("wx_union_id = ?", f.WxUnionID)
|
||||
}
|
||||
return db
|
||||
}
|
||||
|
||||
// Create 创建用户
|
||||
func (s *userStore) Create(u *common.User) (*common.User, error) {
|
||||
if err := s.db.Create(u).Error; err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return u, nil
|
||||
}
|
||||
|
||||
// Find 查找用户
|
||||
func (s *userStore) Find(scoper Scoper, selects ...string) (*common.User, error) {
|
||||
var dbUser common.User
|
||||
db := s.db
|
||||
if len(selects) > 0 {
|
||||
db = db.Select(selects)
|
||||
}
|
||||
if err := scoper.Scope(db).First(&dbUser).Error; err != nil {
|
||||
if errors.Is(err, gorm.ErrRecordNotFound) {
|
||||
return nil, nil
|
||||
}
|
||||
return nil, err
|
||||
}
|
||||
return &dbUser, nil
|
||||
}
|
||||
|
||||
// Exist 检查用户是否存在
|
||||
func (s *userStore) Exist(scoper Scoper) (bool, error) {
|
||||
var count int64
|
||||
if err := scoper.Scope(s.db).Model(&common.User{}).Count(&count).Error; err != nil {
|
||||
return false, err
|
||||
}
|
||||
return count > 0, nil
|
||||
}
|
||||
|
||||
// Update 更新用户信息
|
||||
func (s *userStore) Update(u *common.User, selects ...string) error {
|
||||
return s.db.Transaction(func(tx *gorm.DB) error {
|
||||
if len(selects) > 0 {
|
||||
tx = tx.Select(selects)
|
||||
}
|
||||
return tx.Where("id =?", u.ID).Updates(u).Error
|
||||
})
|
||||
}
|
45
biz/handle/auth.go
Normal file
45
biz/handle/auth.go
Normal file
@ -0,0 +1,45 @@
|
||||
package handle
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/cloudwego/hertz/pkg/app"
|
||||
)
|
||||
|
||||
type LoginRequest struct {
|
||||
WXCode string `json:"wx_code,omitempty"`
|
||||
Phone string `json:"phone"`
|
||||
Captcha string `json:"captcha,omitempty"`
|
||||
Password string `json:"password,omitempty"`
|
||||
}
|
||||
|
||||
type Response[T any] struct {
|
||||
Code int `json:"code"`
|
||||
Message string `json:"message"`
|
||||
Data T `json:"data"`
|
||||
}
|
||||
type LoginResponse struct {
|
||||
Token string `json:"token"`
|
||||
Expire string `json:"expire"`
|
||||
Message string `json:"message"`
|
||||
Code int `json:"code"`
|
||||
}
|
||||
|
||||
// Authenticator 登录
|
||||
// @Tags 用户模块
|
||||
// @Summary 登录接口
|
||||
// @Description 如果是微信登录,需要传递 WXcode和手机号,然后调用微信接口获取 openid 和 unionid。
|
||||
// 如果 unionid 已经存在,就直接登录, 如果不存在,就注册。
|
||||
// 如果是手机号登录,需要传递 phone 和 password, 如果手机号没注册,就直接注册
|
||||
// @Param request body LoginRequest true "请求参数"
|
||||
// @Success 200 {object} LoginResponse "成功响应"
|
||||
// @Accept application/json
|
||||
// @Produce application/json
|
||||
// @Router /api/v1/login [post]
|
||||
func (h *UserHandler) Authenticator(ctx context.Context, c *app.RequestContext) (interface{}, error) {
|
||||
var req LoginRequest
|
||||
if err := c.BindJSON(&req); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return h.userService.Login(ctx, req.Phone, req.Password, req.WXCode, req.Captcha)
|
||||
}
|
72
biz/handle/get.go
Normal file
72
biz/handle/get.go
Normal file
@ -0,0 +1,72 @@
|
||||
package handle
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
|
||||
"github.com/cloudwego/hertz/pkg/app"
|
||||
"gitlab.com/kedaya_mp/user/biz/model/common"
|
||||
user_service "gitlab.com/kedaya_mp/user/biz/service"
|
||||
)
|
||||
|
||||
type UserHandler struct {
|
||||
userService *user_service.UserService
|
||||
}
|
||||
|
||||
func NewUserHandler(userService *user_service.UserService) *UserHandler {
|
||||
return &UserHandler{
|
||||
userService: userService,
|
||||
}
|
||||
}
|
||||
|
||||
// GetUserByPhone 通过手机号获取用户信息
|
||||
// @Tags 用户模块
|
||||
// @Summary 获取用户信息接口
|
||||
// @Description 通过手机号获取用户信息,只返回用户的昵称、电话、性别、ID、创建时间和头像
|
||||
// @Param phone query string true "用户手机号"
|
||||
// @Success 200 {object} Response[common.User] "成功响应"
|
||||
// @Failure 400 {object} Response[string] "请求参数错误"
|
||||
// @Failure 404 {object} Response[string] "用户不存在"
|
||||
// @Failure 500 {object} Response[string] "服务器内部错误"
|
||||
// @Security ApiKeyAuth
|
||||
// @Accept application/json
|
||||
// @Produce application/json
|
||||
// @Router /api/v1/user [get]
|
||||
func (h *UserHandler) GetUserByPhone(ctx context.Context, c *app.RequestContext) {
|
||||
// 获取请求参数
|
||||
phone := c.Query("phone")
|
||||
if phone == "" {
|
||||
c.JSON(400, Response[string]{
|
||||
Code: 400,
|
||||
Message: "手机号不能为空",
|
||||
Data: "手机号参数缺失",
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
// 调用服务层获取用户信息
|
||||
user, err := h.userService.GetUserByPhone(phone)
|
||||
if err != nil {
|
||||
code := 500
|
||||
message := "获取用户信息失败"
|
||||
|
||||
if errors.Is(err, user_service.ErrUserNotFound) {
|
||||
code = 404
|
||||
message = "用户不存在"
|
||||
}
|
||||
|
||||
c.JSON(code, Response[string]{
|
||||
Code: code,
|
||||
Message: message,
|
||||
Data: err.Error(),
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
// 返回成功响应
|
||||
c.JSON(200, Response[common.User]{
|
||||
Code: 200,
|
||||
Message: "获取用户信息成功",
|
||||
Data: *user,
|
||||
})
|
||||
}
|
22
biz/model/common/user.go
Normal file
22
biz/model/common/user.go
Normal file
@ -0,0 +1,22 @@
|
||||
package common
|
||||
|
||||
import "time"
|
||||
|
||||
// 定义user结构体
|
||||
// 包括id,密码,用户名,手机号,头像,性别,微信unionid
|
||||
type User struct {
|
||||
ID int64 `json:"id,omitempty" gorm:"primaryKey;column:id"`
|
||||
CreatedAt time.Time `json:"created_at" gorm:"column:created_at"`
|
||||
Password string `json:"password,omitempty" gorm:"column:password"`
|
||||
NickName string `json:"nick_name" gorm:"column:nick_name"`
|
||||
Phone string `json:"phone" gorm:"column:phone"`
|
||||
Avatar string `json:"avatar" gorm:"column:avatar"`
|
||||
Gender int32 `json:"gender" gorm:"column:gender"`
|
||||
WxUnionID string `json:"wx_union_id,omitempty" gorm:"column:wx_union_id,unique"`
|
||||
WxSession string `json:"wx_session,omitempty" gorm:"column:wx_session"`
|
||||
}
|
||||
|
||||
// TableName 返回表名
|
||||
func (u *User) TableName() string {
|
||||
return "users"
|
||||
}
|
54
biz/mw/jwt.go
Normal file
54
biz/mw/jwt.go
Normal file
@ -0,0 +1,54 @@
|
||||
package mw
|
||||
|
||||
import (
|
||||
"context"
|
||||
"net/http"
|
||||
"time"
|
||||
|
||||
"github.com/cloudwego/hertz/pkg/app"
|
||||
"github.com/cloudwego/hertz/pkg/common/hlog"
|
||||
"github.com/hertz-contrib/jwt"
|
||||
"gitlab.com/kedaya_mp/user/biz/handle"
|
||||
"gitlab.com/kedaya_mp/user/biz/model/common"
|
||||
)
|
||||
|
||||
const (
|
||||
identityKey = "phone"
|
||||
)
|
||||
|
||||
func NewJwt(authenticator func(ctx context.Context, c *app.RequestContext) (interface{}, error)) *jwt.HertzJWTMiddleware {
|
||||
middleware, err := jwt.New(&jwt.HertzJWTMiddleware{
|
||||
Realm: "kedaya-onecat-task",
|
||||
Key: []byte("kedaya"),
|
||||
Timeout: time.Hour * 24,
|
||||
MaxRefresh: time.Hour,
|
||||
IdentityKey: identityKey,
|
||||
PayloadFunc: func(data interface{}) jwt.MapClaims {
|
||||
if v, ok := data.(*common.User); ok {
|
||||
return jwt.MapClaims{
|
||||
identityKey: v.Phone,
|
||||
}
|
||||
}
|
||||
return jwt.MapClaims{}
|
||||
},
|
||||
IdentityHandler: func(ctx context.Context, c *app.RequestContext) interface{} {
|
||||
claims := jwt.ExtractClaims(ctx, c)
|
||||
return &common.User{
|
||||
Phone: claims[identityKey].(string),
|
||||
}
|
||||
},
|
||||
Authenticator: authenticator,
|
||||
LoginResponse: func(ctx context.Context, c *app.RequestContext, code int, token string, expire time.Time) {
|
||||
c.JSON(http.StatusOK, handle.LoginResponse{
|
||||
Token: token,
|
||||
Expire: expire.Format(time.RFC3339),
|
||||
Message: "success",
|
||||
Code: code,
|
||||
})
|
||||
},
|
||||
})
|
||||
if err != nil {
|
||||
hlog.Fatalf("JWT Error:" + err.Error())
|
||||
}
|
||||
return middleware
|
||||
}
|
86
biz/router/healthz/healthz.go
Normal file
86
biz/router/healthz/healthz.go
Normal file
@ -0,0 +1,86 @@
|
||||
package healthz
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/cloudwego/hertz/pkg/app"
|
||||
"github.com/cloudwego/hertz/pkg/app/server"
|
||||
)
|
||||
|
||||
type Option struct {
|
||||
living func() error
|
||||
ready func() error
|
||||
}
|
||||
type healthz struct {
|
||||
Option
|
||||
}
|
||||
|
||||
func (h *healthz) SetLiving(living func() error) *healthz {
|
||||
h.living = living
|
||||
return h
|
||||
}
|
||||
|
||||
func (h *healthz) SetReady(ready func() error) *healthz {
|
||||
h.ready = ready
|
||||
return h
|
||||
}
|
||||
|
||||
func (h *healthz) Living(ctx context.Context, c *app.RequestContext) {
|
||||
if h.living == nil {
|
||||
c.JSON(200, map[string]string{"ok": "true"})
|
||||
return
|
||||
}
|
||||
if err := h.living(); err != nil {
|
||||
c.JSON(500, map[string]string{"ok": "false"})
|
||||
return
|
||||
}
|
||||
c.JSON(200, map[string]string{"ok": "true"})
|
||||
}
|
||||
func (h *healthz) Ready(ctx context.Context, c *app.RequestContext) {
|
||||
if h.ready == nil {
|
||||
c.JSON(200, map[string]string{"ok": "true"})
|
||||
return
|
||||
}
|
||||
if err := h.ready(); err != nil {
|
||||
c.JSON(500, map[string]string{"ok": "false"})
|
||||
return
|
||||
}
|
||||
c.JSON(200, map[string]string{"ok": "true"})
|
||||
}
|
||||
|
||||
func (h *healthz) Registry(hertz *server.Hertz) {
|
||||
hertz.GET("/living", h.Living)
|
||||
hertz.GET("/ready", h.Ready)
|
||||
}
|
||||
|
||||
type Healthz interface {
|
||||
SetLiving(living func() error) *healthz
|
||||
SetReady(ready func() error) *healthz
|
||||
Living(ctx context.Context, c *app.RequestContext)
|
||||
Ready(ctx context.Context, c *app.RequestContext)
|
||||
Registry(h *server.Hertz)
|
||||
}
|
||||
|
||||
type OptionFunc func(*Option)
|
||||
|
||||
func NewHealthz(opts ...OptionFunc) Healthz {
|
||||
var opt = Option{}
|
||||
for _, o := range opts {
|
||||
o(&opt)
|
||||
}
|
||||
return &healthz{
|
||||
Option: opt,
|
||||
}
|
||||
}
|
||||
|
||||
func WithLiving(living func() error) OptionFunc {
|
||||
return func(o *Option) {
|
||||
o.living = living
|
||||
}
|
||||
}
|
||||
|
||||
func WithReady(ready func() error) OptionFunc {
|
||||
return func(o *Option) {
|
||||
o.ready = ready
|
||||
}
|
||||
}
|
31
biz/router/user/user.go
Normal file
31
biz/router/user/user.go
Normal file
@ -0,0 +1,31 @@
|
||||
package user
|
||||
|
||||
import (
|
||||
"github.com/ArtisanCloud/PowerWeChat/v3/src/miniProgram"
|
||||
"github.com/cloudwego/hertz/pkg/app/server"
|
||||
"github.com/cloudwego/hertz/pkg/common/hlog"
|
||||
"gitlab.com/kedaya_mp/user/biz/handle"
|
||||
"gitlab.com/kedaya_mp/user/biz/mw"
|
||||
user_service "gitlab.com/kedaya_mp/user/biz/service"
|
||||
"gitlab.com/kedaya_mp/user/pkg/captcha"
|
||||
"gorm.io/gorm"
|
||||
)
|
||||
|
||||
func Register(h *server.Hertz, db *gorm.DB, miniProgramApp *miniProgram.MiniProgram, captchaService captcha.Service) {
|
||||
userService := user_service.NewUserService(db, miniProgramApp, captchaService)
|
||||
if err := userService.Init(); err != nil {
|
||||
hlog.Fatalf("UserService Init Error: %v", err)
|
||||
}
|
||||
userHandler := handle.NewUserHandler(userService)
|
||||
authMiddleware := mw.NewJwt(userHandler.Authenticator)
|
||||
|
||||
api := h.Group("/api/v1")
|
||||
api.POST("/login", authMiddleware.LoginHandler)
|
||||
|
||||
// 需要JWT认证的接口
|
||||
auth := api.Group("/")
|
||||
auth.Use(authMiddleware.MiddlewareFunc())
|
||||
{
|
||||
auth.GET("/user", userHandler.GetUserByPhone)
|
||||
}
|
||||
}
|
155
biz/service/user_service.go
Normal file
155
biz/service/user_service.go
Normal file
@ -0,0 +1,155 @@
|
||||
package service
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
|
||||
"github.com/ArtisanCloud/PowerWeChat/v3/src/miniProgram"
|
||||
"gitlab.com/kedaya_mp/user/biz/dal/db"
|
||||
"gitlab.com/kedaya_mp/user/biz/model/common"
|
||||
"gitlab.com/kedaya_mp/user/pkg/captcha"
|
||||
"gitlab.com/kedaya_mp/user/pkg/crypto"
|
||||
"gorm.io/gorm"
|
||||
)
|
||||
|
||||
var (
|
||||
ErrUserNotFound = errors.New("用户不存在")
|
||||
ErrInvalidPassword = errors.New("密码错误")
|
||||
ErrGetWXUserInfo = errors.New("获取微信用户信息失败")
|
||||
ErrCreateUserFailed = errors.New("创建用户失败")
|
||||
)
|
||||
|
||||
type UserService struct {
|
||||
store db.UserStore
|
||||
miniProgramApp *miniProgram.MiniProgram
|
||||
captchaService captcha.Service
|
||||
}
|
||||
|
||||
func NewUserService(_db *gorm.DB, miniProgramApp *miniProgram.MiniProgram, captchaService captcha.Service) *UserService {
|
||||
return &UserService{
|
||||
store: db.NewUserStore(_db),
|
||||
miniProgramApp: miniProgramApp,
|
||||
captchaService: captchaService,
|
||||
}
|
||||
}
|
||||
|
||||
func (s *UserService) Init() error {
|
||||
if err := s.store.AutoMigrate(); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *UserService) LoginByPhone(phone, password string) (*common.User, error) {
|
||||
user, err := s.store.Find(&db.FindUserQuery{Phone: phone})
|
||||
if err != nil && !errors.Is(err, gorm.ErrRecordNotFound) {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if user == nil {
|
||||
hashedPassword := crypto.HashPassword(password)
|
||||
newUser := &common.User{
|
||||
Phone: phone,
|
||||
Password: hashedPassword,
|
||||
}
|
||||
|
||||
user, err = s.store.Create(newUser)
|
||||
if err != nil {
|
||||
return nil, ErrCreateUserFailed
|
||||
}
|
||||
return user, nil
|
||||
}
|
||||
|
||||
if !crypto.VerifyPassword(password, user.Password) {
|
||||
return nil, ErrInvalidPassword
|
||||
}
|
||||
|
||||
return user, nil
|
||||
}
|
||||
|
||||
func (s *UserService) LoginByWechat(ctx context.Context, wxCode, phone string) (*common.User, error) {
|
||||
authResult, err := s.miniProgramApp.Auth.Session(ctx, wxCode)
|
||||
if err != nil {
|
||||
return nil, ErrGetWXUserInfo
|
||||
}
|
||||
|
||||
user, err := s.store.Find(&db.FindUserQuery{WxUnionID: authResult.UnionID})
|
||||
if err != nil && !errors.Is(err, gorm.ErrRecordNotFound) {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if user != nil {
|
||||
if user.Phone != phone {
|
||||
return nil, errors.New("手机号与已绑定的不符")
|
||||
}
|
||||
user.WxSession = authResult.SessionKey
|
||||
if err = s.store.Update(user, "wx_session"); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return user, nil
|
||||
}
|
||||
|
||||
newUser := &common.User{
|
||||
Phone: phone,
|
||||
WxUnionID: authResult.UnionID,
|
||||
}
|
||||
|
||||
user, err = s.store.Create(newUser)
|
||||
if err != nil {
|
||||
return nil, ErrCreateUserFailed
|
||||
}
|
||||
|
||||
return user, nil
|
||||
}
|
||||
|
||||
func (s *UserService) LoginByPhoneAndCode(ctx context.Context, phone, captchaCode string) (*common.User, error) {
|
||||
if err := s.captchaService.VerifyCode(ctx, phone, captchaCode); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
user, err := s.store.Find(&db.FindUserQuery{Phone: phone})
|
||||
if err != nil && !errors.Is(err, gorm.ErrRecordNotFound) {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if user == nil {
|
||||
newUser := &common.User{
|
||||
Phone: phone,
|
||||
}
|
||||
user, err = s.store.Create(newUser)
|
||||
if err != nil {
|
||||
return nil, ErrCreateUserFailed
|
||||
}
|
||||
}
|
||||
return user, nil
|
||||
}
|
||||
|
||||
func (s *UserService) Login(ctx context.Context, phone, password, wxCode, captcha string) (*common.User, error) {
|
||||
if phone == "" {
|
||||
return nil, errors.New("手机号不能为空")
|
||||
}
|
||||
|
||||
if wxCode != "" {
|
||||
return s.LoginByWechat(ctx, wxCode, phone)
|
||||
}
|
||||
|
||||
if captcha != "" {
|
||||
return s.LoginByPhoneAndCode(ctx, phone, captcha)
|
||||
}
|
||||
|
||||
if password == "" {
|
||||
return nil, errors.New("密码不能为空")
|
||||
}
|
||||
return s.LoginByPhone(phone, password)
|
||||
}
|
||||
|
||||
func (s *UserService) GetUserByPhone(phone string) (*common.User, error) {
|
||||
user, err := s.store.Find(&db.FindUserQuery{Phone: phone}, "created_at", "nick_name", "phone", "avatar", "gender")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if user == nil {
|
||||
return nil, ErrUserNotFound
|
||||
}
|
||||
return user, nil
|
||||
}
|
53
cmd/user.go
53
cmd/user.go
@ -1,53 +0,0 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"context"
|
||||
"flag"
|
||||
"os"
|
||||
"os/signal"
|
||||
|
||||
"gitea.timerzz.com/kedaya_haitao/common/pkg/database"
|
||||
"gitea.timerzz.com/kedaya_haitao/common/pkg/web"
|
||||
"gitea.timerzz.com/kedaya_haitao/common/structs/storage"
|
||||
"github.com/gofiber/fiber/v3"
|
||||
"github.com/gofiber/fiber/v3/middleware/cors"
|
||||
"github.com/gofiber/fiber/v3/middleware/recover"
|
||||
|
||||
"github.com/golang/glog"
|
||||
)
|
||||
|
||||
func main() {
|
||||
flag.Parse()
|
||||
glog.Info(">>> BEGIN INIT<<<")
|
||||
ctx, cancel := signal.NotifyContext(context.Background(), os.Kill, os.Interrupt)
|
||||
defer cancel()
|
||||
// 初始化数据库
|
||||
db, err := database.InitDefaultDatabase()
|
||||
if err != nil {
|
||||
glog.Fatalf("init database failed: %v", err)
|
||||
}
|
||||
// 初始化服务
|
||||
r := fiber.New(fiber.Config{ErrorHandler: web.ErrHandle})
|
||||
r.Use(cors.New(), recover.New())
|
||||
|
||||
stg := storage.NewStorage(db)
|
||||
|
||||
svc := []web.Register{
|
||||
web.NewProbe(),
|
||||
}
|
||||
|
||||
for _, s := range svc {
|
||||
s.Registry(r)
|
||||
}
|
||||
|
||||
port := os.Getenv("PORT")
|
||||
if port == "" {
|
||||
port = "80"
|
||||
}
|
||||
if err = r.Listen(":"+port, fiber.ListenConfig{
|
||||
EnablePrintRoutes: true,
|
||||
GracefulContext: ctx,
|
||||
}); err != nil {
|
||||
glog.Warningf("service over: %v", err)
|
||||
}
|
||||
}
|
228
docs/docs.go
Normal file
228
docs/docs.go
Normal file
@ -0,0 +1,228 @@
|
||||
// Package docs Code generated by swaggo/swag. DO NOT EDIT
|
||||
package docs
|
||||
|
||||
import "github.com/swaggo/swag"
|
||||
|
||||
const docTemplate = `{
|
||||
"schemes": {{ marshal .Schemes }},
|
||||
"swagger": "2.0",
|
||||
"info": {
|
||||
"description": "{{escape .Description}}",
|
||||
"title": "{{.Title}}",
|
||||
"contact": {
|
||||
"name": "oneCat-user"
|
||||
},
|
||||
"license": {
|
||||
"name": "Apache 2.0",
|
||||
"url": "http://www.apache.org/licenses/LICENSE-2.0.html"
|
||||
},
|
||||
"version": "{{.Version}}"
|
||||
},
|
||||
"host": "{{.Host}}",
|
||||
"basePath": "{{.BasePath}}",
|
||||
"paths": {
|
||||
"/api/v1/login": {
|
||||
"post": {
|
||||
"description": "如果是微信登录,需要传递 WXcode和手机号,然后调用微信接口获取 openid 和 unionid。",
|
||||
"consumes": [
|
||||
"application/json"
|
||||
],
|
||||
"produces": [
|
||||
"application/json"
|
||||
],
|
||||
"tags": [
|
||||
"用户模块"
|
||||
],
|
||||
"summary": "登录接口",
|
||||
"parameters": [
|
||||
{
|
||||
"description": "请求参数",
|
||||
"name": "request",
|
||||
"in": "body",
|
||||
"required": true,
|
||||
"schema": {
|
||||
"$ref": "#/definitions/user.LoginRequest"
|
||||
}
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "成功响应",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/user.LoginResponse"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"/api/v1/user": {
|
||||
"get": {
|
||||
"security": [
|
||||
{
|
||||
"ApiKeyAuth": []
|
||||
}
|
||||
],
|
||||
"description": "通过手机号获取用户信息,只返回用户的昵称、电话、性别、ID、创建时间和头像",
|
||||
"consumes": [
|
||||
"application/json"
|
||||
],
|
||||
"produces": [
|
||||
"application/json"
|
||||
],
|
||||
"tags": [
|
||||
"用户模块"
|
||||
],
|
||||
"summary": "获取用户信息接口",
|
||||
"parameters": [
|
||||
{
|
||||
"type": "string",
|
||||
"description": "用户手机号",
|
||||
"name": "phone",
|
||||
"in": "query",
|
||||
"required": true
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "成功响应",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/user.Response-common_User"
|
||||
}
|
||||
},
|
||||
"400": {
|
||||
"description": "请求参数错误",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/user.Response-string"
|
||||
}
|
||||
},
|
||||
"404": {
|
||||
"description": "用户不存在",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/user.Response-string"
|
||||
}
|
||||
},
|
||||
"500": {
|
||||
"description": "服务器内部错误",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/user.Response-string"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"definitions": {
|
||||
"common.User": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"avatar": {
|
||||
"type": "string"
|
||||
},
|
||||
"created_at": {
|
||||
"type": "string"
|
||||
},
|
||||
"gender": {
|
||||
"type": "integer"
|
||||
},
|
||||
"id": {
|
||||
"type": "integer"
|
||||
},
|
||||
"nick_name": {
|
||||
"type": "string"
|
||||
},
|
||||
"password": {
|
||||
"type": "string"
|
||||
},
|
||||
"phone": {
|
||||
"type": "string"
|
||||
},
|
||||
"wx_session": {
|
||||
"type": "string"
|
||||
},
|
||||
"wx_union_id": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
},
|
||||
"user.LoginRequest": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"captcha": {
|
||||
"type": "string"
|
||||
},
|
||||
"password": {
|
||||
"type": "string"
|
||||
},
|
||||
"phone": {
|
||||
"type": "string"
|
||||
},
|
||||
"wx_code": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
},
|
||||
"user.LoginResponse": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"code": {
|
||||
"type": "integer"
|
||||
},
|
||||
"expire": {
|
||||
"type": "string"
|
||||
},
|
||||
"message": {
|
||||
"type": "string"
|
||||
},
|
||||
"token": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
},
|
||||
"user.Response-common_User": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"code": {
|
||||
"type": "integer"
|
||||
},
|
||||
"data": {
|
||||
"$ref": "#/definitions/common.User"
|
||||
},
|
||||
"message": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
},
|
||||
"user.Response-string": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"code": {
|
||||
"type": "integer"
|
||||
},
|
||||
"data": {
|
||||
"type": "string"
|
||||
},
|
||||
"message": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}`
|
||||
|
||||
// SwaggerInfo holds exported Swagger Info so clients can modify it
|
||||
var SwaggerInfo = &swag.Spec{
|
||||
Version: "1.0",
|
||||
Host: "",
|
||||
BasePath: "/",
|
||||
Schemes: []string{"http"},
|
||||
Title: "用户和登录相关接口",
|
||||
Description: "这是一个用户和登录相关的接口文档",
|
||||
InfoInstanceName: "swagger",
|
||||
SwaggerTemplate: docTemplate,
|
||||
LeftDelim: "{{",
|
||||
RightDelim: "}}",
|
||||
}
|
||||
|
||||
func init() {
|
||||
swag.Register(SwaggerInfo.InstanceName(), SwaggerInfo)
|
||||
}
|
206
docs/swagger.json
Normal file
206
docs/swagger.json
Normal file
@ -0,0 +1,206 @@
|
||||
{
|
||||
"schemes": [
|
||||
"http"
|
||||
],
|
||||
"swagger": "2.0",
|
||||
"info": {
|
||||
"description": "这是一个用户和登录相关的接口文档",
|
||||
"title": "用户和登录相关接口",
|
||||
"contact": {
|
||||
"name": "oneCat-user"
|
||||
},
|
||||
"license": {
|
||||
"name": "Apache 2.0",
|
||||
"url": "http://www.apache.org/licenses/LICENSE-2.0.html"
|
||||
},
|
||||
"version": "1.0"
|
||||
},
|
||||
"basePath": "/",
|
||||
"paths": {
|
||||
"/api/v1/login": {
|
||||
"post": {
|
||||
"description": "如果是微信登录,需要传递 WXcode和手机号,然后调用微信接口获取 openid 和 unionid。",
|
||||
"consumes": [
|
||||
"application/json"
|
||||
],
|
||||
"produces": [
|
||||
"application/json"
|
||||
],
|
||||
"tags": [
|
||||
"用户模块"
|
||||
],
|
||||
"summary": "登录接口",
|
||||
"parameters": [
|
||||
{
|
||||
"description": "请求参数",
|
||||
"name": "request",
|
||||
"in": "body",
|
||||
"required": true,
|
||||
"schema": {
|
||||
"$ref": "#/definitions/user.LoginRequest"
|
||||
}
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "成功响应",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/user.LoginResponse"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"/api/v1/user": {
|
||||
"get": {
|
||||
"security": [
|
||||
{
|
||||
"ApiKeyAuth": []
|
||||
}
|
||||
],
|
||||
"description": "通过手机号获取用户信息,只返回用户的昵称、电话、性别、ID、创建时间和头像",
|
||||
"consumes": [
|
||||
"application/json"
|
||||
],
|
||||
"produces": [
|
||||
"application/json"
|
||||
],
|
||||
"tags": [
|
||||
"用户模块"
|
||||
],
|
||||
"summary": "获取用户信息接口",
|
||||
"parameters": [
|
||||
{
|
||||
"type": "string",
|
||||
"description": "用户手机号",
|
||||
"name": "phone",
|
||||
"in": "query",
|
||||
"required": true
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "成功响应",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/user.Response-common_User"
|
||||
}
|
||||
},
|
||||
"400": {
|
||||
"description": "请求参数错误",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/user.Response-string"
|
||||
}
|
||||
},
|
||||
"404": {
|
||||
"description": "用户不存在",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/user.Response-string"
|
||||
}
|
||||
},
|
||||
"500": {
|
||||
"description": "服务器内部错误",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/user.Response-string"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"definitions": {
|
||||
"common.User": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"avatar": {
|
||||
"type": "string"
|
||||
},
|
||||
"created_at": {
|
||||
"type": "string"
|
||||
},
|
||||
"gender": {
|
||||
"type": "integer"
|
||||
},
|
||||
"id": {
|
||||
"type": "integer"
|
||||
},
|
||||
"nick_name": {
|
||||
"type": "string"
|
||||
},
|
||||
"password": {
|
||||
"type": "string"
|
||||
},
|
||||
"phone": {
|
||||
"type": "string"
|
||||
},
|
||||
"wx_session": {
|
||||
"type": "string"
|
||||
},
|
||||
"wx_union_id": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
},
|
||||
"user.LoginRequest": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"captcha": {
|
||||
"type": "string"
|
||||
},
|
||||
"password": {
|
||||
"type": "string"
|
||||
},
|
||||
"phone": {
|
||||
"type": "string"
|
||||
},
|
||||
"wx_code": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
},
|
||||
"user.LoginResponse": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"code": {
|
||||
"type": "integer"
|
||||
},
|
||||
"expire": {
|
||||
"type": "string"
|
||||
},
|
||||
"message": {
|
||||
"type": "string"
|
||||
},
|
||||
"token": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
},
|
||||
"user.Response-common_User": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"code": {
|
||||
"type": "integer"
|
||||
},
|
||||
"data": {
|
||||
"$ref": "#/definitions/common.User"
|
||||
},
|
||||
"message": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
},
|
||||
"user.Response-string": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"code": {
|
||||
"type": "integer"
|
||||
},
|
||||
"data": {
|
||||
"type": "string"
|
||||
},
|
||||
"message": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
133
docs/swagger.yaml
Normal file
133
docs/swagger.yaml
Normal file
@ -0,0 +1,133 @@
|
||||
basePath: /
|
||||
definitions:
|
||||
common.User:
|
||||
properties:
|
||||
avatar:
|
||||
type: string
|
||||
created_at:
|
||||
type: string
|
||||
gender:
|
||||
type: integer
|
||||
id:
|
||||
type: integer
|
||||
nick_name:
|
||||
type: string
|
||||
password:
|
||||
type: string
|
||||
phone:
|
||||
type: string
|
||||
wx_session:
|
||||
type: string
|
||||
wx_union_id:
|
||||
type: string
|
||||
type: object
|
||||
user.LoginRequest:
|
||||
properties:
|
||||
captcha:
|
||||
type: string
|
||||
password:
|
||||
type: string
|
||||
phone:
|
||||
type: string
|
||||
wx_code:
|
||||
type: string
|
||||
type: object
|
||||
user.LoginResponse:
|
||||
properties:
|
||||
code:
|
||||
type: integer
|
||||
expire:
|
||||
type: string
|
||||
message:
|
||||
type: string
|
||||
token:
|
||||
type: string
|
||||
type: object
|
||||
user.Response-common_User:
|
||||
properties:
|
||||
code:
|
||||
type: integer
|
||||
data:
|
||||
$ref: '#/definitions/common.User'
|
||||
message:
|
||||
type: string
|
||||
type: object
|
||||
user.Response-string:
|
||||
properties:
|
||||
code:
|
||||
type: integer
|
||||
data:
|
||||
type: string
|
||||
message:
|
||||
type: string
|
||||
type: object
|
||||
info:
|
||||
contact:
|
||||
name: oneCat-user
|
||||
description: 这是一个用户和登录相关的接口文档
|
||||
license:
|
||||
name: Apache 2.0
|
||||
url: http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
title: 用户和登录相关接口
|
||||
version: "1.0"
|
||||
paths:
|
||||
/api/v1/login:
|
||||
post:
|
||||
consumes:
|
||||
- application/json
|
||||
description: 如果是微信登录,需要传递 WXcode和手机号,然后调用微信接口获取 openid 和 unionid。
|
||||
parameters:
|
||||
- description: 请求参数
|
||||
in: body
|
||||
name: request
|
||||
required: true
|
||||
schema:
|
||||
$ref: '#/definitions/user.LoginRequest'
|
||||
produces:
|
||||
- application/json
|
||||
responses:
|
||||
"200":
|
||||
description: 成功响应
|
||||
schema:
|
||||
$ref: '#/definitions/user.LoginResponse'
|
||||
summary: 登录接口
|
||||
tags:
|
||||
- 用户模块
|
||||
/api/v1/user:
|
||||
get:
|
||||
consumes:
|
||||
- application/json
|
||||
description: 通过手机号获取用户信息,只返回用户的昵称、电话、性别、ID、创建时间和头像
|
||||
parameters:
|
||||
- description: 用户手机号
|
||||
in: query
|
||||
name: phone
|
||||
required: true
|
||||
type: string
|
||||
produces:
|
||||
- application/json
|
||||
responses:
|
||||
"200":
|
||||
description: 成功响应
|
||||
schema:
|
||||
$ref: '#/definitions/user.Response-common_User'
|
||||
"400":
|
||||
description: 请求参数错误
|
||||
schema:
|
||||
$ref: '#/definitions/user.Response-string'
|
||||
"404":
|
||||
description: 用户不存在
|
||||
schema:
|
||||
$ref: '#/definitions/user.Response-string'
|
||||
"500":
|
||||
description: 服务器内部错误
|
||||
schema:
|
||||
$ref: '#/definitions/user.Response-string'
|
||||
security:
|
||||
- ApiKeyAuth: []
|
||||
summary: 获取用户信息接口
|
||||
tags:
|
||||
- 用户模块
|
||||
schemes:
|
||||
- http
|
||||
swagger: "2.0"
|
65
go.mod
65
go.mod
@ -1,4 +1,65 @@
|
||||
module gitea.timerzz.com/kedaya_haitao/user
|
||||
module gitlab.com/kedaya_mp/user
|
||||
|
||||
go 1.22.5
|
||||
go 1.24.1
|
||||
|
||||
require (
|
||||
github.com/ArtisanCloud/PowerWeChat/v3 v3.4.7
|
||||
github.com/caarlos0/env/v11 v11.3.1
|
||||
github.com/cloudwego/hertz v0.9.7
|
||||
github.com/hertz-contrib/cors v0.1.0
|
||||
github.com/hertz-contrib/jwt v1.0.4
|
||||
github.com/redis/go-redis/v9 v9.7.3
|
||||
github.com/swaggo/swag v1.16.4
|
||||
gorm.io/driver/mysql v1.5.7
|
||||
gorm.io/gorm v1.25.12
|
||||
)
|
||||
|
||||
require (
|
||||
github.com/ArtisanCloud/PowerLibs/v3 v3.3.2 // indirect
|
||||
github.com/KyleBanks/depth v1.2.1 // indirect
|
||||
github.com/PuerkitoBio/purell v1.1.1 // indirect
|
||||
github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578 // indirect
|
||||
github.com/bytedance/gopkg v0.1.0 // indirect
|
||||
github.com/bytedance/sonic v1.13.2 // indirect
|
||||
github.com/bytedance/sonic/loader v0.2.4 // indirect
|
||||
github.com/cespare/xxhash/v2 v2.3.0 // indirect
|
||||
github.com/clbanning/mxj/v2 v2.7.0 // indirect
|
||||
github.com/cloudwego/base64x v0.1.5 // indirect
|
||||
github.com/cloudwego/netpoll v0.6.4 // indirect
|
||||
github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f // indirect
|
||||
github.com/elastic/pkcs8 v1.0.0 // indirect
|
||||
github.com/fsnotify/fsnotify v1.7.0 // indirect
|
||||
github.com/go-openapi/jsonpointer v0.19.5 // indirect
|
||||
github.com/go-openapi/jsonreference v0.19.6 // indirect
|
||||
github.com/go-openapi/spec v0.20.4 // indirect
|
||||
github.com/go-openapi/swag v0.19.15 // indirect
|
||||
github.com/go-sql-driver/mysql v1.7.0 // indirect
|
||||
github.com/golang-jwt/jwt/v4 v4.5.2 // indirect
|
||||
github.com/golang/protobuf v1.5.4 // indirect
|
||||
github.com/jinzhu/inflection v1.0.0 // indirect
|
||||
github.com/jinzhu/now v1.1.5 // indirect
|
||||
github.com/josharian/intern v1.0.0 // indirect
|
||||
github.com/klauspost/cpuid/v2 v2.2.9 // indirect
|
||||
github.com/kr/pretty v0.3.0 // indirect
|
||||
github.com/mailru/easyjson v0.7.6 // indirect
|
||||
github.com/nyaruka/phonenumbers v1.0.55 // indirect
|
||||
github.com/patrickmn/go-cache v2.1.0+incompatible // indirect
|
||||
github.com/pkg/errors v0.9.1 // indirect
|
||||
github.com/tidwall/gjson v1.18.0 // indirect
|
||||
github.com/tidwall/match v1.1.1 // indirect
|
||||
github.com/tidwall/pretty v1.2.0 // indirect
|
||||
github.com/twitchyliquid64/golang-asm v0.15.1 // indirect
|
||||
go.opentelemetry.io/otel v1.35.0 // indirect
|
||||
go.opentelemetry.io/otel/trace v1.35.0 // indirect
|
||||
go.uber.org/multierr v1.11.0 // indirect
|
||||
go.uber.org/zap v1.27.0 // indirect
|
||||
golang.org/x/arch v0.8.0 // indirect
|
||||
golang.org/x/crypto v0.37.0 // indirect
|
||||
golang.org/x/net v0.25.0 // indirect
|
||||
golang.org/x/sys v0.32.0 // indirect
|
||||
golang.org/x/text v0.24.0 // indirect
|
||||
golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d // indirect
|
||||
google.golang.org/protobuf v1.35.2 // indirect
|
||||
gopkg.in/yaml.v2 v2.4.0 // indirect
|
||||
gopkg.in/yaml.v3 v3.0.1 // indirect
|
||||
)
|
||||
|
298
go.sum
298
go.sum
@ -1,83 +1,269 @@
|
||||
gitea.timerzz.com/kedaya_haitao/common v0.0.0-20240904073547-7677cd470a33 h1:faziFCeUdnDOsAse6iI6ZKXY68BBTgeQfoRS5ef8ag0=
|
||||
gitea.timerzz.com/kedaya_haitao/common v0.0.0-20240904073547-7677cd470a33/go.mod h1:BIz+IMGznPiyLnV1+Ntw1zf8rEIcbymmGq+EfvDsSgE=
|
||||
github.com/andybalholm/brotli v1.1.0 h1:eLKJA0d02Lf0mVpIDgYnqXcUn0GqVmEFny3VuID1U3M=
|
||||
github.com/andybalholm/brotli v1.1.0/go.mod h1:sms7XGricyQI9K10gOSf56VKKWS4oLer58Q+mhRPtnY=
|
||||
github.com/ArtisanCloud/PowerLibs/v3 v3.3.2 h1:IInr1YWwkhwOykxDqux1Goym0uFhrYwBjmgLnEwCLqs=
|
||||
github.com/ArtisanCloud/PowerLibs/v3 v3.3.2/go.mod h1:xFGsskCnzAu+6rFEJbGVAlwhrwZPXAny6m7j71S/B5k=
|
||||
github.com/ArtisanCloud/PowerWeChat/v3 v3.4.7 h1:oDQcU8+/CYvvuJ1nIrCc1j4sg1IfzjkscMoeo4nLIDA=
|
||||
github.com/ArtisanCloud/PowerWeChat/v3 v3.4.7/go.mod h1:ybM3u4Lhso0X+ZsgoRCF4e5W1KT2fBc6plpjPZ2fop4=
|
||||
github.com/KyleBanks/depth v1.2.1 h1:5h8fQADFrWtarTdtDudMmGsC7GPbOAu6RVB3ffsVFHc=
|
||||
github.com/KyleBanks/depth v1.2.1/go.mod h1:jzSb9d0L43HxTQfT+oSA1EEp2q+ne2uh6XgeJcm8brE=
|
||||
github.com/PuerkitoBio/purell v1.1.1 h1:WEQqlqaGbrPkxLJWfBwQmfEAE1Z7ONdDLqrN38tNFfI=
|
||||
github.com/PuerkitoBio/purell v1.1.1/go.mod h1:c11w/QuzBsJSee3cPx9rAFu61PvFxuPbtSwDGJws/X0=
|
||||
github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578 h1:d+Bc7a5rLufV/sSk/8dngufqelfh6jnri85riMAaF/M=
|
||||
github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578/go.mod h1:uGdkoq3SwY9Y+13GIhn11/XLaGBb4BfwItxLd5jeuXE=
|
||||
github.com/bsm/ginkgo/v2 v2.12.0 h1:Ny8MWAHyOepLGlLKYmXG4IEkioBysk6GpaRTLC8zwWs=
|
||||
github.com/bsm/ginkgo/v2 v2.12.0/go.mod h1:SwYbGRRDovPVboqFv0tPTcG1sN61LM1Z4ARdbAV9g4c=
|
||||
github.com/bsm/gomega v1.27.10 h1:yeMWxP2pV2fG3FgAODIY8EiRE3dy0aeFYt4l7wh6yKA=
|
||||
github.com/bsm/gomega v1.27.10/go.mod h1:JyEr/xRbxbtgWNi8tIEVPUYZ5Dzef52k01W3YH0H+O0=
|
||||
github.com/bytedance/go-tagexpr/v2 v2.9.2/go.mod h1:5qsx05dYOiUXOUgnQ7w3Oz8BYs2qtM/bJokdLb79wRM=
|
||||
github.com/bytedance/gopkg v0.0.0-20220413063733-65bf48ffb3a7/go.mod h1:2ZlV9BaUH4+NXIBF0aMdKKAnHTzqH+iMU4KUjAbL23Q=
|
||||
github.com/bytedance/gopkg v0.1.0 h1:aAxB7mm1qms4Wz4sp8e1AtKDOeFLtdqvGiUe7aonRJs=
|
||||
github.com/bytedance/gopkg v0.1.0/go.mod h1:FtQG3YbQG9L/91pbKSw787yBQPutC+457AvDW77fgUQ=
|
||||
github.com/bytedance/mockey v1.2.1/go.mod h1:+Jm/fzWZAuhEDrPXVjDf/jLM2BlLXJkwk94zf2JZ3X4=
|
||||
github.com/bytedance/mockey v1.2.12 h1:aeszOmGw8CPX8CRx1DZ/Glzb1yXvhjDh6jdFBNZjsU4=
|
||||
github.com/bytedance/mockey v1.2.12/go.mod h1:3ZA4MQasmqC87Tw0w7Ygdy7eHIc2xgpZ8Pona5rsYIk=
|
||||
github.com/bytedance/sonic v1.5.0/go.mod h1:ED5hyg4y6t3/9Ku1R6dU/4KyJ48DZ4jPhfY1O2AihPM=
|
||||
github.com/bytedance/sonic v1.8.1/go.mod h1:i736AoUSYt75HyZLoJW9ERYxcy6eaN6h4BZXU064P/U=
|
||||
github.com/bytedance/sonic v1.13.2 h1:8/H1FempDZqC4VqjptGo14QQlJx8VdZJegxs6wwfqpQ=
|
||||
github.com/bytedance/sonic v1.13.2/go.mod h1:o68xyaF9u2gvVBuGHPlUVCy+ZfmNNO5ETf1+KgkJhz4=
|
||||
github.com/bytedance/sonic/loader v0.1.1/go.mod h1:ncP89zfokxS5LZrJxl5z0UJcsk4M4yY2JpfqGeCtNLU=
|
||||
github.com/bytedance/sonic/loader v0.2.4 h1:ZWCw4stuXUsn1/+zQDqeE7JKP+QO47tz7QCNan80NzY=
|
||||
github.com/bytedance/sonic/loader v0.2.4/go.mod h1:N8A3vUdtUebEY2/VQC0MyhYeKUFosQU6FxH2JmUe6VI=
|
||||
github.com/caarlos0/env/v11 v11.3.1 h1:cArPWC15hWmEt+gWk7YBi7lEXTXCvpaSdCiZE2X5mCA=
|
||||
github.com/caarlos0/env/v11 v11.3.1/go.mod h1:qupehSf/Y0TUTsxKywqRt/vJjN5nz6vauiYEUUr8P4U=
|
||||
github.com/cespare/xxhash/v2 v2.3.0 h1:UL815xU9SqsFlibzuggzjXhog7bL6oX9BbNZnL2UFvs=
|
||||
github.com/cespare/xxhash/v2 v2.3.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
|
||||
github.com/chenzhuoyu/base64x v0.0.0-20211019084208-fb5309c8db06/go.mod h1:DH46F32mSOjUmXrMHnKwZdA8wcEefY7UVqBKYGjpdQY=
|
||||
github.com/chenzhuoyu/base64x v0.0.0-20221115062448-fe3a3abad311/go.mod h1:b583jCggY9gE99b6G5LEC39OIiVsWj+R97kbl5odCEk=
|
||||
github.com/clbanning/mxj/v2 v2.7.0 h1:WA/La7UGCanFe5NpHF0Q3DNtnCsVoxbPKuyBNHWRyME=
|
||||
github.com/clbanning/mxj/v2 v2.7.0/go.mod h1:hNiWqW14h+kc+MdF9C6/YoRfjEJoR3ou6tn/Qo+ve2s=
|
||||
github.com/cloudwego/base64x v0.1.5 h1:XPciSp1xaq2VCSt6lF0phncD4koWyULpl5bUxbfCyP4=
|
||||
github.com/cloudwego/base64x v0.1.5/go.mod h1:0zlkT4Wn5C6NdauXdJRhSKRlJvmclQ1hhJgA0rcu/8w=
|
||||
github.com/cloudwego/hertz v0.6.2/go.mod h1:2em2hGREvCBawsTQcQxyWBGVlCeo+N1pp2q0HkkbwR0=
|
||||
github.com/cloudwego/hertz v0.9.7 h1:tAVaiO+vTf+ZkQhvNhKbDJ0hmC4oJ7bzwDi1KhvhHy4=
|
||||
github.com/cloudwego/hertz v0.9.7/go.mod h1:t6d7NcoQxPmETvzPMMIVPHMn5C5QzpqIiFsaavoLJYQ=
|
||||
github.com/cloudwego/iasm v0.2.0/go.mod h1:8rXZaNYT2n95jn+zTI1sDr+IgcD2GVs0nlbbQPiEFhY=
|
||||
github.com/cloudwego/netpoll v0.3.1/go.mod h1:1T2WVuQ+MQw6h6DpE45MohSvDTKdy2DlzCx2KsnPI4E=
|
||||
github.com/cloudwego/netpoll v0.6.4 h1:z/dA4sOTUQof6zZIO4QNnLBXsDFFFEos9OOGloR6kno=
|
||||
github.com/cloudwego/netpoll v0.6.4/go.mod h1:BtM+GjKTdwKoC8IOzD08/+8eEn2gYoiNLipFca6BVXQ=
|
||||
github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
|
||||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
||||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/expr-lang/expr v1.16.9 h1:WUAzmR0JNI9JCiF0/ewwHB1gmcGw5wW7nWt8gc6PpCI=
|
||||
github.com/expr-lang/expr v1.16.9/go.mod h1:8/vRC7+7HBzESEqt5kKpYXxrxkr31SaO8r40VO/1IT4=
|
||||
github.com/gofiber/fiber/v3 v3.0.0-beta.3 h1:7Q2I+HsIqnIEEDB+9oe7Gadpakh6ZLhXpTYz/L20vrg=
|
||||
github.com/gofiber/fiber/v3 v3.0.0-beta.3/go.mod h1:kcMur0Dxqk91R7p4vxEpJfDWZ9u5IfvrtQc8Bvv/JmY=
|
||||
github.com/gofiber/utils/v2 v2.0.0-beta.4 h1:1gjbVFFwVwUb9arPcqiB6iEjHBwo7cHsyS41NeIW3co=
|
||||
github.com/gofiber/utils/v2 v2.0.0-beta.4/go.mod h1:sdRsPU1FXX6YiDGGxd+q2aPJRMzpsxdzCXo9dz+xtOY=
|
||||
github.com/golang/glog v1.2.1 h1:OptwRhECazUx5ix5TTWC3EZhsZEHWcYWY4FQHTIubm4=
|
||||
github.com/golang/glog v1.2.1/go.mod h1:6AhwSGph0fcJtXVM/PEHPqZlFeoLxhs7/t5UDAwmO+w=
|
||||
github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI=
|
||||
github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
|
||||
github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
|
||||
github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
||||
github.com/henrylee2cn/ameda v1.4.10 h1:JdvI2Ekq7tapdPsuhrc4CaFiqw6QXFvZIULWJgQyCAk=
|
||||
github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f h1:lO4WD4F/rVNCu3HqELle0jiPLLBs70cWOduZpkS1E78=
|
||||
github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f/go.mod h1:cuUVRXasLTGF7a8hSLbxyZXjz+1KgoB3wDUb6vlszIc=
|
||||
github.com/elastic/pkcs8 v1.0.0 h1:HhitlUKxhN288kcNcYkjW6/ouvuwJWd9ioxpjnD9jVA=
|
||||
github.com/elastic/pkcs8 v1.0.0/go.mod h1:ipsZToJfq1MxclVTwpG7U/bgeDtf+0HkUiOxebk95+0=
|
||||
github.com/fsnotify/fsnotify v1.5.4/go.mod h1:OVB6XrOHzAwXMpEM7uPOzcehqUV2UqJxmVXmkdnm1bU=
|
||||
github.com/fsnotify/fsnotify v1.7.0 h1:8JEhPFa5W2WU7YfeZzPNqzMP6Lwt7L2715Ggo0nosvA=
|
||||
github.com/fsnotify/fsnotify v1.7.0/go.mod h1:40Bi/Hjc2AVfZrqy+aj+yEI+/bRxZnMJyTJwOpGvigM=
|
||||
github.com/go-logr/logr v1.4.2 h1:6pFjapn8bFcIbiKo3XT4j/BhANplGihG6tvd+8rYgrY=
|
||||
github.com/go-logr/logr v1.4.2/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY=
|
||||
github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag=
|
||||
github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE=
|
||||
github.com/go-openapi/jsonpointer v0.19.3/go.mod h1:Pl9vOtqEWErmShwVjC8pYs9cog34VGT37dQOVbmoatg=
|
||||
github.com/go-openapi/jsonpointer v0.19.5 h1:gZr+CIYByUqjcgeLXnQu2gHYQC9o73G2XUeOFYEICuY=
|
||||
github.com/go-openapi/jsonpointer v0.19.5/go.mod h1:Pl9vOtqEWErmShwVjC8pYs9cog34VGT37dQOVbmoatg=
|
||||
github.com/go-openapi/jsonreference v0.19.6 h1:UBIxjkht+AWIgYzCDSv2GN+E/togfwXUJFRTWhl2Jjs=
|
||||
github.com/go-openapi/jsonreference v0.19.6/go.mod h1:diGHMEHg2IqXZGKxqyvWdfWU/aim5Dprw5bqpKkTvns=
|
||||
github.com/go-openapi/spec v0.20.4 h1:O8hJrt0UMnhHcluhIdUgCLRWyM2x7QkBXRvOs7m+O1M=
|
||||
github.com/go-openapi/spec v0.20.4/go.mod h1:faYFR1CvsJZ0mNsmsphTMSoRrNV3TEDoAM7FOEWeq8I=
|
||||
github.com/go-openapi/swag v0.19.5/go.mod h1:POnQmlKehdgb5mhVOsnJFsivZCEZ/vjK9gh66Z9tfKk=
|
||||
github.com/go-openapi/swag v0.19.15 h1:D2NRCBzS9/pEY3gP9Nl8aDqGUcPFrwG2p+CNFrLyrCM=
|
||||
github.com/go-openapi/swag v0.19.15/go.mod h1:QYRuS/SOXUCsnplDa677K7+DxSOj6IPNl/eQntq43wQ=
|
||||
github.com/go-playground/assert/v2 v2.0.1 h1:MsBgLAaY856+nPRTKrp3/OZK38U/wa0CcBYNjji3q3A=
|
||||
github.com/go-playground/assert/v2 v2.0.1/go.mod h1:VDjEfimB/XKnb+ZQfWdccd7VUvScMdVu0Titje2rxJ4=
|
||||
github.com/go-sql-driver/mysql v1.7.0 h1:ueSltNNllEqE3qcWBTD0iQd3IpL/6U+mJxLkazJ7YPc=
|
||||
github.com/go-sql-driver/mysql v1.7.0/go.mod h1:OXbVy3sEdcQ2Doequ6Z5BW6fXNQTmx+9S1MCJN5yJMI=
|
||||
github.com/golang-jwt/jwt/v4 v4.5.2 h1:YtQM7lnr8iZ+j5q71MGKkNw9Mn7AjHM68uc9g5fXeUI=
|
||||
github.com/golang-jwt/jwt/v4 v4.5.2/go.mod h1:m21LjoU+eqJr34lmDMbreY2eSTRJ1cv77w39/MY0Ch0=
|
||||
github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
||||
github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk=
|
||||
github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek=
|
||||
github.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6rSs7xps=
|
||||
github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||
github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8=
|
||||
github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU=
|
||||
github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1 h1:EGx4pi6eqNxGaHF6qqu48+N2wcFQ5qg5FXgOdqsJ5d8=
|
||||
github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY=
|
||||
github.com/henrylee2cn/ameda v1.4.8/go.mod h1:liZulR8DgHxdK+MEwvZIylGnmcjzQ6N6f2PlWe7nEO4=
|
||||
github.com/henrylee2cn/ameda v1.4.10/go.mod h1:liZulR8DgHxdK+MEwvZIylGnmcjzQ6N6f2PlWe7nEO4=
|
||||
github.com/jackc/pgpassfile v1.0.0 h1:/6Hmqy13Ss2zCq62VdNG8tM1wchn8zjSGOBJ6icpsIM=
|
||||
github.com/jackc/pgpassfile v1.0.0/go.mod h1:CEx0iS5ambNFdcRtxPj5JhEz+xB6uRky5eyVu/W2HEg=
|
||||
github.com/jackc/pgservicefile v0.0.0-20221227161230-091c0ba34f0a h1:bbPeKD0xmW/Y25WS6cokEszi5g+S0QxI/d45PkRi7Nk=
|
||||
github.com/jackc/pgservicefile v0.0.0-20221227161230-091c0ba34f0a/go.mod h1:5TJZWKEWniPve33vlWYSoGYefn3gLQRzjfDlhSJ9ZKM=
|
||||
github.com/jackc/pgx/v5 v5.4.3 h1:cxFyXhxlvAifxnkKKdlxv8XqUf59tDlYjnV5YYfsJJY=
|
||||
github.com/jackc/pgx/v5 v5.4.3/go.mod h1:Ig06C2Vu0t5qXC60W8sqIthScaEnFvojjj9dSljmHRA=
|
||||
github.com/henrylee2cn/goutil v0.0.0-20210127050712-89660552f6f8/go.mod h1:Nhe/DM3671a5udlv2AdV2ni/MZzgfv2qrPL5nIi3EGQ=
|
||||
github.com/hertz-contrib/cors v0.1.0 h1:PQ5mATygSMzTlYtfyMyHjobYoJeHKe2Qt3tcAOgbI6E=
|
||||
github.com/hertz-contrib/cors v0.1.0/go.mod h1:VPReoq+Rvu/lZOfpp5CcX3x4mpZUc3EpSXBcVDcbvOc=
|
||||
github.com/hertz-contrib/jwt v1.0.4 h1:PHddo1FDBpGHXx9nkhSwXamEyPNCkZCtszYXcRCD3q8=
|
||||
github.com/hertz-contrib/jwt v1.0.4/go.mod h1:YntlFg4tdWw1CM5mELU00HbO8Gsa92xPd7EyrSYxAcg=
|
||||
github.com/jinzhu/inflection v1.0.0 h1:K317FqzuhWc8YvSVlFMCCUb36O/S9MCKRDI7QkRKD/E=
|
||||
github.com/jinzhu/inflection v1.0.0/go.mod h1:h+uFLlag+Qp1Va5pdKtLDYj+kHp5pxUVkryuEj+Srlc=
|
||||
github.com/jinzhu/now v1.1.5 h1:/o9tlHleP7gOFmsnYNz3RGnqzefHA47wQpKrrdTIwXQ=
|
||||
github.com/jinzhu/now v1.1.5/go.mod h1:d3SSVoowX0Lcu0IBviAWJpolVfI5UJVZZ7cO71lE/z8=
|
||||
github.com/klauspost/compress v1.17.9 h1:6KIumPrER1LHsvBVuDa0r5xaG0Es51mhhB9BQB2qeMA=
|
||||
github.com/klauspost/compress v1.17.9/go.mod h1:Di0epgTjJY877eYKx5yC51cX2A2Vl2ibi7bDH9ttBbw=
|
||||
github.com/josharian/intern v1.0.0 h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8HmY=
|
||||
github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y=
|
||||
github.com/jtolds/gls v4.20.0+incompatible h1:xdiiI2gbIgH/gLH7ADydsJ1uDOEzR8yvV7C0MuV77Wo=
|
||||
github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU=
|
||||
github.com/klauspost/cpuid/v2 v2.0.9/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg=
|
||||
github.com/klauspost/cpuid/v2 v2.2.9 h1:66ze0taIn2H33fBvCkXuv9BmCwDfafmiIVpKV9kKGuY=
|
||||
github.com/klauspost/cpuid/v2 v2.2.9/go.mod h1:rqkxqrZ1EhYM9G+hXH7YdowN5R5RGN6NK4QwQ3WMXF8=
|
||||
github.com/knz/go-libedit v1.10.1/go.mod h1:MZTVkCWyz0oBc7JOWP3wNAzd002ZbM/5hgShxwh4x8M=
|
||||
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
|
||||
github.com/kr/pretty v0.3.0 h1:WgNl7dwNpEZ6jJ9k1snq4pZsg7DOEN8hP9Xw0Tsjwk0=
|
||||
github.com/kr/pretty v0.3.0/go.mod h1:640gp4NfQd8pI5XOwp5fnNeVWj67G7CFk/SaSQn7NBk=
|
||||
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
|
||||
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
|
||||
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
|
||||
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
|
||||
github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA=
|
||||
github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg=
|
||||
github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM=
|
||||
github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY=
|
||||
github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
|
||||
github.com/mailru/easyjson v0.0.0-20190614124828-94de47d64c63/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc=
|
||||
github.com/mailru/easyjson v0.0.0-20190626092158-b2ccc519800e/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc=
|
||||
github.com/mailru/easyjson v0.7.6 h1:8yTIVnZgCoiM1TgqoeTl+LfU5Jg6/xL3QhGQnimLYnA=
|
||||
github.com/mailru/easyjson v0.7.6/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc=
|
||||
github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno=
|
||||
github.com/nyaruka/phonenumbers v1.0.55 h1:bj0nTO88Y68KeUQ/n3Lo2KgK7lM1hF7L9NFuwcCl3yg=
|
||||
github.com/nyaruka/phonenumbers v1.0.55/go.mod h1:sDaTZ/KPX5f8qyV9qN+hIm+4ZBARJrupC6LuhshJq1U=
|
||||
github.com/patrickmn/go-cache v2.1.0+incompatible h1:HRMgzkcYKYpi3C8ajMPV8OFXaaRUnok+kx1WdO15EQc=
|
||||
github.com/patrickmn/go-cache v2.1.0+incompatible/go.mod h1:3Qf8kWWT7OJRJbdiICTKqZju1ZixQ/KpMGzzAfe6+WQ=
|
||||
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
|
||||
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||
github.com/rogpeppe/go-internal v1.12.0 h1:exVL4IDcn6na9z1rAb56Vxr+CgyK3nn3O+epU5NdKM8=
|
||||
github.com/rogpeppe/go-internal v1.12.0/go.mod h1:E+RYuTGaKKdloAfM02xzb0FW3Paa99yedzYV+kq4uf4=
|
||||
github.com/samber/lo v1.39.0 h1:4gTz1wUhNYLhFSKl6O+8peW0v2F4BCY034GRpU9WnuA=
|
||||
github.com/samber/lo v1.39.0/go.mod h1:+m/ZKRl6ClXCE2Lgf3MsQlWfh4bn1bz6CXEOxnEXnEA=
|
||||
github.com/redis/go-redis/v9 v9.7.3 h1:YpPyAayJV+XErNsatSElgRZZVCwXX9QzkKYNvO7x0wM=
|
||||
github.com/redis/go-redis/v9 v9.7.3/go.mod h1:bGUrSggJ9X9GUmZpZNEOQKaANxSGgOEBRltRTZHSvrA=
|
||||
github.com/rogpeppe/go-internal v1.6.1 h1:/FiVV8dS/e+YqF2JvO3yXRFbBLTIuSDkuC7aBOAvL+k=
|
||||
github.com/rogpeppe/go-internal v1.6.1/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTEfhy4qGm1nDQc=
|
||||
github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d h1:zE9ykElWQ6/NYmHa3jpm/yHnI4xSofP+UP6SpjHcSeM=
|
||||
github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc=
|
||||
github.com/smartystreets/goconvey v1.6.4 h1:fv0U8FUIMPNf1L9lnHLvLhgicrIVChEkdzIKYqbNC9s=
|
||||
github.com/smartystreets/goconvey v1.6.4/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA=
|
||||
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||
github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
|
||||
github.com/stretchr/objx v0.5.0 h1:1zr/of2m5FGMsad5YfcqgdqdWrIhu+EBEJRhR1U7z/c=
|
||||
github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo=
|
||||
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
|
||||
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
|
||||
github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA=
|
||||
github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||
github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg=
|
||||
github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
|
||||
github.com/valyala/bytebufferpool v1.0.0 h1:GqA5TC/0021Y/b9FG4Oi9Mr3q7XYx6KllzawFIhcdPw=
|
||||
github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc=
|
||||
github.com/valyala/fasthttp v1.55.0 h1:Zkefzgt6a7+bVKHnu/YaYSOPfNYNisSVBo/unVCf8k8=
|
||||
github.com/valyala/fasthttp v1.55.0/go.mod h1:NkY9JtkrpPKmgwV3HTaS2HWaJss9RSIsRVfcxxoHiOM=
|
||||
github.com/valyala/tcplisten v1.0.0 h1:rBHj/Xf+E1tRGZyWIWwJDiRY0zc1Js+CV5DqwacVSA8=
|
||||
github.com/valyala/tcplisten v1.0.0/go.mod h1:T0xQ8SeCZGxckz9qRXTfG43PvQ/mcWh7FwZEA7Ioqkc=
|
||||
golang.org/x/crypto v0.24.0 h1:mnl8DM0o513X8fdIkmyFE/5hTYxbwYOjDS/+rK6qpRI=
|
||||
golang.org/x/crypto v0.24.0/go.mod h1:Z1PMYSOR5nyMcyAVAIQSKCDwalqy85Aqn1x3Ws4L5DM=
|
||||
golang.org/x/exp v0.0.0-20240416160154-fe59bbe5cc7f h1:99ci1mjWVBWwJiEKYY6jWa4d2nTQVIEhZIptnrVb1XY=
|
||||
golang.org/x/exp v0.0.0-20240416160154-fe59bbe5cc7f/go.mod h1:/lliqkxwWAhPjf5oSOIJup2XcqJaw8RGS6k3TGEc7GI=
|
||||
golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.21.0 h1:rF+pYz3DAGSQAxAu1CbC7catZg4ebC4UIeIhKxBZvws=
|
||||
golang.org/x/sys v0.21.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||
golang.org/x/text v0.16.0 h1:a94ExnEXNtEwYLGJSIUxnWoxoRz/ZcCsV63ROupILh4=
|
||||
golang.org/x/text v0.16.0/go.mod h1:GhwF1Be+LQoKShO3cGOHzqOgRrGaYc9AvblQOmPVHnI=
|
||||
github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
|
||||
github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
|
||||
github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA=
|
||||
github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
|
||||
github.com/swaggo/swag v1.16.4 h1:clWJtd9LStiG3VeijiCfOVODP6VpHtKdQy9ELFG3s1A=
|
||||
github.com/swaggo/swag v1.16.4/go.mod h1:VBsHJRsDvfYvqoiMKnsdwhNV9LEMHgEDZcyVYX0sxPg=
|
||||
github.com/tidwall/gjson v1.9.3/go.mod h1:/wbyibRr2FHMks5tjHJ5F8dMZh3AcwJEMf5vlfC0lxk=
|
||||
github.com/tidwall/gjson v1.13.0/go.mod h1:/wbyibRr2FHMks5tjHJ5F8dMZh3AcwJEMf5vlfC0lxk=
|
||||
github.com/tidwall/gjson v1.18.0 h1:FIDeeyB800efLX89e5a8Y0BNH+LOngJyGrIWxG2FKQY=
|
||||
github.com/tidwall/gjson v1.18.0/go.mod h1:/wbyibRr2FHMks5tjHJ5F8dMZh3AcwJEMf5vlfC0lxk=
|
||||
github.com/tidwall/match v1.1.1 h1:+Ho715JplO36QYgwN9PGYNhgZvoUSc9X2c80KVTi+GA=
|
||||
github.com/tidwall/match v1.1.1/go.mod h1:eRSPERbgtNPcGhD8UCthc6PmLEQXEWd3PRB5JTxsfmM=
|
||||
github.com/tidwall/pretty v1.2.0 h1:RWIZEg2iJ8/g6fDDYzMpobmaoGh5OLl4AXtGUGPcqCs=
|
||||
github.com/tidwall/pretty v1.2.0/go.mod h1:ITEVvHYasfjBbM0u2Pg8T2nJnzm8xPwvNhhsoaGGjNU=
|
||||
github.com/twitchyliquid64/golang-asm v0.15.1 h1:SU5vSMR7hnwNxj24w34ZyCi/FmDZTkS4MhqMhdFk5YI=
|
||||
github.com/twitchyliquid64/golang-asm v0.15.1/go.mod h1:a1lVb/DtPvCB8fslRZhAngC2+aY1QWCk3Cedj/Gdt08=
|
||||
github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
|
||||
go.opentelemetry.io/auto/sdk v1.1.0 h1:cH53jehLUN6UFLY71z+NDOiNJqDdPRaXzTel0sJySYA=
|
||||
go.opentelemetry.io/auto/sdk v1.1.0/go.mod h1:3wSPjt5PWp2RhlCcmmOial7AvC4DQqZb7a7wCow3W8A=
|
||||
go.opentelemetry.io/otel v1.35.0 h1:xKWKPxrxB6OtMCbmMY021CqC45J+3Onta9MqjhnusiQ=
|
||||
go.opentelemetry.io/otel v1.35.0/go.mod h1:UEqy8Zp11hpkUrL73gSlELM0DupHoiq72dR+Zqel/+Y=
|
||||
go.opentelemetry.io/otel/metric v1.35.0 h1:0znxYu2SNyuMSQT4Y9WDWej0VpcsxkuklLa4/siN90M=
|
||||
go.opentelemetry.io/otel/metric v1.35.0/go.mod h1:nKVFgxBZ2fReX6IlyW28MgZojkoAkJGaE8CpgeAU3oE=
|
||||
go.opentelemetry.io/otel/sdk v1.4.0 h1:LJE4SW3jd4lQTESnlpQZcBhQ3oci0U2MLR5uhicfTHQ=
|
||||
go.opentelemetry.io/otel/sdk v1.4.0/go.mod h1:71GJPNJh4Qju6zJuYl1CrYtXbrgfau/M9UAggqiy1UE=
|
||||
go.opentelemetry.io/otel/trace v1.35.0 h1:dPpEfJu1sDIqruz7BHFG3c7528f6ddfSWfFDVt/xgMs=
|
||||
go.opentelemetry.io/otel/trace v1.35.0/go.mod h1:WUk7DtFp1Aw2MkvqGdwiXYDZZNvA/1J8o6xRXLrIkyc=
|
||||
go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto=
|
||||
go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE=
|
||||
go.uber.org/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0=
|
||||
go.uber.org/multierr v1.11.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y=
|
||||
go.uber.org/zap v1.27.0 h1:aJMhYGrd5QSmlpLMr2MftRKl7t8J8PTZPA732ud/XR8=
|
||||
go.uber.org/zap v1.27.0/go.mod h1:GB2qFLM7cTU87MWRP2mPIjqfIDnGu+VIO4V/SdhGo2E=
|
||||
golang.org/x/arch v0.0.0-20201008161808-52c3e6f60cff/go.mod h1:flIaEI6LNU6xOCD5PaJvn9wGP0agmIOqjrtsKGRguv4=
|
||||
golang.org/x/arch v0.0.0-20210923205945-b76863e36670/go.mod h1:5om86z9Hs0C8fWVUuoMHwpExlXzs5Tkyp9hOrfG7pp8=
|
||||
golang.org/x/arch v0.8.0 h1:3wRIsP3pM4yUptoR96otTUOXI367OS0+c9eeRi9doIc=
|
||||
golang.org/x/arch v0.8.0/go.mod h1:FEVrYAQjsQXMVJ1nsMoVVXPZg6p2JE2mx8psSWTDQys=
|
||||
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
||||
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
|
||||
golang.org/x/crypto v0.19.0/go.mod h1:Iy9bg/ha4yyC70EfRS8jz+B6ybOBKMaSxLj6P6oBDfU=
|
||||
golang.org/x/crypto v0.22.0/go.mod h1:vr6Su+7cTlO45qkww3VDJlzDn0ctJvRgYbC2NvXHt+M=
|
||||
golang.org/x/crypto v0.37.0 h1:kJNSjF/Xp7kU0iB2Z+9viTPMW4EqqsrywMXLJOOsXSE=
|
||||
golang.org/x/crypto v0.37.0/go.mod h1:vg+k43peMZ0pUMhYmVAWysMK35e6ioLh3wB8ZCAfbVc=
|
||||
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
|
||||
golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
|
||||
golang.org/x/mod v0.17.0 h1:zY54UmvipHiNd+pm+m0x9KhZ9hl1/7QNMyxXbc6ICqA=
|
||||
golang.org/x/mod v0.17.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c=
|
||||
golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
|
||||
golang.org/x/net v0.0.0-20210421230115-4e50805a0758/go.mod h1:72T/g9IO56b78aLF+1Kcs5dz7/ng1VjMUvfKvpfy+jM=
|
||||
golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
|
||||
golang.org/x/net v0.0.0-20221014081412-f15817d10f9b/go.mod h1:YDH+HFinaLZZlnHAfSS6ZXJJ9M9t4Dl22yv3iI2vPwk=
|
||||
golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs=
|
||||
golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg=
|
||||
golang.org/x/net v0.21.0/go.mod h1:bIjVDfnllIU7BJ2DNgfnXvpSvtn8VRwhlsaeUTyUS44=
|
||||
golang.org/x/net v0.25.0 h1:d/OCCoBEUq33pjydKrGQhw7IlUPI2Oylr+8qLx49kac=
|
||||
golang.org/x/net v0.25.0/go.mod h1:JkAGAh7GEvH74S6FOH42FLoXpXbE/aqXSrIQjXgsiwM=
|
||||
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.13.0 h1:AauUjRAJ9OSnvULf/ARrrVywoJDy0YS2AwQ98I37610=
|
||||
golang.org/x/sync v0.13.0/go.mod h1:1dzgHSNfp02xaA81J2MS99Qcpr2w7fw1gpm99rleRqA=
|
||||
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210420072515-93ed5bcd2bfe/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220110181412-a018aaa089fe/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220412211240-33da011f77ad/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220728004956-3c1f35247d10/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.17.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||
golang.org/x/sys v0.19.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||
golang.org/x/sys v0.32.0 h1:s77OFDvIQeibCmezSnk/q6iAfkdiQaJi4VzroCFrN20=
|
||||
golang.org/x/sys v0.32.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k=
|
||||
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
||||
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
|
||||
golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k=
|
||||
golang.org/x/term v0.8.0/go.mod h1:xPskH00ivmX89bAKVGSKKtLOWNx2+17Eiy94tnKShWo=
|
||||
golang.org/x/term v0.17.0/go.mod h1:lLRBjIVuehSbZlaOtGMbcMncT+aqLLLmKrsjNrUguwk=
|
||||
golang.org/x/term v0.19.0/go.mod h1:2CuTdWZ7KHSQwUzKva0cbMg6q2DMI3Mmxp+gKJbskEk=
|
||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
|
||||
golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
|
||||
golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8=
|
||||
golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
|
||||
golang.org/x/text v0.24.0 h1:dd5Bzh4yt5KYA8f9CJHCP4FB4D51c2c6JvN37xJJkJ0=
|
||||
golang.org/x/text v0.24.0/go.mod h1:L8rBsPeo2pSS+xqN0d5u2ikmjtmoJbDBT1b7nHvFCdU=
|
||||
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
golang.org/x/tools v0.0.0-20190328211700-ab21143f2384/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
|
||||
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||
golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
|
||||
golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU=
|
||||
golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d h1:vU5i/LfpvrRCpgM/VPfJLg5KjxD3E+hfT1SH+d9zLwg=
|
||||
golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d/go.mod h1:aiJjzUbINMkxbQROHiO6hDPo2LHcIPhhQsa9DLh0yGk=
|
||||
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw=
|
||||
google.golang.org/protobuf v1.27.1/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
|
||||
google.golang.org/protobuf v1.35.2 h1:8Ar7bF+apOIoThw1EdZl0p1oWvMqTHmpA2fRTyZO8io=
|
||||
google.golang.org/protobuf v1.35.2/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=
|
||||
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q=
|
||||
gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI=
|
||||
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY=
|
||||
gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
|
||||
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||
gopkg.in/yaml.v3 v3.0.0-20200615113413-eeeca48fe776/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
|
||||
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||
gorm.io/driver/postgres v1.5.7 h1:8ptbNJTDbEmhdr62uReG5BGkdQyeasu/FZHxI0IMGnM=
|
||||
gorm.io/driver/postgres v1.5.7/go.mod h1:3e019WlBaYI5o5LIdNV+LyxCMNtLOQETBXL2h4chKpA=
|
||||
gorm.io/gorm v1.25.10 h1:dQpO+33KalOA+aFYGlK+EfxcI5MbO7EP2yYygwh9h+s=
|
||||
gorm.io/gorm v1.25.10/go.mod h1:hbnx/Oo0ChWMn1BIhpy1oYozzpM15i4YPuHDmfYtwg8=
|
||||
gorm.io/driver/mysql v1.5.7 h1:MndhOPYOfEp2rHKgkZIhJ16eVUIRf2HmzgoPmh7FCWo=
|
||||
gorm.io/driver/mysql v1.5.7/go.mod h1:sEtPWMiqiN1N1cMXoXmBbd8C6/l+TESwriotuRRpkDM=
|
||||
gorm.io/gorm v1.25.7/go.mod h1:hbnx/Oo0ChWMn1BIhpy1oYozzpM15i4YPuHDmfYtwg8=
|
||||
gorm.io/gorm v1.25.12 h1:I0u8i2hWQItBq1WfE0o2+WuL9+8L21K9e2HHSTE/0f8=
|
||||
gorm.io/gorm v1.25.12/go.mod h1:xh7N7RHfYlNc5EmcI/El95gXusucDrQnHXe0+CgWcLQ=
|
||||
nullprogram.com/x/optparse v1.0.0/go.mod h1:KdyPE+Igbe0jQUrVfMqDMeJQIJZEuyV7pjYmp6pbG50=
|
||||
rsc.io/pdf v0.1.1/go.mod h1:n8OzWcQ6Sp37PL01nO98y4iUCRdTGarVfzxY20ICaU4=
|
||||
|
56
main.go
Normal file
56
main.go
Normal file
@ -0,0 +1,56 @@
|
||||
// Code generated by hertz generator.
|
||||
|
||||
package main
|
||||
|
||||
import (
|
||||
"os"
|
||||
|
||||
"github.com/ArtisanCloud/PowerWeChat/v3/src/miniProgram"
|
||||
"github.com/cloudwego/hertz/pkg/app/server"
|
||||
"github.com/hertz-contrib/cors"
|
||||
"gitlab.com/kedaya_mp/user/biz/router/healthz"
|
||||
"gitlab.com/kedaya_mp/user/biz/router/user"
|
||||
"gitlab.com/kedaya_mp/user/pkg/captcha"
|
||||
"gitlab.com/kedaya_mp/user/pkg/mysql"
|
||||
"gitlab.com/kedaya_mp/user/pkg/wx"
|
||||
"gorm.io/gorm"
|
||||
)
|
||||
|
||||
func register(h *server.Hertz, db *gorm.DB, miniProgramApp *miniProgram.MiniProgram, captchaService captcha.Service) {
|
||||
user.Register(h, db, miniProgramApp, captchaService)
|
||||
healthz.NewHealthz().Registry(h)
|
||||
}
|
||||
|
||||
// @title 用户和登录相关接口
|
||||
// @version 1.0
|
||||
// @description 这是一个用户和登录相关的接口文档
|
||||
// @contact.name oneCat-user
|
||||
// @license.name Apache 2.0
|
||||
// @license.url http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
|
||||
// @BasePath /
|
||||
// @schemes http
|
||||
func main() {
|
||||
port := ":80"
|
||||
if os.Getenv("PORT") != "" {
|
||||
port = os.Getenv("PORT")
|
||||
}
|
||||
|
||||
h := server.Default(server.WithHostPorts(port))
|
||||
h.Use(cors.New(cors.Config{
|
||||
AllowAllOrigins: true,
|
||||
AllowMethods: []string{"GET", "POST"},
|
||||
ExposeHeaders: []string{"Content-Length"},
|
||||
AllowHeaders: []string{"Origin", "Authorization", "Content-Type"},
|
||||
AllowCredentials: true,
|
||||
}))
|
||||
|
||||
db := mysql.InitDB()
|
||||
miniProgramApp := wx.NewWX()
|
||||
captchaService := captcha.InitDefaultService()
|
||||
defer captchaService.Close()
|
||||
|
||||
register(h, db, miniProgramApp, captchaService)
|
||||
|
||||
h.Spin()
|
||||
}
|
28
pkg/captcha/captcha.go
Normal file
28
pkg/captcha/captcha.go
Normal file
@ -0,0 +1,28 @@
|
||||
package captcha
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"math"
|
||||
"math/rand/v2"
|
||||
"time"
|
||||
)
|
||||
|
||||
type Generator interface {
|
||||
Generate() string
|
||||
}
|
||||
|
||||
type stringCaptchaGenerator struct {
|
||||
length int
|
||||
}
|
||||
|
||||
func NewStringCaptchaGenerator(length int) Generator {
|
||||
return &stringCaptchaGenerator{
|
||||
length: length,
|
||||
}
|
||||
}
|
||||
|
||||
func (s *stringCaptchaGenerator) Generate() string {
|
||||
n := math.Pow(10, float64(s.length))
|
||||
r := rand.New(rand.NewPCG(uint64(time.Now().UnixNano()), 2)).IntN(int(n))
|
||||
return fmt.Sprintf("%0*d", s.length, r)
|
||||
}
|
30
pkg/captcha/init.go
Normal file
30
pkg/captcha/init.go
Normal file
@ -0,0 +1,30 @@
|
||||
package captcha
|
||||
|
||||
import (
|
||||
"github.com/caarlos0/env/v11"
|
||||
"github.com/cloudwego/hertz/pkg/common/hlog"
|
||||
"github.com/redis/go-redis/v9"
|
||||
)
|
||||
|
||||
type Config struct {
|
||||
Address string `env:"CAPTCHA_REDIS_ADDRESS"`
|
||||
Password string `env:"CAPTCHA_REDIS_PASSWORD"`
|
||||
DB int `env:"CAPTCHA_REDIS_DB"`
|
||||
}
|
||||
|
||||
func InitDefaultService() Service {
|
||||
var opt Config
|
||||
if err := env.Parse(&opt); err != nil {
|
||||
hlog.Fatalf("parse captcha config failed: %v", err)
|
||||
}
|
||||
rdb := redis.NewClient(&redis.Options{
|
||||
Addr: opt.Address,
|
||||
Password: opt.Password,
|
||||
DB: opt.DB,
|
||||
})
|
||||
return NewSMSCaptchaService(
|
||||
NewRedisStore(rdb),
|
||||
// TODO 替换为真实的短信服务
|
||||
nil,
|
||||
)
|
||||
}
|
26
pkg/captcha/interface.go
Normal file
26
pkg/captcha/interface.go
Normal file
@ -0,0 +1,26 @@
|
||||
package captcha
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"time"
|
||||
)
|
||||
|
||||
var (
|
||||
ErrCodeSendTooMany = errors.New("发送验证码太频繁")
|
||||
ErrCodeVerifyFail = errors.New("验证码错误")
|
||||
)
|
||||
|
||||
// Service 发送和验证验证码
|
||||
type Service interface {
|
||||
SendCode(ctx context.Context, phone string) error
|
||||
VerifyCode(ctx context.Context, phone, code string) error
|
||||
Close() error
|
||||
}
|
||||
|
||||
type Store interface {
|
||||
Set(ctx context.Context, key string, value string, timeout time.Duration) error
|
||||
Get(ctx context.Context, key string) (string, error)
|
||||
Delete(ctx context.Context, key string) error
|
||||
Close() error
|
||||
}
|
51
pkg/captcha/sms.go
Normal file
51
pkg/captcha/sms.go
Normal file
@ -0,0 +1,51 @@
|
||||
package captcha
|
||||
|
||||
import (
|
||||
"context"
|
||||
"time"
|
||||
|
||||
"gitlab.com/kedaya_mp/user/pkg/sms"
|
||||
)
|
||||
|
||||
// 短信验证码
|
||||
type smsService struct {
|
||||
store Store
|
||||
sms sms.Service
|
||||
generator Generator
|
||||
}
|
||||
|
||||
func NewSMSCaptchaService(store Store, sms sms.Service) Service {
|
||||
return &smsService{
|
||||
store: store,
|
||||
sms: sms,
|
||||
generator: NewStringCaptchaGenerator(6),
|
||||
}
|
||||
}
|
||||
|
||||
func (s *smsService) SendCode(ctx context.Context, phone string) error {
|
||||
captcha := s.generator.Generate()
|
||||
if err := s.sms.Send(ctx, phone, captcha); err != nil {
|
||||
return err
|
||||
}
|
||||
return s.store.Set(ctx, phone, captcha, time.Minute*5)
|
||||
}
|
||||
func (s *smsService) VerifyCode(ctx context.Context, phone, code string) error {
|
||||
// 从store中获取验证码
|
||||
captcha, _ := s.store.Get(ctx, phone)
|
||||
// TODO 写一个测试用的验证码,后面接入真实的短信服务后,就可以删除这个if语句
|
||||
if code == "zhhg" {
|
||||
return nil
|
||||
}
|
||||
if captcha == "" {
|
||||
return ErrCodeVerifyFail
|
||||
}
|
||||
|
||||
if captcha != code {
|
||||
return ErrCodeVerifyFail
|
||||
}
|
||||
_ = s.store.Delete(ctx, phone)
|
||||
return nil
|
||||
}
|
||||
func (s *smsService) Close() error {
|
||||
return s.store.Close()
|
||||
}
|
28
pkg/captcha/store.go
Normal file
28
pkg/captcha/store.go
Normal file
@ -0,0 +1,28 @@
|
||||
package captcha
|
||||
|
||||
import (
|
||||
"context"
|
||||
"time"
|
||||
|
||||
"github.com/redis/go-redis/v9"
|
||||
)
|
||||
|
||||
type redisStore struct {
|
||||
client *redis.Client
|
||||
}
|
||||
|
||||
func NewRedisStore(client *redis.Client) Store {
|
||||
return &redisStore{client: client}
|
||||
}
|
||||
func (s *redisStore) Set(ctx context.Context, key string, value string, timeout time.Duration) error {
|
||||
return s.client.Set(ctx, key, value, timeout).Err()
|
||||
}
|
||||
func (s *redisStore) Get(ctx context.Context, key string) (string, error) {
|
||||
return s.client.Get(ctx, key).Result()
|
||||
}
|
||||
func (s *redisStore) Delete(ctx context.Context, key string) error {
|
||||
return s.client.Del(ctx, key).Err()
|
||||
}
|
||||
func (s *redisStore) Close() error {
|
||||
return s.client.Close()
|
||||
}
|
18
pkg/crypto/password.go
Normal file
18
pkg/crypto/password.go
Normal file
@ -0,0 +1,18 @@
|
||||
package crypto
|
||||
|
||||
import (
|
||||
"crypto/sha256"
|
||||
"encoding/hex"
|
||||
)
|
||||
|
||||
// HashPassword 使用 SHA-256 对密码进行加密
|
||||
func HashPassword(password string) string {
|
||||
hash := sha256.New()
|
||||
hash.Write([]byte(password))
|
||||
return hex.EncodeToString(hash.Sum(nil))
|
||||
}
|
||||
|
||||
// VerifyPassword 验证密码是否匹配
|
||||
func VerifyPassword(password, hashedPassword string) bool {
|
||||
return HashPassword(password) == hashedPassword
|
||||
}
|
68
pkg/mysql/db.go
Normal file
68
pkg/mysql/db.go
Normal file
@ -0,0 +1,68 @@
|
||||
package mysql
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"log"
|
||||
"os"
|
||||
"time"
|
||||
|
||||
"github.com/caarlos0/env/v11"
|
||||
"github.com/cloudwego/hertz/pkg/common/hlog"
|
||||
"gorm.io/driver/mysql"
|
||||
"gorm.io/gorm"
|
||||
"gorm.io/gorm/logger"
|
||||
"gorm.io/gorm/schema"
|
||||
)
|
||||
|
||||
type Config struct {
|
||||
Address string `env:"MYSQL_ADDRESS"`
|
||||
User string `env:"MYSQL_USERNAME"`
|
||||
Password string `env:"MYSQL_PASSWORD"`
|
||||
DBName string `env:"MYSQL_DBNAME"`
|
||||
}
|
||||
|
||||
// InitDB 初始化数据库连接
|
||||
func InitDB() *gorm.DB {
|
||||
var cfg Config
|
||||
if err := env.Parse(&cfg); err != nil {
|
||||
hlog.Fatalf("解析数据库环境变量失败: %v", err)
|
||||
}
|
||||
// 配置日志
|
||||
newLogger := logger.New(
|
||||
log.New(os.Stdout, "\r\n", log.LstdFlags),
|
||||
logger.Config{
|
||||
SlowThreshold: time.Second, // 慢SQL阈值
|
||||
LogLevel: logger.Warn, // 日志级别
|
||||
IgnoreRecordNotFoundError: true, // 忽略记录未找到错误
|
||||
Colorful: true, // 彩色输出
|
||||
},
|
||||
)
|
||||
|
||||
// 配置GORM
|
||||
config := &gorm.Config{
|
||||
Logger: newLogger,
|
||||
NamingStrategy: schema.NamingStrategy{
|
||||
SingularTable: true, // 使用单数表名
|
||||
},
|
||||
}
|
||||
dsn := fmt.Sprintf("%s:%s@tcp(%s)/%s?charset=utf8mb4&parseTime=True&loc=Local", cfg.User, cfg.Password, cfg.Address, cfg.DBName)
|
||||
// 连接数据库
|
||||
DB, err := gorm.Open(mysql.Open(dsn), config)
|
||||
if err != nil {
|
||||
hlog.Fatalf("连接数据库失败: %v", err)
|
||||
}
|
||||
|
||||
hlog.Info("数据库连接成功")
|
||||
|
||||
// 获取底层SQL连接池
|
||||
sqlDB, err := DB.DB()
|
||||
if err != nil {
|
||||
hlog.Fatalf("获取数据库连接池失败: %v", err)
|
||||
}
|
||||
|
||||
// 设置连接池参数
|
||||
sqlDB.SetMaxIdleConns(10) // 最大空闲连接数
|
||||
sqlDB.SetMaxOpenConns(100) // 最大打开连接数
|
||||
sqlDB.SetConnMaxLifetime(time.Hour) // 连接最大生命周期
|
||||
return DB
|
||||
}
|
11
pkg/sms/sms.go
Normal file
11
pkg/sms/sms.go
Normal file
@ -0,0 +1,11 @@
|
||||
package sms
|
||||
|
||||
import (
|
||||
"context"
|
||||
)
|
||||
|
||||
type Service interface {
|
||||
Send(ctx context.Context, phone, msg string) error
|
||||
}
|
||||
|
||||
// todo实现发短信
|
38
pkg/wx/client.go
Normal file
38
pkg/wx/client.go
Normal file
@ -0,0 +1,38 @@
|
||||
package wx
|
||||
|
||||
import (
|
||||
"github.com/ArtisanCloud/PowerWeChat/v3/src/kernel"
|
||||
"github.com/ArtisanCloud/PowerWeChat/v3/src/miniProgram"
|
||||
"github.com/caarlos0/env/v11"
|
||||
"github.com/cloudwego/hertz/pkg/common/hlog"
|
||||
)
|
||||
|
||||
type WX struct {
|
||||
AppID string `env:"WX_APPID"`
|
||||
AppSecret string `env:"WX_APPSECRET"`
|
||||
Address string `env:"WX_REDIS_ADDRESS"`
|
||||
Password string `env:"WX_REDIS_PASSWORD"`
|
||||
DB int `env:"WX_REDIS_DB"`
|
||||
}
|
||||
|
||||
// NewWX 初始化默认的微信客户端
|
||||
func NewWX() *miniProgram.MiniProgram {
|
||||
var config WX
|
||||
err := env.Parse(&config)
|
||||
if err != nil {
|
||||
hlog.Fatalf("加载微信客户端配置失败: %v", err)
|
||||
}
|
||||
mp, _err := miniProgram.NewMiniProgram(&miniProgram.UserConfig{
|
||||
AppID: config.AppID,
|
||||
Secret: config.AppSecret,
|
||||
Cache: kernel.NewRedisClient(&kernel.UniversalOptions{
|
||||
Addrs: []string{config.Address},
|
||||
Password: config.Password,
|
||||
DB: config.DB,
|
||||
}),
|
||||
})
|
||||
if _err != nil {
|
||||
hlog.Fatalf("初始化微信客户端失败: %v", _err)
|
||||
}
|
||||
return mp
|
||||
}
|
@ -1,26 +0,0 @@
|
||||
package service
|
||||
|
||||
import (
|
||||
"gitea.timerzz.com/kedaya_haitao/common/pkg/web"
|
||||
"gitea.timerzz.com/kedaya_haitao/common/structs/storage"
|
||||
)
|
||||
|
||||
type user struct {
|
||||
storage *storage.Storage
|
||||
}
|
||||
|
||||
func Newuser(storage *storage.Storage) *user {
|
||||
return &user{
|
||||
storage: storage,
|
||||
}
|
||||
}
|
||||
|
||||
func (s *user) Registry(r fiber.Router) {
|
||||
api := r.Group("/api/v2")
|
||||
}
|
||||
|
||||
func (s *user) List(c fiber.Ctx) error {
|
||||
|
||||
|
||||
return c.JSON(web.NewResponse(web.NewListResponse(total, sellers)))
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user