Bladeren bron

init:初始化项目

zqbao 9 maanden geleden
commit
715614be00

+ 6 - 0
.gitignore

@@ -0,0 +1,6 @@
+/conf/
+/.vscode/
+/etalogs/
+*.exe
+*.exe~
+go.sum

+ 104 - 0
controllers/base_auth.go

@@ -0,0 +1,104 @@
+package controllers
+
+import (
+	"encoding/json"
+	"eta/eta_mini_api/models"
+	"eta/eta_mini_api/utils"
+	"net/http"
+	"strconv"
+	"strings"
+	"time"
+
+	"github.com/beego/beego/v2/client/orm"
+	"github.com/beego/beego/v2/server/web"
+)
+
+type BaseAuthController struct {
+	web.Controller
+	User    *models.User
+	Session *models.WxSession
+}
+
+func (c *BaseAuthController) Prepare() {
+	method := c.Ctx.Input.Method()
+	// uri := c.Ctx.Input.URI()
+	if method != "HEAD" {
+		if method == "POST" || method == "GET" {
+			authorization := c.Ctx.Input.Header("authorization")
+			if authorization == "" {
+				c.JSON(models.BaseResponse{Ret: 408, Msg: "请重新授权!", ErrMsg: "请重新授权:Token is empty or account is empty"})
+				c.StopRun()
+				return
+			}
+			tokenStr := authorization
+			tokenArr := strings.Split(tokenStr, "=")
+			token := tokenArr[1]
+
+			session, err := models.GetWxSessionByToken(token)
+			if err != nil {
+				if err == orm.ErrNoRows {
+					c.JSON(models.BaseResponse{Ret: 408, Msg: "信息已变更,请重新登陆!", ErrMsg: "Token 信息已变更:Token: " + token})
+					c.StopRun()
+					return
+				}
+				c.JSON(models.BaseResponse{Ret: 408, Msg: "网络异常,请稍后重试!", ErrMsg: "获取用户信息异常,Eerr:" + err.Error()})
+				c.StopRun()
+				return
+			}
+			if session == nil {
+				c.JSON(models.BaseResponse{Ret: 408, Msg: "网络异常,请稍后重试!", ErrMsg: "sesson is empty "})
+				c.StopRun()
+				return
+			}
+
+			account := utils.MD5(strconv.Itoa(session.UserId))
+			if !utils.CheckToken(account, token) {
+				c.JSON(models.BaseResponse{Ret: 408, Msg: "鉴权失败,请重新登录!", ErrMsg: "登录失效,请重新登陆!,CheckToken Fail"})
+				c.StopRun()
+				return
+			}
+			if time.Now().After(session.ExpiredTime) {
+				c.JSON(models.BaseResponse{Ret: 408, Msg: "请重新登录!", ErrMsg: "获取用户信息异常"})
+				c.StopRun()
+				return
+			}
+			user, err := models.GetUserById(session.UserId)
+			if err != nil {
+				if err == orm.ErrNoRows {
+					c.JSON(models.BaseResponse{Ret: 408, Msg: "信息已变更,请重新登陆!", ErrMsg: "获取sysUser信息失败: " + strconv.Itoa(session.UserId)})
+					c.StopRun()
+					return
+				}
+				c.JSON(models.BaseResponse{Ret: 408, Msg: "网络异常,请稍后重试!", ErrMsg: "获取sysUser信息异常,Err:" + err.Error()})
+				c.StopRun()
+				return
+			}
+			if user == nil {
+				c.JSON(models.BaseResponse{Ret: 408, Msg: "网络异常,请稍后重试!", ErrMsg: "sysUser is empty"})
+				c.StopRun()
+				return
+			}
+			c.User = user
+			c.Session = session
+		}
+	}
+}
+
+func (c *BaseAuthController) JSON(data interface{}) error {
+	c.Ctx.Output.Header("Content-Type", "application/json; charset=utf-8")
+	desEncrypt := utils.DesBase64Encrypt([]byte(utils.DesKey), utils.DesKeySalt)
+	c.Ctx.Output.Header("Dk", string(desEncrypt)) // des3加解密key
+	// 设置Cookie为HTTPOnly
+	c.Ctx.SetCookie("", "", -1, "/", "", false, true, "")
+
+	content, err := json.Marshal(data)
+	if err != nil {
+		http.Error(c.Ctx.Output.Context.ResponseWriter, err.Error(), http.StatusInternalServerError)
+		return err
+	}
+	if utils.RunMode != "debug" {
+		content = utils.DesBase64Encrypt(content, utils.DesKey)
+		content = []byte(`"` + string(content) + `"`)
+	}
+	return c.Ctx.Output.Body(content)
+}

+ 25 - 0
controllers/base_common.go

@@ -0,0 +1,25 @@
+package controllers
+
+import (
+	"eta/eta_mini_api/utils"
+	"net/url"
+
+	"github.com/beego/beego/v2/server/web"
+)
+
+type BaseCommonController struct {
+	web.Controller
+}
+
+func (c *BaseCommonController) Prepare() {
+	var requestBody string
+	method := c.Ctx.Input.Method()
+	if method == "GET" {
+		requestBody = c.Ctx.Request.RequestURI
+	} else {
+		requestBody, _ = url.QueryUnescape(string(c.Ctx.Input.RequestBody))
+	}
+
+	ip := c.Ctx.Input.IP()
+	utils.ApiLog.Info("uri:%s, requestBody:%s, ip:%s", c.Ctx.Input.URI(), requestBody, ip)
+}

+ 138 - 0
controllers/user.go

