diff --git a/business/jxutils/jxutils.go b/business/jxutils/jxutils.go index e4c8aee39..d700f5640 100644 --- a/business/jxutils/jxutils.go +++ b/business/jxutils/jxutils.go @@ -75,6 +75,8 @@ func SplitUniversalOrderID(universalOrderID string) (orderID string, vendorID in vendorID = model.VendorIDJD } else if orderIDLen == len("3022716176275221584") { vendorID = model.VendorIDELM + } else if orderIDLen == len("15380342248732") { + vendorID = model.VendorIDEBAI } else { // globals.SugarLogger.Errorf("unkown order type:%v", universalOrderID) panic(fmt.Sprintf("unkown order type:%v, orderIDLen:%d", universalOrderID, orderIDLen)) diff --git a/business/partner/purchase/ebai/callback.go b/business/partner/purchase/ebai/callback.go new file mode 100644 index 000000000..f6c474169 --- /dev/null +++ b/business/partner/purchase/ebai/callback.go @@ -0,0 +1,20 @@ +package ebai + +import ( + "git.rosy.net.cn/baseapi/platformapi/ebaiapi" + "git.rosy.net.cn/jx-callback/business/jxutils" + "git.rosy.net.cn/jx-callback/business/model" +) + +func OnCallbackMsg(msg *ebaiapi.CallbackMsg) (response *ebaiapi.CallbackResponse) { + orderID := msg.Body["order_id"].(string) + jxutils.CallMsgHandler(func() { + switch msg.Cmd { + case ebaiapi.CmdOrderCreate, ebaiapi.CmdOrderStatus: + response = curPurchaseHandler.onOrderMsg(msg) + case ebaiapi.CmdOrderDeliveryStatus: + response = curPurchaseHandler.onWaybillMsg(msg) + } + }, jxutils.ComposeUniversalOrderID(orderID, model.VendorIDEBAI)) + return response +} diff --git a/business/partner/purchase/ebai/order.go b/business/partner/purchase/ebai/order.go index 2c0107bb9..814606356 100644 --- a/business/partner/purchase/ebai/order.go +++ b/business/partner/purchase/ebai/order.go @@ -1,39 +1,188 @@ package ebai import ( + "strings" + "time" + + "git.rosy.net.cn/baseapi/platformapi/autonavi" + "git.rosy.net.cn/baseapi/platformapi/ebaiapi" + "git.rosy.net.cn/baseapi/utils" + "git.rosy.net.cn/jx-callback/business/jxutils" "git.rosy.net.cn/jx-callback/business/model" + "git.rosy.net.cn/jx-callback/business/partner" + "git.rosy.net.cn/jx-callback/globals/api" +) + +var ( + VendorStatus2StatusMap = map[string]int{ + ebaiapi.OrderStatusNew: model.OrderStatusNew, + ebaiapi.OrderStatusAccepted: model.OrderStatusAccepted, + ebaiapi.OrderStatusCourierAccepted: model.OrderStatusDelivering, + ebaiapi.OrderStatusCourierPickedup: model.OrderStatusDelivering, + ebaiapi.OrderStatusFinished: model.OrderStatusFinished, + ebaiapi.OrderStatusCanceled: model.OrderStatusCanceled, + } ) func (p *PurchaseHandler) GetStatusFromVendorStatus(vendorStatus string) int { - return 0 + if status, ok := VendorStatus2StatusMap[vendorStatus]; ok { + return status + } + return model.OrderStatusUnknown } + func (p *PurchaseHandler) GetOrder(vendorOrderID string) (order *model.GoodsOrder, err error) { + result, err := api.EbaiAPI.OrderGet(vendorOrderID) + // globals.SugarLogger.Info(result) + if err == nil { + shopMap := result["shop"].(map[string]interface{}) + orderMap := result["order"].(map[string]interface{}) + userMap := result["user"].(map[string]interface{}) + order = &model.GoodsOrder{ + VendorOrderID: vendorOrderID, + VendorID: model.VendorIDEBAI, + VendorStoreID: shopMap["baidu_shop_id"].(string), + StoreID: int(utils.Str2Int64WithDefault(utils.Interface2String(shopMap["id"]), 0)), + StoreName: shopMap["name"].(string), + ConsigneeName: utils.FilterMb4(userMap["name"].(string)), + ConsigneeMobile: userMap["phone"].(string), + ConsigneeAddress: utils.FilterMb4(userMap["address"].(string)), + CoordinateType: model.CoordinateTypeBaiDu, + BuyerComment: utils.FilterMb4(strings.Trim(utils.Interface2String(orderMap["remark"]), "\n\r\t ")), + ExpectedDeliveredTime: getTimeFromTimestampStr(utils.Interface2String(orderMap["send_time"])), + VendorStatus: utils.Int64ToStr(utils.MustInterface2Int64(orderMap["status"])), + OrderSeq: int(utils.Str2Int64(utils.Interface2String(result["order_index"]))), + StatusTime: getTimeFromTimestampStr(utils.Interface2String(orderMap["create_time"])), + OriginalData: utils.FilterMb4(string(utils.MustMarshal(result))), + ActualPayPrice: utils.MustInterface2Int64(orderMap["user_fee"]), + Skus: []*model.OrderSku{}, + } + order.Status = p.GetStatusFromVendorStatus(order.VendorStatus) + if utils.MustInterface2Int64(orderMap["send_immediately"]) == 1 { + order.BusinessType = model.BusinessTypeImmediate + } else { + order.BusinessType = model.BusinessTypeDingshida + } + + deliveryGeo := userMap["coord"].(map[string]interface{}) + originalLng := utils.MustInterface2Float64(deliveryGeo["longitude"]) + originalLat := utils.MustInterface2Float64(deliveryGeo["latitude"]) + lng, lat, err2 := api.AutonaviAPI.CoordinateConvert(originalLng, originalLat, autonavi.CoordSysBaidu) + if err2 == nil { + originalLng = lng + originalLat = lat + order.CoordinateType = model.CoordinateTypeMars + } + order.ConsigneeLng = jxutils.StandardCoordinate2Int(originalLng) + order.ConsigneeLat = jxutils.StandardCoordinate2Int(originalLat) + + products := result["products"].([]interface{})[0].([]interface{}) + // discounts := result["discount"].(map[string]interface{}) + for _, product2 := range products { + product := product2.(map[string]interface{}) + sku := &model.OrderSku{ + VendorOrderID: order.VendorOrderID, + VendorID: model.VendorIDEBAI, + Count: int(utils.MustInterface2Int64(product["product_amount"])), + SkuID: int(utils.Str2Int64WithDefault(utils.Interface2String(product["custom_sku_id"]), 0)), + VendorSkuID: utils.Interface2String(product["baidu_product_id"]), + SkuName: product["product_name"].(string), + Weight: 0, // todo + SalePrice: utils.MustInterface2Int64(product["product_price"]), + // PromotionType: int(utils.MustInterface2Int64(product["promotionType"])), + } + // if product["isGift"].(bool) { + // sku.SkuType = 1 + // } + order.Skus = append(order.Skus, sku) + order.SkuCount++ + order.GoodsCount += sku.Count + order.SalePrice += sku.SalePrice * int64(sku.Count) + order.Weight += sku.Weight * sku.Count + } + // setOrederDetailFee(result, order) + } return order, err } func (p *PurchaseHandler) AcceptOrRefuseOrder(order *model.GoodsOrder, isAcceptIt bool, userName string) (err error) { + if isAcceptIt { + err = api.EbaiAPI.OrderConfirm(order.VendorOrderID) + } else { + err = api.EbaiAPI.OrderCancel(order.VendorOrderID, ebaiapi.CancelTypeCustom, "bu") + } return err } + func (p *PurchaseHandler) PickupGoods(order *model.GoodsOrder, userName string) (err error) { + err = api.EbaiAPI.OrderCallDelivery(order.VendorOrderID) return err } // 将订单从购物平台配送转为自送 func (p *PurchaseHandler) Swtich2SelfDeliver(order *model.GoodsOrder, userName string) (err error) { + err = api.EbaiAPI.OrderSwitchselfdelivery(order.VendorOrderID) return err } // 将订单从购物平台配送转为自送后又送达 func (p *PurchaseHandler) Swtich2SelfDelivered(order *model.GoodsOrder, userName string) (err error) { + // todo 饿百转商家自送后,没有确认送达的概念,空操作 return err } // 完全自送的门店表示开始配送 func (p *PurchaseHandler) SelfDeliverDelievering(order *model.GoodsOrder, userName string) (err error) { + err = api.EbaiAPI.OrderSendOut(order.VendorOrderID, userName) return err } // 完全自送的门店表示配送完成 func (p *PurchaseHandler) SelfDeliverDelievered(order *model.GoodsOrder, userName string) (err error) { + err = api.EbaiAPI.OrderComplete(order.VendorOrderID, userName) return err } + +// +func (c *PurchaseHandler) onOrderMsg(msg *ebaiapi.CallbackMsg) (retVal *ebaiapi.CallbackResponse) { + if ebaiapi.CmdOrderCreate == msg.Cmd { + retVal = c.onOrderNew(msg) + } else { + status := c.callbackMsg2Status(msg) + err := partner.CurOrderManager.OnOrderStatusChanged(status) + retVal = ebaiapi.Err2CallbackResponse(err, status.VendorStatus) + } + return retVal +} + +func (c *PurchaseHandler) onOrderNew(msg *ebaiapi.CallbackMsg) (response *ebaiapi.CallbackResponse) { + order, err := c.GetOrder(msg.Body["order_id"].(string)) + if err == nil { + err = partner.CurOrderManager.OnOrderNew(order, order.VendorStatus) + } + return ebaiapi.Err2CallbackResponse(err, "ebai onOrderNew") +} + +func (c *PurchaseHandler) callbackMsg2Status(msg *ebaiapi.CallbackMsg) *model.OrderStatus { + body := msg.Body + orderStatus := &model.OrderStatus{ + VendorOrderID: body["order_id"].(string), + VendorID: model.VendorIDEBAI, + OrderType: model.OrderTypeOrder, + RefVendorOrderID: body["order_id"].(string), + RefVendorID: model.VendorIDEBAI, + VendorStatus: body["status"].(string), + Status: c.GetStatusFromVendorStatus(body["status"].(string)), + StatusTime: utils.Timestamp2Time(msg.TimeStamp), + Remark: utils.Interface2String(body["reason"]), + } + return orderStatus +} + +func getTimeFromTimestampStr(sendTime string) time.Time { + timeStamp := utils.Str2Int64WithDefault(sendTime, 0) + if timeStamp == 0 { + return utils.DefaultTimeValue + } + return utils.Timestamp2Time(timeStamp) +} diff --git a/business/partner/purchase/ebai/waybill.go b/business/partner/purchase/ebai/waybill.go index 745aa2b8a..affda5f89 100644 --- a/business/partner/purchase/ebai/waybill.go +++ b/business/partner/purchase/ebai/waybill.go @@ -1,2 +1,61 @@ package ebai +import ( + "git.rosy.net.cn/baseapi/platformapi/ebaiapi" + "git.rosy.net.cn/baseapi/utils" + "git.rosy.net.cn/jx-callback/business/model" + "git.rosy.net.cn/jx-callback/business/partner" + "git.rosy.net.cn/jx-callback/globals/api" +) + +var ( + VendorWaybillStatus2StatusMap = map[string]int{ + ebaiapi.WaybillStatusNew: model.WaybillStatusNew, + ebaiapi.WaybillStatusRequestDelivery: model.WaybillStatusUnknown, + ebaiapi.WaybillStatusWait4Courier: model.WaybillStatusUnknown, + ebaiapi.WaybillStatusCourierAccepted: model.WaybillStatusAccepted, + ebaiapi.WaybillStatusCourierPickedup: model.WaybillStatusDelivering, + ebaiapi.WaybillStatusDeliveryCancled: model.WaybillStatusCanceled, + ebaiapi.WaybillStatusFinished: model.WaybillStatusDelivered, + ebaiapi.WaybillStatusExceptional: model.WaybillStatusUnknown, + ebaiapi.WaybillStatusSelfDelivery: model.WaybillStatusUnknown, + ebaiapi.WaybillStatusNotInDelivering: model.WaybillStatusUnknown, + ebaiapi.WaybillStatusDeliveryRejected: model.WaybillStatusAcceptCanceled, // ? + } +) + +func (p *PurchaseHandler) GetWaybillStatusFromVendorStatus(vendorStatus string) int { + if status, ok := VendorWaybillStatus2StatusMap[vendorStatus]; ok { + return status + } + return model.WaybillStatusUnknown +} + +func (c *PurchaseHandler) onWaybillMsg(msg *ebaiapi.CallbackMsg) (retVal *ebaiapi.CallbackResponse) { + order := c.callbackMsg2Waybill(msg) + if order.Status == model.WaybillStatusAccepted { + if result, err := api.EbaiAPI.OrderGet(order.VendorOrderID); err != nil { + return ebaiapi.Err2CallbackResponse(err, order.VendorOrderID) + } else { + order.CourierMobile = utils.Interface2String(result["order"].(map[string]interface{})["delivery_phone"]) + } + } + return ebaiapi.Err2CallbackResponse(partner.CurOrderManager.OnWaybillStatusChanged(order), order.VendorStatus) +} + +func (c *PurchaseHandler) callbackMsg2Waybill(msg *ebaiapi.CallbackMsg) (retVal *model.Waybill) { + body := msg.Body + vendorStatus := body["status"].(string) + retVal = &model.Waybill{ + VendorOrderID: body["order_id"].(string), + OrderVendorID: model.VendorIDEBAI, + VendorWaybillID: body["order_id"].(string), + WaybillVendorID: model.VendorIDEBAI, + Status: c.GetWaybillStatusFromVendorStatus(vendorStatus), + CourierName: "", // 饿百取不到骑手的名字 + // CourierMobile: msg.Phone, + VendorStatus: vendorStatus, + StatusTime: utils.Timestamp2Time(msg.TimeStamp), + } + return retVal +} diff --git a/controllers/ebai_order.go b/controllers/ebai_order.go index 182fe10cd..3bb620aa0 100644 --- a/controllers/ebai_order.go +++ b/controllers/ebai_order.go @@ -1,10 +1,26 @@ package controllers import ( - _ "git.rosy.net.cn/jx-callback/business/partner/purchase/ebai" + "net/http" + + "git.rosy.net.cn/jx-callback/business/partner/purchase/ebai" + "git.rosy.net.cn/jx-callback/globals/api" "github.com/astaxie/beego" ) type EbaiController struct { beego.Controller } + +func (c *EbaiController) Msg() { + if c.Ctx.Input.Method() == http.MethodPost { + obj, callbackResponse := api.EbaiAPI.GetCallbackMsg(c.Ctx.Request) + if callbackResponse == nil { + callbackResponse = ebai.OnCallbackMsg(obj) + } + c.Data["json"] = callbackResponse + c.ServeJSON() + } else { + c.Abort("404") + } +}