package mtwmapi import ( "fmt" "net/http" "strings" "git.rosy.net.cn/baseapi/platformapi" "git.rosy.net.cn/baseapi/utils" ) const ( userURL = "http://i.waimai.meituan.com" orderURL = "https://shangoue.meituan.com" actURL = "https://waimaieapp.meituan.com" ) const ( ResponseCodeSuccess = 0 ) type ListShopItem struct { Address string `json:"address"` AveragePriceTip string `json:"averagePriceTip"` DeliveryTimeTip string `json:"deliveryTimeTip"` DeliveryType int `json:"deliveryType"` Distance string `json:"distance"` MinPriceTip string `json:"minPriceTip"` MonthSalesTip string `json:"monthSalesTip"` MtWmPoiID string `json:"mtWmPoiId"` PicURL string `json:"picUrl"` PoiTypeIcon string `json:"poiTypeIcon"` ShippingFeeTip string `json:"shippingFeeTip"` ShippingTime string `json:"shipping_time"` ShopName string `json:"shopName"` Status int `json:"status"` StatusDesc string `json:"statusDesc"` WmPoiScore int `json:"wmPoiScore"` } var ( actionHostMap = map[string]string{ "v2/order/receive/processed/w/distribute/tipAmount/v2": orderURL, "v2/order/receive/processed/r/distribute/list/v2": orderURL, "reuse/sc/product/packageprice/w/update": orderURL, "reuse/sc/product/packageprice/r/get": orderURL, "reuse/sc/product/retail/r/getStandardProductListWithCond": orderURL, "api/sg/promotion/invite/centerList": actURL, "api/invite/detail": actURL, "v2/logon/setToken": orderURL, "reuse/sc/product/retail/r/searchListPage": orderURL, } ) func getRootURL(subURL string) (rootURL string) { rootURL = actionHostMap[subURL] if rootURL == "" { rootURL = userURL } return rootURL } func (a *API) AccessUserPage2(subURL string, params map[string]interface{}, isPost bool) (retVal map[string]interface{}, err error) { if a.GetCookieCount() == 0 { return nil, fmt.Errorf("需要设置User Cookie才能使用此方法") } rootURL := getRootURL(subURL) err = platformapi.AccessPlatformAPIWithRetry(a.client, func() *http.Request { var request *http.Request if isPost { fullURL := utils.GenerateGetURL(rootURL, subURL, nil) request, _ = http.NewRequest(http.MethodPost, fullURL, strings.NewReader(utils.Map2URLValues(params).Encode())) request.Header.Set("charset", "UTF-8") request.Header.Set("Content-Type", "application/x-www-form-urlencoded") request.Header.Set("User-Agent", "Mozilla/5.0 (iPhone; CPU iPhone OS 11_0 like Mac OS X) AppleWebKit/604.1.38 (KHTML, like Gecko) Version/11.0 Mobile/15A372 Safari/604.1") request.Header.Set("Pragma", "no-cache") if subURL == `reuse/sc/product/retail/r/searchListPage` { //request.Header.Set("") } } else { request, _ = http.NewRequest(http.MethodGet, utils.GenerateGetURL(rootURL, subURL, params), nil) } a.FillRequestCookies(request) return request }, a.config, func(response *http.Response, bodyStr string, jsonResult1 map[string]interface{}) (errLevel string, err error) { if jsonResult1 == nil { return platformapi.ErrLevelRecoverableErr, fmt.Errorf("mapData is nil") } retVal = jsonResult1 if jsonResult1["code"] == nil { return platformapi.ErrLevelGeneralFail, fmt.Errorf("返回结果格式不正常") } code := int(utils.MustInterface2Int64(jsonResult1["code"])) if code == ResponseCodeSuccess { retVal, _ = jsonResult1["data"].(map[string]interface{}) return platformapi.ErrLevelSuccess, nil } newErr := utils.NewErrorIntCode(jsonResult1["msg"].(string), code) return platformapi.ErrLevelCodeIsNotOK, newErr }) return retVal, err } func (a *API) AccessUserPage(subURL string, params map[string]interface{}) (retVal map[string]interface{}, err error) { return a.AccessUserPage2(subURL, params, true) } func (a *API) AccessUserPage3(subURL string, params map[string]interface{}) (retVal map[string]interface{}, err error) { return a.AccessUserPage2(subURL, params, false) } func (a *API) GetStoreList(lng, lat float64) (shopList []*ListShopItem, err error) { params := map[string]interface{}{ "sortId": 1, "navigateType": 101578, "firstCategoryId": 101578, "secondCategoryId": 101578, "initialLng": lng, "initialLat": lat, "geoType": 2, "wm_longitude": int(lng * 1000000), "wm_latitude": int(lat * 1000000), } startIndex := 0 for { params["startIndex"] = startIndex result, err := a.AccessUserPage("openh5/channel/kingkongshoplist", params) if err != nil { return shopList, err } var batchShopList []*ListShopItem if err = utils.Map2StructByJson(result["shopList"], &batchShopList, false); err != nil { return shopList, err } shopList = append(shopList, batchShopList...) if poiHasNextPage, ok := result["poiHasNextPage"].(bool); !ok || !poiHasNextPage { break } startIndex++ } return shopList, nil } func (a *API) GetStoreInfo(storeID string) (storeInfo map[string]interface{}, err error) { params := map[string]interface{}{ "mtWmPoiId": storeID, } retVal, err := a.AccessUserPage("openh5/poi/info", params) return retVal, err } type GetStandardProductListWithCondResult struct { IsMedicare bool `json:"isMedicare"` SpVideoVo interface{} `json:"spVideoVo"` LockStatus int `json:"lockStatus"` LockTips interface{} `json:"lockTips"` SpPicContent string `json:"spPicContent"` ExistInPoi bool `json:"existInPoi"` MonthSale int `json:"monthSale"` Skus []struct { ShelfNum string `json:"shelfNum"` ItemNum string `json:"itemNum"` LimitStock int `json:"limitStock"` Sequence int `json:"sequence"` Weight float64 `json:"weight"` Price interface{} `json:"price"` WeightUnit string `json:"weightUnit"` SkuAttrs interface{} `json:"skuAttrs"` Spec string `json:"spec"` Stock interface{} `json:"stock"` MinOrderCount int `json:"minOrderCount"` Unit string `json:"unit"` UpcCode string `json:"upcCode"` BizValue interface{} `json:"bizValue"` ProductName interface{} `json:"productName"` BoxPrice float64 `json:"boxPrice"` BoxNum int `json:"boxNum"` ID int `json:"id"` } `json:"skus"` CategoryAttrMap struct { Num1200000088 struct { SupportFilter int `json:"supportFilter"` Application string `json:"application"` OptionMaxSize int `json:"optionMaxSize"` TextMaxLength int `json:"textMaxLength"` CharacterType string `json:"characterType"` SupportExtend string `json:"supportExtend"` AttrName string `json:"attrName"` Sequence int `json:"sequence"` Level int `json:"level"` InputType int `json:"inputType"` WmPoiID int `json:"wmPoiId"` CategoryID int `json:"categoryId"` IsLeaf int `json:"isLeaf"` SpuID int `json:"spuId"` ValueList []struct { Sequence int `json:"sequence"` Text interface{} `json:"text"` IsLeaf int `json:"isLeaf"` ValueID int `json:"valueId"` ValueIDPath string `json:"valueIdPath"` ValuePath string `json:"valuePath"` Selected int `json:"selected"` Value string `json:"value"` } `json:"valueList"` AttrID int `json:"attrId"` AttrType int `json:"attrType"` TemplateID int `json:"templateId"` IsRequired int `json:"isRequired"` ID int `json:"id"` } `json:"1200000088"` Num1200000094 struct { SupportFilter int `json:"supportFilter"` Application string `json:"application"` OptionMaxSize int `json:"optionMaxSize"` TextMaxLength int `json:"textMaxLength"` CharacterType string `json:"characterType"` SupportExtend string `json:"supportExtend"` AttrName string `json:"attrName"` Sequence int `json:"sequence"` Level int `json:"level"` InputType int `json:"inputType"` WmPoiID int `json:"wmPoiId"` CategoryID int `json:"categoryId"` IsLeaf int `json:"isLeaf"` SpuID int `json:"spuId"` ValueList []struct { Sequence int `json:"sequence"` Text interface{} `json:"text"` IsLeaf int `json:"isLeaf"` ValueID int `json:"valueId"` ValueIDPath string `json:"valueIdPath"` ValuePath string `json:"valuePath"` Selected int `json:"selected"` Value string `json:"value"` } `json:"valueList"` AttrID int `json:"attrId"` AttrType int `json:"attrType"` TemplateID int `json:"templateId"` IsRequired int `json:"isRequired"` ID int `json:"id"` } `json:"1200000094"` Num1200000135 struct { SupportFilter int `json:"supportFilter"` Application string `json:"application"` OptionMaxSize int `json:"optionMaxSize"` TextMaxLength int `json:"textMaxLength"` CharacterType string `json:"characterType"` SupportExtend string `json:"supportExtend"` AttrName string `json:"attrName"` Sequence int `json:"sequence"` Level int `json:"level"` InputType int `json:"inputType"` WmPoiID int `json:"wmPoiId"` CategoryID int `json:"categoryId"` IsLeaf int `json:"isLeaf"` SpuID int `json:"spuId"` ValueList []struct { Sequence int `json:"sequence"` Text interface{} `json:"text"` IsLeaf int `json:"isLeaf"` ValueID int `json:"valueId"` ValueIDPath interface{} `json:"valueIdPath"` ValuePath interface{} `json:"valuePath"` Selected int `json:"selected"` Value string `json:"value"` } `json:"valueList"` AttrID int `json:"attrId"` AttrType int `json:"attrType"` TemplateID int `json:"templateId"` IsRequired int `json:"isRequired"` ID int `json:"id"` } `json:"1200000135"` Num1200000210 struct { SupportFilter int `json:"supportFilter"` Application string `json:"application"` OptionMaxSize int `json:"optionMaxSize"` TextMaxLength int `json:"textMaxLength"` CharacterType string `json:"characterType"` SupportExtend string `json:"supportExtend"` AttrName string `json:"attrName"` Sequence int `json:"sequence"` Level int `json:"level"` InputType int `json:"inputType"` WmPoiID int `json:"wmPoiId"` CategoryID int `json:"categoryId"` IsLeaf int `json:"isLeaf"` SpuID int `json:"spuId"` ValueList []struct { Sequence int `json:"sequence"` Text interface{} `json:"text"` IsLeaf int `json:"isLeaf"` ValueID int `json:"valueId"` ValueIDPath interface{} `json:"valueIdPath"` ValuePath interface{} `json:"valuePath"` Selected int `json:"selected"` Value string `json:"value"` } `json:"valueList"` AttrID int `json:"attrId"` AttrType int `json:"attrType"` TemplateID int `json:"templateId"` IsRequired int `json:"isRequired"` ID int `json:"id"` } `json:"1200000210"` } `json:"categoryAttrMap"` SpuSaleAttrMap interface{} `json:"spuSaleAttrMap"` OriginName string `json:"originName"` SetOrigin bool `json:"setOrigin"` SetWeightUnit bool `json:"setWeightUnit"` AvgPrice int `json:"avgPrice"` SetAvgPrice bool `json:"setAvgPrice"` SetEan bool `json:"setEan"` SetShelfStatus bool `json:"setShelfStatus"` ShelfStatus int `json:"shelfStatus"` RefCount int `json:"refCount"` SetRefCount bool `json:"setRefCount"` IsReceipt int `json:"is_receipt"` SetPic bool `json:"setPic"` CheckerID int `json:"checkerId"` SetCheckerID bool `json:"setCheckerId"` CheckerName string `json:"checkerName"` SetCheckerName bool `json:"setCheckerName"` CheckRemark interface{} `json:"checkRemark"` SetCheckRemark bool `json:"setCheckRemark"` CheckTime int `json:"checkTime"` SetCheckTime bool `json:"setCheckTime"` IsMulitEan int `json:"isMulitEan"` SetIsMulitEan bool `json:"setIsMulitEan"` SetCategoryNamePath bool `json:"setCategoryNamePath"` CategoryIDPath string `json:"categoryIdPath"` SetCategoryIDPath bool `json:"setCategoryIdPath"` SetBrandNamePath bool `json:"setBrandNamePath"` SuggestedPrice int `json:"suggestedPrice"` SetSuggestedPrice bool `json:"setSuggestedPrice"` SetRiseMax bool `json:"setRiseMax"` SetDropMax bool `json:"setDropMax"` ExpPeriod int `json:"expPeriod"` SetExpPeriod bool `json:"setExpPeriod"` ExpUnit int `json:"expUnit"` SetExpUnit bool `json:"setExpUnit"` SuppleFact string `json:"suppleFact"` SetSuppleFact bool `json:"setSuppleFact"` SubOrigin int `json:"subOrigin"` SetSubOrigin bool `json:"setSubOrigin"` SalePriceWeight int `json:"salePriceWeight"` SetSalePriceWeight bool `json:"setSalePriceWeight"` SrcPic string `json:"srcPic"` SetSrcPic bool `json:"setSrcPic"` BrandZhName interface{} `json:"brandZhName"` SetBrandZhName bool `json:"setBrandZhName"` BrandEnName interface{} `json:"brandEnName"` SetBrandEnName bool `json:"setBrandEnName"` SetIsReceipt bool `json:"setIs_receipt"` ReceiptorID int `json:"receiptorId"` SetReceiptorID bool `json:"setReceiptorId"` SpecNew float64 `json:"specNew"` SetSpecNew bool `json:"setSpecNew"` SpecUnit string `json:"specUnit"` SetSpecUnit bool `json:"setSpecUnit"` SpecCount int `json:"specCount"` SetSpecCount bool `json:"setSpecCount"` SpecCountUnit string `json:"specCountUnit"` SetSpecCountUnit bool `json:"setSpecCountUnit"` IsBigSpec int `json:"isBigSpec"` SetIsBigSpec bool `json:"setIsBigSpec"` WeightNew float64 `json:"weightNew"` SetWeightNew bool `json:"setWeightNew"` Description string `json:"description"` Sequence int `json:"sequence"` SetSize bool `json:"setSize"` Source int `json:"source"` Origin int `json:"origin"` OriginType int `json:"originType"` SetName bool `json:"setName"` SetID bool `json:"setId"` Weight int `json:"weight"` SetWeight bool `json:"setWeight"` Valid int `json:"valid"` BrandID int `json:"brandId"` CategoryName string `json:"categoryName"` CategoryID int `json:"categoryId"` WeightUnit interface{} `json:"weightUnit"` Pic string `json:"pic"` Spec string `json:"spec"` Ctime int `json:"ctime"` EanList []string `json:"eanList"` CategoryNamePath string `json:"categoryNamePath"` Utime int `json:"utime"` Unit string `json:"unit"` IsSp int `json:"isSp"` Ean string `json:"ean"` CheckStatus int `json:"checkStatus"` SpName string `json:"spName"` BrandNamePath string `json:"brandNamePath"` Cuid int `json:"cuid"` RiseMax int `json:"riseMax"` DropMax int `json:"dropMax"` SetSpName bool `json:"setSpName"` SetOriginType bool `json:"setOriginType"` SetIsSp bool `json:"setIsSp"` SetBrandID bool `json:"setBrandId"` SetCheckStatus bool `json:"setCheckStatus"` EanListSize int `json:"eanListSize"` EanListIterator []string `json:"eanListIterator"` SetEanList bool `json:"setEanList"` SetCategoryID bool `json:"setCategoryId"` SetSpec bool `json:"setSpec"` Muid int `json:"muid"` SetMuid bool `json:"setMuid"` SetSource bool `json:"setSource"` SetUnit bool `json:"setUnit"` SetSequence bool `json:"setSequence"` SetCtime bool `json:"setCtime"` SetUtime bool `json:"setUtime"` SetValid bool `json:"setValid"` SetDescription bool `json:"setDescription"` Cuname interface{} `json:"cuname"` SetCuname bool `json:"setCuname"` Muname interface{} `json:"muname"` SetMuname bool `json:"setMuname"` SetCuid bool `json:"setCuid"` SetCategoryName bool `json:"setCategoryName"` Name string `json:"name"` ID int `json:"id"` Size string `json:"size"` } //https://shangoue.meituan.com/reuse/sc/product/retail/r/getStandardProductListWithCond func (a *API) GetStandardProductListWithCond(upc string) (getStandardProductListWithCondResult *GetStandardProductListWithCondResult, err error) { params := map[string]interface{}{ "keyword": upc, "pageNo": 1, "pageSize": 20, } result, err := a.AccessUserPage("reuse/sc/product/retail/r/getStandardProductListWithCond", params) if err == nil { if len(result["list"].([]interface{})) == 0 { return nil, err } else { utils.Map2StructByJson(result["list"].([]interface{})[0], &getStandardProductListWithCondResult, false) } } return getStandardProductListWithCondResult, err } func (a *API) SetTokenPage() (err error) { params := map[string]interface{}{ "acctId": 57396785, "wmPoiId": -1, "bsid": "y-5VaK3uFxP705tpXsnJPee2sJc9dJ23LmGwYmg2kCO81d9EjD7TJrUeflcJRrqRxg9DFCNGhrJSaWYSCgXvxg", "device_uuid": "!ac34e5d7-5472-47fd-b7c4-029c1f7e7576", "token": "1bWbK5VbK50E2BmIhIH2zHB-am_y7mB37yXHm6RLZWx4*", "region_version": 0, "region_id": "", } a.SetCookieWithStr(` uuid=350a86177dd64c43b875.1619071312.1.0.0; _lxsdk_cuid=178f88ba3cec8-0db6e384ebfa36-5b1f321a-1fa400-178f88ba3cec8; _lxsdk=178f88ba3cec8-0db6e384ebfa36-5b1f321a-1fa400-178f88ba3cec8; uuid_update=true; _ga=GA1.2.2092976141.1619502287; pushToken=04OVj3PayJdT62H_Irz4BXYfNQHh9N33gDO_WFnGaovs*; device_uuid=!ac34e5d7-5472-47fd-b7c4-029c1f7e7576; mtcdn=K; lsu=; e_u_id_3299326472=e5ae16afe444349d24af7d33b66620a1; wpush_server_url=wss://wpush.meituan.com; shopCategory=food; _lxsdk_s=17b15442f31-e81-89b-533%7C%7C187 `) _, err = a.AccessUserPage3("v2/logon/setToken", params) return err }