Compare commits
	
		
			47 Commits
		
	
	
	| Author | SHA1 | Date | 
|---|---|---|
| 
							
							
								 | 
						574899c08d | |
| 
							
							
								 | 
						cb517934a3 | |
| 
							
							
								 | 
						3c9e732552 | |
| 
							
							
								 | 
						64a2b6ee34 | |
| 
							
							
								 | 
						c19ab6b61e | |
| 
							
							
								 | 
						07c8a4b7d0 | |
| 
							
							
								 | 
						4b48142491 | |
| 
							
							
								 | 
						570cf7b8f1 | |
| 
							
							
								 | 
						308825f9c2 | |
| 
							
							
								 | 
						d2cf1a4dfd | |
| 
							
							
								 | 
						79b19999f0 | |
| 
							
							
								 | 
						2094a7b249 | |
| 
							
							
								 | 
						0ea412e725 | |
| 
							
							
								 | 
						8fe213156a | |
| 
							
							
								 | 
						ea7d9768d0 | |
| 
							
							
								 | 
						2bf7ef6e8a | |
| 
							
							
								 | 
						5466a2881c | |
| 
							
							
								 | 
						76eeabdf7f | |
| 
							
							
								 | 
						b897f0b5c8 | |
| 
							
							
								 | 
						82145021a1 | |
| 
							
							
								 | 
						4f5b0f3f9a | |
| 
							
							
								 | 
						d0852f5d3a | |
| 
							
							
								 | 
						b9f59140a7 | |
| 
							
							
								 | 
						fef08db999 | |
| 
							
							
								 | 
						c2bfb0372c | |
| 
							
							
								 | 
						d272537cf4 | |
| 
							
							
								 | 
						7c308c725c | |
| 
							
							
								 | 
						8788f7e89b | |
| 
							
							
								 | 
						46cccf22e2 | |
| 
							
							
								 | 
						4f20218bcd | |
| 
							
							
								 | 
						f72dfcf95e | |
| 
							
							
								 | 
						12549c1636 | |
| 
							
							
								 | 
						5bf2e81ea9 | |
| 
							
							
								 | 
						16ea108595 | |
| 
							
							
								
								 | 
						e7efe49016 | |
| 
							
							
								
								 | 
						93aa6dd20f | |
| 
							
							
								 | 
						0f678ff28a | |
| 
							
							
								 | 
						61d7b5850d | |
| 
							
							
								 | 
						4de10ff715 | |
| 
							
							
								 | 
						328662cc95 | |
| 
							
							
								 | 
						d60dfd7673 | |
| 
							
							
								 | 
						5aebf6a070 | |
| 
							
							
								 | 
						38b82067c7 | |
| 
							
							
								 | 
						d33f3d7063 | |
| 
							
							
								 | 
						8c519bbab7 | |
| 
							
							
								 | 
						09f5647319 | |
| 
							
							
								 | 
						4ddea224a1 | 
							
								
								
									
										2
									
								
								go.mod
								
								
								
								
							
							
						
						
									
										2
									
								
								go.mod
								
								
								
								
							| 
						 | 
				
			
			@ -4,7 +4,7 @@ go 1.20
 | 
			
		|||
 | 
			
		||||
