feishu.go 6.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218
  1. package service
  2. import (
  3. "context"
  4. "encoding/base64"
  5. "errors"
  6. "gadmin/config"
  7. "gadmin/internal/admin/forms"
  8. "gadmin/internal/admin/library/feishu"
  9. "gadmin/internal/gorm/model"
  10. "gadmin/internal/gorm/query"
  11. "gadmin/utility/serializer"
  12. "gadmin/utility/token"
  13. "github.com/gin-gonic/gin"
  14. jsoniter "github.com/json-iterator/go"
  15. "github.com/larksuite/oapi-sdk-go/v3/core"
  16. "github.com/larksuite/oapi-sdk-go/v3/service/authen/v1"
  17. "github.com/sirupsen/logrus"
  18. "gorm.io/gorm"
  19. "strings"
  20. "time"
  21. )
  22. var FeiShu = new(feishuService)
  23. type feishuService struct{}
  24. func (s *feishuService) FeiShuUserLogin(c *gin.Context) serializer.Response {
  25. q := query.Use(config.AdminDB).AdminUser
  26. //encodeToken := token.GetAuthorization(c)
  27. //if encodeToken != "" {
  28. // bytesT, err := base64.URLEncoding.DecodeString(encodeToken)
  29. // if err != nil {
  30. // logrus.Warningf("middleware base64.URLEncoding.DecodeString:%+v", err.Error())
  31. // return serializer.CheckLogin()
  32. // }
  33. // t := string(bytesT)
  34. // tokenKey := config.GetTokenKey(t)
  35. // if config.TokenRedis.Exists(tokenKey).Val() == 0 {
  36. // return serializer.CheckLogin()
  37. // }
  38. // userStr := config.TokenRedis.Get(tokenKey).Val()
  39. //
  40. // claims := new(token.UserClaims)
  41. // if err := jsoniter.UnmarshalFromString(userStr, claims); err != nil {
  42. // return serializer.CheckLogin()
  43. // }
  44. //
  45. // // 查询登录token是否有效
  46. // key := config.GetUserTokenKey(claims.ID)
  47. // tokenCTStr := config.TokenRedis.HGet(key, t).Val()
  48. // tokenCreateTime, err := strconv.Atoi(tokenCTStr)
  49. // if err != nil {
  50. // logrus.Warningf("middleware config.LogRedis.HGet:%+v", err.Error())
  51. // return serializer.CheckLogin()
  52. // }
  53. // tokenCT := time.Unix(int64(tokenCreateTime), 0)
  54. //
  55. // if tokenCT.Before(time.Now().Add(-config.TokenExpireTime)) {
  56. // return serializer.CheckLogin()
  57. // }
  58. //
  59. // u, err := q.Where(q.ID.Eq(claims.ID)).First()
  60. // if err != nil && !errors.Is(err, gorm.ErrRecordNotFound) {
  61. // return serializer.Err(2, "", err)
  62. // }
  63. // if u.Status != 1 {
  64. // return serializer.ParamErr("账号已被禁用", nil)
  65. // }
  66. // user := &token.UserClaims{
  67. // ID: u.ID,
  68. // UserName: u.UserName,
  69. // RoleId: int64(u.RoleID),
  70. // Avatar: u.Avatar,
  71. // Nickname: u.Nickname,
  72. // AccessToken: t,
  73. // }
  74. // userStr, _ = jsoniter.MarshalToString(user)
  75. //
  76. // config.TokenRedis.HSet(key, t, time.Now().Unix())
  77. // config.TokenRedis.Expire(key, time.Hour*12)
  78. //
  79. // config.TokenRedis.Set(tokenKey, userStr, time.Hour*12)
  80. //
  81. // return serializer.Suc(forms.UserLoginRes{
  82. // ID: u.ID,
  83. // UserName: u.UserName,
  84. // Nickname: u.Nickname,
  85. // Status: u.Status,
  86. // Avatar: u.Avatar,
  87. // Token: encodeToken,
  88. // })
  89. //}
  90. code := c.Query("code")
  91. if code == "" {
  92. return serializer.ParamErr("code is empty", nil)
  93. }
  94. feishuUserInfo, err := s.GetFeiShuUserByCode(code)
  95. if err != nil {
  96. return serializer.Err(1, "", err)
  97. }
  98. if feishuUserInfo == nil {
  99. return serializer.Err(1, "获取用户信息失败", nil)
  100. }
  101. u, err := q.Where(q.FeishuUnionID.Eq(*feishuUserInfo.UnionId)).First()
  102. if err != nil && !errors.Is(err, gorm.ErrRecordNotFound) {
  103. return serializer.Err(2, "", err)
  104. }
  105. if u == nil {
  106. // 不存在,创建
  107. u = &model.AdminUser{
  108. UserName: *feishuUserInfo.Name,
  109. Nickname: *feishuUserInfo.Name,
  110. Avatar: *feishuUserInfo.AvatarUrl,
  111. //Mobile: *feishuUserInfo.Mobile,
  112. FeishuUnionID: *feishuUserInfo.UnionId,
  113. CreatedAt: time.Now(),
  114. }
  115. if err = q.WithContext(context.Background()).Create(u); err != nil {
  116. return serializer.DBErr(err.Error(), err)
  117. }
  118. return serializer.Err(9999, "注册成功,请联系管理员分配权限!", nil)
  119. }
  120. if u.Status != 1 {
  121. return serializer.ParamErr("账号已被禁用", nil)
  122. }
  123. if u.RoleID == 0 {
  124. return serializer.Err(9999, "请联系管理员分配权限!", nil)
  125. }
  126. t := token.GenerateTokenUsingUUID()
  127. // 记录登录token
  128. key := config.GetUserTokenKey(u.ID)
  129. config.TokenRedis.HSet(key, t, time.Now().Unix())
  130. config.TokenRedis.Expire(key, time.Hour*12)
  131. tokenKey := config.GetTokenKey(t)
  132. user := &token.UserClaims{
  133. ID: u.ID,
  134. UserName: u.UserName,
  135. RoleId: int64(u.RoleID),
  136. Avatar: u.Avatar,
  137. Nickname: u.Nickname,
  138. AccessToken: t,
  139. }
  140. userStr, err := jsoniter.MarshalToString(user)
  141. if err != nil {
  142. return serializer.Err(1, "", err)
  143. }
  144. config.TokenRedis.Set(tokenKey, userStr, time.Hour*12)
  145. return serializer.Suc(forms.UserLoginRes{
  146. ID: u.ID,
  147. UserName: u.UserName,
  148. Nickname: u.Nickname,
  149. Status: u.Status,
  150. Avatar: u.Avatar,
  151. Token: base64.URLEncoding.EncodeToString([]byte(t)),
  152. })
  153. }
  154. func (s *feishuService) GetFeiShuUserByCode(code string) (*larkauthen.GetUserInfoRespData, error) {
  155. // 使用获取到的 code 获取 token
  156. req := larkauthen.NewCreateAccessTokenReqBuilder().Body(
  157. larkauthen.NewCreateAccessTokenReqBodyBuilder().
  158. GrantType("authorization_code").
  159. Code(code).
  160. Build(),
  161. ).Build()
  162. resp, err := feishu.LarkClient.Authen.V1.AccessToken.Create(context.Background(), req)
  163. if err != nil {
  164. logrus.Warnf("GetAccessToken() failed with '%s'\n", err)
  165. return nil, err
  166. }
  167. if !resp.Success() {
  168. logrus.Warnf("logId: %s, error response: \n%s", resp.RequestId(), larkcore.Prettify(resp.CodeError))
  169. return nil, err
  170. }
  171. userInfoResp, err := feishu.LarkClient.Authen.V1.UserInfo.Get(context.Background(), larkcore.WithUserAccessToken(*resp.Data.AccessToken))
  172. // 处理错误
  173. if err != nil {
  174. logrus.Warnf("GetUserInfo() failed with '%s'\n", err)
  175. return nil, err
  176. }
  177. // 服务端错误处理
  178. if !userInfoResp.Success() {
  179. logrus.Warnf("logId: %s, error response: \n%s", userInfoResp.RequestId(), larkcore.Prettify(userInfoResp.CodeError))
  180. return nil, errors.New(larkcore.Prettify(userInfoResp.CodeError))
  181. }
  182. return userInfoResp.Data, nil
  183. }
  184. // 取出手机号码
  185. func extractPhoneNumber(phone string) string {
  186. // 定义可能的国际前缀列表
  187. prefixes := []string{"+86", "86"}
  188. for _, prefix := range prefixes {
  189. if strings.HasPrefix(phone, prefix) {
  190. // 如果手机号以该前缀开头,则返回去掉前缀后的部分
  191. return strings.TrimPrefix(phone, prefix)
  192. }
  193. }
  194. // 如果没有匹配的前缀,直接返回原号码
  195. return phone
  196. }