package logic import ( "context" "crypto/sha1" "encoding/base64" "encoding/hex" "encoding/json" "errors" "fmt" "time" "git.i2edu.net/i2/go-zero/core/logx" "git.i2edu.net/i2/go-zero/core/stores/sqlc" "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" "git.i2edu.net/i2/i2-bill-erp/transformclient" "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.AuthLoginBody) (*types.AuthResponse, error) { alb := req userInfo, err := l.Login(alb.Code, alb.UserInfo) if err != nil { return nil, err } // resp, err := l.svcCtx.Transformer.GetUser(l.ctx, &transformclient.Request{ Id: "0909", }) if err != nil { return nil, err } fmt.Println(resp.Roles) user, err := l.svcCtx.UserModel.FindOneByWeiXinOpenId(userInfo.OpenID) if err == sqlc.ErrNotFound { newuser := model.User{Username: utils.GetUUID(), Password: "", RegisterTime: utils.GetTimestamp(), RegisterIp: "", Mobile: "", WeixinOpenid: userInfo.OpenID, Avatar: userInfo.AvatarUrl, Gender: userInfo.Gender, Nickname: userInfo.NickName} l.svcCtx.UserModel.Insert(newuser) user, _ = l.svcCtx.UserModel.FindOneByWeiXinOpenId(userInfo.OpenID) } rtnInfo := types.AuthResponse{} rtnInfo.UserInfo.ID = user.Id rtnInfo.UserInfo.UserName = user.Username rtnInfo.UserInfo.NickName = user.Nickname rtnInfo.UserInfo.Gender = user.Gender rtnInfo.UserInfo.Avatar = user.Avatar rtnInfo.UserInfo.Birthday = user.Birthday user.LastLoginIp = "" user.LastLoginTime = utils.GetTimestamp() if err := l.svcCtx.UserModel.Update(*user); err == nil { return nil, err } var accessExpire = l.svcCtx.Config.JwtAuth.AccessExpire now := time.Now().Unix() payloads := map[string]interface{}{ "user_id": user.Id, } accessToken, err := l.CreateJWT(now, l.svcCtx.Config.JwtAuth.AccessSecret, payloads, accessExpire) if err != nil { 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, fullUserInfo types.ResUserInfo) (*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) s := sha1.New() s.Write([]byte(fullUserInfo.RawData + res.SessionKey)) sha1 := s.Sum(nil) sha1hash := hex.EncodeToString(sha1) if fullUserInfo.Signature != sha1hash { return nil, errors.New("signature err") } userinfo, err := l.DecryptUserInfoData(res.SessionKey, fullUserInfo.EncryptedData, fullUserInfo.IV) return userinfo, err } func (l *LoginByWeixinLogic) DecryptUserInfoData(sessionKey string, encryptedData string, iv string) (*types.WXUserInfo, error) { sk, _ := base64.StdEncoding.DecodeString(sessionKey) ed, _ := base64.StdEncoding.DecodeString(encryptedData) i, _ := base64.StdEncoding.DecodeString(iv) decryptedData, err := utils.AesCBCDecrypt(ed, sk, i) if err != nil { return nil, err } var wxuserinfo types.WXUserInfo err = json.Unmarshal(decryptedData, &wxuserinfo) if err != nil { return nil, err } return &wxuserinfo, nil }