user.go 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509
  1. package user
  2. import (
  3. "encoding/json"
  4. "errors"
  5. "github.com/gin-gonic/gin"
  6. "github.com/silenceper/wechat/v2/miniprogram/auth"
  7. admin2 "hongze/hongze_yb/models/tables/admin"
  8. "hongze/hongze_yb/models/tables/rddp/session"
  9. "hongze/hongze_yb/models/tables/research_variety_tag_relation"
  10. "hongze/hongze_yb/models/tables/user_record"
  11. "hongze/hongze_yb/models/tables/wx_user"
  12. "hongze/hongze_yb/models/tables/wx_user_log"
  13. "hongze/hongze_yb/utils"
  14. "strconv"
  15. "time"
  16. )
  17. var ERR_NO_USER_RECORD = errors.New("用户关系没有入库")
  18. var ERR_USER_NOT_BIND = errors.New("用户没有绑定")
  19. type UserInfo struct {
  20. wx_user.WxUser
  21. RecordInfo *user_record.UserRecord
  22. LoginToken string
  23. }
  24. // GetWxUserItemByOpenId 通过openid获取用户信息
  25. func GetWxUserItemByOpenId(openid string) (userInfo UserInfo, err error) {
  26. //通过openid获取用户关联信息
  27. userRecord, e := user_record.GetByOpenID(openid)
  28. if e != nil {
  29. if e == utils.ErrNoRow {
  30. err = ERR_NO_USER_RECORD
  31. return
  32. }
  33. err = e
  34. return
  35. }
  36. //该openid在系统中没有关联关系
  37. if userRecord == nil {
  38. err = ERR_NO_USER_RECORD
  39. return
  40. }
  41. //该openid没有绑定用户
  42. if userRecord.UserID <= 0 {
  43. err = ERR_USER_NOT_BIND
  44. item := new(wx_user.WxUser)
  45. //格式化返回用户数据
  46. userInfo = formatWxUserAndUserRecord(item, userRecord)
  47. return
  48. }
  49. //获取用户信息
  50. item, wxUserErr := wx_user.GetByUserId(userRecord.UserID)
  51. if wxUserErr != nil {
  52. err = wxUserErr
  53. //如果是找不到数据,那么可能是该用户被删除了,但是user_record没有删除对应的关系
  54. if wxUserErr == utils.ErrNoRow {
  55. //用户被删除了,但是user_record没有删除对应的关系,那么去解除绑定
  56. userUnbindErr := user_record.UnBindUserRecordByOpenid(openid)
  57. if userUnbindErr != nil {
  58. err = userUnbindErr
  59. return
  60. }
  61. //返回状态为 用户未绑定 逻辑代码
  62. err = ERR_USER_NOT_BIND
  63. item := new(wx_user.WxUser)
  64. //格式化返回用户数据
  65. userInfo = formatWxUserAndUserRecord(item, userRecord)
  66. return
  67. }
  68. return
  69. }
  70. //格式化返回用户数据
  71. userInfo = formatWxUserAndUserRecord(item, userRecord)
  72. return
  73. }
  74. // GetWxUserItemByUserId 根据用户id和平台id获取用户信息
  75. func GetWxUserItemByUserId(userId, platform int) (userInfo UserInfo, err error) {
  76. //获取用户信息
  77. wxUser, err := wx_user.GetByUserId(userId)
  78. if err != nil {
  79. return
  80. }
  81. //格式化返回用户数据
  82. userInfo = formatWxUser(wxUser, platform)
  83. return
  84. }
  85. // GetWxUserItemByEmail 根据用户邮箱和平台id获取用户信息
  86. func GetWxUserItemByEmail(email string, platform int) (userInfo UserInfo, err error) {
  87. //获取用户信息
  88. wxUser, err := wx_user.GetByEmail(email)
  89. if err != nil {
  90. return
  91. }
  92. //格式化返回用户数据
  93. userInfo = formatWxUser(wxUser, platform)
  94. return
  95. }
  96. // GetWxUserItemByMobile 根据用户手机号和平台id获取用户信息
  97. func GetWxUserItemByMobile(mobile string, platform int) (userInfo UserInfo, err error) {
  98. //获取用户信息
  99. wxUser, err := wx_user.GetByMobile(mobile)
  100. if err != nil {
  101. return
  102. }
  103. //格式化返回用户数据
  104. userInfo = formatWxUser(wxUser, platform)
  105. return
  106. }
  107. // GetWxUserItemByUnionId 根据用户unionid和平台id获取用户信息
  108. func GetWxUserItemByUnionId(unionId string, platform int) (userInfo UserInfo, err error) {
  109. // 获取用户信息
  110. userRecord, userRecordErr := user_record.GetByUnionID(unionId, platform)
  111. if userRecordErr != nil {
  112. if userRecordErr == utils.ErrNoRow {
  113. err = ERR_NO_USER_RECORD
  114. return
  115. } else {
  116. err = userRecordErr
  117. return
  118. }
  119. }
  120. // 该union在系统中没有关联关系
  121. if userRecord == nil {
  122. err = ERR_NO_USER_RECORD
  123. return
  124. }
  125. // 该openid没有绑定用户
  126. if userRecord.UserID <= 0 {
  127. err = ERR_USER_NOT_BIND
  128. item := new(wx_user.WxUser)
  129. //格式化返回用户数据
  130. userInfo = formatWxUserAndUserRecord(item, userRecord)
  131. return
  132. }
  133. item, wxUserErr := wx_user.GetByUserId(userRecord.UserID)
  134. if wxUserErr != nil {
  135. err = wxUserErr
  136. // 如果是找不到数据,那么可能是该用户被删除了,但是user_record没有删除对应的关系
  137. if wxUserErr == utils.ErrNoRow {
  138. // 用户被删除了,但是user_record没有删除对应的关系,那么去解除绑定
  139. userUnbindErr := user_record.UnBindUserRecordByUnionId(unionId, platform)
  140. if userUnbindErr != nil {
  141. err = userUnbindErr
  142. return
  143. }
  144. // 返回状态为用户未绑定
  145. err = ERR_USER_NOT_BIND
  146. item := new(wx_user.WxUser)
  147. // 格式化返回用户数据
  148. userInfo = formatWxUserAndUserRecord(item, userRecord)
  149. return
  150. }
  151. return
  152. }
  153. // 格式化返回用户数据
  154. userInfo = formatWxUserAndUserRecord(item, userRecord)
  155. return
  156. }
  157. // GetFirstWxUserItemByUnionId 根据用户unionid获取最小平台的用户信息(已经绑定了user_id的)
  158. func GetFirstWxUserItemByUnionId(unionId string) (userInfo UserInfo, err error) {
  159. // 获取用户信息
  160. userRecord, userRecordErr := user_record.GetFirstByUnionID(unionId)
  161. if userRecordErr != nil {
  162. if userRecordErr == utils.ErrNoRow {
  163. err = ERR_NO_USER_RECORD
  164. return
  165. } else {
  166. err = userRecordErr
  167. return
  168. }
  169. }
  170. // 该union在系统中没有关联关系
  171. if userRecord == nil {
  172. err = ERR_NO_USER_RECORD
  173. return
  174. }
  175. // 该openid没有绑定用户
  176. if userRecord.UserID <= 0 {
  177. err = ERR_USER_NOT_BIND
  178. item := new(wx_user.WxUser)
  179. //格式化返回用户数据
  180. userInfo = formatWxUserAndUserRecord(item, userRecord)
  181. return
  182. }
  183. item, wxUserErr := wx_user.GetByUserId(userRecord.UserID)
  184. if wxUserErr != nil {
  185. err = wxUserErr
  186. // 如果是找不到数据,那么可能是该用户被删除了,但是user_record没有删除对应的关系
  187. if wxUserErr == utils.ErrNoRow {
  188. // 用户被删除了,但是user_record没有删除对应的关系,那么去解除绑定
  189. userUnbindErr := user_record.UnBindUserRecordByUnionId(unionId, int(userRecord.CreatePlatform))
  190. if userUnbindErr != nil {
  191. err = userUnbindErr
  192. return
  193. }
  194. // 返回状态为用户未绑定
  195. err = ERR_USER_NOT_BIND
  196. item := new(wx_user.WxUser)
  197. // 格式化返回用户数据
  198. userInfo = formatWxUserAndUserRecord(item, userRecord)
  199. return
  200. }
  201. return
  202. }
  203. // 格式化返回用户数据
  204. userInfo = formatWxUserAndUserRecord(item, userRecord)
  205. return
  206. }
  207. // formatWxUserAndUserRecord 通过用户 关系表记录 和 用户记录 格式化返回 用户数据
  208. func formatWxUserAndUserRecord(wxUser *wx_user.WxUser, userRecord *user_record.UserRecord) (userInfo UserInfo) {
  209. wxUser.OpenID = userRecord.OpenID
  210. wxUser.UnionID = userRecord.UnionID
  211. //wxUser.NickName = userRecord.NickName
  212. //wxUser.RealName = userRecord.RealName
  213. //wxUser.BindAccount = userRecord.BindAccount
  214. //wxUser.Headimgurl = userRecord.Headimgurl
  215. wxUserJson, _ := json.Marshal(wxUser)
  216. _ = json.Unmarshal(wxUserJson, &userInfo)
  217. userInfo.RecordInfo = userRecord
  218. return
  219. }
  220. // formatWxUser 通过用户 用户记录 和 来源平台 格式化返回 用户数据
  221. func formatWxUser(wxUser *wx_user.WxUser, platform int) (userInfo UserInfo) {
  222. //根据用户id和平台id获取用户关系
  223. userRecord, userRecordErr := user_record.GetByUserId(int(wxUser.UserID), platform)
  224. if userRecordErr != nil {
  225. if userRecordErr != utils.ErrNoRow {
  226. return
  227. }
  228. }
  229. //该openid在系统中没有关联关系
  230. if userRecord == nil {
  231. wxUserJson, _ := json.Marshal(wxUser)
  232. _ = json.Unmarshal(wxUserJson, &userInfo)
  233. return
  234. } else {
  235. userInfo = formatWxUserAndUserRecord(wxUser, userRecord)
  236. }
  237. return
  238. }
  239. // WxLogin 微信登录
  240. func WxLogin(wxPlatform int, wxSession auth.ResCode2Session) (token string, userId int, isBind bool, err error) {
  241. openId := wxSession.OpenID
  242. unionId := wxSession.UnionID
  243. sessionKey := wxSession.SessionKey
  244. needUpdateSessionKey := true //是否更新sessionKey
  245. QUERY_WX_USER:
  246. wxUser, wxUserErr := GetWxUserItemByOpenId(openId)
  247. if wxUserErr == ERR_NO_USER_RECORD { //没有用户openid记录
  248. _, recordErr := AddUserRecord(openId, unionId, "", "", "", "", "", "", sessionKey, wxPlatform, 0, 0)
  249. //如果插入失败,那么直接将错误信息返回
  250. if recordErr != nil {
  251. err = recordErr
  252. return
  253. }
  254. needUpdateSessionKey = false //因为是新增用户微信信息,所以不需要更新sessionKey的数据了
  255. //插入成功后,需要重新查询该用户,并进入下面的逻辑
  256. goto QUERY_WX_USER
  257. } else if wxUserErr == ERR_USER_NOT_BIND {
  258. // 未绑定则去查询unionId是否已经绑定了用户(其他平台,不区分平台),有相应的手机号邮箱信息则自动绑定
  259. //platformUser, platformErr := GetFirstWxUserItemByUnionId(unionId)
  260. //if platformErr == nil {
  261. // // 当公众号用户存在时
  262. // if platformUser.Mobile != "" || platformUser.Email != "" {
  263. // // 有手机号或邮箱则绑定信息则自动绑定并新增wx_user
  264. // countryCode := 0
  265. // if platformUser.CountryCode != "" {
  266. // countryCode, _ = strconv.Atoi(platformUser.CountryCode)
  267. // }
  268. // tempToken, tempUser, tempErr, errMsg := BindWxUser(openId, platformUser.Mobile, platformUser.Email, "", 3, countryCode, 1)
  269. // if tempErr != nil {
  270. // err = errors.New("自动绑定公众号用户失败,Err:" + tempErr.Error() + ", errMsg:" + errMsg)
  271. // return
  272. // }
  273. // token = tempToken
  274. // userId = int(tempUser.UserID)
  275. // isBind = true
  276. // return
  277. // }
  278. //}
  279. } else if wxUserErr != nil {
  280. err = wxUserErr
  281. return
  282. }
  283. //更新微信用户的sessionKey
  284. if needUpdateSessionKey {
  285. _ = user_record.ModifySessionKeyByOpenid(openId, sessionKey)
  286. }
  287. // 如果已经登录注册绑定的情况下/或者首次登录且为弘则研究公众号用户
  288. if wxUserErr == nil {
  289. userId = int(wxUser.UserID)
  290. // 如果账户有绑定了手机号或者邮箱,那么标记为已绑定
  291. if wxUser.Mobile != "" || wxUser.Email != "" {
  292. isBind = true
  293. }
  294. }
  295. //获取登录token
  296. tokenItem, tokenErr := session.GetTokenByOpenId(openId)
  297. if tokenErr != nil && tokenErr != utils.ErrNoRow {
  298. err = errors.New("登录失败,获取token失败:" + tokenErr.Error())
  299. return
  300. }
  301. if tokenErr != nil && tokenErr == utils.ErrNoRow {
  302. timeUnix := time.Now().Unix()
  303. timeUnixStr := strconv.FormatInt(timeUnix, 10)
  304. token = utils.MD5(openId) + utils.MD5(timeUnixStr)
  305. //新增session
  306. {
  307. sessionItem := &session.Session{
  308. OpenID: openId,
  309. UserID: int64(userId),
  310. CreatedTime: time.Now(),
  311. LastUpdatedTime: time.Now(),
  312. ExpireTime: time.Now().AddDate(0, 3, 0),
  313. AccessToken: token,
  314. }
  315. sessionErr := sessionItem.Create()
  316. if err != nil {
  317. err = errors.New("登录失败,新增用户session信息失败:" + sessionErr.Error())
  318. return
  319. }
  320. }
  321. } else {
  322. token = tokenItem.AccessToken
  323. //如果联系人编号不为空,且联系人编号与session里面的联系人编号不一致的时候,需要做session变更
  324. //if userId > 0 && tokenItem.UserID != int64(userId) {
  325. // _ = tokenItem.UpdateSession(int64(userId), time.Now().AddDate(0, 1, 0))
  326. //}
  327. //if userId > 0 {
  328. //}
  329. _ = tokenItem.UpdateSession(int64(userId), time.Now().AddDate(0, 1, 0))
  330. }
  331. //新增登录日志
  332. {
  333. loginLog := &wx_user_log.WxUserLog{
  334. UserID: userId,
  335. OpenID: openId,
  336. UnionID: unionId,
  337. CreateTime: time.Now(),
  338. Handle: "yb_login",
  339. Remark: token,
  340. }
  341. go loginLog.Create()
  342. }
  343. return
  344. }
  345. // AddUserRecord 添加第三方用户(微信)记录
  346. func AddUserRecord(openId, unionId, nickName, realName, province, city, country, headimgurl, sessionKey string, platform, sex, subscribe int) (userRecordInfo *user_record.UserRecord, err error) {
  347. find, err := user_record.GetByOpenID(openId)
  348. if err == nil {
  349. userRecordInfo = find
  350. return
  351. }
  352. if err != utils.ErrNoRow {
  353. return
  354. }
  355. userRecordInfo = &user_record.UserRecord{
  356. OpenID: openId, //用户open_id
  357. UnionID: unionId, //用户union_id
  358. Subscribe: int8(subscribe),
  359. NickName: nickName, //用户昵称,最大长度:32
  360. RealName: realName, //用户实际名称,最大长度:32
  361. Sex: int64(sex), //普通用户性别,1为男性,2为女性
  362. Province: province, //普通用户个人资料填写的省份,最大长度:30
  363. City: city, //普通用户个人资料填写的城市,最大长度:30
  364. Country: country, //国家,如中国为CN,最大长度:30
  365. Headimgurl: headimgurl, //用户第三方(微信)头像,最大长度:512
  366. CreateTime: time.Now(), //创建时间,关系添加时间、用户授权时间
  367. CreatePlatform: int8(platform), //注册平台,1:日度点评公众号,2:管理后台,3:pc端网站,4:查研观向小程序;默认:1
  368. SessionKey: sessionKey, //微信小程序会话密钥,最大长度:255
  369. }
  370. err = userRecordInfo.Create()
  371. return
  372. }
  373. // GetInfoByClaims 从Claims中获取用户信息
  374. func GetInfoByClaims(c *gin.Context) (userInfo UserInfo) {
  375. //获取jwt数据失败
  376. claims, _ := c.Get("userInfo")
  377. userInfo = claims.(UserInfo)
  378. return
  379. }
  380. // GetAdminByUserInfo 判断当前用户是否为内部人员
  381. func GetAdminByUserInfo(userInfo UserInfo) (ok bool, adminInfo *admin2.Admin, err error) {
  382. mobile := userInfo.Mobile
  383. if mobile == "" {
  384. // 用户有可能是通过邮箱登录
  385. return
  386. }
  387. if userInfo.CompanyID != utils.HzCompanyId {
  388. return
  389. }
  390. adminInfo, err = admin2.GetAdminByMobile(mobile)
  391. if err != nil {
  392. if err == utils.ErrNoRow {
  393. err = nil
  394. return
  395. }
  396. return
  397. }
  398. if adminInfo.Enabled != 1 {
  399. return
  400. }
  401. ok = true
  402. return
  403. }
  404. // GetResearcherByUserInfo 判断当前用户是否为研究员-以是否有研究分组为判断标准
  405. func GetResearcherByUserInfo(userInfo UserInfo) (ok bool, adminInfo *admin2.Admin, err error) {
  406. mobile := userInfo.Mobile
  407. if mobile == "" {
  408. // 用户有可能是通过邮箱登录
  409. return
  410. }
  411. if userInfo.CompanyID != utils.HzCompanyId {
  412. return
  413. }
  414. adminInfo, err = admin2.GetAdminByMobile(mobile)
  415. if err != nil {
  416. if err == utils.ErrNoRow {
  417. err = nil
  418. return
  419. }
  420. return
  421. }
  422. if adminInfo.Enabled != 1 {
  423. return
  424. }
  425. researchGroupList, e := research_variety_tag_relation.GetResearchVarietyTagRelationByAdminId(int(adminInfo.AdminID))
  426. if e != nil {
  427. err = e
  428. return
  429. }
  430. if len(researchGroupList) > 0 {
  431. ok = true
  432. }
  433. return
  434. }
  435. // GetUserInfoByToken 通过token获取用户信息
  436. func GetUserInfoByToken(token string) (userInfo UserInfo, err error) {
  437. sessionInfo, e := session.GetTokenByToken(token)
  438. if e != nil {
  439. err = errors.New("找不到对应session")
  440. return
  441. }
  442. if sessionInfo.SessionID <= 0 {
  443. err = errors.New("找不到对应session")
  444. return
  445. }
  446. if sessionInfo.OpenID != "" {
  447. u, e := GetWxUserItemByOpenId(sessionInfo.OpenID)
  448. if e != nil {
  449. err = errors.New("用户记录不存在或未绑定")
  450. return
  451. }
  452. userInfo = u
  453. } else {
  454. // PC端
  455. u, e := GetWxUserItemByUserId(int(sessionInfo.UserID), utils.USER_RECORD_PLATFORM_PC)
  456. if e != nil {
  457. err = errors.New("用户PC记录不存在或未绑定")
  458. return
  459. }
  460. userInfo = u
  461. }
  462. return
  463. }