feat(zarinhub): automate access token refresh

This commit is contained in:
2026-09-21 16:27:30 +03:30
parent 7f2f26e596
commit c54332cd61
9 changed files with 621 additions and 36 deletions

View File

@@ -16,28 +16,60 @@ import (
const maxResponseBodySize = 1 << 20
type Client struct {
httpClient *http.Client
endpointURL string
accessToken string
httpClient *http.Client
endpointURL string
tokenProvider TokenProvider
}
var _ service.CardToIBANClient = (*Client)(nil)
type TokenProvider interface {
AccessToken(ctx context.Context) (string, error)
Invalidate(token string)
}
func NewClient(
httpClient *http.Client,
endpointURL string,
accessToken string,
tokenProvider TokenProvider,
) *Client {
return &Client{
httpClient: httpClient,
endpointURL: endpointURL,
accessToken: accessToken,
httpClient: httpClient,
endpointURL: endpointURL,
tokenProvider: tokenProvider,
}
}
func (c *Client) Convert(
ctx context.Context,
cardNumber string,
) (service.ConversionResult, error) {
accessToken, err := c.tokenProvider.AccessToken(ctx)
if err != nil {
return service.ConversionResult{},
fmt.Errorf("get zarinhub access token: %w", err)
}
result, err := c.convert(ctx, cardNumber, accessToken)
if !errors.Is(err, ErrAuthentication) ||
result.UpstreamHTTPStatus != http.StatusUnauthorized {
return result, err
}
c.tokenProvider.Invalidate(accessToken)
accessToken, err = c.tokenProvider.AccessToken(ctx)
if err != nil {
return result, fmt.Errorf("refresh zarinhub access token: %w", err)
}
return c.convert(ctx, cardNumber, accessToken)
}
func (c *Client) convert(
ctx context.Context,
cardNumber string,
accessToken string,
) (service.ConversionResult, error) {
payload, err := json.Marshal(convertRequest{
Card: cardNumber,
@@ -60,7 +92,7 @@ func (c *Client) Convert(
req.Header.Set(
"Authorization",
"Bearer "+c.accessToken,
"Bearer "+accessToken,
)
req.Header.Set(