233 lines
		
	
	
		
			6.5 KiB
		
	
	
	
		
			Go
		
	
	
	
			
		
		
	
	
			233 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"
 | |
| 
 | |
| 	baseURLProd     = "https://gw.viettelpost.vn"
 | |
| 	baseURLAuthProd = "https://dws-sso.viettelpost.vn"
 | |
| 
 | |
| 	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
 | |
| }
 |