Skip to content

Commit c74e95b

Browse files
Make it easier to check if UK API access token has expired (#12)
* Make it easier to check if UK API access token has expired * Forgot a comment * Use time.Time instead of int timestamp
1 parent cfd1afb commit c74e95b

File tree

3 files changed

+18
-9
lines changed

3 files changed

+18
-9
lines changed

uk_vat_service.go

Lines changed: 16 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -9,21 +9,22 @@ import (
99
"net/http"
1010
"net/url"
1111
"strings"
12+
"time"
1213
)
1314

1415
// ukVATService is service that calls a UK VAT API to validate UK VAT numbers.
1516
type ukVATService struct{}
1617

1718
// Validate checks if the given VAT number exists and is active. If no error is returned, then it is.
1819
func (s *ukVATService) Validate(vatNumber string, opts ValidatorOpts) error {
19-
if opts.UKAccessToken == "" {
20-
// if no access token is provided, try to generate one
20+
if opts.UKAccessToken == nil || opts.UKAccessToken.IsExpired() {
21+
// if no access token is provided or if it's expired, try to generate one
2122
// (it is recommended to generate one separately and cache it and pass it in as an option here)
2223
accessToken, err := GenerateUKAccessToken(opts)
2324
if err != nil {
2425
return ErrMissingUKAccessToken
2526
}
26-
opts.UKAccessToken = accessToken.Token
27+
opts.UKAccessToken = accessToken
2728
}
2829

2930
vatNumber = strings.ToUpper(vatNumber)
@@ -45,7 +46,7 @@ func (s *ukVATService) Validate(vatNumber string, opts ValidatorOpts) error {
4546
}
4647

4748
req.Header.Set("Accept", "application/vnd.hmrc.2.0+json")
48-
req.Header.Set("Authorization", fmt.Sprintf("Bearer %s", opts.UKAccessToken))
49+
req.Header.Set("Authorization", fmt.Sprintf("Bearer %s", opts.UKAccessToken.Token))
4950

5051
client := &http.Client{
5152
Timeout: serviceTimeout,
@@ -77,9 +78,15 @@ func (s *ukVATService) Validate(vatNumber string, opts ValidatorOpts) error {
7778

7879
// UKAccessToken contains access token information used to authenticate with the UK VAT API.
7980
type UKAccessToken struct {
80-
Token string `json:"access_token"`
81-
SecondsUntilExpires int `json:"expires_in"`
82-
IsTest bool `json:"-"`
81+
Token string `json:"access_token"`
82+
SecondsUntilExpires int64 `json:"expires_in"`
83+
ExpiresAt time.Time `json:"expires_at"`
84+
IsTest bool `json:"-"`
85+
}
86+
87+
// IsExpired checks if the access token is expired.
88+
func (t UKAccessToken) IsExpired() bool {
89+
return t.ExpiresAt.Before(time.Now())
8390
}
8491

8592
// GenerateUKAccessToken generates an access token from given client credentials for use with the UK VAT API.
@@ -128,6 +135,8 @@ func GenerateUKAccessToken(opts ValidatorOpts) (*UKAccessToken, error) {
128135
if err := json.NewDecoder(resp.Body).Decode(&token); err != nil {
129136
return nil, ErrUnableToGenerateUKAccessToken{Err: err}
130137
}
138+
// set the expiration time to 1 minute before the actual expiration for safety
139+
token.ExpiresAt = time.Now().Add(time.Duration(token.SecondsUntilExpires - 60))
131140
if opts.IsUKTest {
132141
token.IsTest = true
133142
}

uk_vat_service_test.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ func TestUKVATService(t *testing.T) {
3333
if err != nil {
3434
t.Fatal(err)
3535
}
36-
opts.UKAccessToken = token.Token
36+
opts.UKAccessToken = token
3737

3838
for _, test := range ukTests {
3939
err := UKVATLookupService.Validate(test.vatNumber, opts)

validate.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -102,6 +102,6 @@ func ValidateExists(vatNumber string, optsSlice ...ValidatorOpts) error {
102102
type ValidatorOpts struct {
103103
UKClientID string
104104
UKClientSecret string
105-
UKAccessToken string
105+
UKAccessToken *UKAccessToken
106106
IsUKTest bool
107107
}

0 commit comments

Comments
 (0)