diff --git a/app/user/cmd/api/internal/logic/user/wxh5authlogic.go b/app/user/cmd/api/internal/logic/user/wxh5authlogic.go index 420f238..ce2cd9f 100644 --- a/app/user/cmd/api/internal/logic/user/wxh5authlogic.go +++ b/app/user/cmd/api/internal/logic/user/wxh5authlogic.go @@ -11,6 +11,7 @@ import ( "time" "tydata-server/app/user/model" jwtx "tydata-server/common/jwt" + "tydata-server/common/xerr" "tydata-server/app/user/cmd/api/internal/svc" "tydata-server/app/user/cmd/api/internal/types" @@ -36,13 +37,13 @@ func (l *WxH5AuthLogic) WxH5Auth(req *types.WXH5AuthReq) (resp *types.WXH5AuthRe // Step 1: 使用code获取access_token accessTokenResp, err := GetAccessToken(req.Code) if err != nil { - return nil, errors.Wrap(err, "获取access_token失败") + return nil, errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "获取access_token失败: %+v", err) } // Step 2: 查找用户授权信息 - userAuth, findErr := l.svcCtx.UserAuthModel.FindOneByAuthTypeAuthKey(l.ctx, accessTokenResp.Openid, "h5-weixin") + userAuth, findErr := l.svcCtx.UserAuthModel.FindOneByAuthTypeAuthKey(l.ctx, accessTokenResp.Openid, model.UserAuthTypeWxh5) if findErr != nil && !errors.Is(findErr, model.ErrNotFound) { - return nil, errors.Wrapf(findErr, "查询用户授权失败,openid: %s", accessTokenResp.Openid) + return nil, errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "查询用户授权失败,findErr: %v", findErr) } // Step 3: 查找或创建用户 @@ -51,12 +52,13 @@ func (l *WxH5AuthLogic) WxH5Auth(req *types.WXH5AuthReq) (resp *types.WXH5AuthRe // 授权信息存在,查找用户 userModel, findUserErr := l.svcCtx.UserModel.FindOne(l.ctx, userAuth.UserId) if findUserErr != nil { - return nil, errors.Wrapf(findUserErr, "查询用户失败,userId: %d", userAuth.UserId) + return nil, errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "查询用户失败,userId: %v", findUserErr) } user = userModel } else { // 授权信息不存在,创建新用户 user = &model.User{} + user.Mobile = accessTokenResp.Openid if transErr := l.svcCtx.UserModel.Trans(l.ctx, func(context context.Context, session sqlx.Session) error { // 插入数据库 insertResult, insertErr := l.svcCtx.UserModel.Insert(l.ctx, session, user) @@ -73,22 +75,21 @@ func (l *WxH5AuthLogic) WxH5Auth(req *types.WXH5AuthReq) (resp *types.WXH5AuthRe userAuth = &model.UserAuth{ UserId: user.Id, AuthKey: accessTokenResp.Openid, - AuthType: "mp-weixin", // 微信小程序 + AuthType: model.UserAuthTypeWxh5, // 微信小程序 } if _, insertUserAuthErr := l.svcCtx.UserAuthModel.Insert(l.ctx, session, userAuth); insertUserAuthErr != nil { return errors.Wrapf(insertUserAuthErr, "创建用户授权失败,openid: %s", accessTokenResp.Openid) } return nil }); transErr != nil { - return nil, transErr + return nil, errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "创建新用户事务失败: %v", transErr) } - } // Step 4: 生成JWT Token token, genErr := jwtx.GenerateJwtToken(user.Id, l.svcCtx.Config.JwtAuth.AccessSecret, l.svcCtx.Config.JwtAuth.AccessExpire) if genErr != nil { - return nil, errors.Wrap(genErr, "生成JWT token失败") + return nil, errors.Wrapf(xerr.NewErrCode(xerr.DB_ERROR), "生成JWT token失败: %v", genErr) } now := time.Now().Unix() @@ -106,8 +107,8 @@ type AccessTokenResp struct { // GetAccessToken 通过code获取access_token func GetAccessToken(code string) (*AccessTokenResp, error) { - appID := "wxd1554b7a57cecc9e" - appSecret := "fb8026c0bc66625b580453300d4b43db" + appID := "wxa581992dc74d860e" + appSecret := "cfca484cf8cebcccb1f16fbaf1d9fe2c" url := fmt.Sprintf("https://api.weixin.qq.com/sns/oauth2/access_token?appid=%s&secret=%s&code=%s&grant_type=authorization_code", appID, appSecret, code) diff --git a/app/user/model/userModel_gen.go b/app/user/model/userModel_gen.go index 782c385..7fc5381 100644 --- a/app/user/model/userModel_gen.go +++ b/app/user/model/userModel_gen.go @@ -7,7 +7,6 @@ import ( "database/sql" "fmt" "strings" - model2 "tydata-server/deploy/script/model" "time" @@ -102,7 +101,7 @@ func (m *defaultUserModel) FindOne(ctx context.Context, id int64) (*User, error) case nil: return &resp, nil case sqlc.ErrNotFound: - return nil, model2.ErrNotFound + return nil, ErrNotFound default: return nil, err } @@ -122,7 +121,7 @@ func (m *defaultUserModel) FindOneByMobile(ctx context.Context, mobile string) ( case nil: return &resp, nil case sqlc.ErrNotFound: - return nil, model2.ErrNotFound + return nil, ErrNotFound default: return nil, err } @@ -173,7 +172,7 @@ func (m *defaultUserModel) UpdateWithVersion(ctx context.Context, session sqlx.S return err } if updateCount == 0 { - return model2.ErrNoRowsUpdate + return ErrNoRowsUpdate } return nil diff --git a/app/user/model/vars.go b/app/user/model/vars.go index 4723f1b..23cf6f0 100644 --- a/app/user/model/vars.go +++ b/app/user/model/vars.go @@ -12,4 +12,4 @@ var UserAuthTypeAppMobile string = "app_mobile" //平台内部 var UserAuthTypeAppWechat string = "app_wechat" //微信小程序 var UserAuthTypeH5Mobile string = "h5_mobile" var UserAuthTypeWxMini string = "wx_mini" -var UserAuthTypeWxOfficialAccount string = "wx_official_account" +var UserAuthTypeWxh5 string = "wx_h5" diff --git a/deploy/script/model/userModel.go b/deploy/script/model/userModel.go new file mode 100644 index 0000000..8123712 --- /dev/null +++ b/deploy/script/model/userModel.go @@ -0,0 +1,27 @@ +package model + +import ( + "github.com/zeromicro/go-zero/core/stores/cache" + "github.com/zeromicro/go-zero/core/stores/sqlx" +) + +var _ UserModel = (*customUserModel)(nil) + +type ( + // UserModel is an interface to be customized, add more methods here, + // and implement the added methods in customUserModel. + UserModel interface { + userModel + } + + customUserModel struct { + *defaultUserModel + } +) + +// NewUserModel returns a model for the database table. +func NewUserModel(conn sqlx.SqlConn, c cache.CacheConf) UserModel { + return &customUserModel{ + defaultUserModel: newUserModel(conn, c), + } +} diff --git a/deploy/script/model/userModel_gen.go b/deploy/script/model/userModel_gen.go new file mode 100644 index 0000000..7fc5381 --- /dev/null +++ b/deploy/script/model/userModel_gen.go @@ -0,0 +1,410 @@ +// Code generated by goctl. DO NOT EDIT! + +package model + +import ( + "context" + "database/sql" + "fmt" + "strings" + + "time" + + "github.com/Masterminds/squirrel" + "github.com/pkg/errors" + "github.com/zeromicro/go-zero/core/stores/builder" + "github.com/zeromicro/go-zero/core/stores/cache" + "github.com/zeromicro/go-zero/core/stores/sqlc" + "github.com/zeromicro/go-zero/core/stores/sqlx" + "github.com/zeromicro/go-zero/core/stringx" + "tydata-server/common/globalkey" +) + +var ( + userFieldNames = builder.RawFieldNames(&User{}) + userRows = strings.Join(userFieldNames, ",") + userRowsExpectAutoSet = strings.Join(stringx.Remove(userFieldNames, "`id`", "`create_time`", "`update_time`"), ",") + userRowsWithPlaceHolder = strings.Join(stringx.Remove(userFieldNames, "`id`", "`create_time`", "`update_time`"), "=?,") + "=?" + + cacheTydataUserIdPrefix = "cache:tydata:user:id:" + cacheTydataUserMobilePrefix = "cache:tydata:user:mobile:" +) + +type ( + userModel interface { + Insert(ctx context.Context, session sqlx.Session, data *User) (sql.Result, error) + FindOne(ctx context.Context, id int64) (*User, error) + FindOneByMobile(ctx context.Context, mobile string) (*User, error) + Update(ctx context.Context, session sqlx.Session, data *User) (sql.Result, error) + UpdateWithVersion(ctx context.Context, session sqlx.Session, data *User) error + Trans(ctx context.Context, fn func(context context.Context, session sqlx.Session) error) error + SelectBuilder() squirrel.SelectBuilder + DeleteSoft(ctx context.Context, session sqlx.Session, data *User) error + FindSum(ctx context.Context, sumBuilder squirrel.SelectBuilder, field string) (float64, error) + FindCount(ctx context.Context, countBuilder squirrel.SelectBuilder, field string) (int64, error) + FindAll(ctx context.Context, rowBuilder squirrel.SelectBuilder, orderBy string) ([]*User, error) + FindPageListByPage(ctx context.Context, rowBuilder squirrel.SelectBuilder, page, pageSize int64, orderBy string) ([]*User, error) + FindPageListByPageWithTotal(ctx context.Context, rowBuilder squirrel.SelectBuilder, page, pageSize int64, orderBy string) ([]*User, int64, error) + FindPageListByIdDESC(ctx context.Context, rowBuilder squirrel.SelectBuilder, preMinId, pageSize int64) ([]*User, error) + FindPageListByIdASC(ctx context.Context, rowBuilder squirrel.SelectBuilder, preMaxId, pageSize int64) ([]*User, error) + Delete(ctx context.Context, session sqlx.Session, id int64) error + } + + defaultUserModel struct { + sqlc.CachedConn + table string + } + + User struct { + Id int64 `db:"id"` + CreateTime time.Time `db:"create_time"` + UpdateTime time.Time `db:"update_time"` + DeleteTime sql.NullTime `db:"delete_time"` // 删除时间 + DelState int64 `db:"del_state"` + Version int64 `db:"version"` // 版本号 + Mobile string `db:"mobile"` + Password sql.NullString `db:"password"` + Nickname string `db:"nickname"` + Info string `db:"info"` + Inside int64 `db:"inside"` + } +) + +func newUserModel(conn sqlx.SqlConn, c cache.CacheConf) *defaultUserModel { + return &defaultUserModel{ + CachedConn: sqlc.NewConn(conn, c), + table: "`user`", + } +} + +func (m *defaultUserModel) Insert(ctx context.Context, session sqlx.Session, data *User) (sql.Result, error) { + data.DelState = globalkey.DelStateNo + tydataUserIdKey := fmt.Sprintf("%s%v", cacheTydataUserIdPrefix, data.Id) + tydataUserMobileKey := fmt.Sprintf("%s%v", cacheTydataUserMobilePrefix, data.Mobile) + return m.ExecCtx(ctx, func(ctx context.Context, conn sqlx.SqlConn) (result sql.Result, err error) { + query := fmt.Sprintf("insert into %s (%s) values (?, ?, ?, ?, ?, ?, ?, ?)", m.table, userRowsExpectAutoSet) + if session != nil { + return session.ExecCtx(ctx, query, data.DeleteTime, data.DelState, data.Version, data.Mobile, data.Password, data.Nickname, data.Info, data.Inside) + } + return conn.ExecCtx(ctx, query, data.DeleteTime, data.DelState, data.Version, data.Mobile, data.Password, data.Nickname, data.Info, data.Inside) + }, tydataUserIdKey, tydataUserMobileKey) +} + +func (m *defaultUserModel) FindOne(ctx context.Context, id int64) (*User, error) { + tydataUserIdKey := fmt.Sprintf("%s%v", cacheTydataUserIdPrefix, id) + var resp User + err := m.QueryRowCtx(ctx, &resp, tydataUserIdKey, func(ctx context.Context, conn sqlx.SqlConn, v interface{}) error { + query := fmt.Sprintf("select %s from %s where `id` = ? and del_state = ? limit 1", userRows, m.table) + return conn.QueryRowCtx(ctx, v, query, id, globalkey.DelStateNo) + }) + switch err { + case nil: + return &resp, nil + case sqlc.ErrNotFound: + return nil, ErrNotFound + default: + return nil, err + } +} + +func (m *defaultUserModel) FindOneByMobile(ctx context.Context, mobile string) (*User, error) { + tydataUserMobileKey := fmt.Sprintf("%s%v", cacheTydataUserMobilePrefix, mobile) + var resp User + err := m.QueryRowIndexCtx(ctx, &resp, tydataUserMobileKey, m.formatPrimary, func(ctx context.Context, conn sqlx.SqlConn, v interface{}) (i interface{}, e error) { + query := fmt.Sprintf("select %s from %s where `mobile` = ? and del_state = ? limit 1", userRows, m.table) + if err := conn.QueryRowCtx(ctx, &resp, query, mobile, globalkey.DelStateNo); err != nil { + return nil, err + } + return resp.Id, nil + }, m.queryPrimary) + switch err { + case nil: + return &resp, nil + case sqlc.ErrNotFound: + return nil, ErrNotFound + default: + return nil, err + } +} + +func (m *defaultUserModel) Update(ctx context.Context, session sqlx.Session, newData *User) (sql.Result, error) { + data, err := m.FindOne(ctx, newData.Id) + if err != nil { + return nil, err + } + tydataUserIdKey := fmt.Sprintf("%s%v", cacheTydataUserIdPrefix, data.Id) + tydataUserMobileKey := fmt.Sprintf("%s%v", cacheTydataUserMobilePrefix, data.Mobile) + return m.ExecCtx(ctx, func(ctx context.Context, conn sqlx.SqlConn) (result sql.Result, err error) { + query := fmt.Sprintf("update %s set %s where `id` = ?", m.table, userRowsWithPlaceHolder) + if session != nil { + return session.ExecCtx(ctx, query, newData.DeleteTime, newData.DelState, newData.Version, newData.Mobile, newData.Password, newData.Nickname, newData.Info, newData.Inside, newData.Id) + } + return conn.ExecCtx(ctx, query, newData.DeleteTime, newData.DelState, newData.Version, newData.Mobile, newData.Password, newData.Nickname, newData.Info, newData.Inside, newData.Id) + }, tydataUserIdKey, tydataUserMobileKey) +} + +func (m *defaultUserModel) UpdateWithVersion(ctx context.Context, session sqlx.Session, newData *User) error { + + oldVersion := newData.Version + newData.Version += 1 + + var sqlResult sql.Result + var err error + + data, err := m.FindOne(ctx, newData.Id) + if err != nil { + return err + } + tydataUserIdKey := fmt.Sprintf("%s%v", cacheTydataUserIdPrefix, data.Id) + tydataUserMobileKey := fmt.Sprintf("%s%v", cacheTydataUserMobilePrefix, data.Mobile) + sqlResult, err = m.ExecCtx(ctx, func(ctx context.Context, conn sqlx.SqlConn) (result sql.Result, err error) { + query := fmt.Sprintf("update %s set %s where `id` = ? and version = ? ", m.table, userRowsWithPlaceHolder) + if session != nil { + return session.ExecCtx(ctx, query, newData.DeleteTime, newData.DelState, newData.Version, newData.Mobile, newData.Password, newData.Nickname, newData.Info, newData.Inside, newData.Id, oldVersion) + } + return conn.ExecCtx(ctx, query, newData.DeleteTime, newData.DelState, newData.Version, newData.Mobile, newData.Password, newData.Nickname, newData.Info, newData.Inside, newData.Id, oldVersion) + }, tydataUserIdKey, tydataUserMobileKey) + if err != nil { + return err + } + updateCount, err := sqlResult.RowsAffected() + if err != nil { + return err + } + if updateCount == 0 { + return ErrNoRowsUpdate + } + + return nil +} + +func (m *defaultUserModel) DeleteSoft(ctx context.Context, session sqlx.Session, data *User) error { + data.DelState = globalkey.DelStateYes + data.DeleteTime = sql.NullTime{Time: time.Now(), Valid: true} + if err := m.UpdateWithVersion(ctx, session, data); err != nil { + return errors.Wrapf(errors.New("delete soft failed "), "UserModel delete err : %+v", err) + } + return nil +} + +func (m *defaultUserModel) FindSum(ctx context.Context, builder squirrel.SelectBuilder, field string) (float64, error) { + + if len(field) == 0 { + return 0, errors.Wrapf(errors.New("FindSum Least One Field"), "FindSum Least One Field") + } + + builder = builder.Columns("IFNULL(SUM(" + field + "),0)") + + query, values, err := builder.Where("del_state = ?", globalkey.DelStateNo).ToSql() + if err != nil { + return 0, err + } + + var resp float64 + err = m.QueryRowNoCacheCtx(ctx, &resp, query, values...) + switch err { + case nil: + return resp, nil + default: + return 0, err + } +} + +func (m *defaultUserModel) FindCount(ctx context.Context, builder squirrel.SelectBuilder, field string) (int64, error) { + + if len(field) == 0 { + return 0, errors.Wrapf(errors.New("FindCount Least One Field"), "FindCount Least One Field") + } + + builder = builder.Columns("COUNT(" + field + ")") + + query, values, err := builder.Where("del_state = ?", globalkey.DelStateNo).ToSql() + if err != nil { + return 0, err + } + + var resp int64 + err = m.QueryRowNoCacheCtx(ctx, &resp, query, values...) + switch err { + case nil: + return resp, nil + default: + return 0, err + } +} + +func (m *defaultUserModel) FindAll(ctx context.Context, builder squirrel.SelectBuilder, orderBy string) ([]*User, error) { + + builder = builder.Columns(userRows) + + if orderBy == "" { + builder = builder.OrderBy("id DESC") + } else { + builder = builder.OrderBy(orderBy) + } + + query, values, err := builder.Where("del_state = ?", globalkey.DelStateNo).ToSql() + if err != nil { + return nil, err + } + + var resp []*User + err = m.QueryRowsNoCacheCtx(ctx, &resp, query, values...) + switch err { + case nil: + return resp, nil + default: + return nil, err + } +} + +func (m *defaultUserModel) FindPageListByPage(ctx context.Context, builder squirrel.SelectBuilder, page, pageSize int64, orderBy string) ([]*User, error) { + + builder = builder.Columns(userRows) + + if orderBy == "" { + builder = builder.OrderBy("id DESC") + } else { + builder = builder.OrderBy(orderBy) + } + + if page < 1 { + page = 1 + } + offset := (page - 1) * pageSize + + query, values, err := builder.Where("del_state = ?", globalkey.DelStateNo).Offset(uint64(offset)).Limit(uint64(pageSize)).ToSql() + if err != nil { + return nil, err + } + + var resp []*User + err = m.QueryRowsNoCacheCtx(ctx, &resp, query, values...) + switch err { + case nil: + return resp, nil + default: + return nil, err + } +} + +func (m *defaultUserModel) FindPageListByPageWithTotal(ctx context.Context, builder squirrel.SelectBuilder, page, pageSize int64, orderBy string) ([]*User, int64, error) { + + total, err := m.FindCount(ctx, builder, "id") + if err != nil { + return nil, 0, err + } + + builder = builder.Columns(userRows) + + if orderBy == "" { + builder = builder.OrderBy("id DESC") + } else { + builder = builder.OrderBy(orderBy) + } + + if page < 1 { + page = 1 + } + offset := (page - 1) * pageSize + + query, values, err := builder.Where("del_state = ?", globalkey.DelStateNo).Offset(uint64(offset)).Limit(uint64(pageSize)).ToSql() + if err != nil { + return nil, total, err + } + + var resp []*User + err = m.QueryRowsNoCacheCtx(ctx, &resp, query, values...) + switch err { + case nil: + return resp, total, nil + default: + return nil, total, err + } +} + +func (m *defaultUserModel) FindPageListByIdDESC(ctx context.Context, builder squirrel.SelectBuilder, preMinId, pageSize int64) ([]*User, error) { + + builder = builder.Columns(userRows) + + if preMinId > 0 { + builder = builder.Where(" id < ? ", preMinId) + } + + query, values, err := builder.Where("del_state = ?", globalkey.DelStateNo).OrderBy("id DESC").Limit(uint64(pageSize)).ToSql() + if err != nil { + return nil, err + } + + var resp []*User + err = m.QueryRowsNoCacheCtx(ctx, &resp, query, values...) + switch err { + case nil: + return resp, nil + default: + return nil, err + } +} + +func (m *defaultUserModel) FindPageListByIdASC(ctx context.Context, builder squirrel.SelectBuilder, preMaxId, pageSize int64) ([]*User, error) { + + builder = builder.Columns(userRows) + + if preMaxId > 0 { + builder = builder.Where(" id > ? ", preMaxId) + } + + query, values, err := builder.Where("del_state = ?", globalkey.DelStateNo).OrderBy("id ASC").Limit(uint64(pageSize)).ToSql() + if err != nil { + return nil, err + } + + var resp []*User + err = m.QueryRowsNoCacheCtx(ctx, &resp, query, values...) + switch err { + case nil: + return resp, nil + default: + return nil, err + } +} + +func (m *defaultUserModel) Trans(ctx context.Context, fn func(ctx context.Context, session sqlx.Session) error) error { + + return m.TransactCtx(ctx, func(ctx context.Context, session sqlx.Session) error { + return fn(ctx, session) + }) + +} + +func (m *defaultUserModel) SelectBuilder() squirrel.SelectBuilder { + return squirrel.Select().From(m.table) +} +func (m *defaultUserModel) Delete(ctx context.Context, session sqlx.Session, id int64) error { + data, err := m.FindOne(ctx, id) + if err != nil { + return err + } + + tydataUserIdKey := fmt.Sprintf("%s%v", cacheTydataUserIdPrefix, id) + tydataUserMobileKey := fmt.Sprintf("%s%v", cacheTydataUserMobilePrefix, data.Mobile) + _, err = m.ExecCtx(ctx, func(ctx context.Context, conn sqlx.SqlConn) (result sql.Result, err error) { + query := fmt.Sprintf("delete from %s where `id` = ?", m.table) + if session != nil { + return session.ExecCtx(ctx, query, id) + } + return conn.ExecCtx(ctx, query, id) + }, tydataUserIdKey, tydataUserMobileKey) + return err +} +func (m *defaultUserModel) formatPrimary(primary interface{}) string { + return fmt.Sprintf("%s%v", cacheTydataUserIdPrefix, primary) +} +func (m *defaultUserModel) queryPrimary(ctx context.Context, conn sqlx.SqlConn, v, primary interface{}) error { + query := fmt.Sprintf("select %s from %s where `id` = ? and del_state = ? limit 1", userRows, m.table) + return conn.QueryRowCtx(ctx, v, query, primary, globalkey.DelStateNo) +} + +func (m *defaultUserModel) tableName() string { + return m.table +}