define tnc api
This commit is contained in:
parent
c0cdae1240
commit
58e830d0a0
|
@ -4,14 +4,23 @@ import "github.com/Selly-Modules/tpl/util/pjson"
|
||||||
|
|
||||||
// NatsResponse ...
|
// NatsResponse ...
|
||||||
type NatsResponse struct {
|
type NatsResponse struct {
|
||||||
Data interface{} `json:"data"`
|
Response *HttpResponse `json:"response"`
|
||||||
Error bool `json:"error"`
|
Error bool `json:"error"`
|
||||||
Message string `json:"message"`
|
Message string `json:"message"`
|
||||||
RequestID string `json:"requestId"`
|
RequestID string `json:"requestId"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// ParseData ...
|
// ParseResponseData ...
|
||||||
func (r *NatsResponse) ParseData(result interface{}) error {
|
func (r *NatsResponse) ParseResponseData(result interface{}) error {
|
||||||
b := pjson.ToBytes(r.Data)
|
if r.Response == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
b := pjson.ToBytes(r.Response.Body)
|
||||||
return pjson.Unmarshal(b, result)
|
return pjson.Unmarshal(b, result)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// HttpResponse ...
|
||||||
|
type HttpResponse struct {
|
||||||
|
Body string `json:"body"`
|
||||||
|
StatusCode int `json:"statusCode"`
|
||||||
|
}
|
||||||
|
|
|
@ -85,7 +85,7 @@ func (c *Client) CreateOrder(p CreateOrderPayload) (*CommonResponse, error) {
|
||||||
if err = pjson.Unmarshal(msg.Data, &r); err != nil {
|
if err = pjson.Unmarshal(msg.Data, &r); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
err = r.ParseData(&res)
|
err = r.ParseResponseData(&res)
|
||||||
return &res, err
|
return &res, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -114,7 +114,7 @@ func (c *Client) GetOrder(orderCode string) (*CommonResponse, error) {
|
||||||
if err = pjson.Unmarshal(msg.Data, &r); err != nil {
|
if err = pjson.Unmarshal(msg.Data, &r); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
err = r.ParseData(&res)
|
err = r.ParseResponseData(&res)
|
||||||
return &res, err
|
return &res, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,41 @@
|
||||||
|
package tnc
|
||||||
|
|
||||||
|
const (
|
||||||
|
TimeLayout = "2006-01-02 15:04:05"
|
||||||
|
|
||||||
|
apiPathCreateOutboundRequest = "/api/v1/ors"
|
||||||
|
apiPathGetOutboundRequest = "/api/v1/ors/%d"
|
||||||
|
apiPathCancelOutboundRequest = "/api/v1/ors/%d/cancel"
|
||||||
|
apiPathAuth = "/auth/realms/%s/protocol/openid-connect/token"
|
||||||
|
|
||||||
|
PriorityUrgent = 3
|
||||||
|
PriorityHigh = 2
|
||||||
|
PriorityNormal = 1
|
||||||
|
|
||||||
|
TPLCodeGHN = "GHN"
|
||||||
|
TPLCodeGHTK = "GHTK"
|
||||||
|
TPLCodeBest = "BEST"
|
||||||
|
TPLCodeSnappy = "SPY"
|
||||||
|
TPLCodeViettelPost = "VTP"
|
||||||
|
TPLCodeSellyExpress = "SE"
|
||||||
|
TPLCodeJTExpress = "JTE"
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
baseURLAuthStaging = "https://auth.stg.tnclog.vn"
|
||||||
|
baseURLStaging = "https://ext-api.stg.tnclog.vn"
|
||||||
|
|
||||||
|
baseURLAuthProd = "https://auth.tnclog.vn"
|
||||||
|
baseURLProd = "https://ext-api.tnclog.vn"
|
||||||
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
baseURLENVMapping = map[ENV]string{
|
||||||
|
EnvProd: baseURLProd,
|
||||||
|
EnvStaging: baseURLStaging,
|
||||||
|
}
|
||||||
|
baseURLAuthENVMapping = map[ENV]string{
|
||||||
|
EnvProd: baseURLAuthProd,
|
||||||
|
EnvStaging: baseURLAuthStaging,
|
||||||
|
}
|
||||||
|
)
|
|
@ -0,0 +1,9 @@
|
||||||
|
package tnc
|
||||||
|
|
||||||
|
// ENV ...
|
||||||
|
type ENV string
|
||||||
|
|
||||||
|
const (
|
||||||
|
EnvStaging ENV = "STAGING"
|
||||||
|
EnvProd ENV = "PROD"
|
||||||
|
)
|
|
@ -0,0 +1,44 @@
|
||||||
|
package tnc
|
||||||
|
|
||||||
|
// Product ...
|
||||||
|
type Product struct {
|
||||||
|
PartnerSKU string `json:"partnerSKU"`
|
||||||
|
UnitCode string `json:"unitCode"`
|
||||||
|
ConditionTypeCode string `json:"conditionTypeCode"`
|
||||||
|
Quantity int64 `json:"quantity"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// Address ...
|
||||||
|
type Address struct {
|
||||||
|
AddressNo string `json:"addressNo"`
|
||||||
|
ProvinceCode string `json:"provinceCode"`
|
||||||
|
DistrictCode string `json:"districtCode"`
|
||||||
|
WardCode string `json:"wardCode"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// OutboundRequestPayload ...
|
||||||
|
type OutboundRequestPayload struct {
|
||||||
|
WarehouseCode string `json:"warehouseCode"`
|
||||||
|
ShippingServiceCode string `json:"shippingServiceCode"`
|
||||||
|
PartnerORCode string `json:"partnerORCode"`
|
||||||
|
PartnerRefId string `json:"partnerRefId"`
|
||||||
|
RefCode string `json:"refCode"`
|
||||||
|
CodAmount float64 `json:"codAmount"`
|
||||||
|
PriorityType int `json:"priorityType"`
|
||||||
|
CustomerName string `json:"customerName"`
|
||||||
|
CustomerPhoneNumber string `json:"customerPhoneNumber"`
|
||||||
|
Type int `json:"type"`
|
||||||
|
ShippingType int `json:"shippingType"`
|
||||||
|
VehicleNumber string `json:"vehicleNumber"`
|
||||||
|
ContainerNumber string `json:"containerNumber"`
|
||||||
|
PackType int `json:"packType"`
|
||||||
|
PackingNote string `json:"packingNote"`
|
||||||
|
CustomLabel bool `json:"customLabel"`
|
||||||
|
BizType int `json:"bizType"`
|
||||||
|
Note string `json:"note"`
|
||||||
|
ShippingAddress Address `json:"shippingAddress"`
|
||||||
|
Products []Product `json:"products"`
|
||||||
|
PartnerCreationTime string `json:"partnerCreationTime"`
|
||||||
|
TPLCode string `json:"tplCode"`
|
||||||
|
TrackingCode string `json:"trackingCode"`
|
||||||
|
}
|
|
@ -0,0 +1,63 @@
|
||||||
|
package tnc
|
||||||
|
|
||||||
|
// OutboundRequestRes ...
|
||||||
|
type OutboundRequestRes struct {
|
||||||
|
OrID int `json:"orId"`
|
||||||
|
OrCode string `json:"orCode"`
|
||||||
|
PartnerORCode string `json:"partnerORCode"`
|
||||||
|
Error *ErrRes `json:"error"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// ErrRes ...
|
||||||
|
type ErrRes struct {
|
||||||
|
Code string `json:"code"`
|
||||||
|
ErrorMessage string `json:"errorMessage"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type authRes struct {
|
||||||
|
AccessToken string `json:"access_token"`
|
||||||
|
ExpiresIn int `json:"expires_in"`
|
||||||
|
RefreshExpiresIn int `json:"refresh_expires_in"`
|
||||||
|
RefreshToken string `json:"refresh_token"`
|
||||||
|
TokenType string `json:"token_type"`
|
||||||
|
NotBeforePolicy int `json:"not-before-policy"`
|
||||||
|
SessionState string `json:"session_state"`
|
||||||
|
Scope string `json:"scope"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// Webhook ...
|
||||||
|
type Webhook struct {
|
||||||
|
OrId int `json:"orId"`
|
||||||
|
PartnerORCode string `json:"partnerORCode"`
|
||||||
|
ErrorCode string `json:"errorCode"`
|
||||||
|
ErrorMessage string `json:"errorMessage"`
|
||||||
|
Event string `json:"event"`
|
||||||
|
Id string `json:"id"`
|
||||||
|
Timestamp int64 `json:"timestamp"`
|
||||||
|
Note string `json:"note"`
|
||||||
|
OrCode string `json:"orCode"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// OutboundRequestInfo ...
|
||||||
|
type OutboundRequestInfo struct {
|
||||||
|
OrId int `json:"orId"`
|
||||||
|
OrCode string `json:"orCode"`
|
||||||
|
PartnerORCode string `json:"partnerORCode"`
|
||||||
|
OriginalPartnerOrCode string `json:"originalPartnerOrCode"`
|
||||||
|
PartnerRefId string `json:"partnerRefId"`
|
||||||
|
RefCode string `json:"refCode"`
|
||||||
|
WarehouseCode string `json:"warehouseCode"`
|
||||||
|
Status string `json:"status"`
|
||||||
|
Note string `json:"note"`
|
||||||
|
ShippingType int `json:"shippingType"`
|
||||||
|
PriorityType int `json:"priorityType"`
|
||||||
|
PackType int `json:"packType"`
|
||||||
|
BizType int `json:"bizType"`
|
||||||
|
CustomerName string `json:"customerName"`
|
||||||
|
CustomerPhoneNumber string `json:"customerPhoneNumber"`
|
||||||
|
ShippingFullAddress string `json:"shippingFullAddress"`
|
||||||
|
CodAmount float64 `json:"codAmount"`
|
||||||
|
ExpectedDeliveryTime string `json:"expectedDeliveryTime"`
|
||||||
|
CreatedDate string `json:"createdDate"`
|
||||||
|
ErrorMessage string `json:"errorMessage"`
|
||||||
|
}
|
|
@ -0,0 +1,268 @@
|
||||||
|
package tnc
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"net/http"
|
||||||
|
"net/url"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/Selly-Modules/logger"
|
||||||
|
"github.com/Selly-Modules/natsio"
|
||||||
|
"github.com/nats-io/nats.go"
|
||||||
|
|
||||||
|
"github.com/Selly-Modules/tpl/constant"
|
||||||
|
natsiomodel "github.com/Selly-Modules/tpl/model/natsio"
|
||||||
|
"github.com/Selly-Modules/tpl/util/pjson"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Client ...
|
||||||
|
type Client struct {
|
||||||
|
// Auth info
|
||||||
|
realm string
|
||||||
|
clientID string
|
||||||
|
clientSecret string
|
||||||
|
|
||||||
|
env ENV
|
||||||
|
natsClient natsio.Server
|
||||||
|
|
||||||
|
token string
|
||||||
|
tokenExpireAt time.Time
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewClient ...
|
||||||
|
func NewClient(env ENV, clientID, clientSecret, realm string, natsClient natsio.Server) (*Client, error) {
|
||||||
|
if env != EnvProd && env != EnvStaging {
|
||||||
|
return nil, fmt.Errorf("tnc.NewClient: invalid_env %s", env)
|
||||||
|
}
|
||||||
|
return &Client{
|
||||||
|
realm: realm,
|
||||||
|
clientID: clientID,
|
||||||
|
clientSecret: clientSecret,
|
||||||
|
token: "",
|
||||||
|
env: env,
|
||||||
|
natsClient: natsClient,
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// CreateOutboundRequest ...
|
||||||
|
func (c *Client) CreateOutboundRequest(p OutboundRequestPayload) (*OutboundRequestRes, error) {
|
||||||
|
apiURL := c.getBaseURL() + apiPathCreateOutboundRequest
|
||||||
|
natsPayload := natsiomodel.NatsRequestHTTP{
|
||||||
|
ResponseImmediately: true,
|
||||||
|
Payload: natsiomodel.HTTPPayload{
|
||||||
|
URL: apiURL,
|
||||||
|
Method: http.MethodGet,
|
||||||
|
Data: pjson.ToJSONString(p),
|
||||||
|
Header: c.getRequestHeader(),
|
||||||
|
},
|
||||||
|
}
|
||||||
|
msg, err := c.requestHttpViaNats(natsPayload)
|
||||||
|
if err != nil {
|
||||||
|
logger.Error("tnc.Client.CreateOutboundRequest - requestHttpViaNats", logger.LogData{
|
||||||
|
"err": err.Error(),
|
||||||
|
"payload": natsPayload,
|
||||||
|
})
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
var (
|
||||||
|
r natsiomodel.NatsResponse
|
||||||
|
errRes ErrRes
|
||||||
|
dataRes []OutboundRequestRes
|
||||||
|
)
|
||||||
|
if err = pjson.Unmarshal(msg.Data, &r); err != nil {
|
||||||
|
return nil, fmt.Errorf("tnc.Client.CreateOutboundRequest: parse_data %v", err)
|
||||||
|
}
|
||||||
|
res := r.Response
|
||||||
|
if res == nil {
|
||||||
|
return nil, fmt.Errorf("tnc.Client.CreateOutboundRequest: empty_response")
|
||||||
|
}
|
||||||
|
if res.StatusCode >= http.StatusBadRequest {
|
||||||
|
if err = r.ParseResponseData(&errRes); err != nil {
|
||||||
|
return nil, fmt.Errorf("tnc.Client.CreateOutboundRequest: parse_response_err: %v", err)
|
||||||
|
}
|
||||||
|
return nil, fmt.Errorf("tnc.Client.CreateOutboundRequest: failed code %s, message %s", errRes.Code, errRes.ErrorMessage)
|
||||||
|
}
|
||||||
|
if err = r.ParseResponseData(&dataRes); err != nil {
|
||||||
|
return nil, fmt.Errorf("tnc.Client.CreateOutboundRequest: parse_response_data: %v", err)
|
||||||
|
}
|
||||||
|
if len(dataRes) == 0 {
|
||||||
|
return nil, fmt.Errorf("tnc.Client.CreateOutboundRequest: empty_result")
|
||||||
|
}
|
||||||
|
|
||||||
|
return &dataRes[0], err
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetOutboundRequestByID ...
|
||||||
|
func (c *Client) GetOutboundRequestByID(requestID int) (*OutboundRequestInfo, error) {
|
||||||
|
apiURL := c.getBaseURL() + fmt.Sprintf(apiPathGetOutboundRequest, requestID)
|
||||||
|
natsPayload := natsiomodel.NatsRequestHTTP{
|
||||||
|
ResponseImmediately: true,
|
||||||
|
Payload: natsiomodel.HTTPPayload{
|
||||||
|
URL: apiURL,
|
||||||
|
Method: http.MethodGet,
|
||||||
|
Header: c.getRequestHeader(),
|
||||||
|
},
|
||||||
|
}
|
||||||
|
msg, err := c.requestHttpViaNats(natsPayload)
|
||||||
|
if err != nil {
|
||||||
|
logger.Error("tnc.Client.GetOutboundRequestByID - requestHttpViaNats", logger.LogData{
|
||||||
|
"err": err.Error(),
|
||||||
|
"payload": natsPayload,
|
||||||
|
})
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
var (
|
||||||
|
r natsiomodel.NatsResponse
|
||||||
|
errRes ErrRes
|
||||||
|
outboundRequest OutboundRequestInfo
|
||||||
|
)
|
||||||
|
if err = pjson.Unmarshal(msg.Data, &r); err != nil {
|
||||||
|
return nil, fmt.Errorf("tnc.Client.GetOutboundRequestByID: parse_data %v", err)
|
||||||
|
}
|
||||||
|
res := r.Response
|
||||||
|
if res == nil {
|
||||||
|
return nil, fmt.Errorf("tnc.Client.GetOutboundRequestByID: empty_response")
|
||||||
|
}
|
||||||
|
if res.StatusCode >= http.StatusBadRequest {
|
||||||
|
if err = r.ParseResponseData(&errRes); err != nil {
|
||||||
|
return nil, fmt.Errorf("tnc.Client.GetOutboundRequestByID: parse_response_err: %v", err)
|
||||||
|
}
|
||||||
|
return nil, fmt.Errorf("tnc.Client.GetOutboundRequestByID: failed code %s, message %s", errRes.Code, errRes.ErrorMessage)
|
||||||
|
}
|
||||||
|
if err = r.ParseResponseData(outboundRequest); err != nil {
|
||||||
|
return nil, fmt.Errorf("tnc.Client.GetOutboundRequestByID: parse_response_data: %v", err)
|
||||||
|
}
|
||||||
|
return &outboundRequest, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// CancelOutboundRequest ...
|
||||||
|
func (c *Client) CancelOutboundRequest(requestID int) error {
|
||||||
|
apiURL := c.getBaseURL() + fmt.Sprintf(apiPathCancelOutboundRequest, requestID)
|
||||||
|
natsPayload := natsiomodel.NatsRequestHTTP{
|
||||||
|
ResponseImmediately: true,
|
||||||
|
Payload: natsiomodel.HTTPPayload{
|
||||||
|
URL: apiURL,
|
||||||
|
Method: http.MethodPost,
|
||||||
|
Header: c.getRequestHeader(),
|
||||||
|
},
|
||||||
|
}
|
||||||
|
msg, err := c.requestHttpViaNats(natsPayload)
|
||||||
|
if err != nil {
|
||||||
|
logger.Error("tnc.Client.CancelOutboundRequest - requestHttpViaNats", logger.LogData{
|
||||||
|
"err": err.Error(),
|
||||||
|
"payload": natsPayload,
|
||||||
|
})
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
var (
|
||||||
|
r natsiomodel.NatsResponse
|
||||||
|
errRes ErrRes
|
||||||
|
)
|
||||||
|
if err = pjson.Unmarshal(msg.Data, &r); err != nil {
|
||||||
|
return fmt.Errorf("tnc.Client.CancelOutboundRequest: parse_data %v", err)
|
||||||
|
}
|
||||||
|
res := r.Response
|
||||||
|
if res == nil {
|
||||||
|
return fmt.Errorf("tnc.Client.CancelOutboundRequest: empty_response")
|
||||||
|
}
|
||||||
|
if res.StatusCode >= http.StatusBadRequest {
|
||||||
|
if err = r.ParseResponseData(&errRes); err != nil {
|
||||||
|
return fmt.Errorf("tnc.Client.CancelOutboundRequest: parse_response_err: %v", err)
|
||||||
|
}
|
||||||
|
return fmt.Errorf("tnc.Client.CancelOutboundRequest: failed code %s, message %s", errRes.Code, errRes.ErrorMessage)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *Client) auth() (*authRes, error) {
|
||||||
|
v := url.Values{}
|
||||||
|
v.Add("realm", c.realm)
|
||||||
|
v.Add("grant_type", "client_credentials")
|
||||||
|
v.Add("client_id", c.clientID)
|
||||||
|
v.Add("client_secret", c.clientSecret)
|
||||||
|
|
||||||
|
body := v.Encode()
|
||||||
|
header := map[string]string{
|
||||||
|
"Content-Type": "application/x-www-form-urlencoded",
|
||||||
|
}
|
||||||
|
apiURL := baseURLAuthENVMapping[c.env] + fmt.Sprintf(apiPathAuth, c.realm)
|
||||||
|
natsPayload := natsiomodel.NatsRequestHTTP{
|
||||||
|
ResponseImmediately: true,
|
||||||
|
Payload: natsiomodel.HTTPPayload{
|
||||||
|
URL: apiURL,
|
||||||
|
Method: http.MethodPost,
|
||||||
|
Data: body,
|
||||||
|
Header: header,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
msg, err := c.requestHttpViaNats(natsPayload)
|
||||||
|
if err != nil {
|
||||||
|
logger.Error("tnc.Client.auth - requestHttpViaNats", logger.LogData{
|
||||||
|
"err": err.Error(),
|
||||||
|
"payload": natsPayload,
|
||||||
|
})
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
var (
|
||||||
|
r natsiomodel.NatsResponse
|
||||||
|
errRes ErrRes
|
||||||
|
data authRes
|
||||||
|
)
|
||||||
|
if err = pjson.Unmarshal(msg.Data, &r); err != nil {
|
||||||
|
return nil, fmt.Errorf("tnc.Client.auth: parse_data %v", err)
|
||||||
|
}
|
||||||
|
res := r.Response
|
||||||
|
if res == nil {
|
||||||
|
return nil, fmt.Errorf("tnc.Client.auth: empty_response")
|
||||||
|
}
|
||||||
|
if res.StatusCode >= http.StatusBadRequest {
|
||||||
|
if err = r.ParseResponseData(&errRes); err != nil {
|
||||||
|
return nil, fmt.Errorf("tnc.Client.auth: parse_response_err: %v", err)
|
||||||
|
}
|
||||||
|
return nil, fmt.Errorf("tnc.Client.auth: failed code %s, message %s", errRes.Code, errRes.ErrorMessage)
|
||||||
|
}
|
||||||
|
if err = r.ParseResponseData(data); err != nil {
|
||||||
|
return nil, fmt.Errorf("tnc.Client.auth: parse_response_data: %v", err)
|
||||||
|
}
|
||||||
|
return &data, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *Client) getRequestHeader() map[string]string {
|
||||||
|
m := map[string]string{
|
||||||
|
"Content-Type": "application/json",
|
||||||
|
}
|
||||||
|
token, err := c.getToken()
|
||||||
|
if err != nil {
|
||||||
|
logger.Error("tnc.Client.getToken", logger.LogData{"err": err.Error()})
|
||||||
|
} else {
|
||||||
|
m["Authorization"] = fmt.Sprintf("Bearer %s", token)
|
||||||
|
}
|
||||||
|
return m
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *Client) requestHttpViaNats(data natsiomodel.NatsRequestHTTP) (*nats.Msg, error) {
|
||||||
|
s := constant.NatsCommunicationSubjectRequestHTTP
|
||||||
|
b := pjson.ToBytes(data)
|
||||||
|
return c.natsClient.Request(s, b)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *Client) getBaseURL() string {
|
||||||
|
return baseURLENVMapping[c.env]
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *Client) getToken() (string, error) {
|
||||||
|
if c.token != "" || c.tokenExpireAt.After(time.Now()) {
|
||||||
|
return c.token, nil
|
||||||
|
}
|
||||||
|
data, err := c.auth()
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
c.token = data.AccessToken
|
||||||
|
d := time.Duration(data.ExpiresIn) * time.Second
|
||||||
|
if d.Minutes() > 30 {
|
||||||
|
d -= 30 * time.Minute
|
||||||
|
}
|
||||||
|
c.tokenExpireAt = time.Now().Add(d)
|
||||||
|
return c.token, nil
|
||||||
|
}
|
Loading…
Reference in New Issue