@@ -9,21 +9,22 @@ import (
9
9
"net/http"
10
10
"net/url"
11
11
"strings"
12
+ "time"
12
13
)
13
14
14
15
// ukVATService is service that calls a UK VAT API to validate UK VAT numbers.
15
16
type ukVATService struct {}
16
17
17
18
// Validate checks if the given VAT number exists and is active. If no error is returned, then it is.
18
19
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
21
22
// (it is recommended to generate one separately and cache it and pass it in as an option here)
22
23
accessToken , err := GenerateUKAccessToken (opts )
23
24
if err != nil {
24
25
return ErrMissingUKAccessToken
25
26
}
26
- opts .UKAccessToken = accessToken . Token
27
+ opts .UKAccessToken = accessToken
27
28
}
28
29
29
30
vatNumber = strings .ToUpper (vatNumber )
@@ -45,7 +46,7 @@ func (s *ukVATService) Validate(vatNumber string, opts ValidatorOpts) error {
45
46
}
46
47
47
48
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 ))
49
50
50
51
client := & http.Client {
51
52
Timeout : serviceTimeout ,
@@ -77,9 +78,15 @@ func (s *ukVATService) Validate(vatNumber string, opts ValidatorOpts) error {
77
78
78
79
// UKAccessToken contains access token information used to authenticate with the UK VAT API.
79
80
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 ())
83
90
}
84
91
85
92
// 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) {
128
135
if err := json .NewDecoder (resp .Body ).Decode (& token ); err != nil {
129
136
return nil , ErrUnableToGenerateUKAccessToken {Err : err }
130
137
}
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 ))
131
140
if opts .IsUKTest {
132
141
token .IsTest = true
133
142
}
0 commit comments