From 1034d2e077a5e8384f2886d7408218abf88c3b71 Mon Sep 17 00:00:00 2001 From: Sinh Date: Fri, 14 Jun 2024 17:31:02 +0700 Subject: [PATCH 01/10] feat: refactor ViettelFFM partner API integration - Add the `const.go` file defining `ENV` type and constants `EnvStaging` and `EnvProd` - Update `go.mod` to use `go 1.20` instead of `go 1.17` - Introduce `model.go` file for ViettelFFM partner API structs - Implement client methods for creating outbound requests and updating logistics information - Implement an authentication method for the client with `AuthRes` struct - Define constants for base URLs and authentication paths in ViettelFFM client - Implement helper methods for getting base URL and making HTTP requests via NATS - Update `util/httputil/const.go` to include `HeaderKeyAuthorization` constant Signed-off-by: Sinh --- const.go | 9 ++ go.mod | 4 +- go.sum | 4 - partnerapi/viettelffm/model.go | 65 +++++++++ partnerapi/viettelffm/viettel_ffm.go | 201 +++++++++++++++++++++++++++ util/httputil/const.go | 3 +- 6 files changed, 279 insertions(+), 7 deletions(-) create mode 100644 const.go create mode 100644 partnerapi/viettelffm/model.go create mode 100644 partnerapi/viettelffm/viettel_ffm.go diff --git a/const.go b/const.go new file mode 100644 index 0000000..bd57f3a --- /dev/null +++ b/const.go @@ -0,0 +1,9 @@ +package tpl + +// ENV ... +type ENV string + +const ( + EnvStaging ENV = "STAGING" + EnvProd ENV = "PROD" +) diff --git a/go.mod b/go.mod index c96ff3a..5bcc490 100644 --- a/go.mod +++ b/go.mod @@ -1,10 +1,11 @@ module git.selly.red/Selly-Modules/3pl -go 1.17 +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 + 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 ) @@ -14,7 +15,6 @@ require ( github.com/elastic/go-licenser v0.4.1 // indirect github.com/elastic/go-sysinfo v1.1.1 // indirect github.com/elastic/go-windows v1.0.1 // indirect - github.com/go-resty/resty/v2 v2.7.0 // indirect github.com/golang/snappy v0.0.3 // indirect github.com/jcchavezs/porto v0.4.0 // indirect github.com/joeshaw/multierror v0.0.0-20140124173710-69b34d4ec901 // indirect diff --git a/go.sum b/go.sum index 4599338..359510a 100644 --- a/go.sum +++ b/go.sum @@ -1,9 +1,5 @@ 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.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.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= diff --git a/partnerapi/viettelffm/model.go b/partnerapi/viettelffm/model.go new file mode 100644 index 0000000..b247f52 --- /dev/null +++ b/partnerapi/viettelffm/model.go @@ -0,0 +1,65 @@ +package viettelffm + +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"` +} + +type UpdateLogisticInfoPayload struct { + PrintLabelLink string `json:"print_label_link"` + TrackingCode string `json:"tracking_code"` +} + +type ORPayload struct { + OrProductLines []ORProductLine `json:"or_product_lines"` + AmountPaid float64 `json:"amount_paid"` + CodAmount float64 `json:"cod_amount"` + CodType string `json:"cod_type"` + Note string `json:"note"` + OrCode string `json:"or_code"` + OrType string `json:"or_type"` + ShippingType string `json:"shipping_type"` + CustomerName string `json:"customer_name"` + CustomerEmail string `json:"customer_email"` + PackType string `json:"pack_type"` + PriorityType string `json:"priority_type"` + Warehouse ORWarehouse `json:"warehouse"` +} + +type ORProductLine struct { + Discount float64 `json:"discount"` + Price float64 `json:"price"` + Product Product `json:"product"` + Quantity int `json:"quantity"` + SpecifiedProductLine SpecifiedProductLine `json:"specified_product_line"` + Unit string `json:"unit"` +} + +type SpecifiedProductLine struct { + ProductConditionType ProdCondType `json:"product_condition_type"` +} + +type Product struct { + PartnerSku string `json:"partner_sku"` + ProductId int `json:"product_id"` +} + +type ProdCondType struct { + Name string `json:"name"` +} + +type ORWarehouse struct { + WarehouseId int `json:"warehouse_id"` +} + +type ORResult struct { + OrCode string `json:"or_code"` + OrId int `json:"or_id"` + Status string `json:"status"` +} diff --git a/partnerapi/viettelffm/viettel_ffm.go b/partnerapi/viettelffm/viettel_ffm.go new file mode 100644 index 0000000..daefd13 --- /dev/null +++ b/partnerapi/viettelffm/viettel_ffm.go @@ -0,0 +1,201 @@ +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/bill" + pathCreateOR = "/wms-core/api/v1/obms/outbound-request/outbound-request-partner" + + 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) UpdateOutboundRequestLogisticInfo(p UpdateLogisticInfoPayload) error { + apiURL := c.getBaseURL() + pathUpdateORLogisticInfo + 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.UpdateOutboundRequestLogisticInfo - 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 +} diff --git a/util/httputil/const.go b/util/httputil/const.go index c708838..90eeb6c 100644 --- a/util/httputil/const.go +++ b/util/httputil/const.go @@ -1,7 +1,8 @@ package httputil const ( - HeaderKeyContentType = "Content-Type" + HeaderKeyContentType = "Content-Type" + HeaderKeyAuthorization = "Authorization" HeaderValueApplicationJSON = "application/json" HeaderValueApplicationURLEncoded = "application/x-www-form-urlencoded" From 178652fcefec5cd18108acbb3f2380706807b78e Mon Sep 17 00:00:00 2001 From: Sinh Date: Tue, 18 Jun 2024 16:02:52 +0700 Subject: [PATCH 02/10] feat: refactor logistics functions in Viettel FFM module - Add a new type `CancelORPayload` to the file `model.go` - Add a new constant `pathCancelOR` in the `viettel_ffm.go` file - Change the method from `POST` to `PUT` in the `UpdateORLogisticInfo` function in `viettel_ffm.go` - Add a new function `CancelOR` in the `viettel_ffm.go` file Signed-off-by: Sinh --- partnerapi/viettelffm/model.go | 4 ++++ partnerapi/viettelffm/viettel_ffm.go | 35 ++++++++++++++++++++++++++-- 2 files changed, 37 insertions(+), 2 deletions(-) diff --git a/partnerapi/viettelffm/model.go b/partnerapi/viettelffm/model.go index b247f52..3b9496a 100644 --- a/partnerapi/viettelffm/model.go +++ b/partnerapi/viettelffm/model.go @@ -16,6 +16,10 @@ type UpdateLogisticInfoPayload struct { TrackingCode string `json:"tracking_code"` } +type CancelORPayload struct { + OrID int `json:"or_id"` +} + type ORPayload struct { OrProductLines []ORProductLine `json:"or_product_lines"` AmountPaid float64 `json:"amount_paid"` diff --git a/partnerapi/viettelffm/viettel_ffm.go b/partnerapi/viettelffm/viettel_ffm.go index daefd13..e83ce32 100644 --- a/partnerapi/viettelffm/viettel_ffm.go +++ b/partnerapi/viettelffm/viettel_ffm.go @@ -27,6 +27,7 @@ const ( pathAuth = "/realms/wms/protocol/openid-connect/token" pathUpdateORLogisticInfo = "/wms-core/api/v1/obms/outbound-request/outbound-request-partner/%s/bill" pathCreateOR = "/wms-core/api/v1/obms/outbound-request/outbound-request-partner" + pathCancelOR = "/wms-core/api/v1/obms/outbound-request/cancel" logTarget = "viettel-ffm" ) @@ -96,12 +97,42 @@ func (c *Client) CreateOR(p ORPayload) (*ORResult, error) { return &data, nil } -func (c *Client) UpdateOutboundRequestLogisticInfo(p UpdateLogisticInfoPayload) error { +func (c *Client) UpdateORLogisticInfo(p UpdateLogisticInfoPayload) error { apiURL := c.getBaseURL() + pathUpdateORLogisticInfo 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{ @@ -121,7 +152,7 @@ func (c *Client) UpdateOutboundRequestLogisticInfo(p UpdateLogisticInfoPayload) } res := r.Response if res.StatusCode >= http.StatusBadRequest { - return fmt.Errorf("viettelffm.Client.UpdateOutboundRequestLogisticInfo - requestHttpViaNats %s", res.Body) + return fmt.Errorf("viettelffm.Client.CancelOR - requestHttpViaNats %s", res.Body) } return nil } From baf7be082046a6cbd4340e4d1ccd53e200999aed Mon Sep 17 00:00:00 2001 From: Sinh Date: Thu, 20 Jun 2024 10:09:35 +0700 Subject: [PATCH 03/10] update model --- partnerapi/viettelffm/model.go | 1 - 1 file changed, 1 deletion(-) diff --git a/partnerapi/viettelffm/model.go b/partnerapi/viettelffm/model.go index 3b9496a..a33bbdd 100644 --- a/partnerapi/viettelffm/model.go +++ b/partnerapi/viettelffm/model.go @@ -51,7 +51,6 @@ type SpecifiedProductLine struct { type Product struct { PartnerSku string `json:"partner_sku"` - ProductId int `json:"product_id"` } type ProdCondType struct { From ee60175a4d22cbb154e8e908089dad3aeb590ed2 Mon Sep 17 00:00:00 2001 From: Sinh Date: Fri, 21 Jun 2024 14:32:52 +0700 Subject: [PATCH 04/10] feat: integrate VTP FFM --- partnerapi/viettelffm/model.go | 1 + 1 file changed, 1 insertion(+) diff --git a/partnerapi/viettelffm/model.go b/partnerapi/viettelffm/model.go index a33bbdd..d464d4e 100644 --- a/partnerapi/viettelffm/model.go +++ b/partnerapi/viettelffm/model.go @@ -51,6 +51,7 @@ type SpecifiedProductLine struct { type Product struct { PartnerSku string `json:"partner_sku"` + SKU string `json:"sku"` } type ProdCondType struct { From d70f298734fdc69251969bfc9d3cc6429a399eec Mon Sep 17 00:00:00 2001 From: Sinh Date: Fri, 21 Jun 2024 14:36:53 +0700 Subject: [PATCH 05/10] change api path --- partnerapi/viettelffm/viettel_ffm.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/partnerapi/viettelffm/viettel_ffm.go b/partnerapi/viettelffm/viettel_ffm.go index e83ce32..4b6b65d 100644 --- a/partnerapi/viettelffm/viettel_ffm.go +++ b/partnerapi/viettelffm/viettel_ffm.go @@ -26,7 +26,7 @@ const ( pathAuth = "/realms/wms/protocol/openid-connect/token" pathUpdateORLogisticInfo = "/wms-core/api/v1/obms/outbound-request/outbound-request-partner/%s/bill" - pathCreateOR = "/wms-core/api/v1/obms/outbound-request/outbound-request-partner" + pathCreateOR = "/wms-core/api/v1/obms/outbound-request/outbound-request-partner/hab" pathCancelOR = "/wms-core/api/v1/obms/outbound-request/cancel" logTarget = "viettel-ffm" From fa6198d7e3a70d46a3b62919b88f2b027ee29b44 Mon Sep 17 00:00:00 2001 From: Sinh Date: Fri, 21 Jun 2024 15:23:51 +0700 Subject: [PATCH 06/10] update VTP FFM model --- partnerapi/viettelffm/model.go | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/partnerapi/viettelffm/model.go b/partnerapi/viettelffm/model.go index d464d4e..8fc904c 100644 --- a/partnerapi/viettelffm/model.go +++ b/partnerapi/viettelffm/model.go @@ -33,7 +33,7 @@ type ORPayload struct { CustomerEmail string `json:"customer_email"` PackType string `json:"pack_type"` PriorityType string `json:"priority_type"` - Warehouse ORWarehouse `json:"warehouse"` + WarehouseCode string `json:"warehouse_code"` } type ORProductLine struct { @@ -58,10 +58,6 @@ type ProdCondType struct { Name string `json:"name"` } -type ORWarehouse struct { - WarehouseId int `json:"warehouse_id"` -} - type ORResult struct { OrCode string `json:"or_code"` OrId int `json:"or_id"` From 00ec7e1f2fff853406632fe56f8f78392422addf Mon Sep 17 00:00:00 2001 From: Sinh Date: Fri, 21 Jun 2024 15:37:59 +0700 Subject: [PATCH 07/10] update VTP FFM model --- partnerapi/viettelffm/model.go | 1 + partnerapi/viettelffm/viettel_ffm.go | 4 ++-- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/partnerapi/viettelffm/model.go b/partnerapi/viettelffm/model.go index 8fc904c..d6aabab 100644 --- a/partnerapi/viettelffm/model.go +++ b/partnerapi/viettelffm/model.go @@ -14,6 +14,7 @@ type AuthRes struct { type UpdateLogisticInfoPayload struct { PrintLabelLink string `json:"print_label_link"` TrackingCode string `json:"tracking_code"` + OrID int `json:"or_id,omitempty"` } type CancelORPayload struct { diff --git a/partnerapi/viettelffm/viettel_ffm.go b/partnerapi/viettelffm/viettel_ffm.go index 4b6b65d..bd65820 100644 --- a/partnerapi/viettelffm/viettel_ffm.go +++ b/partnerapi/viettelffm/viettel_ffm.go @@ -25,7 +25,7 @@ const ( baseURLAuthProd = "" pathAuth = "/realms/wms/protocol/openid-connect/token" - pathUpdateORLogisticInfo = "/wms-core/api/v1/obms/outbound-request/outbound-request-partner/%s/bill" + pathUpdateORLogisticInfo = "/wms-core/api/v1/obms/outbound-request/outbound-request-partner/%d/bill" pathCreateOR = "/wms-core/api/v1/obms/outbound-request/outbound-request-partner/hab" pathCancelOR = "/wms-core/api/v1/obms/outbound-request/cancel" @@ -98,7 +98,7 @@ func (c *Client) CreateOR(p ORPayload) (*ORResult, error) { } func (c *Client) UpdateORLogisticInfo(p UpdateLogisticInfoPayload) error { - apiURL := c.getBaseURL() + pathUpdateORLogisticInfo + apiURL := c.getBaseURL() + fmt.Sprintf(pathUpdateORLogisticInfo, p.OrID) token, err := c.getToken() if err != nil { return err From e5619ae68cb92472296feea891d55370297ef03e Mon Sep 17 00:00:00 2001 From: Sinh Date: Tue, 25 Jun 2024 14:13:40 +0700 Subject: [PATCH 08/10] update VTP FFM api path --- partnerapi/viettelffm/viettel_ffm.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/partnerapi/viettelffm/viettel_ffm.go b/partnerapi/viettelffm/viettel_ffm.go index bd65820..e424e78 100644 --- a/partnerapi/viettelffm/viettel_ffm.go +++ b/partnerapi/viettelffm/viettel_ffm.go @@ -25,7 +25,7 @@ const ( baseURLAuthProd = "" pathAuth = "/realms/wms/protocol/openid-connect/token" - pathUpdateORLogisticInfo = "/wms-core/api/v1/obms/outbound-request/outbound-request-partner/%d/bill" + pathUpdateORLogisticInfo = "/wms-core/api/v1/obms/outbound-request/outbound-request-partner/%d" pathCreateOR = "/wms-core/api/v1/obms/outbound-request/outbound-request-partner/hab" pathCancelOR = "/wms-core/api/v1/obms/outbound-request/cancel" From 624cb9623936f8c936dae7f03e26b9af4a184fe4 Mon Sep 17 00:00:00 2001 From: Sinh Date: Tue, 25 Jun 2024 14:53:10 +0700 Subject: [PATCH 09/10] update VTP FFM model --- partnerapi/viettelffm/model.go | 2 +- partnerapi/viettelffm/viettel_ffm.go | 5 +++-- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/partnerapi/viettelffm/model.go b/partnerapi/viettelffm/model.go index d6aabab..a3bb4ca 100644 --- a/partnerapi/viettelffm/model.go +++ b/partnerapi/viettelffm/model.go @@ -14,7 +14,7 @@ type AuthRes struct { type UpdateLogisticInfoPayload struct { PrintLabelLink string `json:"print_label_link"` TrackingCode string `json:"tracking_code"` - OrID int `json:"or_id,omitempty"` + OrCode string `json:"or_code,omitempty"` } type CancelORPayload struct { diff --git a/partnerapi/viettelffm/viettel_ffm.go b/partnerapi/viettelffm/viettel_ffm.go index e424e78..afdafa6 100644 --- a/partnerapi/viettelffm/viettel_ffm.go +++ b/partnerapi/viettelffm/viettel_ffm.go @@ -25,7 +25,7 @@ const ( baseURLAuthProd = "" pathAuth = "/realms/wms/protocol/openid-connect/token" - pathUpdateORLogisticInfo = "/wms-core/api/v1/obms/outbound-request/outbound-request-partner/%d" + 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" @@ -98,7 +98,8 @@ func (c *Client) CreateOR(p ORPayload) (*ORResult, error) { } func (c *Client) UpdateORLogisticInfo(p UpdateLogisticInfoPayload) error { - apiURL := c.getBaseURL() + fmt.Sprintf(pathUpdateORLogisticInfo, p.OrID) + apiURL := c.getBaseURL() + fmt.Sprintf(pathUpdateORLogisticInfo, p.OrCode) + p.OrCode = "" token, err := c.getToken() if err != nil { return err From b7195b364ffd5fa4e4cd9ca57d69997d9f0924bc Mon Sep 17 00:00:00 2001 From: Sinh Date: Wed, 26 Jun 2024 16:53:44 +0700 Subject: [PATCH 10/10] feat: refactor webhook handling for ViettelFFM partner API - Add structs `Webhook`, `WebhookData` to handle webhook data in ViettelFFM partner API Signed-off-by: Sinh --- partnerapi/viettelffm/model.go | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/partnerapi/viettelffm/model.go b/partnerapi/viettelffm/model.go index a3bb4ca..d772802 100644 --- a/partnerapi/viettelffm/model.go +++ b/partnerapi/viettelffm/model.go @@ -64,3 +64,16 @@ type ORResult struct { OrId int `json:"or_id"` Status string `json:"status"` } + +type Webhook struct { + Data WebhookData `json:"data"` +} + +type WebhookData struct { + OrId int `json:"or_id"` + OrCode string `json:"or_code"` + PartnerOrCode string `json:"partner_or_code"` + Status string `json:"status"` + TotalPrice float64 `json:"total_price"` + ShippingFee int `json:"shipping_fee"` +}