@@ -0,0 +1,138 @@
+package controllers
+
+import (
+	"encoding/json"
+	"eta/eta_mini_api/models"
+	"eta/eta_mini_api/models/request"
+	"eta/eta_mini_api/services"
+	"eta/eta_mini_api/utils"
+	"fmt"
+)
+
+type UserController struct {
+	BaseCommonController
+}
+
+// @Title 用户登录接口
+// @Description 用户登录
+// @Param	request	body models.LoginReq true "type json string"
+// @Success 200 {object} models.LoginResp
+// @router /login [post]
+func (this *UserController) Login() {
+	br := new(models.BaseResponse).Init()
+	defer func() {
+		this.Data["json"] = br
+		this.ServeJSON()
+	}()
+
+	var req request.LoginReq
+	err := json.Unmarshal(this.Ctx.Input.RequestBody, &req)
+	if err != nil {
+		br.Msg = "参数解析失败"
+		br.ErrMsg = "参数解析失败,Err:" + err.Error()
+		return
+	}
+	switch req.LoginType {
+	case 1:
+		if req.Mobile == "" {
+			br.Msg = "请输入手机号"
+			return
+		}
+		if req.VerifyCode == "" {
+			br.Msg = "请输入验证码"
+			return
+		}
+		code := utils.GetRandDigit(6)
+		ok := services.SendSmsCode(req.Mobile, code)
+		if !ok {
+			br.Msg = "短信验证码发送失败"
+			return
+		}
+
+	case 2:
+		if req.Email == "" {
+			br.Msg = "请输入邮箱"
+			return
+		}
+		if req.VerifyCode == "" {
+			br.Msg = "请输入验证码"
+			return
+		}
+
+	}
+
+	br.Msg = "登录成功"
+	br.Success = true
+	br.Ret = 200
+}
+
+// GetVerifyCode
+// @Title 获取短信/邮箱验证码
+// @Description 获取短信/邮箱验证码
+// @Param	request	body VerifyCodeReq true "type json string"
+// @Success 200 Ret=200 获取成功
+// @Router /getSmsCode [get]
+func (this *UserController) GetVerifyCode() {
+	br := new(models.BaseResponse).Init()
+	defer func() {
+		this.Data["json"] = br
+		this.ServeJSON()
+	}()
+
+	var req request.VerifyCodeReq
+	err := json.Unmarshal(this.Ctx.Input.RequestBody, &req)
+	if err != nil {
+		br.Msg = "参数解析异常!"
+		br.ErrMsg = "参数解析失败,Err:" + err.Error()
+		return
+	}
+	if req.VerifyType != 1 && req.VerifyType != 2 {
+		br.Msg = "验证方式有误"
+		br.ErrMsg = fmt.Sprintf("验证方式异常<%d>", req.VerifyType)
+	}
+
+	switch req.VerifyType {
+	case 1:
+		if req.TelAreaCode == "" {
+			br.Msg = "请选择区号"
+			return
+		}
+		if req.Mobile == "" {
+			br.Msg = "请输入手机号"
+			return
+		}
+		if req.TelAreaCode == utils.TelAreaCodeHome && !utils.ValidateMobileFormatat(req.Mobile) {
+			br.Msg = "您的手机号输入有误, 请检查"
+			return
+		}
+		ok := services.SendSmsCode(req.Mobile, req.TelAreaCode)
+		if !ok {
+			br.ErrMsg = "短信验证码发送错误" + err.Error()
+			return
+		}
+	case 2:
+		if req.Email == "" {
+			br.Msg = "请输入邮箱"
+		}
+		if !utils.ValidateEmailFormatat(req.Email) {
+			br.Msg = "您的邮箱格式输入有误, 请检查"
+			return
+		}
+		// err := services.SendEmailCode(req.Email)
+	}
+
+	br.Ret = 200
+	br.Success = true
+	br.Msg = "发送成功"
+}
+
+// SendEmail
+// @Title 获取短信/邮箱验证码
+// @Description 获取短信/邮箱验证码
+// @Param	request	body VerifyCodeReq true "type json string"
+// @Success 200 Ret=200 获取成功
+// @Router /sendEmail [get]
+func (this *UserController) SendEmail() {
+	utils.SendEmailByHz("测试邮箱", "测试内容", "564693862@qq.com")
+
+}

+ 86 - 0
controllers/wechat.go

@@ -0,0 +1,86 @@
+package controllers
+
+import (
+	"eta/eta_mini_api/models"
+	"eta/eta_mini_api/services/wechat"
+	"eta/eta_mini_api/services/wx_app"
+	"eta/eta_mini_api/utils"
+	"fmt"
+)
+
+type WechatController struct {
+	BaseCommonController
+}
+
+// Login
+// @Title 微信用户登录
+// @Description 用户登录
+// @Param	request	body UserLoginReq true "type json string"
+// @Success 200 {object} models.LoginResp
+// @router /login [get]
+func (this *WechatController) Login() {
+	br := new(models.BaseResponse).Init()
+	defer func() {
+		this.Data["json"] = br
+		this.ServeJSON()
+	}()
+
+	code := this.GetString("code")
+	wxUserInfo, err := wx_app.GetSession(code)
+	if err != nil {
+		br.Msg = "获取失败"
+		br.ErrMsg = "获取失败,Err:" + err.Error()
+		return
+	}
+
+	fmt.Println("openid", wxUserInfo.OpenID)
+	user, err := wechat.GetUserInfo(wxUserInfo.OpenID)
+	if err != nil {
+		br.Msg = "获取失败"
+		br.ErrMsg = "获取失败,Err:" + err.Error()
+		return
+	}
+	fmt.Println("user----", user)
+	fmt.Println(wxUserInfo)
+	fmt.Println("openid", wxUserInfo.OpenID)
+	fmt.Println("unionid", wxUserInfo.UnionID)
+	// token, userId, isBind, err := services.WxLogin(wxUserInfo)
+}
+
+// GetUserInfo
+// @Title 获取微信用户信息
+// @Description 获取微信用户信息
+// @Param	request	body UserLoginReq true "type json string"
+// @Success 200 {object} models.LoginResp
+// @router /userInfo [get]
+func (this *WechatController) UserInfo() {
+	br := new(models.BaseResponse).Init()
+	defer func() {
+		this.Data["json"] = br
+		this.ServeJSON()
+	}()
+
+	openid := `oxgGc63ul7XT_kkxijd5mQI_6agg`
+	userInfo, err := wechat.GetUserInfo(openid)
+	if err != nil {
+		br.Msg = "获取失败"
+		br.ErrMsg = "获取失败,系统错误,Err:" + err.Error()
+		return
+	}
+
+	br.Data = userInfo
+	br.Msg = "获取成功"
+	br.Success = true
+	br.Ret = 200
+}
+
+// SendEmail
+// @Title 获取微信用户信息
+// @Description 获取微信用户信息
+// @Param	request	body UserLoginReq true "type json string"
+// @Success 200 {object} models.LoginResp
+// @router /SendEmail [get]
+func (this *WechatController) SendEmail() {
+	utils.SendEmailByHz("测试邮箱", "测试内容", "564693862@qq.com")
+
+}

+ 46 - 0
go.mod

@@ -0,0 +1,46 @@
+module eta/eta_mini_api
+
+go 1.21
+
+require github.com/beego/beego/v2 v2.1.0
+
+require (
+	github.com/beego/bee/v2 v2.1.0
+	github.com/dgrijalva/jwt-go v3.2.0+incompatible
+	github.com/go-sql-driver/mysql v1.7.0
+	github.com/silenceper/wechat/v2 v2.1.6
+	gopkg.in/gomail.v2 v2.0.0-20160411212932-81ebce5c23df
+)
+
+require (
+	github.com/beorn7/perks v1.0.1 // indirect
+	github.com/bradfitz/gomemcache v0.0.0-20220106215444-fb4bf637b56d // indirect
+	github.com/cespare/xxhash/v2 v2.2.0 // indirect
+	github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f // indirect
+	github.com/fatih/structs v1.1.0 // indirect
+	github.com/go-redis/redis/v8 v8.11.5 // indirect
+	github.com/golang/protobuf v1.5.3 // indirect
+	github.com/hashicorp/golang-lru v0.5.4 // indirect
+	github.com/kr/text v0.2.0 // indirect
+	github.com/mattn/go-sqlite3 v2.0.3+incompatible // indirect
+	github.com/matttproud/golang_protobuf_extensions v1.0.4 // indirect
+	github.com/mitchellh/mapstructure v1.5.0 // indirect
+	github.com/pkg/errors v0.9.1 // indirect
+	github.com/prometheus/client_golang v1.15.1 // indirect
+	github.com/prometheus/client_model v0.3.0 // indirect
+	github.com/prometheus/common v0.42.0 // indirect
+	github.com/prometheus/procfs v0.9.0 // indirect
+	github.com/shiena/ansicolor v0.0.0-20200904210342-c7312218db18 // indirect
+	github.com/sirupsen/logrus v1.9.0 // indirect
+	github.com/spf13/cast v1.4.1 // indirect
+	github.com/tidwall/gjson v1.14.1 // indirect
+	github.com/tidwall/match v1.1.1 // indirect
+	github.com/tidwall/pretty v1.2.0 // indirect
+	golang.org/x/crypto v0.12.0 // indirect
+	golang.org/x/net v0.14.0 // indirect
+	golang.org/x/sys v0.11.0 // indirect
+	golang.org/x/text v0.12.0 // indirect
+	google.golang.org/protobuf v1.30.0 // indirect
+	gopkg.in/alexcesaro/quotedprintable.v3 v3.0.0-20150716171945-2caba252f4dc // indirect
+	gopkg.in/yaml.v3 v3.0.1 // indirect
+)

+ 11 - 0
main.go

@@ -0,0 +1,11 @@
+package main
+
+import (
+	_ "eta/eta_mini_api/routers"
+	beego "github.com/beego/beego/v2/server/web"
+)
+
+func main() {
+	beego.Run()
+}
+

+ 16 - 0
models/base.go

@@ -0,0 +1,16 @@
+package models
+
+type BaseResponse struct {
+	Ret         int
+	Msg         string
+	ErrMsg      string
+	ErrCode     string
+	Data        interface{}
+	Success     bool `description:"true 执行成功,false 执行失败"`
+	IsSendEmail bool `json:"-" description:"true 发送邮件,false 不发送邮件"`
+	IsAddLog    bool `json:"-" description:"true 新增操作日志,false 不新增操作日志" `
+}
+
+func (r *BaseResponse) Init() *BaseResponse {
+	return &BaseResponse{Ret: 403, IsSendEmail: true}
+}

+ 37 - 0
models/db.go

@@ -0,0 +1,37 @@
+package models
+
+import (
+	"eta/eta_mini_api/utils"
+	"time"
+
+	"github.com/beego/beego/v2/client/orm"
+	_ "github.com/go-sql-driver/mysql"
+)
+
+func init() {
+	_ = orm.RegisterDataBase("rddp", "mysql", utils.MYSQL_URL_RDDP)
+	orm.SetMaxIdleConns("rddp", 50)
+	orm.SetMaxOpenConns("rddp", 100)
+
+	report_db, _ := orm.GetDB("rddp")
+	report_db.SetConnMaxLifetime(10 * time.Minute)
+
+	_ = orm.RegisterDataBase("master", "mysql", utils.MYSQL_URL_MASTER)
+	orm.SetMaxIdleConns("master", 50)
+	orm.SetMaxOpenConns("master", 100)
+
+	master_db, _ := orm.GetDB("master")
+	master_db.SetConnMaxLifetime(10 * time.Minute)
+
+	orm.Debug = true
+	orm.DebugLog = orm.NewLog(utils.BinLog)
+
+	// register model
+	orm.RegisterModel(
+		new(WxSession),
+		new(MsgCode),
+		new(User),
+		new(WxToken),
+	)
+
+}

+ 23 - 0
models/msg_code.go

@@ -0,0 +1,23 @@
+package models
+
+import (
+	"time"
+
+	"github.com/beego/beego/v2/client/orm"
+)
+
+// MsgCode 验证码列表
+type MsgCode struct {
+	MsgCodeID  int64     `orm:"pk" description:"id"` // 短信验证码id
+	OpenID     string    `description:"用户openId"`    // 用户id
+	Mobile     string    `description:"手机号/邮箱"`      // 手机号/邮箱
+	Code       string    `description:"验证码"`         // 验证码
+	ExpiredIn  int64     `description:"过期时间"`        // 过期时间
+	CreateTime time.Time `description:"创建时间"`        // 创建时间
+}
+
+func (m *MsgCode) Insert() (err error) {
+	o := orm.NewOrmUsingDB("master")
+	_, err = o.Insert(m)
+	return
+}

+ 17 - 0
models/request/user.go

@@ -0,0 +1,17 @@
+package request
+
+type LoginReq struct {
+	WxCode     string `description:"用户code"`
+	LoginType  int    `description:"登录方式:1:手机,2:邮箱"`
+	Mobile     string `description:"手机号"`
+	Email      string `description:"邮箱"`
+	AreaNum    int    `description:"国际区号"`
+	VerifyCode string `description:"短信/邮箱 验证码"`
+}
+
+type VerifyCodeReq struct {
+	VerifyType  int    `description:"验证方式: 1-手机号; 2-邮箱"`
+	Mobile      string `description:"手机号"`
+	TelAreaCode string `description:"手机区号"`
+	Email       string `description:"邮箱"`
+}

+ 38 - 0
models/sys_session.go

