Compare commits
92 Commits
Author | SHA1 | Date |
---|---|---|
|
af64aeab31 | |
|
5fc7fa9843 | |
|
400aa5fa58 | |
|
dd1d93a020 | |
|
d1fc6632eb | |
|
a37bcd610d | |
|
08029dfd8e | |
|
3cb41cb650 | |
|
5c20536492 | |
|
4b621b9b41 | |
|
91e69993af | |
|
b7195b364f | |
|
624cb96239 | |
|
e5619ae68c | |
|
00ec7e1f2f | |
|
fa6198d7e3 | |
|
d70f298734 | |
|
ee60175a4d | |
|
baf7be0820 | |
|
178652fcef | |
|
1034d2e077 | |
|
756740a2d7 | |
|
9fb4f0c6f3 | |
|
ac8aa89d70 | |
|
d4915875e9 | |
|
a33809e092 | |
|
d549cc5103 | |
|
1c6be73d04 | |
|
a9b7f39b09 | |
|
71e2f0b842 | |
|
aa202e8fcb | |
|
51afbc9c0e | |
|
83201d37af | |
|
007796e668 | |
|
fb417551f4 | |
|
efd91a81dd | |
|
8a0e7c2cb7 | |
|
89d2f1c8fb | |
|
6bf4914ade | |
|
844b01604a | |
|
03b68fd7e4 | |
|
cd317aa9a2 | |
|
fc532e5b0c | |
|
1f4c6890eb | |
|
5257cd21bc | |
|
a929e52324 | |
|
9e15bfc101 | |
|
b15d883542 | |
|
94d6e0c606 | |
|
7d1d63039d | |
|
5b1b55ee78 | |
|
ba6851fe19 | |
|
4b8e6c4178 | |
|
13eec58c2b | |
|
04c8804c9d | |
|
01a693f36a | |
|
1e16cae1e3 | |
|
83b1969941 | |
|
2d7b0b5662 | |
|
93651891ab | |
|
ff3264f0d3 | |
|
dd33c7f9f9 | |
|
fce18340f1 | |
|
e9f66f611e | |
|
ce8344fdc9 | |
|
ba87bb90be | |
|
9124e39283 | |
|
9807db0739 | |
|
00d2d0f895 | |
|
4380f5339b | |
|
ad143b3736 | |
|
d21ec08233 | |
|
04cc91bb5f | |
|
d3a7fe684b | |
|
590bbe2076 | |
|
c8868f34b5 | |
|
ee4024dbe4 | |
|
7343221d5e | |
|
ed37e02fdf | |
|
26390c4633 | |
|
5f58965975 | |
|
b627377b17 | |
|
ab895e78cb | |
|
dcb2bb5d73 | |
|
68fe77da6c | |
|
f9046088ea | |
|
bc3db15466 | |
|
e354f157a0 | |
|
fb104bb0bd | |
|
faf05aea63 | |
|
a0f382fd9c | |
|
e7f2ec779c |
|
@ -0,0 +1,9 @@
|
||||||
|
package tpl
|
||||||
|
|
||||||
|
// ENV ...
|
||||||
|
type ENV string
|
||||||
|
|
||||||
|
const (
|
||||||
|
EnvStaging ENV = "STAGING"
|
||||||
|
EnvProd ENV = "PROD"
|
||||||
|
)
|
|
@ -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))
|
||||||
|
}
|
46
go.mod
46
go.mod
|
@ -1,37 +1,43 @@
|
||||||
module github.com/Selly-Modules/3pl
|
module git.selly.red/Selly-Modules/3pl
|
||||||
|
|
||||||
go 1.17
|
go 1.20
|
||||||
|
|
||||||
require (
|
require (
|
||||||
github.com/Selly-Modules/logger v0.0.1
|
git.selly.red/Selly-Modules/logger v0.0.2-0.20221010053254-567df039afdb
|
||||||
github.com/Selly-Modules/natsio v1.0.1
|
git.selly.red/Selly-Modules/natsio v1.0.3-0.20231020090841-5edec97ee393
|
||||||
github.com/nats-io/nats.go v1.13.0
|
github.com/go-resty/resty/v2 v2.7.0
|
||||||
github.com/thoas/go-funk v0.9.1
|
github.com/nats-io/nats.go v1.17.0
|
||||||
|
github.com/thoas/go-funk v0.9.2
|
||||||
)
|
)
|
||||||
|
|
||||||
require (
|
require (
|
||||||
github.com/armon/go-radix v1.0.0 // indirect
|
github.com/armon/go-radix v1.0.0 // indirect
|
||||||
github.com/elastic/go-licenser v0.3.1 // indirect
|
github.com/elastic/go-licenser v0.4.1 // indirect
|
||||||
github.com/elastic/go-sysinfo v1.1.1 // indirect
|
github.com/elastic/go-sysinfo v1.1.1 // indirect
|
||||||
github.com/elastic/go-windows v1.0.0 // indirect
|
github.com/elastic/go-windows v1.0.1 // indirect
|
||||||
github.com/jcchavezs/porto v0.1.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
|
github.com/joeshaw/multierror v0.0.0-20140124173710-69b34d4ec901 // indirect
|
||||||
|
github.com/klauspost/compress v1.13.6 // indirect
|
||||||
github.com/nats-io/nkeys v0.3.0 // indirect
|
github.com/nats-io/nkeys v0.3.0 // indirect
|
||||||
github.com/nats-io/nuid v1.0.1 // indirect
|
github.com/nats-io/nuid v1.0.1 // indirect
|
||||||
github.com/pkg/errors v0.8.1 // indirect
|
github.com/pkg/errors v0.9.1 // indirect
|
||||||
github.com/prometheus/procfs v0.0.0-20190425082905-87a4384529e0 // indirect
|
github.com/prometheus/procfs v0.0.0-20190425082905-87a4384529e0 // indirect
|
||||||
github.com/santhosh-tekuri/jsonschema v1.2.4 // indirect
|
github.com/santhosh-tekuri/jsonschema v1.2.4 // indirect
|
||||||
go.elastic.co/apm v1.13.1 // indirect
|
github.com/youmark/pkcs8 v0.0.0-20181117223130-1be2e3e5546d // indirect
|
||||||
go.elastic.co/apm/module/apmzap v1.13.1 // indirect
|
go.elastic.co/apm v1.15.0 // indirect
|
||||||
|
go.elastic.co/apm/module/apmzap v1.15.0 // indirect
|
||||||
go.elastic.co/fastjson v1.1.0 // indirect
|
go.elastic.co/fastjson v1.1.0 // indirect
|
||||||
|
go.mongodb.org/mongo-driver v1.10.1 // indirect
|
||||||
go.uber.org/atomic v1.7.0 // indirect
|
go.uber.org/atomic v1.7.0 // indirect
|
||||||
go.uber.org/multierr v1.6.0 // indirect
|
go.uber.org/multierr v1.8.0 // indirect
|
||||||
go.uber.org/zap v1.18.1 // indirect
|
go.uber.org/zap v1.18.1 // indirect
|
||||||
golang.org/x/crypto v0.0.0-20210616213533-5ff15b29337e // indirect
|
golang.org/x/crypto v0.0.0-20220622213112-05595931fe9d // indirect
|
||||||
golang.org/x/lint v0.0.0-20201208152925-83fdc39ff7b5 // indirect
|
golang.org/x/lint v0.0.0-20210508222113-6edffad5e616 // indirect
|
||||||
golang.org/x/mod v0.3.0 // indirect
|
golang.org/x/mod v0.5.1 // indirect
|
||||||
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1 // indirect
|
golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2 // indirect
|
||||||
golang.org/x/tools v0.0.0-20200509030707-2212a7e161a5 // indirect
|
golang.org/x/sys v0.0.0-20211102192858-4dd72447c267 // indirect
|
||||||
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 // indirect
|
golang.org/x/tools v0.1.7 // indirect
|
||||||
howett.net/plist v0.0.0-20181124034731-591f970eefbb // indirect
|
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 // indirect
|
||||||
|
howett.net/plist v1.0.0 // indirect
|
||||||
)
|
)
|
||||||
|
|
97
go.sum
97
go.sum
|
@ -1,7 +1,7 @@
|
||||||
github.com/Selly-Modules/logger v0.0.1 h1:dwLLtW53FfVBlklhdtFRB63eP0ofIh0IUQ/Gjgi0r5k=
|
git.selly.red/Selly-Modules/logger v0.0.2-0.20221010053254-567df039afdb h1:AmcYd88IcdSkH+NEvKyJLT7psidSkjJQT/nAg/KuzFk=
|
||||||
github.com/Selly-Modules/logger v0.0.1/go.mod h1:RWhSQ3F01an8KD00VjzRBZOMcE5eV2Cy0/l4ZkeieyU=
|
git.selly.red/Selly-Modules/logger v0.0.2-0.20221010053254-567df039afdb/go.mod h1:Q1//Z6HRmfa7VyjH2J6YyT0YV2jT8+K6SIgwnYuS4II=
|
||||||
github.com/Selly-Modules/natsio v1.0.1 h1:0HoP00hP0Fz5h03p23Al3aARZwg+JSKpOrBo5Oh7pwY=
|
git.selly.red/Selly-Modules/natsio v1.0.3-0.20231020090841-5edec97ee393 h1:43kE03FW3NONfE6hXlghafS1d233dfc7grlFqd+15SA=
|
||||||
github.com/Selly-Modules/natsio v1.0.1/go.mod h1:NG55g9ip18nvN5tfP6PcSEKec10/lOeIOZC8HqBVNlQ=
|
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=
|
||||||
|
@ -9,12 +9,16 @@ github.com/benbjohnson/clock v1.1.0/go.mod h1:J11/hYXuz8f4ySSvYwY0FKfm+ezbsZBKZx
|
||||||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||||
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
||||||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||||
github.com/elastic/go-licenser v0.3.1 h1:RmRukU/JUmts+rpexAw0Fvt2ly7VVu6mw8z4HrEzObU=
|
|
||||||
github.com/elastic/go-licenser v0.3.1/go.mod h1:D8eNQk70FOCVBl3smCGQt/lv7meBeQno2eI1S5apiHQ=
|
github.com/elastic/go-licenser v0.3.1/go.mod h1:D8eNQk70FOCVBl3smCGQt/lv7meBeQno2eI1S5apiHQ=
|
||||||
|
github.com/elastic/go-licenser v0.4.1 h1:1xDURsc8pL5zYT9R29425J3vkHdt4RT5TNEMeRN48x4=
|
||||||
|
github.com/elastic/go-licenser v0.4.1/go.mod h1:V56wHMpmdURfibNBggaSBfqgPxyT1Tldns1i87iTEvU=
|
||||||
github.com/elastic/go-sysinfo v1.1.1 h1:ZVlaLDyhVkDfjwPGU55CQRCRolNpc7P0BbyhhQZQmMI=
|
github.com/elastic/go-sysinfo v1.1.1 h1:ZVlaLDyhVkDfjwPGU55CQRCRolNpc7P0BbyhhQZQmMI=
|
||||||
github.com/elastic/go-sysinfo v1.1.1/go.mod h1:i1ZYdU10oLNfRzq4vq62BEwD2fH8KaWh6eh0ikPT9F0=
|
github.com/elastic/go-sysinfo v1.1.1/go.mod h1:i1ZYdU10oLNfRzq4vq62BEwD2fH8KaWh6eh0ikPT9F0=
|
||||||
github.com/elastic/go-windows v1.0.0 h1:qLURgZFkkrYyTTkvYpsZIgf83AUsdIHfvlJaqaZ7aSY=
|
|
||||||
github.com/elastic/go-windows v1.0.0/go.mod h1:TsU0Nrp7/y3+VwE82FoZF8gC/XFg/Elz6CcloAxnPgU=
|
github.com/elastic/go-windows v1.0.0/go.mod h1:TsU0Nrp7/y3+VwE82FoZF8gC/XFg/Elz6CcloAxnPgU=
|
||||||
|
github.com/elastic/go-windows v1.0.1 h1:AlYZOldA+UJ0/2nBuqWdo90GFCgG9xuyw9SYzGUtJm0=
|
||||||
|
github.com/elastic/go-windows v1.0.1/go.mod h1:FoVvqWSun28vaDQPbj2Elfc0JahhPB7WQEGa3c814Ss=
|
||||||
|
github.com/go-resty/resty/v2 v2.7.0 h1:me+K9p3uhSmXtrBZ4k9jcEAfJmuC8IivWHwaLZwPrFY=
|
||||||
|
github.com/go-resty/resty/v2 v2.7.0/go.mod h1:9PWDzw47qPphMRFfhsyk0NnSgvluHcljSMVIq3w7q0I=
|
||||||
github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8=
|
github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8=
|
||||||
github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA=
|
github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA=
|
||||||
github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs=
|
github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs=
|
||||||
|
@ -24,25 +28,31 @@ github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw
|
||||||
github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk=
|
github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk=
|
||||||
github.com/golang/protobuf v1.5.2 h1:ROPKBNFfQgOUMifHyP+KYbvpjbdoFNs+aK7DXlji0Tw=
|
github.com/golang/protobuf v1.5.2 h1:ROPKBNFfQgOUMifHyP+KYbvpjbdoFNs+aK7DXlji0Tw=
|
||||||
github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY=
|
github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY=
|
||||||
|
github.com/golang/snappy v0.0.1/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
|
||||||
|
github.com/golang/snappy v0.0.3 h1:fHPg5GQYlCeLIPB9BZqMVR5nR9A+IM5zcgeTdjMYmLA=
|
||||||
github.com/golang/snappy v0.0.3/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
|
github.com/golang/snappy v0.0.3/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
|
||||||
github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
|
github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
|
||||||
github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
|
github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
|
||||||
github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||||
|
github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||||
github.com/google/go-cmp v0.5.5 h1:Khx7svrCpmxxtHBq5j2mp/xVjsi8hQMfNLvJFAlrGgU=
|
github.com/google/go-cmp v0.5.5 h1:Khx7svrCpmxxtHBq5j2mp/xVjsi8hQMfNLvJFAlrGgU=
|
||||||
github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||||
github.com/jcchavezs/porto v0.1.0 h1:Xmxxn25zQMmgE7/yHYmh19KcItG81hIwfbEEFnd6w/Q=
|
|
||||||
github.com/jcchavezs/porto v0.1.0/go.mod h1:fESH0gzDHiutHRdX2hv27ojnOVFco37hg1W6E9EZF4A=
|
github.com/jcchavezs/porto v0.1.0/go.mod h1:fESH0gzDHiutHRdX2hv27ojnOVFco37hg1W6E9EZF4A=
|
||||||
|
github.com/jcchavezs/porto v0.4.0 h1:Zj7RligrxmDdKGo6fBO2xYAHxEgrVBfs1YAja20WbV4=
|
||||||
|
github.com/jcchavezs/porto v0.4.0/go.mod h1:fESH0gzDHiutHRdX2hv27ojnOVFco37hg1W6E9EZF4A=
|
||||||
github.com/jessevdk/go-flags v1.4.0/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI=
|
github.com/jessevdk/go-flags v1.4.0/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI=
|
||||||
github.com/joeshaw/multierror v0.0.0-20140124173710-69b34d4ec901 h1:rp+c0RAYOWj8l6qbCUTSiRLG/iKnW3K3/QfPPuSsBt4=
|
github.com/joeshaw/multierror v0.0.0-20140124173710-69b34d4ec901 h1:rp+c0RAYOWj8l6qbCUTSiRLG/iKnW3K3/QfPPuSsBt4=
|
||||||
github.com/joeshaw/multierror v0.0.0-20140124173710-69b34d4ec901/go.mod h1:Z86h9688Y0wesXCyonoVr47MasHilkuLMqGhRZ4Hpak=
|
github.com/joeshaw/multierror v0.0.0-20140124173710-69b34d4ec901/go.mod h1:Z86h9688Y0wesXCyonoVr47MasHilkuLMqGhRZ4Hpak=
|
||||||
github.com/klauspost/compress v1.13.4 h1:0zhec2I8zGnjWcKyLl6i3gPqKANCCn5e9xmviEEeX6s=
|
|
||||||
github.com/klauspost/compress v1.13.4/go.mod h1:8dP1Hq4DHOhN9w426knH3Rhby4rFm6D8eO+e+Dq5Gzg=
|
github.com/klauspost/compress v1.13.4/go.mod h1:8dP1Hq4DHOhN9w426knH3Rhby4rFm6D8eO+e+Dq5Gzg=
|
||||||
|
github.com/klauspost/compress v1.13.6 h1:P76CopJELS0TiO2mebmnzgWaajssP/EszplttgQxcgc=
|
||||||
|
github.com/klauspost/compress v1.13.6/go.mod h1:/3/Vjq9QcHkK5uEr5lBEmyoZ1iFhe47etQ6QUkpK6sk=
|
||||||
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
|
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
|
||||||
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
|
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
|
||||||
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
|
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
|
||||||
github.com/logrusorgru/aurora v2.0.3+incompatible/go.mod h1:7rIyQOR62GCctdiQpZ/zOJlFyk6y+94wXzv6RNZgaR4=
|
|
||||||
github.com/minio/highwayhash v1.0.1 h1:dZ6IIu8Z14VlC0VpfKofAhCy74wu/Qb5gcn52yWoz/0=
|
github.com/minio/highwayhash v1.0.1 h1:dZ6IIu8Z14VlC0VpfKofAhCy74wu/Qb5gcn52yWoz/0=
|
||||||
github.com/minio/highwayhash v1.0.1/go.mod h1:BQskDq+xkJ12lmlUUi7U0M5Swg3EWR+dLTk+kldvVxY=
|
github.com/minio/highwayhash v1.0.1/go.mod h1:BQskDq+xkJ12lmlUUi7U0M5Swg3EWR+dLTk+kldvVxY=
|
||||||
|
github.com/montanaflynn/stats v0.0.0-20171201202039-1bf9dbcd8cbe h1:iruDEfMl2E6fbMZ9s0scYfZQ84/6SPL6zC8ACM2oIL0=
|
||||||
|
github.com/montanaflynn/stats v0.0.0-20171201202039-1bf9dbcd8cbe/go.mod h1:wL8QJuTMNUDYhXwkmfOly8iTdp5TEcJFWZD2D7SIkUc=
|
||||||
github.com/nats-io/jwt v1.2.2 h1:w3GMTO969dFg+UOKTmmyuu7IGdusK+7Ytlt//OYH/uU=
|
github.com/nats-io/jwt v1.2.2 h1:w3GMTO969dFg+UOKTmmyuu7IGdusK+7Ytlt//OYH/uU=
|
||||||
github.com/nats-io/jwt v1.2.2/go.mod h1:/xX356yQA6LuXI9xWW7mZNpxgF2mBmGecH+Fj34sP5Q=
|
github.com/nats-io/jwt v1.2.2/go.mod h1:/xX356yQA6LuXI9xWW7mZNpxgF2mBmGecH+Fj34sP5Q=
|
||||||
github.com/nats-io/jwt/v2 v2.0.3 h1:i/O6cmIsjpcQyWDYNcq2JyZ3/VTF8SJ4JWluI5OhpvI=
|
github.com/nats-io/jwt/v2 v2.0.3 h1:i/O6cmIsjpcQyWDYNcq2JyZ3/VTF8SJ4JWluI5OhpvI=
|
||||||
|
@ -50,16 +60,18 @@ github.com/nats-io/jwt/v2 v2.0.3/go.mod h1:VRP+deawSXyhNjXmxPCHskrR6Mq50BqpEI5SE
|
||||||
github.com/nats-io/nats-server/v2 v2.6.1 h1:cJy+ia7/4EaJL+ZYDmIy2rD1mDWTfckhtPBU0GYo8xM=
|
github.com/nats-io/nats-server/v2 v2.6.1 h1:cJy+ia7/4EaJL+ZYDmIy2rD1mDWTfckhtPBU0GYo8xM=
|
||||||
github.com/nats-io/nats-server/v2 v2.6.1/go.mod h1:Az91TbZiV7K4a6k/4v6YYdOKEoxCXj+iqhHVf/MlrKo=
|
github.com/nats-io/nats-server/v2 v2.6.1/go.mod h1:Az91TbZiV7K4a6k/4v6YYdOKEoxCXj+iqhHVf/MlrKo=
|
||||||
github.com/nats-io/nats.go v1.12.3/go.mod h1:BPko4oXsySz4aSWeFgOHLZs3G4Jq4ZAyE6/zMCxRT6w=
|
github.com/nats-io/nats.go v1.12.3/go.mod h1:BPko4oXsySz4aSWeFgOHLZs3G4Jq4ZAyE6/zMCxRT6w=
|
||||||
github.com/nats-io/nats.go v1.13.0 h1:LvYqRB5epIzZWQp6lmeltOOZNLqCvm4b+qfvzZO03HE=
|
|
||||||
github.com/nats-io/nats.go v1.13.0/go.mod h1:BPko4oXsySz4aSWeFgOHLZs3G4Jq4ZAyE6/zMCxRT6w=
|
github.com/nats-io/nats.go v1.13.0/go.mod h1:BPko4oXsySz4aSWeFgOHLZs3G4Jq4ZAyE6/zMCxRT6w=
|
||||||
|
github.com/nats-io/nats.go v1.17.0 h1:1jp5BThsdGlN91hW0k3YEfJbfACjiOYtUiLXG0RL4IE=
|
||||||
|
github.com/nats-io/nats.go v1.17.0/go.mod h1:BPko4oXsySz4aSWeFgOHLZs3G4Jq4ZAyE6/zMCxRT6w=
|
||||||
github.com/nats-io/nkeys v0.2.0/go.mod h1:XdZpAbhgyyODYqjTawOnIOI7VlbKSarI9Gfy1tqEu/s=
|
github.com/nats-io/nkeys v0.2.0/go.mod h1:XdZpAbhgyyODYqjTawOnIOI7VlbKSarI9Gfy1tqEu/s=
|
||||||
github.com/nats-io/nkeys v0.3.0 h1:cgM5tL53EvYRU+2YLXIK0G2mJtK12Ft9oeooSZMA2G8=
|
github.com/nats-io/nkeys v0.3.0 h1:cgM5tL53EvYRU+2YLXIK0G2mJtK12Ft9oeooSZMA2G8=
|
||||||
github.com/nats-io/nkeys v0.3.0/go.mod h1:gvUNGjVcM2IPr5rCsRsC6Wb3Hr2CQAm08dsxtV6A5y4=
|
github.com/nats-io/nkeys v0.3.0/go.mod h1:gvUNGjVcM2IPr5rCsRsC6Wb3Hr2CQAm08dsxtV6A5y4=
|
||||||
github.com/nats-io/nuid v1.0.1 h1:5iA8DT8V7q8WK2EScv2padNa/rTESc1KdnPw4TC2paw=
|
github.com/nats-io/nuid v1.0.1 h1:5iA8DT8V7q8WK2EScv2padNa/rTESc1KdnPw4TC2paw=
|
||||||
github.com/nats-io/nuid v1.0.1/go.mod h1:19wcPz3Ph3q0Jbyiqsd0kePYG7A95tJPxeL+1OSON2c=
|
github.com/nats-io/nuid v1.0.1/go.mod h1:19wcPz3Ph3q0Jbyiqsd0kePYG7A95tJPxeL+1OSON2c=
|
||||||
github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||||
github.com/pkg/errors v0.8.1 h1:iURUrRGxPUNPdy5/HRSm+Yj6okJ6UtLINN0Q9M4+h3I=
|
|
||||||
github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||||
|
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
|
||||||
|
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||||
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
||||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||||
github.com/prometheus/procfs v0.0.0-20190425082905-87a4384529e0 h1:c8R11WC8m7KNMkTv/0+Be8vvwo4I3/Ut9AC2FW8fX3U=
|
github.com/prometheus/procfs v0.0.0-20190425082905-87a4384529e0 h1:c8R11WC8m7KNMkTv/0+Be8vvwo4I3/Ut9AC2FW8fX3U=
|
||||||
|
@ -72,23 +84,40 @@ github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81P
|
||||||
github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||||
github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY=
|
github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY=
|
||||||
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||||
github.com/thoas/go-funk v0.9.1 h1:O549iLZqPpTUQ10ykd26sZhzD+rmR5pWhuElrhbC20M=
|
|
||||||
github.com/thoas/go-funk v0.9.1/go.mod h1:+IWnUfUmFO1+WVYQWQtIJHeRRdaIyyYglZN7xzUPe4Q=
|
github.com/thoas/go-funk v0.9.1/go.mod h1:+IWnUfUmFO1+WVYQWQtIJHeRRdaIyyYglZN7xzUPe4Q=
|
||||||
|
github.com/thoas/go-funk v0.9.2 h1:oKlNYv0AY5nyf9g+/GhMgS/UO2ces0QRdPKwkhY3VCk=
|
||||||
|
github.com/thoas/go-funk v0.9.2/go.mod h1:+IWnUfUmFO1+WVYQWQtIJHeRRdaIyyYglZN7xzUPe4Q=
|
||||||
|
github.com/tidwall/pretty v1.0.0 h1:HsD+QiTn7sK6flMKIvNmpqz1qrpP3Ps6jOKIKMooyg4=
|
||||||
|
github.com/tidwall/pretty v1.0.0/go.mod h1:XNkn88O1ChpSDQmQeStsy+sBenx6DDtFZJxhVysOjyk=
|
||||||
|
github.com/xdg-go/pbkdf2 v1.0.0 h1:Su7DPu48wXMwC3bs7MCNG+z4FhcyEuz5dlvchbq0B0c=
|
||||||
|
github.com/xdg-go/pbkdf2 v1.0.0/go.mod h1:jrpuAogTd400dnrH08LKmI/xc1MbPOebTwRqcT5RDeI=
|
||||||
|
github.com/xdg-go/scram v1.1.1 h1:VOMT+81stJgXW3CpHyqHN3AXDYIMsx56mEFrB37Mb/E=
|
||||||
|
github.com/xdg-go/scram v1.1.1/go.mod h1:RaEWvsqvNKKvBPvcKeFjrG2cJqOkHTiyTpzz23ni57g=
|
||||||
|
github.com/xdg-go/stringprep v1.0.3 h1:kdwGpVNwPFtjs98xCGkHjQtGKh86rDcRZN17QEMCOIs=
|
||||||
|
github.com/xdg-go/stringprep v1.0.3/go.mod h1:W3f5j4i+9rC0kuIEJL0ky1VpHXQU3ocBgklLGvcBnW8=
|
||||||
|
github.com/youmark/pkcs8 v0.0.0-20181117223130-1be2e3e5546d h1:splanxYIlg+5LfHAM6xpdFEAYOk8iySO56hMFq6uLyA=
|
||||||
|
github.com/youmark/pkcs8 v0.0.0-20181117223130-1be2e3e5546d/go.mod h1:rHwXgn7JulP+udvsHwJoVG1YGAP6VLg4y9I5dyZdqmA=
|
||||||
github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
||||||
go.elastic.co/apm v1.13.1 h1:ICIcUcQOImg/bve9mQVyLCvm1cSUZ1afdwK6ACnxczU=
|
github.com/yuin/goldmark v1.4.0/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k=
|
||||||
go.elastic.co/apm v1.13.1/go.mod h1:dylGv2HKR0tiCV+wliJz1KHtDyuD8SPe69oV7VyK6WY=
|
go.elastic.co/apm v1.13.1/go.mod h1:dylGv2HKR0tiCV+wliJz1KHtDyuD8SPe69oV7VyK6WY=
|
||||||
go.elastic.co/apm/module/apmzap v1.13.1 h1:Soa4vNYYabPvOW1vm1A00C0UcEmfEzcx3YBjAgf5ue4=
|
go.elastic.co/apm v1.15.0 h1:uPk2g/whK7c7XiZyz/YCUnAUBNPiyNeE3ARX3G6Gx7Q=
|
||||||
|
go.elastic.co/apm v1.15.0/go.mod h1:dylGv2HKR0tiCV+wliJz1KHtDyuD8SPe69oV7VyK6WY=
|
||||||
go.elastic.co/apm/module/apmzap v1.13.1/go.mod h1:Tu8/TwffpBoNGmI05VcL1Ye2AC8oXrlMKNaKD1TIQy0=
|
go.elastic.co/apm/module/apmzap v1.13.1/go.mod h1:Tu8/TwffpBoNGmI05VcL1Ye2AC8oXrlMKNaKD1TIQy0=
|
||||||
|
go.elastic.co/apm/module/apmzap v1.15.0 h1:SjXslnImV3jaK2BtNqRl994H9mpG8+6qqPAahbzwIys=
|
||||||
|
go.elastic.co/apm/module/apmzap v1.15.0/go.mod h1:eowOIqa+vS+BZ9YOCztd8poYGxSxXh8YfVuOHTMhKQs=
|
||||||
go.elastic.co/fastjson v1.1.0 h1:3MrGBWWVIxe/xvsbpghtkFoPciPhOCmjsR/HfwEeQR4=
|
go.elastic.co/fastjson v1.1.0 h1:3MrGBWWVIxe/xvsbpghtkFoPciPhOCmjsR/HfwEeQR4=
|
||||||
go.elastic.co/fastjson v1.1.0/go.mod h1:boNGISWMjQsUPy/t6yqt2/1Wx4YNPSe+mZjlyw9vKKI=
|
go.elastic.co/fastjson v1.1.0/go.mod h1:boNGISWMjQsUPy/t6yqt2/1Wx4YNPSe+mZjlyw9vKKI=
|
||||||
|
go.mongodb.org/mongo-driver v1.10.1 h1:NujsPveKwHaWuKUer/ceo9DzEe7HIj1SlJ6uvXZG0S4=
|
||||||
|
go.mongodb.org/mongo-driver v1.10.1/go.mod h1:z4XpeoU6w+9Vht+jAFyLgVrD+jGSQQe0+CBWFHNiHt8=
|
||||||
go.uber.org/atomic v1.3.2/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE=
|
go.uber.org/atomic v1.3.2/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE=
|
||||||
go.uber.org/atomic v1.7.0 h1:ADUqmZGgLDDfbSL9ZmPxKTybcoEYHgpYfELNoN+7hsw=
|
go.uber.org/atomic v1.7.0 h1:ADUqmZGgLDDfbSL9ZmPxKTybcoEYHgpYfELNoN+7hsw=
|
||||||
go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc=
|
go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc=
|
||||||
go.uber.org/goleak v1.1.10 h1:z+mqJhf6ss6BSfSM671tgKyZBFPTTJM+HLxnhPC3wu0=
|
go.uber.org/goleak v1.1.10 h1:z+mqJhf6ss6BSfSM671tgKyZBFPTTJM+HLxnhPC3wu0=
|
||||||
go.uber.org/goleak v1.1.10/go.mod h1:8a7PlsEVH3e/a/GLqe5IIrQx6GzcnRmZEufDUTk4A7A=
|
go.uber.org/goleak v1.1.10/go.mod h1:8a7PlsEVH3e/a/GLqe5IIrQx6GzcnRmZEufDUTk4A7A=
|
||||||
go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0=
|
go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0=
|
||||||
go.uber.org/multierr v1.6.0 h1:y6IPFStTAIT5Ytl7/XYmHvzXQ7S3g/IeZW9hyZ5thw4=
|
|
||||||
go.uber.org/multierr v1.6.0/go.mod h1:cdWPpRnG4AhwMwsgIHip0KRBQjJy5kYEpYjJxpXp9iU=
|
go.uber.org/multierr v1.6.0/go.mod h1:cdWPpRnG4AhwMwsgIHip0KRBQjJy5kYEpYjJxpXp9iU=
|
||||||
|
go.uber.org/multierr v1.8.0 h1:dg6GjLku4EH+249NNmoIciG9N/jURbDG+pFlTkhzIC8=
|
||||||
|
go.uber.org/multierr v1.8.0/go.mod h1:7EAYxJLBy9rStEaz58O2t4Uvip6FSURkq8/ppBp95ak=
|
||||||
go.uber.org/zap v1.9.1/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q=
|
go.uber.org/zap v1.9.1/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q=
|
||||||
go.uber.org/zap v1.18.1 h1:CSUJ2mjFszzEWt4CdKISEuChVIXGBn3lAPwkRGyVrc4=
|
go.uber.org/zap v1.18.1 h1:CSUJ2mjFszzEWt4CdKISEuChVIXGBn3lAPwkRGyVrc4=
|
||||||
go.uber.org/zap v1.18.1/go.mod h1:xg/QME4nWcxGxrpdeYfq7UvYrLh66cuVKdrbD1XF/NI=
|
go.uber.org/zap v1.18.1/go.mod h1:xg/QME4nWcxGxrpdeYfq7UvYrLh66cuVKdrbD1XF/NI=
|
||||||
|
@ -96,34 +125,51 @@ golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACk
|
||||||
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||||
golang.org/x/crypto v0.0.0-20200323165209-0ec3e9974c59/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
golang.org/x/crypto v0.0.0-20200323165209-0ec3e9974c59/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||||
golang.org/x/crypto v0.0.0-20210314154223-e6e6c4f2bb5b/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4=
|
golang.org/x/crypto v0.0.0-20210314154223-e6e6c4f2bb5b/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4=
|
||||||
golang.org/x/crypto v0.0.0-20210616213533-5ff15b29337e h1:gsTQYXdTw2Gq7RBsWvlQ91b+aEQ6bXFUngBGuR8sPpI=
|
|
||||||
golang.org/x/crypto v0.0.0-20210616213533-5ff15b29337e/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
|
golang.org/x/crypto v0.0.0-20210616213533-5ff15b29337e/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
|
||||||
|
golang.org/x/crypto v0.0.0-20220622213112-05595931fe9d h1:sK3txAijHtOK88l68nt020reeT1ZdKLIYetKl95FzVY=
|
||||||
|
golang.org/x/crypto v0.0.0-20220622213112-05595931fe9d/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
|
||||||
golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
|
golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
|
||||||
golang.org/x/lint v0.0.0-20201208152925-83fdc39ff7b5 h1:2M3HP5CCK1Si9FQhwnzYhXdG6DXeebvUHFpre8QvbyI=
|
|
||||||
golang.org/x/lint v0.0.0-20201208152925-83fdc39ff7b5/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY=
|
golang.org/x/lint v0.0.0-20201208152925-83fdc39ff7b5/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY=
|
||||||
|
golang.org/x/lint v0.0.0-20210508222113-6edffad5e616 h1:VLliZ0d+/avPrXXH+OakdXhpJuEoBZuwh1m2j7U6Iug=
|
||||||
|
golang.org/x/lint v0.0.0-20210508222113-6edffad5e616/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY=
|
||||||
golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg=
|
golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg=
|
||||||
golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
||||||
golang.org/x/mod v0.3.0 h1:RM4zey1++hCTbCVQfnWeKs9/IEsaBLA8vTkd0WVtmH4=
|
|
||||||
golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
||||||
|
golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
||||||
|
golang.org/x/mod v0.5.1 h1:OJxoQ/rynoF0dcCdI7cLPktw/hR2cueqYfjm43oqK38=
|
||||||
|
golang.org/x/mod v0.5.1/go.mod h1:5OXOZSfqPIIbmVBIIKWRFfZjPR0E5r58TLhUjH0a2Ro=
|
||||||
golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||||
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||||
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||||
golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||||
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
|
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
|
||||||
|
golang.org/x/net v0.0.0-20210805182204-aaa1db679c0d/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
||||||
|
golang.org/x/net v0.0.0-20211029224645-99673261e6eb/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
||||||
|
golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2 h1:CIJ76btIcR3eFI5EgSo6k1qKw9KJexJuRLI9G7Hp5wE=
|
||||||
|
golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
||||||
golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
|
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c h1:5KslGYwFpkhGh+Q16bwMP3cOontH8FOep7tGV86Y7SQ=
|
||||||
|
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
golang.org/x/sys v0.0.0-20190130150945-aca44879d564/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
golang.org/x/sys v0.0.0-20190130150945-aca44879d564/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||||
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||||
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
|
golang.org/x/sys v0.0.0-20190813064441-fde4db37ae7a/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20191025021431-6c3a3bfe00ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20191025021431-6c3a3bfe00ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1 h1:SrN+KX8Art/Sf4HNj6Zcz06G7VEz+7w9tdXTPOZ7+l4=
|
golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
|
golang.org/x/sys v0.0.0-20210809222454-d867a43fc93e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
|
golang.org/x/sys v0.0.0-20211102192858-4dd72447c267 h1:7zYaz3tjChtpayGDzu6H0hDAUM5zIGA2XW7kRNgQ0jc=
|
||||||
|
golang.org/x/sys v0.0.0-20211102192858-4dd72447c267/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
||||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||||
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||||
|
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||||
|
golang.org/x/text v0.3.7 h1:olpwvP2KacW1ZWvsR7uQhoyTYvKAupfQrRGBFM352Gk=
|
||||||
|
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
|
||||||
golang.org/x/time v0.0.0-20200416051211-89c76fbcd5d1 h1:NusfzzA6yGQ+ua51ck7E3omNUX/JuqbFSaRGqU8CcLI=
|
golang.org/x/time v0.0.0-20200416051211-89c76fbcd5d1 h1:NusfzzA6yGQ+ua51ck7E3omNUX/JuqbFSaRGqU8CcLI=
|
||||||
golang.org/x/time v0.0.0-20200416051211-89c76fbcd5d1/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
golang.org/x/time v0.0.0-20200416051211-89c76fbcd5d1/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||||
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||||
|
@ -131,12 +177,14 @@ golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3
|
||||||
golang.org/x/tools v0.0.0-20191108193012-7d206e10da11/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
golang.org/x/tools v0.0.0-20191108193012-7d206e10da11/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||||
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||||
golang.org/x/tools v0.0.0-20200130002326-2f3ba24bd6e7/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
|
golang.org/x/tools v0.0.0-20200130002326-2f3ba24bd6e7/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
|
||||||
golang.org/x/tools v0.0.0-20200509030707-2212a7e161a5 h1:MeC2gMlMdkd67dn17MEby3rGXRxZtWeiRXOnISfTQ74=
|
|
||||||
golang.org/x/tools v0.0.0-20200509030707-2212a7e161a5/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
|
golang.org/x/tools v0.0.0-20200509030707-2212a7e161a5/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
|
||||||
|
golang.org/x/tools v0.1.7 h1:6j8CgantCy3yc8JGBqkDLMKWqZ0RDU2g1HVgacojGWQ=
|
||||||
|
golang.org/x/tools v0.1.7/go.mod h1:LGqMHiF4EqQNHR1JncWGqT5BVaXmza+X+BDGol+dOxo=
|
||||||
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||||
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||||
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4=
|
|
||||||
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||||
|
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 h1:go1bK/D/BFZV2I8cIQd1NKEZ+0owSTG1fDTci4IqFcE=
|
||||||
|
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||||
google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8=
|
google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8=
|
||||||
google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0=
|
google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0=
|
||||||
google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM=
|
google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM=
|
||||||
|
@ -149,12 +197,15 @@ google.golang.org/protobuf v1.27.1 h1:SnqbnDw1V7RiZcXPx5MEeqPv2s79L9i7BJUlG/+Rur
|
||||||
google.golang.org/protobuf v1.27.1/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
|
google.golang.org/protobuf v1.27.1/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
|
||||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||||
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||||
|
gopkg.in/yaml.v1 v1.0.0-20140924161607-9f9df34309c0/go.mod h1:WDnlLJ4WF5VGsH/HVa3CI79GS0ol3YnhVnKP89i0kNg=
|
||||||
gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||||
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||||
gopkg.in/yaml.v2 v2.2.8 h1:obN1ZagJSUGI0Ek/LBmuj4SNLPfIny3KsKFopxRdj10=
|
gopkg.in/yaml.v2 v2.2.8 h1:obN1ZagJSUGI0Ek/LBmuj4SNLPfIny3KsKFopxRdj10=
|
||||||
gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||||
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||||
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b h1:h8qDotaEPuJATrMmW04NCwg7v22aHH28wwpauUhK9Oo=
|
|
||||||
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||||
howett.net/plist v0.0.0-20181124034731-591f970eefbb h1:jhnBjNi9UFpfpl8YZhA9CrOqpnJdvzuiHsl/dnxl11M=
|
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
|
||||||
|
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||||
howett.net/plist v0.0.0-20181124034731-591f970eefbb/go.mod h1:vMygbs4qMhSZSc4lCUl2OEE+rDiIIJAIdR4m7MiMcm0=
|
howett.net/plist v0.0.0-20181124034731-591f970eefbb/go.mod h1:vMygbs4qMhSZSc4lCUl2OEE+rDiIIJAIdR4m7MiMcm0=
|
||||||
|
howett.net/plist v1.0.0 h1:7CrbWYbPPO/PyNy38b2EB/+gYbjCe2DXBxgtOOZbSQM=
|
||||||
|
howett.net/plist v1.0.0/go.mod h1:lqaXoTrLY4hg8tnEzNru53gicrbv7rrk+2xJA/7hw9g=
|
||||||
|
|
|
@ -20,19 +20,33 @@ const (
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
VehicleTypeID50ccAbove = 1
|
MotorbikeProductCode = "bbxm"
|
||||||
VehicleTypeID50ccBelow = 2
|
MotorbikeProviderID = 4
|
||||||
VehicleTypeIDElectricBike = 3
|
MotorbikeProductID = 18
|
||||||
|
|
||||||
|
CarProductCode = "bbot"
|
||||||
|
CarProviderID = 10
|
||||||
|
CarProductID = 35
|
||||||
|
|
||||||
|
NumOfSeatsMinValue = 25
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
type InsuranceConfig struct {
|
||||||
CarOccupantAccidentInsurance0 = 1
|
ProductCode string
|
||||||
CarOccupantAccidentInsurance10m = 2
|
ProviderID int
|
||||||
CarOccupantAccidentInsurance20m = 3
|
ProductID int
|
||||||
)
|
}
|
||||||
|
|
||||||
const (
|
var (
|
||||||
productCodeDefault = "bbxm"
|
CarConfig = InsuranceConfig{
|
||||||
providerIDDefault = 4
|
ProductCode: CarProductCode,
|
||||||
productIDDefault = 18
|
ProviderID: CarProviderID,
|
||||||
|
ProductID: CarProductID,
|
||||||
|
}
|
||||||
|
|
||||||
|
MotorbikeConfig = InsuranceConfig{
|
||||||
|
ProductCode: MotorbikeProductCode,
|
||||||
|
ProviderID: MotorbikeProviderID,
|
||||||
|
ProductID: MotorbikeProductID,
|
||||||
|
}
|
||||||
)
|
)
|
||||||
|
|
|
@ -1,19 +1,25 @@
|
||||||
package globalcare
|
package globalcare
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"crypto"
|
||||||
|
"crypto/rand"
|
||||||
"crypto/rsa"
|
"crypto/rsa"
|
||||||
|
"crypto/sha256"
|
||||||
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"log"
|
||||||
"net/http"
|
"net/http"
|
||||||
|
|
||||||
"github.com/Selly-Modules/logger"
|
"git.selly.red/Selly-Modules/logger"
|
||||||
"github.com/Selly-Modules/natsio"
|
"git.selly.red/Selly-Modules/natsio"
|
||||||
"github.com/Selly-Modules/natsio/model"
|
"git.selly.red/Selly-Modules/natsio/model"
|
||||||
"github.com/Selly-Modules/natsio/subject"
|
"git.selly.red/Selly-Modules/natsio/subject"
|
||||||
"github.com/nats-io/nats.go"
|
"github.com/nats-io/nats.go"
|
||||||
"github.com/thoas/go-funk"
|
"github.com/thoas/go-funk"
|
||||||
|
|
||||||
"github.com/Selly-Modules/3pl/util/base64"
|
"git.selly.red/Selly-Modules/3pl/util/base64"
|
||||||
"github.com/Selly-Modules/3pl/util/pjson"
|
"git.selly.red/Selly-Modules/3pl/util/httputil"
|
||||||
|
"git.selly.red/Selly-Modules/3pl/util/pjson"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Client ...
|
// Client ...
|
||||||
|
@ -27,7 +33,7 @@ type Client struct {
|
||||||
// NewClient generate Client
|
// NewClient generate Client
|
||||||
// using privateKey to decrypt data from Global Care
|
// using privateKey to decrypt data from Global Care
|
||||||
// using publicKey to encrypt data before send to Global Care
|
// using publicKey to encrypt data before send to Global Care
|
||||||
func NewClient(env ENV, privateKey, publicKey string) (*Client, error) {
|
func NewClient(env ENV, privateKey, publicKey string, natsClient natsio.Server) (*Client, error) {
|
||||||
validENVs := []ENV{EnvProd, EnvDev, EnvStaging}
|
validENVs := []ENV{EnvProd, EnvDev, EnvStaging}
|
||||||
if !funk.Contains(validENVs, env) {
|
if !funk.Contains(validENVs, env) {
|
||||||
return nil, fmt.Errorf("globalcare.NewClient - invalid_env: %s", env)
|
return nil, fmt.Errorf("globalcare.NewClient - invalid_env: %s", env)
|
||||||
|
@ -43,24 +49,22 @@ func NewClient(env ENV, privateKey, publicKey string) (*Client, error) {
|
||||||
return &Client{
|
return &Client{
|
||||||
privateKey: privKey,
|
privateKey: privKey,
|
||||||
publicKey: pubKey,
|
publicKey: pubKey,
|
||||||
|
env: env,
|
||||||
|
natsClient: natsClient,
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// CreateOrder ...
|
// CreateOrder ...
|
||||||
func (c *Client) CreateOrder(p CreateOrderPayload) (*CommonResponse, error) {
|
func (c *Client) CreateOrder(data CreateOrderPayload) (*CreateOrderResponseDecoded, error) {
|
||||||
url := c.getBaseURL() + apiPathCreateOrder
|
url := c.getBaseURL() + apiPathCreateOrder
|
||||||
data := createOrderData{
|
dataString := base64.Encode(pjson.ToBytes(data))
|
||||||
ProductCode: productCodeDefault,
|
sign, err := c.signData(dataString)
|
||||||
ProviderID: providerIDDefault,
|
if err != nil {
|
||||||
ProductID: productIDDefault,
|
return nil, fmt.Errorf("globalcare.Client.CreateOrder - sign_err %v", err)
|
||||||
PartnerID: p.PartnerOrderCode,
|
|
||||||
VehicleInfo: p.VehicleInfo,
|
|
||||||
InsuredInfo: p.InsuredInfo,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
body := CommonRequestBody{
|
body := CommonRequestBody{
|
||||||
Signature: "", // TODO:implement
|
Signature: sign,
|
||||||
Data: base64.Encode(pjson.ToBytes(data)),
|
Data: dataString,
|
||||||
}
|
}
|
||||||
natsPayload := model.CommunicationRequestHttp{
|
natsPayload := model.CommunicationRequestHttp{
|
||||||
ResponseImmediately: true,
|
ResponseImmediately: true,
|
||||||
|
@ -68,6 +72,9 @@ func (c *Client) CreateOrder(p CreateOrderPayload) (*CommonResponse, error) {
|
||||||
URL: url,
|
URL: url,
|
||||||
Method: http.MethodPost,
|
Method: http.MethodPost,
|
||||||
Data: pjson.ToJSONString(body),
|
Data: pjson.ToJSONString(body),
|
||||||
|
Header: map[string]string{
|
||||||
|
httputil.HeaderKeyContentType: httputil.HeaderValueApplicationJSON,
|
||||||
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
msg, err := c.requestNats(subject.Communication.RequestHTTP, natsPayload)
|
msg, err := c.requestNats(subject.Communication.RequestHTTP, natsPayload)
|
||||||
|
@ -83,14 +90,38 @@ func (c *Client) CreateOrder(p CreateOrderPayload) (*CommonResponse, error) {
|
||||||
res CommonResponse
|
res CommonResponse
|
||||||
)
|
)
|
||||||
if err = pjson.Unmarshal(msg.Data, &r); err != nil {
|
if err = pjson.Unmarshal(msg.Data, &r); err != nil {
|
||||||
|
log.Printf("globalcare.Client.CreateOrder - pjson.Unmarshal %v, %s\n", err, string(msg.Data))
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
err = r.ParseResponseData(&res)
|
if err = r.ParseResponseData(&res); err != nil {
|
||||||
return &res, err
|
log.Printf("globalcare.Client.CreateOrder - ParseResponseData %v, %s\n", err, string(msg.Data))
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
if r.Response == nil {
|
||||||
|
log.Println("globalcare.Client.CreateOrder - nil response")
|
||||||
|
return nil, fmt.Errorf("globalcare.Client.CreateOrder create_order_empty_response")
|
||||||
|
}
|
||||||
|
|
||||||
|
if r.Response.StatusCode >= http.StatusBadRequest {
|
||||||
|
log.Println("globalcare.Client.CreateOrder - bad request", res)
|
||||||
|
info, err := res.DecodeError()
|
||||||
|
if err != nil {
|
||||||
|
log.Println("globalcare.Client.CreateOrder - decode err", err)
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return nil, errors.New(info.Message)
|
||||||
|
}
|
||||||
|
info, err := res.DecodeCreateOrderSuccess()
|
||||||
|
if err != nil {
|
||||||
|
log.Println("globalcare.Client.CreateOrder - DecodeCreateOrderSuccess err:", err, string(msg.Data))
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return &info, err
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetOrder ...
|
// GetOrder ...
|
||||||
func (c *Client) GetOrder(orderCode string) (*CommonResponse, error) {
|
func (c *Client) GetOrder(orderCode string) (*GetOrderResponseDecoded, error) {
|
||||||
url := c.getBaseURL() + fmt.Sprintf(apiPathGetOrder, orderCode)
|
url := c.getBaseURL() + fmt.Sprintf(apiPathGetOrder, orderCode)
|
||||||
natsPayload := model.CommunicationRequestHttp{
|
natsPayload := model.CommunicationRequestHttp{
|
||||||
ResponseImmediately: true,
|
ResponseImmediately: true,
|
||||||
|
@ -114,8 +145,25 @@ func (c *Client) GetOrder(orderCode string) (*CommonResponse, error) {
|
||||||
if err = pjson.Unmarshal(msg.Data, &r); err != nil {
|
if err = pjson.Unmarshal(msg.Data, &r); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
err = r.ParseResponseData(&res)
|
if err = r.ParseResponseData(&res); err != nil {
|
||||||
return &res, err
|
return nil, err
|
||||||
|
}
|
||||||
|
if r.Response == nil {
|
||||||
|
return nil, fmt.Errorf("globalcare.Client.GetOrder get_order_empty_response")
|
||||||
|
}
|
||||||
|
|
||||||
|
if r.Response.StatusCode >= http.StatusBadRequest {
|
||||||
|
info, err := res.DecodeError()
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return nil, errors.New(info.Message)
|
||||||
|
}
|
||||||
|
info, err := res.DecodeGetOrderSuccess()
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return &info, err
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Client) requestNats(subject string, data interface{}) (*nats.Msg, error) {
|
func (c *Client) requestNats(subject string, data interface{}) (*nats.Msg, error) {
|
||||||
|
@ -126,3 +174,18 @@ func (c *Client) requestNats(subject string, data interface{}) (*nats.Msg, error
|
||||||
func (c *Client) getBaseURL() string {
|
func (c *Client) getBaseURL() string {
|
||||||
return baseURLENVMapping[c.env]
|
return baseURLENVMapping[c.env]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (c *Client) signData(s string) (string, error) {
|
||||||
|
msgHash := sha256.New()
|
||||||
|
_, err := msgHash.Write([]byte(s))
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
msgHashSum := msgHash.Sum(nil)
|
||||||
|
signature, err := rsa.SignPKCS1v15(rand.Reader, c.privateKey, crypto.SHA256, msgHashSum)
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
|
||||||
|
return base64.Encode(signature), nil
|
||||||
|
}
|
||||||
|
|
|
@ -1,5 +1,9 @@
|
||||||
package globalcare
|
package globalcare
|
||||||
|
|
||||||
|
import (
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
// CommonRequestBody ...
|
// CommonRequestBody ...
|
||||||
type CommonRequestBody struct {
|
type CommonRequestBody struct {
|
||||||
Signature string `json:"signature"`
|
Signature string `json:"signature"`
|
||||||
|
@ -8,12 +12,6 @@ type CommonRequestBody struct {
|
||||||
|
|
||||||
// CreateOrderPayload ...
|
// CreateOrderPayload ...
|
||||||
type CreateOrderPayload struct {
|
type CreateOrderPayload struct {
|
||||||
PartnerOrderCode string `json:"partnerOrderCode"`
|
|
||||||
VehicleInfo VehicleInfo `json:"vehicleInfo"`
|
|
||||||
InsuredInfo InsuredInfo `json:"insuredInfo"`
|
|
||||||
}
|
|
||||||
|
|
||||||
type createOrderData struct {
|
|
||||||
ProductCode string `json:"productCode"`
|
ProductCode string `json:"productCode"`
|
||||||
ProviderID int `json:"providerId"`
|
ProviderID int `json:"providerId"`
|
||||||
ProductID int `json:"productId"`
|
ProductID int `json:"productId"`
|
||||||
|
@ -24,12 +22,25 @@ type createOrderData struct {
|
||||||
|
|
||||||
// VehicleInfo ...
|
// VehicleInfo ...
|
||||||
type VehicleInfo struct {
|
type VehicleInfo struct {
|
||||||
TypeID int `json:"typeId"`
|
TypeID int `json:"typeId"`
|
||||||
TypeName string `json:"typeName"`
|
TypeName string `json:"typeName"`
|
||||||
CarOccupantAccidentInsurance int `json:"carOccupantAccidentInsurance"`
|
License string `json:"license"`
|
||||||
License string `json:"license"`
|
Chassis string `json:"chassis"`
|
||||||
Chassis string `json:"chassis"`
|
Engine string `json:"engine"`
|
||||||
Engine string `json:"engine"`
|
|
||||||
|
// V2 = true if TypeID = 1 and insurance type is car
|
||||||
|
V2 bool `json:"v2,omitempty"`
|
||||||
|
// CarOccupantAccidentInsurance type int for motorbike, type CarOccupantAccidentInsuranceObj for car insurance
|
||||||
|
CarOccupantAccidentInsurance interface{} `json:"carOccupantAccidentInsurance"`
|
||||||
|
NumberOfSeatsOver25 int `json:"numberOfSeatsOver25"`
|
||||||
|
NumberOfSeatsOrTonnageName string `json:"numberOfSeatsOrTonnageName"`
|
||||||
|
NumberOfSeatsOrTonnage int `json:"numberOfSeatsOrTonnage"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// CarOccupantAccidentInsuranceObj ...
|
||||||
|
type CarOccupantAccidentInsuranceObj struct {
|
||||||
|
NumberOfSeats int `json:"numberOfSeats"`
|
||||||
|
Buy int `json:"buy"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// InsuredInfo ...
|
// InsuredInfo ...
|
||||||
|
@ -41,3 +52,13 @@ type InsuredInfo struct {
|
||||||
YearsOfInsurance string `json:"yearsOfInsurance"`
|
YearsOfInsurance string `json:"yearsOfInsurance"`
|
||||||
BeginDate string `json:"beginDate"`
|
BeginDate string `json:"beginDate"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Webhook ...
|
||||||
|
type Webhook struct {
|
||||||
|
Status int `json:"status"`
|
||||||
|
OrderCode string `json:"orderCode"`
|
||||||
|
UpdatedAt time.Time `json:"updatedAt"`
|
||||||
|
Note string `json:"note"`
|
||||||
|
CertLink string `json:"certLink"`
|
||||||
|
PartnerOrderCode string `json:"partnerOrderCode"`
|
||||||
|
}
|
||||||
|
|
|
@ -1,8 +1,92 @@
|
||||||
package globalcare
|
package globalcare
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/json"
|
||||||
|
|
||||||
|
"git.selly.red/Selly-Modules/3pl/util/base64"
|
||||||
|
)
|
||||||
|
|
||||||
// CommonResponse ...
|
// CommonResponse ...
|
||||||
type CommonResponse struct {
|
type CommonResponse struct {
|
||||||
StatusCode int `json:"statusCode"`
|
Data string `json:"data"`
|
||||||
Message string `json:"message"`
|
Signature string `json:"signature"`
|
||||||
Result interface{} `json:"result"`
|
}
|
||||||
|
|
||||||
|
// DecodeCreateOrderSuccess ...
|
||||||
|
func (r *CommonResponse) DecodeCreateOrderSuccess() (res CreateOrderResponseDecoded, err error) {
|
||||||
|
err = r.Decode(&res)
|
||||||
|
return res, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// DecodeGetOrderSuccess ...
|
||||||
|
func (r *CommonResponse) DecodeGetOrderSuccess() (res GetOrderResponseDecoded, err error) {
|
||||||
|
err = r.Decode(&res)
|
||||||
|
return res, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// DecodeError ...
|
||||||
|
func (r *CommonResponse) DecodeError() (res ResponseError, err error) {
|
||||||
|
err = r.Decode(&res)
|
||||||
|
return res, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// Decode ...
|
||||||
|
func (r *CommonResponse) Decode(resultPointer interface{}) error {
|
||||||
|
b := base64.Decode(r.Data)
|
||||||
|
return json.Unmarshal(b, resultPointer)
|
||||||
|
}
|
||||||
|
|
||||||
|
// CreateOrderResponseDecoded ...
|
||||||
|
type CreateOrderResponseDecoded struct {
|
||||||
|
StatusCode int `json:"statusCode"`
|
||||||
|
Result CreateOrderResult `json:"result"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// CreateOrderResult ...
|
||||||
|
type CreateOrderResult struct {
|
||||||
|
OrderCode string `json:"orderCode"`
|
||||||
|
PaymentLink string `json:"paymentLink"`
|
||||||
|
Fees int `json:"fees"`
|
||||||
|
StatusId int `json:"statusId"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// ResponseError ...
|
||||||
|
type ResponseError struct {
|
||||||
|
StatusCode int `json:"statusCode"`
|
||||||
|
Message string `json:"message"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetOrderResponseDecoded ...
|
||||||
|
type GetOrderResponseDecoded struct {
|
||||||
|
StatusCode int `json:"statusCode"`
|
||||||
|
Result GetOrderResult `json:"result"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetOrderResult ...
|
||||||
|
type GetOrderResult struct {
|
||||||
|
ProviderTitle string `json:"providerTitle"`
|
||||||
|
BeginDate string `json:"beginDate"`
|
||||||
|
EndDate string `json:"endDate"`
|
||||||
|
Amount string `json:"amount"`
|
||||||
|
CertLink string `json:"certLink"`
|
||||||
|
StatusId int `json:"statusId"`
|
||||||
|
StatusTitle string `json:"statusTitle"`
|
||||||
|
Buyer BuyerInfo `json:"buyer"`
|
||||||
|
InsuredInfo InsuranceInfo `json:"insuredInfo"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// InsuranceInfo ...
|
||||||
|
type InsuranceInfo struct {
|
||||||
|
TypeId int `json:"typeId"`
|
||||||
|
TypeName string `json:"typeName"`
|
||||||
|
CarOccupantAccidentInsurance int `json:"carOccupantAccidentInsurance"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// BuyerInfo ...
|
||||||
|
type BuyerInfo struct {
|
||||||
|
BuyerName string `json:"buyerName"`
|
||||||
|
BuyerPrivateId interface{} `json:"buyerPrivateId"`
|
||||||
|
BuyerPhone string `json:"buyerPhone"`
|
||||||
|
BuyerAddress string `json:"buyerAddress"`
|
||||||
|
BuyerEmail string `json:"buyerEmail"`
|
||||||
}
|
}
|
||||||
|
|
|
@ -1 +0,0 @@
|
||||||
package globalcare
|
|
|
@ -7,7 +7,7 @@ import (
|
||||||
"encoding/pem"
|
"encoding/pem"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
|
||||||
"github.com/Selly-Modules/logger"
|
"git.selly.red/Selly-Modules/logger"
|
||||||
)
|
)
|
||||||
|
|
||||||
// toBytes ...
|
// toBytes ...
|
||||||
|
|
|
@ -0,0 +1,21 @@
|
||||||
|
package jtexpress
|
||||||
|
|
||||||
|
const (
|
||||||
|
apiHostProd = "https://ylstandard.jtexpress.vn"
|
||||||
|
apiHostDev = "https://demo-ylstandard.jtexpress.vn"
|
||||||
|
|
||||||
|
apiPathEstimateFee = "/yuenan-interface-web/jtpos/inquiry!freight.action"
|
||||||
|
apiPathCreateOrder = "/yuenan-interface-web/order/orderAction!createOrder.action"
|
||||||
|
apiPathCancelOrder = "/yuenan-interface-web/order/orderAction!createOrder.action"
|
||||||
|
apiPathTrackingOrder = ""
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
statusSuccess = "true"
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
msgTypeEstimateFee = "FREIGHTQUERY"
|
||||||
|
msgTypeCreateOrder = "ORDERCREATE"
|
||||||
|
msgTypeCancelOrder = "UPDATE"
|
||||||
|
)
|
|
@ -0,0 +1,120 @@
|
||||||
|
package jtexpress
|
||||||
|
|
||||||
|
import (
|
||||||
|
"crypto/md5"
|
||||||
|
"fmt"
|
||||||
|
"io"
|
||||||
|
|
||||||
|
"github.com/go-resty/resty/v2"
|
||||||
|
|
||||||
|
"git.selly.red/Selly-Modules/3pl/util/base64"
|
||||||
|
"git.selly.red/Selly-Modules/3pl/util/pjson"
|
||||||
|
)
|
||||||
|
|
||||||
|
func New(digestKey, companyID string, isProd, debug bool) *Client {
|
||||||
|
host := apiHostDev
|
||||||
|
if isProd {
|
||||||
|
host = apiHostProd
|
||||||
|
}
|
||||||
|
c := &Client{
|
||||||
|
DigestKey: digestKey,
|
||||||
|
EccompanyID: companyID,
|
||||||
|
IsProduction: isProd,
|
||||||
|
Debug: debug,
|
||||||
|
host: host,
|
||||||
|
httpClient: resty.New().SetDebug(debug),
|
||||||
|
}
|
||||||
|
return c
|
||||||
|
}
|
||||||
|
|
||||||
|
type Client struct {
|
||||||
|
DigestKey string
|
||||||
|
EccompanyID string
|
||||||
|
IsProduction bool
|
||||||
|
Debug bool
|
||||||
|
host string
|
||||||
|
httpClient *resty.Client
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *Client) EstimateFee(req *EstimateFeeReq) (r Response) {
|
||||||
|
path := c.host + apiPathEstimateFee
|
||||||
|
data := pjson.ToJSONString(req)
|
||||||
|
body := map[string]string{
|
||||||
|
"logistics_interface": data,
|
||||||
|
"data_digest": c.getDigest(data),
|
||||||
|
"msg_type": msgTypeEstimateFee,
|
||||||
|
"eccompanyid": c.EccompanyID,
|
||||||
|
}
|
||||||
|
r.Request.Body = pjson.ToBytes(body)
|
||||||
|
r.Request.URL = path
|
||||||
|
resp, err := c.httpClient.R().
|
||||||
|
SetMultipartFormData(body).
|
||||||
|
Post(path)
|
||||||
|
if err != nil {
|
||||||
|
r.Error = fmt.Errorf("jtepxress: request %s, err %v", path, err)
|
||||||
|
return r
|
||||||
|
}
|
||||||
|
r.Response.StatusCode = resp.StatusCode()
|
||||||
|
r.Response.Body = resp.Body()
|
||||||
|
|
||||||
|
return r
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *Client) CancelOrder(req *CancelOrderReq) (r Response) {
|
||||||
|
path := c.host + apiPathCancelOrder
|
||||||
|
data := pjson.ToJSONString(req)
|
||||||
|
body := map[string]string{
|
||||||
|
"logistics_interface": data,
|
||||||
|
"data_digest": c.getDigest(data),
|
||||||
|
"msg_type": msgTypeCancelOrder,
|
||||||
|
"eccompanyid": c.EccompanyID,
|
||||||
|
}
|
||||||
|
r.Request.Body = pjson.ToBytes(body)
|
||||||
|
r.Request.URL = path
|
||||||
|
resp, err := c.httpClient.R().
|
||||||
|
SetMultipartFormData(body).
|
||||||
|
Post(path)
|
||||||
|
if err != nil {
|
||||||
|
r.Error = fmt.Errorf("jtepxress: request %s, err %v", path, err)
|
||||||
|
return r
|
||||||
|
}
|
||||||
|
|
||||||
|
r.Response.StatusCode = resp.StatusCode()
|
||||||
|
r.Response.Body = resp.Body()
|
||||||
|
|
||||||
|
return r
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *Client) CreateOrder(req *CreateOrderReq) (r Response) {
|
||||||
|
path := c.host + apiPathCreateOrder
|
||||||
|
data := pjson.ToJSONString(req)
|
||||||
|
body := map[string]string{
|
||||||
|
"logistics_interface": data,
|
||||||
|
"data_digest": c.getDigest(data),
|
||||||
|
"msg_type": msgTypeCreateOrder,
|
||||||
|
"eccompanyid": c.EccompanyID,
|
||||||
|
}
|
||||||
|
r.Request.Body = pjson.ToBytes(body)
|
||||||
|
r.Request.URL = path
|
||||||
|
|
||||||
|
resp, err := c.httpClient.R().
|
||||||
|
SetMultipartFormData(body).
|
||||||
|
Post(path)
|
||||||
|
if err != nil {
|
||||||
|
r.Error = fmt.Errorf("jtepxress: request %s, err %v", path, err)
|
||||||
|
return r
|
||||||
|
}
|
||||||
|
|
||||||
|
r.Response.StatusCode = resp.StatusCode()
|
||||||
|
r.Response.Body = resp.Body()
|
||||||
|
|
||||||
|
return r
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *Client) getDigest(data string) string {
|
||||||
|
s := data + c.DigestKey
|
||||||
|
h := md5.New()
|
||||||
|
|
||||||
|
io.WriteString(h, s)
|
||||||
|
return base64.Encode([]byte(fmt.Sprintf("%x", h.Sum(nil))))
|
||||||
|
}
|
|
@ -0,0 +1,76 @@
|
||||||
|
package jtexpress
|
||||||
|
|
||||||
|
type EstimateFeeLocation struct {
|
||||||
|
Prov string `json:"prov"`
|
||||||
|
City string `json:"city"`
|
||||||
|
Area string `json:"area"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type EstimateFeeReq struct {
|
||||||
|
Cusname string `json:"cusname"` // = customerid
|
||||||
|
SelfAddress int `json:"selfAddress"`
|
||||||
|
ProductType string `json:"producttype"`
|
||||||
|
GoodsValue string `json:"goodsvalue"`
|
||||||
|
ItemsValue string `json:"itemsvalue"`
|
||||||
|
Weight string `json:"weight"`
|
||||||
|
Sender EstimateFeeLocation `json:"sender"`
|
||||||
|
Receiver EstimateFeeLocation `json:"receiver"`
|
||||||
|
Decs string `json:"decs"`
|
||||||
|
FeeType string `json:"feetype"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type CreateOrderReq struct {
|
||||||
|
Eccompanyid string `json:"eccompanyid"`
|
||||||
|
Customerid string `json:"customerid"`
|
||||||
|
Txlogisticid string `json:"txlogisticid"`
|
||||||
|
Ordertype int `json:"ordertype"`
|
||||||
|
Servicetype int `json:"servicetype"`
|
||||||
|
SelfAddress int `json:"selfAddress"`
|
||||||
|
Special string `json:"special"`
|
||||||
|
Partsign string `json:"partsign"`
|
||||||
|
Sender CreateOrderLocation `json:"sender"`
|
||||||
|
Receiver CreateOrderLocation `json:"receiver"`
|
||||||
|
Createordertime string `json:"createordertime"`
|
||||||
|
Sendstarttime string `json:"sendstarttime"`
|
||||||
|
Sendendtime string `json:"sendendtime"`
|
||||||
|
Paytype string `json:"paytype"`
|
||||||
|
Itemsvalue string `json:"itemsvalue"`
|
||||||
|
Goodsvalue string `json:"goodsvalue"`
|
||||||
|
IsInsured string `json:"isInsured"`
|
||||||
|
Items []OrderItem `json:"items"`
|
||||||
|
Weight string `json:"weight"`
|
||||||
|
Volume string `json:"volume"`
|
||||||
|
Remark string `json:"remark"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type CreateOrderLocation struct {
|
||||||
|
Name string `json:"name"`
|
||||||
|
Phone string `json:"phone"`
|
||||||
|
Mobile string `json:"mobile"`
|
||||||
|
Prov string `json:"prov"`
|
||||||
|
City string `json:"city"`
|
||||||
|
Area string `json:"area"`
|
||||||
|
Address string `json:"address"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type OrderItem struct {
|
||||||
|
Itemname string `json:"itemname"`
|
||||||
|
EnglishName string `json:"englishName"`
|
||||||
|
Number string `json:"number"`
|
||||||
|
Itemvalue string `json:"itemvalue"`
|
||||||
|
Desc string `json:"desc"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type CancelOrderReq struct {
|
||||||
|
Eccompanyid string `json:"eccompanyid"`
|
||||||
|
Customerid string `json:"customerid"`
|
||||||
|
Logisticproviderid string `json:"logisticproviderid"`
|
||||||
|
Fieldlist []CancelOrderFieldList `json:"fieldlist"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type CancelOrderFieldList struct {
|
||||||
|
Txlogisticid string `json:"txlogisticid"`
|
||||||
|
Fieldname string `json:"fieldname"`
|
||||||
|
Fieldvalue string `json:"fieldvalue"`
|
||||||
|
Remark string `json:"remark"`
|
||||||
|
}
|
|
@ -0,0 +1,62 @@
|
||||||
|
package jtexpress
|
||||||
|
|
||||||
|
type EstimateFeeItemRes struct {
|
||||||
|
ProductType string `json:"producttype"`
|
||||||
|
Price string `json:"price"`
|
||||||
|
CodFee string `json:"codfee"`
|
||||||
|
InsuranceFee string `json:"insurancefee"`
|
||||||
|
DiscountFee string `json:"discountFee"`
|
||||||
|
Success string `json:"success"`
|
||||||
|
Reason string `json:"reason"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type EstimateFeeRes struct {
|
||||||
|
LogisticProviderID string `json:"logisticproviderid"`
|
||||||
|
ResponseItems []*EstimateFeeItemRes `json:"responseitems"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type CreateOrderRes struct {
|
||||||
|
LogisticProviderID string `json:"logisticproviderid"`
|
||||||
|
ResponseItems []*CreateOrderItemRes `json:"responseitems"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type CreateOrderItemRes struct {
|
||||||
|
Billcode string `json:"billcode"`
|
||||||
|
CodFee string `json:"codFee"`
|
||||||
|
Code string `json:"code"`
|
||||||
|
DiscountFee string `json:"discountFee"`
|
||||||
|
DispatchSite string `json:"dispatchSite"`
|
||||||
|
InquiryFee string `json:"inquiryFee"`
|
||||||
|
Insurancefee string `json:"insurancefee"`
|
||||||
|
Reason string `json:"reason"`
|
||||||
|
Reportnewurl string `json:"reportnewurl"`
|
||||||
|
Reporturl string `json:"reporturl"`
|
||||||
|
ReporturlJT string `json:"reporturlJT"`
|
||||||
|
Success string `json:"success"`
|
||||||
|
Transport string `json:"transport"`
|
||||||
|
Txlogisticid string `json:"txlogisticid"`
|
||||||
|
SortLine string `json:"sortLine"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type CancelOrderRes struct {
|
||||||
|
LogisticProviderID string `json:"logisticproviderid"`
|
||||||
|
ResponseItems []*CreateOrderItemRes `json:"responseitems"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type Response struct {
|
||||||
|
Request RequestInfo
|
||||||
|
Response ResponseInfo
|
||||||
|
Error error
|
||||||
|
}
|
||||||
|
|
||||||
|
type ResponseInfo struct {
|
||||||
|
StatusCode int
|
||||||
|
Body []byte
|
||||||
|
}
|
||||||
|
|
||||||
|
type RequestInfo struct {
|
||||||
|
Method string
|
||||||
|
URL string
|
||||||
|
Headers map[string]string
|
||||||
|
Body []byte
|
||||||
|
}
|
|
@ -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"`
|
||||||
|
}
|
|
@ -0,0 +1,39 @@
|
||||||
|
package onpoint
|
||||||
|
|
||||||
|
const (
|
||||||
|
PaymentMethodCOD = "cod"
|
||||||
|
PaymentMethodBankTransfer = "bank_transfer"
|
||||||
|
PaymentMethodWallet = "wallet"
|
||||||
|
PaymentMethodFundiin = "fundiin"
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
CodeSuccess = "SUCCESS"
|
||||||
|
|
||||||
|
TimeLayout = "2006-01-02T15:04:05Z"
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
baseURLStaging = "https://dev-selly-api.onpoint.vn"
|
||||||
|
baseURLProd = "https://selly-api.onpoint.vn"
|
||||||
|
|
||||||
|
apiPathCreateOrder = "/v1/orders/create"
|
||||||
|
apiPathUpdateDelivery = "/v1/orders/update_delivery"
|
||||||
|
apiPathCancelOrder = "/v1/orders/cancel"
|
||||||
|
apiPathGetChannels = "/v1/channels"
|
||||||
|
apiPathGetInventories = "/v1/inventories"
|
||||||
|
|
||||||
|
headerXAPIKey = "x-api-key"
|
||||||
|
headerXTimestamp = "x-timestamp"
|
||||||
|
headerXSignature = "x-signature"
|
||||||
|
|
||||||
|
webhookEventUpdateOrderStatus = "UPDATE_ORDER_STATUS"
|
||||||
|
webhookEventUpdateInventory = "UPDATE_INVENTORY"
|
||||||
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
baseURLENVMapping = map[ENV]string{
|
||||||
|
EnvProd: baseURLProd,
|
||||||
|
EnvStaging: baseURLStaging,
|
||||||
|
}
|
||||||
|
)
|
|
@ -0,0 +1,9 @@
|
||||||
|
package onpoint
|
||||||
|
|
||||||
|
// ENV ...
|
||||||
|
type ENV string
|
||||||
|
|
||||||
|
const (
|
||||||
|
EnvStaging ENV = "STAGING"
|
||||||
|
EnvProd ENV = "PROD"
|
||||||
|
)
|
|
@ -0,0 +1,25 @@
|
||||||
|
package onpoint
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"strings"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Error ...
|
||||||
|
type Error struct {
|
||||||
|
Message string `json:"message"`
|
||||||
|
Code string `json:"code"`
|
||||||
|
Errors map[string][]string `json:"errors"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// Error ...
|
||||||
|
func (e Error) Error() string {
|
||||||
|
msg := fmt.Sprintf("onpoint_err: code %s, message: %s", e.Code, e.Message)
|
||||||
|
if len(e.Errors) > 0 {
|
||||||
|
msg += "\ndetail: "
|
||||||
|
for k, v := range e.Errors {
|
||||||
|
msg += fmt.Sprintf("field %s - error %s", k, strings.Join(v, ","))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return msg
|
||||||
|
}
|
|
@ -0,0 +1,116 @@
|
||||||
|
package onpoint
|
||||||
|
|
||||||
|
import (
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"git.selly.red/Selly-Modules/3pl/util/pjson"
|
||||||
|
)
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Request payload
|
||||||
|
*/
|
||||||
|
|
||||||
|
// CreateOrderRequest ...
|
||||||
|
type CreateOrderRequest struct {
|
||||||
|
StoreCode string `json:"store_code"`
|
||||||
|
DeliveryPlatform string `json:"delivery_platform"`
|
||||||
|
OrderCode string `json:"order_code"`
|
||||||
|
OrderDate time.Time `json:"order_date"`
|
||||||
|
PickupLocationCode string `json:"pickup_location_code"`
|
||||||
|
Note string `json:"note"`
|
||||||
|
SubtotalPrice int `json:"subtotal_price"`
|
||||||
|
TotalDiscounts int `json:"total_discounts"`
|
||||||
|
TotalPrice int `json:"total_price"`
|
||||||
|
PaymentMethod string `json:"payment_method"`
|
||||||
|
Items []OrderItem `json:"items"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// OrderItem ...
|
||||||
|
type OrderItem struct {
|
||||||
|
SellingPrice int `json:"selling_price"`
|
||||||
|
Quantity int `json:"quantity"`
|
||||||
|
Uom string `json:"uom"`
|
||||||
|
Amount int `json:"amount"`
|
||||||
|
Name string `json:"name"`
|
||||||
|
PartnerSku string `json:"sku"`
|
||||||
|
DiscountedPrice int `json:"discounted_price"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// UpdateOrderDeliveryRequest ...
|
||||||
|
type UpdateOrderDeliveryRequest struct {
|
||||||
|
OrderCode string `json:"order_code"` // required
|
||||||
|
DeliveryPlatform string `json:"delivery_platform"` // required
|
||||||
|
DeliveryTrackingNumber string `json:"delivery_tracking_number"`
|
||||||
|
DeliveryStatus string `json:"delivery_status"`
|
||||||
|
ShippingLabel string `json:"shipping_label"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// CancelOrderRequest ...
|
||||||
|
type CancelOrderRequest struct {
|
||||||
|
OrderNo string `json:"order_code"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type ListInventoriesReq struct {
|
||||||
|
UpdatedFrom time.Time
|
||||||
|
UpdatedTo time.Time
|
||||||
|
SKUList []string
|
||||||
|
Size int
|
||||||
|
Page int
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* WEBHOOK ONPOINT
|
||||||
|
*/
|
||||||
|
|
||||||
|
// WebhookDataUpdateInventory ...
|
||||||
|
type WebhookDataUpdateInventory struct {
|
||||||
|
Sku string `json:"sku"`
|
||||||
|
AvailableQuantity int `json:"available_quantity"`
|
||||||
|
PickupLocationCode string `json:"pickup_location_code"`
|
||||||
|
UpdatedAt time.Time `json:"updated_at"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// WebhookDataUpdateOrderStatus ...
|
||||||
|
type WebhookDataUpdateOrderStatus struct {
|
||||||
|
OrderCode string `json:"order_code"`
|
||||||
|
OnpointOrderCode string `json:"onpoint_order_code"`
|
||||||
|
Status string `json:"status"`
|
||||||
|
UpdatedAt string `json:"updated_at"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// WebhookPayload ...
|
||||||
|
type WebhookPayload struct {
|
||||||
|
Event string `json:"event"`
|
||||||
|
RequestedAt time.Time `json:"requested_at"`
|
||||||
|
Payload interface{} `json:"payload"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetDataEventUpdateOrderStatus ...
|
||||||
|
func (p WebhookPayload) GetDataEventUpdateOrderStatus() (data *WebhookDataUpdateOrderStatus, ok bool) {
|
||||||
|
if p.Event != webhookEventUpdateOrderStatus {
|
||||||
|
return nil, false
|
||||||
|
}
|
||||||
|
b, err := pjson.Marshal(p.Payload)
|
||||||
|
if err != nil {
|
||||||
|
return nil, false
|
||||||
|
}
|
||||||
|
if err = pjson.Unmarshal(b, &data); err != nil {
|
||||||
|
return nil, false
|
||||||
|
}
|
||||||
|
return data, true
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetDataEventUpdateInventory ...
|
||||||
|
func (p WebhookPayload) GetDataEventUpdateInventory() (data *WebhookDataUpdateInventory, ok bool) {
|
||||||
|
if p.Event != webhookEventUpdateInventory {
|
||||||
|
return nil, false
|
||||||
|
}
|
||||||
|
b, err := pjson.Marshal(p.Payload)
|
||||||
|
if err != nil {
|
||||||
|
return nil, false
|
||||||
|
}
|
||||||
|
if err = pjson.Unmarshal(b, &data); err != nil {
|
||||||
|
return nil, false
|
||||||
|
}
|
||||||
|
return data, true
|
||||||
|
}
|
|
@ -0,0 +1,69 @@
|
||||||
|
package onpoint
|
||||||
|
|
||||||
|
import "time"
|
||||||
|
|
||||||
|
// CreateOrderResponse ...
|
||||||
|
type CreateOrderResponse struct {
|
||||||
|
OrderCode string `json:"order_code"`
|
||||||
|
OnpointOrderCode string `json:"onpoint_order_code"`
|
||||||
|
OrderDate string `json:"order_date"`
|
||||||
|
Note string `json:"note"`
|
||||||
|
SubtotalPrice int `json:"subtotal_price"`
|
||||||
|
TotalDiscounts int `json:"total_discounts"`
|
||||||
|
TotalPrice int `json:"total_price"`
|
||||||
|
PaymentMethod string `json:"payment_method"`
|
||||||
|
DeliveryPlatform string `json:"delivery_platform"`
|
||||||
|
Status string `json:"status"`
|
||||||
|
UpdatedAt string `json:"updated_at"`
|
||||||
|
Items []OrderItem `json:"items"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// UpdateOrderDeliveryResponse ...
|
||||||
|
type UpdateOrderDeliveryResponse struct {
|
||||||
|
DeliveryPlatform string `json:"delivery_platform"`
|
||||||
|
DeliveryTrackingNumber string `json:"delivery_tracking_number"`
|
||||||
|
ShippingLabel string `json:"shipping_label"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// CancelOrderResponse ...
|
||||||
|
type CancelOrderResponse struct {
|
||||||
|
OrderNo string `json:"order_no"`
|
||||||
|
Status string `json:"status"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// ChannelResponse ...
|
||||||
|
type ChannelResponse struct {
|
||||||
|
Code string `json:"code"`
|
||||||
|
Name string `json:"name"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type ListInventoriesRes struct {
|
||||||
|
Code string `json:"code"`
|
||||||
|
Data struct {
|
||||||
|
Entries []InventoryEntry `json:"entries"`
|
||||||
|
Page int `json:"page"`
|
||||||
|
Size int `json:"size"`
|
||||||
|
TotalEntries int `json:"total_entries"`
|
||||||
|
TotalPages int `json:"total_pages"`
|
||||||
|
} `json:"data"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type InventoryEntry struct {
|
||||||
|
AvailableQuantity int `json:"available_quantity"`
|
||||||
|
PickupLocation Pickup `json:"pickup_location"`
|
||||||
|
Product Product `json:"product"`
|
||||||
|
UpdatedAt time.Time `json:"updated_at"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type Product struct {
|
||||||
|
Name string `json:"name"`
|
||||||
|
OriginalPrice int `json:"original_price"`
|
||||||
|
SellingPrice int `json:"selling_price"`
|
||||||
|
Sku string `json:"sku"`
|
||||||
|
Uom interface{} `json:"uom"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type Pickup struct {
|
||||||
|
Code string `json:"code"`
|
||||||
|
Name string `json:"name"`
|
||||||
|
}
|
|
@ -0,0 +1,247 @@
|
||||||
|
package onpoint
|
||||||
|
|
||||||
|
import (
|
||||||
|
"errors"
|
||||||
|
"fmt"
|
||||||
|
"net/http"
|
||||||
|
"net/url"
|
||||||
|
"strconv"
|
||||||
|
"strings"
|
||||||
|
"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"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Client ...
|
||||||
|
type Client struct {
|
||||||
|
env ENV
|
||||||
|
apiKey string
|
||||||
|
secretKey string
|
||||||
|
natsClient natsio.Server
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewClient generate OnPoint client
|
||||||
|
func NewClient(env ENV, apiKey, secretKey string, nc natsio.Server) (*Client, error) {
|
||||||
|
if apiKey == "" {
|
||||||
|
return nil, errors.New("onpoint: cannot init with empty api key")
|
||||||
|
}
|
||||||
|
return &Client{
|
||||||
|
env: env,
|
||||||
|
apiKey: apiKey,
|
||||||
|
secretKey: secretKey,
|
||||||
|
natsClient: nc,
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// CreateOrder ...
|
||||||
|
func (c *Client) CreateOrder(p CreateOrderRequest) (*CreateOrderResponse, error) {
|
||||||
|
url := c.getBaseURL() + apiPathCreateOrder
|
||||||
|
natsPayload := model.CommunicationRequestHttp{
|
||||||
|
ResponseImmediately: true,
|
||||||
|
Payload: model.HttpRequest{
|
||||||
|
URL: url,
|
||||||
|
Method: http.MethodPost,
|
||||||
|
Data: pjson.ToJSONString(p),
|
||||||
|
},
|
||||||
|
}
|
||||||
|
var (
|
||||||
|
r model.CommunicationHttpResponse
|
||||||
|
errRes Error
|
||||||
|
dataRes struct {
|
||||||
|
Code string `json:"code"`
|
||||||
|
Data CreateOrderResponse `json:"data"`
|
||||||
|
}
|
||||||
|
)
|
||||||
|
if err := c.requestHttpViaNats(natsPayload, &r); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
res := r.Response
|
||||||
|
if res == nil {
|
||||||
|
return nil, fmt.Errorf("onpoint.Client.CreateOrder: empty_response")
|
||||||
|
}
|
||||||
|
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, 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 &dataRes.Data, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// UpdateDelivery ...
|
||||||
|
func (c *Client) UpdateDelivery(p UpdateOrderDeliveryRequest) (*UpdateOrderDeliveryResponse, error) {
|
||||||
|
url := c.getBaseURL() + apiPathUpdateDelivery
|
||||||
|
natsPayload := model.CommunicationRequestHttp{
|
||||||
|
ResponseImmediately: true,
|
||||||
|
Payload: model.HttpRequest{
|
||||||
|
URL: url,
|
||||||
|
Method: http.MethodPost,
|
||||||
|
Data: pjson.ToJSONString(p),
|
||||||
|
},
|
||||||
|
}
|
||||||
|
var (
|
||||||
|
r model.CommunicationHttpResponse
|
||||||
|
errRes Error
|
||||||
|
dataRes struct {
|
||||||
|
Data UpdateOrderDeliveryResponse `json:"data"`
|
||||||
|
}
|
||||||
|
)
|
||||||
|
if err := c.requestHttpViaNats(natsPayload, &r); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
res := r.Response
|
||||||
|
if res == nil {
|
||||||
|
return nil, fmt.Errorf("onpoint.Client.UpdateDelivery: empty_response")
|
||||||
|
}
|
||||||
|
if res.StatusCode >= http.StatusBadRequest {
|
||||||
|
if err := r.ParseResponseData(&errRes); err != nil {
|
||||||
|
return nil, fmt.Errorf("onpoint.Client.UpdateDelivery: parse_response_err: %v", err)
|
||||||
|
}
|
||||||
|
return nil, errRes
|
||||||
|
}
|
||||||
|
if err := r.ParseResponseData(&dataRes); err != nil {
|
||||||
|
return nil, fmt.Errorf("onpoint.Client.UpdateDelivery: parse_response_data: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return &dataRes.Data, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// CancelOrder ...
|
||||||
|
func (c *Client) CancelOrder(p CancelOrderRequest) (*CancelOrderResponse, error) {
|
||||||
|
url := c.getBaseURL() + apiPathCancelOrder
|
||||||
|
natsPayload := model.CommunicationRequestHttp{
|
||||||
|
ResponseImmediately: true,
|
||||||
|
Payload: model.HttpRequest{
|
||||||
|
URL: url,
|
||||||
|
Method: http.MethodPost,
|
||||||
|
Data: pjson.ToJSONString(p),
|
||||||
|
},
|
||||||
|
}
|
||||||
|
var (
|
||||||
|
r model.CommunicationHttpResponse
|
||||||
|
errRes Error
|
||||||
|
dataRes struct {
|
||||||
|
Data CancelOrderResponse `json:"data"`
|
||||||
|
}
|
||||||
|
)
|
||||||
|
if err := c.requestHttpViaNats(natsPayload, &r); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
res := r.Response
|
||||||
|
if res == nil {
|
||||||
|
return nil, fmt.Errorf("onpoint.Client.CancelOrder: empty_response")
|
||||||
|
}
|
||||||
|
if res.StatusCode >= http.StatusBadRequest {
|
||||||
|
if err := r.ParseResponseData(&errRes); err != nil {
|
||||||
|
return nil, fmt.Errorf("onpoint.Client.CancelOrder: parse_response_err: %v", err)
|
||||||
|
}
|
||||||
|
return nil, errRes
|
||||||
|
}
|
||||||
|
if err := r.ParseResponseData(&dataRes); err != nil {
|
||||||
|
return nil, fmt.Errorf("onpoint.Client.CancelOrder: parse_response_data: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return &dataRes.Data, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetInventories ...
|
||||||
|
func (c *Client) GetInventories(req ListInventoriesReq) (*ListInventoriesRes, error) {
|
||||||
|
url := c.getBaseURL() + apiPathGetInventories
|
||||||
|
q := map[string]string{}
|
||||||
|
if !req.UpdatedFrom.IsZero() {
|
||||||
|
q["updated_from"] = req.UpdatedFrom.Format(TimeLayout)
|
||||||
|
}
|
||||||
|
if !req.UpdatedTo.IsZero() {
|
||||||
|
q["updated_to"] = req.UpdatedTo.Format(TimeLayout)
|
||||||
|
}
|
||||||
|
if len(req.SKUList) > 0 {
|
||||||
|
q["sku_list"] = strings.Join(req.SKUList, ",")
|
||||||
|
}
|
||||||
|
if req.Page > 0 {
|
||||||
|
q["page"] = strconv.Itoa(req.Page)
|
||||||
|
}
|
||||||
|
if req.Size > 0 {
|
||||||
|
q["size"] = strconv.Itoa(req.Size)
|
||||||
|
}
|
||||||
|
natsPayload := model.CommunicationRequestHttp{
|
||||||
|
ResponseImmediately: true,
|
||||||
|
Payload: model.HttpRequest{
|
||||||
|
URL: url,
|
||||||
|
Method: http.MethodGet,
|
||||||
|
Query: q,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
var (
|
||||||
|
r model.CommunicationHttpResponse
|
||||||
|
errRes Error
|
||||||
|
dataRes ListInventoriesRes
|
||||||
|
)
|
||||||
|
if err := c.requestHttpViaNats(natsPayload, &r); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
res := r.Response
|
||||||
|
if res == nil {
|
||||||
|
return nil, fmt.Errorf("onpoint.Client.GetInventories: empty_response")
|
||||||
|
}
|
||||||
|
if res.StatusCode >= http.StatusBadRequest {
|
||||||
|
if err := r.ParseResponseData(&errRes); err != nil {
|
||||||
|
return nil, fmt.Errorf("onpoint.Client.GetInventories: parse_response_err: %v", err)
|
||||||
|
}
|
||||||
|
return nil, errRes
|
||||||
|
}
|
||||||
|
if err := r.ParseResponseData(&dataRes); err != nil {
|
||||||
|
return nil, fmt.Errorf("onpoint.Client.GetInventories: parse_response_data: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return &dataRes, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *Client) requestHttpViaNats(data model.CommunicationRequestHttp, res interface{}) error {
|
||||||
|
ec, err := c.natsClient.NewJSONEncodedConn()
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("onpoint: request via nats %v", err)
|
||||||
|
}
|
||||||
|
u, err := url.ParseRequestURI(data.Payload.URL)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("onpoint: request via nats %v", err)
|
||||||
|
}
|
||||||
|
q := u.Query()
|
||||||
|
for k, v := range data.Payload.Query {
|
||||||
|
q.Set(k, v)
|
||||||
|
}
|
||||||
|
u.RawQuery = q.Encode()
|
||||||
|
|
||||||
|
now := time.Now().Unix()
|
||||||
|
ts := strconv.FormatInt(now, 10)
|
||||||
|
arr := []string{
|
||||||
|
u.RawQuery,
|
||||||
|
data.Payload.Data,
|
||||||
|
ts,
|
||||||
|
}
|
||||||
|
s := strings.Join(arr, ".")
|
||||||
|
// sign data
|
||||||
|
sign := hashSHA256AndUppercase(s, c.secretKey)
|
||||||
|
data.Payload.Header = map[string]string{
|
||||||
|
headerXAPIKey: c.apiKey,
|
||||||
|
headerXSignature: sign,
|
||||||
|
headerXTimestamp: ts,
|
||||||
|
httputil.HeaderKeyContentType: httputil.HeaderValueApplicationJSON,
|
||||||
|
}
|
||||||
|
data.Payload.Query = map[string]string{}
|
||||||
|
data.Payload.URL = u.String()
|
||||||
|
|
||||||
|
return ec.Request(subject.Communication.RequestHTTP, data, res)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *Client) getBaseURL() string {
|
||||||
|
return baseURLENVMapping[c.env]
|
||||||
|
}
|
|
@ -0,0 +1,18 @@
|
||||||
|
package onpoint
|
||||||
|
|
||||||
|
const (
|
||||||
|
OrderStatusNew = "new"
|
||||||
|
OrderStatusPendingWarehouse = "pending_warehouse"
|
||||||
|
OrderStatusWhPending = "wh_pending"
|
||||||
|
OrderStatusWhProcessing = "wh_processing"
|
||||||
|
OrderStatusWhCompleted = "wh_completed"
|
||||||
|
OrderStatusDlPending = "dl_pending"
|
||||||
|
OrderStatusDlIntransit = "dl_intransit"
|
||||||
|
OrderStatusDLDelivered = "dl_delivered"
|
||||||
|
OrderStatusDLReturning = "dl_returning"
|
||||||
|
OrderStatusReturned = "returned"
|
||||||
|
OrderStatusPartialCancelled = "partial_cancelled"
|
||||||
|
OrderStatusCancelled = "cancelled"
|
||||||
|
OrderStatusCompleted = "completed"
|
||||||
|
OrderStatusUnknown = "unknown"
|
||||||
|
)
|
|
@ -0,0 +1,18 @@
|
||||||
|
package onpoint
|
||||||
|
|
||||||
|
import (
|
||||||
|
"crypto/hmac"
|
||||||
|
"crypto/sha256"
|
||||||
|
"encoding/hex"
|
||||||
|
"strings"
|
||||||
|
)
|
||||||
|
|
||||||
|
func hashSHA256(data, key string) string {
|
||||||
|
h := hmac.New(sha256.New, []byte(key))
|
||||||
|
h.Write([]byte(data))
|
||||||
|
return hex.EncodeToString(h.Sum(nil))
|
||||||
|
}
|
||||||
|
|
||||||
|
func hashSHA256AndUppercase(data, key string) string {
|
||||||
|
return strings.ToUpper(hashSHA256(data, key))
|
||||||
|
}
|
|
@ -15,7 +15,7 @@ const (
|
||||||
|
|
||||||
TPLCodeGHN = "GHN"
|
TPLCodeGHN = "GHN"
|
||||||
TPLCodeGHTK = "GHTK"
|
TPLCodeGHTK = "GHTK"
|
||||||
TPLCodeBest = "BEST"
|
TPLCodeBest = "BEX"
|
||||||
TPLCodeSnappy = "SPY"
|
TPLCodeSnappy = "SPY"
|
||||||
TPLCodeViettelPost = "VTP"
|
TPLCodeViettelPost = "VTP"
|
||||||
TPLCodeSellyExpress = "SE"
|
TPLCodeSellyExpress = "SE"
|
||||||
|
@ -30,11 +30,11 @@ const (
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
baseURLAuthStaging = "https://auth.stg.tnclog.vn"
|
baseURLAuthStaging = "https://auth.stg.vnfai.com"
|
||||||
baseURLStaging = "https://ext-api.stg.tnclog.vn"
|
baseURLStaging = "https://ext.stg.vnfai.com"
|
||||||
|
|
||||||
baseURLAuthProd = "https://auth.tnclog.vn"
|
baseURLAuthProd = "https://auth.vnfai.com"
|
||||||
baseURLProd = "https://ext-api.tnclog.vn"
|
baseURLProd = "https://ext-api.vnfai.com"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
|
|
|
@ -45,8 +45,14 @@ type OutboundRequestPayload struct {
|
||||||
|
|
||||||
// UpdateORLogisticInfoPayload ...
|
// UpdateORLogisticInfoPayload ...
|
||||||
type UpdateORLogisticInfoPayload struct {
|
type UpdateORLogisticInfoPayload struct {
|
||||||
OrID int `json:"orId"`
|
OrID int `json:"orId"`
|
||||||
TrackingCode string `json:"trackingCode"`
|
|
||||||
ShippingLabel string `json:"shippingLabel"`
|
TPLCode string `json:"tplCode"`
|
||||||
SlaShipDate string `json:"slaShipDate"`
|
TrackingCode string `json:"trackingCode"`
|
||||||
|
ShippingLabels []LogisticInfoLabel `json:"shippingLabels"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type LogisticInfoLabel struct {
|
||||||
|
Caption string `json:"caption"`
|
||||||
|
URI string `json:"uri"`
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,13 +6,14 @@ import (
|
||||||
"net/url"
|
"net/url"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/Selly-Modules/logger"
|
"git.selly.red/Selly-Modules/logger"
|
||||||
"github.com/Selly-Modules/natsio"
|
"git.selly.red/Selly-Modules/natsio"
|
||||||
"github.com/Selly-Modules/natsio/model"
|
"git.selly.red/Selly-Modules/natsio/model"
|
||||||
"github.com/Selly-Modules/natsio/subject"
|
"git.selly.red/Selly-Modules/natsio/subject"
|
||||||
"github.com/nats-io/nats.go"
|
"github.com/nats-io/nats.go"
|
||||||
|
|
||||||
"github.com/Selly-Modules/3pl/util/pjson"
|
"git.selly.red/Selly-Modules/3pl/util/httputil"
|
||||||
|
"git.selly.red/Selly-Modules/3pl/util/pjson"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Client ...
|
// Client ...
|
||||||
|
@ -66,7 +67,6 @@ func (c *Client) CreateOutboundRequest(p OutboundRequestPayload) (*OutboundReque
|
||||||
}
|
}
|
||||||
var (
|
var (
|
||||||
r model.CommunicationHttpResponse
|
r model.CommunicationHttpResponse
|
||||||
errRes Error
|
|
||||||
dataRes []OutboundRequestRes
|
dataRes []OutboundRequestRes
|
||||||
)
|
)
|
||||||
if err = pjson.Unmarshal(msg.Data, &r); err != nil {
|
if err = pjson.Unmarshal(msg.Data, &r); err != nil {
|
||||||
|
@ -77,6 +77,7 @@ func (c *Client) CreateOutboundRequest(p OutboundRequestPayload) (*OutboundReque
|
||||||
return nil, fmt.Errorf("tnc.Client.CreateOutboundRequest: empty_response")
|
return nil, fmt.Errorf("tnc.Client.CreateOutboundRequest: empty_response")
|
||||||
}
|
}
|
||||||
if res.StatusCode >= http.StatusBadRequest {
|
if res.StatusCode >= http.StatusBadRequest {
|
||||||
|
var errRes Error
|
||||||
if err = r.ParseResponseData(&errRes); err != nil {
|
if err = r.ParseResponseData(&errRes); err != nil {
|
||||||
return nil, fmt.Errorf("tnc.Client.CreateOutboundRequest: parse_response_err: %v", err)
|
return nil, fmt.Errorf("tnc.Client.CreateOutboundRequest: parse_response_err: %v", err)
|
||||||
}
|
}
|
||||||
|
@ -91,7 +92,7 @@ func (c *Client) CreateOutboundRequest(p OutboundRequestPayload) (*OutboundReque
|
||||||
item := &dataRes[0]
|
item := &dataRes[0]
|
||||||
e := item.Error
|
e := item.Error
|
||||||
if e != nil {
|
if e != nil {
|
||||||
return nil, errRes
|
return nil, e
|
||||||
}
|
}
|
||||||
|
|
||||||
return item, err
|
return item, err
|
||||||
|
@ -230,7 +231,7 @@ func (c *Client) auth() (*authRes, error) {
|
||||||
|
|
||||||
body := v.Encode()
|
body := v.Encode()
|
||||||
header := map[string]string{
|
header := map[string]string{
|
||||||
"Content-Type": "application/x-www-form-urlencoded",
|
httputil.HeaderKeyContentType: httputil.HeaderValueApplicationURLEncoded,
|
||||||
}
|
}
|
||||||
apiURL := baseURLAuthENVMapping[c.env] + fmt.Sprintf(apiPathAuth, c.realm)
|
apiURL := baseURLAuthENVMapping[c.env] + fmt.Sprintf(apiPathAuth, c.realm)
|
||||||
natsPayload := model.CommunicationRequestHttp{
|
natsPayload := model.CommunicationRequestHttp{
|
||||||
|
@ -276,7 +277,7 @@ func (c *Client) auth() (*authRes, error) {
|
||||||
|
|
||||||
func (c *Client) getRequestHeader() map[string]string {
|
func (c *Client) getRequestHeader() map[string]string {
|
||||||
m := map[string]string{
|
m := map[string]string{
|
||||||
"Content-Type": "application/json",
|
httputil.HeaderKeyContentType: httputil.HeaderValueApplicationJSON,
|
||||||
}
|
}
|
||||||
token, err := c.getToken()
|
token, err := c.getToken()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
|
@ -0,0 +1,80 @@
|
||||||
|
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"`
|
||||||
|
OrCode string `json:"or_code,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type CancelORPayload struct {
|
||||||
|
OrID int `json:"or_id"`
|
||||||
|
}
|
||||||
|
|
||||||
|
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"`
|
||||||
|
PartnerORCode string `json:"partner_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"`
|
||||||
|
WarehouseCode string `json:"warehouse_code"`
|
||||||
|
}
|
||||||
|
|
||||||
|
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"`
|
||||||
|
SKU string `json:"sku"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type ProdCondType struct {
|
||||||
|
Name string `json:"name"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type ORResult struct {
|
||||||
|
OrCode string `json:"or_code"`
|
||||||
|
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"`
|
||||||
|
}
|
|
@ -0,0 +1,232 @@
|
||||||
|
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://dev-wms-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-integration/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
|
||||||
|
}
|
|
@ -0,0 +1,9 @@
|
||||||
|
package httputil
|
||||||
|
|
||||||
|
const (
|
||||||
|
HeaderKeyContentType = "Content-Type"
|
||||||
|
HeaderKeyAuthorization = "Authorization"
|
||||||
|
|
||||||
|
HeaderValueApplicationJSON = "application/json"
|
||||||
|
HeaderValueApplicationURLEncoded = "application/x-www-form-urlencoded"
|
||||||
|
)
|
|
@ -3,7 +3,7 @@ package pjson
|
||||||
import (
|
import (
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
|
|
||||||
"github.com/Selly-Modules/logger"
|
"git.selly.red/Selly-Modules/logger"
|
||||||
)
|
)
|
||||||
|
|
||||||
// ToBytes ...
|
// ToBytes ...
|
||||||
|
|
|
@ -0,0 +1,15 @@
|
||||||
|
package pjson
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/json"
|
||||||
|
"log"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Marshal ...
|
||||||
|
func Marshal(data interface{}) ([]byte, error) {
|
||||||
|
b, err := json.Marshal(data)
|
||||||
|
if err != nil {
|
||||||
|
log.Printf("3pl/util/pjson.Marshal: err %v, payload %v", err, data)
|
||||||
|
}
|
||||||
|
return b, err
|
||||||
|
}
|
|
@ -2,18 +2,14 @@ package pjson
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
|
"log"
|
||||||
"github.com/Selly-Modules/logger"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// Unmarshal ...
|
// Unmarshal ...
|
||||||
func Unmarshal(b []byte, resultP interface{}) error {
|
func Unmarshal(b []byte, resultP interface{}) error {
|
||||||
err := json.Unmarshal(b, resultP)
|
err := json.Unmarshal(b, resultP)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logger.Error("pjson.Unmarshal", logger.LogData{
|
log.Printf("3pl/util/pjson.Unmarshal: err %v, payload %s", err, string(b))
|
||||||
"raw": string(b),
|
|
||||||
"err": err.Error(),
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue