From cc5b0ce75a58572c20bcb35cb996573105c5b60e Mon Sep 17 00:00:00 2001
From: huangjiajun <582604932@qq.com>
Date: Fri, 26 Aug 2022 13:35:11 +0800
Subject: [PATCH] =?UTF-8?q?add=20reverse:for=20v1.0.0=20=E6=9B=B4=E6=96=B0?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
.idea/.gitignore | 8 +
.idea/modules.xml | 8 +
.idea/vcs.xml | 6 +
.idea/zyos_go_third_party_api.iml | 9 +
go.mod | 9 +
go.sum | 8 +
tik_tok/api.go | 115 ++++++++++
tik_tok/md_tik_tok_goods.go | 27 +++
tik_tok/svc_tik_tok_auth.go | 39 ++++
tik_tok/svc_tik_tok_convert.go | 89 ++++++++
tik_tok/svc_tik_tok_goods.go | 142 ++++++++++++
tik_tok/svc_tik_tok_live.go | 58 +++++
tik_tok/svc_tik_tok_order.go | 148 ++++++++++++
tik_tok/tik_tok_test.go | 9 +
utils/convert.go | 366 ++++++++++++++++++++++++++++++
utils/curl.go | 231 +++++++++++++++++++
utils/serialize.go | 23 ++
utils/time.go | 233 +++++++++++++++++++
18 files changed, 1528 insertions(+)
create mode 100644 .idea/.gitignore
create mode 100644 .idea/modules.xml
create mode 100644 .idea/vcs.xml
create mode 100644 .idea/zyos_go_third_party_api.iml
create mode 100644 go.mod
create mode 100644 go.sum
create mode 100644 tik_tok/api.go
create mode 100644 tik_tok/md_tik_tok_goods.go
create mode 100644 tik_tok/svc_tik_tok_auth.go
create mode 100644 tik_tok/svc_tik_tok_convert.go
create mode 100644 tik_tok/svc_tik_tok_goods.go
create mode 100644 tik_tok/svc_tik_tok_live.go
create mode 100644 tik_tok/svc_tik_tok_order.go
create mode 100644 tik_tok/tik_tok_test.go
create mode 100644 utils/convert.go
create mode 100644 utils/curl.go
create mode 100644 utils/serialize.go
create mode 100644 utils/time.go
diff --git a/.idea/.gitignore b/.idea/.gitignore
new file mode 100644
index 0000000..35410ca
--- /dev/null
+++ b/.idea/.gitignore
@@ -0,0 +1,8 @@
+# 默认忽略的文件
+/shelf/
+/workspace.xml
+# 基于编辑器的 HTTP 客户端请求
+/httpRequests/
+# Datasource local storage ignored files
+/dataSources/
+/dataSources.local.xml
diff --git a/.idea/modules.xml b/.idea/modules.xml
new file mode 100644
index 0000000..5f6ea10
--- /dev/null
+++ b/.idea/modules.xml
@@ -0,0 +1,8 @@
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/vcs.xml b/.idea/vcs.xml
new file mode 100644
index 0000000..94a25f7
--- /dev/null
+++ b/.idea/vcs.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/zyos_go_third_party_api.iml b/.idea/zyos_go_third_party_api.iml
new file mode 100644
index 0000000..5e764c4
--- /dev/null
+++ b/.idea/zyos_go_third_party_api.iml
@@ -0,0 +1,9 @@
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/go.mod b/go.mod
new file mode 100644
index 0000000..dab7a94
--- /dev/null
+++ b/go.mod
@@ -0,0 +1,9 @@
+module code.fnuoos.com/go_rely_warehouse/zyos_go_third_party_api.git
+
+go 1.15
+
+require (
+github.com/syyongx/php2go v0.9.7
+ github.com/tidwall/gjson v1.14.1
+
+)
diff --git a/go.sum b/go.sum
new file mode 100644
index 0000000..c7570e6
--- /dev/null
+++ b/go.sum
@@ -0,0 +1,8 @@
+github.com/syyongx/php2go v0.9.7 h1:boZtLbm2xYbW49mX9M7Vq2zkVhBhv3fCqs2T16d2bGA=
+github.com/syyongx/php2go v0.9.7/go.mod h1:meN2eIhhUoxOd2nMxbpe8g6cFPXI5O9/UAAuz7oDdzw=
+github.com/tidwall/gjson v1.14.1 h1:iymTbGkQBhveq21bEvAQ81I0LEBork8BFe1CUZXdyuo=
+github.com/tidwall/gjson v1.14.1/go.mod h1:/wbyibRr2FHMks5tjHJ5F8dMZh3AcwJEMf5vlfC0lxk=
+github.com/tidwall/match v1.1.1 h1:+Ho715JplO36QYgwN9PGYNhgZvoUSc9X2c80KVTi+GA=
+github.com/tidwall/match v1.1.1/go.mod h1:eRSPERbgtNPcGhD8UCthc6PmLEQXEWd3PRB5JTxsfmM=
+github.com/tidwall/pretty v1.2.0 h1:RWIZEg2iJ8/g6fDDYzMpobmaoGh5OLl4AXtGUGPcqCs=
+github.com/tidwall/pretty v1.2.0/go.mod h1:ITEVvHYasfjBbM0u2Pg8T2nJnzm8xPwvNhhsoaGGjNU=
diff --git a/tik_tok/api.go b/tik_tok/api.go
new file mode 100644
index 0000000..875f14f
--- /dev/null
+++ b/tik_tok/api.go
@@ -0,0 +1,115 @@
+package tik_tok
+
+import (
+ "bytes"
+ zhios_third_party_utils "code.fnuoos.com/go_rely_warehouse/zyos_go_third_party_api.git/utils"
+ "crypto/hmac"
+ "crypto/sha256"
+ "encoding/hex"
+ "encoding/json"
+ "github.com/syyongx/php2go"
+ "sort"
+ "strings"
+ "time"
+)
+
+func Send(appkey, appSecret, method string, params map[string]interface{}, acctoken string) (string, error) {
+ methodPath := strings.ReplaceAll(method, ".", "/")
+ url := "https://openapi-fxg.jinritemai.com/" + methodPath
+ paramJson := GetSortJson(params)
+ paramJson = strings.ReplaceAll(paramJson, "\n", "")
+ param := map[string]string{
+ "app_key": appkey,
+ "method": method,
+ "param_json": paramJson,
+ "timestamp": zhios_third_party_utils.Int64ToStr(time.Now().Unix()),
+ "v": "2",
+ }
+ sign := GetSign(appSecret, param)
+ if acctoken != "" {
+ param["access_token"] = acctoken
+ }
+ param["sign"] = sign
+ param["sign_method"] = "hmac-sha256"
+ for k, v := range param {
+ if strings.Contains(url, "?") {
+ url += "&" + k + "=" + php2go.URLEncode(v)
+ } else {
+ url += "?" + k + "=" + php2go.URLEncode(v)
+ }
+ }
+ data, err := zhios_third_party_utils.CurlPost(url, paramJson, nil)
+ return string(data), err
+}
+func GetSign(appSecret string, param map[string]string) string {
+ str := ""
+ keys := KsortToStr(param)
+ for _, k := range keys {
+ str += k + param[k]
+ }
+ signStr := appSecret + str + appSecret
+ h := hmac.New(sha256.New, []byte(appSecret))
+ _, _ = h.Write([]byte(signStr))
+ return hex.EncodeToString(h.Sum(nil))
+}
+func Ksort(params map[string]interface{}) []string {
+ keys := make([]string, len(params))
+ i := 0
+ for k, _ := range params {
+ keys[i] = k
+ i++
+ }
+ sort.Strings(keys)
+ return keys
+}
+func KsortToStr(params map[string]string) []string {
+ keys := make([]string, len(params))
+ i := 0
+ for k, _ := range params {
+ keys[i] = k
+ i++
+ }
+ sort.Strings(keys)
+ return keys
+}
+
+//func GetSortJson(params map[string]interface{}) string {
+// // 排序
+// keys := Ksort(params)
+// for _, k := range keys {
+// fmt.Println(k)
+// }
+//
+// byteBuf := bytes.NewBuffer([]byte{})
+// encoder := json.NewEncoder(byteBuf)
+// // 特殊字符不转义
+// encoder.SetEscapeHTML(false)
+// err := encoder.Encode(params)
+// if err != nil {
+// panic(err)
+// }
+// data := byteBuf.String()
+// return data
+//}
+
+// Marshal 序列化参数
+func GetSortJson(o interface{}) string {
+ // 序列化一次
+ raw, _ := json.Marshal(o)
+
+ // 反序列化为map
+ m := make(map[string]interface{})
+ reader := bytes.NewReader(raw)
+ decode := json.NewDecoder(reader)
+ decode.UseNumber()
+ _ = decode.Decode(&m)
+
+ // 重新做一次序列化,并禁用Html Escape
+ buffer := bytes.NewBufferString("")
+ encoder := json.NewEncoder(buffer)
+ encoder.SetEscapeHTML(false)
+ _ = encoder.Encode(m)
+
+ marshal := strings.TrimSpace(buffer.String()) // Trim掉末尾的换行符
+ return marshal
+}
diff --git a/tik_tok/md_tik_tok_goods.go b/tik_tok/md_tik_tok_goods.go
new file mode 100644
index 0000000..82e767d
--- /dev/null
+++ b/tik_tok/md_tik_tok_goods.go
@@ -0,0 +1,27 @@
+package tik_tok
+
+type TikTokGoods struct {
+ Commission string `json:"commission"`
+ CostPrice string `json:"cost_price"`
+ DetailURL string `json:"detail_url"`
+ GoodsID string `json:"goods_id"`
+ GoodsImg string `json:"goods_img"`
+ GoodsSales string `json:"goods_sales"`
+ GoodsTitle string `json:"goods_title"`
+ Imgs []interface{} `json:"imgs"`
+ InStock string `json:"in_stock"`
+ Price string `json:"price"`
+ Sharable string `json:"sharable"`
+ ShopID string `json:"shop_id"`
+ ShopName string `json:"shop_name"`
+ ShopTotalScore string `json:"shop_total_score"`
+ YhqPrice string `json:"yhq_price"`
+}
+type TikTokLive struct {
+ LiveId string `json:"live_id"`
+ Name string `json:"name"`
+ HeadImg string `json:"head_img"`
+ FansNum string `json:"fans_num"`
+ IsLive string `json:"is_live"`
+ Pvd string `json:"pvd"`
+}
diff --git a/tik_tok/svc_tik_tok_auth.go b/tik_tok/svc_tik_tok_auth.go
new file mode 100644
index 0000000..5af8c85
--- /dev/null
+++ b/tik_tok/svc_tik_tok_auth.go
@@ -0,0 +1,39 @@
+package tik_tok
+
+import (
+ zhios_third_party_utils "code.fnuoos.com/go_rely_warehouse/zyos_go_third_party_api.git/utils"
+ "github.com/tidwall/gjson"
+ "time"
+)
+
+//第一次授权
+func FirstAuth(args map[string]string) map[string]string {
+ params := map[string]interface{}{"code": args["code"], "grant_type": args["grantType"]}
+ send, err := Send(args["appkey"], args["appSecret"], "token.create", params, args["acctoken"])
+ var data = map[string]string{}
+ if err != nil {
+ return data
+ }
+ endTime := time.Now().Unix() + gjson.Get(send, "data.expires_in").Int() - 10
+ data = map[string]string{
+ "tik_tok_acc_token": gjson.Get(send, "data.access_token").String(),
+ "tik_tok_acc_token_time": zhios_third_party_utils.Int64ToStr(endTime),
+ "tik_tok_acc_refresh_token": gjson.Get(send, "data.refresh_token").String(),
+ }
+ return data
+}
+func RefreshAuth(args map[string]string) map[string]string {
+ params := map[string]interface{}{"refresh_token": args["refresh_token"], "grant_type": "refresh_token"}
+ send, err := Send(args["appkey"], args["appSecret"], "token.refresh", params, args["acctoken"])
+ var data = map[string]string{}
+ if err != nil {
+ return data
+ }
+ endTime := time.Now().Unix() + gjson.Get(send, "data.expires_in").Int() - 10
+ data = map[string]string{
+ "tik_tok_acc_token": gjson.Get(send, "data.access_token").String(),
+ "tik_tok_acc_token_time": zhios_third_party_utils.Int64ToStr(endTime),
+ "tik_tok_acc_refresh_token": gjson.Get(send, "data.refresh_token").String(),
+ }
+ return data
+}
diff --git a/tik_tok/svc_tik_tok_convert.go b/tik_tok/svc_tik_tok_convert.go
new file mode 100644
index 0000000..08e7459
--- /dev/null
+++ b/tik_tok/svc_tik_tok_convert.go
@@ -0,0 +1,89 @@
+package tik_tok
+
+import (
+ "fmt"
+ "github.com/syyongx/php2go"
+ "github.com/tidwall/gjson"
+)
+
+//创建推广位
+func GoodsCreatePid(args map[string]string) map[string]string {
+ //args = map[string]string{
+ // "appkey": "7076371480799348261",
+ // "appSecret": "9e58409e-5729-441e-a9f3-c077ec939fbb",
+ // "acctoken": "52f7ea67-5267-4874-9e05-a837dd1d6a48",
+ // "media_name": "测试",
+ // "site_name": "测试",
+ //}
+ params := map[string]interface{}{"media_type": "4", "media_name": args["media_name"], "site_name": args["site_name"]}
+ send, err := Send(args["appkey"], args["appSecret"], "buyin.kolPidCreate", params, args["acctoken"])
+ fmt.Println(send)
+ var data = map[string]string{}
+ if err != nil {
+ return data
+ }
+ data["pid"] = gjson.Get(send, "data.pid").String()
+ return data
+}
+func GoodsConvertUrl(args map[string]string) map[string]string {
+ //args = map[string]string{
+ // "appkey": "7076371480799348261",
+ // "appSecret": "9e58409e-5729-441e-a9f3-c077ec939fbb",
+ // "acctoken": "52f7ea67-5267-4874-9e05-a837dd1d6a48",
+ // "external_info": "123",
+ // "pid": "dy_107018934375430799627_13603_920074249",
+ // "product_url": "https://haohuo.jinritemai.com/views/product/item2?id=3378039360158085752",
+ //}
+ params := map[string]interface{}{"pid": args["pid"], "external_info": args["external_info"], "product_url": args["product_url"]}
+ send, err := Send(args["appkey"], args["appSecret"], "buyin.kolProductShare", params, args["acctoken"])
+ fmt.Println(send)
+ var data = map[string]string{}
+ if err != nil {
+ return data
+ }
+ data["deeplink"] = gjson.Get(send, "data.dy_deeplink").String()
+ data["content"] = php2go.Base64Encode(gjson.Get(send, "data.dy_password").String())
+ data["qr_code"] = gjson.Get(send, "data.qr_code.url").String()
+
+ return data
+}
+func LiveCreatePid(args map[string]string) map[string]string {
+ //args = map[string]string{
+ // "appkey": "7076371480799348261",
+ // "appSecret": "9e58409e-5729-441e-a9f3-c077ec939fbb",
+ // "acctoken": "52f7ea67-5267-4874-9e05-a837dd1d6a48",
+ // "media_name": "测试",
+ // "site_name": "测试",
+ //}
+ params := map[string]interface{}{"media_type": "4", "media_name": args["media_name"], "site_name": args["site_name"]}
+ send, err := Send(args["appkey"], args["appSecret"], "buyin.institutePidCreate", params, args["acctoken"])
+ fmt.Println(send)
+ var data = map[string]string{}
+ if err != nil {
+ return data
+ }
+ data["pid"] = gjson.Get(send, "data.pid").String()
+ return data
+}
+func LiveConvertUrl(args map[string]string) map[string]string {
+ //args = map[string]string{
+ // "appkey": "7076371480799348261",
+ // "appSecret": "9e58409e-5729-441e-a9f3-c077ec939fbb",
+ // "acctoken": "52f7ea67-5267-4874-9e05-a837dd1d6a48",
+ // "external_info": "123",
+ // "pid": "dy_107018934375430799627_13603_920074249",
+ // "product_url": "https://haohuo.jinritemai.com/views/product/item2?id=3378039360158085752",
+ //}
+ params := map[string]interface{}{"pid_info": map[string]interface{}{"pid": args["pid"], "external_info": args["external_info"]}, "open_id": args["open_id"]}
+ send, err := Send(args["appkey"], args["appSecret"], "buyin.instituteLiveShare", params, args["acctoken"])
+ fmt.Println(send)
+ var data = map[string]string{}
+ if err != nil {
+ return data
+ }
+ data["deeplink"] = gjson.Get(send, "data.dy_deeplink").String()
+ data["content"] = php2go.Base64Encode(gjson.Get(send, "data.dy_password").String())
+ data["qr_code"] = gjson.Get(send, "data.qr_code.url").String()
+
+ return data
+}
diff --git a/tik_tok/svc_tik_tok_goods.go b/tik_tok/svc_tik_tok_goods.go
new file mode 100644
index 0000000..b6cd6cf
--- /dev/null
+++ b/tik_tok/svc_tik_tok_goods.go
@@ -0,0 +1,142 @@
+package tik_tok
+
+import (
+ zhios_third_party_utils "code.fnuoos.com/go_rely_warehouse/zyos_go_third_party_api.git/utils"
+ "encoding/json"
+ "github.com/syyongx/php2go"
+ "github.com/tidwall/gjson"
+)
+
+//抖音商品
+func GoodsList(args map[string]string) []TikTokGoods {
+ sortArr := map[string]map[string]string{
+ "default": {"search_type": "0", "sort_type": "0"},
+ "qhPriceDesc": {"search_type": "2", "sort_type": "1"},
+ "qhPriceAsc": {"search_type": "2", "sort_type": "0"},
+ "commissionDesc": {"search_type": "4", "sort_type": "1"},
+ "commissionAsc": {"search_type": "4", "sort_type": "0"},
+ "salesDesc": {"search_type": "1", "sort_type": "1"},
+ "salesAsc": {"search_type": "1", "sort_type": "0"},
+ }
+ params := map[string]interface{}{
+ "search_type": sortArr[args["sort"]]["search_type"],
+ "sort_type": sortArr[args["sort"]]["sort_type"],
+ "page": args["page"],
+ "page_size": args["page_size"],
+ "share_status": "1",
+ }
+ if args["title"] != "" {
+ params["title"] = args["title"]
+ }
+ if args["first_cids"] != "" {
+ params["first_cids"] = []string{args["first_cids"]}
+ }
+ if args["price_min"] != "" {
+ params["price_min"] = zhios_third_party_utils.Float64ToStr(zhios_third_party_utils.StrToFloat64(args["price_min"]) * 100)
+ }
+ if args["price_max"] != "" {
+ params["price_max"] = zhios_third_party_utils.Float64ToStr(zhios_third_party_utils.StrToFloat64(args["price_max"]) * 100)
+ }
+ if args["sell_num_min"] != "" {
+ params["sell_num_min"] = args["sell_num_min"]
+ }
+ if args["sell_num_max"] != "" {
+ params["sell_num_max"] = args["sell_num_max"]
+ }
+ if args["cos_fee_min"] != "" {
+ params["cos_fee_min"] = zhios_third_party_utils.Float64ToStr(zhios_third_party_utils.StrToFloat64(args["cos_fee_min"]) * 100)
+ }
+ if args["cos_fee_max"] != "" {
+ params["cos_fee_max"] = zhios_third_party_utils.Float64ToStr(zhios_third_party_utils.StrToFloat64(args["cos_fee_max"]) * 100)
+ }
+ if args["cos_ratio_min"] != "" {
+ params["cos_ratio_min"] = zhios_third_party_utils.Float64ToStr(zhios_third_party_utils.StrToFloat64(args["cos_ratio_min"]) * 100)
+ }
+ if args["cos_ratio_max"] != "" {
+ params["cos_ratio_max"] = zhios_third_party_utils.Float64ToStr(zhios_third_party_utils.StrToFloat64(args["cos_ratio_max"]) * 100)
+ }
+ send, err := Send(args["appkey"], args["appSecret"], "alliance.materialsProductsSearch", params, args["acctoken"])
+ var goodsList = make([]TikTokGoods, 0)
+ product := gjson.Get(send, "data.products").String()
+ if err != nil || product == "" {
+ return goodsList
+ }
+ var tmpList = make([]interface{}, 0)
+ err = json.Unmarshal([]byte(product), &tmpList)
+ if err != nil {
+ return goodsList
+ }
+ for _, v := range tmpList {
+ goods := v.(map[string]interface{})
+ tmp := CommGoodsDetail(goods)
+ goodsList = append(goodsList, tmp)
+ }
+ return goodsList
+}
+
+//详情
+func GetDetail(args map[string]string) TikTokGoods {
+ params := map[string]interface{}{"product_ids": []string{args["id"]}, "with_share_status": true}
+ send, err := Send(args["appkey"], args["appSecret"], "alliance.materialsProductsDetails", params, args["acctoken"])
+ var goodsList = TikTokGoods{}
+ product := gjson.Get(send, "data.products").String()
+ if err != nil || product == "" {
+ return goodsList
+ }
+ var tmpList = make([]interface{}, 0)
+ err = json.Unmarshal([]byte(product), &tmpList)
+ if err != nil {
+ return goodsList
+ }
+ for _, v := range tmpList {
+ goods := v.(map[string]interface{})
+ tmp := CommGoodsDetail(goods)
+ if tmp.GoodsID == args["id"] {
+ return tmp
+ }
+ }
+ return goodsList
+}
+func GetKlGoods(args map[string]string) TikTokGoods {
+ params := map[string]interface{}{"command": php2go.Base64Encode(args["content"])}
+ send, err := Send(args["appkey"], args["appSecret"], "buyin.shareCommandParse", params, args["acctoken"])
+ var goodsList = TikTokGoods{}
+ product := gjson.Get(send, "data.product_info").String()
+ if err != nil || product == "" {
+ return goodsList
+ }
+ args["id"] = gjson.Get(product, "product_id").String()
+ goodsList = GetDetail(args)
+ return goodsList
+}
+func CommGoodsDetail(goods map[string]interface{}) TikTokGoods {
+ img := make([]interface{}, 0)
+ imgs, ok := goods["imgs"].([]interface{})
+ if ok {
+ img = imgs
+ }
+ var tmp = TikTokGoods{
+ Commission: zhios_third_party_utils.AnyToString(goods["cos_ratio"]),
+ CostPrice: zhios_third_party_utils.Float64ToStr(zhios_third_party_utils.AnyToFloat64(goods["price"]) / 100),
+ DetailURL: zhios_third_party_utils.AnyToString(goods["detail_url"]),
+ GoodsID: zhios_third_party_utils.AnyToString(goods["product_id"]),
+ GoodsImg: zhios_third_party_utils.AnyToString(goods["cover"]),
+ GoodsSales: zhios_third_party_utils.AnyToString(goods["sales"]),
+ GoodsTitle: zhios_third_party_utils.AnyToString(goods["title"]),
+ Imgs: img,
+ InStock: zhios_third_party_utils.AnyToString(goods["in_stock"]),
+ Price: zhios_third_party_utils.Float64ToStr(zhios_third_party_utils.AnyToFloat64(goods["coupon_price"]) / 100),
+ Sharable: zhios_third_party_utils.AnyToString(goods["sharable"]),
+ ShopID: zhios_third_party_utils.AnyToString(goods["shop_id"]),
+ ShopName: zhios_third_party_utils.AnyToString(goods["shop_name"]),
+ ShopTotalScore: zhios_third_party_utils.AnyToString(goods["shop_total_score"]),
+ YhqPrice: "0",
+ }
+ if zhios_third_party_utils.StrToFloat64(tmp.Price) == 0 {
+ tmp.Price = tmp.CostPrice
+ } else {
+ tmp.YhqPrice = zhios_third_party_utils.Float64ToStr(zhios_third_party_utils.AnyToFloat64(goods["price"])/100 - zhios_third_party_utils.AnyToFloat64(goods["coupon_price"])/100)
+ }
+ return tmp
+
+}
diff --git a/tik_tok/svc_tik_tok_live.go b/tik_tok/svc_tik_tok_live.go
new file mode 100644
index 0000000..1b0d5d5
--- /dev/null
+++ b/tik_tok/svc_tik_tok_live.go
@@ -0,0 +1,58 @@
+package tik_tok
+
+import (
+ zhios_third_party_utils "code.fnuoos.com/go_rely_warehouse/zyos_go_third_party_api.git/utils"
+ "encoding/json"
+ "github.com/tidwall/gjson"
+)
+
+func LiveList(args map[string]string) []TikTokLive {
+ params := map[string]interface{}{"page": args["page"], "page_size": args["page_size"]}
+ if args["author_type"] != "" {
+ params["author_type"] = args["author_type"]
+ }
+ if args["author_levels"] != "" {
+ params["author_levels"] = []string{args["author_levels"]}
+ }
+ if args["first_cids"] != "" {
+ params["first_cids"] = []string{args["first_cids"]}
+ }
+ if args["keyword"] != "" {
+ params["keyword"] = args["keyword"]
+ }
+ if args["sell_num_max"] != "" {
+ params["sell_num_max"] = args["sell_num_max"]
+ }
+ if args["sort_type"] != "" {
+ params["sort_type"] = args["sort_type"]
+ }
+ if args["sort_by"] != "" {
+ params["sort_by"] = args["sort_by"]
+ }
+ send, err := Send(args["appkey"], args["appSecret"], "buyin.liveShareMaterial", params, args["acctoken"])
+ var goodsList = make([]TikTokLive, 0)
+ product := gjson.Get(send, "data.data").String()
+ if err != nil || product == "" {
+ return goodsList
+ }
+ var tmpList = make([]interface{}, 0)
+ err = json.Unmarshal([]byte(product), &tmpList)
+ if err != nil {
+ return goodsList
+ }
+ for _, v := range tmpList {
+ goods := v.(map[string]interface{})
+ if zhios_third_party_utils.AnyToBool(goods["is_live"]) == false {
+ continue
+ }
+ tmp := TikTokLive{
+ LiveId: zhios_third_party_utils.AnyToString(goods["author_openid"]),
+ Name: zhios_third_party_utils.AnyToString(goods["author_name"]),
+ HeadImg: zhios_third_party_utils.AnyToString(goods["author_pic"]),
+ FansNum: zhios_third_party_utils.AnyToString(goods["fans_num"]),
+ Pvd: "tikTok",
+ }
+ goodsList = append(goodsList, tmp)
+ }
+ return goodsList
+}
diff --git a/tik_tok/svc_tik_tok_order.go b/tik_tok/svc_tik_tok_order.go
new file mode 100644
index 0000000..c79c3d0
--- /dev/null
+++ b/tik_tok/svc_tik_tok_order.go
@@ -0,0 +1,148 @@
+package tik_tok
+
+import (
+ zhios_third_party_utils "code.fnuoos.com/go_rely_warehouse/zyos_go_third_party_api.git/utils"
+ "encoding/json"
+ "fmt"
+ "github.com/tidwall/gjson"
+ "strings"
+)
+
+func GoodsOrder(args map[string]string) map[string]interface{} {
+ args = map[string]string{
+ "appkey": "7076371480799348261",
+ "appSecret": "9e58409e-5729-441e-a9f3-c077ec939fbb",
+ "acctoken": "52f7ea67-5267-4874-9e05-a837dd1d6a48",
+ "size": "10",
+ "cursor": "0",
+ "start_time": "2022-08-25 00:00:00",
+ "end_time": "2022-08-26 00:00:00",
+ }
+ params := map[string]interface{}{"size": args["size"], "cursor": args["cursor"], "start_time": args["start_time"], "end_time": args["end_time"], "distribution_type": "ProductDetail"}
+ send, err := Send(args["appkey"], args["appSecret"], "buyin.kolOrderAds", params, args["acctoken"])
+ fmt.Println(send)
+ var data = map[string]interface{}{}
+ if err != nil {
+ return data
+ }
+ order := gjson.Get(send, "data.orders").String()
+ data["cursor"] = gjson.Get(send, "data.cursor").String()
+ var tmpList = make([]interface{}, 0)
+ err = json.Unmarshal([]byte(order), &tmpList)
+ if err != nil {
+ return data
+ }
+ var orderTmp = make([]map[string]string, 0)
+ statusArr := map[string]string{
+ "PAY_SUCC": "订单付款",
+ "REFUND": "订单退款",
+ "SETTLE": "订单结算",
+ "CONFIRM": "订单成功",
+ }
+ for _, v := range tmpList {
+ tmp := CommOrder(v, statusArr)
+ if tmp["oid"] == "" {
+ continue
+ }
+ orderTmp = append(orderTmp, tmp)
+ }
+ data["order"] = orderTmp
+ return data
+
+}
+
+func LiveOrder(args map[string]string) map[string]interface{} {
+ //args = map[string]string{
+ // "appkey": "7076371480799348261",
+ // "appSecret": "9e58409e-5729-441e-a9f3-c077ec939fbb",
+ // "acctoken": "52f7ea67-5267-4874-9e05-a837dd1d6a48",
+ // "size": "10",
+ // "cursor": "0",
+ // "start_time": "2022-08-26 00:00:00",
+ // "end_time": "2022-08-27 00:00:00",
+ //}
+ params := map[string]interface{}{"size": args["size"], "cursor": args["cursor"], "start_time": args["start_time"], "end_time": args["end_time"], "distribution_type": "Live"}
+ send, err := Send(args["appkey"], args["appSecret"], "buyin.instituteOrderAds", params, args["acctoken"])
+ fmt.Println(send)
+ var data = map[string]interface{}{}
+ if err != nil {
+ return data
+ }
+ order := gjson.Get(send, "data.orders").String()
+ data["cursor"] = gjson.Get(send, "data.cursor").String()
+ var tmpList = make([]interface{}, 0)
+ err = json.Unmarshal([]byte(order), &tmpList)
+ if err != nil {
+ return data
+ }
+ var orderTmp = make([]map[string]string, 0)
+ statusArr := map[string]string{
+ "PAY_SUCC": "订单付款",
+ "REFUND": "订单退款",
+ "SETTLE": "订单结算",
+ "CONFIRM": "订单成功",
+ }
+ for _, v := range tmpList {
+ tmp := CommOrder(v, statusArr)
+ if tmp["oid"] == "" {
+ continue
+ }
+ orderTmp = append(orderTmp, tmp)
+ }
+ data["order"] = orderTmp
+ return data
+
+}
+func CommOrder(v interface{}, statusArr map[string]string) map[string]string {
+ tmp := make(map[string]string)
+ goods := v.(map[string]interface{})
+ pidInfo, ok := goods["pid_info"].(map[string]interface{})
+ mediaTypeName := ""
+ if ok == false {
+ return tmp
+ }
+ mediaTypeName = zhios_third_party_utils.AnyToString(pidInfo["media_type_name"])
+ tmp = map[string]string{
+ "pid": zhios_third_party_utils.AnyToString(pidInfo["pid"]),
+ "oid": zhios_third_party_utils.AnyToString(goods["order_id"]),
+ "info": zhios_third_party_utils.AnyToString(goods["product_name"]),
+ "num": zhios_third_party_utils.AnyToString(goods["item_num"]),
+ "type": zhios_third_party_utils.AnyToString(mediaTypeName),
+ "product_id": zhios_third_party_utils.AnyToString(goods["product_id"]),
+ "product_img": zhios_third_party_utils.AnyToString(goods["product_img"]),
+ "payment": zhios_third_party_utils.AnyToString(zhios_third_party_utils.AnyToFloat64(goods["total_pay_amount"]) / 100),
+ "status": statusArr[zhios_third_party_utils.AnyToString(goods["flow_point"])],
+ "create_time": zhios_third_party_utils.Int64ToStr(zhios_third_party_utils.TimeStdParseUnix(zhios_third_party_utils.AnyToString(goods["pay_success_time"]))),
+ "update_time": zhios_third_party_utils.Int64ToStr(zhios_third_party_utils.TimeStdParseUnix(zhios_third_party_utils.AnyToString(goods["update_time"]))),
+ "refund_time": "",
+ "lm_js_time": "",
+ }
+ external_info := zhios_third_party_utils.AnyToString(pidInfo["external_info"])
+ tmp["is_share"] = "0"
+ split := strings.Split(external_info, "_")
+ if len(split) > 1 {
+ if split[0] == "s" {
+ tmp["is_share"] = "1"
+ }
+ tmp["uid"] = split[1]
+ }
+ if tmp["type"] == "Live" {
+ tmp["commission"] = zhios_third_party_utils.AnyToString(zhios_third_party_utils.AnyToFloat64(goods["ads_estimated_commission"]) / 100)
+ if zhios_third_party_utils.AnyToFloat64(goods["ads_real_commission"]) > 0 {
+ tmp["commission"] = zhios_third_party_utils.AnyToString(zhios_third_party_utils.AnyToFloat64(goods["ads_real_commission"]) / 100)
+ }
+ }
+ if tmp["type"] == "ProductDetail" {
+ tmp["commission"] = zhios_third_party_utils.AnyToString(zhios_third_party_utils.AnyToFloat64(goods["estimated_commission"]) / 100)
+ if zhios_third_party_utils.AnyToFloat64(goods["real_commission"]) > 0 {
+ tmp["commission"] = zhios_third_party_utils.AnyToString(zhios_third_party_utils.AnyToFloat64(goods["real_commission"]) / 100)
+ }
+ }
+ if zhios_third_party_utils.AnyToString(goods["refund_time"]) != "" {
+ tmp["refund_time"] = zhios_third_party_utils.Int64ToStr(zhios_third_party_utils.TimeStdParseUnix(zhios_third_party_utils.AnyToString(goods["pay_success_time"])))
+ }
+ if zhios_third_party_utils.AnyToString(goods["settle_time"]) != "" {
+ tmp["lm_js_time"] = zhios_third_party_utils.Int64ToStr(zhios_third_party_utils.TimeStdParseUnix(zhios_third_party_utils.AnyToString(goods["settle_time"])))
+ }
+ return tmp
+}
diff --git a/tik_tok/tik_tok_test.go b/tik_tok/tik_tok_test.go
new file mode 100644
index 0000000..5404527
--- /dev/null
+++ b/tik_tok/tik_tok_test.go
@@ -0,0 +1,9 @@
+package tik_tok
+
+import (
+ "testing"
+)
+
+func TestGoods(t *testing.T) {
+ GoodsOrder(map[string]string{})
+}
diff --git a/utils/convert.go b/utils/convert.go
new file mode 100644
index 0000000..2c6bade
--- /dev/null
+++ b/utils/convert.go
@@ -0,0 +1,366 @@
+package zhios_third_party_utils
+
+import (
+ "encoding/binary"
+ "encoding/json"
+ "fmt"
+ "math"
+ "strconv"
+ "strings"
+)
+
+func ToString(raw interface{}, e error) (res string) {
+ if e != nil {
+ return ""
+ }
+ return AnyToString(raw)
+}
+
+func ToInt64(raw interface{}, e error) int64 {
+ if e != nil {
+ return 0
+ }
+ return AnyToInt64(raw)
+}
+
+func AnyToBool(raw interface{}) bool {
+ switch i := raw.(type) {
+ case float32, float64, int, int64, uint, uint8, uint16, uint32, uint64, int8, int16, int32:
+ return i != 0
+ case []byte:
+ return i != nil
+ case string:
+ if i == "false" {
+ return false
+ }
+ return i != ""
+ case error:
+ return false
+ case nil:
+ return true
+ }
+ val := fmt.Sprint(raw)
+ val = strings.TrimLeft(val, "&")
+ if strings.TrimLeft(val, "{}") == "" {
+ return false
+ }
+ if strings.TrimLeft(val, "[]") == "" {
+ return false
+ }
+ // ptr type
+ b, err := json.Marshal(raw)
+ if err != nil {
+ return false
+ }
+ if strings.TrimLeft(string(b), "\"\"") == "" {
+ return false
+ }
+ if strings.TrimLeft(string(b), "{}") == "" {
+ return false
+ }
+ return true
+}
+
+func AnyToInt64(raw interface{}) int64 {
+ switch i := raw.(type) {
+ case string:
+ res, _ := strconv.ParseInt(i, 10, 64)
+ return res
+ case []byte:
+ return BytesToInt64(i)
+ case int:
+ return int64(i)
+ case int64:
+ return i
+ case uint:
+ return int64(i)
+ case uint8:
+ return int64(i)
+ case uint16:
+ return int64(i)
+ case uint32:
+ return int64(i)
+ case uint64:
+ return int64(i)
+ case int8:
+ return int64(i)
+ case int16:
+ return int64(i)
+ case int32:
+ return int64(i)
+ case float32:
+ return int64(i)
+ case float64:
+ return int64(i)
+ case error:
+ return 0
+ case bool:
+ if i {
+ return 1
+ }
+ return 0
+ }
+ return 0
+}
+
+func AnyToString(raw interface{}) string {
+ switch i := raw.(type) {
+ case []byte:
+ return string(i)
+ case int:
+ return strconv.FormatInt(int64(i), 10)
+ case int64:
+ return strconv.FormatInt(i, 10)
+ case float32:
+ return Float64ToStr(float64(i))
+ case float64:
+ return Float64ToStr(i)
+ case uint:
+ return strconv.FormatInt(int64(i), 10)
+ case uint8:
+ return strconv.FormatInt(int64(i), 10)
+ case uint16:
+ return strconv.FormatInt(int64(i), 10)
+ case uint32:
+ return strconv.FormatInt(int64(i), 10)
+ case uint64:
+ return strconv.FormatInt(int64(i), 10)
+ case int8:
+ return strconv.FormatInt(int64(i), 10)
+ case int16:
+ return strconv.FormatInt(int64(i), 10)
+ case int32:
+ return strconv.FormatInt(int64(i), 10)
+ case string:
+ return i
+ case error:
+ return i.Error()
+ case bool:
+ return strconv.FormatBool(i)
+ }
+ return fmt.Sprintf("%#v", raw)
+}
+
+func AnyToFloat64(raw interface{}) float64 {
+ switch i := raw.(type) {
+ case []byte:
+ f, _ := strconv.ParseFloat(string(i), 64)
+ return f
+ case int:
+ return float64(i)
+ case int64:
+ return float64(i)
+ case float32:
+ return float64(i)
+ case float64:
+ return i
+ case uint:
+ return float64(i)
+ case uint8:
+ return float64(i)
+ case uint16:
+ return float64(i)
+ case uint32:
+ return float64(i)
+ case uint64:
+ return float64(i)
+ case int8:
+ return float64(i)
+ case int16:
+ return float64(i)
+ case int32:
+ return float64(i)
+ case string:
+ f, _ := strconv.ParseFloat(i, 64)
+ return f
+ case bool:
+ if i {
+ return 1
+ }
+ }
+ return 0
+}
+
+func ToByte(raw interface{}, e error) []byte {
+ if e != nil {
+ return []byte{}
+ }
+ switch i := raw.(type) {
+ case string:
+ return []byte(i)
+ case int:
+ return Int64ToBytes(int64(i))
+ case int64:
+ return Int64ToBytes(i)
+ case float32:
+ return Float32ToByte(i)
+ case float64:
+ return Float64ToByte(i)
+ case uint:
+ return Int64ToBytes(int64(i))
+ case uint8:
+ return Int64ToBytes(int64(i))
+ case uint16:
+ return Int64ToBytes(int64(i))
+ case uint32:
+ return Int64ToBytes(int64(i))
+ case uint64:
+ return Int64ToBytes(int64(i))
+ case int8:
+ return Int64ToBytes(int64(i))
+ case int16:
+ return Int64ToBytes(int64(i))
+ case int32:
+ return Int64ToBytes(int64(i))
+ case []byte:
+ return i
+ case error:
+ return []byte(i.Error())
+ case bool:
+ if i {
+ return []byte("true")
+ }
+ return []byte("false")
+ }
+ return []byte(fmt.Sprintf("%#v", raw))
+}
+
+func Int64ToBytes(i int64) []byte {
+ var buf = make([]byte, 8)
+ binary.BigEndian.PutUint64(buf, uint64(i))
+ return buf
+}
+
+func BytesToInt64(buf []byte) int64 {
+ return int64(binary.BigEndian.Uint64(buf))
+}
+
+func StrToInt(s string) int {
+ res, _ := strconv.Atoi(s)
+ return res
+}
+
+func StrToInt64(s string) int64 {
+ res, _ := strconv.ParseInt(s, 10, 64)
+ return res
+}
+
+func Float32ToByte(float float32) []byte {
+ bits := math.Float32bits(float)
+ bytes := make([]byte, 4)
+ binary.LittleEndian.PutUint32(bytes, bits)
+
+ return bytes
+}
+
+func ByteToFloat32(bytes []byte) float32 {
+ bits := binary.LittleEndian.Uint32(bytes)
+ return math.Float32frombits(bits)
+}
+
+func Float64ToByte(float float64) []byte {
+ bits := math.Float64bits(float)
+ bytes := make([]byte, 8)
+ binary.LittleEndian.PutUint64(bytes, bits)
+ return bytes
+}
+
+func ByteToFloat64(bytes []byte) float64 {
+ bits := binary.LittleEndian.Uint64(bytes)
+ return math.Float64frombits(bits)
+}
+
+func Float64ToStr(f float64) string {
+ return strconv.FormatFloat(f, 'f', 2, 64)
+}
+func Float64ToStrPrec1(f float64) string {
+ return strconv.FormatFloat(f, 'f', 1, 64)
+}
+func Float64ToStrByPrec(f float64, prec int) string {
+ return strconv.FormatFloat(f, 'f', prec, 64)
+}
+
+func Float32ToStr(f float32) string {
+ return Float64ToStr(float64(f))
+}
+
+func StrToFloat64(s string) float64 {
+ res, err := strconv.ParseFloat(s, 64)
+ if err != nil {
+ return 0
+ }
+ return res
+}
+func StrToFormat(s string, prec int) string {
+ ex := strings.Split(s, ".")
+ if len(ex) == 2 {
+ if StrToFloat64(ex[1]) == 0 { //小数点后面为空就是不要小数点了
+ return ex[0]
+ }
+ //看取多少位
+ str := ex[1]
+ str1 := str
+ if prec < len(str) {
+ str1 = str[0:prec]
+ } else {
+ for i := 0; i < prec-len(str); i++ {
+ str1 += "0"
+ }
+ }
+ if prec > 0 {
+ return ex[0] + "." + str1
+ } else {
+ return ex[0]
+ }
+ }
+ return s
+}
+
+func StrToFloat32(s string) float32 {
+ res, err := strconv.ParseFloat(s, 32)
+ if err != nil {
+ return 0
+ }
+ return float32(res)
+}
+
+func StrToBool(s string) bool {
+ b, _ := strconv.ParseBool(s)
+ return b
+}
+
+func BoolToStr(b bool) string {
+ if b {
+ return "true"
+ }
+ return "false"
+}
+
+func FloatToInt64(f float64) int64 {
+ return int64(f)
+}
+
+func IntToStr(i int) string {
+ return strconv.Itoa(i)
+}
+
+func Int64ToStr(i int64) string {
+ return strconv.FormatInt(i, 10)
+}
+
+func IntToFloat64(i int) float64 {
+ s := strconv.Itoa(i)
+ res, err := strconv.ParseFloat(s, 64)
+ if err != nil {
+ return 0
+ }
+ return res
+}
+func Int64ToFloat64(i int64) float64 {
+ s := strconv.FormatInt(i, 10)
+ res, err := strconv.ParseFloat(s, 64)
+ if err != nil {
+ return 0
+ }
+ return res
+}
diff --git a/utils/curl.go b/utils/curl.go
new file mode 100644
index 0000000..1cbeb4b
--- /dev/null
+++ b/utils/curl.go
@@ -0,0 +1,231 @@
+package zhios_third_party_utils
+
+import (
+ "bytes"
+ "crypto/tls"
+ "encoding/json"
+ "fmt"
+ "io"
+ "io/ioutil"
+ "net/http"
+ "net/url"
+ "sort"
+ "strings"
+ "time"
+)
+
+var CurlDebug bool
+
+func CurlGet(router string, header map[string]string) ([]byte, error) {
+ return curl(http.MethodGet, router, nil, header)
+}
+func CurlGetJson(router string, body interface{}, header map[string]string) ([]byte, error) {
+ return curl_new(http.MethodGet, router, body, header)
+}
+
+// 只支持form 与json 提交, 请留意body的类型, 支持string, []byte, map[string]string
+func CurlPost(router string, body interface{}, header map[string]string) ([]byte, error) {
+ return curl(http.MethodPost, router, body, header)
+}
+
+func CurlPut(router string, body interface{}, header map[string]string) ([]byte, error) {
+ return curl(http.MethodPut, router, body, header)
+}
+
+// 只支持form 与json 提交, 请留意body的类型, 支持string, []byte, map[string]string
+func CurlPatch(router string, body interface{}, header map[string]string) ([]byte, error) {
+ return curl(http.MethodPatch, router, body, header)
+}
+
+// CurlDelete is curl delete
+func CurlDelete(router string, body interface{}, header map[string]string) ([]byte, error) {
+ return curl(http.MethodDelete, router, body, header)
+}
+
+func curl(method, router string, body interface{}, header map[string]string) ([]byte, error) {
+ var reqBody io.Reader
+ contentType := "application/json"
+ switch v := body.(type) {
+ case string:
+ reqBody = strings.NewReader(v)
+ case []byte:
+ reqBody = bytes.NewReader(v)
+ case map[string]string:
+ val := url.Values{}
+ for k, v := range v {
+ val.Set(k, v)
+ }
+ reqBody = strings.NewReader(val.Encode())
+ contentType = "application/x-www-form-urlencoded"
+ case map[string]interface{}:
+ val := url.Values{}
+ for k, v := range v {
+ va, ok := v.(string)
+ if !ok {
+ val.Set(k, convertToString(va))
+ } else {
+ val.Set(k, va)
+ }
+
+ }
+ reqBody = strings.NewReader(val.Encode())
+ contentType = "application/x-www-form-urlencoded"
+ }
+ if header == nil {
+ header = map[string]string{"Content-Type": contentType}
+ }
+ if _, ok := header["Content-Type"]; !ok {
+ header["Content-Type"] = contentType
+ }
+ resp, er := CurlReq(method, router, reqBody, header)
+ if er != nil {
+ return nil, er
+ }
+ res, err := ioutil.ReadAll(resp.Body)
+ if CurlDebug {
+ blob := SerializeStr(body)
+ if contentType != "application/json" {
+ blob = HttpBuild(body)
+ }
+ fmt.Printf("\n\n=====================\n[url]: %s\n[time]: %s\n[method]: %s\n[content-type]: %v\n[req_header]: %s\n[req_body]: %#v\n[resp_err]: %v\n[resp_header]: %v\n[resp_body]: %v\n=====================\n\n",
+ router,
+ time.Now().Format("2006-01-02 15:04:05.000"),
+ method,
+ contentType,
+ HttpBuildQuery(header),
+ blob,
+ err,
+ SerializeStr(resp.Header),
+ string(res),
+ )
+ }
+ resp.Body.Close()
+ return res, err
+}
+
+func curl_new(method, router string, body interface{}, header map[string]string) ([]byte, error) {
+ var reqBody io.Reader
+ contentType := "application/json"
+
+ if header == nil {
+ header = map[string]string{"Content-Type": contentType}
+ }
+ if _, ok := header["Content-Type"]; !ok {
+ header["Content-Type"] = contentType
+ }
+ resp, er := CurlReq(method, router, reqBody, header)
+ if er != nil {
+ return nil, er
+ }
+ res, err := ioutil.ReadAll(resp.Body)
+ if CurlDebug {
+ blob := SerializeStr(body)
+ if contentType != "application/json" {
+ blob = HttpBuild(body)
+ }
+ fmt.Printf("\n\n=====================\n[url]: %s\n[time]: %s\n[method]: %s\n[content-type]: %v\n[req_header]: %s\n[req_body]: %#v\n[resp_err]: %v\n[resp_header]: %v\n[resp_body]: %v\n=====================\n\n",
+ router,
+ time.Now().Format("2006-01-02 15:04:05.000"),
+ method,
+ contentType,
+ HttpBuildQuery(header),
+ blob,
+ err,
+ SerializeStr(resp.Header),
+ string(res),
+ )
+ }
+ resp.Body.Close()
+ return res, err
+}
+
+func CurlReq(method, router string, reqBody io.Reader, header map[string]string) (*http.Response, error) {
+ req, _ := http.NewRequest(method, router, reqBody)
+ if header != nil {
+ for k, v := range header {
+ req.Header.Set(k, v)
+ }
+ }
+ // 绕过github等可能因为特征码返回503问题
+ // https://www.imwzk.com/posts/2021-03-14-why-i-always-get-503-with-golang/
+ defaultCipherSuites := []uint16{0xc02f, 0xc030, 0xc02b, 0xc02c, 0xcca8, 0xcca9, 0xc013, 0xc009,
+ 0xc014, 0xc00a, 0x009c, 0x009d, 0x002f, 0x0035, 0xc012, 0x000a}
+ client := &http.Client{
+ Transport: &http.Transport{
+ TLSClientConfig: &tls.Config{
+ InsecureSkipVerify: true,
+ CipherSuites: append(defaultCipherSuites[8:], defaultCipherSuites[:8]...),
+ },
+ },
+ // 获取301重定向
+ CheckRedirect: func(req *http.Request, via []*http.Request) error {
+ return http.ErrUseLastResponse
+ },
+ }
+ return client.Do(req)
+}
+
+// 组建get请求参数,sortAsc true为小到大,false为大到小,nil不排序 a=123&b=321
+func HttpBuildQuery(args map[string]string, sortAsc ...bool) string {
+ str := ""
+ if len(args) == 0 {
+ return str
+ }
+ if len(sortAsc) > 0 {
+ keys := make([]string, 0, len(args))
+ for k := range args {
+ keys = append(keys, k)
+ }
+ if sortAsc[0] {
+ sort.Strings(keys)
+ } else {
+ sort.Sort(sort.Reverse(sort.StringSlice(keys)))
+ }
+ for _, k := range keys {
+ str += "&" + k + "=" + args[k]
+ }
+ } else {
+ for k, v := range args {
+ str += "&" + k + "=" + v
+ }
+ }
+ return str[1:]
+}
+
+func HttpBuild(body interface{}, sortAsc ...bool) string {
+ params := map[string]string{}
+ if args, ok := body.(map[string]interface{}); ok {
+ for k, v := range args {
+ params[k] = AnyToString(v)
+ }
+ return HttpBuildQuery(params, sortAsc...)
+ }
+ if args, ok := body.(map[string]string); ok {
+ for k, v := range args {
+ params[k] = AnyToString(v)
+ }
+ return HttpBuildQuery(params, sortAsc...)
+ }
+ if args, ok := body.(map[string]int); ok {
+ for k, v := range args {
+ params[k] = AnyToString(v)
+ }
+ return HttpBuildQuery(params, sortAsc...)
+ }
+ return AnyToString(body)
+}
+
+func convertToString(v interface{}) string {
+ if v == nil {
+ return ""
+ }
+ var (
+ bs []byte
+ err error
+ )
+ if bs, err = json.Marshal(v); err != nil {
+ return ""
+ }
+ str := string(bs)
+ return str
+}
diff --git a/utils/serialize.go b/utils/serialize.go
new file mode 100644
index 0000000..ed07194
--- /dev/null
+++ b/utils/serialize.go
@@ -0,0 +1,23 @@
+package zhios_third_party_utils
+
+import (
+ "encoding/json"
+)
+
+func Serialize(data interface{}) []byte {
+ res, err := json.Marshal(data)
+ if err != nil {
+ return []byte{}
+ }
+ return res
+}
+
+func Unserialize(b []byte, dst interface{}) {
+ if err := json.Unmarshal(b, dst); err != nil {
+ dst = nil
+ }
+}
+
+func SerializeStr(data interface{}, arg ...interface{}) string {
+ return string(Serialize(data))
+}
diff --git a/utils/time.go b/utils/time.go
new file mode 100644
index 0000000..a1a6046
--- /dev/null
+++ b/utils/time.go
@@ -0,0 +1,233 @@
+package zhios_third_party_utils
+
+import (
+ "errors"
+ "fmt"
+ "strconv"
+ "strings"
+ "time"
+)
+
+func StrToTime(s string) (int64, error) {
+ // delete all not int characters
+ if s == "" {
+ return time.Now().Unix(), nil
+ }
+ r := make([]rune, 14)
+ l := 0
+ // 过滤除数字以外的字符
+ for _, v := range s {
+ if '0' <= v && v <= '9' {
+ r[l] = v
+ l++
+ if l == 14 {
+ break
+ }
+ }
+ }
+ for l < 14 {
+ r[l] = '0' // 补0
+ l++
+ }
+ t, err := time.Parse("20060102150405", string(r))
+ if err != nil {
+ return 0, err
+ }
+ return t.Unix(), nil
+}
+func String2Time(timeStr string) time.Time {
+ toTime, err := time.ParseInLocation("2006-01-02 15:04:05", timeStr, time.Local)
+ if err != nil {
+ return time.Now()
+ }
+ return toTime
+}
+
+func TimeToStr(unixSecTime interface{}, layout ...string) string {
+ i := AnyToInt64(unixSecTime)
+ if i == 0 {
+ return ""
+ }
+ f := "2006-01-02 15:04:05"
+ if len(layout) > 0 {
+ f = layout[0]
+ }
+ return time.Unix(i, 0).Format(f)
+}
+func Time2String(date time.Time, format string) string {
+ if format == "" {
+ format = "2006-01-02 15:04:05"
+ }
+ timeS := date.Format(format)
+ if timeS == "0001-01-01 00:00:00" {
+ return ""
+ }
+ return timeS
+}
+
+func FormatNanoUnix() string {
+ return strings.Replace(time.Now().Format("20060102150405.0000000"), ".", "", 1)
+}
+
+func TimeParse(format, src string) (time.Time, error) {
+ return time.ParseInLocation(format, src, time.Local)
+}
+
+func TimeParseStd(src string) time.Time {
+ t, _ := TimeParse("2006-01-02 15:04:05", src)
+ return t
+}
+
+func TimeStdParseUnix(src string) int64 {
+ t, err := TimeParse("2006-01-02 15:04:05", src)
+ if err != nil {
+ return 0
+ }
+ return t.Unix()
+}
+
+// 获取一个当前时间 时间间隔 时间戳
+func GetTimeInterval(unit string, amount int) (startTime, endTime int64) {
+ t := time.Now()
+ nowTime := t.Unix()
+ tmpTime := int64(0)
+ switch unit {
+ case "years":
+ tmpTime = time.Date(t.Year()+amount, t.Month(), t.Day(), t.Hour(), 0, 0, 0, t.Location()).Unix()
+ case "months":
+ tmpTime = time.Date(t.Year(), t.Month()+time.Month(amount), t.Day(), t.Hour(), 0, 0, 0, t.Location()).Unix()
+ case "days":
+ tmpTime = time.Date(t.Year(), t.Month(), t.Day()+amount, t.Hour(), 0, 0, 0, t.Location()).Unix()
+ case "hours":
+ tmpTime = time.Date(t.Year(), t.Month(), t.Day(), t.Hour()+amount, 0, 0, 0, t.Location()).Unix()
+ }
+ if amount > 0 {
+ startTime = nowTime
+ endTime = tmpTime
+ } else {
+ startTime = tmpTime
+ endTime = nowTime
+ }
+ return
+}
+
+// 几天前
+func TimeInterval(newTime int) string {
+ now := time.Now().Unix()
+ newTime64 := AnyToInt64(newTime)
+ if newTime64 >= now {
+ return "刚刚"
+ }
+ interval := now - newTime64
+ switch {
+ case interval < 60:
+ return AnyToString(interval) + "秒前"
+ case interval < 60*60:
+ return AnyToString(interval/60) + "分前"
+ case interval < 60*60*24:
+ return AnyToString(interval/60/60) + "小时前"
+ case interval < 60*60*24*30:
+ return AnyToString(interval/60/60/24) + "天前"
+ case interval < 60*60*24*30*12:
+ return AnyToString(interval/60/60/24/30) + "月前"
+ default:
+ return AnyToString(interval/60/60/24/30/12) + "年前"
+ }
+}
+
+// 时分秒字符串转时间戳,传入示例:8:40 or 8:40:10
+func HmsToUnix(str string) (int64, error) {
+ t := time.Now()
+ arr := strings.Split(str, ":")
+ if len(arr) < 2 {
+ return 0, errors.New("Time format error")
+ }
+ h, _ := strconv.Atoi(arr[0])
+ m, _ := strconv.Atoi(arr[1])
+ s := 0
+ if len(arr) == 3 {
+ s, _ = strconv.Atoi(arr[3])
+ }
+ formatted1 := fmt.Sprintf("%d%02d%02d%02d%02d%02d", t.Year(), t.Month(), t.Day(), h, m, s)
+ res, err := time.ParseInLocation("20060102150405", formatted1, time.Local)
+ if err != nil {
+ return 0, err
+ } else {
+ return res.Unix(), nil
+ }
+}
+
+// 获取特定时间范围
+func GetTimeRange(s string) map[string]int64 {
+ t := time.Now()
+ var stime, etime time.Time
+
+ switch s {
+ case "today":
+ stime = time.Date(t.Year(), t.Month(), t.Day(), 0, 0, 0, 0, t.Location())
+ etime = time.Date(t.Year(), t.Month(), t.Day()+1, 0, 0, 0, 0, t.Location())
+ case "yesterday":
+ stime = time.Date(t.Year(), t.Month(), t.Day()-1, 0, 0, 0, 0, t.Location())
+ etime = time.Date(t.Year(), t.Month(), t.Day(), 0, 0, 0, 0, t.Location())
+ case "within_seven_days":
+ // 前6天0点
+ stime = time.Date(t.Year(), t.Month(), t.Day()-6, 0, 0, 0, 0, t.Location())
+ // 明天 0点
+ etime = time.Date(t.Year(), t.Month(), t.Day()+1, 0, 0, 0, 0, t.Location())
+ case "current_month":
+ stime = time.Date(t.Year(), t.Month(), 0, 0, 0, 0, 0, t.Location())
+ etime = time.Date(t.Year(), t.Month()+1, 0, 0, 0, 0, 0, t.Location())
+ case "last_month":
+ stime = time.Date(t.Year(), t.Month()-1, 0, 0, 0, 0, 0, t.Location())
+ etime = time.Date(t.Year(), t.Month(), 0, 0, 0, 0, 0, t.Location())
+ }
+
+ return map[string]int64{
+ "start": stime.Unix(),
+ "end": etime.Unix(),
+ }
+}
+
+// 获取特定时间范围
+func GetDateTimeRangeStr(s string) (string, string) {
+ t := time.Now()
+ var stime, etime time.Time
+
+ switch s {
+ case "today":
+ stime = time.Date(t.Year(), t.Month(), t.Day(), 0, 0, 0, 0, t.Location())
+ etime = time.Date(t.Year(), t.Month(), t.Day()+1, 0, 0, 0, 0, t.Location())
+ case "yesterday":
+ stime = time.Date(t.Year(), t.Month(), t.Day()-1, 0, 0, 0, 0, t.Location())
+ etime = time.Date(t.Year(), t.Month(), t.Day(), 0, 0, 0, 0, t.Location())
+ case "within_seven_days":
+ // 前6天0点
+ stime = time.Date(t.Year(), t.Month(), t.Day()-6, 0, 0, 0, 0, t.Location())
+ // 明天 0点
+ etime = time.Date(t.Year(), t.Month(), t.Day()+1, 0, 0, 0, 0, t.Location())
+ case "current_month":
+ stime = time.Date(t.Year(), t.Month(), 0, 0, 0, 0, 0, t.Location())
+ etime = time.Date(t.Year(), t.Month()+1, 0, 0, 0, 0, 0, t.Location())
+ case "last_month":
+ stime = time.Date(t.Year(), t.Month()-1, 0, 0, 0, 0, 0, t.Location())
+ etime = time.Date(t.Year(), t.Month(), 0, 0, 0, 0, 0, t.Location())
+ }
+
+ return stime.Format("2006-01-02 15:04:05"), etime.Format("2006-01-02 15:04:05")
+}
+
+//获取传入的时间所在月份的第一天,即某月第一天的0点。如传入time.Now(), 返回当前月份的第一天0点时间。
+func GetFirstDateOfMonth(d time.Time) time.Time {
+ d = d.AddDate(0, 0, -d.Day()+1)
+ return GetZeroTime(d)
+}
+
+//获取传入的时间所在月份的最后一天,即某月最后一天的0点。如传入time.Now(), 返回当前月份的最后一天0点时间。
+func GetLastDateOfMonth(d time.Time) time.Time {
+ return GetFirstDateOfMonth(d).AddDate(0, 1, -1)
+}
+
+//获取某一天的0点时间
+func GetZeroTime(d time.Time) time.Time {
+ return time.Date(d.Year(), d.Month(), d.Day(), 0, 0, 0, 0, d.Location())
+}