@@ -0,0 +1,38 @@
+package models
+
+import (
+	"time"
+
+	"github.com/beego/beego/v2/client/orm"
+)
+
+type WxSession struct {
+	WxSessionId     int `orm:"pk"`
+	UserId          int
+	OpenId          string
+	AccessToken     string
+	ExpiredTime     time.Time
+	CreatedTime     time.Time
+	LastUpdatedTime time.Time
+}
+
+func (s *WxSession) AddWxSession() (err error) {
+	o := orm.NewOrmUsingDB("master")
+	_, err = o.Insert(s)
+	return
+}
+
+func GetWxSessionByToken(token string) (item *WxSession, err error) {
+	sql := `SELECT * FROM wx_session WHERE access_token=? AND expired_time> NOW() ORDER BY expired_time DESC LIMIT 1 `
+	o := orm.NewOrmUsingDB("master")
+	err = o.Raw(sql, token).QueryRow(&item)
+	return
+}
+
+// ExpiredWxSessionByUserId 过期掉用户token
+func ExpiredWxSessionByUserId(UserId int) (err error) {
+	sql := `UPDATE wx_session SET expired_time = NOW()  WHERE user_id=? AND expired_time > NOW()`
+	o := orm.NewOrmUsingDB("master")
+	_, err = o.Raw(sql, UserId).Exec()
+	return
+}

+ 32 - 0
models/user.go

@@ -0,0 +1,32 @@
+package models
+
+import (
+	"time"
+
+	"github.com/beego/beego/v2/client/orm"
+)
+
+type User struct {
+	UserId         int       `orm:"pk" description:"用户id"`
+	RealName       string    `description:"姓名"`
+	Phone          string    `description:"手机号"`
+	AreaCode       string    `description:"区号"`
+	Email          string    `description:"邮箱"`
+	SellerId       int       `description:"销售id(SysUserId)"`
+	Company        string    `description:"所属公司"`
+	ValidStartTime time.Time `description:"有效期开始时间"`
+	ValidEndTime   time.Time `description:"有效期结束时间"`
+	Status         int       `description:"用户类型: 0表示禁用,1表示潜在客户,2表示正式客户"`
+	CreateTime     time.Time `description:"系统中首次新增用户的时间"`
+	ModifyTime     time.Time `description:"系统中用户信息变更的时间"`
+	RegisterTime   time.Time `description:"用户首次登录小程序的时间"`
+	IsSubscribed   bool      `description:"是否关注公众号: 0表示没有关注,1表示关注"`
+	IsRegistered   bool      `description:"是否注册: 0表示没有注册,1表示注册"`
+}
+
+func GetUserById(userId int) (item *User, err error) {
+	o := orm.NewOrmUsingDB("master")
+	sql := `SELECT * FROM user WHERE user_id=? `
+	err = o.Raw(sql, userId).QueryRow(&item)
+	return
+}

+ 26 - 0
models/wx_token.go

@@ -0,0 +1,26 @@
+package models
+
+import (
+	"github.com/beego/beego/v2/client/orm"
+)
+
+type WxToken struct {
+	AccessToken string `description:"微信token"` //  微信token
+	ExpiresIn   int64  `description:"过期时间"`    // 过期时间
+	Id          int    `description:"id"`      // id
+}
+
+// Update 更新对应字段数据
+func (w *WxToken) Update(cols []string) (err error) {
+	o := orm.NewOrmUsingDB("master")
+	_, err = o.Update(w, cols...)
+	return
+}
+
+// GetById 根据id获取accessToken信息
+func GetWxTokenById() (info WxToken, err error) {
+	o := orm.NewOrmUsingDB("master")
+	sql := `SELECT * FROM wx_token WHERE id = ?`
+	err = o.Raw(sql, 0).QueryRow(&info)
+	return
+}

+ 20 - 0
models/wx_user.go

@@ -0,0 +1,20 @@
+package models
+
+type WxUser struct {
+	Id             int64
+	OpenId         string
+	UnionId        string
+	NickName       string
+	Sex            int
+	Language       string
+	City           string
+	Province       string
+	Country        string
+	HeadImgUrl     string
+	SubscribeTime  int64
+	SubscribeScene string
+	QrScene        int
+	QrSceneStr     string
+	CreateTime     int64
+	UpdateTime     int64
+}

+ 46 - 0
routers/commentsRouter.go

@@ -0,0 +1,46 @@
+package routers
+
+import (
+	beego "github.com/beego/beego/v2/server/web"
+	"github.com/beego/beego/v2/server/web/context/param"
+)
+
+func init() {
+
+    beego.GlobalControllerRouter["eta/eta_mini_api/controllers:UserController"] = append(beego.GlobalControllerRouter["eta/eta_mini_api/controllers:UserController"],
+        beego.ControllerComments{
+            Method: "Login",
+            Router: `/login`,
+            AllowHTTPMethods: []string{"post"},
+            MethodParams: param.Make(),
+            Filters: nil,
+            Params: nil})
+
+    beego.GlobalControllerRouter["eta/eta_mini_api/controllers:WechatController"] = append(beego.GlobalControllerRouter["eta/eta_mini_api/controllers:WechatController"],
+        beego.ControllerComments{
+            Method: "SendEmail",
+            Router: `/SendEmail`,
+            AllowHTTPMethods: []string{"get"},
+            MethodParams: param.Make(),
+            Filters: nil,
+            Params: nil})
+
+    beego.GlobalControllerRouter["eta/eta_mini_api/controllers:WechatController"] = append(beego.GlobalControllerRouter["eta/eta_mini_api/controllers:WechatController"],
+        beego.ControllerComments{
+            Method: "Login",
+            Router: `/login`,
+            AllowHTTPMethods: []string{"get"},
+            MethodParams: param.Make(),
+            Filters: nil,
+            Params: nil})
+
+    beego.GlobalControllerRouter["eta/eta_mini_api/controllers:WechatController"] = append(beego.GlobalControllerRouter["eta/eta_mini_api/controllers:WechatController"],
+        beego.ControllerComments{
+            Method: "UserInfo",
+            Router: `/userInfo`,
+            AllowHTTPMethods: []string{"get"},
+            MethodParams: param.Make(),
+            Filters: nil,
+            Params: nil})
+
+}

+ 32 - 0
routers/router.go

