@@ -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 | |||
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 | |||
) |
@@ -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/go.mod h1:meN2eIhhUoxOd2nMxbpe8g6cFPXI5O9/UAAuz7oDdzw= | |||
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_TIKTOKLIVE = "tikTok_live" | |||
PVD_KUAISHOULIVE = "kuaishou_live" | |||
PVD_JD = "jd" | |||
PVD_JD = "jdSdk" | |||
PVD_SN = "suning" | |||
PVD_VIP = "vip" | |||
PVD_PDD = "pdd" | |||
@@ -71,7 +71,7 @@ var PVD_LIST = map[string]string{ | |||
var PVD_NEW_LIST = []map[string]string{ | |||
{"name": "淘宝", "key": "taobao", "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": "pdd", "is_more_union": "1"}, | |||
{"name": "苏宁", "key": "suning", "is_more_union": "1"}, | |||
@@ -1,14 +1,12 @@ | |||
package tik_tok | |||
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" | |||
"crypto/hmac" | |||
"crypto/sha256" | |||
"encoding/hex" | |||
"encoding/json" | |||
"github.com/syyongx/php2go" | |||
"sort" | |||
"strings" | |||
"time" | |||
) | |||
@@ -16,7 +14,7 @@ import ( | |||
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 := comm.GetSortJson(params) | |||
paramJson = strings.ReplaceAll(paramJson, "\n", "") | |||
param := map[string]string{ | |||
"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 { | |||
str := "" | |||
keys := KsortToStr(param) | |||
keys := comm.KsortToStr(param) | |||
for _, k := range keys { | |||
str += k + param[k] | |||
} | |||
@@ -52,64 +50,3 @@ func GetSign(appSecret string, param map[string]string) string { | |||
_, _ = 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 | |||
} |