@@ -0,0 +1,51 @@ | |||||
package comm | |||||
import ( | |||||
"bytes" | |||||
"encoding/json" | |||||
"sort" | |||||
"strings" | |||||
) | |||||
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 | |||||
} | |||||
// 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 | |||||
} |
@@ -0,0 +1,9 @@ | |||||
package comm | |||||
import "time" | |||||
// GetCacheFunc 获取缓存委托 | |||||
type getCacheFunc func(cacheKey string) []byte | |||||
// SetCacheFunc 设置缓存委托 | |||||
type setCacheFunc func(cacheKey string, value []byte, expiration time.Duration) bool |
@@ -0,0 +1,324 @@ | |||||
package comm | |||||
import ( | |||||
"bytes" | |||||
"crypto/md5" | |||||
"crypto/tls" | |||||
"encoding/hex" | |||||
"encoding/json" | |||||
"errors" | |||||
"io" | |||||
"io/ioutil" | |||||
"net/http" | |||||
"net/url" | |||||
"sort" | |||||
"strconv" | |||||
"strings" | |||||
"time" | |||||
"github.com/bitly/go-simplejson" | |||||
"github.com/nilorg/sdk/convert" | |||||
) | |||||
var ( | |||||
/**公用方法**/ | |||||
// Session 用户登录授权成功后,TOP颁发给应用的授权信息。当此API的标签上注明:“需要授权”,则此参数必传;“不需要授权”,则此参数不需要传;“可选授权”,则此参数为可选 | |||||
Session string | |||||
// Timeout ... | |||||
Timeout time.Duration | |||||
// CacheExpiration 缓存过期时间 | |||||
CacheExpiration = time.Hour | |||||
// GetCache 获取缓存 | |||||
GetCache getCacheFunc | |||||
// SetCache 设置缓存 | |||||
SetCache setCacheFunc | |||||
/**淘宝平台信息**/ | |||||
TaobaoAppKey string | |||||
TaobaoAppSecret string | |||||
TaobaoRouter string | |||||
TaobaoVersion = "2.0" | |||||
/**京东平台信息**/ | |||||
JDAppKey string | |||||
JDAppSecret string | |||||
JDRouter string | |||||
JDSdkRouter string | |||||
JDVersion = "2.0" | |||||
/**拼多多平台信息**/ | |||||
PDDAppKey string | |||||
PDDAppSecret string | |||||
PDDRouter string | |||||
PDDVersion = "v1.0" | |||||
/**考拉海购平台信息**/ | |||||
KaolaAppKey string | |||||
KaolaAppSecret string | |||||
KaolaRouter string | |||||
KaolaVersion = "1.0" | |||||
) | |||||
// Arg 参数 | |||||
type Arg map[string]interface{} | |||||
// copyArg 复制参数 | |||||
func copyArg(srcArgs Arg) Arg { | |||||
newArgs := make(Arg) | |||||
for key, value := range srcArgs { | |||||
newArgs[key] = value | |||||
} | |||||
return newArgs | |||||
} | |||||
// newCacheKey 创建缓存Key | |||||
func newCacheKey(p Arg) string { | |||||
cpArgs := copyArg(p) | |||||
delete(cpArgs, "session") | |||||
delete(cpArgs, "timestamp") | |||||
delete(cpArgs, "sign") | |||||
keys := []string{} | |||||
for k := range cpArgs { | |||||
keys = append(keys, k) | |||||
} | |||||
// 排序asc | |||||
sort.Strings(keys) | |||||
// 把所有参数名和参数值串在一起 | |||||
cacheKeyBuf := new(bytes.Buffer) | |||||
for _, k := range keys { | |||||
cacheKeyBuf.WriteString(k) | |||||
cacheKeyBuf.WriteString("=") | |||||
cacheKeyBuf.WriteString(interfaceToString(cpArgs[k])) | |||||
} | |||||
h := md5.New() | |||||
io.Copy(h, cacheKeyBuf) | |||||
return hex.EncodeToString(h.Sum(nil)) | |||||
} | |||||
// execute 执行API接口 | |||||
func execute(p Arg, router string) (bytes []byte, err error) { | |||||
err = checkConfig() | |||||
if err != nil { | |||||
return | |||||
} | |||||
var req *http.Request | |||||
req, err = http.NewRequest("POST", router, strings.NewReader(p.getReqData())) | |||||
if err != nil { | |||||
return | |||||
} | |||||
tr := &http.Transport{ | |||||
TLSClientConfig: &tls.Config{InsecureSkipVerify: true}, | |||||
} | |||||
req.Header.Add("Content-Type", "application/x-www-form-urlencoded;charset=utf-8") | |||||
httpClient := &http.Client{Transport: tr} | |||||
httpClient.Timeout = Timeout | |||||
var resp *http.Response | |||||
resp, err = httpClient.Do(req) | |||||
if err != nil { | |||||
return | |||||
} | |||||
if resp.StatusCode != 200 { | |||||
err = errors.New("请求错误:" + strconv.Itoa(resp.StatusCode)) | |||||
return | |||||
} | |||||
defer resp.Body.Close() | |||||
bytes, err = ioutil.ReadAll(resp.Body) | |||||
// fmt.Printf("\n\n\nreq: %v\n\nresp: %v\n\n\n", p.getReqData(), string(bytes)) | |||||
return | |||||
} | |||||
// Execute 执行API接口 | |||||
func Execute(method string, p Arg) (res *simplejson.Json, err error) { | |||||
p, r := setReqData(p, method) | |||||
var bodyBytes []byte | |||||
bodyBytes, err = execute(p, r) | |||||
if err != nil { | |||||
return | |||||
} | |||||
return bytesToResult(bodyBytes) | |||||
} | |||||
func bytesToResult(bytes []byte) (res *simplejson.Json, err error) { | |||||
res, err = simplejson.NewJson(bytes) | |||||
if err != nil { | |||||
return | |||||
} | |||||
if responseError, ok := res.CheckGet("error_response"); ok { | |||||
if subMsg, subOk := responseError.CheckGet("sub_msg"); subOk { | |||||
err = errors.New(subMsg.MustString()) | |||||
} else if zhDesc, descOk := responseError.CheckGet("zh_desc"); descOk { | |||||
err = errors.New(zhDesc.MustString()) | |||||
} else { | |||||
err = errors.New(responseError.Get("msg").MustString()) | |||||
} | |||||
res = nil | |||||
} | |||||
return | |||||
} | |||||
// ExecuteCache 执行API接口,缓存 | |||||
func ExecuteCache(method string, param Arg) (res *simplejson.Json, err error) { | |||||
p, r := setReqData(param, method) | |||||
cacheKey := newCacheKey(p) | |||||
// 获取缓存 | |||||
if GetCache != nil { | |||||
cacheBytes := GetCache(cacheKey) | |||||
if len(cacheBytes) > 0 { | |||||
res, err = simplejson.NewJson(cacheBytes) | |||||
if err == nil && res != nil { | |||||
return | |||||
} | |||||
} | |||||
} | |||||
var bodyBytes []byte | |||||
bodyBytes, err = execute(param, r) | |||||
if err != nil { | |||||
return | |||||
} | |||||
res, err = bytesToResult(bodyBytes) | |||||
if err != nil { | |||||
return | |||||
} | |||||
ejsonBody, _ := res.MarshalJSON() | |||||
// 设置缓存 | |||||
if SetCache != nil { | |||||
go SetCache(cacheKey, ejsonBody, CacheExpiration) | |||||
} | |||||
return | |||||
} | |||||
// 检查配置 | |||||
func checkConfig() error { | |||||
if TaobaoAppKey == "" && JDAppKey == "" && KaolaAppKey == "" && PDDAppKey == "" { | |||||
return errors.New("至少需要设置一个平台参数") | |||||
} | |||||
return nil | |||||
} | |||||
//组装参数及添加公共参数 | |||||
func setReqData(p Arg, method string) (Arg, string) { | |||||
platform := strings.Split(method, ".")[0] | |||||
router := "" | |||||
hh, _ := time.ParseDuration("8h") | |||||
loc := time.Now().UTC().Add(hh) | |||||
if platform == "taobao" { | |||||
//淘宝 | |||||
p["timestamp"] = strconv.FormatInt(loc.Unix(), 10) | |||||
p["partner_id"] = "Blant" | |||||
p["app_key"] = TaobaoAppKey | |||||
p["v"] = TaobaoVersion | |||||
if Session != "" { | |||||
p["session"] = Session | |||||
} | |||||
p["method"] = method | |||||
p["format"] = "json" | |||||
p["sign_method"] = "md5" | |||||
// 设置签名 | |||||
p["sign"] = getSign(p, TaobaoAppSecret) | |||||
router = TaobaoRouter | |||||
} else if platform == "jdSdk" || platform == "jd" { | |||||
//京东 | |||||
param := p | |||||
p = Arg{} | |||||
p["param_json"] = param | |||||
p["app_key"] = JDAppKey | |||||
p["v"] = JDVersion | |||||
p["timestamp"] = loc.Format("2006-01-02 15:04:05") | |||||
p["method"] = method | |||||
p["format"] = "json" | |||||
p["sign_method"] = "md5" | |||||
// 设置签名 | |||||
p["sign"] = getSign(p, JDAppSecret) | |||||
router = JDSdkRouter | |||||
if platform == "jd" { | |||||
router = JDRouter | |||||
} | |||||
} else if platform == "pdd" { | |||||
//拼多多 | |||||
p["type"] = method | |||||
p["data_type"] = "json" | |||||
p["version"] = PDDVersion | |||||
p["client_id"] = PDDAppKey | |||||
p["timestamp"] = strconv.FormatInt(loc.Unix(), 10) | |||||
// 设置签名 | |||||
p["sign"] = getSign(p, PDDAppSecret) | |||||
router = PDDRouter | |||||
} else if platform == "kaola" { | |||||
//考拉海购 | |||||
p["method"] = method | |||||
p["v"] = KaolaVersion | |||||
p["signMethod"] = "md5" | |||||
p["unionId"] = KaolaAppKey | |||||
p["timestamp"] = loc.Format("2006-01-02 15:04:05") | |||||
// 设置签名 | |||||
p["sign"] = getSign(p, KaolaAppSecret) | |||||
router = KaolaRouter | |||||
} else if platform == "suning" { | |||||
// TODO 苏宁 | |||||
} else if platform == "vip" { | |||||
// TODO 唯品会 | |||||
} | |||||
return p, router | |||||
} | |||||
// 获取请求数据 | |||||
func (p Arg) getReqData() string { | |||||
// 公共参数 | |||||
args := url.Values{} | |||||
// 请求参数 | |||||
for key, val := range p { | |||||
args.Set(key, interfaceToString(val)) | |||||
} | |||||
return args.Encode() | |||||
} | |||||
// 获取签名 | |||||
func getSign(p Arg, secret string) string { | |||||
// 获取Key | |||||
var keys []string | |||||
for k := range p { | |||||
keys = append(keys, k) | |||||
} | |||||
// 排序asc | |||||
sort.Strings(keys) | |||||
// 把所有参数名和参数值串在一起 | |||||
query := bytes.NewBufferString(secret) | |||||
for _, k := range keys { | |||||
query.WriteString(k) | |||||
query.WriteString(interfaceToString(p[k])) | |||||
} | |||||
query.WriteString(secret) | |||||
// 使用MD5加密 | |||||
h := md5.New() | |||||
_, _ = io.Copy(h, query) | |||||
// 把二进制转化为大写的十六进制 | |||||
return strings.ToUpper(hex.EncodeToString(h.Sum(nil))) | |||||
} | |||||
func interfaceToString(src interface{}) string { | |||||
if src == nil { | |||||
panic(ErrTypeIsNil) | |||||
} | |||||
switch src.(type) { | |||||
case string: | |||||
return src.(string) | |||||
case int, int8, int32, int64: | |||||
case uint8, uint16, uint32, uint64: | |||||
case float32, float64: | |||||
return convert.ToString(src) | |||||
} | |||||
data, err := json.Marshal(src) | |||||
if err != nil { | |||||
panic(err) | |||||
} | |||||
return string(data) | |||||
} |
@@ -0,0 +1,8 @@ | |||||
package comm | |||||
import "errors" | |||||
var ( | |||||
ErrTypeIsNil = errors.New("类型为Nil") | |||||
ErrTypeUnknown = errors.New("未处理到的数据类型") | |||||
) |
@@ -3,7 +3,11 @@ module code.fnuoos.com/go_rely_warehouse/zyos_go_third_party_api.git | |||||
go 1.15 | go 1.15 | ||||
require ( | require ( | ||||
github.com/syyongx/php2go v0.9.7 | |||||
github.com/bitly/go-simplejson v0.5.0 | |||||
github.com/bmizerany/assert v0.0.0-20160611221934-b7ed37b82869 // indirect | |||||
github.com/kr/pretty v0.3.1 // indirect | |||||
github.com/nilorg/sdk v0.0.0-20221104025912-4b6ccb7004d8 | |||||
github.com/syyongx/php2go v0.9.7 | |||||
github.com/tidwall/gjson v1.14.1 | github.com/tidwall/gjson v1.14.1 | ||||
) | ) |
@@ -1,3 +1,17 @@ | |||||
github.com/bitly/go-simplejson v0.5.0 h1:6IH+V8/tVMab511d5bn4M7EwGXZf9Hj6i2xSwkNEM+Y= | |||||
github.com/bitly/go-simplejson v0.5.0/go.mod h1:cXHtHw4XUPsvGaxgjIAn8PhEWG9NfngEKAMDJEczWVA= | |||||
github.com/bmizerany/assert v0.0.0-20160611221934-b7ed37b82869 h1:DDGfHa7BWjL4YnC6+E63dPcxHo2sUxDIu8g3QgEJdRY= | |||||
github.com/bmizerany/assert v0.0.0-20160611221934-b7ed37b82869/go.mod h1:Ekp36dRnpXw/yCqJaO+ZrUyxD+3VXMFFr56k5XYrpB4= | |||||
github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= | |||||
github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= | |||||
github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk= | |||||
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= | |||||
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= | |||||
github.com/nilorg/sdk v0.0.0-20221104025912-4b6ccb7004d8 h1:9hvJ/9GQssABrUYNOW1Q6X9/7uY6+Srj9YYYQZVC0AE= | |||||
github.com/nilorg/sdk v0.0.0-20221104025912-4b6ccb7004d8/go.mod h1:X1swpPdqguAZaBDoEPyEWHSsJii0YQ1o+3piMv6W3JU= | |||||
github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e/go.mod h1:pJLUxLENpZxwdsKMEsNbx1VGcRFpLqf3715MtcvvzbA= | |||||
github.com/rogpeppe/go-internal v1.9.0 h1:73kH8U+JUqXU8lRuOHeVHaa/SZPifC7BkcraZVejAe8= | |||||
github.com/rogpeppe/go-internal v1.9.0/go.mod h1:WtVeX8xhTBvf0smdhujwtBcq4Qrzq/fJaraNFVN+nFs= | |||||
github.com/syyongx/php2go v0.9.7 h1:boZtLbm2xYbW49mX9M7Vq2zkVhBhv3fCqs2T16d2bGA= | github.com/syyongx/php2go v0.9.7 h1:boZtLbm2xYbW49mX9M7Vq2zkVhBhv3fCqs2T16d2bGA= | ||||
github.com/syyongx/php2go v0.9.7/go.mod h1:meN2eIhhUoxOd2nMxbpe8g6cFPXI5O9/UAAuz7oDdzw= | 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 h1:iymTbGkQBhveq21bEvAQ81I0LEBork8BFe1CUZXdyuo= | ||||
@@ -0,0 +1,19 @@ | |||||
package jdSdk | |||||
import "code.fnuoos.com/go_rely_warehouse/zyos_go_third_party_api.git/comm" | |||||
func init() { | |||||
comm.JDAppKey = "444ab671c4d095122916453d09af27fc" | |||||
comm.JDAppSecret = "aef3c2745cc44194816d0c89c65b3847" | |||||
comm.JDVersion = "1.0" | |||||
comm.JDRouter = "https://router.jd.com/api" | |||||
comm.JDSdkRouter = "https://router.jdSdk.com/api" | |||||
} | |||||
func send(method string, args map[string]interface{}) ([]byte, error) { | |||||
result, err := comm.Execute(method, args) | |||||
if err != nil { | |||||
return nil, err | |||||
} | |||||
return result.MarshalJSON() | |||||
} |
@@ -0,0 +1,17 @@ | |||||
package jdSdk | |||||
import "code.fnuoos.com/go_rely_warehouse/zyos_go_third_party_api.git/comm" | |||||
func ConventUrl(r *RequestJD) ([]byte, error) { | |||||
method := "jd.union.open.promotion.byunionid.get" | |||||
args := map[string]interface{}{ | |||||
"materialId": r.MaterialId, //推广物料链接,建议链接使用微Q前缀,能较好适配微信手Q页面 | |||||
"unionId": r.UnionId, // 目标推客的联盟ID | |||||
"positionId": r.PositionId, //推广位id | |||||
"chainType": "3", //转链类型,1:长链, 2 :短链 ,3: 长链+短链,默认短链 | |||||
} | |||||
if r.CouponUrl != "" { | |||||
args["couponUrl"] = r.CouponUrl | |||||
} | |||||
return send(method, comm.Arg{"promotionCodeReq": args}) | |||||
} |
@@ -0,0 +1,17 @@ | |||||
package jdSdk | |||||
import "code.fnuoos.com/go_rely_warehouse/zyos_go_third_party_api.git/comm" | |||||
// Featured is 京粉精选商品 https://open.jd.com/home/home#/doc/api?apiCateId=461&apiId=3588&apiName=jd.union.open.goods.jingfen.query | |||||
func Featured(r *RequestJD) ([]byte, error) { | |||||
method := "jdSdk.union.open.goods.jingfen.query" | |||||
args := map[string]interface{}{ | |||||
"pageIndex": r.PageIndex, | |||||
"pageSize": r.PageSize, | |||||
// 1-好券商品,2-精选卖场,10-9.9包邮,15-京东配送,22-实时热销榜,23-为你推荐,24-数码家电,25-超市,26-母婴玩具,27-家具日用,28-美妆穿搭,29-医药保健,30-图书文具,31-今日必推,32-京东好物,33-京东秒杀,34-拼购商品,40-高收益榜,41-自营热卖榜,109-新品首发,110-自营,112-京东爆品,125-首购商品,129-高佣榜单,130-视频商品,153-历史最低价商品榜 | |||||
"eliteId": r.EliteID, | |||||
// 排序字段(price:单价, commissionShare:佣金比例, commission:佣金, inOrderCount30DaysSku:sku维度30天引单量,comments:评论数,goodComments:好评数) | |||||
"sortName": r.SortName, | |||||
} | |||||
return send(method, comm.Arg{"goodsReq": args}) | |||||
} |
@@ -0,0 +1,21 @@ | |||||
package jdSdk | |||||
import "code.fnuoos.com/go_rely_warehouse/zyos_go_third_party_api.git/comm" | |||||
// Guess is 猜你喜欢 https://open.jd.com/home/home#/doc/api?apiCateId=461&apiId=5479&apiName=jd.union.open.goods.material.query | |||||
func Guess(r *RequestJD) ([]byte, error) { | |||||
method := "jdSdk.union.open.goods.material.query" | |||||
args := map[string]interface{}{ | |||||
"pageIndex": r.PageIndex, | |||||
"pageSize": r.PageSize, | |||||
// 1-好券商品,2-精选卖场,10-9.9包邮,15-京东配送,22-实时热销榜,23-为你推荐,24-数码家电,25-超市,26-母婴玩具,27-家具日用,28-美妆穿搭,29-医药保健,30-图书文具,31-今日必推,32-京东好物,33-京东秒杀,34-拼购商品,40-高收益榜,41-自营热卖榜,109-新品首发,110-自营,112-京东爆品,125-首购商品,129-高佣榜单,130-视频商品,153-历史最低价商品榜 | |||||
"eliteId": r.EliteID, | |||||
// 排序字段(price:单价, commissionShare:佣金比例, commission:佣金, inOrderCount30DaysSku:sku维度30天引单量,comments:评论数,goodComments:好评数) | |||||
"sortName": r.SortName, | |||||
} | |||||
if r.UserIDType != 0 && r.UserID != "" { | |||||
args["userIdType"] = r.UserIDType | |||||
args["userId"] = r.UserID | |||||
} | |||||
return send(method, comm.Arg{"goodsReq": args}) | |||||
} |
@@ -0,0 +1,95 @@ | |||||
package jdSdk | |||||
// 1-好券商品,2-精选卖场,10-9.9包邮,15-京东配送,22-实时热销榜,23-为你推荐,24-数码家电,25-超市,26-母婴玩具,27-家具日用,28-美妆穿搭,29-医药保健,30-图书文具,31-今日必推,32-京东好物,33-京东秒杀,34-拼购商品,40-高收益榜,41-自营热卖榜,109-新品首发,110-自营,112-京东爆品,125-首购商品,129-高佣榜单,130-视频商品,153-历史最低价商品榜 | |||||
// 排序字段(price:单价, commissionShare:佣金比例, commission:佣金, inOrderCount30DaysSku:sku维度30天引单量,comments:评论数,goodComments:好评数) | |||||
//RequestJD is 请求 京东sdk的参数 | |||||
type RequestJD struct { | |||||
PageIndex int `json:"page_index"` | |||||
PageSize int `json:"page_size"` | |||||
EliteID int `json:"elite_id"` | |||||
SortName string `json:"sort_name"` | |||||
UserIDType int `json:"userid_type"` | |||||
UserID string `json:"user_id"` | |||||
MaterialId string `json:"materialId"` //推广物料链接,建议链接使用微Q前缀,能较好适配微信手Q页面 | |||||
UnionId string `json:"unionId"` // 目标推客的联盟ID | |||||
PositionId string `json:"positionId"` //推广位id | |||||
CouponUrl string `json:"couponUrl"` | |||||
Time string `json:"time"` | |||||
Type string `json:"type"` | |||||
} | |||||
// JDFeaturedResponse is return from taoke.jdSdk | |||||
type JDFeaturedResponse struct { | |||||
JdUnionOpenGoodsJingfenQueryResponse struct { | |||||
Code string `json:"code"` | |||||
Result string `json:"result"` | |||||
} `json:"jd_union_open_goods_jingfen_query_response"` | |||||
} | |||||
// JDFeature is jdSdk 精选 for微信 | |||||
type JDFeature struct { | |||||
BrandCode string `json:"brandCode"` | |||||
BrandName string `json:"brandName"` | |||||
CategoryInfo struct { | |||||
Cid1 int `json:"cid1"` | |||||
Cid1Name string `json:"cid1Name"` | |||||
Cid2 int `json:"cid2"` | |||||
Cid2Name string `json:"cid2Name"` | |||||
Cid3 int `json:"cid3"` | |||||
Cid3Name string `json:"cid3Name"` | |||||
} `json:"categoryInfo"` | |||||
Comments int `json:"comments"` | |||||
CommissionInfo struct { | |||||
Commission float64 `json:"commission"` | |||||
CommissionShare float64 `json:"commissionShare"` | |||||
CouponCommission float64 `json:"couponCommission"` | |||||
PlusCommissionShare float64 `json:"plusCommissionShare"` | |||||
} `json:"commissionInfo"` | |||||
CouponInfo struct { | |||||
CouponList []struct { | |||||
BindType int `json:"bindType"` | |||||
Discount float64 `json:"discount"` | |||||
GetEndTime int64 `json:"getEndTime"` | |||||
GetStartTime int64 `json:"getStartTime"` | |||||
HotValue int `json:"hotValue"` | |||||
IsBest int `json:"isBest"` | |||||
Link string `json:"link"` | |||||
PlatformType int `json:"platformType"` | |||||
Quota float64 `json:"quota"` | |||||
UseEndTime int64 `json:"useEndTime"` | |||||
UseStartTime int64 `json:"useStartTime"` | |||||
} `json:"couponList"` | |||||
} `json:"couponInfo"` | |||||
GoodCommentsShare float64 `json:"goodCommentsShare"` | |||||
ImageInfo struct { | |||||
ImageList []struct { | |||||
URL string `json:"url"` | |||||
} `json:"imageList"` | |||||
} `json:"imageInfo"` | |||||
InOrderCount30Days int `json:"inOrderCount30Days"` | |||||
InOrderCount30DaysSku int `json:"inOrderCount30DaysSku"` | |||||
IsHot int `json:"isHot"` | |||||
MaterialURL string `json:"materialUrl"` | |||||
Owner string `json:"owner"` | |||||
PinGouInfo struct { | |||||
} `json:"pinGouInfo"` | |||||
PriceInfo struct { | |||||
LowestCouponPrice float64 `json:"lowestCouponPrice"` | |||||
LowestPrice float64 `json:"lowestPrice"` | |||||
LowestPriceType int `json:"lowestPriceType"` | |||||
Price float64 `json:"price"` | |||||
} `json:"priceInfo"` | |||||
ResourceInfo struct { | |||||
EliteID int `json:"eliteId"` | |||||
EliteName string `json:"eliteName"` | |||||
} `json:"resourceInfo"` | |||||
ShopInfo struct { | |||||
ShopID int `json:"shopId"` | |||||
ShopLevel float64 `json:"shopLevel"` | |||||
ShopName string `json:"shopName"` | |||||
} `json:"shopInfo"` | |||||
SkuID int64 `json:"skuId"` | |||||
SkuName string `json:"skuName"` | |||||
Spuid int64 `json:"spuid"` | |||||
} |
@@ -0,0 +1,15 @@ | |||||
package jdSdk | |||||
import "code.fnuoos.com/go_rely_warehouse/zyos_go_third_party_api.git/comm" | |||||
func OrderFollow(r *RequestJD) ([]byte, error) { | |||||
method := "jd.union.open.order.query" | |||||
args := map[string]interface{}{ | |||||
"pageNo": r.PageIndex, // | |||||
"key": r.UnionId, // 目标推客的联盟ID | |||||
"pageSize": r.PageSize, //推广位id | |||||
"type": r.Type, //1:下单时间,2:完成时间,3:更新时间 | |||||
"time": r.Time, | |||||
} | |||||
return send(method, comm.Arg{"orderReq": args}) | |||||
} |
@@ -0,0 +1,17 @@ | |||||
package jdSdk | |||||
import "code.fnuoos.com/go_rely_warehouse/zyos_go_third_party_api.git/comm" | |||||
// Recommend is 京东推荐商品https://open.jdSdk.com/home/home#/doc/api?apiCateId=461&apiId=3588&apiName=jdSdk.union.open.goods.jingfen.query | |||||
func Recommend(r *RequestJD) ([]byte, error) { | |||||
method := "jdSdk.kpl.open.union.search.byelited" | |||||
args := map[string]interface{}{ | |||||
"pageIndex": r.PageIndex, | |||||
"pageSize": r.PageSize, | |||||
// 1-好券商品,2-超级大卖场,10-9.9专区,22-热销爆品,23-为你推荐,24-数码家电,25-超市,26-母婴玩具,27-家具日用,28-美妆穿搭,29-医药保健,30-图书文具,31-今日必推,32-品牌好货,33-秒杀商品,34-拼购商品,109-新品首发,110-自营,125-首购商品,129-高佣榜单,130-视频商品 | |||||
"eliteId": r.EliteID, | |||||
// 排序字段price:单价, commissionShare:佣金比例, commission:佣金, inOrderCount30DaysSku:sku维度30天引单量,comments:评论数,goodComments:好评数 | |||||
"sortName": r.SortName, | |||||
} | |||||
return send(method, comm.Arg{"goodsReq": args}) | |||||
} |
@@ -0,0 +1,113 @@ | |||||
package jdSdk | |||||
import ( | |||||
"encoding/json" | |||||
) | |||||
//SDK is sdk for jdSdk | |||||
type SDK struct { | |||||
response []byte | |||||
fmap map[string]func(*RequestJD) | |||||
fname string | |||||
err error | |||||
} | |||||
//Init is init sdk | |||||
func (s *SDK) Init() { | |||||
s.fmap = make(map[string]func(*RequestJD)) | |||||
} | |||||
//SelectFunction is select func | |||||
func (s *SDK) SelectFunction(fname string) *SDK { | |||||
s.fname = fname | |||||
return s | |||||
} | |||||
//WithArgs is request args | |||||
func (s *SDK) WithArgs(args *RequestJD) *SDK { | |||||
f := s.fmap[s.fname] | |||||
f(args) | |||||
return s | |||||
} | |||||
// Result is func result | |||||
func (s *SDK) Result() (*SDK, error) { | |||||
return s, s.err | |||||
} | |||||
// Register is register func | |||||
func (s *SDK) Register(name string, f func(*RequestJD)) { | |||||
s.fmap[name] = f | |||||
} | |||||
//ToBytes is return []byte | |||||
func (s *SDK) ToBytes() []byte { | |||||
return s.response | |||||
} | |||||
// ToString is return string | |||||
func (s *SDK) ToString() string { | |||||
return string(s.response) | |||||
} | |||||
//ToMapInterface is return map[string]interface{} | |||||
func (s *SDK) ToMapInterface() map[string]interface{} { | |||||
m := make(map[string]interface{}) | |||||
json.Unmarshal(s.response, &m) | |||||
return m | |||||
} | |||||
// Featured is jdSdk 精选列表 | |||||
func (s *SDK) Featured(r *RequestJD) { | |||||
d, err := Featured(r) | |||||
if err != nil { | |||||
s.err = err | |||||
} | |||||
s.response = d | |||||
} | |||||
// Guess is 猜你喜欢列表 | |||||
func (s *SDK) Guess(r *RequestJD) { | |||||
d, err := Guess(r) | |||||
if err != nil { | |||||
s.err = err | |||||
} | |||||
s.response = d | |||||
} | |||||
// Recommend is 推荐列表 | |||||
func (s *SDK) Recommend(r *RequestJD) { | |||||
d, err := Recommend(r) | |||||
if err != nil { | |||||
s.err = err | |||||
} | |||||
s.response = d | |||||
} | |||||
//转链 | |||||
func (s *SDK) ConventUrl(r *RequestJD) { | |||||
d, err := ConventUrl(r) | |||||
if err != nil { | |||||
s.err = err | |||||
} | |||||
s.response = d | |||||
} | |||||
func (s *SDK) OrderFollow(r *RequestJD) { | |||||
d, err := OrderFollow(r) | |||||
if err != nil { | |||||
s.err = err | |||||
} | |||||
s.response = d | |||||
} | |||||
//NewJDSDK is jingdong sdk | |||||
func NewJDSDK() *SDK { | |||||
sdk := new(SDK) | |||||
sdk.Init() | |||||
sdk.Register("featured", sdk.Featured) | |||||
sdk.Register("guess", sdk.Guess) | |||||
sdk.Register("recommend", sdk.Recommend) | |||||
sdk.Register("convent_url", sdk.ConventUrl) | |||||
sdk.Register("order_follow", sdk.OrderFollow) | |||||
return sdk | |||||
} |
@@ -0,0 +1,19 @@ | |||||
package jdSdk | |||||
import ( | |||||
"fmt" | |||||
"testing" | |||||
) | |||||
func TestConventUrl(t *testing.T) { | |||||
rq := &RequestJD{ | |||||
PageIndex: 1, // | |||||
UnionId: "d3ee30b44a6fec06fa8a4eee4bd541b2d279e836750f97dfe56144d7be74233d5d131b3028a81cfc", // 目标推客的联盟ID | |||||
PageSize: 100, //推广位id | |||||
Type: "3", //1:下单时间,2:完成时间,3:更新时间 | |||||
Time: "2022121910", | |||||
} | |||||
sdk, err := NewJDSDK().SelectFunction("order_follow").WithArgs(rq).Result() | |||||
fmt.Println(string(sdk.ToBytes())) | |||||
fmt.Println(err) | |||||
} |
@@ -0,0 +1,42 @@ | |||||
package macao_logistics | |||||
import ( | |||||
"code.fnuoos.com/go_rely_warehouse/zyos_go_third_party_api.git/comm" | |||||
zhios_third_party_utils "code.fnuoos.com/go_rely_warehouse/zyos_go_third_party_api.git/utils" | |||||
"strings" | |||||
) | |||||
func GetSign(appSecret string, param map[string]string) string { | |||||
str := "" | |||||
keys := comm.KsortToStr(param) | |||||
for _, k := range keys { | |||||
str += strings.ReplaceAll(param[k], "\\n", "") | |||||
} | |||||
return "" | |||||
} | |||||
func Send(method string, params map[string]interface{}, acctoken string) (string, error) { | |||||
url := "http://jyb-admin-backend-test.aoyunltd.cn/api/v1" + method | |||||
header := make(map[string]string, 0) | |||||
if acctoken != "" { | |||||
header["Authorization"] = "Bearer " + acctoken | |||||
} | |||||
data, err := zhios_third_party_utils.CurlPost(url, params, header) | |||||
return string(data), err | |||||
} | |||||
func SendGet(method string, params map[string]interface{}, acctoken string) (string, error) { | |||||
url := "http://jyb-admin-backend-test.aoyunltd.cn/api/v1" + method | |||||
header := make(map[string]string, 0) | |||||
if acctoken != "" { | |||||
header["Authorization"] = "Bearer " + acctoken | |||||
} | |||||
for k, v := range params { | |||||
if strings.Contains(url, "?") == false { | |||||
url += "?" + k + "=" + zhios_third_party_utils.AnyToString(v) | |||||
} else { | |||||
url += "&" + k + "=" + zhios_third_party_utils.AnyToString(v) | |||||
} | |||||
} | |||||
data, err := zhios_third_party_utils.CurlGet(url, header) | |||||
return string(data), err | |||||
} |
@@ -0,0 +1,31 @@ | |||||
package macao_logistics | |||||
import "github.com/tidwall/gjson" | |||||
func GetToken() string { | |||||
params := map[string]interface{}{ | |||||
"phone": "15217160421", | |||||
"password": "123456789@", | |||||
} | |||||
//7c2f6cbd480a96f1aa69509f9dd65462 | |||||
send, err := Send("/jyb/admin/login/password", params, "") | |||||
if err != nil { | |||||
return "" | |||||
} | |||||
return gjson.Get(send, "data.token").String() | |||||
} | |||||
func GetGoods(params map[string]interface{}) string { | |||||
send, err := SendGet("/admin/goods/detailed/list", params, "7c2f6cbd480a96f1aa69509f9dd65462") | |||||
if err != nil { | |||||
return "" | |||||
} | |||||
return gjson.Get(send, "data.data").String() | |||||
} | |||||
func GetStore(params map[string]interface{}) string { | |||||
send, err := SendGet("/jyb/order/delivery/store", params, "7c2f6cbd480a96f1aa69509f9dd65462") | |||||
if err != nil { | |||||
return "" | |||||
} | |||||
return gjson.Get(send, "data.data").String() | |||||
} |
@@ -0,0 +1,17 @@ | |||||
package macao_logistics | |||||
import "testing" | |||||
func TestLogin(t *testing.T) { | |||||
params := map[string]interface{}{ | |||||
"order_number": "test12311", //單號,長度不可以超過30 | |||||
"phone": "15217160421", // 电话号码長度為8 or 11 | |||||
"arrive": "60", // 門店個點ID,可以用ID 也可以用AYG001的參數 | |||||
"type": "1", // 是指的是快件是否預付,1代表是用戶支付2是商家餘額支付,3是商家月結 | |||||
"weight": "20", // 重量,必須是int,沒有小數點 | |||||
"order_type": "1", | |||||
"city": "珠海", | |||||
} | |||||
//7c2f6cbd480a96f1aa69509f9dd65462 | |||||
Send("/jyb/order/delivery/add", params, "7c2f6cbd480a96f1aa69509f9dd65462") | |||||
} |
@@ -6,7 +6,7 @@ const ( | |||||
PVD_KUAISHOU = "kuaishou" | PVD_KUAISHOU = "kuaishou" | ||||
PVD_TIKTOKLIVE = "tikTok_live" | PVD_TIKTOKLIVE = "tikTok_live" | ||||
PVD_KUAISHOULIVE = "kuaishou_live" | PVD_KUAISHOULIVE = "kuaishou_live" | ||||
PVD_JD = "jd" | |||||
PVD_JD = "jdSdk" | |||||
PVD_SN = "suning" | PVD_SN = "suning" | ||||
PVD_VIP = "vip" | PVD_VIP = "vip" | ||||
PVD_PDD = "pdd" | PVD_PDD = "pdd" | ||||
@@ -71,7 +71,7 @@ var PVD_LIST = map[string]string{ | |||||
var PVD_NEW_LIST = []map[string]string{ | var PVD_NEW_LIST = []map[string]string{ | ||||
{"name": "淘宝", "key": "taobao", "is_more_union": "1"}, | {"name": "淘宝", "key": "taobao", "is_more_union": "1"}, | ||||
{"name": "抖音", "key": "tikTok", "is_more_union": "1"}, | {"name": "抖音", "key": "tikTok", "is_more_union": "1"}, | ||||
{"name": "京东", "key": "jd", "is_more_union": "1"}, | |||||
{"name": "京东", "key": "jdSdk", "is_more_union": "1"}, | |||||
{"name": "唯品会", "key": "vip", "is_more_union": "1"}, | {"name": "唯品会", "key": "vip", "is_more_union": "1"}, | ||||
{"name": "拼多多", "key": "pdd", "is_more_union": "1"}, | {"name": "拼多多", "key": "pdd", "is_more_union": "1"}, | ||||
{"name": "苏宁", "key": "suning", "is_more_union": "1"}, | {"name": "苏宁", "key": "suning", "is_more_union": "1"}, | ||||
@@ -1,14 +1,12 @@ | |||||
package tik_tok | package tik_tok | ||||
import ( | import ( | ||||
"bytes" | |||||
"code.fnuoos.com/go_rely_warehouse/zyos_go_third_party_api.git/comm" | |||||
zhios_third_party_utils "code.fnuoos.com/go_rely_warehouse/zyos_go_third_party_api.git/utils" | zhios_third_party_utils "code.fnuoos.com/go_rely_warehouse/zyos_go_third_party_api.git/utils" | ||||
"crypto/hmac" | "crypto/hmac" | ||||
"crypto/sha256" | "crypto/sha256" | ||||
"encoding/hex" | "encoding/hex" | ||||
"encoding/json" | |||||
"github.com/syyongx/php2go" | "github.com/syyongx/php2go" | ||||
"sort" | |||||
"strings" | "strings" | ||||
"time" | "time" | ||||
) | ) | ||||
@@ -16,7 +14,7 @@ import ( | |||||
func Send(appkey, appSecret, method string, params map[string]interface{}, acctoken string) (string, error) { | func Send(appkey, appSecret, method string, params map[string]interface{}, acctoken string) (string, error) { | ||||
methodPath := strings.ReplaceAll(method, ".", "/") | methodPath := strings.ReplaceAll(method, ".", "/") | ||||
url := "https://openapi-fxg.jinritemai.com/" + methodPath | url := "https://openapi-fxg.jinritemai.com/" + methodPath | ||||
paramJson := GetSortJson(params) | |||||
paramJson := comm.GetSortJson(params) | |||||
paramJson = strings.ReplaceAll(paramJson, "\n", "") | paramJson = strings.ReplaceAll(paramJson, "\n", "") | ||||
param := map[string]string{ | param := map[string]string{ | ||||
"app_key": appkey, | "app_key": appkey, | ||||
@@ -43,7 +41,7 @@ func Send(appkey, appSecret, method string, params map[string]interface{}, accto | |||||
} | } | ||||
func GetSign(appSecret string, param map[string]string) string { | func GetSign(appSecret string, param map[string]string) string { | ||||
str := "" | str := "" | ||||
keys := KsortToStr(param) | |||||
keys := comm.KsortToStr(param) | |||||
for _, k := range keys { | for _, k := range keys { | ||||
str += k + param[k] | str += k + param[k] | ||||
} | } | ||||
@@ -52,64 +50,3 @@ func GetSign(appSecret string, param map[string]string) string { | |||||
_, _ = h.Write([]byte(signStr)) | _, _ = h.Write([]byte(signStr)) | ||||
return hex.EncodeToString(h.Sum(nil)) | 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 | |||||
} |