Files
jx-callback/business/partner/delivery/uupt/waybill.go

411 lines
16 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 uupt
import (
"fmt"
"strings"
"time"
"git.rosy.net.cn/baseapi/platformapi/baidunavi"
"git.rosy.net.cn/baseapi/platformapi/mtpsapi"
"git.rosy.net.cn/baseapi/platformapi/uuptapi"
"git.rosy.net.cn/baseapi/utils"
"git.rosy.net.cn/jx-callback/business/jxutils"
"git.rosy.net.cn/jx-callback/business/jxutils/jxcontext"
"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/business/partner/delivery"
"git.rosy.net.cn/jx-callback/globals"
"git.rosy.net.cn/jx-callback/globals/api"
)
const (
//errCode 错误码说明
ErrorParameter1 = -101 //参数格式校验错误
ErrorParameter2 = -199 //参数格式校验错误
ErrorTimestamp = -102 //timestamp错误
ErrorAppID = -103 //appid无效
ErrorSignatureCheck = -104 //签名校验失败
ErrorOpenIDInvalid = -105 //openid无效
ErrorUnableParseOrigin = -1001 //无法解析起始地
ErrorUnableParseDestination = -1002 //无法解析目的地
ErrorCantGetCityInformation = -1003 //无法获取订单城市相关信息
ErrorOrderCategory = -1004 //订单小类出现错误
ErrorNoUserInformation = -1005 //没有用户信息
ErrorCouponID = -1006 //优惠券ID错误
ErrorPriceToken1 = -2001 //price_token无效
ErrorPriceToken2 = -2002 //price_token无效
ErrorPushType = -2003 //push_type错误
ErrorSpecialType = -2004 //special_type错误
ErrorCallMeWithTake = -2005 //callMe_withTake错误
ErrorOrderPrice = -2006 //order_price错误
ErrorBalancePayMoney = -2007 //balance_payMoney错误
ErrorOrderTotalMoney = -2008 //订单总金额错误
ErrorPayMoney = -2009 //支付金额错误
ErrorUserNotMatch = -2010 //用户不一致
ErrorWrongPhone = -2011 //手机号错误
ErrorNotExistBind = -2012 //不存在绑定关系
ErrorCancelReasonCantEmpty = -4001 //取消原因不能为空
ErrorOrderNumber1 = -4002 //订单编号无效
ErrorOrderNumber2 = -5001 //订单编号无效
ErrorOrderNumber3 = -5002 //订单编号无效
ErrorOrderNumber4 = -5003 //订单编号无效
ErrorFrequencyTooFast = -10001 //发送频率过快,请稍候重试
ErrorNeedCommitVerificationCode = -106 //接口返回base64图片需要提交对应图片验证码
)
var ErrCode = map[int]string{
ErrorParameter1: "参数格式校验错误",
ErrorParameter2: "参数格式校验错误",
ErrorTimestamp: "timestamp错误",
ErrorAppID: "appid无效",
ErrorSignatureCheck: "签名校验失败",
ErrorOpenIDInvalid: "openid无效",
ErrorUnableParseOrigin: "无法解析起始地",
ErrorUnableParseDestination: "无法解析目的地",
ErrorCantGetCityInformation: "无法获取订单城市相关信息",
ErrorOrderCategory: "订单小类出现错误",
ErrorNoUserInformation: "没有用户信息",
ErrorCouponID: "优惠券ID错误",
ErrorPriceToken1: "price_token无效",
ErrorPriceToken2: "price_token无效",
ErrorPushType: "push_type错误",
ErrorSpecialType: "special_type错误",
ErrorCallMeWithTake: "callMe_withTake错误",
ErrorOrderPrice: "order_price错误",
ErrorBalancePayMoney: "balance_payMoney错误",
ErrorOrderTotalMoney: "订单总金额错误",
ErrorPayMoney: "支付金额错误",
ErrorUserNotMatch: "用户不一致",
ErrorWrongPhone: "手机号错误",
ErrorNotExistBind: "不存在绑定关系",
ErrorCancelReasonCantEmpty: "取消原因不能为空",
ErrorOrderNumber1: "订单编号无效",
ErrorOrderNumber2: "订单编号无效",
ErrorOrderNumber3: "订单编号无效",
ErrorOrderNumber4: "订单编号无效",
ErrorFrequencyTooFast: "发送频率过快,请稍候重试",
ErrorNeedCommitVerificationCode: "接口返回base64图片需要提交对应图片验证码",
}
var (
curDeliveryHandler *DeliveryHandler
)
type DeliveryHandler struct {
}
func init() {
if api.UuAPI != nil {
curDeliveryHandler = new(DeliveryHandler)
partner.RegisterDeliveryPlatform(curDeliveryHandler, true)
}
}
func (d DeliveryHandler) GetVendorID() int {
return model.VendorIDUUPT
}
func (d DeliveryHandler) CreateStore(ctx *jxcontext.Context, storeDetail *dao.StoreDetail2) (vendorStoreID string, status int, err error) {
return "", 0, fmt.Errorf("uu跑腿暂不支持此操作")
}
func (d DeliveryHandler) GetStore(ctx *jxcontext.Context, storeID int, vendorStoreID string) (storeDetail *dao.StoreDetail2, err error) {
//uu跑腿无门店概念
store, err := dao.GetStoreDetail(dao.GetDB(), utils.Str2Int(vendorStoreID), model.VendorIDUUPT, "")
if err == nil {
storeDetail = &dao.StoreDetail2{
Store: model.Store{
Name: store.Name,
Tel1: store.Tel1,
Address: store.Address,
Lat: store.Lat,
Lng: store.Lng,
},
VendorID: model.VendorIDUUPT,
VendorStoreID: utils.Int2Str(storeID),
CourierStatus: model.StoreStatusOpened,
}
}
return storeDetail, err
}
func (d DeliveryHandler) IsErrStoreNotExist(err error) bool {
return false
}
func (d DeliveryHandler) IsErrStoreExist(err error) bool {
return false
}
func (d DeliveryHandler) CreateWaybill(order *model.GoodsOrder, maxDeliveryFee int64) (bill *model.Waybill, err error) {
//获取门店老板详情
storeOwner, err := dao.GetStoreDetail(dao.GetDB(), getReallyStoreID(order.StoreID, order.JxStoreID), 0, "")
if err != nil {
return nil, err
}
//获取金额令牌,实际需要支付金额
price, err := getOrderPrice(order)
if err != nil {
return nil, err
}
param := map[string]interface{}{
"price_token": price.PriceToken,
"order_price": price.TotalMoney,
"balance_paymoney": price.NeedPayMoney,
"receiver": order.ConsigneeName,
"receiver_phone": order.ConsigneeMobile,
"note": fmt.Sprintf("%s#%s号单", model.VendorChineseNames[order.VendorID], utils.Int2Str(order.OrderSeq)) + utils.FilterMb4("客户电话:"+order.ConsigneeMobile+"配送遇到问题可联系18048531223取消配送单禁止未配送直接完成订单"),
"callback_url": uuptapi.WaybillCallbackURL,
"push_type": uuptapi.PushTypeOpen,
"pubusermobile": storeOwner.Tel1, //老板电话
"special_type": uuptapi.SpecialTypeNo,
"callme_withtake": uuptapi.CallMeWithTakeYes,
}
if orderCode, originID, err := api.UuAPI.AddOrder(param); err != nil {
return nil, err
} else {
bill = &model.Waybill{
VendorOrderID: order.VendorOrderID,
OrderVendorID: order.VendorID,
VendorWaybillID: orderCode,
VendorWaybillID2: originID,
WaybillVendorID: model.VendorIDUUPT,
DesiredFee: jxutils.StandardPrice2Int(utils.Str2Float64(price.TotalMoney)),
}
}
delivery.OnWaybillCreated(bill)
return bill, err
}
func (d DeliveryHandler) CancelWaybill(bill *model.Waybill, cancelReasonID int, cancelReason string) (err error) {
if err = api.UuAPI.CancelOrder(bill.VendorWaybillID, uuptapi.CancelReasonNormal); err != nil {
return err
}
bill.Status = model.WaybillStatusCanceled
bill.Remark = cancelReason
partner.CurOrderManager.OnWaybillStatusChanged(bill)
return nil
}
func (d DeliveryHandler) GetWaybillFee(order *model.GoodsOrder) (deliveryFeeInfo *partner.WaybillFeeInfo, err error) {
if orderPrice, err := getOrderPrice(order); err != nil {
return nil, err
} else {
deliveryFeeInfo = &partner.WaybillFeeInfo{}
// deliveryFeeInfo.DeliveryFee = jxutils.StandardPrice2Int(utils.Str2Float64(orderPrice.NeedPayMoney)) 优惠后金额
deliveryFeeInfo.DeliveryFee = jxutils.StandardPrice2Int(utils.Str2Float64(orderPrice.TotalMoney)) // 原始金额
}
return deliveryFeeInfo, err
}
func (d DeliveryHandler) ComplaintRider(bill *model.Waybill, resonID int, resonContent string) (err error) {
return fmt.Errorf("UU跑腿暂不支持此操作")
}
func (d DeliveryHandler) GetRiderInfo(orderId string, deliveryId int64, mtPeisongId string) (rider *mtpsapi.RiderInfo, err error) {
waybill, err := api.UuAPI.GetOrderDetail(orderId)
if err != nil {
return nil, err
}
temp := strings.Split(waybill.DriverLastloc, ",") //格式:113.71776,34.767501
param := &mtpsapi.RiderInfo{
OrderId: orderId,
ThirdCarrierOrderId: waybill.OrderCode,
CourierName: waybill.DriverName,
CourierPhone: waybill.DriverMobile,
LogisticsProviderCode: mtpsapi.UUPTCode,
LogisticsStatus: utils.Str2Int(waybill.State),
Longitude: temp[0],
Latitude: temp[1],
}
switch waybill.State {
case uuptapi.StateConfirmSuccess:
param.LogisticsStatus = model.WaybillStatusNew
param.LogisticsContext = model.RiderWaitRider
case uuptapi.StateRMGrabsOrder:
param.LogisticsStatus = model.WaybillStatusCourierAssigned
param.LogisticsContext = model.RiderGetOrder
case uuptapi.StateArrivedStore:
param.LogisticsStatus = model.WaybillStatusCourierArrived
param.LogisticsContext = model.RiderToStore
case uuptapi.StatePickUp, uuptapi.StateArrivedDestination:
param.LogisticsStatus = model.WaybillStatusDelivering
param.LogisticsContext = model.RiderGetOrderDelivering
case uuptapi.StateReceiverGetGoods:
param.LogisticsStatus = model.WaybillStatusDelivered
param.LogisticsContext = model.RiderGetOrderDelivered
case uuptapi.StateOrderCancel:
param.LogisticsStatus = model.WaybillStatusCanceled
param.LogisticsContext = model.RiderGetOrderCanceled
}
return param, nil
}
func (c *DeliveryHandler) GetDeliverLiquidatedDamages(orderId string, deliverId string) (money int64, err error) {
return api.UuAPI.GetOrderLiquidatedDamages(deliverId, orderId)
}
//辅助函数
func getOrderPrice(order *model.GoodsOrder) (orderPrice *uuptapi.GetOrderPriceResp, err error) {
store, err := dao.GetStoreDetail(dao.GetDB(), getReallyStoreID(order.StoreID, order.JxStoreID), 0, "")
if err != nil {
return nil, err
}
//转换百度坐标系
var coords []*baidunavi.Coordinate
coords = append(coords, &baidunavi.Coordinate{
Lng: jxutils.IntCoordinate2Standard(store.Lng),
Lat: jxutils.IntCoordinate2Standard(store.Lat),
}, &baidunavi.Coordinate{
Lat: jxutils.IntCoordinate2Standard(order.ConsigneeLat),
Lng: jxutils.IntCoordinate2Standard(order.ConsigneeLng),
})
coords, err = api.BaiDuNaviAPI.BatchCoordinateConvert(coords, baidunavi.CoordSysGCJ02, baidunavi.CoordSysBaiDu)
weight := 4
tempWeight := 0
if order.Weight/1000 >= weight {
tempWeight = weight
} else if order.Weight/1000 < 1 {
tempWeight = 1
} else {
tempWeight = int(order.Weight / 1000)
}
param := map[string]interface{}{
"origin_id": order.VendorOrderID,
"from_address": store.Address,
"from_usernote": "京西菜市(" + store.Store.Name + ")",
"to_address": order.ConsigneeAddress,
"city_name": store.CityName,
"send_type": uuptapi.SendTypeHelpMeDeliver,
"from_lat": coords[0].Lat,
"from_lng": coords[0].Lng,
"to_lat": coords[1].Lat,
"to_lng": coords[1].Lng,
"goods_weight": tempWeight,
}
if orderPrice, err = api.UuAPI.GetOrderPrice(param); err != nil {
return nil, err
} else {
return orderPrice, nil
}
}
func OnWaybillMsg(req *uuptapi.WaybillCallbackParam) (resp *uuptapi.CallbackResponse) {
param := &model.Waybill{
VendorOrderID: req.OriginID,
VendorWaybillID: req.OrderCode,
WaybillVendorID: model.VendorIDUUPT,
CourierName: req.DriverName,
CourierMobile: req.DriverMobile,
VendorStatus: req.State,
StatusTime: time.Now(),
Remark: req.StateText,
}
var good *model.GoodsOrder
var reallyPrice int64
sql := `SELECT * FROM goods_order WHERE vendor_order_id = ? ORDER BY order_created_at DESC LIMIT 1 OFFSET 0`
sqlParams := []interface{}{req.OriginID}
dao.GetRow(dao.GetDB(), &good, sql, sqlParams)
param.OrderVendorID = good.VendorID
//查询运单价格
uuPrice, err := api.UuAPI.GetOrderDetail(req.OrderCode)
if err != nil {
reallyPrice = 0
} else {
reallyPrice = int64(utils.Str2Float64(uuPrice.OrderPrice) * 100)
}
actualFee := int64((utils.Str2Float64(uuPrice.OrderPrice)-utils.Str2Float64(uuPrice.PriceOff))*100) - int64(utils.WayBillDeliveryMarkUp)
switch req.State {
case uuptapi.StateConfirmSuccess:
param.Status = model.WaybillStatusNew //5 待调度
param.DesiredFee = reallyPrice
param.ActualFee = actualFee
case uuptapi.StateRMGrabsOrder:
param.Status = model.WaybillStatusCourierAssigned
param.Remark = req.DriverName + "," + req.DriverMobile
param.DesiredFee = reallyPrice
param.ActualFee = actualFee
case uuptapi.StateArrivedStore:
param.Status = model.WaybillStatusCourierArrived
param.DesiredFee = reallyPrice
param.ActualFee = actualFee
case uuptapi.StatePickUp:
param.Status = model.WaybillStatusUuPickUp
param.DesiredFee = reallyPrice
param.ActualFee = actualFee
case uuptapi.StateArrivedDestination:
param.Status = model.WaybillStatusUuArrivedDestination
param.DesiredFee = reallyPrice
param.ActualFee = actualFee
case uuptapi.StateReceiverGetGoods:
param.Status = model.WaybillStatusDelivered
param.DesiredFee = reallyPrice
param.ActualFee = actualFee
case uuptapi.StateOrderCancel:
param.Status = model.WaybillStatusCanceled
default:
globals.SugarLogger.Warnf("onWaybillMsg unknown State:%v", req.State)
}
if err := partner.CurOrderManager.OnWaybillStatusChanged(param); err != nil {
return uuptapi.Err2CallbackResponse(err)
}
//推送抖音
if param.OrderVendorID == model.VendorIDDD {
result := &mtpsapi.RiderInfo{
OrderId: param.VendorOrderID,
ThirdCarrierOrderId: param.VendorOrderID,
CourierName: param.CourierName,
CourierPhone: param.CourierMobile,
LogisticsProviderCode: "10002",
LogisticsStatus: param.Status,
OpCode: "",
}
switch req.State {
case uuptapi.StateConfirmSuccess: //下单成功
result.LogisticsStatus = model.WaybillStatusNew
result.LogisticsContext = model.RiderWaitRider
case uuptapi.StateRMGrabsOrder: //骑手已接单
result.LogisticsStatus = model.WaybillStatusCourierAssigned // 分配骑手
result.LogisticsContext = model.RiderWaitGetGoods
case uuptapi.StateArrivedStore: //骑手到店
result.LogisticsStatus = model.WaybillStatusCourierArrived
result.LogisticsContext = model.RiderToStore
case uuptapi.StatePickUp: //已取件
result.LogisticsStatus = model.WaybillStatusUuPickUp
result.LogisticsContext = model.RiderPickUp
case uuptapi.StateArrivedDestination: //到达取件人地址处
result.LogisticsStatus = model.WaybillStatusUuArrivedDestination
result.LogisticsContext = model.RiderArrivedDestination
case uuptapi.StateReceiverGetGoods: //取件人收货
result.LogisticsStatus = model.WaybillStatusDelivered
result.LogisticsContext = model.RiderGetOrderDelivered
case uuptapi.StateOrderCancel: //运单取消
result.LogisticsStatus = model.WaybillStatusCanceled
result.LogisticsContext = model.RiderGetOrderCanceled
default:
result.LogisticsStatus = 0
result.LogisticsContext = model.RiderGetOrderDeliverOther
}
delivery.PullTiktokRiderInfo(result)
}
defer delivery.GetOrderRiderInfoToPlatform(param.VendorOrderID, param.Status) // 骑手位置更新
return uuptapi.Err2CallbackResponse(nil)
}
//辅助函数
func getReallyStoreID(storeID, jxStoreID int) int {
if storeID == 0 && jxStoreID == 0 {
return 0
}
if storeID == 0 {
return jxStoreID
} else {
return storeID
}
}
func (c *DeliveryHandler) UpdateStoreName(storeId, name string) (err error) {
return err
}