package jdshop import ( "bytes" "encoding/base64" "encoding/hex" "fmt" "math" "strings" "time" "git.rosy.net.cn/jx-callback/business/jxutils/jxcontext" "git.rosy.net.cn/baseapi/platformapi/dingdingapi" "git.rosy.net.cn/baseapi/platformapi/jcqapi" "git.rosy.net.cn/baseapi/platformapi/jdshopapi" "git.rosy.net.cn/baseapi/utils" "git.rosy.net.cn/jx-callback/business/jxstore/common" "git.rosy.net.cn/jx-callback/business/jxutils" "git.rosy.net.cn/jx-callback/business/jxutils/ddmsg" "git.rosy.net.cn/jx-callback/business/model" "git.rosy.net.cn/jx-callback/business/model/dao" "git.rosy.net.cn/jx-callback/business/partner" "git.rosy.net.cn/jx-callback/globals" "git.rosy.net.cn/jx-callback/globals/api" ) func OnCallbackMsg(msg *jdshopapi.CallBackResult) (err error) { msgType := msg.MsgType switch msgType { case jcqapi.TopicOrderPay: utils.CallFuncAsync(func() { SaveJdsOrders(msg) }) case jcqapi.TopicOrderCancel: utils.CallFuncAsync(func() { order := getRealOrderID(msg.OrderID) if order != nil { if order.Status != model.OrderStatusCanceled { CurPurchaseHandler.CancelOrder(jxcontext.AdminCtx, order, "系统取消") } } }) case jcqapi.TopicOrderOut: utils.CallFuncAsync(func() { globals.SugarLogger.Debugf("jdsOrderOut", utils.Format4Output(msg, false)) orders := getAllRealOrderID(msg.OrderID) if len(orders) > 0 { for _, order := range orders { if order.ActualPayPrice == 0 { if jxutils.StandardPrice2Int(utils.Str2Float64(msg.OrderPayment)) == 0 { order.ActualPayPrice = jxutils.StandardPrice2Int(utils.Str2Float64(msg.OrderTotalPrice) + utils.Str2Float64(msg.FreightPrice) - utils.Str2Float64(msg.SellerDiscount)) } else { order.ActualPayPrice = jxutils.StandardPrice2Int(utils.Str2Float64(msg.OrderPayment)) } order.TotalShopMoney = utils.Float64TwoInt64(float64(order.ActualPayPrice) * jdshopapi.JdsPayPercentage) partner.CurOrderManager.UpdateOrderFields(order, []string{"ActualPayPrice", "TotalShopMoney"}) } } } }) default: return fmt.Errorf("暂不支持的topic类型!topic: %v", msgType) } return err } func SaveJdsOrders(msg *jdshopapi.CallBackResult) (err error) { order, err := result2Orders(msg) if err != nil || order == nil { return err } partner.CurOrderManager.OnOrderNew(order, model.Order2Status(order)) noticeMsg := fmt.Sprintf("京东商城新订单,订单号:[%v] ,将要发到的门店id:[%v] , 门店名:[%v]", order.VendorOrderID, order.StoreID, order.StoreName) if order.OrderType == model.OrderTypeAddressErr { noticeMsg += " 此订单地址有问题,需要矫正坐标!" } ddmsg.SendUserMessage(dingdingapi.MsgTyeText, "DDC5657B43EE11E9A9FF525400E86DC0", "京东商城来新订单了!", noticeMsg) ddmsg.SendUserMessage(dingdingapi.MsgTyeText, "1439B3E07D3911EA881A525400E86DC0", "京东商城来新订单了!", noticeMsg) return err } func result2Orders(msg *jdshopapi.CallBackResult) (order *model.GoodsOrder, err error) { //有可能是库里已经有这个订单了 orderE, err := partner.CurOrderManager.LoadOrder(msg.OrderID+"000001", model.VendorIDJDShop) if orderE != nil { return order, fmt.Errorf("已经存在此订单!") } order = &model.GoodsOrder{ VendorOrderID2: msg.OrderID, VendorOrderID: msg.OrderID + "000001", VendorID: model.VendorIDJDShop, BaseFreightMoney: jxutils.StandardPrice2Int(utils.Str2Float64(msg.FreightPrice)), VendorStatus: msg.OrderState, VendorUserID: msg.Pin, BuyerComment: msg.OrderRemark, PickDeadline: utils.DefaultTimeValue, OriginalData: string(utils.MustMarshal(msg)), OrderCreatedAt: utils.Str2Time(msg.OrderStartTime), ConsigneeAddress: Decrypt(msg.ConsigneeInfo.FullAddress), ConsigneeName: Decrypt(msg.ConsigneeInfo.Fullname), ConsigneeMobile: Decrypt(msg.ConsigneeInfo.Mobile), ConsigneeMobile2: Decrypt(msg.ConsigneeInfo.Telephone), ActualPayPrice: jxutils.StandardPrice2Int(utils.Str2Float64(msg.OrderPayment)), Status: model.OrderStatusNew, TotalShopMoney: utils.Float64TwoInt64(math.Round(float64(jxutils.StandardPrice2Int(utils.Str2Float64(msg.OrderPayment))) * jdshopapi.JdsPayPercentage)), DeliveryType: model.OrderDeliveryTypeStoreSelf, StatusTime: utils.Str2Time(msg.OrderStartTime), OrderSeq: 0, } if order.TotalShopMoney < 100 { order.TotalShopMoney = 100 } if order.ConsigneeAddress != "" { lng, lat, err2 := api.AutonaviAPI.GetCoordinateFromAddressByPage(order.ConsigneeAddress) if err = err2; err != nil { globals.SugarLogger.Infof("高德page err: %v", err) } lng2, lat2, _ := api.AutonaviAPI.GetCoordinateFromAddress(order.ConsigneeAddress, "") distance := jxutils.EarthDistance(lng, lat, lng2, lat2) if distance > 1 { order.OrderType = model.OrderTypeAddressErr } if err == nil && lng != 0 && lat != 0 { order.ConsigneeLng = jxutils.StandardCoordinate2Int(lng) order.ConsigneeLat = jxutils.StandardCoordinate2Int(lat) } else { order.ConsigneeLng = jxutils.StandardCoordinate2Int(lng2) order.ConsigneeLat = jxutils.StandardCoordinate2Int(lat2) } order.CoordinateType = model.CoordinateTypeMars } for _, v := range msg.ItemInfoList { sku := &model.OrderSku{ VendorID: model.VendorIDJDShop, VendorOrderID: order.VendorOrderID, Count: utils.Str2Int(v.ItemTotal), VendorSkuID: v.SkuID, SkuName: v.SkuName, VendorPrice: jxutils.StandardPrice2Int(utils.Str2Float64(v.JdPrice)), SalePrice: jxutils.StandardPrice2Int(utils.Str2Float64(v.JdPrice)), // SkuID: utils.Str2Int(v.OuterSkuID), } if v.OuterSkuID != "" { sku.SkuID = utils.Str2Int(v.OuterSkuID) } _, _, _, specUnit, _, specQuality := jxutils.SplitSkuName(v.SkuName) sku.Weight = jxutils.FormatSkuWeight(specQuality, specUnit) order.Skus = append(order.Skus, sku) } storeList, err := common.GetStoreListByLocation(jxcontext.AdminCtx, jxutils.IntCoordinate2Standard(order.ConsigneeLng), jxutils.IntCoordinate2Standard(order.ConsigneeLat), 3000, false, true) if err != nil { globals.SugarLogger.Debugf("jds GetStoreListByLocation error: %v", err.Error()) return order, err } if len(storeList) > 0 { for _, store := range storeList { order.StoreID = store.ID order.JxStoreID = store.ID order.StoreName = store.Name globals.SugarLogger.Debugf("jds GetStoreListByLocation, orderID: %v storeID :%v", order.VendorOrderID, order.StoreID) //结算类型 storeDetail, _ := dao.GetStoreDetail(dao.GetDB(), order.StoreID, model.VendorIDJDShop) if storeDetail != nil { if storeDetail.PayPercentage < 50 { order.EarningType = model.EarningTypePoints } else { order.EarningType = model.EarningTypeQuote } } var ( shopPriceSum int saleNormalSum int ) for _, sku := range order.Skus { storeSkuList, _ := dao.GetStoresSkusInfo(dao.GetDB(), []int{order.StoreID}, []int{sku.SkuID}) if len(storeSkuList) > 0 { if storeSkuList[0].Status == model.StoreSkuBindStatusNormal { saleNormalSum += 1 } shopPriceSum += storeSkuList[0].Price * sku.Count } } //可售数小于一半就不行 if math.Mod(float64(len(order.Skus)), float64(2)) == 0 { if saleNormalSum < len(order.Skus)/2 { buildOrderTo102919(order) continue } else { if order.EarningType == model.EarningTypeQuote && shopPriceSum+700 > int(order.TotalShopMoney) { buildOrderTo102919(order) continue } } } else { if saleNormalSum <= len(order.Skus)/2 { buildOrderTo102919(order) continue } else { if order.EarningType == model.EarningTypeQuote && shopPriceSum+700 > int(order.TotalShopMoney) { buildOrderTo102919(order) continue } } } break } } else { buildOrderTo102919(order) } storeMaps, _ := dao.GetStoresMapList(dao.GetDB(), []int{model.VendorIDJDShop}, []int{order.StoreID}, nil, model.StoreStatusAll, model.StoreIsSyncAll, "", "") if len(storeMaps) > 0 { order.VendorStoreID = storeMaps[0].VendorStoreID } // 如果是暂停,表示是预订单g if msg.OrderState == jdshopapi.OrderStatusPause || msg.OrderState == jdshopapi.OrderStatusPopPause { order.BusinessType = model.BusinessTypeDingshida if time2, err := api.JdShopAPI.GetOrderExtInfoByOrderId(order.VendorOrderID2); err == nil { order.ExpectedDeliveredTime = utils.Str2Time(time2).Add(-time.Minute * 30) } order.PickDeadline = order.ExpectedDeliveredTime.Add(-time.Hour) } else if msg.OrderState == jdshopapi.OrderStatusWait { order.ExpectedDeliveredTime = order.OrderCreatedAt.Add(time.Hour) order.BusinessType = model.BusinessTypeImmediate } else { globals.SugarLogger.Debugf("暂不支持的京东商城订单类型!type: %v", msg.OrderState) return nil, err } if msg.IDSopShipmenttype == jdshopapi.IdSopShipmenttypeTC { if time2, err := api.JdShopAPI.GetOrderExtInfoByOrderId(order.VendorOrderID2); err == nil { order.BusinessType = model.BusinessTypeDingshida order.ExpectedDeliveredTime = utils.Str2Time(time2).Add(-time.Minute * 30) } } setJdsOrderSeq(order) if order.OrderType == model.OrderTypeAddressErr { buildOrderTo102919(order) } return order, err } func buildOrderTo102919(order *model.GoodsOrder) { order.StoreID = 102919 order.JxStoreID = 102919 order.StoreName = "商城模板(成都发货)" order.VendorStoreID = model.JdShopMainVendorStoreID order.DeliveryFlag = model.OrderDeliveryFlagMaskScheduleDisabled } func setJdsOrderSeq(order *model.GoodsOrder) (err error) { type tCount struct { Count int `json:"count"` } var count = &tCount{} sql := ` SELECT count(*) count FROM goods_order WHERE store_id = ? AND order_create_at >= ? AND order_create_at <= ? AND vendor_id = ? ` sqlParams := []interface{}{ order.StoreID, utils.Time2Date(time.Now()), utils.Time2Date(time.Now().AddDate(0, 0, 1)), order.VendorID, } err = dao.GetRow(dao.GetDB(), &count, sql, sqlParams) order.OrderSeq = count.Count + 1 return err } func Decrypt(p string) (result string) { if p == "" { return "" } data, _ := base64.StdEncoding.DecodeString(strings.ReplaceAll(p, " ", "+")) key := GetKey(hex.EncodeToString(data)[4:36]) globals.SugarLogger.Debugf("Decrypt keys : %v", key) data2, _ := base64.StdEncoding.DecodeString(key) b := bytes.NewBuffer(data) b.Next(18) iv := make([]byte, 16) b.Read(iv) main := make([]byte, len(data)-18-16) b.Read(main) decryptedData, _ := utils.AESCBCDecpryt(main, data2[:16], iv) return string(decryptedData) } func getRealOrderID(orderID string) (order *model.GoodsOrder) { var ( db = dao.GetDB() ) sql := ` SELECT * FROM goods_order WHERE vendor_order_id2 = ? ORDER BY vendor_order_id DESC LIMIT 1 ` sqlParams := []interface{}{ orderID, } dao.GetRow(db, &order, sql, sqlParams) return order } func getAllRealOrderID(orderID string) (orders []*model.GoodsOrder) { var ( db = dao.GetDB() ) sql := ` SELECT * FROM goods_order WHERE vendor_order_id2 = ? ` sqlParams := []interface{}{ orderID, } dao.GetRows(db, &orders, sql, sqlParams) return orders }