Commit 2decca18a614cf664e83c446a6614bfa61bb89b0
1 parent
cda08d33
Exists in
master
接入微信登录
Showing
6 changed files
with
253 additions
and
19 deletions
Show diff stats
src/HttpServer/logic/constdef.go
src/HttpServer/logic/datadef.go
| @@ -14,6 +14,20 @@ const ( | @@ -14,6 +14,20 @@ const ( | ||
| 14 | 14 | ||
| 15 | ) | 15 | ) |
| 16 | 16 | ||
| 17 | +type WechatLoginReq struct { | ||
| 18 | + Channel_id int `json:"channel_id"` | ||
| 19 | + Invite_type int `json:"invite_type"` | ||
| 20 | + Invite_res_id int `json:"invite_res_id"` | ||
| 21 | + User_invite_uid int `json:"user_invite_uid"` | ||
| 22 | + Code string `json:"code"` | ||
| 23 | + Signature string `json:"signature"` | ||
| 24 | + Iv string `json:"iv"` | ||
| 25 | + Raw_data string `json:"raw_data"` | ||
| 26 | + Encrypted_data string `json:"encrypted_data"` | ||
| 27 | + Token string `json:"token"` | ||
| 28 | + Version string `json:"version"` | ||
| 29 | +} | ||
| 30 | + | ||
| 17 | type UserLoginReq struct { | 31 | type UserLoginReq struct { |
| 18 | Channel_id int `json:"channel_id"` | 32 | Channel_id int `json:"channel_id"` |
| 19 | Invite_type int `json:"invite_type"` | 33 | Invite_type int `json:"invite_type"` |
| @@ -23,9 +37,6 @@ type UserLoginReq struct { | @@ -23,9 +37,6 @@ type UserLoginReq struct { | ||
| 23 | RefAppId int `json:"refAppId"` | 37 | RefAppId int `json:"refAppId"` |
| 24 | Code string `json:"code"` | 38 | Code string `json:"code"` |
| 25 | Token string `json:"token"` | 39 | Token string `json:"token"` |
| 26 | - Logintype int `json:"logintype"` | ||
| 27 | - Useraccount string `json:"useraccount"` | ||
| 28 | - Userpwd string `json:"userpwd"` | ||
| 29 | Version string `json:"version"` | 40 | Version string `json:"version"` |
| 30 | 41 | ||
| 31 | } | 42 | } |
src/HttpServer/logic/errordef.go
| @@ -35,4 +35,5 @@ const ( | @@ -35,4 +35,5 @@ const ( | ||
| 35 | ERROR_FRIENDNOTFRIEND = 30 //不是好友 | 35 | ERROR_FRIENDNOTFRIEND = 30 //不是好友 |
| 36 | ERROR_FRIENDDELFRIENDFAILED = 31 //删除好友失败 | 36 | ERROR_FRIENDDELFRIENDFAILED = 31 //删除好友失败 |
| 37 | ERROR_FRIENDGETFRIENDINFOFAILED = 32 //获取好友信息失败 | 37 | ERROR_FRIENDGETFRIENDINFOFAILED = 32 //获取好友信息失败 |
| 38 | + ERROR_WECHATLOGINFAILED = 33 //获取好友信息失败 | ||
| 38 | ) | 39 | ) |
| 39 | \ No newline at end of file | 40 | \ No newline at end of file |
src/HttpServer/logic/httpserver.go
| @@ -29,7 +29,8 @@ func CheckErr(err error) { | @@ -29,7 +29,8 @@ func CheckErr(err error) { | ||
| 29 | } | 29 | } |
| 30 | 30 | ||
| 31 | func startServerHttpServe() { | 31 | func startServerHttpServe() { |
| 32 | - http.HandleFunc("/catcafe/login", UserLogin) //登录 | 32 | + http.HandleFunc("/catcafe/login", UserLogin) //游客登录 |
| 33 | + http.HandleFunc("/catcafe/wechatlogin", Wechatlogin) //微信登录 | ||
| 33 | http.HandleFunc("/catcafe/user/saveUserData", SaveUserData) //保存用户数据 | 34 | http.HandleFunc("/catcafe/user/saveUserData", SaveUserData) //保存用户数据 |
| 34 | http.HandleFunc("/catcafe/data/saveData", SaveData) //保存游戏自定义数据 | 35 | http.HandleFunc("/catcafe/data/saveData", SaveData) //保存游戏自定义数据 |
| 35 | http.HandleFunc("/catcafe/data/getData", GetData) //获取自定义数据 | 36 | http.HandleFunc("/catcafe/data/getData", GetData) //获取自定义数据 |
| @@ -60,6 +61,18 @@ func startServerHttpServe() { | @@ -60,6 +61,18 @@ func startServerHttpServe() { | ||
| 60 | } | 61 | } |
| 61 | 62 | ||
| 62 | 63 | ||
| 64 | +func Wechatlogin(w http.ResponseWriter, r *http.Request) { | ||
| 65 | + | ||
| 66 | + result, _ := ioutil.ReadAll(r.Body) | ||
| 67 | + r.Body.Close() | ||
| 68 | + | ||
| 69 | + s := string(result) | ||
| 70 | + logger.Info("Wechatlogin , body:%v,uuid=%v", s) | ||
| 71 | + | ||
| 72 | + HandleWechatlogin(w,s) | ||
| 73 | +} | ||
| 74 | + | ||
| 75 | + | ||
| 63 | func QueryPlayerData(w http.ResponseWriter, r *http.Request) { | 76 | func QueryPlayerData(w http.ResponseWriter, r *http.Request) { |
| 64 | 77 | ||
| 65 | result, _ := ioutil.ReadAll(r.Body) | 78 | result, _ := ioutil.ReadAll(r.Body) |
src/HttpServer/logic/logic.go
| @@ -25,6 +25,44 @@ func init() { | @@ -25,6 +25,44 @@ func init() { | ||
| 25 | } | 25 | } |
| 26 | 26 | ||
| 27 | 27 | ||
| 28 | +func InitUserExt(req *UserLoginReq,resp *UserLoginResp,uuid int) { | ||
| 29 | + var extdata UserExtData | ||
| 30 | + extdata.User_id = uuid | ||
| 31 | + extdata.Lv = 1 | ||
| 32 | + extdata.Bean = 0 | ||
| 33 | + extdata.Coin = 0 | ||
| 34 | + extdata.Exp = 0 | ||
| 35 | + extdata.Hot = 0 | ||
| 36 | + extdata.Invite_uid = req.User_invite_uid | ||
| 37 | + extdata.LoveExp = 0 | ||
| 38 | + extdata.Reg_time = int(time.Now().Unix()) | ||
| 39 | + extdata.ShopNum = 0 | ||
| 40 | + extdata.User_channel = req.Channel_id | ||
| 41 | + extdata.User_is_black = 0 | ||
| 42 | + extdata.User_reg_time = int(time.Now().Unix()) | ||
| 43 | + extdata.User_scene = req.Scene | ||
| 44 | + resp.Result.Data.Extdata = extdata | ||
| 45 | + //保存 | ||
| 46 | + udata :=new(UserData) | ||
| 47 | + udata.Scene = extdata.User_scene | ||
| 48 | + udata.Hot = extdata.Hot | ||
| 49 | + udata.Exp = extdata.Exp | ||
| 50 | + udata.Coin = extdata.Coin | ||
| 51 | + udata.Bean = extdata.Bean | ||
| 52 | + udata.Lv = extdata.Lv | ||
| 53 | + udata.Channel = extdata.User_channel | ||
| 54 | + udata.InviteUid = extdata.Invite_uid | ||
| 55 | + udata.Isblack = extdata.User_is_black | ||
| 56 | + udata.Loevexp = extdata.LoveExp | ||
| 57 | + udata.Regtime = extdata.Reg_time | ||
| 58 | + udata.Shopnum = extdata.ShopNum | ||
| 59 | + udata.Userid = extdata.User_id | ||
| 60 | + udata.UserInviteId = extdata.User_invite_uid | ||
| 61 | + udata.Userregtime = extdata.User_reg_time | ||
| 62 | + | ||
| 63 | + SaveUserExt(udata) | ||
| 64 | +} | ||
| 65 | + | ||
| 28 | 66 | ||
| 29 | func InitTourist(req *UserLoginReq,resp *UserLoginResp) { | 67 | func InitTourist(req *UserLoginReq,resp *UserLoginResp) { |
| 30 | //首先生成user_base_data | 68 | //首先生成user_base_data |
| @@ -43,6 +81,28 @@ func InitTourist(req *UserLoginReq,resp *UserLoginResp) { | @@ -43,6 +81,28 @@ func InitTourist(req *UserLoginReq,resp *UserLoginResp) { | ||
| 43 | 81 | ||
| 44 | SetTouristUid(req.Token,basedata.User_id) | 82 | SetTouristUid(req.Token,basedata.User_id) |
| 45 | //然后生成user_ext_data | 83 | //然后生成user_ext_data |
| 84 | + InitUserExt(req,resp,basedata.User_id) | ||
| 85 | + | ||
| 86 | +} | ||
| 87 | + | ||
| 88 | +//微信登录账户初始化 | ||
| 89 | +func InitWeChatUser(req *WechatLoginReq,resp *UserLoginResp,uinfo *WxUserInfo) { | ||
| 90 | + //首先生成user_base_data | ||
| 91 | + var basedata UserBaseData | ||
| 92 | + basedata.User_id = GetNewUUid() | ||
| 93 | + basedata.User_avatar_url = uinfo.AvatarURL | ||
| 94 | + basedata.User_city = uinfo.City | ||
| 95 | + basedata.User_gender = uinfo.Gender | ||
| 96 | + basedata.User_nickname = uinfo.NickName | ||
| 97 | + basedata.User_openid = uinfo.OpenID | ||
| 98 | + basedata.User_token = req.Token | ||
| 99 | + resp.Result.Data.Dasedata = basedata | ||
| 100 | + //保存base data | ||
| 101 | + basic, _ := json.Marshal(&basedata) | ||
| 102 | + SaveUserBasic(basedata.User_id,string(basic)) | ||
| 103 | + | ||
| 104 | + SetTouristUid(uinfo.OpenID,basedata.User_id) | ||
| 105 | + //然后生成user_ext_data | ||
| 46 | var extdata UserExtData | 106 | var extdata UserExtData |
| 47 | extdata.User_id = basedata.User_id | 107 | extdata.User_id = basedata.User_id |
| 48 | extdata.Lv = 1 | 108 | extdata.Lv = 1 |
| @@ -57,7 +117,7 @@ func InitTourist(req *UserLoginReq,resp *UserLoginResp) { | @@ -57,7 +117,7 @@ func InitTourist(req *UserLoginReq,resp *UserLoginResp) { | ||
| 57 | extdata.User_channel = req.Channel_id | 117 | extdata.User_channel = req.Channel_id |
| 58 | extdata.User_is_black = 0 | 118 | extdata.User_is_black = 0 |
| 59 | extdata.User_reg_time = int(time.Now().Unix()) | 119 | extdata.User_reg_time = int(time.Now().Unix()) |
| 60 | - extdata.User_scene = req.Scene | 120 | + extdata.User_scene = 0 |
| 61 | resp.Result.Data.Extdata = extdata | 121 | resp.Result.Data.Extdata = extdata |
| 62 | //保存 | 122 | //保存 |
| 63 | udata :=new(UserData) | 123 | udata :=new(UserData) |
| @@ -81,6 +141,65 @@ func InitTourist(req *UserLoginReq,resp *UserLoginResp) { | @@ -81,6 +141,65 @@ func InitTourist(req *UserLoginReq,resp *UserLoginResp) { | ||
| 81 | 141 | ||
| 82 | } | 142 | } |
| 83 | 143 | ||
| 144 | +//处理微信登录 | ||
| 145 | +func HandleWechatlogin(w http.ResponseWriter, data string) { | ||
| 146 | + | ||
| 147 | + SetHeader(w) | ||
| 148 | + var resp UserLoginResp | ||
| 149 | + resp.Status = "true" | ||
| 150 | + resp.Result.Code = ERROR_OK | ||
| 151 | + var rdata WechatLoginReq | ||
| 152 | + err := json.Unmarshal([]byte(data), &rdata) | ||
| 153 | + for { | ||
| 154 | + if err != nil { | ||
| 155 | + logger.Error("HandleWechatlogin json unmarshal failed=%v", err) | ||
| 156 | + resp.Result.Code = ERROR_JSONUNMASHFAILED | ||
| 157 | + break | ||
| 158 | + } | ||
| 159 | + | ||
| 160 | + pc := NewWXUserDataCrypt(WETCHATAPPID, WETCHATSERCRT) | ||
| 161 | + userInfo, err := pc.Decrypt(rdata.Encrypted_data, rdata.Iv) | ||
| 162 | + if err != nil { | ||
| 163 | + logger.Error("HandleWechatlogin wechatloginfailed failed=%v", err) | ||
| 164 | + resp.Result.Code = ERROR_WECHATLOGINFAILED | ||
| 165 | + break | ||
| 166 | + } | ||
| 167 | + logger.Info("HandleWechatlogin userInfo=%v",userInfo) | ||
| 168 | + | ||
| 169 | + uuid,_ := GetTouristUid(userInfo.OpenID) | ||
| 170 | + if uuid == 0 { | ||
| 171 | + //新的账号 需要初始化保存 | ||
| 172 | + InitWeChatUser(&rdata,&resp,userInfo) | ||
| 173 | + }else { | ||
| 174 | + //读取数据 | ||
| 175 | + basic,err := GetUserBasic(uuid) | ||
| 176 | + if err != nil { | ||
| 177 | + logger.Error("HandleWechatlogin getbasic failed=%v", err) | ||
| 178 | + resp.Result.Code = ERROR_GETUSERBASICFAILED | ||
| 179 | + break | ||
| 180 | + } | ||
| 181 | + resp.Result.Data.Dasedata = *basic | ||
| 182 | + | ||
| 183 | + ext,err := GetUserExt(uuid) | ||
| 184 | + if err != nil { | ||
| 185 | + logger.Error("HandleWechatlogin getext failed=%v", err) | ||
| 186 | + resp.Result.Code = ERROR_GETUSEREXTFAILED | ||
| 187 | + break | ||
| 188 | + } | ||
| 189 | + resp.Result.Data.Extdata = *ext | ||
| 190 | + | ||
| 191 | + m_userInfo.Set(uint32(ext.User_id),ext) | ||
| 192 | + } | ||
| 193 | + | ||
| 194 | + resp.Result.Code = ERROR_OK | ||
| 195 | + break | ||
| 196 | + } | ||
| 197 | + | ||
| 198 | + //回包 | ||
| 199 | + respstr, _ := json.Marshal(&resp) | ||
| 200 | + fmt.Fprint(w, string(respstr)) | ||
| 201 | +} | ||
| 202 | + | ||
| 84 | //处理游客登录 | 203 | //处理游客登录 |
| 85 | func HandleTouristLogin(w http.ResponseWriter, req *UserLoginReq,resp *UserLoginResp) { | 204 | func HandleTouristLogin(w http.ResponseWriter, req *UserLoginReq,resp *UserLoginResp) { |
| 86 | 205 | ||
| @@ -134,23 +253,11 @@ func HandleUserLogin(w http.ResponseWriter, data string) { | @@ -134,23 +253,11 @@ func HandleUserLogin(w http.ResponseWriter, data string) { | ||
| 134 | break | 253 | break |
| 135 | } | 254 | } |
| 136 | 255 | ||
| 137 | - if rdata.Logintype ==LOGIN_TYPE_TOURIST { | ||
| 138 | - //游客登录 | ||
| 139 | - HandleTouristLogin(w,&rdata,&resp) | ||
| 140 | - break | ||
| 141 | - } | ||
| 142 | 256 | ||
| 143 | - if rdata.Logintype == LOGIN_TYPE_ACCOUNT { | ||
| 144 | - //账号密码登录 | 257 | + HandleTouristLogin(w,&rdata,&resp) |
| 145 | 258 | ||
| 146 | - break | ||
| 147 | - } | ||
| 148 | 259 | ||
| 149 | - if rdata.Logintype == LOGIN_TYPE_WECHAT { | ||
| 150 | - //微信登录 | ||
| 151 | 260 | ||
| 152 | - break | ||
| 153 | - } | ||
| 154 | 261 | ||
| 155 | 262 | ||
| 156 | } | 263 | } |
| @@ -301,7 +408,7 @@ func HandlegetData(w http.ResponseWriter, data string) { | @@ -301,7 +408,7 @@ func HandlegetData(w http.ResponseWriter, data string) { | ||
| 301 | } | 408 | } |
| 302 | 409 | ||
| 303 | func GetAccessToken() string{ | 410 | func GetAccessToken() string{ |
| 304 | - //首先从缓存取 | 411 | + //首先从缓存取kwiffwiffiaowosfwkfko |
| 305 | exist,err := redishandler.GetRedisClient().Exists(redis.MSG_CKECK_ACCESSTOKEN) | 412 | exist,err := redishandler.GetRedisClient().Exists(redis.MSG_CKECK_ACCESSTOKEN) |
| 306 | if err != nil { | 413 | if err != nil { |
| 307 | logger.Error("GetAccessToken err=%v",err) | 414 | logger.Error("GetAccessToken err=%v",err) |
| @@ -0,0 +1,98 @@ | @@ -0,0 +1,98 @@ | ||
| 1 | +package logic | ||
| 2 | + | ||
| 3 | +import ( | ||
| 4 | + "crypto/aes" | ||
| 5 | + "crypto/cipher" | ||
| 6 | + "encoding/base64" | ||
| 7 | + "encoding/json" | ||
| 8 | + "errors" | ||
| 9 | +) | ||
| 10 | + | ||
| 11 | +var ( | ||
| 12 | + ErrAppIDNotMatch = errors.New("app id not match") | ||
| 13 | + ErrInvalidBlockSize = errors.New("invalid block size") | ||
| 14 | + ErrInvalidPKCS7Data = errors.New("invalid PKCS7 data") | ||
| 15 | + ErrInvalidPKCS7Padding = errors.New("invalid padding on input") | ||
| 16 | +) | ||
| 17 | + | ||
| 18 | +type WxUserInfo struct { | ||
| 19 | + OpenID string `json:"openId"` | ||
| 20 | + UnionID string `json:"unionId"` | ||
| 21 | + NickName string `json:"nickName"` | ||
| 22 | + Gender int `json:"gender"` | ||
| 23 | + City string `json:"city"` | ||
| 24 | + Province string `json:"province"` | ||
| 25 | + Country string `json:"country"` | ||
| 26 | + AvatarURL string `json:"avatarUrl"` | ||
| 27 | + Language string `json:"language"` | ||
| 28 | + Watermark struct { | ||
| 29 | + Timestamp int64 `json:"timestamp"` | ||
| 30 | + AppID string `json:"appid"` | ||
| 31 | + } `json:"watermark"` | ||
| 32 | +} | ||
| 33 | + | ||
| 34 | +type WXUserDataCrypt struct { | ||
| 35 | + appID, sessionKey string | ||
| 36 | +} | ||
| 37 | + | ||
| 38 | +func NewWXUserDataCrypt(appID, sessionKey string) *WXUserDataCrypt { | ||
| 39 | + return &WXUserDataCrypt{ | ||
| 40 | + appID: appID, | ||
| 41 | + sessionKey: sessionKey, | ||
| 42 | + } | ||
| 43 | +} | ||
| 44 | + | ||
| 45 | +// pkcs7Unpad returns slice of the original data without padding | ||
| 46 | +func pkcs7Unpad(data []byte, blockSize int) ([]byte, error) { | ||
| 47 | + if blockSize <= 0 { | ||
| 48 | + return nil, ErrInvalidBlockSize | ||
| 49 | + } | ||
| 50 | + if len(data)%blockSize != 0 || len(data) == 0 { | ||
| 51 | + return nil, ErrInvalidPKCS7Data | ||
| 52 | + } | ||
| 53 | + c := data[len(data)-1] | ||
| 54 | + n := int(c) | ||
| 55 | + if n == 0 || n > len(data) { | ||
| 56 | + return nil, ErrInvalidPKCS7Padding | ||
| 57 | + } | ||
| 58 | + for i := 0; i < n; i++ { | ||
| 59 | + if data[len(data)-n+i] != c { | ||
| 60 | + return nil, ErrInvalidPKCS7Padding | ||
| 61 | + } | ||
| 62 | + } | ||
| 63 | + return data[:len(data)-n], nil | ||
| 64 | +} | ||
| 65 | + | ||
| 66 | +func (w *WXUserDataCrypt) Decrypt(encryptedData, iv string) (*WxUserInfo, error) { | ||
| 67 | + aesKey, err := base64.StdEncoding.DecodeString(w.sessionKey) | ||
| 68 | + if err != nil { | ||
| 69 | + return nil, err | ||
| 70 | + } | ||
| 71 | + cipherText, err := base64.StdEncoding.DecodeString(encryptedData) | ||
| 72 | + if err != nil { | ||
| 73 | + return nil, err | ||
| 74 | + } | ||
| 75 | + ivBytes, err := base64.StdEncoding.DecodeString(iv) | ||
| 76 | + if err != nil { | ||
| 77 | + return nil, err | ||
| 78 | + } | ||
| 79 | + block, err := aes.NewCipher(aesKey) | ||
| 80 | + if err != nil { | ||
| 81 | + return nil, err | ||
| 82 | + } | ||
| 83 | + mode := cipher.NewCBCDecrypter(block, ivBytes) | ||
| 84 | + mode.CryptBlocks(cipherText, cipherText) | ||
| 85 | + cipherText, err = pkcs7Unpad(cipherText, block.BlockSize()) | ||
| 86 | + if err != nil { | ||
| 87 | + return nil, err | ||
| 88 | + } | ||
| 89 | + var userInfo WxUserInfo | ||
| 90 | + err = json.Unmarshal(cipherText, &userInfo) | ||
| 91 | + if err != nil { | ||
| 92 | + return nil, err | ||
| 93 | + } | ||
| 94 | + if userInfo.Watermark.AppID != w.appID { | ||
| 95 | + return nil, ErrAppIDNotMatch | ||
| 96 | + } | ||
| 97 | + return &userInfo, nil | ||
| 98 | +} | ||
| 0 | \ No newline at end of file | 99 | \ No newline at end of file |