package auth import ( "context" "fmt" "time" "git.i2edu.net/i2/go-zero/core/logx" "git.i2edu.net/i2/go-zero/core/stores/sqlc" "git.i2edu.net/i2/go-zero/core/stores/sqlx" "git.i2edu.net/i2/i2-bill-api/internal/svc" "git.i2edu.net/i2/i2-bill-api/internal/types" "git.i2edu.net/i2/i2-bill-api/internal/utils" "git.i2edu.net/i2/i2-bill-api/model" "github.com/dgrijalva/jwt-go" ) type LoginByWeixinLogic struct { logx.Logger ctx context.Context svcCtx *svc.ServiceContext } func NewLoginByWeixinLogic(ctx context.Context, svcCtx *svc.ServiceContext) LoginByWeixinLogic { return LoginByWeixinLogic{ Logger: logx.WithContext(ctx), ctx: ctx, svcCtx: svcCtx, } } func (l *LoginByWeixinLogic) LoginByWeixin(req types.LoginByWeixinRequest) (*types.LoginByWeixinResponse, error) { alb, rtnInfo := req, types.LoginByWeixinResponse{} userInfo, err := l.Login(alb.Code) if err != nil { logx.Error(err) return nil, err } err = l.svcCtx.SqlConn.Transact(func(session sqlx.Session) error { var user model.User err := session.QueryRowPartial(&user, fmt.Sprintf("select %s from i2bill_user where `weixin_openid` = ? limit 1", model.UserRows), userInfo.OpenID) if err == sqlc.ErrNotFound { user.Username = utils.GetUUID() user.Password = "" user.RegisterTime = utils.GetTimestamp() user.RegisterIp = "" user.Mobile = "" user.WeixinOpenid = userInfo.OpenID user.Avatar = userInfo.AvatarUrl user.Gender = userInfo.Gender user.Nickname = userInfo.NickName _, err = session.Exec(`insert into i2bill_user (%s) values ( mobile, avatar, weixin_openid, password, birthday, register_time, last_login_time, nickname, erp_id, username, gender, user_level_id, register_ip, last_login_ip )`, user.Mobile, user.Avatar, user.WeixinOpenid, user.Password, user.Birthday, user.RegisterTime, user.LastLoginTime, user.Nickname, user.ErpId, user.Username, user.Gender, user.UserLevelId, user.RegisterIp, user.LastLoginIp) if err != nil { logx.Error(err) return err } err = session.QueryRowPartial(&user, fmt.Sprintf("select %s from i2bill_user where `weixin_openid` = ? limit 1", model.UserRows), userInfo.OpenID) if err != nil { logx.Error(err) return err } } rtnInfo.UserInfo.ID = user.Id rtnInfo.UserInfo.UserName = user.Username rtnInfo.UserInfo.NickName = user.Nickname rtnInfo.UserInfo.Mobile = user.Mobile rtnInfo.UserInfo.Gender = user.Gender rtnInfo.UserInfo.Avatar = user.Avatar rtnInfo.UserInfo.Birthday = user.Birthday user.LastLoginIp = "" user.LastLoginTime = utils.GetTimestamp() _, err = session.Exec(`update i2bill_user set mobile = ?, avatar = ?, weixin_openid = ?, password = ?, birthday = ?, register_time = ?, last_login_time = ?, nickname = ?, erp_id = ?, username = ?, gender = ?, user_level_id = ?, register_ip = ?, last_login_ip = ? where id = ?`, user.Mobile, user.Avatar, user.WeixinOpenid, user.Password, user.Birthday, user.RegisterTime, user.LastLoginTime, user.Nickname, user.ErpId, user.Username, user.Gender, user.UserLevelId, user.RegisterIp, user.LastLoginIp, user.Id) if err != nil { logx.Error(err) return err } return nil }) if err != nil { return nil, err } var accessExpire = l.svcCtx.Config.JwtAuth.AccessExpire now := time.Now().Unix() payloads := map[string]interface{}{ "userId": rtnInfo.UserInfo.ID, "sessionKey": userInfo.SessionKey, } accessToken, err := l.CreateJWT(now, l.svcCtx.Config.JwtAuth.AccessSecret, payloads, accessExpire) if err != nil { logx.Error(err) return nil, err } rtnInfo.Token = accessToken return &rtnInfo, nil } func (l *LoginByWeixinLogic) CreateJWT(iat int64, secretKey string, payloads map[string]interface{}, seconds int64) (string, error) { claims := make(jwt.MapClaims) claims["exp"] = iat + seconds claims["iat"] = iat for k, v := range payloads { claims[k] = v } token := jwt.New(jwt.SigningMethodHS256) token.Claims = claims return token.SignedString([]byte(secretKey)) } func (l *LoginByWeixinLogic) Login(code string) (*types.WXUserInfo, error) { secret := l.svcCtx.Config.Weixin.Secret appid := l.svcCtx.Config.Weixin.Appid req := utils.Get("https://api.weixin.qq.com/sns/jscode2session") req.Param("grant_type", "authorization_code") req.Param("js_code", code) req.Param("secret", secret) req.Param("appid", appid) var res types.WXLoginResponse req.ToJSON(&res) userinfo, err := l.DecryptUserInfoData(res.SessionKey) userinfo.OpenID = res.OpenID userinfo.SessionKey = res.SessionKey return userinfo, err } func (l *LoginByWeixinLogic) DecryptUserInfoData(sessionKey string) (*types.WXUserInfo, error) { var wxuserinfo types.WXUserInfo return &wxuserinfo, nil }