@@ -0,0 +1,32 @@
+package routers
+
+import (
+	"eta/eta_mini_api/controllers"
+
+	beego "github.com/beego/beego/v2/server/web"
+	"github.com/beego/beego/v2/server/web/filter/cors"
+)
+
+func init() {
+	beego.InsertFilter("*", beego.BeforeRouter, cors.Allow(&cors.Options{
+		AllowAllOrigins:  true,
+		AllowMethods:     []string{"GET", "POST", "PUT", "DELETE", "OPTIONS"},
+		AllowHeaders:     []string{"Origin", "Authorization", "Uuid", "Accesstoken", "Access-Control-Allow-Origin", "Access-Control-Allow-Headers", "Content-Type"},
+		ExposeHeaders:    []string{"Content-Length", "Access-Control-Allow-Origin", "Access-Control-Allow-Headers", "Content-Type"},
+		AllowCredentials: true,
+	}))
+	// beego.Router("/", &controllers.MainController{})
+	ns := beego.NewNamespace("api",
+		beego.NSNamespace("/user",
+			beego.NSInclude(
+				&controllers.UserController{},
+			),
+		),
+		beego.NSNamespace("/wechat",
+			beego.NSInclude(
+				&controllers.WechatController{},
+			),
+		),
+	)
+	beego.AddNamespace(ns)
+}

+ 5 - 0
services/email.go

@@ -0,0 +1,5 @@
+package services
+
+func SendEmail() {
+
+}

+ 115 - 0
services/sms.go

@@ -0,0 +1,115 @@
+package services
+
+import (
+	"encoding/json"
+	"eta/eta_mini_api/utils"
+	"fmt"
+	"io/ioutil"
+	"net/http"
+	"net/url"
+)
+
+func SendSmsCode(mobile, vcode string) bool {
+	flag := false
+	tplId := "262642"
+	expiresTime := "15"
+	result, err := sendSms(mobile, tplId, vcode, expiresTime)
+	if err != nil {
+		fmt.Println("发送短信失败")
+		return false
+	}
+	fmt.Println("result", string(result))
+	var netReturn map[string]interface{}
+	err = json.Unmarshal(result, &netReturn)
+	if err != nil {
+		go utils.SendEmail("短信验证码发送失败", "err:"+err.Error()+" result"+string(result), utils.EmailSendToUsers)
+		flag = false
+	}
+	if netReturn["error_code"].(float64) == 0 {
+		fmt.Printf("接口返回result字段是:\r\n%v", netReturn["result"])
+		flag = true
+	} else {
+		go utils.SendEmail("短信验证码发送失败", " result"+string(result), utils.EmailSendToUsers)
+		flag = false
+	}
+	return flag
+}
+
+func sendSms(mobile, tplId, code, expirdTime string) (rs []byte, err error) {
+	var Url *url.URL
+	apiURL := "http://v.juhe.cn/sms/send"
+	//初始化参数
+	param := url.Values{}
+	//配置请求参数,方法内部已处理urlencode问题,中文参数可以直接传参
+	param.Set("mobile", mobile)                                  //接受短信的用户手机号码
+	param.Set("tpl_id", tplId)                                   //您申请的短信模板ID,根据实际情况修改
+	param.Set("tpl_value", "#code#="+code+"&"+"#m#="+expirdTime) //您设置的模板变量,根据实际情况
+	param.Set("key", utils.JhGnAppKey)                           //应用APPKEY(应用详细页查询)
+
+	Url, err = url.Parse(apiURL)
+	if err != nil {
+		fmt.Printf("解析url错误:\r\n%v", err)
+		return nil, err
+	}
+	//如果参数中有中文参数,这个方法会进行URLEncode
+	Url.RawQuery = param.Encode()
+	resp, err := http.Get(Url.String())
+	if err != nil {
+		fmt.Println("err:", err)
+		return nil, err
+	}
+	defer resp.Body.Close()
+	return ioutil.ReadAll(resp.Body)
+}
+
+func SendSmsCodeGj(mobile, vcode, areaNum string) bool {
+	flag := false
+	result, err := sendSmsGj(mobile, vcode, areaNum)
+	if err != nil {
+		fmt.Println("发送短信失败")
+		return false
+	}
+	fmt.Println("result", string(result))
+	var netReturn map[string]interface{}
+	err = json.Unmarshal(result, &netReturn)
+	if err != nil {
+		go utils.SendEmail("短信验证码发送失败", "err:"+err.Error()+" result"+string(result), utils.EmailSendToUsers)
+		flag = false
+	}
+	if netReturn["error_code"].(float64) == 0 {
+		fmt.Printf("接口返回result字段是:\r\n%v", netReturn["result"])
+		flag = true
+	} else {
+		go utils.SendEmail("短信验证码发送失败", " result"+string(result), utils.EmailSendToUsers)
+		flag = false
+	}
+	return flag
+}
+
+func sendSmsGj(mobile, code, areaNum string) (rs []byte, err error) {
+	var Url *url.URL
+	apiURL := "http://v.juhe.cn/smsInternational/send.php"
+	//初始化参数
+	param := url.Values{}
+	//配置请求参数,方法内部已处理urlencode问题,中文参数可以直接传参
+	param.Set("mobile", mobile)           //接受短信的用户手机号码
+	param.Set("tplId", "10054")           //您申请的短信模板ID,根据实际情况修改
+	param.Set("tplValue", "#code#="+code) //您设置的模板变量,根据实际情况
+	param.Set("key", utils.JhGjAppKey)    //应用APPKEY(应用详细页查询)
+	param.Set("areaNum", areaNum)         //应用APPKEY(应用详细页查询)
+
+	Url, err = url.Parse(apiURL)
+	if err != nil {
+		fmt.Printf("解析url错误:\r\n%v", err)
+		return nil, err
+	}
+	//如果参数中有中文参数,这个方法会进行URLEncode
+	Url.RawQuery = param.Encode()
+	resp, err := http.Get(Url.String())
+	if err != nil {
+		fmt.Println("err:", err)
+		return nil, err
+	}
+	defer resp.Body.Close()
+	return ioutil.ReadAll(resp.Body)
+}

+ 19 - 0
services/user.go

@@ -0,0 +1,19 @@
+package services
+
+import "github.com/silenceper/wechat/v2/miniprogram/auth"
+
+type UserInfo struct {
+}
+
+func WxLogin(wxSession auth.ResCode2Session) (token string, userId int, isBind bool, err error) {
+	// openId := wxSession.OpenID
+	// unionId := wxSession.UnionID
+	// sessionKey := wxSession.SessionKey
+
+	return
+}
+
+// GetWxUserItemByOpenId 通过openid获取用户信息
+func GetWxUserItemByOpenId(openid string) (userInfo UserInfo, err error) {
+	return
+}

+ 96 - 0
services/wechat/wechat.go

