848 lines
31 KiB
Go
848 lines
31 KiB
Go
package mtwmapi
|
||
|
||
import (
|
||
"encoding/json"
|
||
"errors"
|
||
"fmt"
|
||
"git.rosy.net.cn/baseapi/utils"
|
||
"strings"
|
||
"time"
|
||
)
|
||
|
||
const (
|
||
MaxBatchPullPhoneNumberLimit = 1000
|
||
)
|
||
|
||
// http://developer.waimai.meituan.com/home/doc/food/99
|
||
const (
|
||
OrderStatusUserCommitted = "1" // 用户已提交订单
|
||
OrderStatusNew = "2" // 向商家推送订单
|
||
OrderStatusReceived = "3" // 商家已收到
|
||
OrderStatusAccepted = "4" // 商家已确认
|
||
OrderStatusDelivering = "6" // 订单配送中
|
||
OrderStatusDelivered = "7" // 订单已送达
|
||
OrderStatusFinished = "8" // 订单已完成
|
||
OrderStatusCanceled = "9" // 订单已取消
|
||
)
|
||
|
||
const (
|
||
WaybillStatusWait4Delivery = "0" // 配送单发往配送
|
||
WaybillStatusPending = "5" // 配送压单
|
||
WaybillStatusAccepted = "10" // 配送单已确认
|
||
WaybillStatusCourierArrived = "15" // 骑手已到店
|
||
WaybillStatusPickedup = "20" // 骑手已取餐
|
||
WaybillStatusDelivered = "40" // 骑手已送达
|
||
WaybillStatusCanceled = "100" // 配送单已取消
|
||
)
|
||
|
||
// APP方URL 推送用户或客服取消订单(必接)
|
||
const (
|
||
CancelReasonAcceptTimeout = 1001 // 系统取消,超时未确认
|
||
CancelReasonPayTimeout = 1002 // 系统取消,在线支付订单15分钟未支付
|
||
CancelReasonPayCanceled = 1101 // 用户取消,在线支付中取消
|
||
CancelReasonCancelBeforeAccepted = 1102 // 用户取消,商家确认前取消
|
||
CancelReasonRefundCanceled = 1103 // 用户取消,用户退款取消
|
||
CancelReasonWrongOrder = 1201 // 客服取消,用户下错单
|
||
CancelReasonUserTest = 1202 // 客服取消,用户测试
|
||
CancelReasonDuplicatedOrder = 1203 // 客服取消,重复订单
|
||
CancelReasonCSOther = 1204 // 客服取消,其他原因
|
||
CancelReasonOther = 1301 // 其他原因
|
||
)
|
||
|
||
const (
|
||
ResTypePending = 0 // 未处理
|
||
ResTypeMerchantRefused = 1 // 商家驳回退款请求
|
||
ResTypeMerchantAgreed = 2 // 商家同意退款
|
||
ResTypeCSRefused = 3 // 客服驳回退款请求
|
||
ResTypeCSAgreed = 4 // 客服帮商家同意退款
|
||
ResTypeTimeoutAutoAgreed = 5 // 超过3小时自动同意
|
||
ResTypeAutoAgreed = 6 // 系统自动确认
|
||
ResTypeUserCancelApply = 7 // 用户取消退款申请
|
||
ResTypeUserCancelComplain = 8 // 用户取消退款申诉
|
||
)
|
||
|
||
const (
|
||
NotifyTypeApply = "apply" // 发起全款退款
|
||
NotifyTypePartyApply = "part" // 发起部分退款
|
||
NotifyTypeSuccess = "agree" // 确认退款
|
||
NotifyTypeReject = "reject" // 驳回退款
|
||
NotifyTypeCancelRefund = "cancelRefund" // 用户取消退款申请
|
||
NotifyTypeCancelRefundComplaint = "cancelRefundComplaint" // 用户取消退款申诉
|
||
)
|
||
|
||
const (
|
||
OrderPickTypeNormal = 0 // 普通(配送)
|
||
OrderPickTypeSelf = 1 // 用户到店自取
|
||
)
|
||
|
||
const (
|
||
UserApplyCancelWaitMinute = 30 // 用户申请退款后,商家未在30分钟内(大连锁商家为3小时内)处理退款请求,系统将自动同意退款
|
||
)
|
||
|
||
const (
|
||
RefundTypeAll = 1
|
||
RefundTypePart = 2
|
||
)
|
||
|
||
const (
|
||
ExtrasPromotionTypeTaoCanZeng = 4 // 套餐赠
|
||
ExtrasPromotionTypeManZeng = 5 // 满赠
|
||
|
||
ExtrasPromotionTypeTeJiaCai = 7 // 特价菜
|
||
ExtrasPromotionTypeZheKouCai = 17 // 折扣菜
|
||
ExtrasPromotionTypeSecondHalfPrice = 20 // 第2份半价活动
|
||
ExtrasPromotionTypeShanGouBaoPin = 56 // 闪购爆品
|
||
)
|
||
|
||
const (
|
||
MaxGap4GetOrderIdByDaySeq = 100
|
||
)
|
||
|
||
type RefundSku struct {
|
||
AppFoodCode string `json:"app_food_code"`
|
||
SkuID string `json:"sku_id,omitempty"`
|
||
Count int `json:"count"`
|
||
ItemID string `json:"item_id,omitempty"`
|
||
ActualWeight float64 `json:"actual_weight,omitempty"`
|
||
}
|
||
|
||
type RefundSkuDetail struct {
|
||
AppFoodCode string `json:"app_food_code"`
|
||
BoxNum float64 `json:"box_num"`
|
||
BoxPrice float64 `json:"box_price"`
|
||
Count int `json:"count"`
|
||
FoodName string `json:"food_name"`
|
||
FoodPrice float64 `json:"food_price"`
|
||
OriginFoodPrice float64 `json:"origin_food_price"`
|
||
RefundPrice float64 `json:"refund_price"`
|
||
SkuID string `json:"sku_id"`
|
||
Spec string `json:"spec"`
|
||
}
|
||
|
||
type RefundDetail struct {
|
||
TotalFoodAmount string `json:"total_food_amount"`
|
||
BoxAmount string `json:"box_amount"`
|
||
ActivityPoiAmount string `json:"activity_poi_amount"`
|
||
ActivityMeituanAmount string `json:"activity_meituan_amount"`
|
||
ActivityAgentAmount string `json:"activity_agent_amount"`
|
||
PlatformChargeFee string `json:"platform_charge_fee"`
|
||
SettleAmount string `json:"settle_amount"`
|
||
Productpreferences string `json:"productpreferences"`
|
||
NotProductpreferences string `json:"not_productpreferences"`
|
||
}
|
||
|
||
type RefundOrderDetail struct {
|
||
ApplyReason string `json:"apply_reason"`
|
||
ApplyType int `json:"apply_type"`
|
||
CTime int64 `json:"ctime"`
|
||
Money float64 `json:"money"`
|
||
OrderID int64 `json:"order_id"`
|
||
Pictures string `json:"pictures"`
|
||
PictureList []string `json:"pictureList"`
|
||
RefundType int `json:"refund_type"`
|
||
ResReason string `json:"res_reason"`
|
||
ResType int `json:"res_type"`
|
||
UTime int64 `json:"utime"`
|
||
WmAppRetailForOrderPartRefundList []*RefundSkuDetail `json:"wmAppRetailForOrderPartRefundList"`
|
||
WmOrderIDView int64 `json:"wm_order_id_view"`
|
||
RefundPartialEstimateCharge *RefundDetail `json:"refund_partial_estimate_charge"`
|
||
}
|
||
|
||
type OrderExtraInfo struct {
|
||
ActDetailID int `json:"act_detail_id,omitempty"`
|
||
MtCharge float64 `json:"mt_charge,omitempty"`
|
||
PoiCharge float64 `json:"poi_charge,omitempty"`
|
||
ReduceFee float64 `json:"reduce_fee,omitempty"`
|
||
Remark string `json:"remark,omitempty"`
|
||
Type int `json:"type,omitempty"`
|
||
|
||
RiderFee float64 `json:"rider_fee,omitempty"`
|
||
}
|
||
|
||
type FoodInfo struct {
|
||
AppFoodCode string `json:"app_food_code"`
|
||
BoxNum float64 `json:"box_num"`
|
||
BoxPrice float64 `json:"box_price"`
|
||
CartID int `json:"cart_id"`
|
||
FoodDiscount float64 `json:"food_discount"`
|
||
FoodName string `json:"food_name"`
|
||
FoodProperty string `json:"food_property"`
|
||
Price float64 `json:"price"`
|
||
Quantity int `json:"quantity"`
|
||
SkuID string `json:"sku_id"`
|
||
Spec string `json:"spec"`
|
||
Unit string `json:"unit"`
|
||
Weight int64 `json:"weight"`
|
||
}
|
||
|
||
type CanRefundFoodInfo struct {
|
||
AppFoodCode string `json:"app_food_code"`
|
||
BoxNum float64 `json:"box_num"`
|
||
BoxPrice float64 `json:"box_price"`
|
||
Count int `json:"count"`
|
||
FoodName string `json:"food_name"`
|
||
FoodPrice float64 `json:"food_price"`
|
||
IsRefundDifference int `json:"is_refund_difference"`
|
||
OriginFoodPrice float64 `json:"origin_food_price"`
|
||
RefundPrice float64 `json:"refund_price"`
|
||
SkuID string `json:"sku_id"`
|
||
}
|
||
|
||
type WmAppOrderActDetailInfo struct {
|
||
ActID int64 `json:"act_id"`
|
||
Count int `json:"count"`
|
||
MtCharge float64 `json:"mtCharge"`
|
||
PoiCharge float64 `json:"poiCharge"`
|
||
Remark string `json:"remark"`
|
||
Type int `json:"type"`
|
||
}
|
||
|
||
type SkuBenefitDetailInfo struct {
|
||
ActivityPrice float64 `json:"activityPrice"`
|
||
AppFoodCode string `json:"app_food_code"`
|
||
BoxNumber float64 `json:"boxNumber"`
|
||
BoxPrice float64 `json:"boxPrice"`
|
||
Count int `json:"count"`
|
||
Name string `json:"name"`
|
||
OriginPrice float64 `json:"originPrice"`
|
||
SkuID string `json:"sku_id"`
|
||
TotalActivityPrice float64 `json:"totalActivityPrice"`
|
||
TotalBoxPrice float64 `json:"totalBoxPrice"`
|
||
TotalMtCharge float64 `json:"totalMtCharge"`
|
||
TotalOriginPrice float64 `json:"totalOriginPrice"`
|
||
TotalPoiCharge float64 `json:"totalPoiCharge"`
|
||
TotalReducePrice float64 `json:"totalReducePrice"`
|
||
WmAppOrderActDetails []*WmAppOrderActDetailInfo `json:"wmAppOrderActDetails"`
|
||
}
|
||
|
||
type ActOrderChargeInfo struct {
|
||
Comment string `json:"comment"`
|
||
FeeTypeDesc string `json:"feeTypeDesc"`
|
||
FeeTypeID int `json:"feeTypeId"`
|
||
MoneyCent int64 `json:"moneyCent"`
|
||
}
|
||
|
||
type PoiReceiveDetailInfo struct {
|
||
ActOrderChargeByMt []*ActOrderChargeInfo `json:"actOrderChargeByMt"`
|
||
ActOrderChargeByPoi []*ActOrderChargeInfo `json:"actOrderChargeByPoi"`
|
||
FoodShareFeeChargeByPoi int64 `json:"foodShareFeeChargeByPoi"`
|
||
LogisticsFee int64 `json:"logisticsFee"`
|
||
OnlinePayment int64 `json:"onlinePayment"`
|
||
WmPoiReceiveCent int64 `json:"wmPoiReceiveCent"`
|
||
}
|
||
|
||
type OrderInfo struct {
|
||
AppOrderCode string `json:"app_order_code"`
|
||
AppPoiCode string `json:"app_poi_code"`
|
||
AvgSendTime float64 `json:"avg_send_time"`
|
||
BackupRecipientPhone string `json:"backup_recipient_phone"`
|
||
Caution string `json:"caution"`
|
||
CityID int `json:"city_id"`
|
||
Ctime int64 `json:"ctime"`
|
||
DaySeq int `json:"day_seq"`
|
||
DeliveryTime int `json:"delivery_time"`
|
||
Detail string `json:"detail"`
|
||
DetailList []*FoodInfo `json:"detailList"`
|
||
DinnersNumber int `json:"dinners_number"`
|
||
ExpectDeliverTime int64 `json:"expect_deliver_time"`
|
||
Extras string `json:"extras"`
|
||
ExtraList []*OrderExtraInfo `json:"extraList"`
|
||
HasInvoiced int `json:"has_invoiced"`
|
||
InvoiceTitle string `json:"invoice_title"`
|
||
IsFavorites bool `json:"is_favorites"`
|
||
IsPoiFirstOrder bool `json:"is_poi_first_order"`
|
||
IsPre int `json:"is_pre"`
|
||
IsThirdShipping int `json:"is_third_shipping"`
|
||
Latitude float64 `json:"latitude"`
|
||
Longitude float64 `json:"longitude"`
|
||
LogisticsCancelTime int64 `json:"logistics_cancel_time"`
|
||
LogisticsCode string `json:"logistics_code"` // 此字段是配送方式变化后,不会改变
|
||
LogisticsCompletedTime int64 `json:"logistics_completed_time"`
|
||
LogisticsConfirmTime int64 `json:"logistics_confirm_time"`
|
||
LogisticsDispatcherMobile string `json:"logistics_dispatcher_mobile"`
|
||
LogisticsDispatcherName string `json:"logistics_dispatcher_name"`
|
||
LogisticsFetchTime int64 `json:"logistics_fetch_time"`
|
||
LogisticsID int `json:"logistics_id"`
|
||
LogisticsName string `json:"logistics_name"`
|
||
LogisticsSendTime int64 `json:"logistics_send_time"`
|
||
LogisticsStatus int `json:"logistics_status"`
|
||
OrderCompletedTime int `json:"order_completed_time"`
|
||
OrderConfirmTime int `json:"order_confirm_time"`
|
||
OrderID int64 `json:"order_id"`
|
||
OrderSendTime int `json:"order_send_time"`
|
||
OriginalPrice float64 `json:"original_price"`
|
||
PackageBagMoney int `json:"package_bag_money"`
|
||
PayType int `json:"pay_type"`
|
||
PickType int `json:"pick_type"`
|
||
PoiReceiveDetail string `json:"poi_receive_detail"`
|
||
PoiReceiveDetailPtr *PoiReceiveDetailInfo `json:"poi_receive_detail_ptr"`
|
||
RecipientAddress string `json:"recipient_address"`
|
||
RecipientName string `json:"recipient_name"`
|
||
RecipientPhone string `json:"recipient_phone"`
|
||
Remark string `json:"remark"`
|
||
Result string `json:"result"`
|
||
ShipperPhone string `json:"shipper_phone"`
|
||
ShippingFee float64 `json:"shipping_fee"`
|
||
ShippingType int `json:"shipping_type"`
|
||
SkuBenefitDetail string `json:"sku_benefit_detail"`
|
||
SkuBenefitDetailList []*SkuBenefitDetailInfo `json:"sku_benefit_detail_list"`
|
||
SourceID int `json:"source_id"`
|
||
Status int `json:"status"`
|
||
TaxpayerID string `json:"taxpayer_id"`
|
||
Total float64 `json:"total"`
|
||
TotalWeight int64 `json:"total_weight"`
|
||
Utime int64 `json:"utime"`
|
||
WmOrderIDView int64 `json:"wm_order_id_view"`
|
||
WmPoiAddress string `json:"wm_poi_address"`
|
||
WmPoiID int `json:"wm_poi_id"`
|
||
WmPoiName string `json:"wm_poi_name"`
|
||
WmPoiPhone string `json:"wm_poi_phone"`
|
||
}
|
||
|
||
type GetOrderActDetailParamAct struct {
|
||
Type int `json:"type,omitempty"`
|
||
ActID int64 `json:"act_id,omitempty"`
|
||
}
|
||
|
||
type GetOrderActDetailParam struct {
|
||
OrderID int64 `json:"order_id_view"`
|
||
ActParam []*GetOrderActDetailParamAct `json:"act_param,omitempty"`
|
||
}
|
||
|
||
type OrderActInfo struct {
|
||
OrderID int64 `json:"order_id_view"`
|
||
ActDetailList []*struct {
|
||
ActID int64 `json:"act_id"`
|
||
CouponDetail interface{} `json:"coupon_detail"`
|
||
EndTime int64 `json:"end_time"`
|
||
GiftsDetail interface{} `json:"gifts_detail"`
|
||
PoiDetail interface{} `json:"poi_detail"`
|
||
ProductDetail struct {
|
||
AppFoodCode string `json:"app_food_code"`
|
||
CategorySeqence int `json:"category_seqence"`
|
||
Charge string `json:"charge"`
|
||
DayLimit int `json:"day_limit"`
|
||
Name string `json:"name"`
|
||
OrderLimit int `json:"order_limit"`
|
||
Period string `json:"period"`
|
||
Policy string `json:"policy"`
|
||
SettingType int `json:"setting_type"`
|
||
UserType int `json:"user_type"`
|
||
WeeksTime string `json:"weeks_time"`
|
||
} `json:"product_detail"`
|
||
Remark string `json:"remark"`
|
||
StartTime int64 `json:"start_time"`
|
||
Status int `json:"status"`
|
||
Type int `json:"type"`
|
||
TypeName string `json:"type_name"`
|
||
} `json:"act_detail_list"`
|
||
}
|
||
|
||
type GetOrderIdByDaySeqResult struct {
|
||
Result string `json:"result"`
|
||
OrderIDs []int64 `json:"order_ids"`
|
||
}
|
||
|
||
type UserRealPhoneNumberInfo struct {
|
||
OrderID int64 `json:"order_id"`
|
||
AppPoiCode string `json:"app_poi_code"`
|
||
WmOrderIDView string `json:"wm_order_id_view"`
|
||
DaySeq int `json:"day_seq"`
|
||
RealPhoneNumber string `json:"real_phone_number"` // 订单收货人的真实手机号码
|
||
RealOrderPhoneNumber string `json:"real_order_phone_number"` // 鲜花绿植类订单预订人的真实手机号码,如无则返回空。
|
||
}
|
||
|
||
type RiderRealPhoneNumberInfo struct {
|
||
OrderID int64 `json:"order_id"`
|
||
AppPoiCode string `json:"app_poi_code"`
|
||
WmOrderIDView string `json:"wm_order_id_view"`
|
||
RiderName string `json:"rider_name"`
|
||
RiderRealPhoneNumber string `json:"rider_real_phone_number"` // 骑手真实手机号
|
||
}
|
||
|
||
// GetRiderDeliveryPath 获取骑手坐标
|
||
type GetRiderDeliveryPath struct {
|
||
//Code int64 `json:"code"`
|
||
//Msg string `json:"msg"`
|
||
//Data []struct {
|
||
Longitude int `json:"longitude"`
|
||
Latitude int `json:"latitude"`
|
||
Time int64 `json:"time"`
|
||
//} `json:"data"`
|
||
}
|
||
|
||
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
|
||
}
|
||
|
||
// 商家确认已完成拣货
|
||
// https://developer.waimai.meituan.com/home/docDetail/216
|
||
func (a *API) PreparationMealComplete(orderID int64) (err error) {
|
||
params := map[string]interface{}{
|
||
KeyOrderID: orderID,
|
||
}
|
||
_, err = a.AccessAPI("order/preparationMealComplete", true, params)
|
||
return err
|
||
}
|
||
|
||
func (a *API) OrderCancel(orderID int64, cancelReason string, cancelReasonCode int) (err error) {
|
||
_, err = a.AccessAPI("order/cancel", true, map[string]interface{}{
|
||
KeyOrderID: orderID,
|
||
"reason": cancelReason,
|
||
"reason_code": cancelReasonCode,
|
||
})
|
||
return err
|
||
}
|
||
|
||
type MtwmOrderDelivering struct {
|
||
Data string `json:"data"`
|
||
Err *Errors `json:"err"`
|
||
}
|
||
type Errors struct {
|
||
Code int64 `json:"code"`
|
||
Msg string `json:"msg"`
|
||
}
|
||
|
||
// 专快混配送转为商家自配送
|
||
// 预定单不能调用此接口
|
||
// https://developer.waimai.meituan.com/home/myquestionDetail/7382
|
||
func (a *API) OrderLogisticsChange2Self(orderID int64) (err error) {
|
||
_, err = a.AccessAPI("order/logistics/change/poi_self", false, map[string]interface{}{
|
||
KeyOrderID: orderID,
|
||
})
|
||
if err != nil && strings.Contains(err.Error(), "您的配送单已取消") {
|
||
return nil
|
||
}
|
||
return err
|
||
}
|
||
|
||
// OrderDelivering 订单自配送中不支持骑手信息
|
||
func (a *API) OrderDelivering(orderID int64) (err error) {
|
||
retval, err := a.AccessAPI("order/delivering", true, map[string]interface{}{
|
||
KeyOrderID: orderID,
|
||
})
|
||
if err != nil {
|
||
return err
|
||
}
|
||
if retval != nil {
|
||
if retval.(string) == "ok" {
|
||
return nil
|
||
} else {
|
||
return errors.New("美团系统操作异常,订单查询ng")
|
||
}
|
||
}
|
||
return err
|
||
}
|
||
|
||
func (a *API) OrderArrived(orderID int64) (err error) {
|
||
result, err := a.AccessAPI("order/arrived", true, map[string]interface{}{
|
||
KeyOrderID: orderID,
|
||
})
|
||
if err != nil {
|
||
return err
|
||
}
|
||
if result != nil {
|
||
if result.(string) == "ok" {
|
||
return nil
|
||
} else {
|
||
return errors.New("美团系统操作异常,订单查询ng")
|
||
}
|
||
}
|
||
|
||
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) OrderApplyPartRefund(orderID int64, reason string, removeSkuList []*RefundSku) (err error) {
|
||
_, err = a.AccessAPI("order/applyPartRefund", false, map[string]interface{}{
|
||
KeyOrderID: orderID,
|
||
"reason": reason,
|
||
"food_data": string(utils.MustMarshal(removeSkuList)),
|
||
})
|
||
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 {
|
||
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 nil, err
|
||
}
|
||
// 老是出现零号流水号订单,还不知道怎么生成的,这个地方直接掐断一下看看
|
||
if int(utils.MustInterface2Int64(result.(map[string]interface{})["day_seq"])) == 0 {
|
||
return nil, fmt.Errorf("订单流水号不能为0,%d", orderID)
|
||
}
|
||
return result.(map[string]interface{}), nil
|
||
}
|
||
|
||
func (a *API) OrderGetPartRefundFoods(orderID int64) (canRefundFoodList []*CanRefundFoodInfo, err error) {
|
||
params := map[string]interface{}{
|
||
KeyOrderID: orderID,
|
||
}
|
||
result, err := a.AccessAPI("order/getPartRefundFoods", true, params)
|
||
if err == nil {
|
||
err = utils.Map2StructByJson(result, &canRefundFoodList, false)
|
||
}
|
||
return canRefundFoodList, 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
|
||
}
|
||
|
||
// OrderLogisticsStatus 获取订单状态
|
||
func (a *API) OrderLogisticsStatus(orderID int64) (status *utils.RiderInfo, err error) {
|
||
result, err := a.AccessAPI("order/logistics/status", true, map[string]interface{}{
|
||
KeyOrderID: orderID,
|
||
})
|
||
if err != nil {
|
||
return nil, err
|
||
}
|
||
|
||
logistics := &utils.RiderInfo{}
|
||
data := result.(map[string]interface{})
|
||
logistics.LogisticsStatus = int(utils.Interface2Int64WithDefault(data["logistics_status"], 0))
|
||
logistics.CourierName = utils.Interface2String(data["dispatcher_name"])
|
||
logistics.CourierPhone = utils.Interface2String(data["dispatcher_mobile"])
|
||
return logistics, err
|
||
}
|
||
|
||
func (a *API) GetDeliveryPath(orderId int64, appPoiCode string) (lng, lat int, err error) {
|
||
result, err := a.AccessAPI("order/getDeliveryPath", true, map[string]interface{}{
|
||
KeyOrderID: orderId,
|
||
KeyAppPoiCode: appPoiCode,
|
||
})
|
||
if err != nil {
|
||
return 0, 0, err
|
||
}
|
||
|
||
if result == nil {
|
||
return 0, 0, nil
|
||
}
|
||
|
||
path, _ := json.Marshal(result)
|
||
riderPath := make([]*GetRiderDeliveryPath, 0, 0)
|
||
if err := json.Unmarshal(path, &riderPath); err != nil {
|
||
return 0, 0, err
|
||
}
|
||
if len(riderPath) > 0 {
|
||
return riderPath[len(riderPath)-1].Longitude, riderPath[len(riderPath)-1].Latitude, nil
|
||
}
|
||
return 0, 0, nil
|
||
}
|
||
|
||
// OrderLogisticsFee 获取订单配送费
|
||
func (a *API) OrderLogisticsFee(orderID int64) (payFee float64, err error) {
|
||
result, err := a.AccessAPI("order/logistics/status", true, map[string]interface{}{
|
||
KeyOrderID: orderID,
|
||
})
|
||
if err != nil {
|
||
return 0, err
|
||
}
|
||
data := result.(map[string]interface{})
|
||
// 美团运单,骑手确认订单之后取消的话就需要扣除全部的运单费用了,到店之后取消订单也不支付骑手配送费
|
||
if utils.Interface2Int64WithDefault(data["logistics_status"], 0) == utils.Str2Int64WithDefault(WaybillStatusCanceled, 0) {
|
||
if utils.Interface2Int64WithDefault(data["dispatcher_reach_poi_time"], 0) != 0 {
|
||
return 2, nil
|
||
} else if utils.Interface2Int64WithDefault(data["send_time"], 0) != 0 {
|
||
return utils.TryInterface2Float64(data["pay_amount"])
|
||
} else {
|
||
return 0, nil
|
||
}
|
||
}
|
||
return utils.TryInterface2Float64(data["pay_amount"])
|
||
}
|
||
|
||
// 拉取用户真实手机号(必接)
|
||
// https://developer.waimai.meituan.com/home/docDetail/222
|
||
// limit最大为MaxBatchPullPhoneNumberLimit = 1000
|
||
func (a *API) OrderBatchPullPhoneNumber(poiCode string, offset, limit int) (realNumberList []*UserRealPhoneNumberInfo, 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 {
|
||
err = utils.Map2StructByJson(result, &realNumberList, false)
|
||
}
|
||
return realNumberList, err
|
||
}
|
||
|
||
// 拉取骑手真实手机号(必接),美团2019-09-17才开始灰度上线
|
||
// https://developer.waimai.meituan.com/home/docDetail/388
|
||
// limit最大为MaxBatchPullPhoneNumberLimit = 1000
|
||
func (a *API) OrderGetRiderInfoPhoneNumber(poiCode string, offset, limit int) (realNumberList []*RiderRealPhoneNumberInfo, err error) {
|
||
params := map[string]interface{}{
|
||
"offset": offset,
|
||
"limit": limit,
|
||
}
|
||
if poiCode != "" {
|
||
params[KeyAppPoiCode] = poiCode
|
||
}
|
||
result, err := a.AccessAPI("order/getRiderInfoPhoneNumber", false, params)
|
||
if err == nil {
|
||
err = utils.Map2StructByJson(result, &realNumberList, false)
|
||
}
|
||
return realNumberList, err
|
||
}
|
||
|
||
// refundOrderDetailList不能定义为[]*RefundOrderDetail,否则会有解析错误,原因不明
|
||
func (a *API) GetOrderRefundDetail(orderID int64, refundType int) (refundOrderDetailList []*RefundOrderDetail, err error) {
|
||
params := map[string]interface{}{
|
||
"wm_order_id_view": orderID,
|
||
}
|
||
if refundType > 0 {
|
||
params["refund_type"] = refundType
|
||
}
|
||
result, err := a.AccessAPI("ecommerce/order/getOrderRefundDetail", true, params)
|
||
if err == nil {
|
||
if err = utils.Map2StructByJson(result, &refundOrderDetailList, false); err == nil {
|
||
for _, v := range refundOrderDetailList {
|
||
if v.Pictures != "" {
|
||
if err = utils.UnmarshalUseNumber([]byte(v.Pictures), &v.PictureList); err != nil {
|
||
return nil, err
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|
||
return refundOrderDetailList, err
|
||
}
|
||
|
||
func (a *API) GetOrderActDetail(queryData []*GetOrderActDetailParam) (orderActList []*OrderActInfo, err error) {
|
||
params := map[string]interface{}{
|
||
"query_data": string(utils.MustMarshal(queryData)),
|
||
}
|
||
result, err := a.AccessAPI("ecommerce/order/getOrderActDetail", true, params)
|
||
if err == nil {
|
||
err = utils.Map2StructByJson(result, &orderActList, false)
|
||
}
|
||
return orderActList, err
|
||
}
|
||
|
||
// 众包配送单追加小费
|
||
// https://developer.waimai.meituan.com/home/docDetail/158
|
||
func (a *API) OrderUpdateTip(orderID int64, tipAmount float64) (err error) {
|
||
params := map[string]interface{}{
|
||
KeyOrderID: orderID,
|
||
"tip_amount": tipAmount,
|
||
}
|
||
_, err = a.AccessAPI("order/zhongbao/update/tip", true, params)
|
||
return err
|
||
}
|
||
|
||
// 美团外卖自配送商家同步发货状态和配送信息(推荐)
|
||
// https://waimaiopen.meituan.com/api/v1/ecommerce/order/logistics/sync
|
||
func (a *API) OrderStatusAndPsInfo(params map[string]interface{}) (err error) {
|
||
delete(params, "opcode") // 美团不需要此参数
|
||
delete(params, "logistics_context") // 美团不需要此参数
|
||
_, err = a.AccessAPI("ecommerce/order/logistics/sync", false, params)
|
||
return err
|
||
}
|
||
|
||
// ApplyCompensation 取消的订单申请订单赔付
|
||
func (a *API) ApplyCompensation(param *ApplyCompensationRes) (err error) {
|
||
_, err = a.AccessAPI2("order/applyCompensation", false, utils.Struct2MapByJson(param), resultKeySuccessMsg, "")
|
||
return err
|
||
}
|
||
|
||
// 获取取消跑腿理由刘表
|
||
// https://open-shangou.meituan.com/home/docDetail/482
|
||
func (a *API) GetCancelDeliveryReason(orderId int64, appPoiCode string) (string, error) {
|
||
data, err := a.AccessAPI("order/getCancelDeliveryReason", false, map[string]interface{}{"order_id": orderId, "app_poi_code": appPoiCode})
|
||
if err != nil {
|
||
return "", err
|
||
}
|
||
|
||
str, _ := json.Marshal(data)
|
||
result := &DeliveryData{}
|
||
if err := json.Unmarshal(str, result); err != nil {
|
||
return "", err
|
||
}
|
||
|
||
list, _ := json.Marshal(&result.ReasonList)
|
||
|
||
return string(list), nil
|
||
}
|
||
|
||
// 取消跑腿配送
|
||
func (a *API) CancelLogisticsByWmOrderId(reasonCode, detailContent, appPoiCode, orderId string) error {
|
||
param := &CancelOrderParam{
|
||
ReasonCode: reasonCode,
|
||
DetailContent: detailContent,
|
||
AppPoiCode: appPoiCode,
|
||
OrderId: orderId,
|
||
}
|
||
data, err := a.AccessAPI("order/cancelLogisticsByWmOrderId", false, utils.Struct2FlatMap(param))
|
||
if err != nil {
|
||
return err
|
||
}
|
||
|
||
result := &ResultMsg{}
|
||
if err := json.Unmarshal([]byte(utils.Interface2String(data)), result); err != nil {
|
||
return err
|
||
}
|
||
if result.Data != "ok" {
|
||
return errors.New(result.Error.Msg)
|
||
}
|
||
return nil
|
||
}
|
||
|
||
// PushPrintMsg 推送订单打印消息,打印机打印时推送次消息
|
||
func (a *API) PushPrintMsg(orderId string) error {
|
||
_, err := a.AccessAPI("ecommerce/poi/keyPointUpload", false, map[string]interface{}{
|
||
"order_id": orderId,
|
||
"op_type": 1,
|
||
})
|
||
return err
|
||
}
|
||
|
||
// EcommerceGetOrderIdByPage 批量获取门店订单号,下面三个被废弃(order/getOrderIdByDaySeq,ecommerce/order/getOrderIdByDaySeq,order/getOrderDaySeq)
|
||
func (a *API) EcommerceGetOrderIdByPage(poiCode string, startTime, endTime time.Time) ([]int64, error) {
|
||
var (
|
||
vernier = ""
|
||
orderIdList = make([]int64, 0, 0)
|
||
)
|
||
params := map[string]interface{}{
|
||
KeyAppPoiCode: poiCode,
|
||
"start_time": startTime.Unix(),
|
||
"end_time": endTime.Unix(),
|
||
"status_list": "1,2,4,8,9",
|
||
"page_size": 100,
|
||
}
|
||
|
||
for {
|
||
if vernier != "" {
|
||
params["vernier"] = vernier
|
||
}
|
||
result, err := a.AccessAPI2("ecommerce/order/getOrderIdByPage", false, params, "", "")
|
||
if err != nil {
|
||
return nil, err
|
||
}
|
||
|
||
resultDate, err := json.Marshal(result)
|
||
if err != nil {
|
||
return nil, err
|
||
}
|
||
orderList := &EcommerceOrder{}
|
||
if err := json.Unmarshal(resultDate, orderList); err != nil {
|
||
return nil, err
|
||
}
|
||
|
||
for _, v := range orderList.SuccessList {
|
||
orderIdList = append(orderIdList, v.OrderId)
|
||
}
|
||
|
||
if len(orderList.SuccessList) == 100 {
|
||
vernier = orderList.SuccessMap.Vernier
|
||
} else {
|
||
return orderIdList, nil
|
||
}
|
||
}
|
||
}
|
||
|
||
// QuerySkuIsNeedUpc 查看商品是否需要填写upc
|
||
func (a *API) QuerySkuIsNeedUpc(tagId int) bool {
|
||
data, err := a.AccessAPI2("retail/field/required/info", true, map[string]interface{}{"tag_id": tagId}, "success_map", "")
|
||
if err != nil {
|
||
return false
|
||
}
|
||
upc := data.(map[string]interface{})["upc"]
|
||
upcCode := utils.Interface2Int64WithDefault(upc, 1)
|
||
return upcCode == 0
|
||
}
|
||
|
||
// 去除多以属性
|
||
func CommonAttrValueUpdate(commonAttrValue string) string {
|
||
commonAttrValueObj := make([]*CommonAttrValueList, 0, 0)
|
||
if err := json.Unmarshal([]byte(commonAttrValue), &commonAttrValueObj); err != nil {
|
||
return ""
|
||
}
|
||
|
||
result := make([]map[string]interface{}, 0, 0)
|
||
for _, v := range commonAttrValueObj {
|
||
commonAttrValueMap := utils.Struct2Map(v, "", false)
|
||
delete(commonAttrValueMap, "setAttrId")
|
||
delete(commonAttrValueMap, "setAttrName")
|
||
delete(commonAttrValueMap, "setValueList")
|
||
delete(commonAttrValueMap, "valueListSize")
|
||
delete(commonAttrValueMap, "valueListIterator")
|
||
result = append(result, commonAttrValueMap)
|
||
}
|
||
|
||
result2, _ := json.Marshal(result)
|
||
return string(result2)
|
||
}
|
||
|
||
type CommonAttrValueList struct {
|
||
AttrId int `json:"attrId"`
|
||
AttrName string `json:"attrName"`
|
||
ValueList []struct {
|
||
SetValue bool `json:"setValue"`
|
||
SetValueId bool `json:"setValueId"`
|
||
Value string `json:"value"`
|
||
ValueId int `json:"valueId"`
|
||
} `json:"valueList"`
|
||
|
||
SetAttrId bool `json:"setAttrId"`
|
||
SetAttrName bool `json:"setAttrName"`
|
||
SetValueList bool `json:"setValueList"`
|
||
ValueListIterator []struct {
|
||
Ref string `json:"$ref"`
|
||
} `json:"valueListIterator"`
|
||
ValueListSize int `json:"valueListSize"`
|
||
}
|