- mtwmapi
This commit is contained in:
@@ -124,3 +124,10 @@ func TestGetProductStatust(t *testing.T) {
|
||||
t.Fatal("GetProductStatus should return error")
|
||||
}
|
||||
}
|
||||
|
||||
func TestDelShopCategory(t *testing.T) {
|
||||
err := jdapi.DelShopCategory(4784689)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
}
|
||||
|
||||
147
platformapi/mtwmapi/food.go
Normal file
147
platformapi/mtwmapi/food.go
Normal file
@@ -0,0 +1,147 @@
|
||||
package mtwmapi
|
||||
|
||||
import (
|
||||
"time"
|
||||
|
||||
"git.rosy.net.cn/baseapi/utils"
|
||||
)
|
||||
|
||||
type FoodCategoryInfo struct {
|
||||
Name string `json:"name"`
|
||||
Sequence int `json:"sequence"`
|
||||
CTime time.Time `json:"ctime"`
|
||||
UTime time.Time `json:"utime"`
|
||||
}
|
||||
|
||||
func (a *API) FoodCatUpdate(poiCode, originName, name string, sequence int) (err error) {
|
||||
params := map[string]interface{}{
|
||||
KeyAppPoiCode: poiCode,
|
||||
"category_name_origin": originName,
|
||||
"sequence": sequence,
|
||||
}
|
||||
if name != "" {
|
||||
params["category_name"] = name
|
||||
}
|
||||
_, err = a.AccessAPI("foodCat/update", false, params)
|
||||
return err
|
||||
}
|
||||
|
||||
func (a *API) FoodCatDelete(poiCode, name string) (err error) {
|
||||
_, err = a.AccessAPI("foodCat/delete", false, map[string]interface{}{
|
||||
KeyAppPoiCode: poiCode,
|
||||
"category_name": name,
|
||||
})
|
||||
return err
|
||||
}
|
||||
|
||||
func (a *API) FoodInitData(poiCode, foodCode string, params map[string]interface{}) (err error) {
|
||||
_, err = a.AccessAPI("food/initdata", false, utils.MergeMaps(map[string]interface{}{
|
||||
KeyAppPoiCode: poiCode,
|
||||
KeyAppFoodCode: foodCode,
|
||||
}, params))
|
||||
return err
|
||||
}
|
||||
|
||||
func (a *API) FoodDelete(poiCode, foodCode string) (err error) {
|
||||
_, err = a.AccessAPI("food/delete", false, map[string]interface{}{
|
||||
KeyAppPoiCode: poiCode,
|
||||
KeyAppFoodCode: foodCode,
|
||||
})
|
||||
return err
|
||||
}
|
||||
|
||||
// offset 从0开始,limit最大不能超过200
|
||||
func (a *API) FoodList(poiCode string, offset, limit int) (foodList []map[string]interface{}, err error) {
|
||||
result, err := a.AccessAPI("food/list", true, map[string]interface{}{
|
||||
KeyAppPoiCode: poiCode,
|
||||
"offset": offset,
|
||||
"limit": limit,
|
||||
})
|
||||
if err == nil {
|
||||
return utils.Slice2MapSlice(result.([]interface{})), nil
|
||||
}
|
||||
return nil, err
|
||||
}
|
||||
|
||||
func (a *API) FoodBatchInitData(poiCode string, foodData map[string]interface{}) (err error) {
|
||||
_, err = a.AccessAPI("food/batchinitdata", false, map[string]interface{}{
|
||||
KeyAppPoiCode: poiCode,
|
||||
"food_data": foodData,
|
||||
})
|
||||
return err
|
||||
}
|
||||
|
||||
func (a *API) FoodCatList(poiCode string) (foodCatList []*FoodCategoryInfo, err error) {
|
||||
result, err := a.AccessAPI("foodCat/list", true, map[string]interface{}{
|
||||
KeyAppPoiCode: poiCode,
|
||||
})
|
||||
if err == nil {
|
||||
catListTmp := result.([]interface{})
|
||||
foodCatList = make([]*FoodCategoryInfo, len(catListTmp))
|
||||
for k, v := range catListTmp {
|
||||
cat := v.(map[string]interface{})
|
||||
foodCatList[k] = &FoodCategoryInfo{
|
||||
Name: utils.Interface2String(cat["name"]),
|
||||
Sequence: int(utils.MustInterface2Int64(cat["sequence"])),
|
||||
CTime: time.Unix(utils.MustInterface2Int64(cat["ctime"]), 0),
|
||||
UTime: time.Unix(utils.MustInterface2Int64(cat["utime"]), 0),
|
||||
}
|
||||
}
|
||||
return foodCatList, nil
|
||||
}
|
||||
return nil, err
|
||||
}
|
||||
|
||||
func (a *API) FoodSkuSave(poiCode, foodCode string, skus []map[string]interface{}) (err error) {
|
||||
_, err = a.AccessAPI("food/sku/save", false, map[string]interface{}{
|
||||
KeyAppPoiCode: poiCode,
|
||||
KeyAppFoodCode: foodCode,
|
||||
"skus": skus,
|
||||
})
|
||||
return err
|
||||
}
|
||||
|
||||
func (a *API) FoodSkuDelete(poiCode, foodCode, skuID string) (err error) {
|
||||
_, err = a.AccessAPI("food/sku/delete", false, map[string]interface{}{
|
||||
KeyAppPoiCode: poiCode,
|
||||
KeyAppFoodCode: foodCode,
|
||||
"sku_id": skuID,
|
||||
})
|
||||
return err
|
||||
}
|
||||
|
||||
func (a *API) FoodSkuPrice(poiCode string, foodData []map[string]interface{}) (err error) {
|
||||
_, err = a.AccessAPI("food/sku/price", false, map[string]interface{}{
|
||||
KeyAppPoiCode: poiCode,
|
||||
"food_data": foodData,
|
||||
})
|
||||
return err
|
||||
}
|
||||
|
||||
func (a *API) FoodSkuStock(poiCode string, foodData []map[string]interface{}) (err error) {
|
||||
_, err = a.AccessAPI("food/sku/stock", false, map[string]interface{}{
|
||||
KeyAppPoiCode: poiCode,
|
||||
"food_data": foodData,
|
||||
})
|
||||
return err
|
||||
}
|
||||
|
||||
func (a *API) FoodGet(poiCode, foodCode string) (food map[string]interface{}, err error) {
|
||||
result, err := a.AccessAPI("food/get", true, map[string]interface{}{
|
||||
KeyAppPoiCode: poiCode,
|
||||
KeyAppFoodCode: foodCode,
|
||||
})
|
||||
if err == nil {
|
||||
return result.(map[string]interface{}), nil
|
||||
}
|
||||
return nil, err
|
||||
}
|
||||
|
||||
func (a *API) FoodSkuSellStatus(poiCode string, foodData []map[string]interface{}, status int) (err error) {
|
||||
_, err = a.AccessAPI("food/sku/sellStatus", false, map[string]interface{}{
|
||||
KeyAppPoiCode: poiCode,
|
||||
"food_data": foodData,
|
||||
"status": status,
|
||||
})
|
||||
return err
|
||||
}
|
||||
16
platformapi/mtwmapi/food_test.go
Normal file
16
platformapi/mtwmapi/food_test.go
Normal file
@@ -0,0 +1,16 @@
|
||||
package mtwmapi
|
||||
|
||||
import (
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestFoodList(t *testing.T) {
|
||||
result, err := api.FoodList(testPoiCode, 0, 200)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if len(result) == 0 {
|
||||
t.Fatal("should have food")
|
||||
}
|
||||
// t.Log(result)
|
||||
}
|
||||
143
platformapi/mtwmapi/mtwmapi.go
Normal file
143
platformapi/mtwmapi/mtwmapi.go
Normal file
@@ -0,0 +1,143 @@
|
||||
package mtwmapi
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"crypto/md5"
|
||||
"fmt"
|
||||
"mime/multipart"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"sort"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"git.rosy.net.cn/baseapi/platformapi"
|
||||
"git.rosy.net.cn/baseapi/utils"
|
||||
)
|
||||
|
||||
const (
|
||||
apiURL = "https://waimaiopen.meituan.com/api/v1"
|
||||
sandboxAPIURL = "http://openapi.b.waimai.test.sankuai.com/api/v1"
|
||||
signKey = "sig"
|
||||
)
|
||||
|
||||
const (
|
||||
KeyAppPoiCode = "app_poi_code"
|
||||
KeyAppPoiCodes = "app_poi_codes"
|
||||
KeyAppFoodCode = "app_food_code"
|
||||
KeyImgName = "img_name"
|
||||
KeyImgData = "img_data"
|
||||
KeyOrderID = "order_id"
|
||||
)
|
||||
|
||||
const (
|
||||
GeneralMaxLimit = 200 // 大多数的API的批处理最大条数
|
||||
)
|
||||
|
||||
type API struct {
|
||||
appID string
|
||||
secret string
|
||||
client *http.Client
|
||||
config *platformapi.APIConfig
|
||||
}
|
||||
|
||||
func New(appID, secret string, config ...*platformapi.APIConfig) *API {
|
||||
curConfig := platformapi.DefAPIConfig
|
||||
if len(config) > 0 {
|
||||
curConfig = *config[0]
|
||||
}
|
||||
return &API{
|
||||
appID: appID,
|
||||
secret: secret,
|
||||
client: &http.Client{Timeout: curConfig.ClientTimeout},
|
||||
config: &curConfig,
|
||||
}
|
||||
}
|
||||
|
||||
func (a *API) genURL(cmd string) string {
|
||||
return apiURL + "/" + cmd
|
||||
}
|
||||
|
||||
func (a *API) signParams(cmd string, params map[string]interface{}) string {
|
||||
keys := make([]string, 0)
|
||||
for k := range params {
|
||||
if k != signKey {
|
||||
keys = append(keys, k)
|
||||
}
|
||||
}
|
||||
|
||||
sort.Strings(keys)
|
||||
finalStr := a.genURL(cmd) + "?"
|
||||
kvPaires := make([]string, len(keys))
|
||||
for k, key := range keys {
|
||||
if params[key] != nil {
|
||||
kvPaires[k] = key + "=" + fmt.Sprintf("%v", params[key])
|
||||
}
|
||||
}
|
||||
finalStr += strings.Join(kvPaires, "&") + a.secret
|
||||
// baseapi.SugarLogger.Debug(finalStr)
|
||||
return fmt.Sprintf("%x", md5.Sum([]byte(finalStr)))
|
||||
}
|
||||
|
||||
func (a *API) AccessAPI(cmd string, isGet bool, bizParams map[string]interface{}) (retVal interface{}, err error) {
|
||||
params := make(map[string]interface{})
|
||||
params["timestamp"] = time.Now().Unix()
|
||||
params["app_id"] = a.appID
|
||||
params = utils.MergeMaps(params, bizParams)
|
||||
imgData := params[KeyImgData]
|
||||
if imgData != nil {
|
||||
delete(params, KeyImgData)
|
||||
}
|
||||
params[signKey] = a.signParams(cmd, params)
|
||||
err = platformapi.AccessPlatformAPIWithRetry(a.client,
|
||||
func() *http.Request {
|
||||
var request *http.Request
|
||||
if isGet {
|
||||
fullURL := utils.GenerateGetURL(apiURL, cmd, params)
|
||||
// baseapi.SugarLogger.Debug(fullURL)
|
||||
request, _ = http.NewRequest(http.MethodGet, fullURL, nil)
|
||||
} else {
|
||||
fullURL := a.genURL(cmd)
|
||||
// baseapi.SugarLogger.Debug(utils.Map2URLValues(params).Encode())
|
||||
if imgData == nil {
|
||||
request, _ = http.NewRequest(http.MethodPost, fullURL, strings.NewReader(utils.Map2URLValues(params).Encode()))
|
||||
request.Header.Set("Content-Type", "application/x-www-form-urlencoded")
|
||||
} else {
|
||||
var b bytes.Buffer
|
||||
w := multipart.NewWriter(&b)
|
||||
if fw, err := w.CreateFormFile("file", params[KeyImgName].(string)); err != nil {
|
||||
panic(err.Error())
|
||||
} else {
|
||||
fw.Write(imgData.([]byte))
|
||||
}
|
||||
for k, v := range params {
|
||||
fmt.Println(k, " ", v)
|
||||
w.WriteField(k, url.QueryEscape(fmt.Sprint(v)))
|
||||
}
|
||||
w.Close()
|
||||
// b.WriteString(utils.Map2URLValues(params).Encode())
|
||||
request, _ = http.NewRequest(http.MethodPost, fullURL, &b)
|
||||
request.Header.Set("Content-Type", w.FormDataContentType())
|
||||
}
|
||||
request.Header.Set("charset", "UTF-8")
|
||||
}
|
||||
// request.Close = true //todo 为了性能考虑还是不要关闭
|
||||
return request
|
||||
},
|
||||
a.config,
|
||||
func(response *http.Response) (errLevel string, err error) {
|
||||
jsonResult1, err := utils.HTTPResponse2Json(response)
|
||||
// baseapi.SugarLogger.Debug(utils.Format4Output(jsonResult1, false))
|
||||
if err != nil {
|
||||
return platformapi.ErrLevelGeneralFail, platformapi.ErrResponseDataFormatWrong
|
||||
}
|
||||
if _, ok := jsonResult1["error"]; ok {
|
||||
errorInfo := jsonResult1["error"].(map[string]interface{})
|
||||
newErr := utils.NewErrorIntCode(errorInfo["msg"].(string), int(utils.MustInterface2Int64(errorInfo["code"])))
|
||||
return platformapi.ErrLevelCodeIsNotOK, newErr
|
||||
}
|
||||
retVal = jsonResult1["data"]
|
||||
return platformapi.ErrLevelSuccess, nil
|
||||
})
|
||||
return retVal, err
|
||||
}
|
||||
30
platformapi/mtwmapi/mtwmapi_test.go
Normal file
30
platformapi/mtwmapi/mtwmapi_test.go
Normal file
@@ -0,0 +1,30 @@
|
||||
package mtwmapi
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"git.rosy.net.cn/baseapi"
|
||||
"git.rosy.net.cn/baseapi/utils"
|
||||
"go.uber.org/zap"
|
||||
)
|
||||
|
||||
var (
|
||||
api *API
|
||||
sugarLogger *zap.SugaredLogger
|
||||
)
|
||||
|
||||
func init() {
|
||||
logger, _ := zap.NewDevelopment()
|
||||
sugarLogger = logger.Sugar()
|
||||
baseapi.Init(sugarLogger)
|
||||
|
||||
api = New("589", "a81eb3df418d83d6a1a4b7c572156d2f")
|
||||
}
|
||||
|
||||
func TestAccessAPI(t *testing.T) {
|
||||
result, err := api.AccessAPI("poi/getids", true, nil)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
t.Log(utils.Format4Output(result, false))
|
||||
}
|
||||
125
platformapi/mtwmapi/order.go
Normal file
125
platformapi/mtwmapi/order.go
Normal file
@@ -0,0 +1,125 @@
|
||||
package mtwmapi
|
||||
|
||||
import (
|
||||
"git.rosy.net.cn/baseapi/utils"
|
||||
)
|
||||
|
||||
const (
|
||||
MaxBatchPullPhoneNumberLimit = 1000
|
||||
)
|
||||
|
||||
func (a *API) OrderReceived(orderID int64) (err error) {
|
||||
_, err = a.AccessAPI("order/poi_received", true, map[string]interface{}{
|
||||
KeyOrderID: orderID,
|
||||
})
|
||||
return err
|
||||
}
|
||||
|
||||
func (a *API) OrderConfirm(orderID int64) (err error) {
|
||||
_, err = a.AccessAPI("order/confirm", true, map[string]interface{}{
|
||||
KeyOrderID: orderID,
|
||||
})
|
||||
return err
|
||||
}
|
||||
|
||||
func (a *API) OrderCancel(orderID int64) (err error) {
|
||||
_, err = a.AccessAPI("order/cancel", true, map[string]interface{}{
|
||||
KeyOrderID: orderID,
|
||||
})
|
||||
return err
|
||||
}
|
||||
|
||||
func (a *API) OrderDelivering(orderID int64) (err error) {
|
||||
_, err = a.AccessAPI("order/delivering", true, map[string]interface{}{
|
||||
KeyOrderID: orderID,
|
||||
})
|
||||
return err
|
||||
}
|
||||
|
||||
func (a *API) OrderArrived(orderID int64) (err error) {
|
||||
_, err = a.AccessAPI("order/arrived", true, map[string]interface{}{
|
||||
KeyOrderID: orderID,
|
||||
})
|
||||
return err
|
||||
}
|
||||
|
||||
func (a *API) OrderRefundAgree(orderID int64, reason string) (err error) {
|
||||
_, err = a.AccessAPI("order/refund/agree", true, map[string]interface{}{
|
||||
KeyOrderID: orderID,
|
||||
"reason": reason,
|
||||
})
|
||||
return err
|
||||
}
|
||||
|
||||
func (a *API) OrderRefundReject(orderID int64, reason string) (err error) {
|
||||
_, err = a.AccessAPI("order/refund/reject", true, map[string]interface{}{
|
||||
KeyOrderID: orderID,
|
||||
"reason": reason,
|
||||
})
|
||||
return err
|
||||
}
|
||||
|
||||
func (a *API) OrderViewStatus(orderID int64) (status int, err error) {
|
||||
result, err := a.AccessAPI("order/viewstatus", true, map[string]interface{}{
|
||||
KeyOrderID: orderID,
|
||||
})
|
||||
if err == nil {
|
||||
// baseapi.SugarLogger.Debug(result)
|
||||
return int(utils.MustInterface2Int64(result.(map[string]interface{})["status"])), nil
|
||||
}
|
||||
return 0, err
|
||||
}
|
||||
|
||||
func (a *API) OrderGetOrderDetail(orderID int64, isMTLogistics bool) (orderInfo map[string]interface{}, err error) {
|
||||
params := map[string]interface{}{
|
||||
KeyOrderID: orderID,
|
||||
}
|
||||
if isMTLogistics {
|
||||
params["is_mt_logistics"] = 1
|
||||
}
|
||||
result, err := a.AccessAPI("order/getOrderDetail", true, params)
|
||||
if err == nil {
|
||||
return result.(map[string]interface{}), nil
|
||||
}
|
||||
return nil, err
|
||||
}
|
||||
|
||||
func (a *API) OrderLogisticsPush(orderID int64, reason string) (err error) {
|
||||
_, err = a.AccessAPI("order/logistics/push", true, map[string]interface{}{
|
||||
KeyOrderID: orderID,
|
||||
})
|
||||
return err
|
||||
}
|
||||
|
||||
func (a *API) OrderLogisticsCancel(orderID int64, reason string) (err error) {
|
||||
_, err = a.AccessAPI("order/logistics/cancel", true, map[string]interface{}{
|
||||
KeyOrderID: orderID,
|
||||
})
|
||||
return err
|
||||
}
|
||||
|
||||
func (a *API) OrderLogisticsStatus(orderID int64) (status map[string]interface{}, err error) {
|
||||
result, err := a.AccessAPI("order/logistics/status", true, map[string]interface{}{
|
||||
KeyOrderID: orderID,
|
||||
})
|
||||
if err == nil {
|
||||
return result.(map[string]interface{}), nil
|
||||
}
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// limit最大为MaxBatchPullPhoneNumberLimit = 1000
|
||||
func (a *API) OrderBatchPullPhoneNumber(poiCode string, offset, limit int) (realNumberList []map[string]interface{}, err error) {
|
||||
params := map[string]interface{}{
|
||||
"offset": offset,
|
||||
"limit": limit,
|
||||
}
|
||||
if poiCode != "" {
|
||||
params[KeyAppPoiCode] = poiCode
|
||||
}
|
||||
result, err := a.AccessAPI("order/batchPullPhoneNumber", false, params)
|
||||
if err == nil {
|
||||
return utils.Slice2MapSlice(result.([]interface{})), nil
|
||||
}
|
||||
return nil, err
|
||||
}
|
||||
13
platformapi/mtwmapi/order_test.go
Normal file
13
platformapi/mtwmapi/order_test.go
Normal file
@@ -0,0 +1,13 @@
|
||||
package mtwmapi
|
||||
|
||||
import (
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestOrderViewStatus(t *testing.T) {
|
||||
result, err := api.OrderViewStatus(9)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
t.Log(result)
|
||||
}
|
||||
135
platformapi/mtwmapi/poi.go
Normal file
135
platformapi/mtwmapi/poi.go
Normal file
@@ -0,0 +1,135 @@
|
||||
package mtwmapi
|
||||
|
||||
import (
|
||||
"io/ioutil"
|
||||
"net/http"
|
||||
"strings"
|
||||
|
||||
"git.rosy.net.cn/baseapi/platformapi"
|
||||
"git.rosy.net.cn/baseapi/utils"
|
||||
)
|
||||
|
||||
type PoiCategoryInfo struct {
|
||||
ID int `json:"id"`
|
||||
Name string `json:"name"`
|
||||
}
|
||||
|
||||
func (a *API) PoiSave(poiCode string, poiParams map[string]interface{}) (err error) {
|
||||
_, err = a.AccessAPI("poi/save", false, utils.MergeMaps(utils.Params2Map(KeyAppPoiCode, poiCode), poiParams))
|
||||
return err
|
||||
}
|
||||
|
||||
func (a *API) PoiGetIDs() (ids []string, err error) {
|
||||
result, err := a.AccessAPI("poi/getids", true, nil)
|
||||
if err == nil {
|
||||
idsTmp := result.([]interface{})
|
||||
ids = make([]string, len(idsTmp))
|
||||
for k, v := range idsTmp {
|
||||
ids[k] = v.(string)
|
||||
}
|
||||
return ids, nil
|
||||
}
|
||||
return nil, err
|
||||
}
|
||||
|
||||
func (a *API) PoiMGet(poiCodes []string) (pois []map[string]interface{}, err error) {
|
||||
result, err := a.AccessAPI("poi/mget", true, map[string]interface{}{
|
||||
KeyAppPoiCodes: strings.Join(poiCodes, ","),
|
||||
})
|
||||
if err == nil {
|
||||
return utils.Slice2MapSlice(result.([]interface{})), nil
|
||||
}
|
||||
return nil, err
|
||||
}
|
||||
|
||||
func (a *API) PoiGet(poiCode string) (poi map[string]interface{}, err error) {
|
||||
result, err := a.PoiMGet([]string{poiCode})
|
||||
if err == nil {
|
||||
return result[0], nil
|
||||
}
|
||||
return nil, err
|
||||
}
|
||||
|
||||
func (a *API) PoiClose(poiCode string) (err error) {
|
||||
_, err = a.AccessAPI("poi/close", false, map[string]interface{}{
|
||||
KeyAppPoiCode: poiCode,
|
||||
})
|
||||
return err
|
||||
}
|
||||
|
||||
func (a *API) PoiOnline(poiCode string) (err error) {
|
||||
_, err = a.AccessAPI("poi/online", false, map[string]interface{}{
|
||||
KeyAppPoiCode: poiCode,
|
||||
})
|
||||
return err
|
||||
}
|
||||
|
||||
func (a *API) PoiUpdatePromoteInfo(poiCode, promotionInfo string) (err error) {
|
||||
_, err = a.AccessAPI("poi/updatepromoteinfo", false, map[string]interface{}{
|
||||
KeyAppPoiCode: poiCode,
|
||||
"promotion_info": promotionInfo,
|
||||
})
|
||||
return err
|
||||
}
|
||||
|
||||
func (a *API) PoiTagList(poiCode string) (catList []*PoiCategoryInfo, err error) {
|
||||
result, err := a.AccessAPI("poiTag/list", false, map[string]interface{}{
|
||||
KeyAppPoiCode: poiCode,
|
||||
})
|
||||
if err == nil {
|
||||
catListTmp := result.([]interface{})
|
||||
catList = make([]*PoiCategoryInfo, len(catListTmp))
|
||||
for k, v := range catListTmp {
|
||||
cat := v.(map[string]interface{})
|
||||
catList[k] = &PoiCategoryInfo{
|
||||
ID: int(utils.MustInterface2Int64(cat["id"])),
|
||||
Name: utils.Interface2String(cat["name"]),
|
||||
}
|
||||
}
|
||||
return catList, nil
|
||||
}
|
||||
return nil, err
|
||||
}
|
||||
|
||||
func (a *API) PoiShipTimeUpdate(poiCode string, beginTime1, endTime1, beginTime2, endTime2 string) (err error) {
|
||||
shippingTime := beginTime1 + "-" + endTime1
|
||||
if beginTime2 != "" {
|
||||
shippingTime += "," + beginTime2 + "-" + endTime2
|
||||
}
|
||||
_, err = a.AccessAPI("poi/updatepromoteinfo", false, map[string]interface{}{
|
||||
KeyAppPoiCode: poiCode,
|
||||
"shipping_time": shippingTime,
|
||||
})
|
||||
return err
|
||||
}
|
||||
|
||||
// 美团要求必须是jpg|jpeg图片格式,且imgName必须以jpg或jpeg结尾
|
||||
func (a *API) ImageUpload(poiCode, imgName string, imgData []byte) (imgID string, err error) {
|
||||
result, err := a.AccessAPI("image/upload", false, map[string]interface{}{
|
||||
KeyAppPoiCode: poiCode,
|
||||
KeyImgName: imgName,
|
||||
KeyImgData: imgData,
|
||||
})
|
||||
if err == nil {
|
||||
return result.(string), nil
|
||||
}
|
||||
return "", err
|
||||
}
|
||||
|
||||
func (a *API) ImageUploadByURL(poiCode, imgName, imgURL string) (imgID string, err error) {
|
||||
response, err := http.Get(imgURL)
|
||||
if err == nil {
|
||||
defer func() {
|
||||
response.Body.Close()
|
||||
}()
|
||||
if response.StatusCode == http.StatusOK {
|
||||
bodyData, err2 := ioutil.ReadAll(response.Body)
|
||||
if err = err2; err == nil {
|
||||
return a.ImageUpload(poiCode, imgName, bodyData)
|
||||
}
|
||||
} else {
|
||||
err = platformapi.ErrHTTPCodeIsNot200
|
||||
}
|
||||
}
|
||||
return "", err
|
||||
}
|
||||
71
platformapi/mtwmapi/poi_test.go
Normal file
71
platformapi/mtwmapi/poi_test.go
Normal file
@@ -0,0 +1,71 @@
|
||||
package mtwmapi
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"git.rosy.net.cn/baseapi/utils"
|
||||
)
|
||||
|
||||
const (
|
||||
testPoiCode = "test_poi_01"
|
||||
)
|
||||
|
||||
func TestPoiGetIDs(t *testing.T) {
|
||||
result, err := api.PoiGetIDs()
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if len(result) == 0 {
|
||||
t.Fatal("should have ids")
|
||||
}
|
||||
// t.Log(result)
|
||||
}
|
||||
|
||||
func TestPoiMGet(t *testing.T) {
|
||||
result, err := api.PoiMGet([]string{testPoiCode})
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if len(result) != 1 {
|
||||
t.Fatal("result len is not ok")
|
||||
}
|
||||
if result[0][KeyAppPoiCode] != testPoiCode {
|
||||
t.Fatal("test_poi_01 is not equal")
|
||||
}
|
||||
t.Log(utils.Format4Output(result, false))
|
||||
}
|
||||
|
||||
func TestPoiSave(t *testing.T) {
|
||||
result, err := api.PoiMGet([]string{testPoiCode})
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
poiParams := utils.FilterMapNilMembers(result[0])
|
||||
poiParams["name"] = "中国"
|
||||
err = api.PoiSave(testPoiCode, poiParams)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestPoiTagList(t *testing.T) {
|
||||
result, err := api.PoiTagList(testPoiCode)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if len(result) == 0 {
|
||||
t.Fatal("should have cats")
|
||||
}
|
||||
t.Log(utils.Format4Output(result, false))
|
||||
}
|
||||
|
||||
func TestImageUploadByURL(t *testing.T) {
|
||||
result, err := api.ImageUploadByURL(testPoiCode, "hello.jpg", "http://image.jxc4.com/56cd1e88ada3660f37548c2d29ea2158.jpg")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if len(result) == 0 {
|
||||
t.Fatal("should have result")
|
||||
}
|
||||
t.Log(result)
|
||||
}
|
||||
207
platformapi/mtwmapi/retail.go
Normal file
207
platformapi/mtwmapi/retail.go
Normal file
@@ -0,0 +1,207 @@
|
||||
package mtwmapi
|
||||
|
||||
import (
|
||||
"strings"
|
||||
|
||||
"git.rosy.net.cn/baseapi/utils"
|
||||
)
|
||||
|
||||
type RetailCategoryInfo struct {
|
||||
Name string `json:"name"`
|
||||
Sequence int `json:"sequence"`
|
||||
Level int `json:"level"`
|
||||
Children []*RetailCategoryInfo `json:"children"`
|
||||
}
|
||||
|
||||
// 美团分类没有ID,就以名字为唯一标识,不论级别都必须不能重名
|
||||
// name(和originName)的长度不能超过10个字符(字符,不是字节)
|
||||
// 首次创建分类时,如果secondaryName不为空,会把一级(如果不存在)及二级分类创建起来,
|
||||
// 如果一级分类已经存在时,要创建二级分类,则要求originName与name都不为空,且值是一样的
|
||||
// 大概逻辑是:
|
||||
// 如果originName不存在,则是创建一级分类,如果secondaryName相应还要创建二级分类,此时的sequence指的是二级的,一级的sequence就没有指定了
|
||||
// 如果originName存在,则指的是更新,一级分类就必须存在,如果不想改名,将name填成与originName一样的即可
|
||||
// todo 但这个函数好像就无法实现变更二级分类的名字及sequence
|
||||
func (a *API) RetailCatUpdate(poiCode, originName, name, secondaryName string, sequence int) (err error) {
|
||||
params := map[string]interface{}{
|
||||
KeyAppPoiCode: poiCode,
|
||||
"category_name": name,
|
||||
"sequence": sequence,
|
||||
}
|
||||
if originName != "" {
|
||||
params["category_name_origin"] = originName
|
||||
}
|
||||
if secondaryName != "" {
|
||||
params["secondary_category_name"] = secondaryName
|
||||
}
|
||||
_, err = a.AccessAPI("retailCat/update", false, params)
|
||||
return err
|
||||
}
|
||||
|
||||
func (a *API) RetailCatDelete(poiCode, name string) (err error) {
|
||||
_, err = a.AccessAPI("retailCat/delete", false, map[string]interface{}{
|
||||
KeyAppPoiCode: poiCode,
|
||||
"category_name": name,
|
||||
})
|
||||
return err
|
||||
}
|
||||
|
||||
func (a *API) RetailCatList(poiCode string) (retailCatList []*RetailCategoryInfo, err error) {
|
||||
result, err := a.AccessAPI("retailCat/list", true, map[string]interface{}{
|
||||
KeyAppPoiCode: poiCode,
|
||||
})
|
||||
if err == nil {
|
||||
return interface2CatList(result, 1, nil), nil
|
||||
}
|
||||
return nil, err
|
||||
}
|
||||
|
||||
func (a *API) RetailInitData(poiCode, foodCode string, params map[string]interface{}) (err error) {
|
||||
_, err = a.AccessAPI("retail/initdata", false, utils.MergeMaps(map[string]interface{}{
|
||||
KeyAppPoiCode: poiCode,
|
||||
KeyAppFoodCode: foodCode,
|
||||
}, params))
|
||||
return err
|
||||
}
|
||||
|
||||
// offset 从0开始,limit最大不能超过200
|
||||
func (a *API) RetailList(poiCode string, offset, limit int) (foodList []map[string]interface{}, err error) {
|
||||
result, err := a.AccessAPI("retail/list", true, map[string]interface{}{
|
||||
KeyAppPoiCode: poiCode,
|
||||
"offset": offset,
|
||||
"limit": limit,
|
||||
})
|
||||
if err == nil {
|
||||
return utils.Slice2MapSlice(result.([]interface{})), nil
|
||||
}
|
||||
return nil, err
|
||||
}
|
||||
|
||||
func (a *API) RetailBatchInitData(poiCode string, foodData map[string]interface{}) (err error) {
|
||||
_, err = a.AccessAPI("retail/batchinitdata", false, map[string]interface{}{
|
||||
KeyAppPoiCode: poiCode,
|
||||
"food_data": string(utils.MustMarshal(foodData)),
|
||||
})
|
||||
return err
|
||||
}
|
||||
|
||||
func (a *API) RetailSkuPrice(poiCode string, foodData []map[string]interface{}) (err error) {
|
||||
_, err = a.AccessAPI("retail/sku/price", false, map[string]interface{}{
|
||||
KeyAppPoiCode: poiCode,
|
||||
"food_data": foodData,
|
||||
})
|
||||
return err
|
||||
}
|
||||
|
||||
func (a *API) RetailSkuStock(poiCode string, foodData []map[string]interface{}) (err error) {
|
||||
_, err = a.AccessAPI("retail/sku/stock", false, map[string]interface{}{
|
||||
KeyAppPoiCode: poiCode,
|
||||
"food_data": foodData,
|
||||
})
|
||||
return err
|
||||
}
|
||||
|
||||
func (a *API) RetailGet(poiCode, foodCode string) (food map[string]interface{}, err error) {
|
||||
result, err := a.AccessAPI("retail/get", true, map[string]interface{}{
|
||||
KeyAppPoiCode: poiCode,
|
||||
KeyAppFoodCode: foodCode,
|
||||
})
|
||||
if err == nil {
|
||||
return result.(map[string]interface{}), nil
|
||||
}
|
||||
return nil, err
|
||||
}
|
||||
|
||||
func (a *API) RetailSkuSave(poiCode, foodCode string, standardSkus, unstandardSkus []map[string]interface{}) (err error) {
|
||||
_, err = a.AccessAPI("retail/sku/save", false, map[string]interface{}{
|
||||
KeyAppPoiCode: poiCode,
|
||||
KeyAppFoodCode: foodCode,
|
||||
"standard_skus": standardSkus,
|
||||
"unstandard_skus": unstandardSkus,
|
||||
})
|
||||
return err
|
||||
}
|
||||
|
||||
func (a *API) RetailSkuSellStatus(poiCode string, foodData []map[string]interface{}, status int) (err error) {
|
||||
_, err = a.AccessAPI("retail/sku/sellStatus", false, map[string]interface{}{
|
||||
KeyAppPoiCode: poiCode,
|
||||
"food_data": foodData,
|
||||
"status": status,
|
||||
})
|
||||
return err
|
||||
}
|
||||
|
||||
func (a *API) RetailDelete(poiCode, foodCode string) (err error) {
|
||||
_, err = a.AccessAPI("retail/delete", false, map[string]interface{}{
|
||||
KeyAppPoiCode: poiCode,
|
||||
KeyAppFoodCode: foodCode,
|
||||
})
|
||||
return err
|
||||
}
|
||||
|
||||
func (a *API) RetailSkuDelete(poiCode, foodCode, skuID string) (err error) {
|
||||
_, err = a.AccessAPI("retail/sku/delete", false, map[string]interface{}{
|
||||
KeyAppPoiCode: poiCode,
|
||||
KeyAppFoodCode: foodCode,
|
||||
"sku_id": skuID,
|
||||
})
|
||||
return err
|
||||
}
|
||||
|
||||
// 就是厂商商品类别
|
||||
func (a *API) RetailGetSpTagIds() (tagIds []map[string]interface{}, err error) {
|
||||
result, err := a.AccessAPI("retail/getSpTagIds", true, nil)
|
||||
if err == nil {
|
||||
return utils.Slice2MapSlice(result.([]interface{})), nil
|
||||
}
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// 此接口将申请授权后方可接入
|
||||
func (a *API) RetailCatSkuBatchDelete(poiCode string, catNames []string, secondaryCatNames []string, foodCodes []string) (err error) {
|
||||
params := map[string]interface{}{
|
||||
KeyAppPoiCode: poiCode,
|
||||
}
|
||||
if len(catNames) > 0 {
|
||||
params["category_names"] = strings.Join(catNames, ",")
|
||||
}
|
||||
if len(secondaryCatNames) > 0 {
|
||||
params["secondary_category_names"] = strings.Join(secondaryCatNames, ",")
|
||||
}
|
||||
if len(foodCodes) > 0 {
|
||||
params["app_food_codes"] = strings.Join(foodCodes, ",")
|
||||
}
|
||||
_, err = a.AccessAPI("retailCat/batchdelete/catandretail", false, params)
|
||||
return err
|
||||
}
|
||||
|
||||
//////////////////////
|
||||
// 私有辅助函数
|
||||
func interface2Cat(data interface{}, level int) (cat *RetailCategoryInfo) {
|
||||
mapData, ok := data.(map[string]interface{})
|
||||
if ok {
|
||||
cat = &RetailCategoryInfo{
|
||||
Name: utils.Interface2String(mapData["name"]),
|
||||
Sequence: int(utils.Interface2Int64WithDefault(mapData["sequence"], 0)),
|
||||
Level: level,
|
||||
}
|
||||
children := mapData["children"]
|
||||
if children != nil {
|
||||
cat.Children = interface2CatList(children, level+1, nil)
|
||||
}
|
||||
}
|
||||
return cat
|
||||
}
|
||||
|
||||
func interface2CatList(data interface{}, level int, interface2CatHandler func(data interface{}, level int) (cat *RetailCategoryInfo)) (cats []*RetailCategoryInfo) {
|
||||
if interface2CatHandler == nil {
|
||||
interface2CatHandler = interface2Cat
|
||||
}
|
||||
maps, ok := data.([]interface{})
|
||||
if ok {
|
||||
cats = make([]*RetailCategoryInfo, len(maps))
|
||||
for index, v := range maps {
|
||||
cats[index] = interface2CatHandler(v, level)
|
||||
}
|
||||
}
|
||||
return cats
|
||||
}
|
||||
69
platformapi/mtwmapi/retail_test.go
Normal file
69
platformapi/mtwmapi/retail_test.go
Normal file
@@ -0,0 +1,69 @@
|
||||
package mtwmapi
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"git.rosy.net.cn/baseapi/utils"
|
||||
)
|
||||
|
||||
func TestRetailCatList(t *testing.T) {
|
||||
result, err := api.RetailCatList(testPoiCode)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
t.Log(utils.Format4Output(result, false))
|
||||
}
|
||||
|
||||
func TestRetailCatUpdate(t *testing.T) {
|
||||
// err := api.RetailCatUpdate(testPoiCode, "测试一级类别", "测试一级类别2", "", 2)
|
||||
err := api.RetailCatUpdate(testPoiCode, "测试一级类别", "测试一级类别", "", 2)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
}
|
||||
func TestRetailCatDelete(t *testing.T) {
|
||||
var err error
|
||||
err = api.RetailCatDelete(testPoiCode, utils.GetUpperUUID())
|
||||
if err == nil {
|
||||
t.Fatal("should return error that can not find such cat")
|
||||
}
|
||||
uniqueCatName := "一二三四五六七八九十"
|
||||
// uniqueCatName := "1234567890" //fmt.Sprintf("CAT%d", time.Now().Unix())
|
||||
err = api.RetailCatUpdate(testPoiCode, "", uniqueCatName, "", 15)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
err = api.RetailCatDelete(testPoiCode, uniqueCatName)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestRetailList(t *testing.T) {
|
||||
result, err := api.RetailList(testPoiCode, 0, GeneralMaxLimit)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if len(result) == 0 {
|
||||
t.Fatal("should have items")
|
||||
}
|
||||
// t.Log(utils.Format4Output(result, false))
|
||||
}
|
||||
|
||||
func TestRetailGetSpTagIds(t *testing.T) {
|
||||
result, err := api.RetailGetSpTagIds()
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if len(result) == 0 {
|
||||
t.Fatal("should have items")
|
||||
}
|
||||
// t.Log(utils.Format4Output(result, false))
|
||||
}
|
||||
|
||||
func TestRetailCatSkuBatchDelete(t *testing.T) {
|
||||
err := api.RetailCatSkuBatchDelete(testPoiCode, []string{"测试一级类别"}, nil, nil)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
}
|
||||
42
platformapi/mtwmapi/shipping.go
Normal file
42
platformapi/mtwmapi/shipping.go
Normal file
@@ -0,0 +1,42 @@
|
||||
package mtwmapi
|
||||
|
||||
import "git.rosy.net.cn/baseapi/utils"
|
||||
|
||||
const (
|
||||
PoiOpenLevelNormal = 1
|
||||
PoiOpenLevelHaveRest = 3
|
||||
PoiOnline = 1
|
||||
PoiOffline = 0
|
||||
)
|
||||
|
||||
func (a *API) ShippingSave(poiCode string, area string, minPrice, shippingFee float32) (err error) {
|
||||
_, err = a.AccessAPI("shipping/save", false, map[string]interface{}{
|
||||
KeyAppPoiCode: poiCode,
|
||||
"app_shipping_code": 1,
|
||||
"type": 1,
|
||||
"area": area,
|
||||
"min_price": minPrice,
|
||||
"shipping_fee": shippingFee,
|
||||
})
|
||||
return err
|
||||
}
|
||||
|
||||
func (a *API) ShippingList(poiCode string) (shippingList []map[string]interface{}, err error) {
|
||||
result, err := a.AccessAPI("shipping/list", true, map[string]interface{}{
|
||||
KeyAppPoiCode: poiCode,
|
||||
})
|
||||
if err == nil {
|
||||
return utils.Slice2MapSlice(result.([]interface{})), nil
|
||||
}
|
||||
return nil, err
|
||||
}
|
||||
|
||||
func (a *API) ShippingFetch(poiCode string) (shippingList []map[string]interface{}, err error) {
|
||||
result, err := a.AccessAPI("shipping/fetch", true, map[string]interface{}{
|
||||
KeyAppPoiCode: poiCode,
|
||||
})
|
||||
if err == nil {
|
||||
return utils.Slice2MapSlice(result.([]interface{})), nil
|
||||
}
|
||||
return nil, err
|
||||
}
|
||||
30
platformapi/mtwmapi/shipping_test.go
Normal file
30
platformapi/mtwmapi/shipping_test.go
Normal file
@@ -0,0 +1,30 @@
|
||||
package mtwmapi
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"git.rosy.net.cn/baseapi/utils"
|
||||
)
|
||||
|
||||
func TestShippingSave(t *testing.T) {
|
||||
err := api.ShippingSave(testPoiCode, `[{"x":39941199,"y":116385384},{"x":39926983,"y":116361694},{"x":39921586,"y":116398430}]`, 0, 0)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestShippingList(t *testing.T) {
|
||||
result, err := api.ShippingList(testPoiCode)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
t.Log(utils.Format4Output(result, false))
|
||||
}
|
||||
|
||||
func TestShippingFetch(t *testing.T) {
|
||||
result, err := api.ShippingFetch(testPoiCode)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
t.Log(utils.Format4Output(result, false))
|
||||
}
|
||||
@@ -215,3 +215,12 @@ func RemoveGeneralMapKeys(obj map[string]interface{}, keys ...string) map[string
|
||||
}
|
||||
return obj
|
||||
}
|
||||
|
||||
func FilterMapNilMembers(mapData map[string]interface{}) map[string]interface{} {
|
||||
for k, v := range mapData {
|
||||
if v == nil {
|
||||
delete(mapData, k)
|
||||
}
|
||||
}
|
||||
return mapData
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user