@@ -0,0 +1,96 @@
+package wechat
+
+import (
+	"eta/eta_mini_api/models"
+	"fmt"
+	"time"
+
+	"github.com/silenceper/wechat/v2"
+	"github.com/silenceper/wechat/v2/cache"
+	"github.com/silenceper/wechat/v2/credential"
+	"github.com/silenceper/wechat/v2/officialaccount"
+	"github.com/silenceper/wechat/v2/officialaccount/config"
+	"github.com/silenceper/wechat/v2/officialaccount/js"
+	"github.com/silenceper/wechat/v2/officialaccount/user"
+)
+
+var (
+	WxAppId     string
+	WxAppSecret string
+)
+
+func init() {
+	WxAppId = `wx1c6d59a9ca4b42b3`
+	WxAppSecret = `090716fa7b7fd89172cb26065fa4e6af`
+}
+
+type WechatAccessToken struct {
+}
+
+func GetWxChat() (officialAccount *officialaccount.OfficialAccount) {
+	wc := wechat.NewWechat()
+	memory := cache.NewMemory()
+	conf := &config.Config{
+		AppID:          WxAppId,
+		AppSecret:      WxAppSecret,
+		Token:          "",
+		EncodingAESKey: "",
+		Cache:          memory,
+	}
+	officialAccount = wc.GetOfficialAccount(conf)
+	wechatAccessToken := &WechatAccessToken{}
+	officialAccount.SetAccessTokenHandle(wechatAccessToken)
+	return
+}
+
+// GetAccessToken 获取accessToken
+func (wechat WechatAccessToken) GetAccessToken() (accessToken string, err error) {
+	wxToken, err := models.GetWxTokenById()
+	if err != nil {
+		return
+	}
+	//如果300s就要过期了,那么就去刷新accessToken
+	if wxToken.ExpiresIn < time.Now().Unix()+300 {
+		tmpAccessToken, expires, tmpErr := getTokenFromServer(WxAppId, WxAppSecret)
+		if tmpErr != nil {
+			err = tmpErr
+			return
+		}
+
+		var updateCols = []string{"access_token", "expires_in"}
+		wxToken.AccessToken = tmpAccessToken
+		wxToken.ExpiresIn = expires - 600 //快过期前10分钟就刷新掉
+		wxToken.Update(updateCols)
+	}
+	accessToken = wxToken.AccessToken
+	return
+}
+
+// getTokenFromServer 服务端获取accessToken
+func getTokenFromServer(appid, wxSecret string) (accessToken string, expires int64, err error) {
+	apiUrl := "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=%s&secret=%s"
+	resAccessToken, err := credential.GetTokenFromServer(fmt.Sprintf(apiUrl, appid, wxSecret))
+	if err != nil {
+		return
+	}
+
+	expires = resAccessToken.ExpiresIn
+	accessToken = resAccessToken.AccessToken
+	return
+}
+
+// GetUserInfo 获取微信用户详情
+func GetUserInfo(openid string) (userInfo *user.Info, err error) {
+	wechatClient := GetWxChat()
+	userClient := wechatClient.GetUser()
+	userInfo, err = userClient.GetUserInfo(openid)
+	return
+}
+
+// GetJsConfig 获取公众号jsConfig
+func GetJsConfig(signUrl string) (jsConf *js.Config, err error) {
+	wechatClient := GetWxChat()
+	j := wechatClient.GetJs()
+	jsConf, err = j.GetConfig(signUrl)
+	return
+}

+ 71 - 0
services/wx_app/wx_app.go

@@ -0,0 +1,71 @@
+package wx_app
+
+import (
+	wechat "github.com/silenceper/wechat/v2"
+	"github.com/silenceper/wechat/v2/cache"
+	"github.com/silenceper/wechat/v2/miniprogram"
+	"github.com/silenceper/wechat/v2/miniprogram/auth"
+	"github.com/silenceper/wechat/v2/miniprogram/config"
+	"github.com/silenceper/wechat/v2/miniprogram/encryptor"
+)
+
+// 微信小程序配置信息
+var (
+	WxId                 string //微信原始ID
+	WxAppId              string
+	WxAppSecret          string
+	WxPlatform           int    //用户来源,需要入库,用来保存该用户来自哪个平台,默认是:1
+	EnvVersion           string // 小程序版本, release-正式版; trial-体验版; develop-开发版
+	SendWxTemplateMsgUrl string
+)
+
+func init() {
+	WxAppId = `wx1c6d59a9ca4b42b3`
+	// WxId = `gh_75abb562a946`
+	WxAppSecret = `090716fa7b7fd89172cb26065fa4e6af`
+	EnvVersion = "trial"
+	SendWxTemplateMsgUrl = "http://127.0.0.1:8086/v1/wechat/send_template_msg"
+}
+
+func GetWxApp() (miniprogram *miniprogram.MiniProgram) {
+	wc := wechat.NewWechat()
+	memory := cache.NewMemory()
+	//memory := cache.NewRedis(global.Redis)
+	cfg := &config.Config{
+		AppID:     WxAppId,
+		AppSecret: WxAppSecret,
+		Cache:     memory,
+	}
+
+	miniprogram = wc.GetMiniProgram(cfg)
+	return
+}
+
+// GetSession 获取用户详情
+func GetSession(code string) (userInfo auth.ResCode2Session, err error) {
+	wechatClient := GetWxApp()
+	authClient := wechatClient.GetAuth()
+	userInfo, err = authClient.Code2Session(code)
+	return
+}
+
+// 获取解密信息 GetDecryptInfo
+func GetDecryptInfo(sessionKey, encryptedData, iv string) (decryptData *encryptor.PlainData, err error) {
+	wechatClient := GetWxApp()
+	encryptorClient := wechatClient.GetEncryptor()
+	decryptData, err = encryptorClient.Decrypt(sessionKey, encryptedData, iv)
+	return
+}
+
+// // MsgSecCheck 检查一段文本是否含有违法违规内容。
+// func MsgSecCheck(openid string, content string) (result security.Result, err error) {
+// 	wechatClient := GetWxApp()
+// 	myMiniprogram := security.NewMyMiniprogram(wechatClient)
+// 	bodyContent := &security.BodyContent{
+// 		Version: 2,
+// 		Content: content,
+// 		Openid:  openid,
+// 		Scene:   2,
+// 	}
+// 	return myMiniprogram.MsgSecCheckWithResult(bodyContent)
+// }

+ 80 - 0
utils/common.go

