feishu.go 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170
  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. code := c.Query("code")
  27. if code == "" {
  28. return serializer.ParamErr("code is empty", nil)
  29. }
  30. feishuUserInfo, err := s.GetFeiShuUserByCode(code)
  31. if err != nil {
  32. return serializer.Err(1, "", err)
  33. }
  34. if feishuUserInfo == nil {
  35. return serializer.Err(1, "获取用户信息失败", nil)
  36. }
  37. u, err := q.Where(q.FeishuUnionID.Eq(*feishuUserInfo.UnionId)).First()
  38. if err != nil && !errors.Is(err, gorm.ErrRecordNotFound) {
  39. return serializer.Err(2, "", err)
  40. }
  41. if u == nil {
  42. // 不存在,创建
  43. u = &model.AdminUser{
  44. UserName: *feishuUserInfo.Name,
  45. Nickname: *feishuUserInfo.Name,
  46. Avatar: *feishuUserInfo.AvatarUrl,
  47. //Mobile: *feishuUserInfo.Mobile,
  48. FeishuUnionID: *feishuUserInfo.UnionId,
  49. CreatedAt: time.Now(),
  50. }
  51. if err = q.WithContext(context.Background()).Create(u); err != nil {
  52. return serializer.DBErr(err.Error(), err)
  53. }
  54. return serializer.Err(9999, "注册成功,请联系管理员分配权限!", nil)
  55. }
  56. if u.Status != 1 {
  57. return serializer.ParamErr("账号已被禁用", nil)
  58. }
  59. if u.RoleID == 0 {
  60. return serializer.Err(9999, "请联系管理员分配权限!", nil)
  61. }
  62. // 验证用户角色状态
  63. rdb := query.Use(config.AdminDB).AdminRole
  64. result, err := rdb.Where(rdb.ID.Eq(int64(u.RoleID))).First()
  65. if err != nil {
  66. logrus.Warnf("AdminRole... err:%+v", err)
  67. return serializer.ParamErr("获取角色信息失败", err)
  68. }
  69. if result == nil {
  70. return serializer.ParamErr("获取角色信息失败", nil)
  71. }
  72. if result.Status != 1 {
  73. return serializer.ParamErr("角色权限已被禁用", nil)
  74. }
  75. // 生成token
  76. t := token.GenerateTokenUsingUUID()
  77. // 记录登录token
  78. key := config.GetUserTokenKey(u.ID)
  79. config.TokenRedis.HSet(key, t, time.Now().Unix())
  80. config.TokenRedis.Expire(key, time.Hour*12)
  81. tokenKey := config.GetTokenKey(t)
  82. user := &token.UserClaims{
  83. ID: u.ID,
  84. UserName: u.UserName,
  85. RoleId: int64(u.RoleID),
  86. Avatar: u.Avatar,
  87. Nickname: u.Nickname,
  88. AccessToken: t,
  89. }
  90. userStr, err := jsoniter.MarshalToString(user)
  91. if err != nil {
  92. return serializer.Err(1, "", err)
  93. }
  94. config.TokenRedis.Set(tokenKey, userStr, time.Hour*12)
  95. return serializer.Suc(forms.UserLoginRes{
  96. ID: u.ID,
  97. UserName: u.UserName,
  98. Nickname: u.Nickname,
  99. Status: u.Status,
  100. Avatar: u.Avatar,
  101. Token: base64.URLEncoding.EncodeToString([]byte(t)),
  102. })
  103. }
  104. func (s *feishuService) GetFeiShuUserByCode(code string) (*larkauthen.GetUserInfoRespData, error) {
  105. // 使用获取到的 code 获取 token
  106. req := larkauthen.NewCreateAccessTokenReqBuilder().Body(
  107. larkauthen.NewCreateAccessTokenReqBodyBuilder().
  108. GrantType("authorization_code").
  109. Code(code).
  110. Build(),
  111. ).Build()
  112. resp, err := feishu.LarkClient.Authen.V1.AccessToken.Create(context.Background(), req)
  113. if err != nil {
  114. logrus.Warnf("GetAccessToken() failed with '%s'\n", err)
  115. return nil, err
  116. }
  117. if !resp.Success() {
  118. logrus.Warnf("logId: %s, error response: \n%s", resp.RequestId(), larkcore.Prettify(resp.CodeError))
  119. return nil, err
  120. }
  121. userInfoResp, err := feishu.LarkClient.Authen.V1.UserInfo.Get(context.Background(), larkcore.WithUserAccessToken(*resp.Data.AccessToken))
  122. // 处理错误
  123. if err != nil {
  124. logrus.Warnf("GetUserInfo() failed with '%s'\n", err)
  125. return nil, err
  126. }
  127. // 服务端错误处理
  128. if !userInfoResp.Success() {
  129. logrus.Warnf("logId: %s, error response: \n%s", userInfoResp.RequestId(), larkcore.Prettify(userInfoResp.CodeError))
  130. return nil, errors.New(larkcore.Prettify(userInfoResp.CodeError))
  131. }
  132. return userInfoResp.Data, nil
  133. }
  134. // 取出手机号码
  135. func extractPhoneNumber(phone string) string {
  136. // 定义可能的国际前缀列表
  137. prefixes := []string{"+86", "86"}
  138. for _, prefix := range prefixes {
  139. if strings.HasPrefix(phone, prefix) {
  140. // 如果手机号以该前缀开头,则返回去掉前缀后的部分
  141. return strings.TrimPrefix(phone, prefix)
  142. }
  143. }
  144. // 如果没有匹配的前缀,直接返回原号码
  145. return phone
  146. }