234 lines
6.5 KiB
Go
234 lines
6.5 KiB
Go
package viettelffm
|
|
|
|
import (
|
|
"errors"
|
|
"fmt"
|
|
"net/http"
|
|
"net/url"
|
|
"time"
|
|
|
|
"git.selly.red/Selly-Modules/natsio"
|
|
"git.selly.red/Selly-Modules/natsio/model"
|
|
"git.selly.red/Selly-Modules/natsio/subject"
|
|
|
|
tpl "git.selly.red/Selly-Modules/3pl"
|
|
"git.selly.red/Selly-Modules/3pl/util/httputil"
|
|
"git.selly.red/Selly-Modules/3pl/util/pjson"
|
|
)
|
|
|
|
const (
|
|
baseURLStag = "https://stg-gw.viettelpost.vn"
|
|
baseURLAuthStag = "https://stg-keycloak.viettelpost.vn"
|
|
|
|
// TODO: update prod url
|
|
baseURLProd = ""
|
|
baseURLAuthProd = ""
|
|
|
|
pathAuth = "/realms/wms/protocol/openid-connect/token"
|
|
pathUpdateORLogisticInfo = "/wms-core/api/v1/obms/outbound-request/outbound-request-partner/%s"
|
|
pathCreateOR = "/wms-core/api/v1/obms/outbound-request/outbound-request-partner/hab"
|
|
pathCancelOR = "/wms-core/api/v1/obms/outbound-request/cancel"
|
|
|
|
logTarget = "viettel-ffm"
|
|
)
|
|
|
|
var (
|
|
baseURLENVMapping = map[tpl.ENV]string{
|
|
tpl.EnvProd: baseURLProd,
|
|
tpl.EnvStaging: baseURLStag,
|
|
}
|
|
)
|
|
|
|
type Client struct {
|
|
env tpl.ENV
|
|
username string
|
|
password string
|
|
|
|
natsClient natsio.Server
|
|
authInfo *AuthRes
|
|
authTokenExpireTime time.Time
|
|
}
|
|
|
|
// NewClient generate OnPoint client
|
|
func NewClient(env tpl.ENV, user, pwd string, nc natsio.Server) (*Client, error) {
|
|
if user == "" || pwd == "" {
|
|
return nil, errors.New("viettelffm: cannot init with empty api key")
|
|
}
|
|
return &Client{
|
|
env: env,
|
|
username: user,
|
|
password: pwd,
|
|
natsClient: nc,
|
|
}, nil
|
|
}
|
|
|
|
func (c *Client) CreateOR(p ORPayload) (*ORResult, error) {
|
|
apiURL := c.getBaseURL() + pathCreateOR
|
|
token, err := c.getToken()
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
natsPayload := model.CommunicationRequestHttp{
|
|
ResponseImmediately: true,
|
|
Payload: model.HttpRequest{
|
|
URL: apiURL,
|
|
Method: http.MethodPost,
|
|
Data: pjson.ToJSONString(p),
|
|
Header: map[string]string{
|
|
httputil.HeaderKeyAuthorization: fmt.Sprintf("Bearer %s", token),
|
|
httputil.HeaderKeyContentType: httputil.HeaderValueApplicationJSON,
|
|
},
|
|
},
|
|
LogTarget: logTarget,
|
|
}
|
|
r, err := c.requestHttpViaNats(natsPayload)
|
|
if err != nil {
|
|
return nil, fmt.Errorf("viettelffm.Client.CreateOR - requestHttpViaNats %v", err)
|
|
}
|
|
|
|
res := r.Response
|
|
if res.StatusCode >= http.StatusBadRequest {
|
|
return nil, fmt.Errorf("viettelffm.Client.CreateOR - requestHttpViaNats %s", res.Body)
|
|
}
|
|
var data ORResult
|
|
if err = r.ParseResponseData(&data); err != nil {
|
|
return nil, fmt.Errorf("viettelffm.Client.CreateOR - requestHttpViaNats parse response %v, %s", err, res.Body)
|
|
}
|
|
return &data, nil
|
|
}
|
|
|
|
func (c *Client) UpdateORLogisticInfo(p UpdateLogisticInfoPayload) error {
|
|
apiURL := c.getBaseURL() + fmt.Sprintf(pathUpdateORLogisticInfo, p.OrCode)
|
|
p.OrCode = ""
|
|
token, err := c.getToken()
|
|
if err != nil {
|
|
return err
|
|
}
|
|
natsPayload := model.CommunicationRequestHttp{
|
|
ResponseImmediately: true,
|
|
Payload: model.HttpRequest{
|
|
URL: apiURL,
|
|
Method: http.MethodPut,
|
|
Data: pjson.ToJSONString(p),
|
|
Header: map[string]string{
|
|
httputil.HeaderKeyAuthorization: fmt.Sprintf("Bearer %s", token),
|
|
httputil.HeaderKeyContentType: httputil.HeaderValueApplicationJSON,
|
|
},
|
|
},
|
|
LogTarget: logTarget,
|
|
}
|
|
r, err := c.requestHttpViaNats(natsPayload)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
res := r.Response
|
|
if res.StatusCode >= http.StatusBadRequest {
|
|
return fmt.Errorf("viettelffm.Client.UpdateOutboundRequestLogisticInfo - requestHttpViaNats %s", res.Body)
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func (c *Client) CancelOR(p CancelORPayload) error {
|
|
apiURL := c.getBaseURL() + pathCancelOR
|
|
token, err := c.getToken()
|
|
if err != nil {
|
|
return err
|
|
}
|
|
natsPayload := model.CommunicationRequestHttp{
|
|
ResponseImmediately: true,
|
|
Payload: model.HttpRequest{
|
|
URL: apiURL,
|
|
Method: http.MethodPost,
|
|
Data: pjson.ToJSONString(p),
|
|
Header: map[string]string{
|
|
httputil.HeaderKeyAuthorization: fmt.Sprintf("Bearer %s", token),
|
|
httputil.HeaderKeyContentType: httputil.HeaderValueApplicationJSON,
|
|
},
|
|
},
|
|
LogTarget: logTarget,
|
|
}
|
|
r, err := c.requestHttpViaNats(natsPayload)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
res := r.Response
|
|
if res.StatusCode >= http.StatusBadRequest {
|
|
return fmt.Errorf("viettelffm.Client.CancelOR - requestHttpViaNats %s", res.Body)
|
|
}
|
|
return nil
|
|
}
|
|
|
|
// Auth ...
|
|
func (c *Client) Auth() (*AuthRes, error) {
|
|
v := url.Values{}
|
|
v.Set("username", c.username)
|
|
v.Set("password", c.password)
|
|
v.Set("grant_type", "password")
|
|
v.Set("client_id", "wms_account")
|
|
b := v.Encode()
|
|
header := map[string]string{
|
|
httputil.HeaderKeyContentType: httputil.HeaderValueApplicationURLEncoded,
|
|
}
|
|
bURL := baseURLAuthStag
|
|
if c.env == tpl.EnvProd {
|
|
bURL = baseURLAuthProd
|
|
}
|
|
api := bURL + pathAuth
|
|
natsPayload := model.CommunicationRequestHttp{
|
|
ResponseImmediately: true,
|
|
Payload: model.HttpRequest{
|
|
URL: api,
|
|
Method: http.MethodPost,
|
|
Data: b,
|
|
Header: header,
|
|
},
|
|
LogTarget: logTarget,
|
|
}
|
|
r, err := c.requestHttpViaNats(natsPayload)
|
|
if err != nil {
|
|
return nil, fmt.Errorf("viettelffm.Client.Auth - requestHttpViaNats: payload %+v, err %v\n", natsPayload, err)
|
|
}
|
|
|
|
res := r.Response
|
|
if res.StatusCode >= http.StatusBadRequest {
|
|
return nil, fmt.Errorf("viettelffm.Client.Auth - requestHttpViaNats %s", res.Body)
|
|
}
|
|
var data AuthRes
|
|
if err = r.ParseResponseData(&data); err != nil {
|
|
return nil, fmt.Errorf("viettelffm.Client.Auth - requestHttpViaNats parse response %v, %s", err, res.Body)
|
|
}
|
|
return &data, nil
|
|
}
|
|
|
|
func (c *Client) getToken() (string, error) {
|
|
if c.authInfo == nil || time.Now().After(c.authTokenExpireTime) {
|
|
auth, err := c.Auth()
|
|
if err != nil {
|
|
return "", err
|
|
}
|
|
c.authInfo = auth
|
|
c.authTokenExpireTime = time.Now().Add(time.Duration(auth.ExpiresIn) * time.Second).Add(-time.Minute)
|
|
}
|
|
return c.authInfo.AccessToken, nil
|
|
}
|
|
|
|
func (c *Client) getBaseURL() string {
|
|
return baseURLENVMapping[c.env]
|
|
}
|
|
|
|
func (c *Client) requestHttpViaNats(data model.CommunicationRequestHttp) (*model.CommunicationHttpResponse, error) {
|
|
b := pjson.ToBytes(data)
|
|
msg, err := c.natsClient.Request(subject.Communication.RequestHTTP, b)
|
|
if err != nil {
|
|
return nil, fmt.Errorf("viettelffm.Client.requestHttpViaNats err: %v, url %s", err, data.Payload.URL)
|
|
}
|
|
var r model.CommunicationHttpResponse
|
|
if err = pjson.Unmarshal(msg.Data, &r); err != nil {
|
|
return nil, fmt.Errorf("viettelffm.Client.requestHttpViaNats parse data err: %v, url %s, data %s", err, data.Payload.URL, string(msg.Data))
|
|
}
|
|
if r.Response == nil {
|
|
return nil, fmt.Errorf("viettelffm.Client.requestHttpViaNats empty reponse")
|
|
}
|
|
return &r, nil
|
|
}
|