require (
 | 
			
		||||
	git.selly.red/Selly-Modules/logger v0.0.2-0.20221010053254-567df039afdb
 | 
			
		||||
	git.selly.red/Selly-Modules/natsio v1.0.3-0.20231020090841-5edec97ee393
 | 
			
		||||
	git.selly.red/Selly-Modules/natsio v1.0.3-0.20240620022429-b891bfc9c52d
 | 
			
		||||
	github.com/go-resty/resty/v2 v2.7.0
 | 
			
		||||
	github.com/nats-io/nats.go v1.17.0
 | 
			
		||||
	github.com/thoas/go-funk v0.9.2
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										4
									
								
								go.sum
								
								
								
								
							
							
						
						
									
										4
									
								
								go.sum
								
								
								
								
							| 
						 | 
				
			
			@ -1,7 +1,7 @@
 | 
			
		|||
git.selly.red/Selly-Modules/logger v0.0.2-0.20221010053254-567df039afdb h1:AmcYd88IcdSkH+NEvKyJLT7psidSkjJQT/nAg/KuzFk=
 | 
			
		||||
git.selly.red/Selly-Modules/logger v0.0.2-0.20221010053254-567df039afdb/go.mod h1:Q1//Z6HRmfa7VyjH2J6YyT0YV2jT8+K6SIgwnYuS4II=
 | 
			
		||||
git.selly.red/Selly-Modules/natsio v1.0.3-0.20231020090841-5edec97ee393 h1:43kE03FW3NONfE6hXlghafS1d233dfc7grlFqd+15SA=
 | 
			
		||||
git.selly.red/Selly-Modules/natsio v1.0.3-0.20231020090841-5edec97ee393/go.mod h1:KNODhfeBqxRmHHQHHU+p3JfH42t8s5aNxfgr6X8fr6g=
 | 
			
		||||
git.selly.red/Selly-Modules/natsio v1.0.3-0.20240620022429-b891bfc9c52d h1:fSFFbzh+Xr7fjyn3R2smaEf/EPF78uZuHCq552OxJlU=
 | 
			
		||||
git.selly.red/Selly-Modules/natsio v1.0.3-0.20240620022429-b891bfc9c52d/go.mod h1:KNODhfeBqxRmHHQHHU+p3JfH42t8s5aNxfgr6X8fr6g=
 | 
			
		||||
github.com/armon/go-radix v1.0.0 h1:F4z6KzEeeQIMeLFa97iZU6vupzoecKdU5TX24SNppXI=
 | 
			
		||||
github.com/armon/go-radix v1.0.0/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8=
 | 
			
		||||
github.com/benbjohnson/clock v1.1.0 h1:Q92kusRqC1XV2MjkWETPvjJVqKetz1OzxZB7mHJLju8=
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -167,7 +167,7 @@ func (c *Client) GetOrder(orderCode string) (*GetOrderResponseDecoded, error) {
 | 
			
		|||
}
 | 
			
		||||
 | 
			
		||||
func (c *Client) requestNats(subject string, data interface{}) (*nats.Msg, error) {
 | 
			
		||||
	b := toBytes(data)
 | 
			
		||||
	b := pjson.ToBytes(data)
 | 
			
		||||
	return c.natsClient.Request(subject, b)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -3,27 +3,10 @@ package globalcare
 | 
			
		|||
import (
 | 
			
		||||
	"crypto/rsa"
 | 
			
		||||
	"crypto/x509"
 | 
			
		||||
	"encoding/json"
 | 
			
		||||
	"encoding/pem"
 | 
			
		||||
	"fmt"
 | 
			
		||||
 | 
			
		||||
	"git.selly.red/Selly-Modules/logger"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// toBytes ...
 | 
			
		||||
func toBytes(data interface{}) []byte {
 | 
			
		||||
	b, err := json.Marshal(data)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		logger.Error("pjson.toBytes", logger.LogData{"payload": data})
 | 
			
		||||
	}
 | 
			
		||||
	return b
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// toJSONString ...
 | 
			
		||||
func toJSONString(data interface{}) string {
 | 
			
		||||
	return string(toBytes(data))
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// GeneratePublicKeyFromBytes ...
 | 
			
		||||
func generatePublicKeyFromBytes(b []byte) (*rsa.PublicKey, error) {
 | 
			
		||||
	pubPem, _ := pem.Decode(b)
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -3,6 +3,7 @@ package onpoint
 | 
			
		|||
import (
 | 
			
		||||
	"errors"
 | 
			
		||||
	"fmt"
 | 
			
		||||
	"log"
 | 
			
		||||
	"net/http"
 | 
			
		||||
	"net/url"
 | 
			
		||||
	"strconv"
 | 
			
		||||
| 
						 | 
				
			
			@ -66,12 +67,12 @@ func (c *Client) CreateOrder(p CreateOrderRequest) (*CreateOrderResponse, error)
 | 
			
		|||
	}
 | 
			
		||||
	if res.StatusCode >= http.StatusBadRequest {
 | 
			
		||||
		if err := r.ParseResponseData(&errRes); err != nil {
 | 
			
		||||
			return nil, fmt.Errorf("onpoint.Client.CreateOrder: parse_response_err: %v. Reason: %s", err, res.Body)
 | 
			
		||||
			return nil, fmt.Errorf("onpoint.Client.CreateOrder: parse_response_err: %v", err)
 | 
			
		||||
		}
 | 
			
		||||
		return nil, errRes
 | 
			
		||||
	}
 | 
			
		||||
	if err := r.ParseResponseData(&dataRes); err != nil {
 | 
			
		||||
		return nil, fmt.Errorf("onpoint.Client.CreateOrder: parse_response_data: %v. Raw response: %s", err, res.Body)
 | 
			
		||||
		return nil, fmt.Errorf("onpoint.Client.CreateOrder: parse_response_data: %v", err)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return &dataRes.Data, nil
 | 
			
		||||
| 
						 | 
				
			
			@ -228,6 +229,8 @@ func (c *Client) requestHttpViaNats(data model.CommunicationRequestHttp, res int
 | 
			
		|||
		ts,
 | 
			
		||||
	}
 | 
			
		||||
	s := strings.Join(arr, ".")
 | 
			
		||||
	log.Println("DEBUG: onpoint. secret_message:", s)
 | 
			
		||||
	log.Println("DEBUG: onpoint. secret_key:", c.secretKey)
 | 
			
		||||
	// sign data
 | 
			
		||||
	sign := hashSHA256AndUppercase(s, c.secretKey)
 | 
			
		||||
	data.Payload.Header = map[string]string{
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -0,0 +1,54 @@
 | 
			
		|||
package shiip
 | 
			
		||||
 | 
			
		||||
const (
 | 
			
		||||
	TimeLayout = "2006-01-02 15:04:05"
 | 
			
		||||
 | 
			
		||||
	apiPathCreateOutboundRequest             = "/v1/api/external/vietful/outbound/requests"
 | 
			
		||||
	apiPathGetOutboundRequest                = "/v1/api/external/vietful/outbound/requests/%d"
 | 
			
		||||
	apiPathCancelOutboundRequest             = "/v1/api/external/vietful/outbound/requests/%d/cancel"
 | 
			
		||||
	apiPathUpdateLogisticInfoOutboundRequest = "/v1/api/external/vietful/outbound/requests/%d/logistic-info"
 | 
			
		||||
	apiPathAuth                              = "/v1/api/external/vietful/auth/access-token"
 | 
			
		||||
 | 
			
		||||
	PriorityUrgent = 3
 | 
			
		||||
	PriorityHigh   = 2
 | 
			
		||||
	PriorityNormal = 1
 | 
			
		||||
 | 
			
		||||
	TPLCodeGHN          = "GHN"
 | 
			
		||||
	TPLCodeGHTK         = "GHTK"
 | 
			
		||||
	TPLCodeBest         = "BEST"
 | 
			
		||||
	TPLCodeSnappy       = "SPY"
 | 
			
		||||
	TPLCodeViettelPost  = "VTP"
 | 
			
		||||
	TPLCodeSellyExpress = "SE"
 | 
			
		||||
	TPLCodeJTExpress    = "JTE"
 | 
			
		||||
 | 
			
		||||
	ShippingServiceCodeSTD = "STD"
 | 
			
		||||
	ORTypeOrder            = 1
 | 
			
		||||
	ShippingTypeSelfShip   = 1
 | 
			
		||||
	PackTypeNormal         = 1
 | 
			
		||||
	BizTypeB2C             = 1
 | 
			
		||||
	ConditionTypeCodeNew   = "NEW"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
const (
 | 
			
		||||
	baseURLAuthStaging = "https://api.shiip.vn"
 | 
			
		||||
	baseURLStaging     = "https://api.shiip.vn"
 | 
			
		||||
 | 
			
		||||
	// TODO: add base URL
 | 
			
		||||
	baseURLAuthProd = ""
 | 
			
		||||
	baseURLProd     = ""
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
const (
 | 
			
		||||
	ErrCodeExistPartnerCode = "exist_partner_code"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
var (
 | 
			
		||||
	baseURLENVMapping = map[ENV]string{
 | 
			
		||||
		EnvProd:    baseURLProd,
 | 
			
		||||
		EnvStaging: baseURLStaging,
 | 
			
		||||
	}
 | 
			
		||||
	baseURLAuthENVMapping = map[ENV]string{
 | 
			
		||||
		EnvProd:    baseURLAuthProd,
 | 
			
		||||
		EnvStaging: baseURLAuthStaging,
 | 
			
		||||
	}
 | 
			
		||||
)
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,9 @@
 | 
			
		|||
package shiip
 | 
			
		||||
 | 
			
		||||
// ENV ...
 | 
			
		||||
type ENV string
 | 
			
		||||
 | 
			
		||||
const (
 | 
			
		||||
	EnvStaging ENV = "STAGING"
 | 
			
		||||
	EnvProd    ENV = "PROD"
 | 
			
		||||
)
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,22 @@
 | 
			
		|||
package shiip
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"fmt"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// Error ...
 | 
			
		||||
type Error struct {
 | 
			
		||||
	Code    string `json:"code"`
 | 
			
		||||
	Message string `json:"errorMessage"`
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Error ...
 | 
			
		||||
func (e Error) Error() string {
 | 
			
		||||
	return fmt.Sprintf("tnc_err: code %s, messsage %s", e.Code, e.Message)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// IsErrExistPartnerCode ...
 | 
			
		||||
func IsErrExistPartnerCode(err error) bool {
 | 
			
		||||
	e, ok := err.(Error)
 | 
			
		||||
	return ok && e.Code == ErrCodeExistPartnerCode
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,62 @@
 | 
			
		|||
package shiip
 | 
			
		||||
 | 
			
		||||
// 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,omitempty"`
 | 
			
		||||
	DistrictCode string `json:"districtCode,omitempty"`
 | 
			
		||||
	WardCode     string `json:"wardCode,omitempty"`
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// 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"`
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// UpdateORLogisticInfoPayload ...
 | 
			
		||||
type UpdateORLogisticInfoPayload struct {
 | 
			
		||||
	OrID           int     `json:"orId"`
 | 
			
		||||
	TrackingCode   string  `json:"trackingCode"`
 | 
			
		||||
	ShippingLabels []Label `json:"shippingLabels"`
 | 
			
		||||
	TPLCode        string  `json:"tplCode"`
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type Label struct {
 | 
			
		||||
	Caption string `json:"caption"`
 | 
			
		||||
	URI     string `json:"uri"`
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type AuthPayload struct {
 | 
			
		||||
	ClientID     string `json:"clientId"`
 | 
			
		||||
	ClientSecret string `json:"clientSecret"`
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,57 @@
 | 
			
		|||
package shiip
 | 
			
		||||
 | 
			
		||||
// OutboundRequestRes ...
 | 
			
		||||
type OutboundRequestRes struct {
 | 
			
		||||
	OrID          int    `json:"orId"`
 | 
			
		||||
	OrCode        string `json:"orCode"`
 | 
			
		||||
	PartnerORCode string `json:"partnerORCode"`
 | 
			
		||||
	Error         *Error `json:"error"`
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
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,295 @@
 | 
			
		|||
package shiip
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"fmt"
 | 
			
		||||
	"log"
 | 
			
		||||
	"net/http"
 | 
			
		||||
	"time"
 | 
			
		||||
 | 
			
		||||
	"git.selly.red/Selly-Modules/natsio"
 | 
			
		||||
	"git.selly.red/Selly-Modules/natsio/model"
 | 
			
		||||
	"git.selly.red/Selly-Modules/natsio/subject"
 | 
			
		||||
	"github.com/nats-io/nats.go"
 | 
			
		||||
 | 
			
		||||
	"git.selly.red/Selly-Modules/3pl/util/httputil"
 | 
			
		||||
	"git.selly.red/Selly-Modules/3pl/util/pjson"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// Client ...
 | 
			
		||||
type Client struct {
 | 
			
		||||
	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("shiip.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 := model.CommunicationRequestHttp{
 | 
			
		||||
		ResponseImmediately: true,
 | 
			
		||||
		Payload: model.HttpRequest{
 | 
			
		||||
			URL:    apiURL,
 | 
			
		||||
			Method: http.MethodPost,
 | 
			
		||||
			Data:   pjson.ToJSONString([]OutboundRequestPayload{p}),
 | 
			
		||||
			Header: c.getRequestHeader(),
 | 
			
		||||
		},
 | 
			
		||||
	}
 | 
			
		||||
	msg, err := c.requestHttpViaNats(natsPayload)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		log.Printf("shiip.Client.CreateOutboundRequest - requestHttpViaNats: %v, %+v\n", err, natsPayload)
 | 
			
		||||
		return nil, err
 | 
			
		||||
	}
 | 
			
		||||
	var (
 | 
			
		||||
		r       model.CommunicationHttpResponse
 | 
			
		||||
		errRes  Error
 | 
			
		||||
		dataRes []OutboundRequestRes
 | 
			
		||||
	)
 | 
			
		||||
	if err = pjson.Unmarshal(msg.Data, &r); err != nil {
 | 
			
		||||
		return nil, fmt.Errorf("shiip.Client.CreateOutboundRequest: parse_data %v", err)
 | 
			
		||||
	}
 | 
			
		||||
	res := r.Response
 | 
			
		||||
	if res == nil {
 | 
			
		||||
		return nil, fmt.Errorf("shiip.Client.CreateOutboundRequest: empty_response")
 | 
			
		||||
	}
 | 
			
		||||
	if res.StatusCode >= http.StatusBadRequest {
 | 
			
		||||
		if err = r.ParseResponseData(&errRes); err != nil {
 | 
			
		||||
			return nil, fmt.Errorf("shiip.Client.CreateOutboundRequest: parse_response_err: %v", err)
 | 
			
		||||
		}
 | 
			
		||||
		return nil, errRes
 | 
			
		||||
	}
 | 
			
		||||
	if err = r.ParseResponseData(&dataRes); err != nil {
 | 
			
		||||
		return nil, fmt.Errorf("shiip.Client.CreateOutboundRequest: parse_response_data: %v", err)
 | 
			
		||||
	}
 | 
			
		||||
	if len(dataRes) == 0 {
 | 
			
		||||
		return nil, fmt.Errorf("shiip.Client.CreateOutboundRequest: empty_result")
 | 
			
		||||
	}
 | 
			
		||||
	item := &dataRes[0]
 | 
			
		||||
	e := item.Error
 | 
			
		||||
	if e != nil {
 | 
			
		||||
		return nil, errRes
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return item, err
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// UpdateOutboundRequestLogisticInfo ...
 | 
			
		||||
func (c *Client) UpdateOutboundRequestLogisticInfo(p UpdateORLogisticInfoPayload) error {
 | 
			
		||||
	apiURL := c.getBaseURL() + fmt.Sprintf(apiPathUpdateLogisticInfoOutboundRequest, p.OrID)
 | 
			
		||||
	natsPayload := model.CommunicationRequestHttp{
 | 
			
		||||
		ResponseImmediately: true,
 | 
			
		||||
		Payload: model.HttpRequest{
 | 
			
		||||
			URL:    apiURL,
 | 
			
		||||
			Method: http.MethodPost,
 | 
			
		||||
			Header: c.getRequestHeader(),
 | 
			
		||||
			Data:   pjson.ToJSONString(p),
 | 
			
		||||
		},
 | 
			
		||||
	}
 | 
			
		||||
	msg, err := c.requestHttpViaNats(natsPayload)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		log.Printf("shiip.Client.UpdateOutboundRequestLogisticInfo - requestHttpViaNats: %v, %+v\n", err, natsPayload)
 | 
			
		||||
		return err
 | 
			
		||||
	}
 | 
			
		||||
	var (
 | 
			
		||||
		r      model.CommunicationHttpResponse
 | 
			
		||||
		errRes Error
 | 
			
		||||
	)
 | 
			
		||||
	if err = pjson.Unmarshal(msg.Data, &r); err != nil {
 | 
			
		||||
		return fmt.Errorf("shiip.Client.UpdateOutboundRequestLogisticInfo: parse_data %v", err)
 | 
			
		||||
	}
 | 
			
		||||
	res := r.Response
 | 
			
		||||
	if res == nil {
 | 
			
		||||
		return fmt.Errorf("shiip.Client.UpdateOutboundRequestLogisticInfo: empty_response")
 | 
			
		||||
	}
 | 
			
		||||
	if res.StatusCode >= http.StatusBadRequest {
 | 
			
		||||
		if err = r.ParseResponseData(&errRes); err != nil {
 | 
			
		||||
			return fmt.Errorf("shiip.Client.UpdateOutboundRequestLogisticInfo: parse_response_err: %v", err)
 | 
			
		||||
		}
 | 
			
		||||
		return errRes
 | 
			
		||||
	}
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// GetOutboundRequestByID ...
 | 
			
		||||
func (c *Client) GetOutboundRequestByID(requestID int) (*OutboundRequestInfo, error) {
 | 
			
		||||
	apiURL := c.getBaseURL() + fmt.Sprintf(apiPathGetOutboundRequest, requestID)
 | 
			
		||||
	natsPayload := model.CommunicationRequestHttp{
 | 
			
		||||
		ResponseImmediately: true,
 | 
			
		||||
		Payload: model.HttpRequest{
 | 
			
		||||
			URL:    apiURL,
 | 
			
		||||
			Method: http.MethodGet,
 | 
			
		||||
			Header: c.getRequestHeader(),
 | 
			
		||||
		},
 | 
			
		||||
	}
 | 
			
		||||
	msg, err := c.requestHttpViaNats(natsPayload)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		log.Printf("shiip.Client.GetOutboundRequestByID - requestHttpViaNats: %v, %+v\n", err, natsPayload)
 | 
			
		||||
		return nil, err
 | 
			
		||||
	}
 | 
			
		||||
	var (
 | 
			
		||||
		r               model.CommunicationHttpResponse
 | 
			
		||||
		errRes          Error
 | 
			
		||||
		outboundRequest OutboundRequestInfo
 | 
			
		||||
	)
 | 
			
		||||
	if err = pjson.Unmarshal(msg.Data, &r); err != nil {
 | 
			
		||||
		return nil, fmt.Errorf("shiip.Client.GetOutboundRequestByID: parse_data %v", err)
 | 
			
		||||
	}
 | 
			
		||||
	res := r.Response
 | 
			
		||||
	if res == nil {
 | 
			
		||||
		return nil, fmt.Errorf("shiip.Client.GetOutboundRequestByID: empty_response")
 | 
			
		||||
	}
 | 
			
		||||
	if res.StatusCode >= http.StatusBadRequest {
 | 
			
		||||
		if err = r.ParseResponseData(&errRes); err != nil {
 | 
			
		||||
			return nil, fmt.Errorf("shiip.Client.GetOutboundRequestByID: parse_response_err: %v", err)
 | 
			
		||||
		}
 | 
			
		||||
		return nil, errRes
 | 
			
		||||
	}
 | 
			
		||||
	if err = r.ParseResponseData(&outboundRequest); err != nil {
 | 
			
		||||
		return nil, fmt.Errorf("shiip.Client.GetOutboundRequestByID: parse_response_data: %v", err)
 | 
			
		||||
	}
 | 
			
		||||
	return &outboundRequest, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// CancelOutboundRequest ...
 | 
			
		||||
func (c *Client) CancelOutboundRequest(requestID int, note string) error {
 | 
			
		||||
	apiURL := c.getBaseURL() + fmt.Sprintf(apiPathCancelOutboundRequest, requestID)
 | 
			
		||||
	data := map[string]string{"note": note}
 | 
			
		||||
	natsPayload := model.CommunicationRequestHttp{
 | 
			
		||||
		ResponseImmediately: true,
 | 
			
		||||
		Payload: model.HttpRequest{
 | 
			
		||||
			URL:    apiURL,
 | 
			
		||||
			Method: http.MethodPost,
 | 
			
		||||
			Header: c.getRequestHeader(),
 | 
			
		||||
			Data:   pjson.ToJSONString(data),
 | 
			
		||||
		},
 | 
			
		||||
	}
 | 
			
		||||
	msg, err := c.requestHttpViaNats(natsPayload)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		log.Printf("shiip.Client.CancelOutboundRequest - requestHttpViaNats: %v, %+v\n", err, natsPayload)
 | 
			
		||||
		return err
 | 
			
		||||
	}
 | 
			
		||||
	var (
 | 
			
		||||
		r      model.CommunicationHttpResponse
 | 
			
		||||
		errRes Error
 | 
			
		||||
	)
 | 
			
		||||
	if err = pjson.Unmarshal(msg.Data, &r); err != nil {
 | 
			
		||||
		return fmt.Errorf("shiip.Client.CancelOutboundRequest: parse_data %v", err)
 | 
			
		||||
	}
 | 
			
		||||
	res := r.Response
 | 
			
		||||
	if res == nil {
 | 
			
		||||
		return fmt.Errorf("shiip.Client.CancelOutboundRequest: empty_response")
 | 
			
		||||
	}
 | 
			
		||||
	if res.StatusCode >= http.StatusBadRequest {
 | 
			
		||||
		if err = r.ParseResponseData(&errRes); err != nil {
 | 
			
		||||
			return fmt.Errorf("shiip.Client.CancelOutboundRequest: parse_response_err: %v", err)
 | 
			
		||||
		}
 | 
			
		||||
		return errRes
 | 
			
		||||
	}
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (c *Client) auth() (*authRes, error) {
 | 
			
		||||
	b := AuthPayload{
 | 
			
		||||
		ClientID:     c.clientID,
 | 
			
		||||
		ClientSecret: c.clientSecret,
 | 
			
		||||
	}
 | 
			
		||||
	header := map[string]string{
 | 
			
		||||
		httputil.HeaderKeyContentType: httputil.HeaderValueApplicationJSON,
 | 
			
		||||
	}
 | 
			
		||||
	apiURL := baseURLAuthENVMapping[c.env] + apiPathAuth
 | 
			
		||||
	natsPayload := model.CommunicationRequestHttp{
 | 
			
		||||
		ResponseImmediately: true,
 | 
			
		||||
		Payload: model.HttpRequest{
 | 
			
		||||
			URL:    apiURL,
 | 
			
		||||
			Method: http.MethodPost,
 | 
			
		||||
			Data:   pjson.ToJSONString(b),
 | 
			
		||||
			Header: header,
 | 
			
		||||
		},
 | 
			
		||||
	}
 | 
			
		||||
	msg, err := c.requestHttpViaNats(natsPayload)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		log.Printf("shiip.Client.auth - requestHttpViaNats: %v, %+v\n", err, natsPayload)
 | 
			
		||||
		return nil, err
 | 
			
		||||
	}
 | 
			
		||||
	var (
 | 
			
		||||
		r      model.CommunicationHttpResponse
 | 
			
		||||
		errRes Error
 | 
			
		||||
		data   authRes
 | 
			
		||||
	)
 | 
			
		||||
	if err = pjson.Unmarshal(msg.Data, &r); err != nil {
 | 
			
		||||
		return nil, fmt.Errorf("shiip.Client.auth: parse_data %v", err)
 | 
			
		||||
	}
 | 
			
		||||
	res := r.Response
 | 
			
		||||
	if res == nil {
 | 
			
		||||
		return nil, fmt.Errorf("shiip.Client.auth: empty_response")
 | 
			
		||||
	}
 | 
			
		||||
	if res.StatusCode >= http.StatusBadRequest {
 | 
			
		||||
		if err = r.ParseResponseData(&errRes); err != nil {
 | 
			
		||||
			return nil, fmt.Errorf("shiip.Client.auth: parse_response_err: %v", err)
 | 
			
		||||
		}
 | 
			
		||||
		return nil, errRes
 | 
			
		||||
	}
 | 
			
		||||
	if err = r.ParseResponseData(&data); err != nil {
 | 
			
		||||
		return nil, fmt.Errorf("shiip.Client.auth: parse_response_data: %v", err)
 | 
			
		||||
	}
 | 
			
		||||
	return &data, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (c *Client) getRequestHeader() map[string]string {
 | 
			
		||||
	m := map[string]string{
 | 
			
		||||
		httputil.HeaderKeyContentType: httputil.HeaderValueApplicationJSON,
 | 
			
		||||
	}
 | 
			
		||||
	token, err := c.getToken()
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		log.Printf("shiip.Client.getToken: %v\n", err)
 | 
			
		||||
	} else {
 | 
			
		||||
		m["Authorization"] = fmt.Sprintf("Bearer %s", token)
 | 
			
		||||
	}
 | 
			
		||||
	return m
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (c *Client) requestHttpViaNats(data model.CommunicationRequestHttp) (*nats.Msg, error) {
 | 
			
		||||
	b := pjson.ToBytes(data)
 | 
			
		||||
	return c.natsClient.Request(subject.Communication.RequestHTTP, 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
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -28,7 +28,6 @@ type ORPayload struct {
 | 
			
		|||
	CodType        string          `json:"cod_type"`
 | 
			
		||||
	Note           string          `json:"note"`
 | 
			
		||||
	OrCode         string          `json:"or_code"`
 | 
			
		||||
	PartnerORCode  string          `json:"partner_or_code"`
 | 
			
		||||
	OrType         string          `json:"or_type"`
 | 
			
		||||
	ShippingType   string          `json:"shipping_type"`
 | 
			
		||||
	CustomerName   string          `json:"customer_name"`
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -17,7 +17,7 @@ import (
 | 
			
		|||
)
 | 
			
		||||
 | 
			
		||||
const (
 | 
			
		||||
	baseURLStag     = "https://dev-wms-gw.viettelpost.vn"
 | 
			
		||||
	baseURLStag     = "https://stg-gw.viettelpost.vn"
 | 
			
		||||
	baseURLAuthStag = "https://stg-keycloak.viettelpost.vn"
 | 
			
		||||
 | 
			
		||||
	baseURLProd     = "https://gw.viettelpost.vn"
 | 
			
		||||
| 
						 | 
				
			
			@ -25,7 +25,7 @@ const (
 | 
			
		|||
 | 
			
		||||
	pathAuth                 = "/realms/wms/protocol/openid-connect/token"
 | 
			
		||||
	pathUpdateORLogisticInfo = "/wms-core/api/v1/obms/outbound-request/outbound-request-partner/%s"
 | 
			
		||||
	pathCreateOR             = "/wms-integration/api/v1/obms/outbound-request/outbound-request-partner/hab"
 | 
			
		||||
	pathCreateOR             = "/wms-core/api/v1/obms/outbound-request/outbound-request-partner/hab"
 | 
			
		||||
	pathCancelOR             = "/wms-core/api/v1/obms/outbound-request/cancel"
 | 
			
		||||
 | 
			
		||||
	logTarget = "viettel-ffm"
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -2,15 +2,14 @@ package pjson
 | 
			
		|||
 | 
			
		||||
import (
 | 
			
		||||
	"encoding/json"
 | 
			
		||||
 | 
			
		||||
	"git.selly.red/Selly-Modules/logger"
 | 
			
		||||
	"log"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// ToBytes ...
 | 
			
		||||
func ToBytes(data interface{}) []byte {
 | 
			
		||||
	b, err := json.Marshal(data)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		logger.Error("pjson.ToBytes", logger.LogData{"payload": data})
 | 
			
		||||
		log.Printf("3pl/util/pjson.ToBytes.Marshal: %v\n", err)
 | 
			
		||||
	}
 | 
			
		||||
	return b
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
		Reference in New Issue