mirror of
https://github.com/chaitin/MonkeyCode.git
synced 2026-02-02 14:53:55 +08:00
100 lines
2.6 KiB
Go
100 lines
2.6 KiB
Go
package oauth
|
|
|
|
import (
|
|
"fmt"
|
|
"time"
|
|
|
|
"github.com/google/uuid"
|
|
|
|
"github.com/chaitin/MonkeyCode/backend/domain"
|
|
"github.com/chaitin/MonkeyCode/backend/pkg/request"
|
|
)
|
|
|
|
type DingTalk struct {
|
|
ClientID string
|
|
ClientSecret string
|
|
RedirectURI string
|
|
client *request.Client
|
|
}
|
|
|
|
var _ domain.OAuther = &DingTalk{}
|
|
|
|
func NewDingTalk(config domain.OAuthConfig) *DingTalk {
|
|
client := request.NewClient("https", "api.dingtalk.com", 30*time.Second)
|
|
client.SetDebug(config.Debug)
|
|
return &DingTalk{
|
|
ClientID: config.ClientID,
|
|
ClientSecret: config.ClientSecret,
|
|
RedirectURI: config.RedirectURI,
|
|
client: client,
|
|
}
|
|
}
|
|
|
|
// GetUserInfo implements domain.OAuther.
|
|
func (d *DingTalk) GetUserInfo(code string) (*domain.OAuthUserInfo, error) {
|
|
accessToken, err := d.getAccessToken(code)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
return d.getUserInfo(accessToken)
|
|
}
|
|
|
|
type dingtalkAccessTokenResp struct {
|
|
AccessToken string `json:"accessToken"`
|
|
ExpiresIn int `json:"expireIn"`
|
|
RefreshToken string `json:"refreshToken"`
|
|
CorpID string `json:"corpId"`
|
|
}
|
|
|
|
type dingtalkAccessTokenReq struct {
|
|
ClientID string `json:"clientId"`
|
|
ClientSecret string `json:"clientSecret"`
|
|
Code string `json:"code"`
|
|
GrantType string `json:"grantType"`
|
|
}
|
|
|
|
func (d *DingTalk) getAccessToken(code string) (string, error) {
|
|
resp, err := request.Post[dingtalkAccessTokenResp](d.client, "/v1.0/oauth2/userAccessToken", dingtalkAccessTokenReq{
|
|
ClientID: d.ClientID,
|
|
ClientSecret: d.ClientSecret,
|
|
Code: code,
|
|
GrantType: "authorization_code",
|
|
})
|
|
if err != nil {
|
|
return "", err
|
|
}
|
|
return resp.AccessToken, nil
|
|
}
|
|
|
|
type dingtalkUserInfoResp struct {
|
|
Nick string `json:"nick"`
|
|
AvatarURL string `json:"avatarUrl"`
|
|
Mobile string `json:"mobile"`
|
|
OpenID string `json:"openId"`
|
|
UnionID string `json:"unionId"`
|
|
Email string `json:"email"`
|
|
StateCode string `json:"stateCode"`
|
|
}
|
|
|
|
func (d *DingTalk) getUserInfo(accessToken string) (*domain.OAuthUserInfo, error) {
|
|
resp, err := request.Get[dingtalkUserInfoResp](d.client, "/v1.0/contact/users/me", request.WithHeader(request.Header{
|
|
"x-acs-dingtalk-access-token": accessToken,
|
|
}))
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
return &domain.OAuthUserInfo{
|
|
ID: resp.OpenID,
|
|
UnionID: resp.UnionID,
|
|
Name: resp.Nick,
|
|
Email: resp.Email,
|
|
AvatarURL: resp.AvatarURL,
|
|
}, nil
|
|
}
|
|
|
|
func (d *DingTalk) GetAuthorizeURL() (string, string) {
|
|
state := uuid.NewString()
|
|
url := fmt.Sprintf("https://login.dingtalk.com/oauth2/auth?response_type=code&scope=openid&client_id=%s&prompt=consent&state=%s&redirect_uri=%s", d.ClientID, state, d.RedirectURI)
|
|
return state, url
|
|
}
|