@@ -0,0 +1,80 @@
+package utils
+
+import (
+	"crypto/md5"
+	"encoding/hex"
+	"fmt"
+	"math"
+	"math/rand"
+	"regexp"
+	"strconv"
+	"time"
+)
+
+// 手机号,电子邮箱正则
+const (
+	RegularMobile = "^((13[0-9])|(14[5|7])|(15([0-3]|[5-9]))|(18[0-9])|(17[0-9])|(16[0-9])|(19[0-9]))\\d{8}$" //手机号码
+	RegularEmail  = `\w+([-+.]\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*`                                             //匹配电子邮箱
+)
+
+const TelAreaCodeHome = "86" // 大陆区号
+
+var rnd = rand.New(rand.NewSource(time.Now().UnixNano()))
+
+// ValidateMobileFormatat 校验手机格式
+func ValidateMobileFormatat(mobileNum string) bool {
+	reg := regexp.MustCompile(RegularMobile)
+	return reg.MatchString(mobileNum)
+}
+
+// ValidateEmailFormatat 校验邮箱格式
+func ValidateEmailFormatat(email string) bool {
+	reg := regexp.MustCompile(RegularEmail)
+	return reg.MatchString(email)
+}
+func MD5(data string) string {
+	m := md5.Sum([]byte(data))
+	return hex.EncodeToString(m[:])
+}
+
+func CheckPwd(pwd string) bool {
+	compile := `([0-9a-z]+){6,12}|(a-z0-9]+){6,12}`
+	reg := regexp.MustCompile(compile)
+	flag := reg.MatchString(pwd)
+	return flag
+}
+
+// 计算分页起始页
+func StartIndex(page, pagesize int) int {
+	if page > 1 {
+		return (page - 1) * pagesize
+	}
+	return 0
+}
+
+// GetLikeKeywordPars 获取sql查询中的参数切片
+func GetLikeKeywordPars(pars []interface{}, keyword string, num int) (newPars []interface{}) {
+	newPars = pars
+	if newPars == nil {
+		newPars = make([]interface{}, 0)
+	}
+	for i := 1; i <= num; i++ {
+		newPars = append(newPars, `%`+keyword+`%`)
+	}
+	return
+}
+
+// GetRandDigit 获取数字随机字符
+func GetRandDigit(n int) string {
+	return fmt.Sprintf("%0"+strconv.Itoa(n)+"d", rnd.Intn(int(math.Pow10(n))))
+}
+
+func GetRandString(size int) string {
+	allLetterDigit := []string{"0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z", "a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m", "n", "o", "p", "q", "r", "s", "t", "u", "v", "w", "x", "y", "z", "!", "@", "#", "$", "%", "^", "&", "*"}
+	randomSb := ""
+	digitSize := len(allLetterDigit)
+	for i := 0; i < size; i++ {
+		randomSb += allLetterDigit[rnd.Intn(digitSize)]
+	}
+	return randomSb
+}

+ 43 - 0
utils/config.go

@@ -0,0 +1,43 @@
+package utils
+
+import (
+	"fmt"
+
+	beeLogger "github.com/beego/bee/v2/logger"
+	"github.com/beego/beego/v2/server/web"
+)
+
+// 数据库配置
+var (
+	RunMode          string
+	MYSQL_URL_MASTER string
+	MYSQL_URL_RDDP   string
+)
+
+var (
+	ApiLogPath string // 接口请求地址和接口返回值日志存放地址
+	ApiLogFile string
+	BinLogPath string // 数据库相关的日志存放地址
+	BinLogFile string
+	LogMaxDays int // 日志最大保留天数
+)
+
+var DesKey string // 接口返回加密KEY
+
+func init() {
+	tmpRunMode, err := web.AppConfig.String("run_mode")
+	if err != nil {
+		panic(any("配置文件读取run_mode错误 " + err.Error()))
+	}
+	RunMode = tmpRunMode
+	fmt.Println("RunMode:", RunMode)
+
+	config, err := web.AppConfig.GetSection(RunMode)
+	if err != nil {
+		panic(any("配置文件读取错误 " + err.Error()))
+	}
+	beeLogger.Log.Info(RunMode + " 模式")
+	MYSQL_URL_RDDP = config["mysql_url_rddp"]
+	MYSQL_URL_MASTER = config["mysql_url_master"]
+
+}

+ 21 - 0
utils/constants.go

@@ -0,0 +1,21 @@
+package utils
+
+// 验证码
+const (
+	CodeCachePrefix        = "eta:mini:login:" // 验证码缓存Key
+	VerifyCodeExpireMinute = 15                // 短信/邮箱验证码过期时间-分钟
+)
+
+const (
+	UserLoginSalt = "kOld9YUdf89T2uIH"         // 用户登录盐值
+	DesKeySalt    = "odNMloUrTAmyRd9fb0TtlrPk" // DesKey盐值
+)
+
+const (
+	APPNAME          = "弘则-日度点评"
+	EmailSendToUsers = "glji@hzinsights.com;pyan@hzinsights.com"
+)
+const (
+	JhGnAppKey = "4c8504c49dd335e99cfd7b6a3a9e2415" //聚合国内AppKey
+	JhGjAppKey = "3326ad2c1047a4cd92ace153e6044ca3"
+)

+ 37 - 0
utils/des3.go

@@ -0,0 +1,37 @@
+package utils
+
+import (
+	"bytes"
+	"crypto/cipher"
+	"crypto/des"
+	"encoding/base64"
+)
+
+// des3 + base64 encrypt
+func DesBase64Encrypt(origData []byte, desKey string) []byte {
+	result, err := TripleDesEncrypt(origData, []byte(desKey))
+	if err != nil {
+		panic(any(err))
+	}
+	return []byte(base64.StdEncoding.EncodeToString(result))
+}
+
+// 3DES加密
+func TripleDesEncrypt(origData, key []byte) ([]byte, error) {
+	block, err := des.NewTripleDESCipher(key)
+	if err != nil {
+		return nil, err
+	}
+	origData = PKCS5Padding(origData, block.BlockSize())
+	// origData = ZeroPadding(origData, block.BlockSize())
+	blockMode := cipher.NewCBCEncrypter(block, key[:8])
+	crypted := make([]byte, len(origData))
+	blockMode.CryptBlocks(crypted, origData)
+	return crypted, nil
+}
+
+func PKCS5Padding(ciphertext []byte, blockSize int) []byte {
+	padding := blockSize - len(ciphertext)%blockSize
+	padtext := bytes.Repeat([]byte{byte(padding)}, padding)
+	return append(ciphertext, padtext...)
+}

+ 58 - 0
utils/email.go

