package youngee_talent_service import ( "bytes" "encoding/json" "fmt" "github.com/gogf/gf/encoding/gjson" "net/http" "youngmini_server/app/dao" "youngmini_server/app/model" "youngmini_server/app/model/youngee_talent_model" "youngmini_server/app/utils" "github.com/gogf/gf/crypto/gmd5" "github.com/gogf/gf/frame/g" "github.com/gogf/gf/net/ghttp" "github.com/gogf/gf/os/gtime" ) type WxLoginResult struct { OpenId string `json:"openid"` SessionKey string `json:"session_key"` UnionId string `json:"unionid"` ErrCode int `json:"errcode"` ErrMsg string `json:"errmsg"` } // 定义 Watermark 结构体 type Watermark struct { Timestamp int `json:"timestamp"` AppID string `json:"appid"` } // 定义 PhoneInfo 结构体 type PhoneInfo struct { PhoneNumber string `json:"phoneNumber"` PurePhoneNumber string `json:"purePhoneNumber"` CountryCode string `json:"countryCode"` Watermark Watermark `json:"watermark"` } // 定义响应结构体 GetPhoneRes type GetPhoneRes struct { ErrCode int `json:"errcode"` ErrMsg string `json:"errmsg"` PhoneInfo PhoneInfo `json:"phone_info"` } const ( urlgetphone = "https://api.weixin.qq.com/wxa/business/getuserphonenumber?access_token=%s" urlformat = "https://api.weixin.qq.com/sns/jscode2session?appid=%s&secret=%s&js_code=%s&grant_type=authorization_code" ) type GetPhoneRequestBody struct { Code string `json:"code"` } func WxLogin(r *ghttp.Request) *TalentHttpResult { l := youngee_talent_model.WxLoginInfo{} err := r.ParseForm(&l) if err != nil { return &TalentHttpResult{Code: -1, Msg: "param error"} } appId := g.Config().GetString("miniapp.appid") secret := g.Config().GetString("miniapp.appsecret") url := fmt.Sprintf(urlformat, appId, secret, l.Code) //通过前端uni.login获得了code用于拼接url resp, err := http.Get(url) if err != nil { return &TalentHttpResult{Code: -2, Msg: err.Error()} } //http.Get(url)之后要关闭 defer resp.Body.Close() // 解码微信服务端传来的信息 wxResp := WxLoginResult{} decoder := json.NewDecoder(resp.Body) if err = decoder.Decode(&wxResp); err != nil { return &TalentHttpResult{Code: -3, Msg: "decode json from wx fail"} } if wxResp.ErrCode != 0 { fmt.Printf("错误码:%d, 错误信息:%s", wxResp.ErrCode, wxResp.ErrMsg) return &TalentHttpResult{Code: -4, Msg: fmt.Sprintf("errCode:%d, errmsg:%s", wxResp.ErrCode, wxResp.ErrMsg)} } //为了获得手机号 phoneNum := getPhoneNum(l.GetPhoneCode) // 根据openid查询达人信息 rec, err := g.DB().Model("youngee_talent_info").One("talent_phone_number", phoneNum) if err != nil { return &TalentHttpResult{Code: -5, Msg: "get talent info failed"} } // 如果达人被拉黑,则返回 if rec != nil && rec[dao.YoungeeTalentInfo.Columns.InBlacklist].Int() > 0 { return &TalentHttpResult{Code: -6, Msg: "in black list"} } //获得登录后的返回结果对象 res := youngee_talent_model.LoginResultData{} var newTalentId string if rec == nil { // 如果数据库中不存在此达人,则插入新的达人信息 // 首先生成达人唯一id newTalentId = utils.GetUuid.GetTalentId() talentInfo := model.YoungeeTalentInfo{ Id: newTalentId, TalentWxOpenid: wxResp.OpenId, Avatar: l.Avatar, TalentWxNickname: l.Nickname, TalentPhoneNumber: phoneNum, //插入手机号 Canwithdraw: 0, Income: 0, Withdrawing: 0, Withdrawed: 0, LastLoginDate: gtime.Now(), CreateDate: gtime.Now(), } res.Avatar = l.Avatar res.Nickname = l.Nickname res.Phone = phoneNum //接口返回手机号 _, err = g.DB().Model(dao.YoungeeTalentInfo.Table).Data(talentInfo).Insert() if err != nil { return &TalentHttpResult{Code: -7, Msg: "get talentId failed"} } } else { // 如果已存在达人,则读取达人id newTalentId = rec["id"].String() res.Avatar = rec["avatar"].String() res.Nickname = rec["talent_wx_nickname"].String() res.Phone = rec["talent_phone_number"].String() // 更新达人最近登录时间 _, err = g.DB().Model(dao.YoungeeTalentInfo.Table).Data( g.Map{ "last_login_date": gtime.Now(), }).Where("id", newTalentId).Update() if err != nil { return &TalentHttpResult{Code: -8, Msg: "update talent last login date failed"} } } // 用微信的openid和SessionKey的md5做为token。会一直生效 token, err := gmd5.EncryptString(wxResp.OpenId + wxResp.SessionKey) fmt.Println("token is " + token) if err != nil { return &TalentHttpResult{Code: -9, Msg: "generate key failed"} } res.Token = token // 以token为键保存session 存储在服务器中 //自动生成一个 session ID 并通过 Cookie 将其发送给客户端,以便在后续请求中识别该客户端的会话 //自动生成一个 session ID,并通过 `Set-Cookie` 头将其发送给客户端,前端可以通过r.header['Set-Cookie']获取cookie err = r.Session.Set(token, g.Map{ "talentId": newTalentId, "wxOpenId": wxResp.OpenId, "wxSessionKey": wxResp.SessionKey, }) if err != nil { return &TalentHttpResult{Code: -10, Msg: "set session failed"} } // 生成自己的session_key返回给小程序 return &TalentHttpResult{Code: 0, Msg: "success", Data: res} } func getPhoneNum(code string) string { //获取access_token accessToken, err := getAndCacheWxAccessToken() fmt.Println("accesstoken===>", accessToken) //post获取电话号码 url := fmt.Sprintf(urlgetphone, accessToken) fmt.Println("url ", url) getPhoneRequest := GetPhoneRequestBody{ Code: code, } jsonBody, err := gjson.Encode(getPhoneRequest) // 发送 POST 请求 response, err := http.Post(url, "application/json", bytes.NewBuffer(jsonBody)) if err != nil { fmt.Printf("post getphoneNum failed") } defer response.Body.Close() // 解码微信服务端传来的信息 var getphoneResp = GetPhoneRes{} decoder := json.NewDecoder(response.Body) if err = decoder.Decode(&getphoneResp); err != nil { fmt.Printf("decode json from wx fail") } if getphoneResp.ErrCode != 0 { fmt.Printf("错误码:%d, 错误信息:%s", getphoneResp.ErrCode, getphoneResp.ErrMsg) fmt.Sprintf("errCode:%d, errmsg:%s", getphoneResp.ErrCode, getphoneResp.ErrMsg) } // 打印解析后的结构体内容 fmt.Println("获取号码接口响应====》", getphoneResp.PhoneInfo.PhoneNumber) return getphoneResp.PhoneInfo.PhoneNumber } func IsLogin(r *ghttp.Request) *TalentHttpResult { return &TalentHttpResult{Code: 0, Msg: "success!"} }