package api import ( "bytes" "encoding/json" "errors" "fmt" "io/ioutil" "net/http" "net/url" ) type ClientOptions struct { Url string AccessToken string RefreshToken string } type Client struct { options *ClientOptions BaseUrl *url.URL } type requestOptions struct { HttpMethod string Body interface{} Headers map[string]string } type OauthTokenResponse struct { TokenType string `json:"token_type"` ExpiresIn int `json:"expires_in"` AccessToken string `json:"access_token"` RefreshToken string `json:"refresh_token"` } func NewClient(options *ClientOptions) (*Client, error) { if len(options.AccessToken) == 0 || len(options.RefreshToken) == 0 || len(options.Url) == 0 { return nil, errors.New("AmoCrm: Invalid options") } resolvedUrl, err := url.Parse(options.Url) if err != nil { return nil, err } return &Client{ options: options, BaseUrl: resolvedUrl, }, nil } func (api *Client) doRequest(resourceUrl string, requestParams requestOptions, result interface{}) error { resolvedUrl, err := url.Parse(resourceUrl) if err != nil { return err } requestUrl := api.BaseUrl.ResolveReference(resolvedUrl) requestBody := new(bytes.Buffer) if requestParams.Body != nil { encoder := json.NewEncoder(requestBody) if err := encoder.Encode(requestParams.Body); err != nil { return err } } request, err := http.NewRequest(requestParams.HttpMethod, requestUrl.String(), requestBody) if err != nil { return err } if requestParams.Headers != nil { for k, v := range requestParams.Headers { request.Header.Set(k, v) } } response, err := http.DefaultClient.Do(request) if err != nil { return errors.New(fmt.Sprintf("Request error: %s %d %s %s", err.Error(), response.StatusCode, requestParams.HttpMethod, resourceUrl)) } defer response.Body.Close() if response.StatusCode >= 400 { bodyBytes, _ := ioutil.ReadAll(response.Body) return errors.New(fmt.Sprintf("%s %d %s %s", string(bodyBytes), response.StatusCode, requestParams.HttpMethod, resourceUrl)) } if result != nil { decoder := json.NewDecoder(response.Body) err = decoder.Decode(result) if err != nil { return err } } return nil } func (api *Client) RefreshToken() (*map[string]interface{}, error) { result := new(map[string]interface{}) request := map[string]string{ "client_id": "7c08f8a9-c49d-4378-890c-a6dba79f88f9", "client_secret": "SDqfNBxxk98zq6CRjLN7tHeyVHS0EAwlQkirAx0i71s81N9fXGPlTlkoxIOZd6Rg", "grant_type": "refresh_token", "refresh_token": api.options.RefreshToken, "redirect_uri": "https://ddamosmartheadru.amocrm.ru", } err := api.doRequest("/oauth2/access_token", requestOptions{ HttpMethod: http.MethodPost, Body: request, Headers: map[string]string{ "Accept": "application/json", "Cache-Control": "no-cache", "Content-Type": "application/json", }, }, result) return result, err } func (api *Client) Get(resource string, result interface{}) error { return api.doRequest(resource, requestOptions{ HttpMethod: http.MethodGet, Body: nil, Headers: map[string]string{ "Accept": "application/json", "Cache-Control": "no-cache", "Content-Type": "application/json", "Authorization": fmt.Sprintf("Bearer %s", api.options.AccessToken), }, }, result) } func (api *Client) Post(resource string, request interface{}, result interface{}) error { return api.doRequest(resource, requestOptions{ HttpMethod: http.MethodPost, Body: request, Headers: map[string]string{ "Accept": "application/json", "Cache-Control": "no-cache", "Content-Type": "application/json", "Authorization": fmt.Sprintf("Bearer %s", api.options.AccessToken), }, }, result) } func (api *Client) Patch(resource string, request interface{}, result interface{}) error { return api.doRequest(resource, requestOptions{ HttpMethod: http.MethodPatch, Body: request, Headers: map[string]string{ "Accept": "application/json", "Cache-Control": "no-cache", "Content-Type": "application/json", "Authorization": fmt.Sprintf("Bearer %s", api.options.AccessToken), }, }, result) }