Files
jx-callback/business/partner/purchase/jdshop/callback.go
苏尹岚 ac2bb2bcfe aa
2021-03-30 10:19:36 +08:00

477 lines
17 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
package jdshop
import (
"bytes"
"encoding/base64"
"encoding/hex"
"fmt"
"math"
"strings"
"time"
"git.rosy.net.cn/jx-callback/business/authz/autils"
"git.rosy.net.cn/jx-callback/business/partner/delivery/dada"
"git.rosy.net.cn/jx-callback/business/jxutils/jxcontext"
beego "github.com/astaxie/beego/adapter"
"git.rosy.net.cn/baseapi/platformapi/dadaapi"
"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"
"git.rosy.net.cn/jx-callback/globals/api2"
)
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
}
globals.SugarLogger.Debugf("SaveJdsOrders : %v", utils.Format4Output(order, false))
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 += " 此订单地址有问题,需要矫正坐标!"
}
var role = autils.NewRole("jdshop", 0)
userIDList, err := api2.RoleMan.GetRoleUserList(role)
for _, v := range userIDList {
ddmsg.SendUserMessage(dingdingapi.MsgTyeText, v, "京东商城来新订单了!", noticeMsg)
}
// ddmsg.SendUserMessage(dingdingapi.MsgTyeText, "1439B3E07D3911EA881A525400E86DC0", "京东商城来新订单了!", noticeMsg)
return err
}
func result2Orders(msg *jdshopapi.CallBackResult) (order *model.GoodsOrder, err error) {
var (
db = dao.GetDB()
)
//有可能是库里已经有这个订单了
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, msg.VendorOrgCode),
ConsigneeName: Decrypt(msg.ConsigneeInfo.Fullname, msg.VendorOrgCode),
// 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,
VendorOrgCode: msg.VendorOrgCode,
}
if utils.Str2Float64(msg.BalanceUsed) != 0 {
order.ActualPayPrice += jxutils.StandardPrice2Int(utils.Str2Float64(msg.BalanceUsed))
}
if len(msg.ConsigneeInfo.Mobile) != 11 {
order.ConsigneeMobile = Decrypt(msg.ConsigneeInfo.Mobile, msg.VendorOrgCode)
} else {
order.ConsigneeMobile = msg.ConsigneeInfo.Mobile
}
if len(msg.ConsigneeInfo.Telephone) != 11 {
order.ConsigneeMobile2 = Decrypt(msg.ConsigneeInfo.Telephone, msg.VendorOrgCode)
} else {
order.ConsigneeMobile2 = msg.ConsigneeInfo.Telephone
}
if order.TotalShopMoney < 100 {
order.TotalShopMoney = 100
}
if order.ConsigneeAddress != "" {
var cityCode int
place, err := dao.GetPlaceByJdsCode(db, utils.Str2Int(msg.ConsigneeInfo.CityID))
if place == nil {
cityCode = 510100
} else {
if place.Level == 3 {
cityCode = place.ParentCode
} else if place.Level == 2 {
cityCode = place.Code
}
}
lng, lat, err2 := api.AutonaviAPI.GetCoordinateFromAddressByPage(order.ConsigneeAddress, cityCode)
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, 0)
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(db, 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(db, []int{order.StoreID}, []int{sku.SkuID})
if len(storeSkuList) > 0 {
if storeSkuList[0].Status == model.StoreSkuBindStatusNormal {
saleNormalSum += 1
}
shopPriceSum += storeSkuList[0].Price * sku.Count
} else {
shopPriceSum += int(sku.SalePrice) * 70 / 100
}
}
//可售数小于一半就不行
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(db, []int{model.VendorIDJDShop}, []int{order.StoreID}, nil, model.StoreStatusAll, model.StoreIsSyncAll, "", "", msg.VendorOrgCode)
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 := getAPI(msg.VendorOrgCode).GetOrderExtInfoByOrderId(order.VendorOrderID2); err == nil {
if time2 == "" {
order.ExpectedDeliveredTime = order.OrderCreatedAt.Add(time.Hour)
} else {
order.ExpectedDeliveredTime = utils.Str2Time(time2)
}
} else {
order.ExpectedDeliveredTime = order.OrderCreatedAt.Add(time.Hour)
err = nil
}
order.PickDeadline = order.ExpectedDeliveredTime.Add(-time.Hour)
} else if msg.OrderState == jdshopapi.OrderStatusWait || msg.OrderState == "WAIT_GOODS_RECEIVE_CONFIRM" || msg.OrderState == "FINISHED_L" {
order.ExpectedDeliveredTime = order.OrderCreatedAt.Add(time.Hour)
order.BusinessType = model.BusinessTypeImmediate
} else if msg.OrderState == "UN_KNOWN" {
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 msg.VendorOrgCode == "1" {
if time2, err := getAPI(msg.VendorOrgCode).GetOrderExtInfoByOrderId(order.VendorOrderID2); err == nil {
order.BusinessType = model.BusinessTypeDingshida
if time2 == "" {
order.ExpectedDeliveredTime = order.OrderCreatedAt.Add(time.Hour)
} else {
order.ExpectedDeliveredTime = utils.Str2Time(time2)
}
}
} else {
order.BusinessType = model.BusinessTypeImmediate
if time2, err := getAPI(msg.VendorOrgCode).GetOrderExtInfoByOrderId(order.VendorOrderID2); err == nil {
if time2 == "" {
order.ExpectedDeliveredTime = order.OrderCreatedAt.Add(time.Hour)
} else {
order.ExpectedDeliveredTime = utils.Str2Time(time2)
}
} else {
order.ExpectedDeliveredTime = order.OrderCreatedAt.Add(time.Hour)
}
}
}
setJdsOrderSeq(order)
if order.OrderType == model.OrderTypeAddressErr {
buildOrderTo102919(order)
}
billParams, _ := GetDaDaBillParams(db, order)
if result, err := api.DadaAPI.QueryDeliverFee(billParams); err == nil {
if result.Fee > 10 {
buildOrderTo102919(order)
}
}
if order.ExpectedDeliveredTime.Sub(order.OrderCreatedAt) <= time.Hour+time.Minute {
order.BusinessType = model.BusinessTypeImmediate
}
buildOrderTo102919(order)
return order, err
}
func buildOrderTo102919(order *model.GoodsOrder) {
if order.VendorOrgCode == "1" {
order.StoreID = 102919
order.JxStoreID = 102919
order.StoreName = "商城模板(成都发货)"
order.VendorStoreID = model.JdShopMainVendorStoreID
} else {
order.StoreID = model.JdShopMainStoreID2
order.JxStoreID = model.JdShopMainStoreID2
order.StoreName = "商城模板店2"
order.VendorStoreID = model.JdShopMainVendorStoreID2
}
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, vendorOrgCode string) (result string) {
if p == "" {
return ""
}
data, _ := base64.StdEncoding.DecodeString(strings.ReplaceAll(p, " ", "+"))
key := GetKey(hex.EncodeToString(data)[4:36], vendorOrgCode)
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
}
func GetDaDaBillParams(db *dao.DaoDB, order *model.GoodsOrder) (billParams *dadaapi.OperateOrderParams, err error) {
billParams = &dadaapi.OperateOrderParams{
OriginID: jxutils.ComposeUniversalOrderID(order.VendorOrderID, order.VendorID),
CargoPrice: jxutils.IntPrice2Standard(limitOrderPrice(order.ActualPayPrice)),
IsPrepay: 0,
ReceiverName: utils.FilterMb4(order.ConsigneeName),
ReceiverAddress: utils.FilterMb4(order.ConsigneeAddress),
ReceiverPhone: order.ConsigneeMobile,
}
if billParams.ShopNo, err = getDadaShopID(order, db); err == nil {
if billParams.CityCode, err = getDataCityCodeFromOrder(order, db); err == nil {
// storeTel := ""
// storeID := jxutils.GetSaleStoreIDFromOrder(order)
// storeDeatail, _ := dao.GetStoreDetail(db, storeID, order.VendorID)
// if storeDeatail.Tel2 != "" {
// storeTel = ",门店电话:" + storeDeatail.Tel2
// }
billParams.ReceiverLng, billParams.ReceiverLat, _ = jxutils.IntCoordinate2MarsStandard(order.ConsigneeLng, order.ConsigneeLat, order.CoordinateType)
billParams.Info = fmt.Sprintf("%s第%d号订单, %s", model.VendorChineseNames[order.VendorID], order.OrderSeq, utils.FilterMb4("客户电话:"+order.ConsigneeMobile+","+order.BuyerComment+"取货失败或配送遇到问题请联系18048531223禁止未配送直接完成定单"))
billParams.CargoType = dadaapi.CargoTypeFresh
billParams.CargoWeight = float64(jxutils.IntWeight2Float(limitOrderWeight(order.Weight)))
billParams.CargoNum = order.GoodsCount
}
}
return billParams, err
}
func limitOrderPrice(price int64) int64 {
var maxOrderPrice int64 = 6399
if price > maxOrderPrice {
return maxOrderPrice
}
return price
}
func limitOrderWeight(weight int) int {
maxOrderWeight := 5000 // 5公斤
if weight > maxOrderWeight {
return maxOrderWeight
}
return weight
}
func getDadaShopID(order *model.GoodsOrder, db *dao.DaoDB) (retVal string, err error) {
saleStoreID := jxutils.GetSaleStoreIDFromOrder(order)
storeCourierList, err2 := dao.GetOpenedStoreCouriersByStoreID(db, saleStoreID, model.VendorIDDada)
if err = err2; err != nil && !dao.IsNoRowsError(err) {
return "", err
}
if len(storeCourierList) == 0 {
return "", partner.ErrStoreHaveNoCourier
}
retVal = storeCourierList[0].VendorStoreID
if beego.BConfig.RunMode == "dev" {
retVal = "test_0001"
}
return retVal, nil
}
func getDataCityCodeFromOrder(order *model.GoodsOrder, db *dao.DaoDB) (retVal string, err error) {
jxStoreID := jxutils.GetSaleStoreIDFromOrder(order)
sql := `
SELECT t2.tel_code
FROM store t1
JOIN place t2 on t1.city_code = t2.code
WHERE t1.id = ?
`
codeInfo := &struct {
TelCode string
}{}
if err = dao.GetRow(db, codeInfo, sql, jxStoreID); err != nil {
globals.SugarLogger.Errorf("GetDataCityCodeFromOrder can not find store info for vendorID:%d, store:%s, error:%v", order.VendorID, order.VendorStoreID, err)
if err == nil {
err = dada.ErrCanNotFindDadaCityCode
}
return "", err
}
return codeInfo.TelCode, nil
}