Initial cloud-services repo - gateway service + pkg modules
This commit is contained in:
593
pkg/tmobile/client.go
Normal file
593
pkg/tmobile/client.go
Normal file
@@ -0,0 +1,593 @@
|
||||
package tmobile
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"strings"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"fiskerinc.com/modules/grpc/sms"
|
||||
"fiskerinc.com/modules/logger"
|
||||
"fiskerinc.com/modules/utils/randomvalues"
|
||||
"github.com/pkg/errors"
|
||||
errorsO "errors"
|
||||
|
||||
tmtg "fiskerinc.com/modules/tmobtokengen"
|
||||
)
|
||||
|
||||
const (
|
||||
failedToParseRequest = "failed to encode request: %v"
|
||||
payloadMsg = "payload: %s"
|
||||
contentType = "Content-Type"
|
||||
failedGeneratePod = "failed to generate pop token: %v"
|
||||
startingTMobileTimeout = time.Millisecond * 10
|
||||
maximumTMobileTimeout = time.Minute
|
||||
|
||||
Endpoint = "https://adn.t-mobile.com"
|
||||
)
|
||||
|
||||
var (
|
||||
fakeIDGenerator = randomvalues.NewNonCryptoGenerator("1234567890", 0)
|
||||
currentTMobileTimeout = startingTMobileTimeout
|
||||
)
|
||||
|
||||
type httpClienter interface {
|
||||
Do(req *http.Request) (*http.Response, error)
|
||||
}
|
||||
|
||||
type TMobClienter interface {
|
||||
AccessToken(ctx context.Context) (out *AccessTokenResponse, err error)
|
||||
SetAccessToken(accessToken string)
|
||||
SendSMS(ctx context.Context, in *SendSMSRequest) (out *SendSMSResponse, err error)
|
||||
Details(ctx context.Context, ID string) (out *SMSDetailsResponse, err error)
|
||||
ChangeRatePlan(context.Context, *ChangeRatePlanRequest) (*ChangeRatePlanResponse, error)
|
||||
CustomAttributes(context.Context, *CustomAtributesRequest) (*CustomAtributesResponse, error)
|
||||
GetProducts(context.Context, *sms.GetAvailableProductsRequest) (*sms.GetAvailableProductsResponse, error)
|
||||
DeviceDetails(context.Context, *DeviceDetailsRequest) (*DeviceDetailsResponse, error)
|
||||
ChangeDeviceStatus(ctx context.Context, cda ChangeDeviceActivation) (err error)
|
||||
|
||||
SetFilter(filter []string)
|
||||
}
|
||||
|
||||
type TMobClient struct {
|
||||
tg tmtg.Generator
|
||||
client httpClienter
|
||||
accessToken string
|
||||
baseURL *url.URL
|
||||
lock sync.RWMutex // Using a read-write mutex and anyone can send a sms at any time, but if the token is do for a renew, we should stop sending sms for a second
|
||||
toRefresh <-chan time.Time
|
||||
iccidFilter ICCIDFilter
|
||||
}
|
||||
|
||||
|
||||
var _ TMobClienter = &TMobClient{}
|
||||
|
||||
const (
|
||||
Authorization = "Authorization"
|
||||
XAuthorization = "X-Authorization"
|
||||
XAuthOriginator = "x-auth-originator"
|
||||
failedToDoRequest = "failed to do request"
|
||||
applicationJSON = "application/json"
|
||||
)
|
||||
|
||||
// baseURLstr: in the url to tmobile i.e. "https://core.saas.api.t-mobile.com"
|
||||
// tg: should have been initiated with the correct keys. I believe this service should do it itself given the correct input
|
||||
// timeout: The amount of time the http client will do a request before it gives up doing the request
|
||||
func NewTMobileClient(baseURLstr string, tg tmtg.Generator, timeout time.Duration) (*TMobClient, error) {
|
||||
u, err := url.Parse(baseURLstr)
|
||||
if err != nil {
|
||||
return nil, errors.WithMessage(err, "failed to parse base URL")
|
||||
}
|
||||
|
||||
tmb := &TMobClient{
|
||||
baseURL: u,
|
||||
tg: tg,
|
||||
client: &http.Client{
|
||||
Timeout: timeout,
|
||||
},
|
||||
toRefresh: make(<-chan time.Time),
|
||||
}
|
||||
tmb.refresh(context.Background())
|
||||
|
||||
tmb.iccidFilter = InitFilter()
|
||||
return tmb, nil
|
||||
}
|
||||
|
||||
func (c *TMobClient) do(req *http.Request, out interface{}) error {
|
||||
|
||||
resp, err := c.client.Do(req)
|
||||
if err != nil {
|
||||
return errors.WithMessagef(ErrDoRequest, "failed to do request: %v", err)
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
|
||||
if resp.StatusCode >= 300 {
|
||||
var body []byte
|
||||
body, err = io.ReadAll(resp.Body)
|
||||
if err != nil {
|
||||
return errors.WithMessagef(ErrReadResponseBody, "failed to read response body: %v", err)
|
||||
}
|
||||
|
||||
toWrapErr := ErrBadStatusCode
|
||||
if resp.StatusCode == http.StatusUnauthorized {
|
||||
toWrapErr = ErrAccessTokenExpired
|
||||
} else if resp.StatusCode == http.StatusBadGateway {
|
||||
toWrapErr = ErrBadGatewayCode
|
||||
} else if resp.StatusCode == http.StatusGatewayTimeout {
|
||||
toWrapErr = ErrBadGatewayCode
|
||||
}
|
||||
|
||||
return errors.WithMessagef(toWrapErr, "request failed with status code %d, body: %s", resp.StatusCode, string(body))
|
||||
}
|
||||
|
||||
err = json.NewDecoder(resp.Body).Decode(out)
|
||||
if err != nil {
|
||||
return errors.WithMessagef(ErrJSONMarshal, "failed to decode response: %v", err)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// Must call setAccessToken after calling this function to set the access token
|
||||
func (c *TMobClient) AccessToken(ctx context.Context) (out *AccessTokenResponse, err error) {
|
||||
path := "/oauth2/v1/tokens"
|
||||
|
||||
c.lock.Lock()
|
||||
defer c.lock.Unlock()
|
||||
emap := make(tmtg.EHTSMap).SetAuthorization(c.tg.ClientSecretAsAuthVal()).
|
||||
SetURI(path).
|
||||
SetHTTPMethod(http.MethodPost)
|
||||
|
||||
token, err := c.tg.Generate(emap)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
fullPath := c.baseURL.String() + path
|
||||
|
||||
req, err := http.NewRequestWithContext(ctx, http.MethodPost, fullPath, nil)
|
||||
if err != nil {
|
||||
return nil, errors.WithMessagef(ErrCreateRequest, "failed to create request")
|
||||
}
|
||||
|
||||
req.Header.Set(Authorization, c.tg.ClientSecretAsAuthVal())
|
||||
req.Header.Set(XAuthorization, token)
|
||||
|
||||
err = c.do(req, &out)
|
||||
if err != nil {
|
||||
return nil, errors.WithMessage(err, failedToDoRequest)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func (c *TMobClient) SetAccessToken(accessToken string) {
|
||||
c.accessToken = "Bearer " + accessToken
|
||||
}
|
||||
|
||||
func (c *TMobClient) SendSMS(ctx context.Context, in *SendSMSRequest) (out *SendSMSResponse, err error) {
|
||||
if !c.iccidFilter.ShouldSend(in.ICCID) {
|
||||
out = &SendSMSResponse{
|
||||
SmsMessageID: fakeSMSID(),
|
||||
}
|
||||
return
|
||||
}
|
||||
path := "/eitcsr-iotcp-notifications-v2/prd02/iotcp/v2/notifications/sms/messages"
|
||||
|
||||
payload := new(bytes.Buffer)
|
||||
if err = json.NewEncoder(payload).Encode(in); err != nil {
|
||||
return nil, errors.WithMessagef(ErrJSONMarshal, failedToParseRequest, err)
|
||||
}
|
||||
|
||||
payloadStr := payload.String()
|
||||
|
||||
emap := make(tmtg.EHTSMap).SetAuthorization(c.accessToken).
|
||||
SetURI(path).
|
||||
SetHTTPMethod(http.MethodPost).
|
||||
SetContentType(applicationJSON).
|
||||
SetBody(payloadStr)
|
||||
|
||||
logger.Debug().Msgf(payloadMsg, payloadStr)
|
||||
|
||||
token, err := c.tg.Generate(emap)
|
||||
if err != nil {
|
||||
return nil, errors.WithMessagef(ErrTokenGen, "failed to generate token: %v", err)
|
||||
}
|
||||
|
||||
fullPath := c.baseURL.String() + path
|
||||
|
||||
req, err := http.NewRequestWithContext(ctx, http.MethodPost, fullPath, bytes.NewBufferString(payloadStr))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
c.lock.RLock()
|
||||
defer c.lock.RUnlock()
|
||||
req.Header.Set(Authorization, c.accessToken)
|
||||
req.Header.Set(XAuthOriginator, ToXAuthOriginator(c.accessToken))
|
||||
req.Header.Set(XAuthorization, token)
|
||||
req.Header.Set(contentType, applicationJSON)
|
||||
|
||||
err = c.do(req, &out)
|
||||
if err != nil {
|
||||
return nil, errors.WithMessage(err, failedToDoRequest)
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
func (c *TMobClient) Details(ctx context.Context, ID string) (out *SMSDetailsResponse, err error) {
|
||||
path := fmt.Sprintf("/eitcsr-iotcp-notifications-v2/prd02/iotcp/v2/notifications/sms/messages/%s", ID)
|
||||
|
||||
emap := make(tmtg.EHTSMap).SetAuthorization(c.accessToken).
|
||||
SetURI(path).
|
||||
SetHTTPMethod(http.MethodGet)
|
||||
|
||||
token, err := c.tg.Generate(emap)
|
||||
if err != nil {
|
||||
return nil, errors.WithMessagef(ErrTokenGen, "failed to generate token: %v", err)
|
||||
}
|
||||
|
||||
fullPath := c.baseURL.String() + path
|
||||
|
||||
req, err := http.NewRequestWithContext(ctx, http.MethodGet, fullPath, nil)
|
||||
if err != nil {
|
||||
return nil, errors.WithMessagef(ErrCreateRequest, "failed to create request: %v", err)
|
||||
}
|
||||
|
||||
c.lock.RLock()
|
||||
defer c.lock.RUnlock()
|
||||
req.Header.Set(Authorization, c.accessToken)
|
||||
req.Header.Set(XAuthOriginator, ToXAuthOriginator(c.accessToken))
|
||||
req.Header.Set(XAuthorization, token)
|
||||
req.Header.Set(contentType, applicationJSON)
|
||||
|
||||
err = c.do(req, &out)
|
||||
if err != nil {
|
||||
return nil, errors.WithMessage(err, failedToDoRequest)
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
func InitTokenGen(pkVal, clientId, secret string) (*tmtg.PopTokenGenerator, error) {
|
||||
// No reason to take a variable and write it to a text file and then read it from the text file
|
||||
|
||||
tg, err := tmtg.NewTokenGenerator(
|
||||
clientId,
|
||||
secret,
|
||||
time.Minute*2,
|
||||
pkVal, // path to public key file
|
||||
)
|
||||
if err != nil {
|
||||
return nil, errors.WithMessage(err, "failed to create token generator")
|
||||
}
|
||||
|
||||
return tg, nil
|
||||
}
|
||||
|
||||
func (c *TMobClient) ChangeRatePlan(ctx context.Context, in *ChangeRatePlanRequest) (*ChangeRatePlanResponse, error) {
|
||||
path := "/eitcsr-iotcp-line-of-service-v1/prd02/iotcp/v1/line-of-service/devices/change-rate-plan"
|
||||
fullPath := c.baseURL.String() + path
|
||||
|
||||
// The in body is so small, no use in using the encode method
|
||||
payload := new(bytes.Buffer)
|
||||
if err := json.NewEncoder(payload).Encode(in); err != nil {
|
||||
return nil, errors.WithMessagef(ErrJSONMarshal, failedToParseRequest, err)
|
||||
}
|
||||
payloadStr := payload.String()
|
||||
|
||||
emap := make(tmtg.EHTSMap).SetAuthorization(c.accessToken).
|
||||
SetURI(path).
|
||||
SetHTTPMethod(http.MethodPost).
|
||||
SetContentType(applicationJSON).
|
||||
SetBody(payloadStr)
|
||||
|
||||
logger.Debug().Msgf(payloadMsg, payloadStr)
|
||||
popToken, err := c.tg.Generate(emap)
|
||||
if err != nil {
|
||||
return nil, errors.WithMessagef(ErrTokenGen, failedGeneratePod, err)
|
||||
}
|
||||
|
||||
req, err := http.NewRequestWithContext(ctx, http.MethodPost, fullPath, payload)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
c.lock.RLock()
|
||||
defer c.lock.RUnlock()
|
||||
req.Header.Set(Authorization, c.accessToken)
|
||||
req.Header.Set(XAuthOriginator, ToXAuthOriginator(c.accessToken))
|
||||
req.Header.Set(XAuthorization, popToken)
|
||||
req.Header.Set(contentType, applicationJSON)
|
||||
out := &ChangeRatePlanResponse{}
|
||||
|
||||
err = c.do(req, out)
|
||||
if err != nil {
|
||||
return nil, errors.WithMessage(err, failedToDoRequest)
|
||||
}
|
||||
|
||||
return out, nil
|
||||
}
|
||||
|
||||
func (c *TMobClient) CustomAttributes(ctx context.Context, in *CustomAtributesRequest) (*CustomAtributesResponse, error) {
|
||||
path := "/eitcsr-iotcp-line-of-service-v1/prd02/iotcp/v1/line-of-service/devices/device-attributes"
|
||||
fullPath := c.baseURL.String() + path
|
||||
|
||||
payload := new(bytes.Buffer)
|
||||
if err := json.NewEncoder(payload).Encode(in); err != nil {
|
||||
return nil, errors.WithMessagef(ErrJSONMarshal, failedToParseRequest, err)
|
||||
}
|
||||
payloadStr := payload.String()
|
||||
|
||||
emap := make(tmtg.EHTSMap).SetAuthorization(c.accessToken).
|
||||
SetURI(path).
|
||||
SetHTTPMethod(http.MethodPost).
|
||||
SetContentType(applicationJSON).
|
||||
SetBody(payloadStr)
|
||||
|
||||
logger.Debug().Msgf(payloadMsg, payloadStr)
|
||||
popToken, err := c.tg.Generate(emap)
|
||||
if err != nil {
|
||||
return nil, errors.WithMessagef(ErrTokenGen, failedGeneratePod, err)
|
||||
}
|
||||
|
||||
req, err := http.NewRequestWithContext(ctx, http.MethodPost, fullPath, payload)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
c.lock.RLock()
|
||||
defer c.lock.RUnlock()
|
||||
req.Header.Set(Authorization, c.accessToken)
|
||||
req.Header.Set(XAuthOriginator, ToXAuthOriginator(c.accessToken))
|
||||
req.Header.Set(XAuthorization, popToken)
|
||||
req.Header.Set(contentType, applicationJSON)
|
||||
out := &CustomAtributesResponse{}
|
||||
|
||||
err = c.do(req, out)
|
||||
if err != nil {
|
||||
return nil, errors.WithMessage(err, failedToDoRequest)
|
||||
}
|
||||
|
||||
return out, nil
|
||||
}
|
||||
|
||||
func (c *TMobClient) GetProducts(ctx context.Context, in *sms.GetAvailableProductsRequest) (*sms.GetAvailableProductsResponse, error) {
|
||||
path := "/eitcsr-iot-product-service-v1/prd02/iotcp/v1/iot-product-service/products/query"
|
||||
fullPath := c.baseURL.String() + path
|
||||
|
||||
payload := new(bytes.Buffer)
|
||||
if err := json.NewEncoder(payload).Encode(in); err != nil {
|
||||
return nil, errors.WithMessagef(ErrJSONMarshal, failedToParseRequest, err)
|
||||
}
|
||||
payloadStr := payload.String()
|
||||
|
||||
emap := make(tmtg.EHTSMap).SetAuthorization(c.accessToken).
|
||||
SetURI(path).
|
||||
SetHTTPMethod(http.MethodPost).
|
||||
SetContentType(applicationJSON).
|
||||
SetBody(payloadStr)
|
||||
|
||||
logger.Debug().Msgf(payloadMsg, payloadStr)
|
||||
popToken, err := c.tg.Generate(emap)
|
||||
if err != nil {
|
||||
return nil, errors.WithMessagef(ErrTokenGen, failedGeneratePod, err)
|
||||
}
|
||||
|
||||
req, err := http.NewRequestWithContext(ctx, http.MethodPost, fullPath, payload)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
c.lock.RLock()
|
||||
defer c.lock.RUnlock()
|
||||
req.Header.Set(Authorization, c.accessToken)
|
||||
req.Header.Set(XAuthOriginator, ToXAuthOriginator(c.accessToken))
|
||||
req.Header.Set(XAuthorization, popToken)
|
||||
req.Header.Set(contentType, applicationJSON)
|
||||
out := &sms.GetAvailableProductsResponse{}
|
||||
|
||||
err = c.do(req, &out.AvailableProducts)
|
||||
if err != nil {
|
||||
return nil, errors.WithMessage(err, failedToDoRequest)
|
||||
}
|
||||
|
||||
return out, nil
|
||||
}
|
||||
|
||||
func (c *TMobClient) DeviceDetails(ctx context.Context, in *DeviceDetailsRequest) (*DeviceDetailsResponse, error) {
|
||||
path := "/eitcsr-iotcp-line-of-service-v1/prd02/iotcp/v1/line-of-service/devices/details"
|
||||
fullPath := c.baseURL.String() + path
|
||||
|
||||
payload := new(bytes.Buffer)
|
||||
if err := json.NewEncoder(payload).Encode(in); err != nil {
|
||||
return nil, errors.WithMessagef(ErrJSONMarshal, failedToParseRequest, err)
|
||||
}
|
||||
payloadStr := payload.String()
|
||||
|
||||
emap := make(tmtg.EHTSMap).SetAuthorization(c.accessToken).
|
||||
SetURI(path).
|
||||
SetHTTPMethod(http.MethodPost).
|
||||
SetContentType(applicationJSON).
|
||||
SetBody(payloadStr)
|
||||
|
||||
logger.Debug().Msgf(payloadMsg, payloadStr)
|
||||
popToken, err := c.tg.Generate(emap)
|
||||
if err != nil {
|
||||
return nil, errors.WithMessagef(ErrTokenGen, failedGeneratePod, err)
|
||||
}
|
||||
|
||||
req, err := http.NewRequestWithContext(ctx, http.MethodPost, fullPath, payload)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
c.lock.RLock()
|
||||
defer c.lock.RUnlock()
|
||||
req.Header.Set(Authorization, c.accessToken)
|
||||
req.Header.Set(XAuthOriginator, ToXAuthOriginator(c.accessToken))
|
||||
req.Header.Set(XAuthorization, popToken)
|
||||
req.Header.Set(contentType, applicationJSON)
|
||||
out := &DeviceDetailsResponse{}
|
||||
|
||||
err = c.do(req, &out)
|
||||
if err != nil {
|
||||
return nil, errors.WithMessage(err, failedToDoRequest)
|
||||
}
|
||||
|
||||
return out, nil
|
||||
}
|
||||
|
||||
func (c *TMobClient) refresh(ctx context.Context) {
|
||||
var expiresIn time.Duration
|
||||
|
||||
at, err := c.AccessToken(ctx)
|
||||
if err != nil {
|
||||
logger.Error().Msgf("failed to get access token: %v", err)
|
||||
expiresIn = currentTMobileTimeout
|
||||
currentTMobileTimeout = currentTMobileTimeout * currentTMobileTimeout
|
||||
if currentTMobileTimeout > maximumTMobileTimeout {
|
||||
currentTMobileTimeout = maximumTMobileTimeout
|
||||
}
|
||||
|
||||
} else {
|
||||
expiresIn = time.Duration(at.ExpiresIn) * time.Second
|
||||
expiresIn -= time.Minute * 1 // Expire 1 minute earlier than needed. Previous code was refreshing in half the time
|
||||
c.SetAccessToken(at.AccessToken)
|
||||
logger.Info().Msgf("Refreshed access token, expires in %s", expiresIn)
|
||||
// Reset the increasing timeout
|
||||
currentTMobileTimeout = startingTMobileTimeout
|
||||
}
|
||||
|
||||
time.AfterFunc(expiresIn, func() { c.refresh(context.Background()) })
|
||||
}
|
||||
|
||||
// SetFilter implements TMobClienter.
|
||||
func (c *TMobClient) SetFilter(filter []string) {
|
||||
c.iccidFilter = ICCIDFilter{
|
||||
filter: filter,
|
||||
}
|
||||
}
|
||||
|
||||
// SmsMessageID is a string consisting of numbers, will return a marker showing its not real
|
||||
func fakeSMSID() (fakeID string) {
|
||||
return fmt.Sprintf("FAKE_SMS_ID:%s", fakeIDGenerator.GetString(10))
|
||||
}
|
||||
|
||||
func IsRealSMSID(smsID string) (isReal bool) {
|
||||
return !strings.HasPrefix(smsID, "FAKE_SMS_ID:")
|
||||
}
|
||||
|
||||
|
||||
// HandleChangeDeviceStatus implements TMobClienter.
|
||||
func (c *TMobClient) ChangeDeviceStatus(ctx context.Context, cda ChangeDeviceActivation) (err error) {
|
||||
var fn func(ctx context.Context, in *ICCIDBody)(out *ICCIDBody, err error)
|
||||
if cda.Enabled {
|
||||
fn = c.handleServiceRestore
|
||||
}else {
|
||||
fn = c.handleServiceCancel
|
||||
}
|
||||
for _, iccid := range cda.ICCIDs {
|
||||
iccid = strings.TrimSuffix(strings.TrimSuffix(iccid, "F"), "f")
|
||||
temp := ICCIDBody{
|
||||
ICCID: iccid,
|
||||
}
|
||||
_, tErr := fn(ctx, &temp)
|
||||
if tErr != nil {
|
||||
err = errorsO.Join(err, tErr)
|
||||
}
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
// sets status as ACTIVATED
|
||||
func (c *TMobClient) handleServiceRestore(ctx context.Context, in *ICCIDBody)(out *ICCIDBody, err error){
|
||||
path := "/eitcsr-iotcp-line-of-service-v1/prd02/iotcp/v1/line-of-service/devices/service-restore"
|
||||
fullPath := c.baseURL.String() + path
|
||||
|
||||
payload := new(bytes.Buffer)
|
||||
err = json.NewEncoder(payload).Encode(in)
|
||||
if err != nil {
|
||||
return nil, errors.WithMessagef(ErrJSONMarshal, failedToParseRequest, err)
|
||||
}
|
||||
payloadStr := payload.String()
|
||||
|
||||
emap := make(tmtg.EHTSMap).SetAuthorization(c.accessToken).
|
||||
SetURI(path).
|
||||
SetHTTPMethod(http.MethodPost).
|
||||
SetContentType(applicationJSON).
|
||||
SetBody(payloadStr)
|
||||
popToken, err := c.tg.Generate(emap)
|
||||
if err != nil {
|
||||
return nil, errors.WithMessagef(ErrTokenGen, failedGeneratePod, err)
|
||||
}
|
||||
|
||||
req, err := http.NewRequestWithContext(ctx, http.MethodPost, fullPath, payload)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
c.lock.RLock()
|
||||
defer c.lock.RUnlock()
|
||||
req.Header.Set(Authorization, c.accessToken)
|
||||
req.Header.Set(XAuthOriginator, ToXAuthOriginator(c.accessToken))
|
||||
req.Header.Set(XAuthorization, popToken)
|
||||
req.Header.Set(contentType, applicationJSON)
|
||||
out = &ICCIDBody{}
|
||||
|
||||
err = c.do(req, &out)
|
||||
|
||||
if err != nil {
|
||||
return nil, errors.WithMessage(err, failedToDoRequest)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// sets status as DEACTIVATED
|
||||
func (c *TMobClient) handleServiceCancel(ctx context.Context, in *ICCIDBody)(out *ICCIDBody, err error){
|
||||
path := "/eitcsr-iotcp-line-of-service-v1/prd02/iotcp/v1/line-of-service/devices/service-suspend"
|
||||
fullPath := c.baseURL.String() + path
|
||||
|
||||
payload := new(bytes.Buffer)
|
||||
err = json.NewEncoder(payload).Encode(in)
|
||||
if err != nil {
|
||||
return nil, errors.WithMessagef(ErrJSONMarshal, failedToParseRequest, err)
|
||||
}
|
||||
payloadStr := payload.String()
|
||||
|
||||
emap := make(tmtg.EHTSMap).SetAuthorization(c.accessToken).
|
||||
SetURI(path).
|
||||
SetHTTPMethod(http.MethodPost).
|
||||
SetContentType(applicationJSON).
|
||||
SetBody(payloadStr)
|
||||
popToken, err := c.tg.Generate(emap)
|
||||
if err != nil {
|
||||
return nil, errors.WithMessagef(ErrTokenGen, failedGeneratePod, err)
|
||||
}
|
||||
|
||||
req, err := http.NewRequestWithContext(ctx, http.MethodPost, fullPath, payload)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
c.lock.RLock()
|
||||
defer c.lock.RUnlock()
|
||||
req.Header.Set(Authorization, c.accessToken)
|
||||
req.Header.Set(XAuthOriginator, ToXAuthOriginator(c.accessToken))
|
||||
req.Header.Set(XAuthorization, popToken)
|
||||
req.Header.Set(contentType, applicationJSON)
|
||||
out = &ICCIDBody{}
|
||||
|
||||
err = c.do(req, &out)
|
||||
|
||||
if err != nil {
|
||||
return nil, errors.WithMessage(err, failedToDoRequest)
|
||||
}
|
||||
return
|
||||
}
|
||||
Reference in New Issue
Block a user