383 lines
15 KiB
Go
383 lines
15 KiB
Go
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.NeedPayMoney)),
|
||
}
|
||
}
|
||
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))
|
||
}
|
||
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 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)
|
||
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,
|
||
}
|
||
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
|
||
//查询运单价格
|
||
if uuPrice, err := api.UuAPI.GetOrderDetail(req.OrderCode); err != nil {
|
||
reallyPrice = 0
|
||
} else {
|
||
reallyPrice = int64((utils.Str2Float64(uuPrice.OrderPrice) - utils.Str2Float64(uuPrice.PriceOff)) * 100)
|
||
}
|
||
switch req.State {
|
||
case uuptapi.StateConfirmSuccess:
|
||
param.Status = model.WaybillStatusNew //5 待调度
|
||
param.DesiredFee = reallyPrice
|
||
case uuptapi.StateRMGrabsOrder:
|
||
param.Status = model.WaybillStatusCourierAssigned
|
||
param.Remark = req.DriverName + "," + req.DriverMobile
|
||
param.DesiredFee = reallyPrice
|
||
case uuptapi.StateArrivedStore:
|
||
param.Status = model.WaybillStatusCourierArrived
|
||
param.DesiredFee = reallyPrice
|
||
case uuptapi.StatePickUp:
|
||
param.Status = model.WaybillStatusUuPickUp
|
||
param.DesiredFee = reallyPrice
|
||
case uuptapi.StateArrivedDestination:
|
||
param.Status = model.WaybillStatusUuArrivedDestination
|
||
param.DesiredFee = reallyPrice
|
||
case uuptapi.StateReceiverGetGoods:
|
||
param.Status = model.WaybillStatusDelivered
|
||
param.DesiredFee = reallyPrice
|
||
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
|
||
}
|
||
}
|