@@ -0,0 +1,58 @@
+package utils
+
+import (
+	"strings"
+
+	"gopkg.in/gomail.v2"
+)
+
+// 发送邮件
+func SendEmail(title, content string, touser string) bool {
+	var arr []string
+	sub := strings.Index(touser, ";")
+	if sub >= 0 {
+		spArr := strings.Split(touser, ";")
+		for _, v := range spArr {
+			arr = append(arr, v)
+		}
+	} else {
+		arr = append(arr, touser)
+	}
+	m := gomail.NewMessage()
+	m.SetHeader("From", "317699326@qq.com ")
+	m.SetHeader("To", arr...)
+	m.SetHeader("Subject", title+" "+GetRandString(16))
+	m.SetBody("text/html", content)
+	d := gomail.NewDialer("smtp.qq.com", 587, "317699326@qq.com", "oqdypwfcvruwcbea")
+	if err := d.DialAndSend(m); err != nil {
+		return false
+	}
+	return true
+}
+
+// 发送邮件
+func SendEmailByHz(title, content string, touser string) (result bool, err error) {
+	var arr []string
+	sub := strings.Index(touser, ";")
+	if sub >= 0 {
+		spArr := strings.Split(touser, ";")
+		arr = append(arr, spArr...)
+		// for _, v := range spArr {
+		// 	arr = append(arr, v)
+		// }
+	} else {
+		arr = append(arr, touser)
+	}
+	m := gomail.NewMessage()
+	m.SetHeader("From", "lvan@dwqh88.com")
+	m.SetHeader("To", arr...)
+	m.SetHeader("Subject", title)
+	m.SetBody("text/html", content)
+	d := gomail.NewDialer("smtp.mxhichina.com", 465, "lvan@dwqh88.com", "Dwqh20248888")
+	if err := d.DialAndSend(m); err != nil {
+		result = false
+		return result, err
+	}
+	result = true
+	return
+}

+ 44 - 0
utils/jwt.go

@@ -0,0 +1,44 @@
+package utils
+
+import (
+	"fmt"
+	"time"
+
+	"github.com/beego/beego/v2/core/logs"
+	"github.com/dgrijalva/jwt-go"
+)
+
+var (
+	KEY = []byte("5McoGDMb5y")
+)
+
+func GenToken(account string) string {
+	token := jwt.New(jwt.SigningMethodHS256)
+	token.Claims = &jwt.StandardClaims{
+		NotBefore: int64(time.Now().Unix()) - int64(1*time.Second),
+		ExpiresAt: int64(time.Now().Unix() + 60*24*60*60),
+		Issuer:    "eta_mini_api",
+		Subject:   account,
+	}
+	ss, err := token.SignedString(KEY)
+	if err != nil {
+		logs.Error(err)
+		return ""
+	}
+	return ss
+}
+
+// 校验token
+func CheckToken(account, token string) bool {
+	t, err := jwt.Parse(token, func(*jwt.Token) (interface{}, error) {
+		return KEY, nil
+	})
+	if err != nil {
+		fmt.Println(err.Error())
+		return false
+	}
+	if account != t.Claims.(jwt.MapClaims)["sub"] {
+		return false
+	}
+	return t.Valid
+}

+ 90 - 0
utils/logs.go

@@ -0,0 +1,90 @@
+package utils
+
+import (
+	"encoding/json"
+	"os"
+	"path"
+
+	"github.com/beego/beego/v2/core/logs"
+)
+
+const (
+	DefaultBinlogPath = "./etalogs/binlog"
+	DefaultApiLogPath = "./etalogs/apilog"
+)
+
+var (
+	BinLog *logs.BeeLogger
+	ApiLog *logs.BeeLogger
+)
+
+func init() {
+	initApiLog()
+	initBinLog()
+}
+
+// 初始化apilog日志
+func initApiLog() {
+	apilogPath := ApiLogPath
+	if apilogPath == "" {
+		apilogPath = DefaultApiLogPath
+	}
+	apilogFile := ApiLogFile
+	if apilogFile == "" {
+		apilogFile = "apilog.log"
+	}
+	os.MkdirAll(apilogPath, os.ModePerm)
+	logFileName := path.Join(apilogPath, apilogFile)
+	ApiLog = logs.NewLogger(1000000)
+	logConf := getDefaultLogConfig()
+	logConf.FileName = logFileName
+
+	b, _ := json.Marshal(logConf)
+	ApiLog.SetLogger(logs.AdapterFile, string(b))
+	ApiLog.EnableFuncCallDepth(true)
+}
+
+// 初始化binlog日志
+func initBinLog() {
+	binlogPath := BinLogPath
+	if binlogPath == "" {
+		binlogPath = DefaultBinlogPath
+	}
+	binlogFile := BinLogFile
+	if binlogFile == "" {
+		binlogFile = "binlog.log"
+	}
+	os.MkdirAll(binlogPath, os.ModePerm)
+	logFileName := path.Join(binlogPath, binlogFile)
+	BinLog = logs.NewLogger(1000000)
+	logConf := getDefaultLogConfig()
+	logConf.FileName = logFileName
+
+	b, _ := json.Marshal(logConf)
+	BinLog.SetLogger(logs.AdapterFile, string(b))
+	BinLog.EnableFuncCallDepth(true)
+}
+
+type logConfig struct {
+	FileName string `json:"filename" description:"保存的文件名"`
+	MaxLines int    `json:"maxlines"  description:"每个文件保存的最大行数,默认值 1000000"`
+	MaxSize  int    `json:"maxsize" description:"每个文件保存的最大尺寸,默认值是 1 << 28, //256 MB"`
+	Daily    bool   `json:"daily" description:"是否按照每天 logrotate,默认是 true"`
+	MaxDays  int    `json:"maxdays" description:"文件最多保存多少天,默认保存 7 天"`
+	Rotate   bool   `json:"rotate" description:"是否开启 logrotate,默认是 true"`
+	Level    int    `json:"level" description:"日志保存的时候的级别,默认是 Trace 级别"`
+	Color    bool   `json:"color" description:"日志是否输出颜色"`
+}
+
+func getDefaultLogConfig() logConfig {
+	return logConfig{
+		FileName: "",
+		MaxLines: 10000000,
+		MaxSize:  1 << 28,
+		Daily:    true,
+		MaxDays:  LogMaxDays,
+		Rotate:   true,
+		Level:    logs.LevelTrace,
+		//Perm:     "",
+	}
+}

+ 7 - 0
utils/redis.go

@@ -0,0 +1,7 @@
+package utils
+
+import "time"
+
+type RedisClient interface {
+	SetNX(key string, val interface{}, timeout time.Duration) bool
+}