package mtwmapi import ( "encoding/json" "fmt" "git.rosy.net.cn/baseapi/platformapi" "git.rosy.net.cn/baseapi/utils" "io/ioutil" "math" "net/http" "strings" ) const ( CommentReplyStatusAll = -1 //全部 CommentReplyStatusNotReplied = 0 // 未回复 CommentReplyStatusReplied = 1 // 已回复 MaxCommentQueryPageSize = 20 CommentUrl = "https://shangoue.meituan.com/api/support/customer/comment/r/list" ) type OrderComment struct { AddComment string `json:"add_comment"` AddCommentTime string `json:"add_comment_time"` CommentContent string `json:"comment_content"` CommentID int64 `json:"comment_id"` CommentLables string `json:"comment_lables"` CommentLableList []string `json:"comment_lable_list"` CommentPictures string `json:"comment_pictures"` CommentTime string `json:"comment_time"` CriticFoodList string `json:"critic_food_list"` DeliveryCommentScore int `json:"delivery_comment_score"` FoodCommentScore int `json:"food_comment_score"` OrderCommentScore int `json:"order_comment_score"` PackingScore int `json:"packing_score"` PraiseFoodList string `json:"praise_food_list"` ReplyStatus int `json:"reply_status"` Result string `json:"result"` ShipTime int `json:"ship_time"` CommentOrderDetail []CommentOrderDetailList `json:"comment_order_detail"` PraiseRetailList []RetailList `json:"praise_retail_list"` // 点赞商品列表 CriticRetailList []RetailList `json:"critic_retail_list"` // 点踩商品列表 } type RetailList struct { AppSpCode string `json:"app_sp_code"` // app方商品ID SkuId string `json:"sku_id"` Name string `json:"name"` } type CommentOrderDetailList struct { FoodName string `json:"food_name"` Count int `json:"count"` } // CommentQuery 根据门店id批量查询评价信息(新版) // http://developer.waimai.meituan.com/home/docDetail/191 func (a *API) CommentQuery(poiCode string, startDateStr, endDateStr string, offset, limit int, replyStatus int) (commentList []*OrderComment, err error) { params := map[string]interface{}{ KeyAppPoiCode: poiCode, "start_time": startDateStr, "end_time": endDateStr, "pageoffset": offset, "pagesize": limit, "replyStatus": replyStatus, } if limit <= 0 { limit = math.MaxInt32 } originalOffset := offset originalLimit := limit for { if limit <= 0 { break } if limit > MaxCommentQueryPageSize { limit = MaxCommentQueryPageSize } params["pageoffset"] = offset params["pagesize"] = limit result, err := a.AccessAPI("comment/query", true, params) if err != nil { break } var batchCommentList []*OrderComment err = utils.Map2StructByJson(result, &batchCommentList, false) if err != nil { break } for _, comment := range batchCommentList { if comment.CommentLables != "" { comment.CommentLableList = strings.Split(comment.CommentLables, ",") } } commentList = append(commentList, batchCommentList...) if len(batchCommentList) < limit { break } offset += limit limit = originalLimit + originalOffset - offset } return commentList, nil } // CommentAddReply 根据评价id添加商家回复 // http://developer.waimai.meituan.com/home/docDetail/194 func (a *API) CommentAddReply(poiCode string, commentID int64, reply string) (err error) { _, err = a.AccessAPI("poi/comment/add_reply", false, map[string]interface{}{ KeyAppPoiCode: poiCode, "comment_id": commentID, "reply": reply, }) return err } func (a *API) GetComment4ShanGou(param map[string]interface{}, isPost bool, cookie string) ([]*CommentsList, error) { result, err := a.AccessStoreComment(CommentUrl, param, isPost, cookie) if err != nil { return nil, err } comments := result["data"].(map[string]interface{})["comments"].([]interface{}) if len(comments) == 0 { return nil, fmt.Errorf("暂未获取到数据") } vendorCommentsList := make([]*CommentsList, 0, 0) commentsJson, _ := json.Marshal(comments) if err := json.Unmarshal(commentsJson, &vendorCommentsList); err != nil { return nil, err } return vendorCommentsList, nil } // AccessStoreComment 拉去美团页面上的评价订单 // https://shangoue.meituan.com/api/support/customer/comment/r/list func (a *API) AccessStoreComment(fullURL string, param map[string]interface{}, isPost bool, cookie string) (retVal map[string]interface{}, err error) { err = platformapi.AccessPlatformAPIWithRetry(a.client, func() *http.Request { var request *http.Request if isPost { request, _ = http.NewRequest(http.MethodPost, fullURL, strings.NewReader(utils.Map2URLValues(param).Encode())) request.Header.Set("Cookie", cookie) request.Header.Set("Content-Type", "application/x-www-form-urlencoded") request.Header.Set("accept", "application/json, text/plain, */*") } 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") } if strings.Contains(bodyStr, "登录") || strings.Contains(bodyStr, "访问的内容") { return platformapi.ErrLevelRecoverableErr, fmt.Errorf("cookie可能过期了!") } if err == nil { if jsonResult1["error_response"] != nil { errLevel = platformapi.ErrLevelGeneralFail err = utils.NewErrorCode(jsonResult1["error_response"].(map[string]interface{})["zh_desc"].(string), jsonResult1["error_response"].(map[string]interface{})["code"].(string)) } retVal = jsonResult1 } return errLevel, err }) return retVal, err } const ( NumberCell = "-----011000010111000001101001\r\nContent-Disposition: form-data; " ) type CommentsList struct { CommentDimensionList []interface{} `json:"commentDimensionList"` MasterCleanComment string `json:"masterCleanComment"` MasterFastLabelList []interface{} `json:"masterFastLabelList"` MasterPhotoList []string `json:"masterPhotoList"` MasterVideo interface{} `json:"masterVideo"` SpuCommentList []struct { SpuId int64 `json:"spuId"` SpuName string `json:"spuName"` CleanComment string `json:"cleanComment"` FastLabelList []interface{} `json:"fastLabelList"` PhotoList []interface{} `json:"photoList"` VideoList []interface{} `json:"videoList"` } `json:"spuCommentList"` // 商品评论列表 Id int64 `json:"id"` WmPoiId int `json:"wm_poi_id"` PoiId int `json:"poi_id"` OrderId int `json:"order_id"` UserId int64 `json:"user_id"` Username string `json:"username"` ShipScore int `json:"ship_score"` Comment string `json:"comment"` Valid int `json:"valid"` Ctime int `json:"ctime"` Utime int `json:"utime"` ShipTime int `json:"ship_time"` CleanComment string `json:"clean_comment"` CommentType int `json:"comment_type"` OrderCommentScore int `json:"order_comment_score"` AddComment interface{} `json:"add_comment"` AddCommentTime int `json:"add_comment_time"` FoodCommentScore int `json:"food_comment_score"` DeliveryCommentScore int `json:"delivery_comment_score"` PictureUrls []string `json:"picture_urls"` BizLabels struct { TagEmotion int `json:"tagEmotion"` Context []interface{} `json:"context"` } `json:"bizLabels"` DeliveryLabels struct { TagEmotion int `json:"tagEmotion"` Context []string `json:"context"` } `json:"deliveryLabels"` PoiName string `json:"poiName"` CreateTime string `json:"createTime"` AddCommentTime1 interface{} `json:"addCommentTime"` OrderStatus struct { Remark string `json:"remark"` DeliveryType string `json:"delivery_type"` Details []struct { FoodName string `json:"food_name"` Count int `json:"count"` } `json:"details"` } `json:"orderStatus"` ScoreMeaning string `json:"scoreMeaning"` Category int `json:"category"` TasteScore int `json:"taste_score"` QualityScore int `json:"quality_score"` PackagingScore int `json:"packaging_score"` PraiseFoodList []string `json:"praise_food_list"` // 表扬食物清单 CriticFoodList []string `json:"critic_food_list"` // 批评食物清单 ShowSort int `json:"showSort"` ShowReport int `json:"showReport"` WmCommentReportInfo struct { HasReported int `json:"hasReported"` ReportReviewStatus int `json:"reportReviewStatus"` ReportReadStatus int `json:"reportReadStatus"` ReportReviewStatusDesc string `json:"reportReviewStatusDesc"` ReportReviewResultDesc string `json:"reportReviewResultDesc"` ReportReviewEquityDesc string `json:"reportReviewEquityDesc"` ReportReviewEquityDescBoldList []interface{} `json:"reportReviewEquityDescBoldList"` } `json:"wmCommentReportInfo"` CanModify bool `json:"canModify"` EnvironmentLabel bool `json:"environmentLabel"` OverDeliveryTime int `json:"overDeliveryTime"` OverDeliveryTimeDesc *string `json:"overDeliveryTimeDesc"` ShowOrderInfo bool `json:"showOrderInfo"` ShowOrderInfoTime int `json:"showOrderInfoTime"` InterceptDay string `json:"intercept_day"` UserPicUrl string `json:"user_pic_url"` HasAppeal bool `json:"has_appeal"` ContactDisplayStatus int `json:"contactDisplayStatus"` ContactDisableReason string `json:"contactDisableReason"` ContactDisableDetails []struct { ItemName string `json:"itemName"` ItemValue string `json:"itemValue"` StandardValue string `json:"standardValue"` Status bool `json:"status"` StatusDesc string `json:"statusDesc"` } `json:"contactDisableDetails"` FirstContactConsumer bool `json:"firstContactConsumer"` UserDel int `json:"userDel"` BlockedStatus int `json:"blockedStatus"` ECommentList []struct { Id int64 `json:"id"` WmPoiId int `json:"wmPoiId"` UserId int `json:"userId"` UserName string `json:"userName"` Comment string `json:"comment"` ToCommentId int64 `json:"toCommentId"` Type int `json:"type"` Valid int `json:"valid"` Ctime int `json:"ctime"` Utime int `json:"utime"` CleanComment string `json:"cleanComment"` CommentType int `json:"commentType"` ReplyTime string `json:"replyTime"` UserCommentCtime int `json:"userCommentCtime"` CanModify bool `json:"canModify"` CreateTime string `json:"createTime"` } `json:"eCommentList"` } func (a *API) AccessStoreComment2(param map[string]interface{}) { url := "https://shangoue.meituan.com/api/support/customer/comment/r/list" wmPoiId := NumberCell + fmt.Sprintf("name=\"wmPoiId\"\r\n\r\n%v\r\n", param["wmPoiId"]) appType := NumberCell + fmt.Sprintf("name=\"appType\"\r\n\r\n%v\r\n", param["appType"]) pageNum := NumberCell + fmt.Sprintf("name=\"pageNum\"\r\n\r\n%v\r\n", param["pageNum"]) rate := NumberCell + fmt.Sprintf("name=\"rate\"\r\n\r\n%v\r\n", param["rate"]) reply := NumberCell + fmt.Sprintf("name=\"reply\"\r\n\r\n%v\r\n", param["reply"]) context := NumberCell + fmt.Sprintf("name=\"context\"\r\n\r\n%v\r\n", param["context"]) startDate := NumberCell + fmt.Sprintf("name=\"startDate\"\r\n\r\n%v\r\n", param["startDate"]) endDate := NumberCell + fmt.Sprintf("name=\"endDate\"\r\n\r\n%v\r\n", param["endDate"]) timeType := NumberCell + fmt.Sprintf("name=\"timeType\"\r\n\r\n%v\r\n-----011000010111000001101001--\r\n\r\n", param["timeType"]) date := wmPoiId + appType + pageNum + rate + reply + context + startDate + endDate + timeType payload := strings.NewReader(date) req, _ := http.NewRequest("POST", url, payload) req.Header.Add("Cookie", `uuid_update=true; _lxsdk_cuid=18a8c469cebc8-0d5443d9234ef1-26021051-240000-18a8c469cebc8; uuid=19f97d5039dc40979c40.1701152326.1.0.0; device_uuid=!303ca77f-1f5c-4db9-8beb-2140b78696e2; pushToken=01YLhAxagh8b3tlBORRhDbRt9URjGhSdCG84G5-PA1w0*; WEBDFPID=29z4yy3y961959z509u92w75626y558381x7618yx56979584y00uw64-2016762763564-1701402763564QQKUMAGfd79fef3d01d5e9aadc18ccd4d0c95073707; epassport_token=oekR9LsWaVAP0AUg0Z6l85HJoHP0OliCE3WcoMW3Xcluu9DZWqGb3SooLjItdc4BDgNRgeGKKLZYqAtpYp3CuQ; iuuid=6150CECD00F8926053D5784EE8E108EC3F622CECA73B5042408DE46AB37C3D80; _lxsdk=6150CECD00F8926053D5784EE8E108EC3F622CECA73B5042408DE46AB37C3D80; _ga=GA1.2.2133425411.1707118186; e_u_id_3299326472=a22cdb4f9c9a66958f72f3fe4d99aba6; isNewCome=1; userTicket=ABDdQinAblqsCpXDsEdtLNYrSpYSSlbRWYlhFyUm; u=893483812; n=tel1808018; lt=AgFCI__eFEzarguG6ly07rQWhiJFBEsWRgxUWRQPXLNOqeBN-U1C0hQ56pWpHL4sm50cGWeduIqVQwAAAAC4IQAAxbA-z1YAE9bBoB64Id-_ZJV3tTdf3aKBnn8v3h5o6AOWhEVtVcGjAr7ax5V84Mej; mt_c_token=AgFCI__eFEzarguG6ly07rQWhiJFBEsWRgxUWRQPXLNOqeBN-U1C0hQ56pWpHL4sm50cGWeduIqVQwAAAAC4IQAAxbA-z1YAE9bBoB64Id-_ZJV3tTdf3aKBnn8v3h5o6AOWhEVtVcGjAr7ax5V84Mej; wpush_server_url=wss://wpush.meituan.com; acctId=57396785; token=07_OvFPg_ZTHgLwGngAZTjwG214Gt4Yxh5HMgvCfYcas*; brandId=-1; isOfflineSelfOpen=0; city_id=0; isChain=1; existBrandPoi=true; ignore_set_router_proxy=true; region_id=; region_version=0; newCategory=true; bsid=GqPMJNy9tK3SglBZptuLYqkzKquaUJg2vmQCBLmZyMxhiHF4l44JeZRFxbW5eud8t7Ejzrsq2tHbHMnJ65_prw; grayPath=newRoot; cityId=510100; provinceId=510000; city_location_id=0; location_id=0; cacheTimeMark=2024-08-02; igateApp=shangouepc; pharmacistAccount=0; timeout=2000; accessToken=GqPMJNy9tK3SglBZptuLYqkzKquaUJg2vmQCBLmZyMxhiHF4l44JeZRFxbW5eud8t7Ejzrsq2tHbHMnJ65_prw; wmPoiName=京西菜市·新生鲜(珍珠园市场店); shopCategory=market; logistics_support=1; _gw_ab_call_43208_4=TRUE; _gw_ab_43208_4=434; wmPoiId=-1; signToken="L5bPEb0sVnqry/aUnAJMgoY7TH3sRjc6Vh3YXkAPPT1V79wwnQZTpV+zNJc4Zp5bDrwDP07NvrMICxPIAYJW4ztXmoL/p3JuZ28PaGGJ1AkaN5ogSY2xA1K1HOTia30DEMB3DbmR+tLgmCqm3oQd6w=="; logan_session_token=y0ktraxb5ilbbvjryqzn; set_info={"wmPoiId":-1,"ignoreSetRouterProxy":true}; _lxsdk_s=191109f37ec-af3-533-8d7||38`) req.Header.Add("content-type", "multipart/form-data; boundary=---011000010111000001101001") res, _ := http.DefaultClient.Do(req) defer res.Body.Close() body, _ := ioutil.ReadAll(res.Body) fmt.Println(res) fmt.Println(string(body)) }