wxlogin.go 6.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213
  1. package youngee_talent_service
  2. import (
  3. "bytes"
  4. "encoding/json"
  5. "fmt"
  6. "github.com/gogf/gf/encoding/gjson"
  7. "net/http"
  8. "youngmini_server/app/dao"
  9. "youngmini_server/app/model"
  10. "youngmini_server/app/model/youngee_talent_model"
  11. "youngmini_server/app/utils"
  12. "github.com/gogf/gf/crypto/gmd5"
  13. "github.com/gogf/gf/frame/g"
  14. "github.com/gogf/gf/net/ghttp"
  15. "github.com/gogf/gf/os/gtime"
  16. )
  17. type WxLoginResult struct {
  18. OpenId string `json:"openid"`
  19. SessionKey string `json:"session_key"`
  20. UnionId string `json:"unionid"`
  21. ErrCode int `json:"errcode"`
  22. ErrMsg string `json:"errmsg"`
  23. }
  24. // 定义 Watermark 结构体
  25. type Watermark struct {
  26. Timestamp int `json:"timestamp"`
  27. AppID string `json:"appid"`
  28. }
  29. // 定义 PhoneInfo 结构体
  30. type PhoneInfo struct {
  31. PhoneNumber string `json:"phoneNumber"`
  32. PurePhoneNumber string `json:"purePhoneNumber"`
  33. CountryCode string `json:"countryCode"`
  34. Watermark Watermark `json:"watermark"`
  35. }
  36. // 定义响应结构体 GetPhoneRes
  37. type GetPhoneRes struct {
  38. ErrCode int `json:"errcode"`
  39. ErrMsg string `json:"errmsg"`
  40. PhoneInfo PhoneInfo `json:"phone_info"`
  41. }
  42. const (
  43. urlgetphone = "https://api.weixin.qq.com/wxa/business/getuserphonenumber?access_token=%s"
  44. urlformat = "https://api.weixin.qq.com/sns/jscode2session?appid=%s&secret=%s&js_code=%s&grant_type=authorization_code"
  45. )
  46. type GetPhoneRequestBody struct {
  47. Code string `json:"code"`
  48. }
  49. func WxLogin(r *ghttp.Request) *TalentHttpResult {
  50. l := youngee_talent_model.WxLoginInfo{}
  51. err := r.ParseForm(&l)
  52. if err != nil {
  53. return &TalentHttpResult{Code: -1, Msg: "param error"}
  54. }
  55. appId := g.Config().GetString("miniapp.appid")
  56. secret := g.Config().GetString("miniapp.appsecret")
  57. url := fmt.Sprintf(urlformat, appId, secret, l.Code)
  58. //通过前端uni.login获得了code用于拼接url
  59. resp, err := http.Get(url)
  60. if err != nil {
  61. return &TalentHttpResult{Code: -2, Msg: err.Error()}
  62. }
  63. //http.Get(url)之后要关闭
  64. defer resp.Body.Close()
  65. // 解码微信服务端传来的信息
  66. wxResp := WxLoginResult{}
  67. decoder := json.NewDecoder(resp.Body)
  68. if err = decoder.Decode(&wxResp); err != nil {
  69. return &TalentHttpResult{Code: -3, Msg: "decode json from wx fail"}
  70. }
  71. if wxResp.ErrCode != 0 {
  72. fmt.Printf("错误码:%d, 错误信息:%s", wxResp.ErrCode, wxResp.ErrMsg)
  73. return &TalentHttpResult{Code: -4, Msg: fmt.Sprintf("errCode:%d, errmsg:%s", wxResp.ErrCode, wxResp.ErrMsg)}
  74. }
  75. //为了获得手机号
  76. phoneNum := getPhoneNum(l.GetPhoneCode)
  77. // 根据openid查询达人信息
  78. rec, err := g.DB().Model("youngee_talent_info").One("talent_phone_number", phoneNum)
  79. if err != nil {
  80. return &TalentHttpResult{Code: -5, Msg: "get talent info failed"}
  81. }
  82. // 如果达人被拉黑,则返回
  83. if rec != nil && rec[dao.YoungeeTalentInfo.Columns.InBlacklist].Int() > 0 {
  84. return &TalentHttpResult{Code: -6, Msg: "in black list"}
  85. }
  86. //获得登录后的返回结果对象
  87. res := youngee_talent_model.LoginResultData{}
  88. var newTalentId string
  89. if rec == nil {
  90. // 如果数据库中不存在此达人,则插入新的达人信息
  91. // 首先生成达人唯一id
  92. newTalentId = utils.GetUuid.GetTalentId()
  93. talentInfo := model.YoungeeTalentInfo{
  94. Id: newTalentId,
  95. TalentWxOpenid: wxResp.OpenId,
  96. Avatar: l.Avatar,
  97. TalentWxNickname: l.Nickname,
  98. TalentPhoneNumber: phoneNum, //插入手机号
  99. Canwithdraw: 0,
  100. Income: 0,
  101. Withdrawing: 0,
  102. Withdrawed: 0,
  103. LastLoginDate: gtime.Now(),
  104. CreateDate: gtime.Now(),
  105. }
  106. res.Avatar = l.Avatar
  107. res.Nickname = l.Nickname
  108. res.Phone = phoneNum //接口返回手机号
  109. _, err = g.DB().Model(dao.YoungeeTalentInfo.Table).Data(talentInfo).Insert()
  110. if err != nil {
  111. return &TalentHttpResult{Code: -7, Msg: "get talentId failed"}
  112. }
  113. } else {
  114. // 如果已存在达人,则读取达人id
  115. newTalentId = rec["id"].String()
  116. res.Avatar = rec["avatar"].String()
  117. res.Nickname = rec["talent_wx_nickname"].String()
  118. res.Phone = rec["talent_phone_number"].String()
  119. // 更新达人最近登录时间
  120. _, err = g.DB().Model(dao.YoungeeTalentInfo.Table).Data(
  121. g.Map{
  122. "last_login_date": gtime.Now(),
  123. }).Where("id", newTalentId).Update()
  124. if err != nil {
  125. return &TalentHttpResult{Code: -8, Msg: "update talent last login date failed"}
  126. }
  127. }
  128. // 用微信的openid和SessionKey的md5做为token。会一直生效
  129. token, err := gmd5.EncryptString(wxResp.OpenId + wxResp.SessionKey)
  130. fmt.Println("token is " + token)
  131. if err != nil {
  132. return &TalentHttpResult{Code: -9, Msg: "generate key failed"}
  133. }
  134. res.Token = token
  135. // 以token为键保存session 存储在服务器中
  136. //自动生成一个 session ID 并通过 Cookie 将其发送给客户端,以便在后续请求中识别该客户端的会话
  137. //自动生成一个 session ID,并通过 `Set-Cookie` 头将其发送给客户端,前端可以通过r.header['Set-Cookie']获取cookie
  138. err = r.Session.Set(token, g.Map{
  139. "talentId": newTalentId,
  140. "wxOpenId": wxResp.OpenId,
  141. "wxSessionKey": wxResp.SessionKey,
  142. })
  143. if err != nil {
  144. return &TalentHttpResult{Code: -10, Msg: "set session failed"}
  145. }
  146. // 生成自己的session_key返回给小程序
  147. return &TalentHttpResult{Code: 0, Msg: "success", Data: res}
  148. }
  149. func getPhoneNum(code string) string {
  150. //获取access_token
  151. accessToken, err := getAndCacheWxAccessToken()
  152. fmt.Println("accesstoken===>", accessToken)
  153. //post获取电话号码
  154. url := fmt.Sprintf(urlgetphone, accessToken)
  155. fmt.Println("url ", url)
  156. getPhoneRequest := GetPhoneRequestBody{
  157. Code: code,
  158. }
  159. jsonBody, err := gjson.Encode(getPhoneRequest)
  160. // 发送 POST 请求
  161. response, err := http.Post(url, "application/json", bytes.NewBuffer(jsonBody))
  162. if err != nil {
  163. fmt.Printf("post getphoneNum failed")
  164. }
  165. defer response.Body.Close()
  166. // 解码微信服务端传来的信息
  167. var getphoneResp = GetPhoneRes{}
  168. decoder := json.NewDecoder(response.Body)
  169. if err = decoder.Decode(&getphoneResp); err != nil {
  170. fmt.Printf("decode json from wx fail")
  171. }
  172. if getphoneResp.ErrCode != 0 {
  173. fmt.Printf("错误码:%d, 错误信息:%s", getphoneResp.ErrCode, getphoneResp.ErrMsg)
  174. fmt.Sprintf("errCode:%d, errmsg:%s", getphoneResp.ErrCode, getphoneResp.ErrMsg)
  175. }
  176. // 打印解析后的结构体内容
  177. fmt.Println("获取号码接口响应====》", getphoneResp.PhoneInfo.PhoneNumber)
  178. return getphoneResp.PhoneInfo.PhoneNumber
  179. }
  180. func IsLogin(r *ghttp.Request) *TalentHttpResult {
  181. return &TalentHttpResult{Code: 0, Msg: "success!"}
  182. }