调整微信扫码登录相关接口,拆分门店奖励:奖励类型、奖励详情
This commit is contained in:
@ -6,5 +6,6 @@ type AdminInfoReq struct {
|
|||||||
g.Meta `path:"/admin/info" method:"get" tags:"Admin" summary:"获取管理员信息"`
|
g.Meta `path:"/admin/info" method:"get" tags:"Admin" summary:"获取管理员信息"`
|
||||||
}
|
}
|
||||||
type AdminInfoRes struct {
|
type AdminInfoRes struct {
|
||||||
g.Meta `mime:"application/json"`
|
g.Meta `mime:"application/json"`
|
||||||
|
Username string `json:"username" dc:"用户名"`
|
||||||
}
|
}
|
||||||
|
|||||||
1
api/user/v1/user.go
Normal file
1
api/user/v1/user.go
Normal file
@ -0,0 +1 @@
|
|||||||
|
package user
|
||||||
@ -3,21 +3,21 @@ package v1
|
|||||||
import "github.com/gogf/gf/v2/frame/g"
|
import "github.com/gogf/gf/v2/frame/g"
|
||||||
|
|
||||||
type WeChatLoginReq struct {
|
type WeChatLoginReq struct {
|
||||||
g.Meta `path:"/wechat/login" method:"post" tags:"WeChat" summary:"获取微信二维码登录"`
|
g.Meta `path:"/wechat/login" method:"post" tags:"WeChat" summary:"获取微信二维码登录"`
|
||||||
UUID string `json:"uuid" v:"required" dc:"UUID"`
|
SceneId string `json:"sceneId" v:"required" dc:"场景ID,规则:[门店id]_[6位随机字符串]"`
|
||||||
}
|
}
|
||||||
type WeChatLoginRes struct {
|
type WeChatLoginRes struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
type WeChatEventReq struct {
|
type WeChatEventReq struct {
|
||||||
g.Meta `path:"/wechat" method:"post" tags:"WeChat" summary:"微信订阅事件"`
|
g.Meta `path:"/wechat" method:"post" tags:"WeChat" summary:"微信订阅事件"`
|
||||||
ToUserName string `xml:"ToUserName" dc:"开发者微信号" json:"ToUserName,omitempty"`
|
ToUserName string `xml:"ToUserName" dc:"开发者微信号" json:"ToUserName"`
|
||||||
FromUserName string `xml:"FromUserName" dc:"发送方账号(OpenID)" json:"FromUserName,omitempty"`
|
FromUserName string `xml:"FromUserName" dc:"发送方账号(OpenID)" json:"FromUserName"`
|
||||||
CreateTime int64 `xml:"CreateTime" dc:"消息创建时间" json:"CreateTime,omitempty"`
|
CreateTime int64 `xml:"CreateTime" dc:"消息创建时间" json:"CreateTime"`
|
||||||
MsgType string `xml:"MsgType" dc:"消息类型" json:"MsgType,omitempty"`
|
MsgType string `xml:"MsgType" dc:"消息类型" json:"MsgType,omitempty"`
|
||||||
Event string `xml:"Event" dc:"事件类型 subscribe | SCAN" json:"Event,omitempty"`
|
Event string `xml:"Event" dc:"事件类型 subscribe | SCAN" json:"Event"`
|
||||||
EventKey string `xml:"EventKey" dc:"事件KEY值" json:"EventKey,omitempty"`
|
EventKey string `xml:"EventKey" dc:"事件KEY值" json:"EventKey"`
|
||||||
Ticket string `xml:"Ticket" dc:"二维码ticket" json:"Ticket,omitempty"`
|
Ticket string `xml:"Ticket" dc:"二维码ticket" json:"Ticket"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type WeChatEventRes struct {
|
type WeChatEventRes struct {
|
||||||
@ -35,8 +35,10 @@ type WeChatVertifyRes struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type WeChatPollingReq struct {
|
type WeChatPollingReq struct {
|
||||||
g.Meta `path:"/wechat/polling" method:"post" tags:"WeChat" summary:"微信长轮询"`
|
g.Meta `path:"/wechat/polling" method:"post" tags:"WeChat" summary:"微信长轮询"`
|
||||||
UUID string `json:"uuid" v:"required" dc:"UUID"`
|
SceneId string `json:"sceneId" v:"required" dc:"场景ID"`
|
||||||
}
|
}
|
||||||
type WeChatPollingRes struct {
|
type WeChatPollingRes struct {
|
||||||
|
Status string `json:"status" dc:"状态"`
|
||||||
|
Token string `json:"token" dc:"token"`
|
||||||
}
|
}
|
||||||
|
|||||||
8
go.mod
8
go.mod
@ -5,31 +5,37 @@ go 1.24.2
|
|||||||
require (
|
require (
|
||||||
github.com/casbin/casbin/v2 v2.105.0
|
github.com/casbin/casbin/v2 v2.105.0
|
||||||
github.com/go-resty/resty/v2 v2.16.5
|
github.com/go-resty/resty/v2 v2.16.5
|
||||||
|
github.com/gogf/gf/contrib/drivers/mysql/v2 v2.9.0
|
||||||
|
github.com/gogf/gf/contrib/nosql/redis/v2 v2.9.0
|
||||||
github.com/gogf/gf/v2 v2.9.0
|
github.com/gogf/gf/v2 v2.9.0
|
||||||
github.com/golang-jwt/jwt/v5 v5.2.2
|
github.com/golang-jwt/jwt/v5 v5.2.2
|
||||||
github.com/google/uuid v1.6.0
|
github.com/google/uuid v1.6.0
|
||||||
github.com/hailaz/gf-casbin-adapter/v2 v2.8.1
|
github.com/hailaz/gf-casbin-adapter/v2 v2.8.1
|
||||||
golang.org/x/crypto v0.38.0
|
golang.org/x/crypto v0.38.0
|
||||||
|
golang.org/x/sync v0.14.0
|
||||||
)
|
)
|
||||||
|
|
||||||
require (
|
require (
|
||||||
github.com/BurntSushi/toml v1.4.0 // indirect
|
github.com/BurntSushi/toml v1.4.0 // indirect
|
||||||
github.com/bmatcuk/doublestar/v4 v4.6.1 // indirect
|
github.com/bmatcuk/doublestar/v4 v4.6.1 // indirect
|
||||||
github.com/casbin/govaluate v1.3.0 // indirect
|
github.com/casbin/govaluate v1.3.0 // indirect
|
||||||
|
github.com/cespare/xxhash/v2 v2.3.0 // indirect
|
||||||
github.com/clbanning/mxj/v2 v2.7.0 // indirect
|
github.com/clbanning/mxj/v2 v2.7.0 // indirect
|
||||||
|
github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f // indirect
|
||||||
github.com/emirpasic/gods v1.18.1 // indirect
|
github.com/emirpasic/gods v1.18.1 // indirect
|
||||||
github.com/fatih/color v1.18.0 // indirect
|
github.com/fatih/color v1.18.0 // indirect
|
||||||
github.com/fsnotify/fsnotify v1.7.0 // indirect
|
github.com/fsnotify/fsnotify v1.7.0 // indirect
|
||||||
github.com/go-logr/logr v1.4.2 // indirect
|
github.com/go-logr/logr v1.4.2 // indirect
|
||||||
github.com/go-logr/stdr v1.2.2 // indirect
|
github.com/go-logr/stdr v1.2.2 // indirect
|
||||||
|
github.com/go-sql-driver/mysql v1.7.1 // indirect
|
||||||
github.com/gorilla/websocket v1.5.3 // indirect
|
github.com/gorilla/websocket v1.5.3 // indirect
|
||||||
github.com/grokify/html-strip-tags-go v0.1.0 // indirect
|
github.com/grokify/html-strip-tags-go v0.1.0 // indirect
|
||||||
github.com/kr/text v0.2.0 // indirect
|
|
||||||
github.com/magiconair/properties v1.8.9 // indirect
|
github.com/magiconair/properties v1.8.9 // indirect
|
||||||
github.com/mattn/go-colorable v0.1.13 // indirect
|
github.com/mattn/go-colorable v0.1.13 // indirect
|
||||||
github.com/mattn/go-isatty v0.0.20 // indirect
|
github.com/mattn/go-isatty v0.0.20 // indirect
|
||||||
github.com/mattn/go-runewidth v0.0.16 // indirect
|
github.com/mattn/go-runewidth v0.0.16 // indirect
|
||||||
github.com/olekukonko/tablewriter v0.0.5 // indirect
|
github.com/olekukonko/tablewriter v0.0.5 // indirect
|
||||||
|
github.com/redis/go-redis/v9 v9.7.0 // indirect
|
||||||
github.com/rivo/uniseg v0.4.7 // indirect
|
github.com/rivo/uniseg v0.4.7 // indirect
|
||||||
go.opentelemetry.io/otel v1.32.0 // indirect
|
go.opentelemetry.io/otel v1.32.0 // indirect
|
||||||
go.opentelemetry.io/otel/metric v1.32.0 // indirect
|
go.opentelemetry.io/otel/metric v1.32.0 // indirect
|
||||||
|
|||||||
19
go.sum
19
go.sum
@ -2,15 +2,22 @@ github.com/BurntSushi/toml v1.4.0 h1:kuoIxZQy2WRRk1pttg9asf+WVv6tWQuBNVmK8+nqPr0
|
|||||||
github.com/BurntSushi/toml v1.4.0/go.mod h1:ukJfTF/6rtPPRCnwkur4qwRxa8vTRFBF0uk2lLoLwho=
|
github.com/BurntSushi/toml v1.4.0/go.mod h1:ukJfTF/6rtPPRCnwkur4qwRxa8vTRFBF0uk2lLoLwho=
|
||||||
github.com/bmatcuk/doublestar/v4 v4.6.1 h1:FH9SifrbvJhnlQpztAx++wlkk70QBf0iBWDwNy7PA4I=
|
github.com/bmatcuk/doublestar/v4 v4.6.1 h1:FH9SifrbvJhnlQpztAx++wlkk70QBf0iBWDwNy7PA4I=
|
||||||
github.com/bmatcuk/doublestar/v4 v4.6.1/go.mod h1:xBQ8jztBU6kakFMg+8WGxn0c6z1fTSPVIjEY1Wr7jzc=
|
github.com/bmatcuk/doublestar/v4 v4.6.1/go.mod h1:xBQ8jztBU6kakFMg+8WGxn0c6z1fTSPVIjEY1Wr7jzc=
|
||||||
|
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/casbin/casbin/v2 v2.105.0 h1:dLj5P6pLApBRat9SADGiLxLZjiDPvA1bsPkyV4PGx6I=
|
github.com/casbin/casbin/v2 v2.105.0 h1:dLj5P6pLApBRat9SADGiLxLZjiDPvA1bsPkyV4PGx6I=
|
||||||
github.com/casbin/casbin/v2 v2.105.0/go.mod h1:Ee33aqGrmES+GNL17L0h9X28wXuo829wnNUnS0edAco=
|
github.com/casbin/casbin/v2 v2.105.0/go.mod h1:Ee33aqGrmES+GNL17L0h9X28wXuo829wnNUnS0edAco=
|
||||||
github.com/casbin/govaluate v1.3.0 h1:VA0eSY0M2lA86dYd5kPPuNZMUD9QkWnOCnavGrw9myc=
|
github.com/casbin/govaluate v1.3.0 h1:VA0eSY0M2lA86dYd5kPPuNZMUD9QkWnOCnavGrw9myc=
|
||||||
github.com/casbin/govaluate v1.3.0/go.mod h1:G/UnbIjZk/0uMNaLwZZmFQrR72tYRZWQkO70si/iR7A=
|
github.com/casbin/govaluate v1.3.0/go.mod h1:G/UnbIjZk/0uMNaLwZZmFQrR72tYRZWQkO70si/iR7A=
|
||||||
|
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/clbanning/mxj/v2 v2.7.0 h1:WA/La7UGCanFe5NpHF0Q3DNtnCsVoxbPKuyBNHWRyME=
|
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/clbanning/mxj/v2 v2.7.0/go.mod h1:hNiWqW14h+kc+MdF9C6/YoRfjEJoR3ou6tn/Qo+ve2s=
|
||||||
github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
|
|
||||||
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
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/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||||
|
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/emirpasic/gods v1.18.1 h1:FXtiHYKDGKCW2KzwZKx0iC0PQmdlorYgdFG9jPXJ1Bc=
|
github.com/emirpasic/gods v1.18.1 h1:FXtiHYKDGKCW2KzwZKx0iC0PQmdlorYgdFG9jPXJ1Bc=
|
||||||
github.com/emirpasic/gods v1.18.1/go.mod h1:8tpGGwCnJ5H4r6BWwaV6OrWmMoPhUl5jm/FMNAnJvWQ=
|
github.com/emirpasic/gods v1.18.1/go.mod h1:8tpGGwCnJ5H4r6BWwaV6OrWmMoPhUl5jm/FMNAnJvWQ=
|
||||||
github.com/fatih/color v1.18.0 h1:S8gINlzdQ840/4pfAwic/ZE0djQEH3wM94VfqLTZcOM=
|
github.com/fatih/color v1.18.0 h1:S8gINlzdQ840/4pfAwic/ZE0djQEH3wM94VfqLTZcOM=
|
||||||
@ -24,6 +31,12 @@ 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-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE=
|
||||||
github.com/go-resty/resty/v2 v2.16.5 h1:hBKqmWrr7uRc3euHVqmh1HTHcKn99Smr7o5spptdhTM=
|
github.com/go-resty/resty/v2 v2.16.5 h1:hBKqmWrr7uRc3euHVqmh1HTHcKn99Smr7o5spptdhTM=
|
||||||
github.com/go-resty/resty/v2 v2.16.5/go.mod h1:hkJtXbA2iKHzJheXYvQ8snQES5ZLGKMwQ07xAwp/fiA=
|
github.com/go-resty/resty/v2 v2.16.5/go.mod h1:hkJtXbA2iKHzJheXYvQ8snQES5ZLGKMwQ07xAwp/fiA=
|
||||||
|
github.com/go-sql-driver/mysql v1.7.1 h1:lUIinVbN1DY0xBg0eMOzmmtGoHwWBbvnWubQUrtU8EI=
|
||||||
|
github.com/go-sql-driver/mysql v1.7.1/go.mod h1:OXbVy3sEdcQ2Doequ6Z5BW6fXNQTmx+9S1MCJN5yJMI=
|
||||||
|
github.com/gogf/gf/contrib/drivers/mysql/v2 v2.9.0 h1:1f7EeD0lfPHoXfaJDSL7cxRcSRelbsAKgF3MGXY+Uyo=
|
||||||
|
github.com/gogf/gf/contrib/drivers/mysql/v2 v2.9.0/go.mod h1:tToO1PjGkLIR+9DbJ0wrKicYma0H/EUHXOpwel6Dw+0=
|
||||||
|
github.com/gogf/gf/contrib/nosql/redis/v2 v2.9.0 h1:EEZqu1PNRSmm+7Cqm9A/8+ObgfbMzhE1ps9Z3LD7HgM=
|
||||||
|
github.com/gogf/gf/contrib/nosql/redis/v2 v2.9.0/go.mod h1:LHrxY+2IzNTHVTPG/s5yaz1VmXbj+CQ7Hr5SeVkHiTw=
|
||||||
github.com/gogf/gf/v2 v2.9.0 h1:semN5Q5qGjDQEv4620VzxcJzJlSD07gmyJ9Sy9zfbHk=
|
github.com/gogf/gf/v2 v2.9.0 h1:semN5Q5qGjDQEv4620VzxcJzJlSD07gmyJ9Sy9zfbHk=
|
||||||
github.com/gogf/gf/v2 v2.9.0/go.mod h1:sWGQw+pLILtuHmbOxoe0D+0DdaXxbleT57axOLH2vKI=
|
github.com/gogf/gf/v2 v2.9.0/go.mod h1:sWGQw+pLILtuHmbOxoe0D+0DdaXxbleT57axOLH2vKI=
|
||||||
github.com/golang-jwt/jwt/v5 v5.2.2 h1:Rl4B7itRWVtYIHFrSNd7vhTiz9UpLdi6gZhZ3wEeDy8=
|
github.com/golang-jwt/jwt/v5 v5.2.2 h1:Rl4B7itRWVtYIHFrSNd7vhTiz9UpLdi6gZhZ3wEeDy8=
|
||||||
@ -58,6 +71,8 @@ github.com/olekukonko/tablewriter v0.0.5 h1:P2Ga83D34wi1o9J6Wh1mRuqd4mF/x/lgBS7N
|
|||||||
github.com/olekukonko/tablewriter v0.0.5/go.mod h1:hPp6KlRPjbx+hW8ykQs1w3UBbZlj6HuIJcUGPhkA7kY=
|
github.com/olekukonko/tablewriter v0.0.5/go.mod h1:hPp6KlRPjbx+hW8ykQs1w3UBbZlj6HuIJcUGPhkA7kY=
|
||||||
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
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/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||||
|
github.com/redis/go-redis/v9 v9.7.0 h1:HhLSs+B6O021gwzl+locl0zEDnyNkxMtf/Z3NNBMa9E=
|
||||||
|
github.com/redis/go-redis/v9 v9.7.0/go.mod h1:f6zhXITC7JUJIlPEiBOTXxJgPLdZcA93GewI7inzyWw=
|
||||||
github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc=
|
github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc=
|
||||||
github.com/rivo/uniseg v0.4.7 h1:WUdvkW8uEhrYfLC4ZzdpI2ztxP1I582+49Oc5Mq64VQ=
|
github.com/rivo/uniseg v0.4.7 h1:WUdvkW8uEhrYfLC4ZzdpI2ztxP1I582+49Oc5Mq64VQ=
|
||||||
github.com/rivo/uniseg v0.4.7/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88=
|
github.com/rivo/uniseg v0.4.7/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88=
|
||||||
@ -80,6 +95,8 @@ golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn
|
|||||||
golang.org/x/net v0.33.0 h1:74SYHlV8BIgHIFC/LrYkOGIwL19eTYXQ5wc6TBuO36I=
|
golang.org/x/net v0.33.0 h1:74SYHlV8BIgHIFC/LrYkOGIwL19eTYXQ5wc6TBuO36I=
|
||||||
golang.org/x/net v0.33.0/go.mod h1:HXLR5J+9DxmrqMwG9qjGCxZ+zKXxBru04zlTvWlWuN4=
|
golang.org/x/net v0.33.0/go.mod h1:HXLR5J+9DxmrqMwG9qjGCxZ+zKXxBru04zlTvWlWuN4=
|
||||||
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
|
golang.org/x/sync v0.14.0 h1:woo0S4Yywslg6hp4eUFjTVOyKt0RookbpAHG4c1HmhQ=
|
||||||
|
golang.org/x/sync v0.14.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-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||||
golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
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.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
|
|||||||
@ -5,7 +5,9 @@ import (
|
|||||||
"github.com/gogf/gf/v2/frame/g"
|
"github.com/gogf/gf/v2/frame/g"
|
||||||
"github.com/gogf/gf/v2/net/ghttp"
|
"github.com/gogf/gf/v2/net/ghttp"
|
||||||
"github.com/gogf/gf/v2/os/gcmd"
|
"github.com/gogf/gf/v2/os/gcmd"
|
||||||
|
"server/internal/controller/admin"
|
||||||
"server/internal/controller/auth"
|
"server/internal/controller/auth"
|
||||||
|
"server/internal/controller/wx"
|
||||||
"server/internal/middleware"
|
"server/internal/middleware"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -21,7 +23,15 @@ var (
|
|||||||
group.Middleware(ghttp.MiddlewareCORS)
|
group.Middleware(ghttp.MiddlewareCORS)
|
||||||
group.Bind(
|
group.Bind(
|
||||||
auth.NewV1(),
|
auth.NewV1(),
|
||||||
|
wx.NewV1(),
|
||||||
)
|
)
|
||||||
|
group.Group("/x", func(group *ghttp.RouterGroup) {
|
||||||
|
group.Middleware(middleware.Auth)
|
||||||
|
group.Middleware(middleware.Casbin)
|
||||||
|
group.Bind(
|
||||||
|
admin.NewV1(),
|
||||||
|
)
|
||||||
|
})
|
||||||
})
|
})
|
||||||
s.Run()
|
s.Run()
|
||||||
return nil
|
return nil
|
||||||
|
|||||||
@ -1 +1,13 @@
|
|||||||
package consts
|
package consts
|
||||||
|
|
||||||
|
const (
|
||||||
|
GuestPermission = "guest"
|
||||||
|
UserPermission = "user"
|
||||||
|
AdminPermission = "admin"
|
||||||
|
MerchantPermission = "merchant"
|
||||||
|
StorePermission = "store"
|
||||||
|
)
|
||||||
|
const (
|
||||||
|
QRCodeExpireTime = 60
|
||||||
|
QRCodeLimitTime = 10
|
||||||
|
)
|
||||||
|
|||||||
@ -2,13 +2,19 @@ package admin
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
"server/internal/model"
|
||||||
|
"server/internal/service"
|
||||||
|
|
||||||
"github.com/gogf/gf/v2/errors/gcode"
|
"github.com/gogf/gf/v2/frame/g"
|
||||||
"github.com/gogf/gf/v2/errors/gerror"
|
|
||||||
|
|
||||||
"server/api/admin/v1"
|
v1 "server/api/admin/v1"
|
||||||
)
|
)
|
||||||
|
|
||||||
func (c *ControllerV1) AdminInfo(ctx context.Context, req *v1.AdminInfoReq) (res *v1.AdminInfoRes, err error) {
|
func (c *ControllerV1) AdminInfo(ctx context.Context, req *v1.AdminInfoReq) (res *v1.AdminInfoRes, err error) {
|
||||||
return nil, gerror.NewCode(gcode.CodeNotImplemented)
|
userId := g.RequestFromCtx(ctx).GetCtxVar("userId").Int()
|
||||||
|
out, err := service.Admin().Info(ctx, &model.AdminInfoIn{Id: userId})
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return &v1.AdminInfoRes{Username: out.Username}, nil
|
||||||
}
|
}
|
||||||
|
|||||||
@ -2,13 +2,19 @@ package auth
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
v1 "server/api/auth/v1"
|
||||||
"github.com/gogf/gf/v2/errors/gcode"
|
"server/internal/model"
|
||||||
"github.com/gogf/gf/v2/errors/gerror"
|
"server/internal/service"
|
||||||
|
|
||||||
"server/api/auth/v1"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
func (c *ControllerV1) AdminLogin(ctx context.Context, req *v1.AdminLoginReq) (res *v1.AdminLoginRes, err error) {
|
func (c *ControllerV1) AdminLogin(ctx context.Context, req *v1.AdminLoginReq) (res *v1.AdminLoginRes, err error) {
|
||||||
return nil, gerror.NewCode(gcode.CodeNotImplemented)
|
|
||||||
|
out, err := service.Admin().Login(ctx, &model.AdminLoginIn{
|
||||||
|
Username: req.Username,
|
||||||
|
Password: req.Password,
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return &v1.AdminLoginRes{Token: out.Token}, nil
|
||||||
}
|
}
|
||||||
|
|||||||
@ -2,32 +2,90 @@ package wx
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"github.com/gogf/gf/v2/os/glog"
|
"fmt"
|
||||||
|
v1 "server/api/wx/v1"
|
||||||
|
"server/internal/model"
|
||||||
|
"server/internal/service"
|
||||||
|
"strings"
|
||||||
|
|
||||||
"server/api/auth/v1"
|
"github.com/gogf/gf/v2/encoding/gjson"
|
||||||
|
"github.com/gogf/gf/v2/frame/g"
|
||||||
|
"github.com/gogf/gf/v2/os/glog"
|
||||||
)
|
)
|
||||||
|
|
||||||
func (c *ControllerV1) WeChatEvent(ctx context.Context, req *v1.WeChatEventReq) (res *v1.WeChatEventRes, err error) {
|
func (c *ControllerV1) WeChatEvent(ctx context.Context, req *v1.WeChatEventReq) (res *v1.WeChatEventRes, err error) {
|
||||||
// 收到微信订阅事件
|
glog.Infof(ctx, "【微信事件】收到事件 | event=%s, msgType=%s, eventKey=%s, fromUserName=%s, toUserName=%s, createTime=%d",
|
||||||
glog.Infof(ctx,
|
req.Event, req.MsgType, req.EventKey, req.FromUserName, req.ToUserName, req.CreateTime,
|
||||||
"微信消息推送:时间=%d, 消息类型=%s, 事件=%s, 事件Key=%s",
|
|
||||||
req.CreateTime,
|
|
||||||
req.MsgType,
|
|
||||||
req.Event,
|
|
||||||
req.EventKey,
|
|
||||||
)
|
)
|
||||||
// 根据事件类型进行不同的处理:
|
|
||||||
switch req.MsgType {
|
switch req.MsgType {
|
||||||
case "event":
|
case "event":
|
||||||
switch req.Event {
|
switch req.Event {
|
||||||
case "subscribe":
|
case "subscribe":
|
||||||
// 未关注,扫描关注后, 注册账号,关联微信的 open_id
|
key := strings.TrimPrefix(req.EventKey, "qrscene_")
|
||||||
|
out, err := service.User().Login(ctx, &model.UserLoginIn{OpenId: req.FromUserName})
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
if err = updateLoginCache(ctx, key, out.Token); err != nil {
|
||||||
|
glog.Errorf(ctx, "【微信事件】更新登录缓存失败 | error=%s", err.Error())
|
||||||
|
}
|
||||||
|
return nil, nil
|
||||||
case "SCAN":
|
case "SCAN":
|
||||||
// 已关注,扫描后,根据 open_id 查找用户生成 token
|
out, err := service.User().Login(ctx, &model.UserLoginIn{OpenId: req.FromUserName})
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
if err = updateLoginCache(ctx, req.EventKey, out.Token); err != nil {
|
||||||
|
glog.Errorf(ctx, "【微信事件】更新登录缓存失败 | error=%s", err.Error())
|
||||||
|
}
|
||||||
|
return nil, nil
|
||||||
default:
|
default:
|
||||||
// 处理其他事件
|
glog.Infof(ctx, "【微信事件】不支持的事件 | event=%s", req.Event)
|
||||||
|
return nil, nil
|
||||||
}
|
}
|
||||||
|
default:
|
||||||
|
glog.Infof(ctx, "【微信事件】不支持的消息类型 | msgType=%s", req.MsgType)
|
||||||
|
return nil, nil
|
||||||
}
|
}
|
||||||
return nil, nil
|
}
|
||||||
|
|
||||||
|
func updateLoginCache(ctx context.Context, key string, token string) error {
|
||||||
|
loginCacheKey := fmt.Sprintf("wx:login:cache:%s", key)
|
||||||
|
glog.Infof(ctx, "【微信事件】准备更新登录缓存 | redisKey=%s, token=%s", loginCacheKey, token)
|
||||||
|
|
||||||
|
// 获取原缓存
|
||||||
|
data, err := g.Redis().Get(ctx, loginCacheKey)
|
||||||
|
if err != nil {
|
||||||
|
glog.Errorf(ctx, "【微信事件】获取缓存失败 | key=%s, error=%v", loginCacheKey, err)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if data.IsEmpty() {
|
||||||
|
glog.Warningf(ctx, "【微信事件】缓存不存在 | key=%s", loginCacheKey)
|
||||||
|
return nil // 不是错误,只是二维码超时或错误
|
||||||
|
}
|
||||||
|
|
||||||
|
// 反序列化
|
||||||
|
var loginCache model.LoginCache
|
||||||
|
if err := gjson.Unmarshal(data.Bytes(), &loginCache); err != nil {
|
||||||
|
glog.Errorf(ctx, "【微信事件】反序列化缓存失败 | key=%s, error=%v", loginCacheKey, err)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// 更新状态与Token
|
||||||
|
loginCache.Status = 1
|
||||||
|
loginCache.Token = token
|
||||||
|
|
||||||
|
// 序列化并写回 Redis
|
||||||
|
newData, err := gjson.Marshal(loginCache)
|
||||||
|
if err != nil {
|
||||||
|
glog.Errorf(ctx, "【微信事件】序列化缓存失败 | key=%s, error=%v", loginCacheKey, err)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if err := g.Redis().SetEX(ctx, loginCacheKey, newData, 60); err != nil {
|
||||||
|
glog.Errorf(ctx, "【微信事件】写入缓存失败 | key=%s, error=%v", loginCacheKey, err)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
glog.Infof(ctx, "【微信事件】缓存更新成功 | key=%s, token=%s", loginCacheKey, token)
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
|||||||
@ -2,14 +2,54 @@ package wx
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
"encoding/json"
|
||||||
|
"fmt"
|
||||||
|
v1 "server/api/wx/v1"
|
||||||
|
"server/internal/model"
|
||||||
|
"server/utility/ecode"
|
||||||
|
|
||||||
"github.com/gogf/gf/v2/errors/gcode"
|
"github.com/gogf/gf/v2/frame/g"
|
||||||
"github.com/gogf/gf/v2/errors/gerror"
|
"github.com/gogf/gf/v2/os/glog"
|
||||||
|
|
||||||
"server/api/auth/v1"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
func (c *ControllerV1) WeChatPolling(ctx context.Context, req *v1.WeChatPollingReq) (res *v1.WeChatPollingRes, err error) {
|
func (c *ControllerV1) WeChatPolling(ctx context.Context, req *v1.WeChatPollingReq) (res *v1.WeChatPollingRes, err error) {
|
||||||
// 收到请求根据 uuid 查询缓存中的数据,看看是否生成了 token
|
loginCacheKey := fmt.Sprintf("wx:login:cache:%s", req.SceneId)
|
||||||
return nil, gerror.NewCode(gcode.CodeNotImplemented)
|
glog.Infof(ctx, "开始处理微信长轮询请求,SceneID: %s", req.SceneId)
|
||||||
|
|
||||||
|
var loginCache model.LoginCache
|
||||||
|
|
||||||
|
data, err := g.Redis().Get(ctx, loginCacheKey)
|
||||||
|
if err != nil {
|
||||||
|
glog.Errorf(ctx, "从 Redis 获取登录缓存失败,SceneID: %s,错误: %v", req.SceneId, err)
|
||||||
|
return nil, ecode.Fail.Sub("获取登录状态失败")
|
||||||
|
}
|
||||||
|
|
||||||
|
if data.IsEmpty() {
|
||||||
|
glog.Warningf(ctx, "用户尚未扫码登录,SceneID: %s", req.SceneId)
|
||||||
|
return nil, ecode.InvalidOperation.Sub("请先调用获取二维码登录")
|
||||||
|
}
|
||||||
|
|
||||||
|
if err = json.Unmarshal(data.Bytes(), &loginCache); err != nil {
|
||||||
|
glog.Errorf(ctx, "解析登录状态失败,SceneID: %s,错误: %v", req.SceneId, err)
|
||||||
|
return nil, ecode.Fail.Sub("解析登录状态失败")
|
||||||
|
}
|
||||||
|
|
||||||
|
switch loginCache.Status {
|
||||||
|
case 0:
|
||||||
|
glog.Infof(ctx, "用户尚未扫码登录,SceneID: %s", req.SceneId)
|
||||||
|
return &v1.WeChatPollingRes{
|
||||||
|
Status: "waiting",
|
||||||
|
Token: "",
|
||||||
|
}, nil
|
||||||
|
case 1:
|
||||||
|
// 直接返回缓存的token
|
||||||
|
glog.Infof(ctx, "用户扫码登录成功,SceneID: %s,返回缓存Token", req.SceneId)
|
||||||
|
return &v1.WeChatPollingRes{
|
||||||
|
Status: "success",
|
||||||
|
Token: loginCache.Token,
|
||||||
|
}, nil
|
||||||
|
default:
|
||||||
|
glog.Warningf(ctx, "未知登录状态 %d,SceneID: %s", loginCache.Status, req.SceneId)
|
||||||
|
return nil, ecode.InvalidOperation.Sub("未知登录状态")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -2,31 +2,34 @@ package wx
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"github.com/gogf/gf/v2/crypto/gsha1"
|
"crypto/sha1"
|
||||||
|
"fmt"
|
||||||
"github.com/gogf/gf/v2/frame/g"
|
"github.com/gogf/gf/v2/frame/g"
|
||||||
"server/utility/ecode"
|
"server/utility/wechat"
|
||||||
"sort"
|
"sort"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"server/api/auth/v1"
|
"server/api/wx/v1"
|
||||||
)
|
)
|
||||||
|
|
||||||
func (c *ControllerV1) WeChatVertify(ctx context.Context, req *v1.WeChatVertifyReq) (res *v1.WeChatVertifyRes, err error) {
|
func (c *ControllerV1) WeChatVertify(ctx context.Context, req *v1.WeChatVertifyReq) (res *v1.WeChatVertifyRes, err error) {
|
||||||
|
|
||||||
weChatToken := g.Config().MustGet(ctx, "wechat.token").String()
|
// 1. 排序
|
||||||
// 1. 将 token、timestamp、nonce 组成 slice
|
params := []string{wechat.GetWeChatClient().GetToken(), req.Timestamp, req.Nonce}
|
||||||
params := []string{weChatToken, req.Timestamp, req.Nonce}
|
|
||||||
// 2. 字典序排序
|
|
||||||
sort.Strings(params)
|
sort.Strings(params)
|
||||||
// 3. 拼接字符串
|
|
||||||
joined := strings.Join(params, "")
|
|
||||||
// 4. SHA1 加密
|
|
||||||
encrypt := gsha1.Encrypt(joined)
|
|
||||||
|
|
||||||
// 5. 与 signature 对比
|
// 2. 拼接成字符串
|
||||||
if encrypt != req.Signature {
|
str := strings.Join(params, "")
|
||||||
return nil, ecode.InvalidOperation.Sub("微信服务器验证失败")
|
|
||||||
|
// 3. SHA1 加密
|
||||||
|
h := sha1.New()
|
||||||
|
h.Write([]byte(str))
|
||||||
|
sha1Str := fmt.Sprintf("%x", h.Sum(nil))
|
||||||
|
|
||||||
|
// 4. 比较签名
|
||||||
|
if sha1Str != req.Signature {
|
||||||
|
return nil, fmt.Errorf("签名错误")
|
||||||
}
|
}
|
||||||
g.RequestFromCtx(ctx).Response.WriteJson(req.EchoStr)
|
g.RequestFromCtx(ctx).Response.Write(req.EchoStr)
|
||||||
return
|
return nil, nil
|
||||||
}
|
}
|
||||||
|
|||||||
@ -26,10 +26,7 @@ type AdminsColumns struct {
|
|||||||
RealName string // 真实姓名
|
RealName string // 真实姓名
|
||||||
Phone string // 手机号
|
Phone string // 手机号
|
||||||
Email string // 邮箱
|
Email string // 邮箱
|
||||||
Role string // 角色:1=超级管理员,2=运营管理员,3=客服管理员,4=财务管理员
|
|
||||||
Status string // 状态:1=正常,2=禁用
|
Status string // 状态:1=正常,2=禁用
|
||||||
LastLoginAt string // 最后登录时间
|
|
||||||
LastLoginIp string // 最后登录IP
|
|
||||||
CreatedAt string // 创建时间
|
CreatedAt string // 创建时间
|
||||||
UpdatedAt string // 更新时间
|
UpdatedAt string // 更新时间
|
||||||
DeletedAt string // 软删除时间戳
|
DeletedAt string // 软删除时间戳
|
||||||
@ -43,10 +40,7 @@ var adminsColumns = AdminsColumns{
|
|||||||
RealName: "real_name",
|
RealName: "real_name",
|
||||||
Phone: "phone",
|
Phone: "phone",
|
||||||
Email: "email",
|
Email: "email",
|
||||||
Role: "role",
|
|
||||||
Status: "status",
|
Status: "status",
|
||||||
LastLoginAt: "last_login_at",
|
|
||||||
LastLoginIp: "last_login_ip",
|
|
||||||
CreatedAt: "created_at",
|
CreatedAt: "created_at",
|
||||||
UpdatedAt: "updated_at",
|
UpdatedAt: "updated_at",
|
||||||
DeletedAt: "deleted_at",
|
DeletedAt: "deleted_at",
|
||||||
|
|||||||
87
internal/dao/internal/reward_types.go
Normal file
87
internal/dao/internal/reward_types.go
Normal file
@ -0,0 +1,87 @@
|
|||||||
|
// ==========================================================================
|
||||||
|
// Code generated and maintained by GoFrame CLI tool. DO NOT EDIT.
|
||||||
|
// ==========================================================================
|
||||||
|
|
||||||
|
package internal
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
|
||||||
|
"github.com/gogf/gf/v2/database/gdb"
|
||||||
|
"github.com/gogf/gf/v2/frame/g"
|
||||||
|
)
|
||||||
|
|
||||||
|
// RewardTypesDao is the data access object for the table reward_types.
|
||||||
|
type RewardTypesDao struct {
|
||||||
|
table string // table is the underlying table name of the DAO.
|
||||||
|
group string // group is the database configuration group name of the current DAO.
|
||||||
|
columns RewardTypesColumns // columns contains all the column names of Table for convenient usage.
|
||||||
|
}
|
||||||
|
|
||||||
|
// RewardTypesColumns defines and stores column names for the table reward_types.
|
||||||
|
type RewardTypesColumns struct {
|
||||||
|
Id string // 类型ID
|
||||||
|
Name string // 类型名称
|
||||||
|
Code string // 类型编码
|
||||||
|
Description string // 类型描述
|
||||||
|
Status string // 状态:1=启用,2=禁用
|
||||||
|
CreatedAt string // 创建时间
|
||||||
|
UpdatedAt string // 更新时间
|
||||||
|
DeletedAt string // 软删除时间
|
||||||
|
}
|
||||||
|
|
||||||
|
// rewardTypesColumns holds the columns for the table reward_types.
|
||||||
|
var rewardTypesColumns = RewardTypesColumns{
|
||||||
|
Id: "id",
|
||||||
|
Name: "name",
|
||||||
|
Code: "code",
|
||||||
|
Description: "description",
|
||||||
|
Status: "status",
|
||||||
|
CreatedAt: "created_at",
|
||||||
|
UpdatedAt: "updated_at",
|
||||||
|
DeletedAt: "deleted_at",
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewRewardTypesDao creates and returns a new DAO object for table data access.
|
||||||
|
func NewRewardTypesDao() *RewardTypesDao {
|
||||||
|
return &RewardTypesDao{
|
||||||
|
group: "default",
|
||||||
|
table: "reward_types",
|
||||||
|
columns: rewardTypesColumns,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// DB retrieves and returns the underlying raw database management object of the current DAO.
|
||||||
|
func (dao *RewardTypesDao) DB() gdb.DB {
|
||||||
|
return g.DB(dao.group)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Table returns the table name of the current DAO.
|
||||||
|
func (dao *RewardTypesDao) Table() string {
|
||||||
|
return dao.table
|
||||||
|
}
|
||||||
|
|
||||||
|
// Columns returns all column names of the current DAO.
|
||||||
|
func (dao *RewardTypesDao) Columns() RewardTypesColumns {
|
||||||
|
return dao.columns
|
||||||
|
}
|
||||||
|
|
||||||
|
// Group returns the database configuration group name of the current DAO.
|
||||||
|
func (dao *RewardTypesDao) Group() string {
|
||||||
|
return dao.group
|
||||||
|
}
|
||||||
|
|
||||||
|
// Ctx creates and returns a Model for the current DAO. It automatically sets the context for the current operation.
|
||||||
|
func (dao *RewardTypesDao) Ctx(ctx context.Context) *gdb.Model {
|
||||||
|
return dao.DB().Model(dao.table).Safe().Ctx(ctx)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Transaction wraps the transaction logic using function f.
|
||||||
|
// It rolls back the transaction and returns the error if function f returns a non-nil error.
|
||||||
|
// It commits the transaction and returns nil if function f returns nil.
|
||||||
|
//
|
||||||
|
// Note: Do not commit or roll back the transaction in function f,
|
||||||
|
// as it is automatically handled by this function.
|
||||||
|
func (dao *RewardTypesDao) Transaction(ctx context.Context, f func(ctx context.Context, tx gdb.TX) error) (err error) {
|
||||||
|
return dao.Ctx(ctx).Transaction(ctx, f)
|
||||||
|
}
|
||||||
@ -20,30 +20,30 @@ type StoreRewardsDao struct {
|
|||||||
|
|
||||||
// StoreRewardsColumns defines and stores column names for the table store_rewards.
|
// StoreRewardsColumns defines and stores column names for the table store_rewards.
|
||||||
type StoreRewardsColumns struct {
|
type StoreRewardsColumns struct {
|
||||||
Id string // 门店奖励ID
|
Id string // 门店奖励ID
|
||||||
StoreId string // 所属门店ID
|
StoreId string // 所属门店ID
|
||||||
RewardType string // 奖励类型:1=积分,2=优惠券,3=商品,4=抽奖券
|
RewardTypeId string // 奖励类型ID
|
||||||
RewardName string // 奖励名称
|
RewardName string // 奖励名称
|
||||||
Amount string // 奖励数量
|
Amount string // 奖励数量
|
||||||
Total string // 该奖励总库存(NULL 表示无限)
|
Total string // 该奖励总库存(NULL 表示无限)
|
||||||
MerchantId string // 所属商户ID
|
MerchantId string // 所属商户ID
|
||||||
CreatedAt string // 创建时间
|
CreatedAt string // 创建时间
|
||||||
UpdatedAt string // 更新时间
|
UpdatedAt string // 更新时间
|
||||||
DeletedAt string // 软删除时间戳
|
DeletedAt string // 软删除时间戳
|
||||||
}
|
}
|
||||||
|
|
||||||
// storeRewardsColumns holds the columns for the table store_rewards.
|
// storeRewardsColumns holds the columns for the table store_rewards.
|
||||||
var storeRewardsColumns = StoreRewardsColumns{
|
var storeRewardsColumns = StoreRewardsColumns{
|
||||||
Id: "id",
|
Id: "id",
|
||||||
StoreId: "store_id",
|
StoreId: "store_id",
|
||||||
RewardType: "reward_type",
|
RewardTypeId: "reward_type_id",
|
||||||
RewardName: "reward_name",
|
RewardName: "reward_name",
|
||||||
Amount: "amount",
|
Amount: "amount",
|
||||||
Total: "total",
|
Total: "total",
|
||||||
MerchantId: "merchant_id",
|
MerchantId: "merchant_id",
|
||||||
CreatedAt: "created_at",
|
CreatedAt: "created_at",
|
||||||
UpdatedAt: "updated_at",
|
UpdatedAt: "updated_at",
|
||||||
DeletedAt: "deleted_at",
|
DeletedAt: "deleted_at",
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewStoreRewardsDao creates and returns a new DAO object for table data access.
|
// NewStoreRewardsDao creates and returns a new DAO object for table data access.
|
||||||
|
|||||||
@ -23,10 +23,8 @@ type UserLoginRecordsColumns struct {
|
|||||||
Id string // 记录ID
|
Id string // 记录ID
|
||||||
UserId string // 用户ID
|
UserId string // 用户ID
|
||||||
StoreId string // 登录门店ID
|
StoreId string // 登录门店ID
|
||||||
MerchantId string // 所属商户ID
|
|
||||||
LoginIp string // 登录IP地址
|
LoginIp string // 登录IP地址
|
||||||
LoginDevice string // 登录设备信息
|
LoginPlatform string // 登录平台:1=PC
|
||||||
LoginPlatform string // 登录平台:1=Web,2=iOS,3=Android,4=微信小程序,5=支付宝小程序,6=其他
|
|
||||||
LoginType string // 登录方式:1=微信,2=手机号,3=账号密码,4=其他
|
LoginType string // 登录方式:1=微信,2=手机号,3=账号密码,4=其他
|
||||||
LoginStatus string // 登录状态:1=成功,2=失败
|
LoginStatus string // 登录状态:1=成功,2=失败
|
||||||
FailReason string // 失败原因
|
FailReason string // 失败原因
|
||||||
@ -40,9 +38,7 @@ var userLoginRecordsColumns = UserLoginRecordsColumns{
|
|||||||
Id: "id",
|
Id: "id",
|
||||||
UserId: "user_id",
|
UserId: "user_id",
|
||||||
StoreId: "store_id",
|
StoreId: "store_id",
|
||||||
MerchantId: "merchant_id",
|
|
||||||
LoginIp: "login_ip",
|
LoginIp: "login_ip",
|
||||||
LoginDevice: "login_device",
|
|
||||||
LoginPlatform: "login_platform",
|
LoginPlatform: "login_platform",
|
||||||
LoginType: "login_type",
|
LoginType: "login_type",
|
||||||
LoginStatus: "login_status",
|
LoginStatus: "login_status",
|
||||||
|
|||||||
27
internal/dao/reward_types.go
Normal file
27
internal/dao/reward_types.go
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
// =================================================================================
|
||||||
|
// This file is auto-generated by the GoFrame CLI tool. You may modify it as needed.
|
||||||
|
// =================================================================================
|
||||||
|
|
||||||
|
package dao
|
||||||
|
|
||||||
|
import (
|
||||||
|
"server/internal/dao/internal"
|
||||||
|
)
|
||||||
|
|
||||||
|
// internalRewardTypesDao is an internal type for wrapping the internal DAO implementation.
|
||||||
|
type internalRewardTypesDao = *internal.RewardTypesDao
|
||||||
|
|
||||||
|
// rewardTypesDao is the data access object for the table reward_types.
|
||||||
|
// You can define custom methods on it to extend its functionality as needed.
|
||||||
|
type rewardTypesDao struct {
|
||||||
|
internalRewardTypesDao
|
||||||
|
}
|
||||||
|
|
||||||
|
var (
|
||||||
|
// RewardTypes is a globally accessible object for table reward_types operations.
|
||||||
|
RewardTypes = rewardTypesDao{
|
||||||
|
internal.NewRewardTypesDao(),
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
// Add your custom methods and functionality below.
|
||||||
@ -2,6 +2,8 @@ package admin
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
"github.com/gogf/gf/v2/os/glog"
|
||||||
|
"server/internal/consts"
|
||||||
"server/internal/dao"
|
"server/internal/dao"
|
||||||
"server/internal/model"
|
"server/internal/model"
|
||||||
"server/internal/model/do"
|
"server/internal/model/do"
|
||||||
@ -19,8 +21,29 @@ func New() service.IAdmin {
|
|||||||
return &sAdmin{}
|
return &sAdmin{}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func checkAdmin() {
|
||||||
|
ctx := context.Background()
|
||||||
|
exist, err := dao.Admins.Ctx(ctx).Where(do.Admins{Username: "admin"}).Exist()
|
||||||
|
if err != nil {
|
||||||
|
panic("初始化管理员失败")
|
||||||
|
}
|
||||||
|
if !exist {
|
||||||
|
passwordHash, _ := utility.EncryptPassword("Aa123456")
|
||||||
|
_, err = dao.Admins.Ctx(ctx).Insert(do.Admins{
|
||||||
|
Username: "admin",
|
||||||
|
PasswordHash: passwordHash,
|
||||||
|
Status: 1,
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
panic("初始化管理员失败")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
glog.Infof(ctx, "初始化管理员成功")
|
||||||
|
}
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
service.RegisterAdmin(New())
|
service.RegisterAdmin(New())
|
||||||
|
go checkAdmin()
|
||||||
}
|
}
|
||||||
func (s *sAdmin) Login(ctx context.Context, in *model.AdminLoginIn) (out *model.LoginOut, err error) {
|
func (s *sAdmin) Login(ctx context.Context, in *model.AdminLoginIn) (out *model.LoginOut, err error) {
|
||||||
exist, err := dao.Admins.Ctx(ctx).Exist(do.Admins{Username: in.Username})
|
exist, err := dao.Admins.Ctx(ctx).Exist(do.Admins{Username: in.Username})
|
||||||
@ -35,12 +58,13 @@ func (s *sAdmin) Login(ctx context.Context, in *model.AdminLoginIn) (out *model.
|
|||||||
return nil, ecode.Fail.Sub("查询管理员失败")
|
return nil, ecode.Fail.Sub("查询管理员失败")
|
||||||
}
|
}
|
||||||
if !utility.ComparePassword(admin.PasswordHash, in.Password) {
|
if !utility.ComparePassword(admin.PasswordHash, in.Password) {
|
||||||
return nil, ecode.Auth.Sub("密码错误")
|
return nil, ecode.Auth
|
||||||
}
|
}
|
||||||
token, err := jwt.GenerateToken(&jwt.TokenIn{UserId: admin.Id, Permission: "admin"})
|
token, err := jwt.GenerateToken(&jwt.TokenIn{UserId: admin.Id, Permission: consts.AdminPermission})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, ecode.Fail.Sub("生成token失败")
|
return nil, ecode.Fail.Sub("生成token失败")
|
||||||
}
|
}
|
||||||
|
|
||||||
out = &model.LoginOut{
|
out = &model.LoginOut{
|
||||||
Token: token,
|
Token: token,
|
||||||
}
|
}
|
||||||
@ -55,5 +79,12 @@ func (s *sAdmin) Info(ctx context.Context, in *model.AdminInfoIn) (out *model.Ad
|
|||||||
if !exist {
|
if !exist {
|
||||||
return nil, ecode.Params.Sub("该用户不存在")
|
return nil, ecode.Params.Sub("该用户不存在")
|
||||||
}
|
}
|
||||||
|
var admin entity.Admins
|
||||||
|
if err := dao.Admins.Ctx(ctx).WherePri(in.Id).Scan(&admin); err != nil {
|
||||||
|
return nil, ecode.Fail.Sub("查询管理员失败")
|
||||||
|
}
|
||||||
|
out = &model.AdminInfoOut{
|
||||||
|
Username: admin.Username,
|
||||||
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1 +1,102 @@
|
|||||||
package user
|
package internal
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"server/internal/consts"
|
||||||
|
"server/internal/dao"
|
||||||
|
"server/internal/model"
|
||||||
|
"server/internal/model/do"
|
||||||
|
"server/internal/model/entity"
|
||||||
|
"server/internal/service"
|
||||||
|
"server/utility/ecode"
|
||||||
|
"server/utility/jwt"
|
||||||
|
|
||||||
|
"github.com/gogf/gf/v2/os/gtime"
|
||||||
|
"github.com/gogf/gf/v2/util/grand"
|
||||||
|
)
|
||||||
|
|
||||||
|
type sUser struct{}
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
service.RegisterUser(New())
|
||||||
|
}
|
||||||
|
|
||||||
|
func New() service.IUser {
|
||||||
|
return &sUser{}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *sUser) Login(ctx context.Context, in *model.UserLoginIn) (out *model.UserLoginOut, err error) {
|
||||||
|
// 根据 OpenId 查找用户
|
||||||
|
exist, err := dao.Users.Ctx(ctx).Where(do.Users{WxOpenId: in.OpenId}).Exist()
|
||||||
|
if err != nil {
|
||||||
|
return nil, ecode.Fail.Sub("查找用户失败")
|
||||||
|
}
|
||||||
|
|
||||||
|
var userId int64
|
||||||
|
if !exist {
|
||||||
|
// 用户不存在,创建新用户
|
||||||
|
user := &entity.Users{
|
||||||
|
WxOpenId: in.OpenId,
|
||||||
|
Username: grand.Digits(10),
|
||||||
|
FirstVisitAt: gtime.Now(),
|
||||||
|
}
|
||||||
|
result, err := dao.Users.Ctx(ctx).Insert(user)
|
||||||
|
if err != nil {
|
||||||
|
return nil, ecode.Fail.Sub("创建用户失败")
|
||||||
|
}
|
||||||
|
userId, err = result.LastInsertId()
|
||||||
|
if err != nil {
|
||||||
|
return nil, ecode.Fail.Sub("获取用户ID失败")
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// 用户存在,更新最后登录时间
|
||||||
|
var user entity.Users
|
||||||
|
if err := dao.Users.Ctx(ctx).Where(do.Users{WxOpenId: in.OpenId}).Scan(&user); err != nil {
|
||||||
|
return nil, ecode.Fail.Sub("查找用户失败")
|
||||||
|
}
|
||||||
|
userId = user.Id
|
||||||
|
if _, err := dao.Users.Ctx(ctx).Where(do.Users{Id: userId}).Update(do.Users{LastLoginAt: gtime.Now()}); err != nil {
|
||||||
|
return nil, ecode.Fail.Sub("更新登录时间失败")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 生成 token
|
||||||
|
token, err := jwt.GenerateToken(&jwt.TokenIn{
|
||||||
|
UserId: userId,
|
||||||
|
Permission: consts.UserPermission,
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
return nil, ecode.Fail.Sub("生成token失败")
|
||||||
|
}
|
||||||
|
|
||||||
|
out = &model.UserLoginOut{
|
||||||
|
Token: token,
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *sUser) Info(ctx context.Context, in *model.UserInfoIn) (out *model.UserInfoOut, err error) {
|
||||||
|
exist, err := dao.Users.Ctx(ctx).Where(do.Users{WxOpenId: in.OpenId, Id: in.Id}).OmitEmptyWhere().Exist()
|
||||||
|
if err != nil {
|
||||||
|
return nil, ecode.Fail.Sub("查找用户失败")
|
||||||
|
}
|
||||||
|
if !exist {
|
||||||
|
return nil, ecode.Params.Sub("用户不存在")
|
||||||
|
}
|
||||||
|
var user entity.Users
|
||||||
|
if err := dao.Users.Ctx(ctx).Where(do.Users{WxOpenId: in.OpenId, Id: in.Id}).OmitEmptyWhere().Scan(&user); err != nil {
|
||||||
|
return nil, ecode.Fail.Sub("查找用户失败")
|
||||||
|
}
|
||||||
|
out = &model.UserInfoOut{
|
||||||
|
Id: user.Id,
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *sUser) Update(ctx context.Context, in *model.UserUpdateIn) (out *model.UpdateOut, err error) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *sUser) BindPhone(ctx context.Context, in *model.UserBindPhoneIn) (out *model.UpdateOut, err error) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|||||||
@ -27,7 +27,7 @@ import (
|
|||||||
// - 若 Token 格式非法或解析失败:终止请求并返回错误。
|
// - 若 Token 格式非法或解析失败:终止请求并返回错误。
|
||||||
// - 若 Token 合法:将用户信息写入上下文,继续执行下一个中间件或处理函数。
|
// - 若 Token 合法:将用户信息写入上下文,继续执行下一个中间件或处理函数。
|
||||||
func Auth(r *ghttp.Request) {
|
func Auth(r *ghttp.Request) {
|
||||||
token := r.Header.Get("Authorization")
|
token := r.GetHeader("Authorization")
|
||||||
ctx := r.GetCtx()
|
ctx := r.GetCtx()
|
||||||
if token == "" {
|
if token == "" {
|
||||||
glog.Infof(ctx, "未登录用户访问: %s %s", r.URL.Path, r.Method)
|
glog.Infof(ctx, "未登录用户访问: %s %s", r.URL.Path, r.Method)
|
||||||
|
|||||||
@ -1,28 +1,27 @@
|
|||||||
package middleware
|
package middleware
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/gogf/gf/v2/net/ghttp"
|
||||||
|
"server/utility/ecode"
|
||||||
|
"server/utility/myCasbin"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Casbin 是用于访问权限控制的中间件。
|
||||||
//
|
//
|
||||||
//import (
|
// 该中间件基于 Casbin 权限控制框架,校验当前用户是否有权访问指定的 URL 和请求方法。
|
||||||
// "github.com/gogf/gf/v2/net/ghttp"
|
// 用户权限从请求上下文中的 "permission" 字段获取,该字段通常由前置中间件(如 Auth)注入。
|
||||||
// "server/utility/ecode"
|
|
||||||
// "server/utility/myCasbin"
|
|
||||||
//)
|
|
||||||
//
|
//
|
||||||
//// Casbin 是用于访问权限控制的中间件。
|
// 参数:
|
||||||
////
|
//
|
||||||
//// 该中间件基于 Casbin 权限控制框架,校验当前用户是否有权访问指定的 URL 和请求方法。
|
// r *ghttp.Request - 当前的 HTTP 请求对象,由框架自动传入。
|
||||||
//// 用户权限从请求上下文中的 "permission" 字段获取,该字段通常由前置中间件(如 Auth)注入。
|
//
|
||||||
////
|
// 行为:
|
||||||
//// 参数:
|
// - 如果权限验证未通过:终止请求,返回权限不足的错误(ecode.Denied)。
|
||||||
////
|
// - 如果权限验证通过:继续执行后续中间件或处理逻辑。
|
||||||
//// r *ghttp.Request - 当前的 HTTP 请求对象,由框架自动传入。
|
func Casbin(r *ghttp.Request) {
|
||||||
////
|
permission := r.GetCtxVar("permission").String()
|
||||||
//// 行为:
|
if !myCasbin.GetMyCasbin().HasPermission(permission, r.URL.Path, r.Method) {
|
||||||
//// - 如果权限验证未通过:终止请求,返回权限不足的错误(ecode.Denied)。
|
Exit(r, ecode.Denied)
|
||||||
//// - 如果权限验证通过:继续执行后续中间件或处理逻辑。
|
}
|
||||||
//func Casbin(r *ghttp.Request) {
|
r.Middleware.Next()
|
||||||
// permission := r.GetCtxVar("permission").String()
|
}
|
||||||
// if !myCasbin.GetMyCasbin().HasPermission(permission, r.URL.Path, r.Method) {
|
|
||||||
// Exit(r, ecode.Denied)
|
|
||||||
// }
|
|
||||||
// r.Middleware.Next()
|
|
||||||
//}
|
|
||||||
|
|||||||
@ -10,6 +10,6 @@ type (
|
|||||||
Id int
|
Id int
|
||||||
}
|
}
|
||||||
AdminInfoOut struct {
|
AdminInfoOut struct {
|
||||||
Token string
|
Username string
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|||||||
@ -3,3 +3,14 @@ package model
|
|||||||
type LoginOut struct {
|
type LoginOut struct {
|
||||||
Token string
|
Token string
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type UpdateOut struct {
|
||||||
|
Success bool
|
||||||
|
}
|
||||||
|
type DeleteOut struct {
|
||||||
|
Success bool
|
||||||
|
}
|
||||||
|
|
||||||
|
type CreateOut struct {
|
||||||
|
Id int64
|
||||||
|
}
|
||||||
|
|||||||
@ -18,10 +18,7 @@ type Admins struct {
|
|||||||
RealName interface{} // 真实姓名
|
RealName interface{} // 真实姓名
|
||||||
Phone interface{} // 手机号
|
Phone interface{} // 手机号
|
||||||
Email interface{} // 邮箱
|
Email interface{} // 邮箱
|
||||||
Role interface{} // 角色:1=超级管理员,2=运营管理员,3=客服管理员,4=财务管理员
|
|
||||||
Status interface{} // 状态:1=正常,2=禁用
|
Status interface{} // 状态:1=正常,2=禁用
|
||||||
LastLoginAt *gtime.Time // 最后登录时间
|
|
||||||
LastLoginIp interface{} // 最后登录IP
|
|
||||||
CreatedAt *gtime.Time // 创建时间
|
CreatedAt *gtime.Time // 创建时间
|
||||||
UpdatedAt *gtime.Time // 更新时间
|
UpdatedAt *gtime.Time // 更新时间
|
||||||
DeletedAt *gtime.Time // 软删除时间戳
|
DeletedAt *gtime.Time // 软删除时间戳
|
||||||
|
|||||||
23
internal/model/do/reward_types.go
Normal file
23
internal/model/do/reward_types.go
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
// =================================================================================
|
||||||
|
// Code generated and maintained by GoFrame CLI tool. DO NOT EDIT.
|
||||||
|
// =================================================================================
|
||||||
|
|
||||||
|
package do
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/gogf/gf/v2/frame/g"
|
||||||
|
"github.com/gogf/gf/v2/os/gtime"
|
||||||
|
)
|
||||||
|
|
||||||
|
// RewardTypes is the golang structure of table reward_types for DAO operations like Where/Data.
|
||||||
|
type RewardTypes struct {
|
||||||
|
g.Meta `orm:"table:reward_types, do:true"`
|
||||||
|
Id interface{} // 类型ID
|
||||||
|
Name interface{} // 类型名称
|
||||||
|
Code interface{} // 类型编码
|
||||||
|
Description interface{} // 类型描述
|
||||||
|
Status interface{} // 状态:1=启用,2=禁用
|
||||||
|
CreatedAt *gtime.Time // 创建时间
|
||||||
|
UpdatedAt *gtime.Time // 更新时间
|
||||||
|
DeletedAt *gtime.Time // 软删除时间
|
||||||
|
}
|
||||||
@ -11,15 +11,15 @@ import (
|
|||||||
|
|
||||||
// StoreRewards is the golang structure of table store_rewards for DAO operations like Where/Data.
|
// StoreRewards is the golang structure of table store_rewards for DAO operations like Where/Data.
|
||||||
type StoreRewards struct {
|
type StoreRewards struct {
|
||||||
g.Meta `orm:"table:store_rewards, do:true"`
|
g.Meta `orm:"table:store_rewards, do:true"`
|
||||||
Id interface{} // 门店奖励ID
|
Id interface{} // 门店奖励ID
|
||||||
StoreId interface{} // 所属门店ID
|
StoreId interface{} // 所属门店ID
|
||||||
RewardType interface{} // 奖励类型:1=积分,2=优惠券,3=商品,4=抽奖券
|
RewardTypeId interface{} // 奖励类型ID
|
||||||
RewardName interface{} // 奖励名称
|
RewardName interface{} // 奖励名称
|
||||||
Amount interface{} // 奖励数量
|
Amount interface{} // 奖励数量
|
||||||
Total interface{} // 该奖励总库存(NULL 表示无限)
|
Total interface{} // 该奖励总库存(NULL 表示无限)
|
||||||
MerchantId interface{} // 所属商户ID
|
MerchantId interface{} // 所属商户ID
|
||||||
CreatedAt *gtime.Time // 创建时间
|
CreatedAt *gtime.Time // 创建时间
|
||||||
UpdatedAt *gtime.Time // 更新时间
|
UpdatedAt *gtime.Time // 更新时间
|
||||||
DeletedAt *gtime.Time // 软删除时间戳
|
DeletedAt *gtime.Time // 软删除时间戳
|
||||||
}
|
}
|
||||||
|
|||||||
@ -15,10 +15,8 @@ type UserLoginRecords struct {
|
|||||||
Id interface{} // 记录ID
|
Id interface{} // 记录ID
|
||||||
UserId interface{} // 用户ID
|
UserId interface{} // 用户ID
|
||||||
StoreId interface{} // 登录门店ID
|
StoreId interface{} // 登录门店ID
|
||||||
MerchantId interface{} // 所属商户ID
|
|
||||||
LoginIp interface{} // 登录IP地址
|
LoginIp interface{} // 登录IP地址
|
||||||
LoginDevice interface{} // 登录设备信息
|
LoginPlatform interface{} // 登录平台:1=PC
|
||||||
LoginPlatform interface{} // 登录平台:1=Web,2=iOS,3=Android,4=微信小程序,5=支付宝小程序,6=其他
|
|
||||||
LoginType interface{} // 登录方式:1=微信,2=手机号,3=账号密码,4=其他
|
LoginType interface{} // 登录方式:1=微信,2=手机号,3=账号密码,4=其他
|
||||||
LoginStatus interface{} // 登录状态:1=成功,2=失败
|
LoginStatus interface{} // 登录状态:1=成功,2=失败
|
||||||
FailReason interface{} // 失败原因
|
FailReason interface{} // 失败原因
|
||||||
|
|||||||
@ -10,17 +10,14 @@ import (
|
|||||||
|
|
||||||
// Admins is the golang structure for table admins.
|
// Admins is the golang structure for table admins.
|
||||||
type Admins struct {
|
type Admins struct {
|
||||||
Id int64 `json:"id" orm:"id" description:"管理员ID"` // 管理员ID
|
Id int64 `json:"id" orm:"id" description:"管理员ID"` // 管理员ID
|
||||||
Username string `json:"username" orm:"username" description:"管理员用户名"` // 管理员用户名
|
Username string `json:"username" orm:"username" description:"管理员用户名"` // 管理员用户名
|
||||||
PasswordHash string `json:"passwordHash" orm:"password_hash" description:"密码哈希"` // 密码哈希
|
PasswordHash string `json:"passwordHash" orm:"password_hash" description:"密码哈希"` // 密码哈希
|
||||||
RealName string `json:"realName" orm:"real_name" description:"真实姓名"` // 真实姓名
|
RealName string `json:"realName" orm:"real_name" description:"真实姓名"` // 真实姓名
|
||||||
Phone string `json:"phone" orm:"phone" description:"手机号"` // 手机号
|
Phone string `json:"phone" orm:"phone" description:"手机号"` // 手机号
|
||||||
Email string `json:"email" orm:"email" description:"邮箱"` // 邮箱
|
Email string `json:"email" orm:"email" description:"邮箱"` // 邮箱
|
||||||
Role int `json:"role" orm:"role" description:"角色:1=超级管理员,2=运营管理员,3=客服管理员,4=财务管理员"` // 角色:1=超级管理员,2=运营管理员,3=客服管理员,4=财务管理员
|
Status int `json:"status" orm:"status" description:"状态:1=正常,2=禁用"` // 状态:1=正常,2=禁用
|
||||||
Status int `json:"status" orm:"status" description:"状态:1=正常,2=禁用"` // 状态:1=正常,2=禁用
|
CreatedAt *gtime.Time `json:"createdAt" orm:"created_at" description:"创建时间"` // 创建时间
|
||||||
LastLoginAt *gtime.Time `json:"lastLoginAt" orm:"last_login_at" description:"最后登录时间"` // 最后登录时间
|
UpdatedAt *gtime.Time `json:"updatedAt" orm:"updated_at" description:"更新时间"` // 更新时间
|
||||||
LastLoginIp string `json:"lastLoginIp" orm:"last_login_ip" description:"最后登录IP"` // 最后登录IP
|
DeletedAt *gtime.Time `json:"deletedAt" orm:"deleted_at" description:"软删除时间戳"` // 软删除时间戳
|
||||||
CreatedAt *gtime.Time `json:"createdAt" orm:"created_at" description:"创建时间"` // 创建时间
|
|
||||||
UpdatedAt *gtime.Time `json:"updatedAt" orm:"updated_at" description:"更新时间"` // 更新时间
|
|
||||||
DeletedAt *gtime.Time `json:"deletedAt" orm:"deleted_at" description:"软删除时间戳"` // 软删除时间戳
|
|
||||||
}
|
}
|
||||||
|
|||||||
21
internal/model/entity/reward_types.go
Normal file
21
internal/model/entity/reward_types.go
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
// =================================================================================
|
||||||
|
// Code generated and maintained by GoFrame CLI tool. DO NOT EDIT.
|
||||||
|
// =================================================================================
|
||||||
|
|
||||||
|
package entity
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/gogf/gf/v2/os/gtime"
|
||||||
|
)
|
||||||
|
|
||||||
|
// RewardTypes is the golang structure for table reward_types.
|
||||||
|
type RewardTypes struct {
|
||||||
|
Id int64 `json:"id" orm:"id" description:"类型ID"` // 类型ID
|
||||||
|
Name string `json:"name" orm:"name" description:"类型名称"` // 类型名称
|
||||||
|
Code string `json:"code" orm:"code" description:"类型编码"` // 类型编码
|
||||||
|
Description string `json:"description" orm:"description" description:"类型描述"` // 类型描述
|
||||||
|
Status int `json:"status" orm:"status" description:"状态:1=启用,2=禁用"` // 状态:1=启用,2=禁用
|
||||||
|
CreatedAt *gtime.Time `json:"createdAt" orm:"created_at" description:"创建时间"` // 创建时间
|
||||||
|
UpdatedAt *gtime.Time `json:"updatedAt" orm:"updated_at" description:"更新时间"` // 更新时间
|
||||||
|
DeletedAt *gtime.Time `json:"deletedAt" orm:"deleted_at" description:"软删除时间"` // 软删除时间
|
||||||
|
}
|
||||||
@ -10,14 +10,14 @@ import (
|
|||||||
|
|
||||||
// StoreRewards is the golang structure for table store_rewards.
|
// StoreRewards is the golang structure for table store_rewards.
|
||||||
type StoreRewards struct {
|
type StoreRewards struct {
|
||||||
Id int64 `json:"id" orm:"id" description:"门店奖励ID"` // 门店奖励ID
|
Id int64 `json:"id" orm:"id" description:"门店奖励ID"` // 门店奖励ID
|
||||||
StoreId int64 `json:"storeId" orm:"store_id" description:"所属门店ID"` // 所属门店ID
|
StoreId int64 `json:"storeId" orm:"store_id" description:"所属门店ID"` // 所属门店ID
|
||||||
RewardType int `json:"rewardType" orm:"reward_type" description:"奖励类型:1=积分,2=优惠券,3=商品,4=抽奖券"` // 奖励类型:1=积分,2=优惠券,3=商品,4=抽奖券
|
RewardTypeId int64 `json:"rewardTypeId" orm:"reward_type_id" description:"奖励类型ID"` // 奖励类型ID
|
||||||
RewardName string `json:"rewardName" orm:"reward_name" description:"奖励名称"` // 奖励名称
|
RewardName string `json:"rewardName" orm:"reward_name" description:"奖励名称"` // 奖励名称
|
||||||
Amount int `json:"amount" orm:"amount" description:"奖励数量"` // 奖励数量
|
Amount int `json:"amount" orm:"amount" description:"奖励数量"` // 奖励数量
|
||||||
Total int `json:"total" orm:"total" description:"该奖励总库存(NULL 表示无限)"` // 该奖励总库存(NULL 表示无限)
|
Total int `json:"total" orm:"total" description:"该奖励总库存(NULL 表示无限)"` // 该奖励总库存(NULL 表示无限)
|
||||||
MerchantId int64 `json:"merchantId" orm:"merchant_id" description:"所属商户ID"` // 所属商户ID
|
MerchantId int64 `json:"merchantId" orm:"merchant_id" description:"所属商户ID"` // 所属商户ID
|
||||||
CreatedAt *gtime.Time `json:"createdAt" orm:"created_at" description:"创建时间"` // 创建时间
|
CreatedAt *gtime.Time `json:"createdAt" orm:"created_at" description:"创建时间"` // 创建时间
|
||||||
UpdatedAt *gtime.Time `json:"updatedAt" orm:"updated_at" description:"更新时间"` // 更新时间
|
UpdatedAt *gtime.Time `json:"updatedAt" orm:"updated_at" description:"更新时间"` // 更新时间
|
||||||
DeletedAt *gtime.Time `json:"deletedAt" orm:"deleted_at" description:"软删除时间戳"` // 软删除时间戳
|
DeletedAt *gtime.Time `json:"deletedAt" orm:"deleted_at" description:"软删除时间戳"` // 软删除时间戳
|
||||||
}
|
}
|
||||||
|
|||||||
@ -10,17 +10,15 @@ import (
|
|||||||
|
|
||||||
// UserLoginRecords is the golang structure for table user_login_records.
|
// UserLoginRecords is the golang structure for table user_login_records.
|
||||||
type UserLoginRecords struct {
|
type UserLoginRecords struct {
|
||||||
Id int64 `json:"id" orm:"id" description:"记录ID"` // 记录ID
|
Id int64 `json:"id" orm:"id" description:"记录ID"` // 记录ID
|
||||||
UserId int64 `json:"userId" orm:"user_id" description:"用户ID"` // 用户ID
|
UserId int64 `json:"userId" orm:"user_id" description:"用户ID"` // 用户ID
|
||||||
StoreId int64 `json:"storeId" orm:"store_id" description:"登录门店ID"` // 登录门店ID
|
StoreId int64 `json:"storeId" orm:"store_id" description:"登录门店ID"` // 登录门店ID
|
||||||
MerchantId int64 `json:"merchantId" orm:"merchant_id" description:"所属商户ID"` // 所属商户ID
|
LoginIp string `json:"loginIp" orm:"login_ip" description:"登录IP地址"` // 登录IP地址
|
||||||
LoginIp string `json:"loginIp" orm:"login_ip" description:"登录IP地址"` // 登录IP地址
|
LoginPlatform int `json:"loginPlatform" orm:"login_platform" description:"登录平台:1=PC"` // 登录平台:1=PC
|
||||||
LoginDevice string `json:"loginDevice" orm:"login_device" description:"登录设备信息"` // 登录设备信息
|
LoginType int `json:"loginType" orm:"login_type" description:"登录方式:1=微信,2=手机号,3=账号密码,4=其他"` // 登录方式:1=微信,2=手机号,3=账号密码,4=其他
|
||||||
LoginPlatform int `json:"loginPlatform" orm:"login_platform" description:"登录平台:1=Web,2=iOS,3=Android,4=微信小程序,5=支付宝小程序,6=其他"` // 登录平台:1=Web,2=iOS,3=Android,4=微信小程序,5=支付宝小程序,6=其他
|
LoginStatus int `json:"loginStatus" orm:"login_status" description:"登录状态:1=成功,2=失败"` // 登录状态:1=成功,2=失败
|
||||||
LoginType int `json:"loginType" orm:"login_type" description:"登录方式:1=微信,2=手机号,3=账号密码,4=其他"` // 登录方式:1=微信,2=手机号,3=账号密码,4=其他
|
FailReason string `json:"failReason" orm:"fail_reason" description:"失败原因"` // 失败原因
|
||||||
LoginStatus int `json:"loginStatus" orm:"login_status" description:"登录状态:1=成功,2=失败"` // 登录状态:1=成功,2=失败
|
CreatedAt *gtime.Time `json:"createdAt" orm:"created_at" description:"登录时间"` // 登录时间
|
||||||
FailReason string `json:"failReason" orm:"fail_reason" description:"失败原因"` // 失败原因
|
UpdatedAt *gtime.Time `json:"updatedAt" orm:"updated_at" description:"更新时间"` // 更新时间
|
||||||
CreatedAt *gtime.Time `json:"createdAt" orm:"created_at" description:"登录时间"` // 登录时间
|
DeletedAt *gtime.Time `json:"deletedAt" orm:"deleted_at" description:"软删除时间戳"` // 软删除时间戳
|
||||||
UpdatedAt *gtime.Time `json:"updatedAt" orm:"updated_at" description:"更新时间"` // 更新时间
|
|
||||||
DeletedAt *gtime.Time `json:"deletedAt" orm:"deleted_at" description:"软删除时间戳"` // 软删除时间戳
|
|
||||||
}
|
}
|
||||||
|
|||||||
29
internal/model/user.go
Normal file
29
internal/model/user.go
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
package model
|
||||||
|
|
||||||
|
import "time"
|
||||||
|
|
||||||
|
type LoginCache struct {
|
||||||
|
Token string `json:"token"`
|
||||||
|
Status int `json:"status" dc:"0-准备扫码,1-已扫码"`
|
||||||
|
CreatedAt time.Time `json:"created_at"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type UserLoginIn struct {
|
||||||
|
OpenId string
|
||||||
|
}
|
||||||
|
type UserLoginOut struct {
|
||||||
|
Token string
|
||||||
|
}
|
||||||
|
|
||||||
|
type UserInfoIn struct {
|
||||||
|
Id int
|
||||||
|
OpenId string
|
||||||
|
}
|
||||||
|
type UserInfoOut struct {
|
||||||
|
Id int64
|
||||||
|
}
|
||||||
|
|
||||||
|
type UserUpdateIn struct {
|
||||||
|
}
|
||||||
|
type UserBindPhoneIn struct {
|
||||||
|
}
|
||||||
@ -1,7 +1,8 @@
|
|||||||
package packed
|
package packed
|
||||||
|
|
||||||
import (
|
import (
|
||||||
//_ "github.com/gogf/gf/contrib/drivers/mysql/v2"
|
_ "github.com/gogf/gf/contrib/drivers/mysql/v2"
|
||||||
//_ "github.com/gogf/gf/contrib/nosql/redis/v2"
|
_ "github.com/gogf/gf/contrib/nosql/redis/v2"
|
||||||
|
_ "server/utility/myCasbin"
|
||||||
_ "server/utility/wechat"
|
_ "server/utility/wechat"
|
||||||
)
|
)
|
||||||
|
|||||||
@ -5,4 +5,31 @@
|
|||||||
|
|
||||||
package service
|
package service
|
||||||
|
|
||||||
type ()
|
import (
|
||||||
|
"context"
|
||||||
|
"server/internal/model"
|
||||||
|
)
|
||||||
|
|
||||||
|
type (
|
||||||
|
IUser interface {
|
||||||
|
Login(ctx context.Context, in *model.UserLoginIn) (out *model.UserLoginOut, err error)
|
||||||
|
Info(ctx context.Context, in *model.UserInfoIn) (out *model.UserInfoOut, err error)
|
||||||
|
Update(ctx context.Context, in *model.UserUpdateIn) (out *model.UpdateOut, err error)
|
||||||
|
BindPhone(ctx context.Context, in *model.UserBindPhoneIn) (out *model.UpdateOut, err error)
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
localUser IUser
|
||||||
|
)
|
||||||
|
|
||||||
|
func User() IUser {
|
||||||
|
if localUser == nil {
|
||||||
|
panic("implement not found for interface IUser, forgot register?")
|
||||||
|
}
|
||||||
|
return localUser
|
||||||
|
}
|
||||||
|
|
||||||
|
func RegisterUser(i IUser) {
|
||||||
|
localUser = i
|
||||||
|
}
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
# Server configuration.
|
# Server configuration.
|
||||||
server:
|
server:
|
||||||
address: ":8000"
|
address: ":9000"
|
||||||
openapiPath: "/api.json"
|
openapiPath: "/api.json"
|
||||||
swaggerPath: "/swagger"
|
swaggerPath: "/swagger"
|
||||||
|
|
||||||
@ -15,7 +15,7 @@ database:
|
|||||||
level: "all"
|
level: "all"
|
||||||
stdout: true
|
stdout: true
|
||||||
default:
|
default:
|
||||||
link: "mysql:root:MSms0427@tcp(127.0.0.1:3306)/dealxuetest?loc=Local&charset=utf8mb4"
|
link: "mysql:root:MSms0427@tcp(127.0.0.1:3306)/arenax?loc=Local&charset=utf8mb4"
|
||||||
debug: true
|
debug: true
|
||||||
|
|
||||||
# Redis configuration.
|
# Redis configuration.
|
||||||
@ -32,4 +32,4 @@ wechat:
|
|||||||
appId: "wx056fad20f1bd9110"
|
appId: "wx056fad20f1bd9110"
|
||||||
appSecret: "4269b5a2bb0274e805b43efb3fbd232a"
|
appSecret: "4269b5a2bb0274e805b43efb3fbd232a"
|
||||||
ticketExpire: 60
|
ticketExpire: 60
|
||||||
token: "arenax.com"
|
token: "arenax"
|
||||||
@ -32,7 +32,12 @@ func init() {
|
|||||||
glog.Errorf(ctx, "init casbin error: %v", err)
|
glog.Errorf(ctx, "init casbin error: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
enforcer.LoadPolicy()
|
||||||
|
{
|
||||||
|
enforcer.AddPolicy("admin", "/x/admin/info", "GET", "获取管理员用户信息")
|
||||||
|
}
|
||||||
instance = &myCasbin{Enforcer: enforcer}
|
instance = &myCasbin{Enforcer: enforcer}
|
||||||
|
|
||||||
})
|
})
|
||||||
glog.Infof(ctx, "init casbin success")
|
glog.Infof(ctx, "init casbin success")
|
||||||
}
|
}
|
||||||
|
|||||||
@ -2,14 +2,16 @@ package wechat
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"github.com/go-resty/resty/v2"
|
|
||||||
"github.com/gogf/gf/v2/frame/g"
|
|
||||||
"github.com/gogf/gf/v2/os/glog"
|
|
||||||
"io"
|
"io"
|
||||||
"os"
|
"os"
|
||||||
"server/utility/ecode"
|
"server/utility/ecode"
|
||||||
"sync"
|
"sync"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"github.com/go-resty/resty/v2"
|
||||||
|
"github.com/gogf/gf/v2/frame/g"
|
||||||
|
"github.com/gogf/gf/v2/os/glog"
|
||||||
|
"github.com/google/uuid"
|
||||||
)
|
)
|
||||||
|
|
||||||
type weChatClient struct {
|
type weChatClient struct {
|
||||||
@ -94,13 +96,13 @@ func (c *weChatClient) autoRefreshToken(ctx context.Context) {
|
|||||||
time.Sleep(refreshAfter)
|
time.Sleep(refreshAfter)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
func (c *weChatClient) GetTicket(sceneID string) (string, error) {
|
func (c *weChatClient) GetTicket(sceneId string) (string, error) {
|
||||||
body := map[string]interface{}{
|
body := map[string]interface{}{
|
||||||
"expire_seconds": c.TicketExpire,
|
"expire_seconds": c.TicketExpire,
|
||||||
"action_name": "QR_SCENE",
|
"action_name": "QR_STR_SCENE",
|
||||||
"action_info": map[string]interface{}{
|
"action_info": map[string]interface{}{
|
||||||
"scene": map[string]interface{}{
|
"scene": map[string]string{
|
||||||
"scene_str": sceneID,
|
"scene_str": sceneId,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
@ -129,7 +131,7 @@ func (c *weChatClient) GetTicket(sceneID string) (string, error) {
|
|||||||
return result.Ticket, nil
|
return result.Ticket, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *weChatClient) GetQrCode(ticket string, filename string) (imagePath string, err error) {
|
func (c *weChatClient) GetQrCode(ticket string) (imagePath string, err error) {
|
||||||
qrCodeUrl := "https://mp.weixin.qq.com/cgi-bin/showqrcode"
|
qrCodeUrl := "https://mp.weixin.qq.com/cgi-bin/showqrcode"
|
||||||
resp, err := resty.New().R().
|
resp, err := resty.New().R().
|
||||||
SetDoNotParseResponse(true).
|
SetDoNotParseResponse(true).
|
||||||
@ -144,8 +146,7 @@ func (c *weChatClient) GetQrCode(ticket string, filename string) (imagePath stri
|
|||||||
glog.Errorf(context.Background(), "获取二维码图片响应异常: %+v", resp.Status())
|
glog.Errorf(context.Background(), "获取二维码图片响应异常: %+v", resp.Status())
|
||||||
return "", ecode.Fail.Sub("获取二维码图片失败")
|
return "", ecode.Fail.Sub("获取二维码图片失败")
|
||||||
}
|
}
|
||||||
|
imagePath = uuid.New().String() + ".jpg"
|
||||||
imagePath = filename
|
|
||||||
|
|
||||||
data, readErr := io.ReadAll(resp.RawBody())
|
data, readErr := io.ReadAll(resp.RawBody())
|
||||||
if readErr != nil {
|
if readErr != nil {
|
||||||
@ -163,3 +164,7 @@ func (c *weChatClient) GetQrCode(ticket string, filename string) (imagePath stri
|
|||||||
glog.Infof(context.Background(), "二维码图片保存成功: %s", imagePath)
|
glog.Infof(context.Background(), "二维码图片保存成功: %s", imagePath)
|
||||||
return imagePath, nil
|
return imagePath, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (c *weChatClient) GetToken() string {
|
||||||
|
return c.Token
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user