Compare commits
5 Commits
44f1b5d4b5
...
bf220076dd
Author | SHA1 | Date | |
---|---|---|---|
bf220076dd | |||
7903175c91 | |||
ad6773c575 | |||
159ef59749 | |||
ed3c15fbb6 |
@ -7,6 +7,7 @@ import (
|
||||
"git.echol.cn/loser/lckt/api/v1/example"
|
||||
"git.echol.cn/loser/lckt/api/v1/system"
|
||||
"git.echol.cn/loser/lckt/api/v1/user"
|
||||
"git.echol.cn/loser/lckt/api/v1/vip"
|
||||
)
|
||||
|
||||
var ApiGroupApp = new(ApiGroup)
|
||||
@ -18,4 +19,5 @@ type ApiGroup struct {
|
||||
BotApiGroup bot.ApiGroup
|
||||
ArticleApiGroup article.ApiGroup
|
||||
UserApiGroup user.APPUserApi
|
||||
VipApiGroup vip.ApiGroup
|
||||
}
|
||||
|
@ -7,6 +7,7 @@ import (
|
||||
"git.echol.cn/loser/lckt/model/user/request"
|
||||
"git.echol.cn/loser/lckt/utils"
|
||||
"git.echol.cn/loser/lckt/utils/user_jwt"
|
||||
"git.echol.cn/loser/lckt/utils/wechat"
|
||||
"github.com/gin-gonic/gin"
|
||||
"github.com/redis/go-redis/v9"
|
||||
"go.uber.org/zap"
|
||||
@ -92,7 +93,45 @@ func (*APPUserApi) WechatLogin(ctx *gin.Context) {
|
||||
global.GVA_LOG.Error("参数错误,登录失败", zap.Error(err))
|
||||
return
|
||||
}
|
||||
|
||||
//Todo 待完善微信登录
|
||||
info := wechat.GetUserInfo(p.Code)
|
||||
if info == nil {
|
||||
r.FailWithMessage("获取用户信息失败", ctx)
|
||||
return
|
||||
}
|
||||
|
||||
user, err := userService.WechatLogin(info)
|
||||
if err != nil {
|
||||
r.FailWithMessage("登录失败", ctx)
|
||||
return
|
||||
}
|
||||
// 生成token
|
||||
token, claims, err := user_jwt.LoginToken(user)
|
||||
if err != nil {
|
||||
global.GVA_LOG.Error("获取token失败!", zap.Error(err))
|
||||
r.FailWithMessage("获取token失败", ctx)
|
||||
return
|
||||
}
|
||||
if _, err = global.GVA_REDIS.Get(ctx, user.Phone).Result(); err == redis.Nil {
|
||||
// 此处过期时间等于jwt过期时间
|
||||
dr, err := utils.ParseDuration(global.GVA_CONFIG.JWT.ExpiresTime)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
timer := dr
|
||||
if err := global.GVA_REDIS.Set(ctx, user.Phone, token, timer).Err(); err != nil {
|
||||
global.GVA_LOG.Error("设置登录状态失败!", zap.Error(err))
|
||||
r.FailWithMessage("设置登录状态失败", ctx)
|
||||
return
|
||||
}
|
||||
user_jwt.SetToken(ctx, token, int(claims.RegisteredClaims.ExpiresAt.Unix()-time.Now().Unix()))
|
||||
r.OkWithDetailed(gin.H{
|
||||
"User": user,
|
||||
"Token": token,
|
||||
"ExpiresAt": claims.RegisteredClaims.ExpiresAt.Unix() * 1000,
|
||||
}, "登录成功", ctx)
|
||||
}
|
||||
}
|
||||
|
||||
// GetUserList 获取用户列表
|
||||
@ -130,3 +169,92 @@ func (*APPUserApi) SetBalance(ctx *gin.Context) {
|
||||
}
|
||||
r.OkWithMessage("设置用户余额成功", ctx)
|
||||
}
|
||||
|
||||
// PwdLogin 密码登录
|
||||
func (*APPUserApi) PwdLogin(ctx *gin.Context) {
|
||||
var p request.PwdLoginReq
|
||||
if err := ctx.ShouldBind(&p); err != nil {
|
||||
r.FailWithMessage(err.Error(), ctx)
|
||||
global.GVA_LOG.Error("参数错误,登录失败", zap.Error(err))
|
||||
return
|
||||
}
|
||||
|
||||
user, err := userService.PwdLogin(p)
|
||||
if err != nil {
|
||||
r.FailWithMessage("手机号或密码错误!", ctx)
|
||||
return
|
||||
}
|
||||
|
||||
// 生成token
|
||||
token, claims, err := user_jwt.LoginToken(user)
|
||||
if err != nil {
|
||||
global.GVA_LOG.Error("获取token失败!", zap.Error(err))
|
||||
r.FailWithMessage("获取token失败", ctx)
|
||||
return
|
||||
}
|
||||
|
||||
// 此处过期时间等于jwt过期时间
|
||||
dr, err := utils.ParseDuration(global.GVA_CONFIG.JWT.ExpiresTime)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
timer := dr
|
||||
if err := global.GVA_REDIS.Set(ctx, user.Phone, token, timer).Err(); err != nil {
|
||||
global.GVA_LOG.Error("设置登录状态失败!", zap.Error(err))
|
||||
r.FailWithMessage("设置登录状态失败", ctx)
|
||||
return
|
||||
}
|
||||
user_jwt.SetToken(ctx, token, int(claims.RegisteredClaims.ExpiresAt.Unix()-time.Now().Unix()))
|
||||
r.OkWithDetailed(gin.H{
|
||||
"User": user,
|
||||
"Token": token,
|
||||
"ExpiresAt": claims.RegisteredClaims.ExpiresAt.Unix() * 1000,
|
||||
}, "登录成功", ctx)
|
||||
}
|
||||
|
||||
// Register 注册-后台用
|
||||
func (*APPUserApi) Register(ctx *gin.Context) {
|
||||
var p request.RegisterReq
|
||||
if err := ctx.ShouldBind(&p); err != nil {
|
||||
r.FailWithMessage(err.Error(), ctx)
|
||||
global.GVA_LOG.Error("参数错误,注册失败", zap.Error(err))
|
||||
return
|
||||
}
|
||||
|
||||
if err := userService.Register(p); err != nil {
|
||||
r.FailWithMessage("注册失败", ctx)
|
||||
return
|
||||
}
|
||||
|
||||
r.OkWithMessage("注册成功", ctx)
|
||||
}
|
||||
|
||||
// SetUserStatus 设置用户状态
|
||||
func (*APPUserApi) SetUserStatus(ctx *gin.Context) {
|
||||
id := ctx.Param("id")
|
||||
if id == "" {
|
||||
r.FailWithMessage("参数错误", ctx)
|
||||
return
|
||||
}
|
||||
|
||||
if err := userService.SetUserStatus(id); err != nil {
|
||||
r.FailWithMessage("设置用户状态失败", ctx)
|
||||
return
|
||||
}
|
||||
r.OkWithMessage("设置用户状态成功", ctx)
|
||||
}
|
||||
|
||||
// GetUserById 根据id获取用户信息
|
||||
func (*APPUserApi) GetUserById(ctx *gin.Context) {
|
||||
id := ctx.Param("id")
|
||||
if id == "" {
|
||||
r.FailWithMessage("参数错误", ctx)
|
||||
return
|
||||
}
|
||||
user, err := userService.GetUserById(id)
|
||||
if err != nil {
|
||||
r.FailWithMessage("获取用户信息失败", ctx)
|
||||
return
|
||||
}
|
||||
r.OkWithDetailed(user, "获取用户信息成功", ctx)
|
||||
}
|
||||
|
7
api/v1/vip/enter.go
Normal file
7
api/v1/vip/enter.go
Normal file
@ -0,0 +1,7 @@
|
||||
package vip
|
||||
|
||||
import "git.echol.cn/loser/lckt/service"
|
||||
|
||||
type ApiGroup struct{ VipApi }
|
||||
|
||||
var vipService = service.ServiceGroupApp.VipServiceGroup.VipService
|
88
api/v1/vip/vip.go
Normal file
88
api/v1/vip/vip.go
Normal file
@ -0,0 +1,88 @@
|
||||
package vip
|
||||
|
||||
import (
|
||||
"git.echol.cn/loser/lckt/model/common/request"
|
||||
"git.echol.cn/loser/lckt/model/common/response"
|
||||
"git.echol.cn/loser/lckt/model/vip"
|
||||
"github.com/gin-gonic/gin"
|
||||
)
|
||||
|
||||
type VipApi struct{}
|
||||
|
||||
// GetVipList 获取会员列表
|
||||
func (v *VipApi) GetVipList(ctx *gin.Context) {
|
||||
var p request.PageInfo
|
||||
if err := ctx.ShouldBind(&p); err != nil {
|
||||
response.FailWithMessage("参数有误", ctx)
|
||||
return
|
||||
}
|
||||
|
||||
vipList, total, err := vipService.GetVipList(p)
|
||||
if err != nil {
|
||||
response.FailWithMessage("获取VIP列表失败", ctx)
|
||||
return
|
||||
}
|
||||
response.OkWithDetailed(
|
||||
response.PageResult{
|
||||
List: vipList,
|
||||
Total: total,
|
||||
Page: p.Page,
|
||||
PageSize: p.PageSize,
|
||||
},
|
||||
"获取VIP列表成功",
|
||||
ctx,
|
||||
)
|
||||
}
|
||||
|
||||
// Create 创建会员
|
||||
func (v *VipApi) Create(ctx *gin.Context) {
|
||||
var p vip.Vip
|
||||
if err := ctx.ShouldBind(&p); err != nil {
|
||||
response.FailWithMessage("参数有误", ctx)
|
||||
return
|
||||
}
|
||||
if err := vipService.CreateVip(p); err != nil {
|
||||
response.FailWithMessage("创建会员失败", ctx)
|
||||
return
|
||||
}
|
||||
response.OkWithMessage("创建会员成功", ctx)
|
||||
}
|
||||
|
||||
// Update 更新会员
|
||||
func (v *VipApi) Update(ctx *gin.Context) {
|
||||
var p vip.Vip
|
||||
if err := ctx.ShouldBind(&p); err != nil {
|
||||
response.FailWithMessage("参数有误", ctx)
|
||||
return
|
||||
}
|
||||
if err := vipService.UpdateVip(p); err != nil {
|
||||
response.FailWithMessage("更新会员失败", ctx)
|
||||
return
|
||||
}
|
||||
response.OkWithMessage("更新会员成功", ctx)
|
||||
}
|
||||
|
||||
// Delete 删除会员
|
||||
func (v *VipApi) Delete(ctx *gin.Context) {
|
||||
var p vip.Vip
|
||||
if err := ctx.ShouldBind(&p); err != nil {
|
||||
response.FailWithMessage("参数有误", ctx)
|
||||
return
|
||||
}
|
||||
if err := vipService.DeleteVip(p); err != nil {
|
||||
response.FailWithMessage("删除会员失败", ctx)
|
||||
return
|
||||
}
|
||||
response.OkWithMessage("删除会员成功", ctx)
|
||||
}
|
||||
|
||||
// GetVipById 获取会员详情
|
||||
func (v *VipApi) GetVipById(ctx *gin.Context) {
|
||||
id := ctx.Param("id")
|
||||
vip, err := vipService.GetVipById(id)
|
||||
if err != nil {
|
||||
response.FailWithMessage("获取会员详情失败", ctx)
|
||||
return
|
||||
}
|
||||
response.OkWithDetailed(vip, "获取会员详情成功", ctx)
|
||||
}
|
14
config.yaml
14
config.yaml
@ -178,9 +178,9 @@ qiniu:
|
||||
use-https: false
|
||||
use-cdn-domains: false
|
||||
redis:
|
||||
name: ""
|
||||
addr: 127.0.0.1:6379
|
||||
password: ""
|
||||
name: "hw"
|
||||
addr: 120.46.165.63:6379
|
||||
password: "loser765911"
|
||||
db: 0
|
||||
useCluster: false
|
||||
clusterAddrs:
|
||||
@ -189,9 +189,9 @@ redis:
|
||||
- 172.21.0.2:7002
|
||||
redis-list:
|
||||
- name: cache
|
||||
addr: 127.0.0.1:6379
|
||||
password: ""
|
||||
db: 0
|
||||
addr: 120.46.165.63:6379
|
||||
password: "loser765911"
|
||||
db: 1
|
||||
useCluster: false
|
||||
clusterAddrs:
|
||||
- 172.21.0.3:7000
|
||||
@ -219,7 +219,7 @@ system:
|
||||
iplimit-count: 15000
|
||||
iplimit-time: 3600
|
||||
use-multipoint: false
|
||||
use-redis: false
|
||||
use-redis: true
|
||||
use-mongo: false
|
||||
use-strict-auth: false
|
||||
tencent-cos:
|
||||
|
@ -6,6 +6,7 @@ import (
|
||||
"git.echol.cn/loser/lckt/model/bot"
|
||||
"git.echol.cn/loser/lckt/model/category"
|
||||
"git.echol.cn/loser/lckt/model/user"
|
||||
"git.echol.cn/loser/lckt/model/vip"
|
||||
)
|
||||
|
||||
func bizModel() error {
|
||||
@ -15,6 +16,7 @@ func bizModel() error {
|
||||
bot.Bot{},
|
||||
article.Article{},
|
||||
user.User{},
|
||||
vip.Vip{},
|
||||
)
|
||||
if err != nil {
|
||||
return err
|
||||
|
@ -28,5 +28,10 @@ func initBizRouter(routers ...*gin.RouterGroup) {
|
||||
{
|
||||
userRouter := router.RouterGroupApp.User
|
||||
userRouter.InitUserRouter(privateGroup, publicGroup)
|
||||
userRouter.InitAppUserRouter(publicGroup)
|
||||
}
|
||||
{
|
||||
vipRouter := router.RouterGroupApp.Vip
|
||||
vipRouter.InitVipRouter(privateGroup, publicGroup)
|
||||
}
|
||||
}
|
||||
|
3
main.go
3
main.go
@ -4,6 +4,7 @@ import (
|
||||
"git.echol.cn/loser/lckt/core"
|
||||
"git.echol.cn/loser/lckt/global"
|
||||
"git.echol.cn/loser/lckt/initialize"
|
||||
"git.echol.cn/loser/lckt/utils/wechat"
|
||||
_ "go.uber.org/automaxprocs"
|
||||
"go.uber.org/zap"
|
||||
)
|
||||
@ -41,5 +42,7 @@ func main() {
|
||||
db, _ := global.GVA_DB.DB()
|
||||
defer db.Close()
|
||||
}
|
||||
|
||||
wechat.InitWeOfficial() // 初始化微信公众号SDK
|
||||
core.RunWindowsServer()
|
||||
}
|
||||
|
@ -4,6 +4,7 @@ import (
|
||||
"errors"
|
||||
"git.echol.cn/loser/lckt/global"
|
||||
"git.echol.cn/loser/lckt/utils"
|
||||
"git.echol.cn/loser/lckt/utils/user_jwt"
|
||||
"github.com/golang-jwt/jwt/v5"
|
||||
"strconv"
|
||||
"time"
|
||||
@ -15,7 +16,7 @@ import (
|
||||
func UserJWTAuth() gin.HandlerFunc {
|
||||
return func(c *gin.Context) {
|
||||
// 我们这里jwt鉴权取头部信息 x-token 登录时回返回token信息 这里前端需要把token存储到cookie或者本地localStorage中 不过需要跟后端协商过期时间 可以约定刷新令牌或者重新登录
|
||||
token := utils.GetToken(c)
|
||||
token := user_jwt.GetToken(c)
|
||||
if token == "" {
|
||||
response.NoAuth("未登录或非法访问", c)
|
||||
c.Abort()
|
||||
@ -28,12 +29,12 @@ func UserJWTAuth() gin.HandlerFunc {
|
||||
if err != nil {
|
||||
if errors.Is(err, utils.TokenExpired) {
|
||||
response.NoAuth("授权已过期", c)
|
||||
utils.ClearToken(c)
|
||||
user_jwt.ClearToken(c)
|
||||
c.Abort()
|
||||
return
|
||||
}
|
||||
response.NoAuth(err.Error(), c)
|
||||
utils.ClearToken(c)
|
||||
user_jwt.ClearToken(c)
|
||||
c.Abort()
|
||||
return
|
||||
}
|
||||
@ -46,7 +47,7 @@ func UserJWTAuth() gin.HandlerFunc {
|
||||
newClaims, _ := j.ParseToken(newToken)
|
||||
c.Header("new-token", newToken)
|
||||
c.Header("new-expires-at", strconv.FormatInt(newClaims.ExpiresAt.Unix(), 10))
|
||||
utils.SetToken(c, newToken, int(dr.Seconds()))
|
||||
user_jwt.SetToken(c, newToken, int(dr.Seconds()))
|
||||
if global.GVA_CONFIG.System.UseMultipoint {
|
||||
// 记录新的活跃jwt
|
||||
_ = jwtService.SetRedisJWT(newToken, newClaims.Username)
|
||||
|
@ -3,49 +3,64 @@ package request
|
||||
import "git.echol.cn/loser/lckt/model/common/request"
|
||||
|
||||
type SendCodeReq struct {
|
||||
Phone string `json:"phone" vd:"@:len($)>0; msg:'手机号码不能为空'"`
|
||||
Phone string `json:"phone" form:"phone" vd:"@:len($)>0; msg:'手机号码不能为空'"`
|
||||
}
|
||||
|
||||
type CodeLoginReq struct {
|
||||
Phone string `json:"phone" vd:"@:len($)>0; msg:'请输入手机号码'"`
|
||||
Code string `json:"code" vd:"@:len($)>0; msg:'请输入短信验证码'"`
|
||||
Phone string `json:"phone" form:"phone" vd:"@:len($)>0; msg:'请输入手机号码'"`
|
||||
Code string `json:"code" form:"code" vd:"@:len($)>0; msg:'请输入短信验证码'"`
|
||||
}
|
||||
|
||||
type InviteLoginReq struct {
|
||||
Phone string `json:"phone" vd:"@:len($)>0; msg:'手机号码不能为空'"`
|
||||
Code string `json:"code" vd:"@:len($)>0; msg:'验证码不能为空'"`
|
||||
Type string `json:"type" vd:"@:len($)>0; msg:'邀请类型不能为空'"`
|
||||
Token string `json:"token" vd:"@:len($)>0; msg:'token不能为空'"`
|
||||
Phone string `json:"phone" form:"phone" vd:"@:len($)>0; msg:'手机号码不能为空'"`
|
||||
Code string `json:"code" form:"code" vd:"@:len($)>0; msg:'验证码不能为空'"`
|
||||
Type string `json:"type" form:"type" vd:"@:len($)>0; msg:'邀请类型不能为空'"`
|
||||
Token string `json:"token" form:"token" vd:"@:len($)>0; msg:'token不能为空'"`
|
||||
}
|
||||
|
||||
type WxLoginReq struct {
|
||||
OpenId string `json:"openId" binding:"required"`
|
||||
NickName string `json:"nickName"`
|
||||
Gender int `json:"gender"`
|
||||
UnionId string `json:"unionId" binding:"required"`
|
||||
AvatarUrl string `json:"avatarUrl"`
|
||||
Province string `json:"province"`
|
||||
City string `json:"city"`
|
||||
OpenId string `json:"openId" form:"openId" binding:"required"`
|
||||
NickName string `json:"nickName" form:"nickName"`
|
||||
Gender int `json:"gender" form:"gender"`
|
||||
UnionId string `json:"unionId" form:"unionId" binding:"required"`
|
||||
AvatarUrl string `json:"avatarUrl" form:"avatarUrl"`
|
||||
Province string `json:"province" form:"province"`
|
||||
City string `json:"city" form:"city"`
|
||||
}
|
||||
|
||||
type BindWechatReq struct {
|
||||
Id int `json:"id" vd:"@:len($)>0; msg:'id不能为空'"`
|
||||
Openid string `json:"openid" vd:"@:len($)>0; msg:'OpenId不能为空'"`
|
||||
UnionId string `json:"unionId" gorm:"type:varchar(64);comment:用户统一标识。针对一个微信开放平台帐号下的应用,同一用户的 unionid 是唯一的。"`
|
||||
Id int `json:"id" form:"id" vd:"@:len($)>0; msg:'id不能为空'"`
|
||||
Openid string `json:"openid" form:"openid" vd:"@:len($)>0; msg:'OpenId不能为空'"`
|
||||
UnionId string `json:"unionId" form:"unionId" gorm:"type:varchar(64);comment:用户统一标识。针对一个微信开放平台帐号下的应用,同一用户的 unionid 是唯一的。"`
|
||||
}
|
||||
|
||||
type BindPhoneReq struct {
|
||||
Id int `json:"id" vd:"@:len($)>0; msg:'用户ID不能为空'"`
|
||||
Phone string `json:"phone" vd:"@:len($)>0; msg:'手机号码不能为空'"`
|
||||
Id int `json:"id" form:"id" vd:"@:len($)>0; msg:'用户ID不能为空'"`
|
||||
Phone string `json:"phone" form:"phone" vd:"@:len($)>0; msg:'手机号码不能为空'"`
|
||||
}
|
||||
|
||||
type GetUserListReq struct {
|
||||
request.PageInfo
|
||||
Type int `json:"type"`
|
||||
UserLabel string `json:"user_label" `
|
||||
Type int `json:"type" form:"type"`
|
||||
UserLabel string `json:"user_label" form:"user_label" `
|
||||
Status int `json:"status" form:"status"`
|
||||
}
|
||||
|
||||
type SetBalanceReq struct {
|
||||
Id int `json:"id" vd:"@:len($)>0; msg:'用户ID不能为空'"`
|
||||
Balance float32 `json:"balance" vd:"@:len($)>0; msg:'余额不能为空'"`
|
||||
Id int `json:"id" form:"id" vd:"@:len($)>0; msg:'用户ID不能为空'"`
|
||||
Balance float32 `json:"balance" form:"balance" vd:"@:len($)>0; msg:'余额不能为空'"`
|
||||
}
|
||||
|
||||
type PwdLoginReq struct {
|
||||
Phone string `json:"phone" form:"phone" vd:"@:len($)>0; msg:'手机号码不能为空'"`
|
||||
Password string `json:"password" form:"password" vd:"@:len($)>0; msg:'密码不能为空'"`
|
||||
NickName string `json:"nick_name" form:"nick_name"`
|
||||
}
|
||||
|
||||
type RegisterReq struct {
|
||||
Phone string `json:"phone" form:"phone" vd:"@:len($)>0; msg:'手机号码不能为空'"`
|
||||
Password string `json:"password" form:"password" vd:"@:len($)>0; msg:'密码不能为空'"`
|
||||
NickName string `json:"nick_name" form:"nick_name"`
|
||||
UserType int8 `json:"user_type" form:"user_type" vd:"@:len($)>0; msg:'用户类型不能为空'"`
|
||||
UserLabel int64 `json:"user_label" form:"user_label" vd:"@:len($)>0; msg:'用户标签不能为空'"`
|
||||
}
|
||||
|
@ -4,18 +4,21 @@ import "git.echol.cn/loser/lckt/global"
|
||||
|
||||
type User struct {
|
||||
global.GVA_MODEL
|
||||
NickName string `json:"nick_name" gorm:"comment:用户昵称"`
|
||||
Phone string `json:"phone" gorm:"comment:用户手机号"`
|
||||
UnionId string `json:"union_id" gorm:"type:varchar(255) comment '微信UnionId'"`
|
||||
NickName string `json:"nick_name" form:"nick_name" gorm:"comment:用户昵称"`
|
||||
Phone string `json:"phone" form:"phone" gorm:"comment:用户手机号"`
|
||||
UnionId string `json:"union_id" form:"union_id" gorm:"type:varchar(255) comment '微信UnionId'"`
|
||||
OpenId string `gorm:"column:open_id;default:'';comment:'openId'" json:"-"`
|
||||
Avatar string `json:"avatar" gorm:"comment:用户头像"`
|
||||
Status int8 `gorm:"column:status;default:1;NOT NULL;comment:'用户状态 0 封禁 1 正常'" json:"status"`
|
||||
Password string `json:"password" form:"password" gorm:"comment:用户密码"`
|
||||
Avatar string `json:"avatar" form:"avatar" gorm:"comment:用户头像"`
|
||||
Status int8 `gorm:"column:status;default:1;NOT NULL;comment:'用户状态 0 封禁 1 正常'" json:"status" form:"status"`
|
||||
//邀请码
|
||||
InviteCode *string `json:"invite_code" gorm:"type:varchar(255) comment '用户专属邀请码'"`
|
||||
Balance float32 `json:"balance" gorm:"type:decimal(10,2);comment:学员余额"`
|
||||
CommenderId int `json:"commender_id" gorm:"comment:推荐人ID"`
|
||||
UserLabel string `json:"user_label" gorm:"type:varchar(255) comment '用户标签 普通/VIP/SVIP'"`
|
||||
UserType int8 `gorm:"column:user_type;default:1;NOT NULL;comment:'用户类型 1 用户 2 讲师'" json:"user_type"`
|
||||
InviteCode *string `json:"invite_code" form:"invite_code" gorm:"type:varchar(255) comment '用户专属邀请码'"`
|
||||
Balance float32 `json:"balance" form:"balance" gorm:"type:decimal(10,2);comment:学员余额"`
|
||||
CommenderId int `json:"commender_id" form:"commender_id" gorm:"comment:推荐人ID"`
|
||||
UserLabel int64 `json:"user_label" form:"user_label" gorm:"comment:用户标签 1 普通用户 2 Vip 3 Svip"`
|
||||
UserType int8 `gorm:"column:user_type;default:1;NOT NULL;comment:'用户类型 1 用户 2 讲师'" json:"user_type" form:"user_type" `
|
||||
IsVip int8 `gorm:"column:is_vip;default:0;NOT NULL;comment:'是否是VIP 0 否 1 是'" json:"is_vip" form:"is_vip"`
|
||||
VipExpireTime string `json:"vip_expire_time" form:"vip_expire_time" gorm:"comment:VIP过期时间"`
|
||||
}
|
||||
|
||||
func (User) TableName() string {
|
||||
|
16
model/vip/vip.go
Normal file
16
model/vip/vip.go
Normal file
@ -0,0 +1,16 @@
|
||||
package vip
|
||||
|
||||
import "git.echol.cn/loser/lckt/global"
|
||||
|
||||
type Vip struct {
|
||||
global.GVA_MODEL
|
||||
Name string `json:"name" form:"name" gorm:"comment:会员名称"` // 会员名称
|
||||
Level int `json:"level" form:"level" gorm:"comment:会员等级 1 Vip 2 Svip"` // 会员等级
|
||||
Price float64 `json:"price" form:"price" gorm:"comment:会员价格"` // 会员价格
|
||||
Expiration int64 `json:"expiration" form:"expiration" gorm:"comment:会员有效期"` // 会员过期时间
|
||||
}
|
||||
|
||||
// TableName 设置表名
|
||||
func (Vip) TableName() string {
|
||||
return "lckt_vip"
|
||||
}
|
@ -7,6 +7,7 @@ import (
|
||||
"git.echol.cn/loser/lckt/router/example"
|
||||
"git.echol.cn/loser/lckt/router/system"
|
||||
"git.echol.cn/loser/lckt/router/user"
|
||||
"git.echol.cn/loser/lckt/router/vip"
|
||||
)
|
||||
|
||||
var RouterGroupApp = new(RouterGroup)
|
||||
@ -18,4 +19,5 @@ type RouterGroup struct {
|
||||
Bot bot.RouterGroup
|
||||
Article article.RouterGroup
|
||||
User user.UserRouter
|
||||
Vip vip.VipRouter
|
||||
}
|
||||
|
@ -10,14 +10,22 @@ type UserRouter struct{}
|
||||
// InitUserRouter 初始化 用户相关 路由信息
|
||||
func (s *UserRouter) InitUserRouter(Router *gin.RouterGroup, PublicRouter *gin.RouterGroup) {
|
||||
userRouter := Router.Group("app_user").Use(middleware.OperationRecord())
|
||||
userRouterWithoutAuth := PublicRouter.Group("app_user")
|
||||
{
|
||||
userRouter.GET("list", userApi.GetUserList) // 获取用户列表
|
||||
userRouter.PUT("setBalance", userApi.SetBalance) // 更新用户余额
|
||||
userRouter.GET("list", userApi.GetUserList) // 获取用户列表
|
||||
userRouter.PUT("setBalance", userApi.SetBalance) // 更新用户余额
|
||||
userRouter.POST("register", userApi.Register) // 注册
|
||||
userRouter.PUT("status/:id", userApi.SetUserStatus) // 更新用户状态
|
||||
userRouter.GET(":id", userApi.GetUserById) // 获取用户信息
|
||||
}
|
||||
}
|
||||
|
||||
func (s *UserRouter) InitAppUserRouter(PublicRouter *gin.RouterGroup) {
|
||||
appUserRouter := PublicRouter.Group("h5_user").Use(middleware.UserJWTAuth())
|
||||
{
|
||||
appUserRouter.DELETE("login", userApi.Login) // 短信验证码登录
|
||||
appUserRouter.POST("sms/send", userApi.SendCode) // 发送短信验证码
|
||||
appUserRouter.POST("wxLogin", userApi.WechatLogin) // 微信登录
|
||||
appUserRouter.POST("pwdlogin", userApi.PwdLogin) // 密码登录
|
||||
appUserRouter.GET(":id", userApi.GetUserById) // 获取用户信息
|
||||
}
|
||||
{
|
||||
userRouterWithoutAuth.DELETE("login", userApi.Login) // 短信验证码登录
|
||||
userRouterWithoutAuth.POST("sms", userApi.SendCode) // 发送短信验证码
|
||||
}
|
||||
|
||||
}
|
||||
|
7
router/vip/enter.go
Normal file
7
router/vip/enter.go
Normal file
@ -0,0 +1,7 @@
|
||||
package vip
|
||||
|
||||
import api "git.echol.cn/loser/lckt/api/v1"
|
||||
|
||||
type RouterGroup struct{ VipRouter }
|
||||
|
||||
var vipApi = api.ApiGroupApp.VipApiGroup
|
23
router/vip/vip.go
Normal file
23
router/vip/vip.go
Normal file
@ -0,0 +1,23 @@
|
||||
package vip
|
||||
|
||||
import (
|
||||
"git.echol.cn/loser/lckt/middleware"
|
||||
"github.com/gin-gonic/gin"
|
||||
)
|
||||
|
||||
type VipRouter struct{}
|
||||
|
||||
// InitVipRouter 初始化会员路由
|
||||
func (s *VipRouter) InitVipRouter(Router *gin.RouterGroup, PublicRouter *gin.RouterGroup) {
|
||||
vipRouter := Router.Group("vip").Use(middleware.OperationRecord())
|
||||
vipNoAuthRouter := PublicRouter.Group("vip").Use(middleware.OperationRecord())
|
||||
{
|
||||
vipRouter.POST("", vipApi.Create) // 获取用户列表
|
||||
vipRouter.DELETE("", vipApi.Delete) // 更新用户余额
|
||||
vipRouter.PUT("", vipApi.Update) // 注册
|
||||
}
|
||||
{
|
||||
vipNoAuthRouter.GET(":id", vipApi.GetVipById) // 根据获取vip信息
|
||||
vipNoAuthRouter.GET("list", vipApi.GetVipList) // 获取会员列表
|
||||
}
|
||||
}
|
@ -7,6 +7,7 @@ import (
|
||||
"git.echol.cn/loser/lckt/service/example"
|
||||
"git.echol.cn/loser/lckt/service/system"
|
||||
"git.echol.cn/loser/lckt/service/user"
|
||||
"git.echol.cn/loser/lckt/service/vip"
|
||||
)
|
||||
|
||||
var ServiceGroupApp = new(ServiceGroup)
|
||||
@ -18,4 +19,5 @@ type ServiceGroup struct {
|
||||
BotServiceGroup bot.ServiceGroup
|
||||
ArticleGroup article.ServiceGroup
|
||||
UserServiceGroup user.ServiceGroup
|
||||
VipServiceGroup vip.ServiceGroup
|
||||
}
|
||||
|
@ -7,15 +7,21 @@ import (
|
||||
"git.echol.cn/loser/lckt/model/user"
|
||||
"git.echol.cn/loser/lckt/model/user/request"
|
||||
"git.echol.cn/loser/lckt/utils/sms"
|
||||
"github.com/ArtisanCloud/PowerSocialite/v3/src/providers"
|
||||
"go.uber.org/zap"
|
||||
"golang.org/x/crypto/bcrypt"
|
||||
"math/rand"
|
||||
"time"
|
||||
)
|
||||
|
||||
type UserService struct{}
|
||||
|
||||
func (u *UserService) GetUserById(id int) (user user.User, err error) {
|
||||
|
||||
func (u *UserService) GetUserById(id string) (user user.User, err error) {
|
||||
err = global.GVA_DB.Where("id = ?", id).First(&user).Error
|
||||
if err != nil {
|
||||
global.GVA_LOG.Error("查询用户失败", zap.Error(err))
|
||||
return
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
@ -61,7 +67,8 @@ func (u *UserService) Login(req request.CodeLoginReq) (users user.User, err erro
|
||||
// 2. 如果用户不存在,则创建用户
|
||||
if count == 0 {
|
||||
user := user.User{
|
||||
Phone: req.Phone,
|
||||
Phone: req.Phone,
|
||||
UserLabel: 1,
|
||||
}
|
||||
err = global.GVA_DB.Save(&user).Error
|
||||
if err != nil {
|
||||
@ -79,7 +86,8 @@ func (u *UserService) Login(req request.CodeLoginReq) (users user.User, err erro
|
||||
return
|
||||
}
|
||||
|
||||
func (u *UserService) GetUserList(p request.GetUserListReq) (userList user.User, total int64, err error) {
|
||||
// GetUserList 获取用户列表
|
||||
func (u *UserService) GetUserList(p request.GetUserListReq) (userList []user.User, total int64, err error) {
|
||||
limit := p.PageSize
|
||||
offset := p.PageSize * (p.Page - 1)
|
||||
// 创建db
|
||||
@ -91,6 +99,9 @@ func (u *UserService) GetUserList(p request.GetUserListReq) (userList user.User,
|
||||
if p.UserLabel != "" {
|
||||
db = db.Where("user_label = ?", p.UserLabel)
|
||||
}
|
||||
if p.Status != 0 {
|
||||
db = db.Where("status = ?", p.Status)
|
||||
}
|
||||
|
||||
err = db.Count(&total).Error
|
||||
if err != nil {
|
||||
@ -105,6 +116,7 @@ func (u *UserService) GetUserList(p request.GetUserListReq) (userList user.User,
|
||||
|
||||
}
|
||||
|
||||
// SetBalance 设置用户余额
|
||||
func (u *UserService) SetBalance(p request.SetBalanceReq) (err error) {
|
||||
err = global.GVA_DB.Model(&user.User{}).Where("id = ?", p.Id).Update("balance", p.Balance).Error
|
||||
if err != nil {
|
||||
@ -113,3 +125,119 @@ func (u *UserService) SetBalance(p request.SetBalanceReq) (err error) {
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// WechatLogin 微信登录
|
||||
func (u *UserService) WechatLogin(info *providers.User) (users user.User, err error) {
|
||||
openID := info.GetOpenID()
|
||||
var count int64
|
||||
// 1. 判断用户是否存在
|
||||
err = global.GVA_DB.Model(&users).Where("open_id = ?", openID).Count(&count).Error
|
||||
if err != nil {
|
||||
global.GVA_LOG.Error("查询用户失败", zap.Error(err))
|
||||
return
|
||||
}
|
||||
|
||||
if count == 0 {
|
||||
newUser := user.User{
|
||||
OpenId: openID,
|
||||
NickName: info.GetNickname(),
|
||||
Avatar: info.GetAvatar(),
|
||||
}
|
||||
err = global.GVA_DB.Save(&newUser).Error
|
||||
if err != nil {
|
||||
global.GVA_LOG.Error("创建用户失败", zap.Error(err))
|
||||
return
|
||||
}
|
||||
return newUser, nil
|
||||
} else {
|
||||
err = global.GVA_DB.Where("open_id = ?", openID).First(&users).Error
|
||||
if err != nil {
|
||||
global.GVA_LOG.Error("查询用户失败", zap.Error(err))
|
||||
return
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// PwdLogin 用户密码登录
|
||||
func (u *UserService) PwdLogin(req request.PwdLoginReq) (users user.User, err error) {
|
||||
// 1. 判断用户是否存在
|
||||
var count int64
|
||||
err = global.GVA_DB.Model(&user.User{}).Where("phone = ?", req.Phone).First(&users).Count(&count).Error
|
||||
if err != nil {
|
||||
global.GVA_LOG.Error("查询用户失败", zap.Error(err))
|
||||
return
|
||||
}
|
||||
if count == 0 {
|
||||
global.GVA_LOG.Error("用户不存在")
|
||||
err = fmt.Errorf("用户不存在")
|
||||
return
|
||||
}
|
||||
|
||||
// 2. 判断密码是否正确
|
||||
err = bcrypt.CompareHashAndPassword([]byte(users.Password), []byte(req.Password))
|
||||
if err != nil {
|
||||
global.GVA_LOG.Error("密码错误", zap.Error(err))
|
||||
return
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// Register 用户注册-后台用
|
||||
func (u *UserService) Register(req request.RegisterReq) (err error) {
|
||||
// 1. 判断用户是否存在
|
||||
var count int64
|
||||
err = global.GVA_DB.Model(&user.User{}).Where("phone = ?", req.Phone).Count(&count).Error
|
||||
if err != nil {
|
||||
global.GVA_LOG.Error("查询用户失败", zap.Error(err))
|
||||
return
|
||||
}
|
||||
if count == 0 {
|
||||
var password []byte
|
||||
password, err = bcrypt.GenerateFromPassword([]byte(req.Password), bcrypt.DefaultCost)
|
||||
if err != nil {
|
||||
global.GVA_LOG.Error("密码加密失败", zap.Error(err))
|
||||
return
|
||||
}
|
||||
user := user.User{
|
||||
Phone: req.Phone,
|
||||
Password: string(password),
|
||||
NickName: req.NickName,
|
||||
UserLabel: req.UserLabel,
|
||||
Status: 1,
|
||||
UserType: req.UserType,
|
||||
}
|
||||
|
||||
err = global.GVA_DB.Save(&user).Error
|
||||
if err != nil {
|
||||
global.GVA_LOG.Error("创建用户失败", zap.Error(err))
|
||||
return
|
||||
}
|
||||
return
|
||||
} else {
|
||||
err = fmt.Errorf("用户已存在")
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
// SetUserStatus 设置用户状态
|
||||
func (u *UserService) SetUserStatus(id string) (err error) {
|
||||
user := user.User{}
|
||||
|
||||
err = global.GVA_DB.Model(&user).Where("id = ?", id).First(&user).Error
|
||||
if err != nil {
|
||||
global.GVA_LOG.Error("查询用户状态失败", zap.Error(err))
|
||||
return
|
||||
}
|
||||
if user.Status == 1 {
|
||||
err = global.GVA_DB.Model(&user).Where("id = ?", id).Update("status", 0).Error
|
||||
} else {
|
||||
err = global.GVA_DB.Model(&user).Where("id = ?", id).Update("status", 1).Error
|
||||
}
|
||||
if err != nil {
|
||||
global.GVA_LOG.Error("设置用户状态失败", zap.Error(err))
|
||||
return
|
||||
}
|
||||
return
|
||||
}
|
||||
|
3
service/vip/enter.go
Normal file
3
service/vip/enter.go
Normal file
@ -0,0 +1,3 @@
|
||||
package vip
|
||||
|
||||
type ServiceGroup struct{ VipService }
|
70
service/vip/vip.go
Normal file
70
service/vip/vip.go
Normal file
@ -0,0 +1,70 @@
|
||||
package vip
|
||||
|
||||
import (
|
||||
"git.echol.cn/loser/lckt/global"
|
||||
"git.echol.cn/loser/lckt/model/common/request"
|
||||
"git.echol.cn/loser/lckt/model/vip"
|
||||
"go.uber.org/zap"
|
||||
)
|
||||
|
||||
type VipService struct{}
|
||||
|
||||
// GetVipList 获取会员列表
|
||||
func (v *VipService) GetVipList(p request.PageInfo) (vipList []vip.Vip, total int64, err error) {
|
||||
limit := p.PageSize
|
||||
offset := p.PageSize * (p.Page - 1)
|
||||
// 创建db
|
||||
db := global.GVA_DB.Model(&vip.Vip{})
|
||||
|
||||
err = db.Count(&total).Error
|
||||
if err != nil {
|
||||
global.GVA_LOG.Error("获取会员列表失败", zap.Error(err))
|
||||
return
|
||||
}
|
||||
|
||||
if limit != 0 {
|
||||
db = db.Limit(limit).Offset(offset)
|
||||
}
|
||||
err = db.Find(&vipList).Error
|
||||
if err != nil {
|
||||
global.GVA_LOG.Error("获取会员列表失败", zap.Error(err))
|
||||
return
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// CreateVip 创建会员
|
||||
func (v *VipService) CreateVip(vip vip.Vip) (err error) {
|
||||
err = global.GVA_DB.Create(&vip).Error
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// UpdateVip 更新会员
|
||||
func (v *VipService) UpdateVip(vip vip.Vip) (err error) {
|
||||
err = global.GVA_DB.Save(&vip).Error
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// DeleteVip 删除会员
|
||||
func (v *VipService) DeleteVip(vip vip.Vip) (err error) {
|
||||
err = global.GVA_DB.Delete(&vip).Error
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// GetVipById 获取会员详情
|
||||
func (v *VipService) GetVipById(id string) (vip vip.Vip, err error) {
|
||||
err = global.GVA_DB.Where("id = ?", id).First(&vip).Error
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
return
|
||||
}
|
@ -19,9 +19,9 @@ func ClearToken(c *gin.Context) {
|
||||
}
|
||||
|
||||
if net.ParseIP(host) != nil {
|
||||
c.SetCookie("app-token", "", -1, "/", "", false, false)
|
||||
c.SetCookie("x-token", "", -1, "/", "", false, false)
|
||||
} else {
|
||||
c.SetCookie("app-token", "", -1, "/", host, false, false)
|
||||
c.SetCookie("x-token", "", -1, "/", host, false, false)
|
||||
}
|
||||
}
|
||||
|
||||
@ -33,17 +33,17 @@ func SetToken(c *gin.Context, token string, maxAge int) {
|
||||
}
|
||||
|
||||
if net.ParseIP(host) != nil {
|
||||
c.SetCookie("app-token", token, maxAge, "/", "", false, false)
|
||||
c.SetCookie("x-token", token, maxAge, "/", "", false, false)
|
||||
} else {
|
||||
c.SetCookie("app-token", token, maxAge, "/", host, false, false)
|
||||
c.SetCookie("x-token", token, maxAge, "/", host, false, false)
|
||||
}
|
||||
}
|
||||
|
||||
func GetToken(c *gin.Context) string {
|
||||
token := c.Request.Header.Get("app-token")
|
||||
token := c.Request.Header.Get("x-token")
|
||||
if token == "" {
|
||||
j := NewJWT()
|
||||
token, _ = c.Cookie("app-token")
|
||||
token, _ = c.Cookie("x-token")
|
||||
claims, err := j.ParseToken(token)
|
||||
if err != nil {
|
||||
global.GVA_LOG.Error("重新写入cookie token失败,未能成功解析token,请检查请求头是否存在x-token且claims是否为规定结构")
|
||||
|
@ -12,41 +12,41 @@ import (
|
||||
)
|
||||
|
||||
func ClearToken(c *gin.Context) {
|
||||
// 增加cookie app-token 向来源的web添加
|
||||
// 增加cookie Authorization 向来源的web添加
|
||||
host, _, err := net.SplitHostPort(c.Request.Host)
|
||||
if err != nil {
|
||||
host = c.Request.Host
|
||||
}
|
||||
|
||||
if net.ParseIP(host) != nil {
|
||||
c.SetCookie("app-token", "", -1, "/", "", false, false)
|
||||
c.SetCookie("Authorization", "", -1, "/", "", false, false)
|
||||
} else {
|
||||
c.SetCookie("app-token", "", -1, "/", host, false, false)
|
||||
c.SetCookie("Authorization", "", -1, "/", host, false, false)
|
||||
}
|
||||
}
|
||||
|
||||
func SetToken(c *gin.Context, token string, maxAge int) {
|
||||
// 增加cookie app-token 向来源的web添加
|
||||
// 增加cookie Authorization 向来源的web添加
|
||||
host, _, err := net.SplitHostPort(c.Request.Host)
|
||||
if err != nil {
|
||||
host = c.Request.Host
|
||||
}
|
||||
|
||||
if net.ParseIP(host) != nil {
|
||||
c.SetCookie("app-token", token, maxAge, "/", "", false, false)
|
||||
c.SetCookie("Authorization", token, maxAge, "/", "", false, false)
|
||||
} else {
|
||||
c.SetCookie("app-token", token, maxAge, "/", host, false, false)
|
||||
c.SetCookie("Authorization", token, maxAge, "/", host, false, false)
|
||||
}
|
||||
}
|
||||
|
||||
func GetToken(c *gin.Context) string {
|
||||
token := c.Request.Header.Get("app-token")
|
||||
token := c.Request.Header.Get("Authorization")
|
||||
if token == "" {
|
||||
j := NewUserJWT()
|
||||
token, _ = c.Cookie("app-token")
|
||||
token, _ = c.Cookie("Authorization")
|
||||
claims, err := j.ParseToken(token)
|
||||
if err != nil {
|
||||
global.GVA_LOG.Error("重新写入cookie token失败,未能成功解析token,请检查请求头是否存在app-token且claims是否为规定结构")
|
||||
global.GVA_LOG.Error("重新写入cookie token失败,未能成功解析token,请检查请求头是否存在Authorization且claims是否为规定结构")
|
||||
return token
|
||||
}
|
||||
SetToken(c, token, int((claims.ExpiresAt.Unix()-time.Now().Unix())/60))
|
||||
@ -59,7 +59,7 @@ func GetClaims(c *gin.Context) (*systemReq.CustomClaims, error) {
|
||||
j := NewUserJWT()
|
||||
claims, err := j.ParseToken(token)
|
||||
if err != nil {
|
||||
global.GVA_LOG.Error("从Gin的Context中获取从jwt解析信息失败, 请检查请求头是否存在app-token且claims是否为规定结构")
|
||||
global.GVA_LOG.Error("从Gin的Context中获取从jwt解析信息失败, 请检查请求头是否存在Authorization且claims是否为规定结构")
|
||||
}
|
||||
return claims, err
|
||||
}
|
||||
|
@ -1,9 +1,12 @@
|
||||
package initialize
|
||||
package wechat
|
||||
|
||||
import (
|
||||
"git.echol.cn/loser/lckt/global"
|
||||
"github.com/ArtisanCloud/PowerSocialite/v3/src/providers"
|
||||
"github.com/ArtisanCloud/PowerWeChat/v3/src/kernel"
|
||||
"github.com/ArtisanCloud/PowerWeChat/v3/src/officialAccount"
|
||||
"github.com/ArtisanCloud/PowerWeChat/v3/src/payment"
|
||||
"go.uber.org/zap"
|
||||
"log"
|
||||
)
|
||||
|
||||
@ -13,8 +16,8 @@ var WechatPay *payment.Payment
|
||||
// InitWeOfficial 初始化微信公众号
|
||||
func InitWeOfficial() {
|
||||
OfficialAccountApp, err := officialAccount.NewOfficialAccount(&officialAccount.UserConfig{
|
||||
AppID: "[appid]", // 公众号、小程序的appid
|
||||
Secret: "[app secret]", //
|
||||
AppID: "wx3d21df18d7f8f9fc", // 公众号、小程序的appid
|
||||
Secret: "ffce59a9a9272c1aaee53950e96617d8", //
|
||||
|
||||
Log: officialAccount.Log{
|
||||
Level: "debug",
|
||||
@ -25,7 +28,7 @@ func InitWeOfficial() {
|
||||
},
|
||||
|
||||
HttpDebug: true,
|
||||
Debug: false,
|
||||
Debug: true,
|
||||
})
|
||||
|
||||
if err != nil {
|
||||
@ -70,3 +73,12 @@ func InitWechatPay() {
|
||||
}
|
||||
WechatPay = PaymentService
|
||||
}
|
||||
|
||||
func GetUserInfo(code string) *providers.User {
|
||||
userFromCode, err := WeOfficial.OAuth.UserFromCode(code)
|
||||
if err != nil {
|
||||
global.GVA_LOG.Error("通过code获取微信用户信息失败", zap.Error(err))
|
||||
return nil
|
||||
}
|
||||
return userFromCode
|
||||
}
|
Loading…
Reference in New Issue
Block a user