user.go 15 KB

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