420 lines
16 KiB
Go
420 lines
16 KiB
Go
package mtwmapi
|
||
|
||
import (
|
||
"encoding/json"
|
||
"fmt"
|
||
"io/ioutil"
|
||
"net/http"
|
||
"strings"
|
||
|
||
"git.rosy.net.cn/baseapi/platformapi"
|
||
"git.rosy.net.cn/baseapi/utils"
|
||
)
|
||
|
||
const (
|
||
MtwmSCTag = "13030000"
|
||
MtwmC4Tag = "11010000"
|
||
MtwmSGTag = "10010000"
|
||
AuditTypeStore = 1 //审核类型:1-门店入驻;2-门店logo(头图)
|
||
AuditTypeStoreLogo = 2
|
||
MtStoreIsOnlineOffLine = 0 // 0 下线 3审核通过可上线
|
||
MtStoreIsOnlineOnLine = 1 // 1上线 2上单
|
||
)
|
||
|
||
type PoiCategoryInfo struct {
|
||
ID int `json:"id"`
|
||
Name string `json:"name"`
|
||
}
|
||
|
||
type PoiInfo struct {
|
||
Address string `json:"address,omitempty"`
|
||
AppID int `json:"app_id,omitempt"`
|
||
AppPoiCode string `json:"app_poi_code,omitempt"`
|
||
CityID int `json:"city_id,omitempt"`
|
||
Ctime int64 `json:"ctime,omitempt"`
|
||
InvoiceDescription string `json:"invoice_description,omitempt"`
|
||
InvoiceMinPrice int `json:"invoice_min_price,omitempt"`
|
||
InvoiceSupport int `json:"invoice_support,omitempt"`
|
||
IsOnline int `json:"is_online,omitempt"` // 0-下线;1-上线;2-上单中;3-审核通过可上线。
|
||
Latitude float64 `json:"latitude,omitempt"`
|
||
LocationID int `json:"location_id,omitempt"`
|
||
Longitude float64 `json:"longitude,omitempt"`
|
||
Name string `json:"name,omitempt"`
|
||
OpenLevel int `json:"open_level,omitempt"`
|
||
Phone string `json:"phone,omitempt"`
|
||
PicURL string `json:"pic_url,omitempt"`
|
||
PicURLLarge string `json:"pic_url_large,omitempt"`
|
||
PreBook int `json:"pre_book,omitempt"`
|
||
PreBookMaxDays int `json:"pre_book_max_days,omitempt"`
|
||
PreBookMinDays int `json:"pre_book_min_days,omitempt"`
|
||
PromotionInfo string `json:"promotion_info,omitempt"`
|
||
Remark string `json:"remark,omitempt"`
|
||
ShippingFee float64 `json:"shipping_fee,omitempt"`
|
||
ShippingTime string `json:"shipping_time,omitempt"`
|
||
StandbyTel string `json:"standby_tel,omitempt"`
|
||
TagName string `json:"tag_name,omitempt"`
|
||
ThirdTagName string `json:"third_tag_name,omitempt"`
|
||
TimeSelect int `json:"time_select,omitempt"`
|
||
Utime int64 `json:"utime,omitempt"`
|
||
LogisticsCodes string `json:"logistics_codes,omitempt"`
|
||
}
|
||
|
||
// todo 此函数在open_level与is_online开店,由于一些原因并没有成功时,好像并不会报错
|
||
// 经常会奇怪的报错:商家已接入美团配送,不可修改门店配送相关信息,但实际并没有修改任何与配送相关的东西
|
||
// 参见:https://developer.waimai.meituan.com/home/myquestionDetail/6194
|
||
func (a *API) PoiSave(poiCode string, poiParams map[string]interface{}) (err error) {
|
||
result, err := a.AccessAPI("poi/save", false, utils.MergeMaps(utils.Params2Map(KeyAppPoiCode, poiCode), poiParams))
|
||
fmt.Println(result)
|
||
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 []*PoiInfo, err error) {
|
||
result, err := a.AccessAPI("poi/mget", true, map[string]interface{}{
|
||
KeyAppPoiCodes: strings.Join(poiCodes, ","),
|
||
})
|
||
if err == nil {
|
||
err = utils.Map2StructByJson(result, &pois, false)
|
||
}
|
||
return pois, err
|
||
}
|
||
|
||
func (a *API) PoiGet(poiCode string) (poi *PoiInfo, err error) {
|
||
result, err := a.PoiMGet([]string{poiCode})
|
||
if err == nil {
|
||
if len(result) == 0 {
|
||
return nil, fmt.Errorf("找不到ID为%s的美团外卖门店", poiCode)
|
||
}
|
||
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) PoiOpen(poiCode string) (err error) {
|
||
_, err = a.AccessAPI("poi/open", false, map[string]interface{}{
|
||
KeyAppPoiCode: poiCode,
|
||
})
|
||
return err
|
||
}
|
||
|
||
// PoiOffline 接口已经下线了,现在默认打开
|
||
func (a *API) PoiOffline(poiCode string) (err error) {
|
||
return nil
|
||
_, err = a.AccessAPI("poi/offline", false, map[string]interface{}{
|
||
KeyAppPoiCode: poiCode,
|
||
})
|
||
return err
|
||
}
|
||
|
||
// PoiOnline 接口已经下线了,现在默认打开
|
||
func (a *API) PoiOnline(poiCode string) (err error) {
|
||
return nil
|
||
_, 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, shippingTime string) (err error) {
|
||
_, err = a.AccessAPI("poi/shippingtime/update", false, map[string]interface{}{
|
||
KeyAppPoiCode: poiCode,
|
||
"shipping_time": shippingTime,
|
||
})
|
||
return err
|
||
}
|
||
|
||
// 美团要求必须是jpg|jpeg图片格式,且imgName必须以jpg或jpeg结尾
|
||
// 此接口虽然要求poiCode参数,但经过测试,发现上传的图片可以跨门店使用
|
||
// imgName好像不支持中文,否则会报签名错
|
||
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
|
||
}
|
||
|
||
type PoiSettleSaveParam struct {
|
||
Type int `json:"type"` //0创建,1更新
|
||
ApplyInfos []*ApplyInfo `json:"apply_info"`
|
||
}
|
||
|
||
type ApplyInfo struct {
|
||
AppPoiCode string `json:"app_poi_code"`
|
||
SettlementID int `json:"settlement_id"`
|
||
MultiPoiBasicInfo *MultiPoiBasicInfo `json:"multi_poi_basic_info"`
|
||
MultiPoiCertInfos []*MultiPoiCertInfo `json:"multi_poi_cert_infos"`
|
||
MultiPoiShippingInfo *MultiPoiShippingInfo `json:"multi_poi_shipping_info"`
|
||
}
|
||
|
||
type MultiPoiBasicInfo struct {
|
||
Name string `json:"name"`
|
||
City string `json:"city"`
|
||
Address string `json:"address"`
|
||
Longitude string `json:"longitude"`
|
||
Latitude string `json:"latitude"`
|
||
FirstTag string `json:"first_tag"`
|
||
CallCenter string `json:"call_center"`
|
||
ContactName string `json:"contact_name"`
|
||
ContactPhone string `json:"contact_phone"`
|
||
EcommerceAccountPhone string `json:"ecommerce_account_phone"`
|
||
ShippingTime string `json:"shipping_time"`
|
||
}
|
||
|
||
type MultiPoiCertInfo struct {
|
||
IsLongTime int `json:"is_long_time"`
|
||
Type int `json:"type"`
|
||
LicenseAddress string `json:"license_address,omitempty"`
|
||
LicenseCheckDate string `json:"license_check_date,omitempty"`
|
||
LicenseCheckOrganization string `json:"license_check_organization,omitempty"`
|
||
LicenseLegalPerson string `json:"license_legal_person,omitempty"`
|
||
LicenseName string `json:"license_name,omitempty"`
|
||
LicenseNumber string `json:"license_number,omitempty"`
|
||
LicenseOperator string `json:"license_operator,omitempty"`
|
||
LicenseProject string `json:"license_project,omitempty"`
|
||
LicenseRegisterDate string `json:"license_register_date,omitempty"`
|
||
LicenseSocialCreditCode string `json:"license_social_credit_code,omitempty"`
|
||
LicenseSubject string `json:"license_subject,omitempty"`
|
||
LicensePic string `json:"license_pic"`
|
||
LicenseValidity string `json:"license_validity,omitempty"`
|
||
LicenseValidStartDate string `json:"license_valid_start_date,omitempty"`
|
||
}
|
||
|
||
type MultiPoiShippingInfo struct {
|
||
ShippingType int `json:"shipping_type"`
|
||
MinPrice float64 `json:"min_price"`
|
||
ShippingFee float64 `json:"shipping_fee"`
|
||
}
|
||
|
||
//https://open-shangou.meituan.com/home/docDetail/530
|
||
func (a *API) PoiSettleSave(poiSettleSaveParam *PoiSettleSaveParam) (vendorStoreID string, err error) {
|
||
data, _ := json.Marshal(poiSettleSaveParam.ApplyInfos)
|
||
result, err := a.AccessAPI3("ecommerce/poi/settle/multi/save", false, map[string]interface{}{
|
||
"type": poiSettleSaveParam.Type,
|
||
"apply_info": string(data),
|
||
})
|
||
if err == nil {
|
||
vendorStoreID = result.(map[string]interface{})["success_list"].([]interface{})[0].(map[string]interface{})["app_poi_code"].(string)
|
||
}
|
||
return vendorStoreID, err
|
||
}
|
||
|
||
//func (a *API) PoiSettleSave2222() (vendorStoreID string, err error) {
|
||
// result, err := a.AccessAPI3("ecommerce/poi/settle/multi/save", false, map[string]interface{}{
|
||
// "type": 0,
|
||
// "apply_info": `[{"app_poi_code":"669387","settlement_id":0,"multi_poi_basic_info":{"name":"京西菜市(优乐购)","city":"南京","address":"南京市六合区大厂街道宁六路366-7号","longitude":"118.742342","latitude":"32.230126","first_tag":"13030000","call_center":"18981810340","contact_name":"赵宇","contact_phone":"18981810340","ecommerce_account_phone":"18048531223","shipping_time":"07:00-19:00"},"multi_poi_cert_infos":[{"is_long_time":0,"type":1,"license_name":"门脸图","license_pic":"https://image.jxc4.com/image/bde4712a92fbf35f002e0960a46bad12.jpg"},{"is_long_time":0,"type":2,"license_name":"环境图","license_pic":"https://image.jxc4.com/image/8bfa70de3eb667d1edcb1c33b3adb4f8.jpg"},{"is_long_time":1,"type":5,"license_address":"南京市六合区大厂街道宁六路366-7号","license_legal_person":"赵宇","license_name":"营业执照","license_register_date":"2024-06-14","license_check_organization":"南京市江北新区管理委员会市场监督管理局","license_check_date":"2024-06-14","license_number":"92320191MADM6X3Y0MM","license_social_credit_code":"92320191MADM6X3Y0MM","license_pic":"https://image.jxc4.com/image/e585db68bc1675b83a2fc79705d42751.jpg","license_valid_start_date":"2024-06-14"},{"is_long_time":0,"type":6,"license_address":"南京市六合区大厂街道宁六路366-7号","license_legal_person":"赵宇","license_name":"食品经营许可证","license_number":"YB23201190095426","license_social_credit_code":"YB23201190095426","license_pic":"https://image.jxc4.com/image/84c3894a73cd06d337e6c3a82ca4e318.jpg","license_validity":"2024-06-14","license_valid_start_date":"2029-12-12"}],"multi_poi_shipping_info":{"shipping_type":5,"min_price":0,"shipping_fee":0}}]`,
|
||
// })
|
||
// if err == nil {
|
||
// vendorStoreID = result.(map[string]interface{})["success_list"].([]interface{})[0].(map[string]interface{})["app_poi_code"].(string)
|
||
// }
|
||
// return vendorStoreID, err
|
||
//}
|
||
|
||
type PoiSettleCategoryListResult struct {
|
||
SingleCategoryTree []struct {
|
||
LevelOneName string `json:"level_one_name"`
|
||
LevelOneCode int `json:"level_one_code"`
|
||
LevelTwoInfo []struct {
|
||
LevelTwoName string `json:"level_two_name"`
|
||
LevelTwoCode int `json:"level_two_code"`
|
||
} `json:"level_two_info"`
|
||
} `json:"single_category_tree"`
|
||
MultiCategoryTree []struct {
|
||
LevelOneName string `json:"level_one_name"`
|
||
LevelOneCode int `json:"level_one_code"`
|
||
LevelTwoInfo []struct {
|
||
LevelTwoName string `json:"level_two_name"`
|
||
LevelTwoCode int `json:"level_two_code"`
|
||
} `json:"level_two_info"`
|
||
} `json:"multi_category_tree"`
|
||
}
|
||
|
||
//查询门店经营品类列表
|
||
func (a *API) PoiSettleCategoryList() (poiSettleCategoryListResult *PoiSettleCategoryListResult, err error) {
|
||
result, err := a.AccessAPI("ecommerce/poi/settle/category/list", true, nil)
|
||
if err == nil {
|
||
utils.Map2StructByJson(result, &poiSettleCategoryListResult, false)
|
||
}
|
||
return poiSettleCategoryListResult, err
|
||
}
|
||
|
||
type PoiSettleSettlementListResult struct {
|
||
ID int `json:"id"`
|
||
Name string `json:"name"`
|
||
BankName string `json:"bank_name"`
|
||
BranchName string `json:"branch_name"`
|
||
BankNum string `json:"bank_num"`
|
||
AccountName string `json:"account_name"`
|
||
FinancialName string `json:"financial_name"`
|
||
FinancialPhone string `json:"financial_phone"`
|
||
}
|
||
|
||
//查询连锁门店结算信息
|
||
func (a *API) PoiSettleSettlementList() (poiSettleSettlementListResult *[]PoiSettleSettlementListResult, err error) {
|
||
result, err := a.AccessAPI("ecommerce/poi/settle/settlement/list", true, map[string]interface{}{
|
||
"page_num": 1,
|
||
"page_size": 50,
|
||
})
|
||
if err == nil {
|
||
utils.Map2StructByJson(result, &poiSettleSettlementListResult, false)
|
||
}
|
||
return poiSettleSettlementListResult, err
|
||
}
|
||
|
||
//批量提交门店审核
|
||
func (a *API) PoiSettleAuditSubmit(appPoiCodes []string) (err error) {
|
||
_, err = a.AccessAPI("ecommerce/poi/settle/audit/submit", false, map[string]interface{}{
|
||
"app_poi_codes": strings.Join(appPoiCodes, ","),
|
||
})
|
||
return err
|
||
}
|
||
|
||
type CommentScoreResult struct {
|
||
AppPoiCode string `json:"appPoiCode"`
|
||
AvgPoiScore float64 `json:"avgPoiScore"`
|
||
AvgTasteScore float64 `json:"avgTasteScore"`
|
||
AvgPackingScore float64 `json:"avgPackingScore"`
|
||
AvgDeliveryScore float64 `json:"avgDeliveryScore"`
|
||
}
|
||
|
||
// 通过门店ID获取当前门店评分
|
||
func (a *API) CommentScore(appPoiCode string) (commentScoreResult *CommentScoreResult, err error) {
|
||
result, err := a.AccessAPI("comment/score", true, map[string]interface{}{
|
||
"app_poi_code": appPoiCode,
|
||
})
|
||
if err == nil {
|
||
utils.Map2StructByJson(result, &commentScoreResult, false)
|
||
}
|
||
return commentScoreResult, err
|
||
}
|
||
|
||
type AuthorizationStatus struct {
|
||
AppID int `json:"app_id"`
|
||
AppPoiCode string `json:"app_poi_code"`
|
||
IsOnline int `json:"is_online"`
|
||
PoiName string `json:"poi_name"`
|
||
WmPoiID int `json:"wm_poi_id"`
|
||
}
|
||
|
||
// 获取授权门店列表
|
||
func (a *API) GetBoundList(otherStoreId string) ([]*AuthorizationStatus, error) {
|
||
param := make(map[string]interface{}, 0)
|
||
param["page_num"] = 1
|
||
param["page_size"] = 20
|
||
if otherStoreId != "" {
|
||
param["app_poi_code"] = otherStoreId
|
||
}
|
||
result, err := a.AccessAPI("ecommerce/poi/bound/list", true, param)
|
||
if err != nil {
|
||
return nil, err
|
||
}
|
||
|
||
var data []*AuthorizationStatus
|
||
if err := utils.Map2StructByJson(result, &data, false); err != nil {
|
||
return nil, err
|
||
}
|
||
|
||
return data, nil
|
||
}
|
||
|
||
type SettleAuditList struct {
|
||
AppPoiCode string `json:"app_poi_code"`
|
||
Status int `json:"status"` //任务状态:0-待完善;1-审核中;2-已驳回;4-待提审;5-审核通过;7-暂不合作;9-创建失败
|
||
//audit_type=1时有效
|
||
BaseStatus int `json:"base_status"` //基本信息模块:0-待录入;1-已录入;2-审核中;3-已驳回;4-签约中;5-签约失败;6-已生效;7-缺失
|
||
LegalPersonStatus int `json:"legal_person_status"` //法人信息模块(仅单店)
|
||
ShippingStatus int `json:"shipping_status"` //配送信息模块
|
||
QualificationStatus int `json:"qualification_status"` //资质信息模块
|
||
SettlementStatus int `json:"settlement_status"` //结算信息模块(仅连锁门店)
|
||
//audit_type=2时有效
|
||
LogoStatus int `json:"logo_status"` //门店logo审核结果:1-审核中;2-审核通过;3-已驳回
|
||
Reason string `json:"reason"` //审核描述
|
||
}
|
||
|
||
// GetSettleAuditList 批量查询门店审核状态,目前只用
|
||
func (a *API) GetSettleAuditList(appPoiCodes string) ([]*SettleAuditList, error) {
|
||
param := make(map[string]interface{}, 0)
|
||
param["app_poi_codes"] = appPoiCodes
|
||
param["audit_type"] = AuditTypeStoreLogo
|
||
|
||
result, err := a.AccessAPI("ecommerce/poi/settle/audit/list", true, param)
|
||
if err != nil {
|
||
return nil, err
|
||
}
|
||
|
||
var data []*SettleAuditList
|
||
if err := utils.Map2StructByJson(result, &data, false); err != nil {
|
||
return nil, err
|
||
}
|
||
|
||
return data, nil
|
||
}
|