user.go 13 KB

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