From 128c8d273830ab5e05fdf28372e724f336bb8c40 Mon Sep 17 00:00:00 2001 From: aarongao Date: Mon, 13 Jan 2020 14:26:39 +0800 Subject: [PATCH] upload --- API/AccessLog.go | 4 +++- API/Sms.go | 106 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ API/User.go | 42 ++++++++++++++++++++++++++++++++---------- Config/config.go | 6 +++--- Config/config.json | 3 ++- DB/db.go | 17 ++++++++++++++++- Lib/Cache/redis.go | 103 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Lib/Code.go | 21 +++++++++++++++++++++ README.md | 22 ++++++++++++++++++++++ main.go | 15 +++++++++++++++ 10 files changed, 323 insertions(+), 16 deletions(-) create mode 100644 API/Sms.go create mode 100644 Lib/Cache/redis.go create mode 100644 Lib/Code.go diff --git a/API/AccessLog.go b/API/AccessLog.go index 3b2cccc..7b88675 100644 --- a/API/AccessLog.go +++ b/API/AccessLog.go @@ -33,10 +33,12 @@ func AccessLog(c *gin.Context) { DateTime, _ := strconv.ParseInt(c.PostForm("DateTime"), 0, 64) + TypeNum, _ := strconv.ParseInt("TypeNum", 0, 64) + DB.CAccessLog.Insert(DB.SAccessLog{ c.PostForm("UserId"), c.PostForm("UserName"), - c.PostForm("TypeNum"), + TypeNum, c.PostForm("TypeName"), DateTime, Location, diff --git a/API/Sms.go b/API/Sms.go new file mode 100644 index 0000000..1cdb005 --- /dev/null +++ b/API/Sms.go @@ -0,0 +1,106 @@ +package Api + +import ( + "encoding/json" + "github.com/aarongao/tools" + "github.com/aliyun/alibaba-cloud-sdk-go/services/dysmsapi" + "github.com/gin-gonic/gin" + "letu/DB" + "letu/Lib" + "time" +) + +// @Title 发送短信验证码 +// @Description 发送短信验证码 +// @Accept json +// @Produce json +// @Param mobile 18616619599 string true "手机号" +// @Param Location {"Latitude": 119, "Longitude": 39} string true "位置" +// @Success 200 {object} tools.ResponseSeccess "{"errcode":0,"result":"ok"}验证码3分钟内有效" +// @Failure 500 {object} tools.ResponseError "{"errcode":1,"errmsg":"错误原因"}" +// @Router /Sms/Send? [post] +func Send(c *gin.Context) { + c.Header("Access-Control-Allow-Origin", c.Request.Header.Get("Origin")) + c.Header("Access-Control-Allow-Credentials", "true") + + if c.PostForm("Mobile") == "" { + c.JSON(200, tools.ResponseError{ + 1, + "手机号不正确", + }) + return + } + if c.PostForm("Location") == "" { + c.JSON(200, tools.ResponseError{ + 1, + "缺少位置信息", + }) + return + } + + cacheCode := DB.Redis.Get(c.PostForm("Mobile")) + if cacheCode != nil { + c.JSON(200, tools.ResponseError{ + 1, + "code没有过期", + }) + return + } + + code := Lib.SmsCode(6) + + client, err := dysmsapi.NewClientWithAccessKey("cn-hangzhou", "LTAI4FdQeNMQXRU6u5J3EFQc", "PwvyF5rRNBWLDya41WrCpvENevYZGi") + + request := dysmsapi.CreateSendSmsRequest() + request.Scheme = "https" + + request.PhoneNumbers = c.PostForm("Mobile") + request.SignName = "乐游图" + request.TemplateCode = "SMS_182595013" + request.TemplateParam = "{\"code\":\"" + string(code) + "\"}" + + response, err := client.SendSms(request) + var reserr string + if err != nil { + println(err.Error()) + reserr = err.Error() + } else { + reserr = "" + DB.Redis.Set(c.PostForm("Mobile"), code, time.Second*60*3) + } + + var Location DB.SLocation + json.Unmarshal([]byte(c.PostForm("Location")), &Location) + + //go func(res *dysmsapi.SendSmsResponse) { + DB.CActionLog.Insert(DB.SActionLog{ + "", + "", + c.PostForm("Mobile"), + 1, + "注册验证码", + time.Now().Unix(), + Location, + string(code), + reserr, + }) + //}(response) + + if response.Code == "OK" { + + c.JSON(200, tools.ResponseSeccess{ + 0, + "ok", + }) + } else { + + c.JSON(200, tools.ResponseSeccess{ + 1, + "验证码发送失败", + }) + } +} + +func CreateAccessLog() { + +} diff --git a/API/User.go b/API/User.go index 75600f8..427133e 100644 --- a/API/User.go +++ b/API/User.go @@ -19,6 +19,7 @@ import ( // @Param confirmpassword 1 string true "确认密码" // @Param birthday 2010.10.10 string true "生日" // @Param fullname aarongao string true "全名" +// @Param code 12345678 string true "6位验证码" // @Param mobile 18616619599 string true "手机,同用户名" // @Param openid 12345 string true "微信id" // @Success 200 {object} tools.ResponseSeccess "{"errcode":0,"result":"ok"}" @@ -28,7 +29,14 @@ func CreateUser(c *gin.Context) { c.Header("Access-Control-Allow-Origin", c.Request.Header.Get("Origin")) c.Header("Access-Control-Allow-Credentials", "true") - if c.PostForm("mobile") == "" || c.PostForm("password") != c.PostForm("confirmpassword") { + if c.PostForm("mobile") == "" { + c.JSON(200, tools.ResponseError{ + 1, + "必须有手机号", + }) + return + } + if c.PostForm("password") != c.PostForm("confirmpassword") { c.JSON(200, tools.ResponseError{ 1, "密码错误", @@ -36,8 +44,18 @@ func CreateUser(c *gin.Context) { return } + // 检查验证码 + code := DB.Redis.Get(c.PostForm("mobile")) + if code == "" || code != c.PostForm("code") { + c.JSON(200, tools.ResponseError{ + 1, + "验证码错误", + }) + return + } + objectID := bson.NewObjectId() - DB.CMember.Insert(DB.SMember{ + err := DB.CMember.Insert(DB.SMember{ &objectID, c.PostForm("password"), c.PostForm("birthday"), @@ -46,11 +64,18 @@ func CreateUser(c *gin.Context) { c.PostForm("openid"), "", }) + if err == nil{ + c.JSON(200, tools.ResponseSeccess{ + 0, + "ok", + }) + }else{ + c.JSON(200, tools.ResponseError{ + 0, + "此手机号已经注册", + }) + } - c.JSON(200, tools.ResponseSeccess{ - 0, - "ok", - }) } @@ -104,8 +129,6 @@ func LoginUser(c *gin.Context) { } - - // @Title 用户信息 // @Description 获取用户信息 // @Accept json @@ -118,7 +141,7 @@ func UserInfo(c *gin.Context) { c.Header("Access-Control-Allow-Origin", c.Request.Header.Get("Origin")) c.Header("Access-Control-Allow-Credentials", "true") - if c.Query("id") == ""{ + if c.Query("id") == "" { c.JSON(200, tools.ResponseError{ 1, "空", @@ -137,7 +160,6 @@ func UserInfo(c *gin.Context) { }) } else { - c.JSON(200, tools.ResponseSeccess{ 0, User, diff --git a/Config/config.go b/Config/config.go index 3eda95e..ff60bfa 100644 --- a/Config/config.go +++ b/Config/config.go @@ -1,7 +1,7 @@ package Config type Config struct { - TagType []string - DbPath string + TagType []string + DbPath string + RedisPath string } - diff --git a/Config/config.json b/Config/config.json index 60303a8..47c9d38 100644 --- a/Config/config.json +++ b/Config/config.json @@ -1,4 +1,5 @@ { "tagType": ["menu","normal"], - "dbPath": "127.0.0.1:27017" + "dbPath": "127.0.0.1:27017", + "redisPath": "127.0.0.1:6379" } diff --git a/DB/db.go b/DB/db.go index 4e7b6bf..565a8a9 100644 --- a/DB/db.go +++ b/DB/db.go @@ -3,8 +3,11 @@ package DB import ( "gopkg.in/mgo.v2" "gopkg.in/mgo.v2/bson" + "letu/Lib/Cache" ) +var Redis *Cache.Redis + var DBSession *mgo.Session var CItem *mgo.Collection //所有游玩项目内容 var CComplaint *mgo.Collection //投诉 @@ -15,6 +18,7 @@ var CTags *mgo.Collection //标签 var CScenic *mgo.Collection //景区 var CLine *mgo.Collection //推荐线路 var CAccessLog *mgo.Collection //访问记录 +var CActionLog *mgo.Collection //行为记录 var DB *mgo.Database type SItem struct { @@ -41,12 +45,23 @@ type SLocation struct { type SAccessLog struct { UserId string `bson:"UserId" json:"UserId"` // 用户ID UserName string `bson:"UserName" json:"UserName"` //用户名称 - TypeNum string `bson:"TypeNum" json:"TypeNum"` //类型编号 + TypeNum int64 `bson:"TypeNum" json:"TypeNum"` //类型编号 TypeName string `bson:"TypeName" json:"TypeName"` //类型名称 DateTime int64 `bson:"DateTime" json:"DateTime"` //时间戳 Location SLocation `bson:"Location" json:"Location"` //位置 Remarks string `bson:"Remarks" json:"Remarks"` //备注 } +type SActionLog struct { + UserId string `bson:"UserId" json:"UserId"` // 用户ID + UserName string `bson:"UserName" json:"UserName"` //用户名称 + Mobile string `bson:"Mobile" json:"Mobile"` //手机号 + TypeNum int64 `bson:"TypeNum" json:"TypeNum"` //类型编号 + TypeName string `bson:"TypeName" json:"TypeName"` //类型名称 + DateTime int64 `bson:"DateTime" json:"DateTime"` //时间戳 + Location SLocation `bson:"Location" json:"Location"` //位置 + Content string `bson:"Content" json:"Content"` //内容 + Error interface{} `bson:"Error" json:"Error"` //错误信息 +} type SCommodity struct { Id *bson.ObjectId `bson:"_id" json:"Id" valid:"required"` Name string `bson:"Name" json:"Name"` diff --git a/Lib/Cache/redis.go b/Lib/Cache/redis.go new file mode 100644 index 0000000..1f93806 --- /dev/null +++ b/Lib/Cache/redis.go @@ -0,0 +1,103 @@ +package Cache + +import ( + "encoding/json" + "github.com/garyburd/redigo/redis" + "time" +) + +//Redis redis cache +type Redis struct { + conn *redis.Pool +} + +//RedisOpts redis 连接属性 +type RedisOpts struct { + Host string `yml:"host" json:"host"` + Password string `yml:"password" json:"password"` + Database int `yml:"database" json:"database"` + MaxIdle int `yml:"max_idle" json:"max_idle"` + MaxActive int `yml:"max_active" json:"max_active"` + IdleTimeout int32 `yml:"idle_timeout" json:"idle_timeout"` //second +} + +//NewRedis 实例化 +func NewRedis(opts *RedisOpts) *Redis { + pool := &redis.Pool{ + MaxActive: opts.MaxActive, + MaxIdle: opts.MaxIdle, + IdleTimeout: time.Second * time.Duration(opts.IdleTimeout), + Dial: func() (redis.Conn, error) { + return redis.Dial("tcp", opts.Host, + redis.DialDatabase(opts.Database), + redis.DialPassword(opts.Password), + ) + }, + TestOnBorrow: func(conn redis.Conn, t time.Time) error { + if time.Since(t) < time.Minute { + return nil + } + _, err := conn.Do("PING") + return err + }, + } + return &Redis{pool} +} + +//Get 获取一个值 +func (r *Redis) Get(key string) interface{} { + conn := r.conn.Get() + defer conn.Close() + + var data []byte + var err error + if data, err = redis.Bytes(conn.Do("GET", key)); err != nil { + return nil + } + var reply interface{} + if err = json.Unmarshal(data, &reply); err != nil { + return nil + } + + return reply +} + +//Set 设置一个值 +func (r *Redis) Set(key string, val interface{}, timeout time.Duration) (err error) { + conn := r.conn.Get() + defer conn.Close() + + var data []byte + if data, err = json.Marshal(val); err != nil { + return + } + + _, err = conn.Do("SETEX", key, int64(timeout/time.Second), data) + + return +} + +//IsExist 判断key是否存在 +func (r *Redis) IsExist(key string) bool { + conn := r.conn.Get() + defer conn.Close() + + a, _ := conn.Do("EXISTS", key) + i := a.(int64) + if i > 0 { + return true + } + return false +} + +//Delete 删除 +func (r *Redis) Delete(key string) error { + conn := r.conn.Get() + defer conn.Close() + + if _, err := conn.Do("DEL", key); err != nil { + return err + } + + return nil +} diff --git a/Lib/Code.go b/Lib/Code.go new file mode 100644 index 0000000..3fd231f --- /dev/null +++ b/Lib/Code.go @@ -0,0 +1,21 @@ +package Lib + +import ( + "fmt" + "math/rand" + "strings" + "time" +) + + +func SmsCode(width int) string { + numeric := [10]byte{0,1,2,3,4,5,6,7,8,9} + r := len(numeric) + rand.Seed(time.Now().UnixNano()) + + var sb strings.Builder + for i := 0; i < width; i++ { + fmt.Fprintf(&sb, "%d", numeric[ rand.Intn(r) ]) + } + return sb.String() +} \ No newline at end of file diff --git a/README.md b/README.md index 85eca55..f9bea89 100644 --- a/README.md +++ b/README.md @@ -20,6 +20,7 @@ 1. [查询线路信息](#lineinfo-get) 1. [用户登录](#loginuser-post) 1. [返回景区基础信息](#scenicinfo-get) +1. [发送短信验证码](#sms/send-post) 1. [标签列表](#tags-get) 1. [更新商品](#updatecommodity-post) 1. [更新设施](#updateitem-post) @@ -166,6 +167,7 @@ | confirmpassword | 1 | string | 确认密码 | Yes | | birthday | 2010.10.10 | string | 生日 | Yes | | fullname | aarongao | string | 全名 | Yes | +| code | 12345678 | string | 6位验证码 | Yes | | mobile | 18616619599 | string | 手机,同用户名 | Yes | | openid | 12345 | string | 微信id | Yes | @@ -254,6 +256,26 @@ + + +#### /Sms/Send (POST) + + +发送短信验证码 + +| Param Name | Example | Data Type | Description | Required? | +|-----|-----|-----|-----|-----| +| mobile | 18616619599 | string | 手机号 | Yes | +| Location | {"Latitude": 119, "Longitude": 39} | string | 位置 | Yes | + + +| Code | Type | Model | Message | +|-----|-----|-----|-----| +| 200 | object | [ResponseSeccess](#github.com.aarongao.tools.ResponseSeccess) | {"errcode":0,"result":"ok"}验证码3分钟内有效 | +| 500 | object | [ResponseError](#github.com.aarongao.tools.ResponseError) | {"errcode":1,"errmsg":"错误原因"} | + + + #### /Tags (GET) diff --git a/main.go b/main.go index 301f28d..7548292 100644 --- a/main.go +++ b/main.go @@ -8,6 +8,7 @@ import ( "letu/Api" "letu/Config" "letu/DB" + "letu/Lib/Cache" "letu/Lib/Ws" "os" ) @@ -30,6 +31,18 @@ func main() { // 连接数据库 DB.DBSession, err = mgo.Dial(conf.DbPath) defer DB.DBSession.Close() + + // 连接redis + DB.Redis = Cache.NewRedis(&Cache.RedisOpts{ + conf.RedisPath, + "", + 0, + 20, + 20, + 0, + }) + + //设置模式 DB.DBSession.SetMode(mgo.Monotonic, true) //获取文档集 @@ -43,6 +56,7 @@ func main() { DB.CScenic = DB.DB.C("Scenic") DB.CLine = DB.DB.C("Line") DB.CAccessLog = DB.DB.C("AccessLog") + DB.CActionLog = DB.DB.C("ActionLog") r := gin.Default() //r.Static("/.well-known", "./.well-known/") @@ -69,6 +83,7 @@ func main() { r.GET("/AllScenic", Api.AllScenic) r.POST("/AccessLog", Api.AccessLog) r.GET("/AccessLog", Api.AccessLog) + r.POST("/Sms/Send", Api.Send) //r.GET("/ws", Api.WsPage) r.Static("/Upload", "./Upload") -- libgit2 0.21.0