Merge pull request 'kiotviet' (#11) from kiotviet into master
Reviewed-on: #11
This commit is contained in:
		
						commit
						007796e668
					
				| 
						 | 
					@ -0,0 +1,39 @@
 | 
				
			||||||
 | 
					package main
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import (
 | 
				
			||||||
 | 
						"fmt"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						"git.selly.red/Selly-Modules/natsio"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						"git.selly.red/Selly-Modules/3pl/partnerapi/kiotviet"
 | 
				
			||||||
 | 
						"git.selly.red/Selly-Modules/3pl/util/pjson"
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func main() {
 | 
				
			||||||
 | 
						var (
 | 
				
			||||||
 | 
							client   = "45575d3e-5785-***"
 | 
				
			||||||
 | 
							secret   = "65ACE104EC4232***"
 | 
				
			||||||
 | 
							retailer = "****"
 | 
				
			||||||
 | 
						)
 | 
				
			||||||
 | 
						if err := natsio.Connect(natsio.Config{URL: "localhost:4222"}); err != nil {
 | 
				
			||||||
 | 
							panic(err)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						c, err := kiotviet.New(client, secret, retailer, natsio.GetServer())
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							panic(err)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						data, err := c.GetBranches(kiotviet.ListBranchesReq{})
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							panic(err)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						fmt.Println(pjson.ToJSONString(data))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						prod, err := c.GetProductOnHands(kiotviet.ListProductOnHandsReq{
 | 
				
			||||||
 | 
							PageSize: 10,
 | 
				
			||||||
 | 
						})
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							panic(err)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						fmt.Println(pjson.ToJSONString(prod))
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										2
									
								
								go.mod
								
								
								
								
							
							
						
						
									
										2
									
								
								go.mod
								
								
								
								
							| 
						 | 
					@ -4,7 +4,7 @@ go 1.17
 | 
				
			||||||
 | 
					
 | 
				
			||||||
require (
 | 
					require (
 | 
				
			||||||
	git.selly.red/Selly-Modules/logger v0.0.2-0.20221010053254-567df039afdb
 | 
						git.selly.red/Selly-Modules/logger v0.0.2-0.20221010053254-567df039afdb
 | 
				
			||||||
	git.selly.red/Selly-Modules/natsio v1.0.2-0.20221010041139-c11419a3ad33
 | 
						git.selly.red/Selly-Modules/natsio v1.0.3-0.20231020090841-5edec97ee393
 | 
				
			||||||
	github.com/nats-io/nats.go v1.17.0
 | 
						github.com/nats-io/nats.go v1.17.0
 | 
				
			||||||
	github.com/thoas/go-funk v0.9.2
 | 
						github.com/thoas/go-funk v0.9.2
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
							
								
								
									
										4
									
								
								go.sum
								
								
								
								
							
							
						
						
									
										4
									
								
								go.sum
								
								
								
								
							| 
						 | 
					@ -2,6 +2,10 @@ git.selly.red/Selly-Modules/logger v0.0.2-0.20221010053254-567df039afdb h1:AmcYd
 | 
				
			||||||
git.selly.red/Selly-Modules/logger v0.0.2-0.20221010053254-567df039afdb/go.mod h1:Q1//Z6HRmfa7VyjH2J6YyT0YV2jT8+K6SIgwnYuS4II=
 | 
					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.2-0.20221010041139-c11419a3ad33 h1:GvQjelaV4XZm++AOihYAKOD6k9510aMAr6B6MGnrXPs=
 | 
					git.selly.red/Selly-Modules/natsio v1.0.2-0.20221010041139-c11419a3ad33 h1:GvQjelaV4XZm++AOihYAKOD6k9510aMAr6B6MGnrXPs=
 | 
				
			||||||
git.selly.red/Selly-Modules/natsio v1.0.2-0.20221010041139-c11419a3ad33/go.mod h1:KNODhfeBqxRmHHQHHU+p3JfH42t8s5aNxfgr6X8fr6g=
 | 
					git.selly.red/Selly-Modules/natsio v1.0.2-0.20221010041139-c11419a3ad33/go.mod h1:KNODhfeBqxRmHHQHHU+p3JfH42t8s5aNxfgr6X8fr6g=
 | 
				
			||||||
 | 
					git.selly.red/Selly-Modules/natsio v1.0.3-0.20231006093940-b3bde5cd0960 h1:wL/BW1xGoB/EXeA2HtxT6Nr/cXpPJYVNfToV3aFtGls=
 | 
				
			||||||
 | 
					git.selly.red/Selly-Modules/natsio v1.0.3-0.20231006093940-b3bde5cd0960/go.mod h1:KNODhfeBqxRmHHQHHU+p3JfH42t8s5aNxfgr6X8fr6g=
 | 
				
			||||||
 | 
					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=
 | 
				
			||||||
github.com/armon/go-radix v1.0.0 h1:F4z6KzEeeQIMeLFa97iZU6vupzoecKdU5TX24SNppXI=
 | 
					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/armon/go-radix v1.0.0/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8=
 | 
				
			||||||
github.com/benbjohnson/clock v1.1.0 h1:Q92kusRqC1XV2MjkWETPvjJVqKetz1OzxZB7mHJLju8=
 | 
					github.com/benbjohnson/clock v1.1.0 h1:Q92kusRqC1XV2MjkWETPvjJVqKetz1OzxZB7mHJLju8=
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -0,0 +1,26 @@
 | 
				
			||||||
 | 
					package kiotviet
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const (
 | 
				
			||||||
 | 
						apiPathListBranches       = "/branches"
 | 
				
			||||||
 | 
						apiPathListProductOnHands = "/productOnHands"
 | 
				
			||||||
 | 
						apiPathListWebhook        = "/webhooks"
 | 
				
			||||||
 | 
						apiPathRegisterWebhook    = "/webhooks"
 | 
				
			||||||
 | 
						apiPathUnregisterWebhook  = "/webhooks/%d" // %s -> webhook id
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						apiPathAuth = "/connect/token"
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const (
 | 
				
			||||||
 | 
						baseURLProd      = "https://public.kiotapi.com"
 | 
				
			||||||
 | 
						baseURLTokenProd = "https://id.kiotviet.vn"
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const (
 | 
				
			||||||
 | 
						WebhookTypeCustomerUpdate = "customer.update"
 | 
				
			||||||
 | 
						WebhookTypeCustomerDelete = "customer.delete"
 | 
				
			||||||
 | 
						WebhookTypeProductUpdate  = "product.update"
 | 
				
			||||||
 | 
						WebhookTypeProductDelete  = "product.delete"
 | 
				
			||||||
 | 
						WebhookTypeStockUpdate    = "stock.update"
 | 
				
			||||||
 | 
						WebhookTypeOrderUpdate    = "order.update"
 | 
				
			||||||
 | 
						WebhookTypeInvoiceUpdate  = "invoice.update"
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
| 
						 | 
					@ -0,0 +1,9 @@
 | 
				
			||||||
 | 
					package kiotviet
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// ENV ...
 | 
				
			||||||
 | 
					type ENV string
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const (
 | 
				
			||||||
 | 
						// EnvStaging ENV = "STAGING"
 | 
				
			||||||
 | 
						EnvProd ENV = "PROD"
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
| 
						 | 
					@ -0,0 +1 @@
 | 
				
			||||||
 | 
					package kiotviet
 | 
				
			||||||
| 
						 | 
					@ -0,0 +1,300 @@
 | 
				
			||||||
 | 
					package kiotviet
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import (
 | 
				
			||||||
 | 
						"fmt"
 | 
				
			||||||
 | 
						"log"
 | 
				
			||||||
 | 
						"net/http"
 | 
				
			||||||
 | 
						"net/url"
 | 
				
			||||||
 | 
						"strconv"
 | 
				
			||||||
 | 
						"time"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						"git.selly.red/Selly-Modules/natsio"
 | 
				
			||||||
 | 
						"git.selly.red/Selly-Modules/natsio/model"
 | 
				
			||||||
 | 
						"git.selly.red/Selly-Modules/natsio/subject"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						"git.selly.red/Selly-Modules/3pl/util/httputil"
 | 
				
			||||||
 | 
						"git.selly.red/Selly-Modules/3pl/util/pjson"
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const (
 | 
				
			||||||
 | 
						logTarget = "kiotviet"
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					type Client struct {
 | 
				
			||||||
 | 
						clientID  string
 | 
				
			||||||
 | 
						secretKey string
 | 
				
			||||||
 | 
						retailer  string
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						natsClient natsio.Server
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						auth           *AuthRes
 | 
				
			||||||
 | 
						authExpireTime time.Time
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func New(clientID, secretKey, retailer string, natsClient natsio.Server) (*Client, error) {
 | 
				
			||||||
 | 
						if clientID == "" || secretKey == "" || retailer == "" {
 | 
				
			||||||
 | 
							return nil, fmt.Errorf("kiotviet: cannot create client with empty info")
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return &Client{
 | 
				
			||||||
 | 
							clientID:   clientID,
 | 
				
			||||||
 | 
							secretKey:  secretKey,
 | 
				
			||||||
 | 
							retailer:   retailer,
 | 
				
			||||||
 | 
							natsClient: natsClient,
 | 
				
			||||||
 | 
						}, nil
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (c *Client) GetProductOnHands(req ListProductOnHandsReq) (*ListProductOnHandsRes, error) {
 | 
				
			||||||
 | 
						apiURL := c.getURL(apiPathListProductOnHands)
 | 
				
			||||||
 | 
						query := map[string]string{
 | 
				
			||||||
 | 
							"orderBy":          req.OrderBy,
 | 
				
			||||||
 | 
							"lastModifiedFrom": req.LastModifiedFrom,
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if req.PageSize > 0 {
 | 
				
			||||||
 | 
							query["pageSize"] = strconv.Itoa(req.PageSize)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if req.CurrentItem > 0 {
 | 
				
			||||||
 | 
							query["currentItem"] = strconv.Itoa(req.CurrentItem)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						natsPayload := model.CommunicationRequestHttp{
 | 
				
			||||||
 | 
							ResponseImmediately: true,
 | 
				
			||||||
 | 
							Payload: model.HttpRequest{
 | 
				
			||||||
 | 
								URL:    apiURL,
 | 
				
			||||||
 | 
								Method: http.MethodGet,
 | 
				
			||||||
 | 
								Query:  query,
 | 
				
			||||||
 | 
								Header: c.getRequestHeader(),
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
							LogTarget: logTarget,
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						r, err := c.requestHttpViaNats(natsPayload)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							log.Printf("kiotviet.Client.GetProductOnHands - requestHttpViaNats: %v, %s\n", err, apiURL)
 | 
				
			||||||
 | 
							return nil, err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						res := r.Response
 | 
				
			||||||
 | 
						if res.StatusCode >= http.StatusBadRequest {
 | 
				
			||||||
 | 
							return nil, fmt.Errorf("kiotviet.Client.GetProductOnHands - requestHttpViaNats bad request %s", res.Body)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						var data ListProductOnHandsRes
 | 
				
			||||||
 | 
						if err = r.ParseResponseData(&data); err != nil {
 | 
				
			||||||
 | 
							return nil, fmt.Errorf("kiotviet.Client.GetProductOnHands - requestHttpViaNats parse response %v, %s", err, res.Body)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return &data, nil
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (c *Client) GetBranches(req ListBranchesReq) (*ListBranchesRes, error) {
 | 
				
			||||||
 | 
						apiURL := c.getURL(apiPathListBranches)
 | 
				
			||||||
 | 
						query := map[string]string{
 | 
				
			||||||
 | 
							"orderBy":          req.OrderBy,
 | 
				
			||||||
 | 
							"lastModifiedFrom": req.LastModifiedFrom,
 | 
				
			||||||
 | 
							"orderDirection":   req.OrderDirection,
 | 
				
			||||||
 | 
							"includeRemoveIds": req.IncludeRemoveIDs,
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if req.PageSize > 0 {
 | 
				
			||||||
 | 
							query["pageSize"] = strconv.Itoa(req.PageSize)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if req.CurrentItem > 0 {
 | 
				
			||||||
 | 
							query["currentItem"] = strconv.Itoa(req.CurrentItem)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						natsPayload := model.CommunicationRequestHttp{
 | 
				
			||||||
 | 
							ResponseImmediately: true,
 | 
				
			||||||
 | 
							Payload: model.HttpRequest{
 | 
				
			||||||
 | 
								URL:    apiURL,
 | 
				
			||||||
 | 
								Method: http.MethodGet,
 | 
				
			||||||
 | 
								Query:  query,
 | 
				
			||||||
 | 
								Header: c.getRequestHeader(),
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
							LogTarget: logTarget,
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						r, err := c.requestHttpViaNats(natsPayload)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							log.Printf("kiotviet.Client.GetBranches - requestHttpViaNats: %v, %s\n", err, apiURL)
 | 
				
			||||||
 | 
							return nil, err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						res := r.Response
 | 
				
			||||||
 | 
						if res.StatusCode >= http.StatusBadRequest {
 | 
				
			||||||
 | 
							return nil, fmt.Errorf("kiotviet.Client.GetBranches - requestHttpViaNats bad request %s", res.Body)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						var data ListBranchesRes
 | 
				
			||||||
 | 
						if err = r.ParseResponseData(&data); err != nil {
 | 
				
			||||||
 | 
							return nil, fmt.Errorf("kiotviet.Client.GetBranches - requestHttpViaNats parse response %v, %s", err, res.Body)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return &data, nil
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (c *Client) ListWebhooks(req ListWebhookReq) (*ListWebhookRes, error) {
 | 
				
			||||||
 | 
						apiURL := c.getURL(apiPathListWebhook)
 | 
				
			||||||
 | 
						natsPayload := model.CommunicationRequestHttp{
 | 
				
			||||||
 | 
							ResponseImmediately: true,
 | 
				
			||||||
 | 
							Payload: model.HttpRequest{
 | 
				
			||||||
 | 
								URL:    apiURL,
 | 
				
			||||||
 | 
								Method: http.MethodGet,
 | 
				
			||||||
 | 
								Header: c.getRequestHeader(),
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
							LogTarget: logTarget,
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						r, err := c.requestHttpViaNats(natsPayload)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							log.Printf("kiotviet.Client.ListWebhooks - requestHttpViaNats: %v, %s\n", err, apiURL)
 | 
				
			||||||
 | 
							return nil, err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						res := r.Response
 | 
				
			||||||
 | 
						if res.StatusCode >= http.StatusBadRequest {
 | 
				
			||||||
 | 
							return nil, fmt.Errorf("kiotviet.Client.ListWebhooks - requestHttpViaNats bad request %s", res.Body)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						var data ListWebhookRes
 | 
				
			||||||
 | 
						if err = r.ParseResponseData(&data); err != nil {
 | 
				
			||||||
 | 
							return nil, fmt.Errorf("kiotviet.Client.ListWebhooks - requestHttpViaNats parse response %v, %s", err, res.Body)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return &data, nil
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (c *Client) RegisterWebhook(req RegisterWebhookReq) (*RegisterWebhookRes, error) {
 | 
				
			||||||
 | 
						apiURL := c.getURL(apiPathRegisterWebhook)
 | 
				
			||||||
 | 
						natsPayload := model.CommunicationRequestHttp{
 | 
				
			||||||
 | 
							ResponseImmediately: true,
 | 
				
			||||||
 | 
							Payload: model.HttpRequest{
 | 
				
			||||||
 | 
								URL:    apiURL,
 | 
				
			||||||
 | 
								Method: http.MethodPost,
 | 
				
			||||||
 | 
								Data:   pjson.ToJSONString(req),
 | 
				
			||||||
 | 
								Header: c.getRequestHeader(),
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
							LogTarget: logTarget,
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						r, err := c.requestHttpViaNats(natsPayload)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							log.Printf("kiotviet.Client.RegisterWebhook - requestHttpViaNats: %v, %s\n", err, apiURL)
 | 
				
			||||||
 | 
							return nil, err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						res := r.Response
 | 
				
			||||||
 | 
						if res.StatusCode >= http.StatusBadRequest {
 | 
				
			||||||
 | 
							return nil, fmt.Errorf("kiotviet.Client.RegisterWebhook - requestHttpViaNats bad request %s", res.Body)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						var data RegisterWebhookRes
 | 
				
			||||||
 | 
						if err = r.ParseResponseData(&data); err != nil {
 | 
				
			||||||
 | 
							return nil, fmt.Errorf("kiotviet.Client.RegisterWebhook - requestHttpViaNats parse response %v, %s", err, res.Body)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return &data, nil
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (c *Client) UnregisterWebhook(req UnregisterWebhookReq) (*UnregisterWebhookRes, error) {
 | 
				
			||||||
 | 
						apiURL := c.getURL(fmt.Sprintf(apiPathUnregisterWebhook, req.ID))
 | 
				
			||||||
 | 
						natsPayload := model.CommunicationRequestHttp{
 | 
				
			||||||
 | 
							ResponseImmediately: true,
 | 
				
			||||||
 | 
							Payload: model.HttpRequest{
 | 
				
			||||||
 | 
								URL:    apiURL,
 | 
				
			||||||
 | 
								Method: http.MethodDelete,
 | 
				
			||||||
 | 
								Header: c.getRequestHeader(),
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
							LogTarget: logTarget,
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						r, err := c.requestHttpViaNats(natsPayload)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							log.Printf("kiotviet.Client.UnregisterWebhook - requestHttpViaNats: %v, %s\n", err, apiURL)
 | 
				
			||||||
 | 
							return nil, err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						res := r.Response
 | 
				
			||||||
 | 
						if res.StatusCode >= http.StatusBadRequest {
 | 
				
			||||||
 | 
							return nil, fmt.Errorf("kiotviet.Client.UnregisterWebhook - requestHttpViaNats bad request %s", res.Body)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						var data UnregisterWebhookRes
 | 
				
			||||||
 | 
						if err = r.ParseResponseData(&data.Success); err != nil {
 | 
				
			||||||
 | 
							return nil, fmt.Errorf("kiotviet.Client.UnregisterWebhook - requestHttpViaNats parse response %v, %s", err, res.Body)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return &data, nil
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (c *Client) Auth() (*AuthRes, error) {
 | 
				
			||||||
 | 
						v := url.Values{}
 | 
				
			||||||
 | 
						v.Add("scopes", "PublicApi.Access")
 | 
				
			||||||
 | 
						v.Add("grant_type", "client_credentials")
 | 
				
			||||||
 | 
						v.Add("client_id", c.clientID)
 | 
				
			||||||
 | 
						v.Add("client_secret", c.secretKey)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						body := v.Encode()
 | 
				
			||||||
 | 
						header := map[string]string{
 | 
				
			||||||
 | 
							httputil.HeaderKeyContentType: httputil.HeaderValueApplicationURLEncoded,
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						apiURL := baseURLTokenProd + apiPathAuth
 | 
				
			||||||
 | 
						natsPayload := model.CommunicationRequestHttp{
 | 
				
			||||||
 | 
							ResponseImmediately: true,
 | 
				
			||||||
 | 
							Payload: model.HttpRequest{
 | 
				
			||||||
 | 
								URL:    apiURL,
 | 
				
			||||||
 | 
								Method: http.MethodPost,
 | 
				
			||||||
 | 
								Data:   body,
 | 
				
			||||||
 | 
								Header: header,
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
							LogTarget: logTarget,
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						r, err := c.requestHttpViaNats(natsPayload)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							log.Printf("kiotviet.Client.Auth - requestHttpViaNats: %v, %s\n", err, apiURL)
 | 
				
			||||||
 | 
							return nil, err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						res := r.Response
 | 
				
			||||||
 | 
						if res.StatusCode >= http.StatusBadRequest {
 | 
				
			||||||
 | 
							return nil, fmt.Errorf("kiotviet.Client.Auth - requestHttpViaNats %s", res.Body)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						var data AuthRes
 | 
				
			||||||
 | 
						if err = r.ParseResponseData(&data); err != nil {
 | 
				
			||||||
 | 
							return nil, fmt.Errorf("kiotviet.Client.Auth - requestHttpViaNats parse response %v, %s", err, res.Body)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return &data, nil
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (c *Client) getURL(path string) string {
 | 
				
			||||||
 | 
						return baseURLProd + path
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					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("kiotviet.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("kiotviet.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("kiotviet.Client.requestHttpViaNats empty reponse")
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return &r, nil
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (c *Client) getRequestHeader() map[string]string {
 | 
				
			||||||
 | 
						m := map[string]string{
 | 
				
			||||||
 | 
							httputil.HeaderKeyContentType: httputil.HeaderValueApplicationJSON,
 | 
				
			||||||
 | 
							"Retailer":                    c.retailer,
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						token, err := c.getToken()
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							log.Printf("kiotviet.Client.getToken err %v\n", err)
 | 
				
			||||||
 | 
						} else {
 | 
				
			||||||
 | 
							m["Authorization"] = fmt.Sprintf("Bearer %s", token)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return m
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (c *Client) getToken() (string, error) {
 | 
				
			||||||
 | 
						auth := c.auth
 | 
				
			||||||
 | 
						if auth != nil && c.authExpireTime.After(time.Now()) {
 | 
				
			||||||
 | 
							return auth.AccessToken, nil
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						data, err := c.Auth()
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							return "", err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						c.auth = data
 | 
				
			||||||
 | 
						d := time.Duration(data.ExpiresIn) * time.Second
 | 
				
			||||||
 | 
						if d.Minutes() > 30 {
 | 
				
			||||||
 | 
							d -= 30 * time.Minute
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						c.authExpireTime = time.Now().Add(d)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return data.AccessToken, nil
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -0,0 +1,63 @@
 | 
				
			||||||
 | 
					package kiotviet
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					type AuthReq struct {
 | 
				
			||||||
 | 
						ClientID     string
 | 
				
			||||||
 | 
						ClientSecret string
 | 
				
			||||||
 | 
						GrantType    string
 | 
				
			||||||
 | 
						Scopes       string
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					type ListProductOnHandsReq struct {
 | 
				
			||||||
 | 
						OrderBy          string `json:"orderBy,omitempty"`
 | 
				
			||||||
 | 
						LastModifiedFrom string `json:"lastModifiedFrom,omitempty"`
 | 
				
			||||||
 | 
						PageSize         int    `json:"pageSize,omitempty"`
 | 
				
			||||||
 | 
						CurrentItem      int    `json:"currentItem,omitempty"`
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					type ListBranchesReq struct {
 | 
				
			||||||
 | 
						OrderBy          string `json:"orderBy,omitempty"`
 | 
				
			||||||
 | 
						LastModifiedFrom string `json:"lastModifiedFrom,omitempty"`
 | 
				
			||||||
 | 
						PageSize         int    `json:"pageSize,omitempty"`
 | 
				
			||||||
 | 
						CurrentItem      int    `json:"currentItem,omitempty"`
 | 
				
			||||||
 | 
						OrderDirection   string `json:"orderDirection,omitempty"`   // Asc/ Desc. Default Desc
 | 
				
			||||||
 | 
						IncludeRemoveIDs string `json:"includeRemoveIds,omitempty"` // true/ false
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					type ListWebhookReq struct {
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					type WebhookReq struct {
 | 
				
			||||||
 | 
						Type     string `json:"Type"`
 | 
				
			||||||
 | 
						Url      string `json:"Url"`
 | 
				
			||||||
 | 
						IsActive bool   `json:"IsActive"`
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					type RegisterWebhookReq struct {
 | 
				
			||||||
 | 
						Webhook WebhookReq `json:"webhook"`
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					type UnregisterWebhookReq struct {
 | 
				
			||||||
 | 
						ID int
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					type WebhookBody struct {
 | 
				
			||||||
 | 
						ID            string                `json:"Id"`
 | 
				
			||||||
 | 
						Attempt       int                   `json:"Attempt"`
 | 
				
			||||||
 | 
						Notifications []WebhookNotification `json:"Notifications"`
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					type WebhookNotification struct {
 | 
				
			||||||
 | 
						Action string                   `json:"Action"`
 | 
				
			||||||
 | 
						Data   []WebhookStockUpdateData `json:"Data"`
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					type WebhookStockUpdateData struct {
 | 
				
			||||||
 | 
						ProductID   int64  `json:"ProductId"`
 | 
				
			||||||
 | 
						ProductCode string `json:"ProductCode"`
 | 
				
			||||||
 | 
						ProductName string `json:"ProductName"`
 | 
				
			||||||
 | 
						BranchID    int    `json:"BranchId"`
 | 
				
			||||||
 | 
						BranchName  string `json:"BranchName"`
 | 
				
			||||||
 | 
						Cost        int64  `json:"Cost"`
 | 
				
			||||||
 | 
						OnHand      int    `json:"OnHand"`
 | 
				
			||||||
 | 
						Reserved    int    `json:"Reserved"`
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -0,0 +1,85 @@
 | 
				
			||||||
 | 
					package kiotviet
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import "time"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					type AuthRes struct {
 | 
				
			||||||
 | 
						AccessToken string `json:"access_token"`
 | 
				
			||||||
 | 
						ExpiresIn   int    `json:"expires_in"`
 | 
				
			||||||
 | 
						TokenType   string `json:"token_type"`
 | 
				
			||||||
 | 
						Scope       string `json:"scope"`
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					type ListProductOnHandsRes struct {
 | 
				
			||||||
 | 
						Total     int             `json:"total"`
 | 
				
			||||||
 | 
						PageSize  int             `json:"pageSize"`
 | 
				
			||||||
 | 
						Data      []ProductOnHand `json:"data"`
 | 
				
			||||||
 | 
						Timestamp time.Time       `json:"timestamp"`
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					type ProductOnHand struct {
 | 
				
			||||||
 | 
						ID           int                      `json:"id"`
 | 
				
			||||||
 | 
						Code         string                   `json:"code"`
 | 
				
			||||||
 | 
						CreatedDate  string                   `json:"createdDate"`
 | 
				
			||||||
 | 
						ModifiedDate string                   `json:"modifiedDate"`
 | 
				
			||||||
 | 
						Inventories  []ProductOnHandInventory `json:"inventories"`
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					type ProductOnHandInventory struct {
 | 
				
			||||||
 | 
						BranchID int `json:"branchId"`
 | 
				
			||||||
 | 
						OnHand   int `json:"onHand"`
 | 
				
			||||||
 | 
						Reserved int `json:"reserved"`
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					type ListBranchesRes struct {
 | 
				
			||||||
 | 
						Total     int       `json:"total"`
 | 
				
			||||||
 | 
						PageSize  int       `json:"pageSize"`
 | 
				
			||||||
 | 
						Data      []Branch  `json:"data"`
 | 
				
			||||||
 | 
						Timestamp time.Time `json:"timestamp"`
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					type Branch struct {
 | 
				
			||||||
 | 
						ID            int    `json:"id"`
 | 
				
			||||||
 | 
						BranchName    string `json:"branchName"`
 | 
				
			||||||
 | 
						Address       string `json:"address"`
 | 
				
			||||||
 | 
						LocationName  string `json:"locationName"`
 | 
				
			||||||
 | 
						ContactNumber string `json:"contactNumber"`
 | 
				
			||||||
 | 
						RetailerID    int    `json:"retailerId"`
 | 
				
			||||||
 | 
						CreatedDate   string `json:"createdDate"`
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					type RegisterWebhookRes struct {
 | 
				
			||||||
 | 
						ID         int    `json:"id"`
 | 
				
			||||||
 | 
						Type       string `json:"type"`
 | 
				
			||||||
 | 
						Url        string `json:"url"`
 | 
				
			||||||
 | 
						IsActive   bool   `json:"isActive"`
 | 
				
			||||||
 | 
						RetailerID int    `json:"retailerId"`
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					type UnregisterWebhookRes struct {
 | 
				
			||||||
 | 
						Success bool
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					type ResponseError struct {
 | 
				
			||||||
 | 
						ResponseStatus RError `json:"responseStatus"`
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					type RError struct {
 | 
				
			||||||
 | 
						ErrorCode string `json:"errorCode"`
 | 
				
			||||||
 | 
						Message   string `json:"message"`
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					type Webhook struct {
 | 
				
			||||||
 | 
						Id           int       `json:"id"`
 | 
				
			||||||
 | 
						Type         string    `json:"type"`
 | 
				
			||||||
 | 
						Url          string    `json:"url"`
 | 
				
			||||||
 | 
						IsActive     bool      `json:"isActive"`
 | 
				
			||||||
 | 
						RetailerId   int       `json:"retailerId"`
 | 
				
			||||||
 | 
						ModifiedDate time.Time `json:"modifiedDate"`
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					type ListWebhookRes struct {
 | 
				
			||||||
 | 
						Total     int       `json:"total"`
 | 
				
			||||||
 | 
						PageSize  int       `json:"pageSize"`
 | 
				
			||||||
 | 
						Data      []Webhook `json:"data"`
 | 
				
			||||||
 | 
						Timestamp time.Time `json:"timestamp"`
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
		Loading…
	
		Reference in New Issue