diff --git a/business/partner/purchase/jx/callback.go b/business/partner/purchase/jx/callback.go index 0696f97a2..27e8cce7d 100644 --- a/business/partner/purchase/jx/callback.go +++ b/business/partner/purchase/jx/callback.go @@ -10,7 +10,8 @@ import ( const ( appKey = "4A86853D-E4B6-454E-940A-B68ECDA2B73E" - MsgTypeOrder = "order" + MsgTypeOrder = "order" + MsgTypeAfsOrder = "afsOrder" ) type CallbackResponse struct { @@ -23,6 +24,7 @@ type CallbackMsg struct { MsgType string `json:"msgType"` SubMsgType string `json:"subMsgType"` ThingID string `json:"thingID"` + ThingID2 string `json:"thingID2"` Data string `json:"data"` Timestamp int64 `json:"timestamp"` } @@ -33,6 +35,8 @@ func OnCallbackMsg(msg *CallbackMsg) (retVal, errCode string, err error) { } if msg.MsgType == MsgTypeOrder { retVal, errCode, err = CurPurchaseHandler.OnOrderMsg(msg) + } else if msg.MsgType == MsgTypeAfsOrder { + err = CurPurchaseHandler.OnAfsOrderMsg(msg) } return retVal, errCode, err } diff --git a/business/partner/purchase/jx/jxapi_order.go b/business/partner/purchase/jx/jxapi_order.go index 27d51eb85..e451dab83 100644 --- a/business/partner/purchase/jx/jxapi_order.go +++ b/business/partner/purchase/jx/jxapi_order.go @@ -29,3 +29,16 @@ func (a *API) NotifyOrderStatusChanged(order *model.GoodsOrder) (err error) { } return err } + +func (a *API) NotifyAfsOrderStatusChanged(afsOrder *model.AfsOrder) (err error) { + status := translateOrderStatus(afsOrder.Status) + if status > 0 { + _, err = a.AccessAPI("afsOrderChangeStatus", map[string]interface{}{ + "orderid": afsOrder.VendorOrderID, + "afsOrderID": afsOrder.AfsOrderID, + "status": status, + "data": "", //string(utils.MustMarshal(order)), + }, "") + } + return err +} diff --git a/business/partner/purchase/jx/order_afs.go b/business/partner/purchase/jx/order_afs.go index e0eb6a006..4f6e0187e 100644 --- a/business/partner/purchase/jx/order_afs.go +++ b/business/partner/purchase/jx/order_afs.go @@ -1,38 +1,171 @@ package jx import ( + "fmt" + "time" + + "git.rosy.net.cn/baseapi/platformapi/jdapi" + "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/partner" ) -func (c *PurchaseHandler) OnAfsOrderMsg(msg *CallbackMsg) (retVal *CallbackResponse) { - jxutils.CallMsgHandlerAsync(func() { - retVal = c.onAfsOrderMsg(msg) - }, jxutils.ComposeUniversalOrderID(msg.ThingID, c.GetVendorID())) - return retVal +type Data4AfsOrderSku struct { + VendorOrderID string `orm:"column(vendor_order_id);size(48)" json:"vendorOrderID"` // 关联原始订单ID + AfsOrderID string `orm:"column(afs_order_id);size(48)" json:"afsOrderID"` // 售后单ID + + // ConfirmTime time.Time `orm:"type(datetime)" json:"confirmTime"` // 订单生成/完成时间 + VendorStoreID string `orm:"column(vendor_store_id);size(48)" json:"vendorStoreID"` // 外部系统里记录的storeid + VendorSkuID string `orm:"column(vendor_sku_id);size(48)" json:"vendorSkuID"` // 平台skuid + PromotionType int `json:"promotionType"` // 商品级别促销类型 (1、无优惠;2、秒杀(已经下线);3、单品直降;4、限时抢购;1202、加价购;1203、满赠(标识商品);6、买赠(买A送B,标识B);9999、表示一个普通商品参与捆绑促销,设置的捆绑类型;9998、表示一个商品参与了捆绑促销,并且还参与了其他促销类型;9997、表示一个商品参与了捆绑促销,但是金额拆分不尽,9996:组合购,8001:轻松购会员价,8:第二件N折,9:拼团促销) + Name string `orm:"size(255)" json:"name"` // 商品名 + SalePrice int64 `json:"salePrice"` // 售卖价 + Count int `json:"count"` // 订单下单数量 } -func (c *PurchaseHandler) onAfsOrderMsg(msg *CallbackMsg) (retVal *CallbackResponse) { - return retVal +type Data4AfsOrder struct { + VendorOrderID string `orm:"column(vendor_order_id);size(48)" json:"vendorOrderID"` // 关联原始订单ID + AfsOrderID string `orm:"column(afs_order_id);size(48)" json:"afsOrderID"` // 售后订单ID + AfsCreatedAt time.Time `orm:"type(datetime);null;index" json:"afsCreatedAt"` // 售后单生成时间 + AfsFinishedAt time.Time `orm:"type(datetime);null;index" json:"afsFinishedAt"` // 售后单结束时间 + VendorStoreID string `orm:"column(vendor_store_id);size(48)" json:"vendorStoreID"` // 外部系统里记录的storeid + + // IsNeedApprove int8 `json:"isNeedApprove"` // 售后单是否需要商家审核 + VendorStatus string `orm:"size(255)" json:"vendorStatus"` + ReasonType int8 `json:"reasonType"` // 售后原因 + VendorReasonType string `orm:"size(255)" json:"vendorReasonType"` + ReasonDesc string `orm:"size(1024)" json:"reasonDesc"` // 售后原因描述 + ReasonImgList string `orm:"size(1024)" json:"reasonImgList"` // 售后描述图片 + VendorAppealType string `orm:"size(255)" json:"vendorAppealType"` // 售后方式 + Flag int `json:"flag"` + RefundType int8 `json:"refundType"` + RefuseReason string `orm:"size(1024)" json:"refuseReason"` + Skus []*Data4AfsOrderSku +} + +func (c *PurchaseHandler) OnAfsOrderMsg(msg *CallbackMsg) (err error) { + jxutils.CallMsgHandlerAsync(func() { + err = c.onAfsOrderMsg(msg) + }, jxutils.ComposeUniversalOrderID(msg.ThingID, c.GetVendorID())) + return err +} + +func (c *PurchaseHandler) buildAfsOrder(msg *CallbackMsg) (outAfsOrder *model.AfsOrder, err error) { + var afsOrder *Data4AfsOrder + if err = utils.UnmarshalUseNumber([]byte(msg.Data), &afsOrder); err == nil { + outAfsOrder = &model.AfsOrder{ + VendorID: model.VendorIDJX, + AfsOrderID: afsOrder.AfsOrderID, + VendorOrderID: afsOrder.VendorOrderID, + VendorStoreID: afsOrder.VendorStoreID, + StoreID: int(utils.Str2Int64WithDefault(afsOrder.VendorStoreID, 0)), + AfsCreatedAt: afsOrder.AfsCreatedAt, + + VendorStatus: afsOrder.VendorStatus, + VendorReasonType: afsOrder.VendorReasonType, + ReasonType: int8(utils.Str2Int64WithDefault(afsOrder.VendorReasonType, 0)), + ReasonDesc: utils.LimitUTF8StringLen(afsOrder.ReasonDesc, 1024), + ReasonImgList: afsOrder.ReasonImgList, + VendorAppealType: afsOrder.VendorAppealType, + AppealType: int8(utils.Str2Int64WithDefault(afsOrder.VendorAppealType, 0)), + } + outAfsOrder.Status = int(utils.Str2Int64WithDefault(afsOrder.VendorStatus, 0)) + + for _, x := range afsOrder.Skus { + orderSku := &model.OrderSkuFinancial{ + Count: x.Count, + VendorSkuID: x.VendorSkuID, + SkuID: int(utils.Str2Int64WithDefault(x.VendorSkuID, 0)), + Name: x.Name, + } + if x.PromotionType != 0 && x.PromotionType != jdapi.PromotionTypeNormal { + orderSku.StoreSubName = utils.Int2Str(x.PromotionType) + } + outAfsOrder.Skus = append(outAfsOrder.Skus, orderSku) + } + } + return outAfsOrder, err +} + +func (c *PurchaseHandler) callbackAfsMsg2Status(msg *CallbackMsg) *model.OrderStatus { + orderStatus := &model.OrderStatus{ + VendorOrderID: msg.ThingID2, // 是售后单ID,不是订单ID,订单ID在RefVendorOrderID中 + VendorID: model.VendorIDJX, + OrderType: model.OrderTypeAfsOrder, + RefVendorOrderID: msg.ThingID, + RefVendorID: model.VendorIDJX, + VendorStatus: msg.SubMsgType, + Status: int(utils.Str2Int64WithDefault(msg.SubMsgType, 0)), + StatusTime: utils.Timestamp2Time(msg.Timestamp), + Remark: "", + } + return orderStatus +} + +func (c *PurchaseHandler) onAfsOrderMsg(msg *CallbackMsg) (err error) { + subMsgType := int(utils.Str2Int64WithDefault(msg.SubMsgType, 0)) + status := c.callbackAfsMsg2Status(msg) + if subMsgType == model.AfsOrderStatusWait4Approve || subMsgType == model.AfsOrderStatusNew { + afsOrder, err2 := c.buildAfsOrder(msg) + if err = err2; err == nil { + err = partner.CurOrderManager.OnAfsOrderNew(afsOrder, status) + } + } else { + err = partner.CurOrderManager.OnOrderStatusChanged(status) + } + return err +} + +func (p *PurchaseHandler) postFakeAfsMsg(orderNo, afsOrderID string, status int) { + msg := &CallbackMsg{ + AppKey: appKey, + MsgType: MsgTypeAfsOrder, + SubMsgType: utils.Int2Str(status), + ThingID: orderNo, + ThingID2: afsOrderID, + Timestamp: time.Now().Unix(), + } + utils.CallFuncAsync(func() { + OnCallbackMsg(msg) + }) +} + +func (c *PurchaseHandler) notifyAfsOrderStatusChanged(order *model.AfsOrder, status int) (err error) { + orderMsg := *order + orderMsg.Status = status + if err = jxAPI.NotifyAfsOrderStatusChanged(&orderMsg); err == nil { + c.postFakeAfsMsg(orderMsg.VendorOrderID, orderMsg.AfsOrderID, orderMsg.Status) + } + return err } // 审核售后单申请 func (c *PurchaseHandler) AgreeOrRefuseRefund(ctx *jxcontext.Context, order *model.AfsOrder, approveType int, reason string) (err error) { - return err + var status int + if approveType == partner.AfsApproveTypeRefused { + status = model.AfsOrderStatusFailed + } else { + status = model.AfsOrderStatusFinished + } + return c.notifyAfsOrderStatusChanged(order, status) } // 确认收到退货 func (c *PurchaseHandler) ConfirmReceivedReturnGoods(ctx *jxcontext.Context, order *model.AfsOrder) (err error) { + err = fmt.Errorf("京西商城当前不支持ConfirmReceivedReturnGoods") return err } // 发起全款退款 func (c *PurchaseHandler) RefundOrder(ctx *jxcontext.Context, order *model.GoodsOrder, reason string) (err error) { + err = fmt.Errorf("%s不支持售后全额退款,请让买家发起退款", model.VendorChineseNames[model.VendorIDJX]) return err } // 发起部分退款 func (c *PurchaseHandler) PartRefundOrder(ctx *jxcontext.Context, order *model.GoodsOrder, refundSkuList []*model.OrderSku, reason string) (err error) { + err = fmt.Errorf("%s不支持售后部分退款,请让买家发起退款", model.VendorChineseNames[model.VendorIDJX]) return err }