package amo import ( "bytes" "encoding/json" "errors" "fmt" "github.com/dgrijalva/jwt-go" "golang.org/x/oauth2" "net/http" "net/url" "time" ) const ( OAUTH_URL = "https://www.amocrm.ru/oauth" ) type Client struct { App *ClientApp HTTPClient *http.Client Subdomain string // Субдомен с которым работаем Code string // Код авторизации Token *oauth2.Token } type ClientApp struct { Secret string // Секретка интеграции ClientID string // Айди интеграции RedirectUri string // Страница перенаправления } func NewClientApp(secret string, ClientID string, redirectUri string) *ClientApp { return &ClientApp{Secret: secret, ClientID: ClientID, RedirectUri: redirectUri} } func (ca *ClientApp) GenerateOAuthUrl() string { val := make(url.Values) //val.Set("state", "myState123") val.Set("client_id", ca.ClientID) val.Set("redirect_uri", ca.RedirectUri) val.Set("mode", "popup") return OAUTH_URL + "?" + val.Encode() } func (ca *ClientApp) DecodeJwt(r *http.Request) (*XAuthToken, error) { tokenHeader := r.Header.Get("x-auth-token") if tokenHeader == "" { return nil, errors.New("empty jwt") } token, err := jwt.ParseWithClaims(tokenHeader, &XAuthToken{}, func(token *jwt.Token) (interface{}, error) { return []byte(ca.Secret), nil }) if err != nil { return nil, err } claims, ok := token.Claims.(*XAuthToken) if !ok || !token.Valid { fmt.Println("token:", token) fmt.Println("claims:", claims) fmt.Println("valid:", token.Valid) return nil, errors.New("invalid token") } return claims, nil } func (ca *ClientApp) NewClient(subdomain, code string) *Client { return &Client{ App: ca, HTTPClient: &http.Client{}, Subdomain: "https://" + subdomain, Code: code, } } // AuthCode - обменивает код авторизации на токен func (c *Client) AuthCode() (*oauth2.Token, error) { body := map[string]string{ "client_id": c.App.ClientID, "client_secret": c.App.Secret, "grant_type": "authorization_code", "code": c.Code, "redirect_uri": c.App.RedirectUri, } bytesBody, err := json.Marshal(body) if err != nil { return nil, err } req, err := http.NewRequest("POST", c.Subdomain+"/oauth2/access_token", bytes.NewBuffer(bytesBody)) if err != nil { fmt.Println("1") return nil, err } c.setHeaders(req) resp, err := c.HTTPClient.Do(req) if err != nil { fmt.Println("2") return nil, err } var response RespAuthCode err = json.NewDecoder(resp.Body).Decode(&response) if err != nil { return nil, err } c.Token = &oauth2.Token{ AccessToken: response.AccessToken, TokenType: response.TokenType, RefreshToken: response.RefreshToken, Expiry: time.Now().Add(time.Duration(response.ExpiresIn) * time.Second), } return c.Token, nil } func (c *Client) SetToken(token *oauth2.Token) { c.Token = token } func (c *Client) GetAccount() (*Account, error) { req, err := http.NewRequest("GET", c.Subdomain+"/api/v4/account", nil) if err != nil { fmt.Println("1") return nil, err } c.setHeaders(req) resp, err := c.HTTPClient.Do(req) if err != nil { fmt.Println("2") return nil, err } var response Account err = json.NewDecoder(resp.Body).Decode(&response) if err != nil { fmt.Println("3") return nil, err } return &response, nil } func (c *Client) GetLeadById(id string) (*Lead, error) { req, err := http.NewRequest("GET", fmt.Sprintf("%v/api/v4/leads/%v?with=contacts,catalog_elements,is_price_modified_by_robot,loss_reason", c.Subdomain, id), nil, ) fmt.Println("URL:", fmt.Sprintf("%v/api/v4/leads/%v?with=contacts,catalog_elements,is_price_modified_by_robot,"+ "loss_reason", c.Subdomain, id)) if err != nil { fmt.Println("1") return nil, err } c.setHeaders(req) resp, err := c.HTTPClient.Do(req) if err != nil { fmt.Println("2") return nil, err } var response Lead err = json.NewDecoder(resp.Body).Decode(&response) if err != nil { return nil, err } return &response, nil } func (c *Client) GetContactById(id string) (*Contact, error) { req, err := http.NewRequest("GET", fmt.Sprintf("%v/api/v4/contacts/%v?with=catalog_elements,leads,customers", c.Subdomain, id), nil, ) if err != nil { fmt.Println("1") return nil, err } c.setHeaders(req) resp, err := c.HTTPClient.Do(req) if err != nil { fmt.Println("2") return nil, err } var response Contact err = json.NewDecoder(resp.Body).Decode(&response) if err != nil { return nil, err } return &response, nil } func (c *Client) GetCompanyById(id string) (*Company, error) { req, err := http.NewRequest("GET", fmt.Sprintf("%v/api/v4/companies/%v?with=contacts,leads,catalog_elements,customers", c.Subdomain, id), nil, ) if err != nil { fmt.Println("1") return nil, err } c.setHeaders(req) resp, err := c.HTTPClient.Do(req) if err != nil { fmt.Println("2") return nil, err } var response Company err = json.NewDecoder(resp.Body).Decode(&response) if err != nil { return nil, err } return &response, nil } func (c *Client) setHeaders(req *http.Request) { req.Header.Set("User-Agent", "amoCRM-oAuth-client/1.0") req.Header.Set("Content-Type", "application/json") if c.Token != nil { c.Token.SetAuthHeader(req) } }