From 0277b266bfa5c30b456e6516f188f0d27f290bf2 Mon Sep 17 00:00:00 2001 From: Aliaksandr Pliutau Date: Fri, 16 Oct 2015 17:00:57 +0700 Subject: [PATCH] GetRefreshToken --- auth.go | 29 +++++++++++++++++++++++++++++ auth_test.go | 16 ++++++++++++++++ client.go | 6 +----- types.go | 20 +++++++++++++------- 4 files changed, 59 insertions(+), 12 deletions(-) diff --git a/auth.go b/auth.go index 1ec522e..1153be0 100644 --- a/auth.go +++ b/auth.go @@ -1,9 +1,12 @@ package paypalsdk import ( + "net/http" "strings" "net/url" "errors" + "bytes" + "fmt" ) // GetAuthorizationCodeURL returns URL where we need to redirect user @@ -21,3 +24,29 @@ func (c *Client) GetAuthorizationCodeURL(redirectURI string, scopes []string) (s url.QueryEscape(c.ClientID) + "&response_type=code&scope=" + strings.Join(scopes, "+") + "&redirect_uri=" + url.QueryEscape(redirectURI), nil } + +// GetRefreshToken returns struct of RefreshTokenResponse +// Client must to get an authorization code before +// redirectURI must match with redirectURI sent to GetAuthorizationCodeURL +func (c *Client) GetRefreshToken(authorizationCode string, redirectURI string) (*RefreshTokenResponse, error) { + if authorizationCode == "" { + return &RefreshTokenResponse{}, errors.New("authorizationCode cannot be empty") + } + if redirectURI == "" { + return &RefreshTokenResponse{}, errors.New("redirectURI cannot be empty") + } + + buf := bytes.NewBuffer([]byte("grant_type=authorization_code&code=" + url.QueryEscape(authorizationCode) + "&redirect_uri=" + url.QueryEscape(redirectURI))) + req, err := http.NewRequest("POST", fmt.Sprintf("%s%s", c.APIBase, "/v1/identity/openidconnect/tokenservice"), buf) + if err != nil { + return &RefreshTokenResponse{}, err + } + + req.SetBasicAuth(c.ClientID, c.Secret) + req.Header.Set("Content-type", "application/x-www-form-urlencoded") + + r := RefreshTokenResponse{} + err = c.Send(req, &r) + + return &r, err +} diff --git a/auth_test.go b/auth_test.go index 418ae43..52895e0 100644 --- a/auth_test.go +++ b/auth_test.go @@ -22,3 +22,19 @@ func TestGetAuthorizationCodeURL(t *testing.T) { t.Errorf("GetAuthorizationCodeURL returns incorrect value for redirectURI=test and scope=address") } } + +func TestGetRefreshToken(t *testing.T) { + c, _ := NewClient("clid", "secret", APIBaseSandBox) + + _, err := c.GetRefreshToken("123", "") + if err == nil { + t.Errorf("redirectURI is required in GetRefreshToken") + } + + _, err = c.GetRefreshToken("", "123") + if err == nil { + t.Errorf("authorizationCode is required in GetRefreshToken") + } + + _, err = c.GetRefreshToken("123", "123") +} diff --git a/client.go b/client.go index e603c21..09123ab 100644 --- a/client.go +++ b/client.go @@ -6,7 +6,6 @@ import ( "net/http" "errors" "bytes" - "time" "fmt" "io" ) @@ -31,7 +30,7 @@ func (c *Client) GetAccessToken() (*TokenResponse, error) { buf := bytes.NewBuffer([]byte("grant_type=client_credentials")) req, err := http.NewRequest("POST", fmt.Sprintf("%s%s", c.APIBase, "/oauth2/token"), buf) if err != nil { - return nil, err + return &TokenResponse{}, err } req.SetBasicAuth(c.ClientID, c.Secret) @@ -39,9 +38,6 @@ func (c *Client) GetAccessToken() (*TokenResponse, error) { t := TokenResponse{} err = c.Send(req, &t) - if err == nil { - t.ExpiresAt = time.Now().Add(time.Duration(t.ExpiresIn/2) * time.Second) - } return &t, err } diff --git a/types.go b/types.go index 400be7d..8307d76 100644 --- a/types.go +++ b/types.go @@ -2,7 +2,6 @@ package paypalsdk import ( "net/http" - "time" "fmt" ) @@ -27,12 +26,19 @@ type ( // TokenResponse maps to the API response for the /oauth2/token endpoint TokenResponse struct { - Scope string `json:"scope"` // "https://api.paypal.com/v1/payments/.* https://api.paypal.com/v1/vault/credit-card https://api.paypal.com/v1/vault/credit-card/.*", - Token string `json:"access_token"` // "EEwJ6tF9x5WCIZDYzyZGaz6Khbw7raYRIBV_WxVvgmsG", - Type string `json:"token_type"` // "Bearer", - AppID string `json:"app_id"` // "APP-6XR95014BA15863X", - ExpiresIn int `json:"expires_in"` // 28800 - ExpiresAt time.Time `json:"expires_at"` + Scope string `json:"scope"` + Token string `json:"access_token"` + Type string `json:"token_type"` + AppID string `json:"app_id"` + ExpiresIn int `json:"expires_in"` + } + + // RefreshTokenResponse maps to the API response for the /v1/identity/openidconnect/tokenservice + RefreshTokenResponse struct { + Type string `json:"token_type"` + RefreshToken string `json:"refresh_token"` + AccessToken string `json:"access_token"` + ExpiresIn int `json:"expires_in"` } // ErrorResponse is used when a response has errors