client.go 2.4 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980
  1. package dingtalk
  2. import (
  3. "context"
  4. "fmt"
  5. "time"
  6. openapi "github.com/alibabacloud-go/darabonba-openapi/v2/client"
  7. dingtalkcard_1_0 "github.com/alibabacloud-go/dingtalk/card_1_0"
  8. dingtalkim_1_0 "github.com/alibabacloud-go/dingtalk/im_1_0"
  9. dingtalkoauth2_1_0 "github.com/alibabacloud-go/dingtalk/oauth2_1_0"
  10. "github.com/alibabacloud-go/tea/tea"
  11. )
  12. // Client 钉钉官方 SDK 客户端(按机器人凭证一份实例)
  13. type Client struct {
  14. ClientID string
  15. ClientSecret string
  16. cardClient *dingtalkcard_1_0.Client
  17. imClient *dingtalkim_1_0.Client
  18. oauthClient *dingtalkoauth2_1_0.Client
  19. }
  20. // NewDingTalkClient 创建钉钉官方客户端
  21. func NewDingTalkClient(clientID, clientSecret string) *Client {
  22. config := &openapi.Config{
  23. Protocol: tea.String("https"),
  24. RegionId: tea.String("central"),
  25. }
  26. cardClient, _ := dingtalkcard_1_0.NewClient(config)
  27. imClient, _ := dingtalkim_1_0.NewClient(config)
  28. oauthClient, _ := dingtalkoauth2_1_0.NewClient(config)
  29. return &Client{
  30. ClientID: clientID,
  31. ClientSecret: clientSecret,
  32. imClient: imClient,
  33. oauthClient: oauthClient,
  34. cardClient: cardClient,
  35. }
  36. }
  37. // GetAccessToken 获取 access_token(带 L1 内存 + L2 可插拔缓存 + singleflight)
  38. func (c *Client) GetAccessToken() (string, error) {
  39. return c.GetAccessTokenCtx(context.Background())
  40. }
  41. // GetAccessTokenCtx 带 ctx 的 token 获取
  42. func (c *Client) GetAccessTokenCtx(ctx context.Context) (string, error) {
  43. return globalTokenManager.Fetch(ctx, c.ClientID, c.refreshAccessToken)
  44. }
  45. // InvalidateAccessToken 主动失效 token 缓存(收到授权类错误时调用)
  46. func (c *Client) InvalidateAccessToken(ctx context.Context) {
  47. globalTokenManager.Invalidate(ctx, c.ClientID)
  48. }
  49. // refreshAccessToken 真正调用钉钉接口获取 token,内部使用
  50. func (c *Client) refreshAccessToken(_ context.Context) (string, time.Duration, error) {
  51. req := &dingtalkoauth2_1_0.GetAccessTokenRequest{
  52. AppKey: tea.String(c.ClientID),
  53. AppSecret: tea.String(c.ClientSecret),
  54. }
  55. resp, err := c.oauthClient.GetAccessToken(req)
  56. if err != nil {
  57. return "", 0, err
  58. }
  59. if resp == nil || resp.Body == nil {
  60. return "", 0, fmt.Errorf("GetAccessToken 响应为空")
  61. }
  62. token := tea.StringValue(resp.Body.AccessToken)
  63. if token == "" {
  64. return "", 0, fmt.Errorf("GetAccessToken 返回空 token")
  65. }
  66. ttl := time.Duration(tea.Int64Value(resp.Body.ExpireIn)) * time.Second
  67. if ttl <= 0 {
  68. ttl = tokenMaxTTL
  69. }
  70. return token, ttl, nil
  71. }