package jdapi import ( "fmt" "git.rosy.net.cn/baseapi" "io/ioutil" "net/http" "strings" "git.rosy.net.cn/baseapi/utils" ) const ( CallbackPrefix = "/djsw/" ) // 如下的常量其实都是京东回调消息的 const ( OrderStatusAddComment = "12001" OrderStatusModifyComment = "12006" OrderStatusTipChanged = "12008" OrderStatusPurchased = "41000" // 也即待处理,JD的消息很怪,新订单消息发过来是32000,但如果不是自动接单的,去查却是41000?,接单后才变为32000 OrderStatusPayed = "31020" // 已付款 StatusIDNewOrder = "32000" OrderStatusWaitOutStore = "32000" OrderStatusAdjust = "33080" StatusIDWaitOutStore = "32001" OrderStatusFinishedPickup = "2" OrderStatusDelivering = "33040" OrderStatusDelivered = "33060" OrderStatusFinished = "90000" OrderStatusCanceled = "20020" OrderStatusVenderAgreeCancel = "20031" // 商家同意取消申请 OrderStatusVenderRejectCancel = "20032" // 商家驳回取消申请 OrderStatusUserApplyCancel = "20030" // 这个其实不是一个状态,是一个动作 OrderStatusLocked = "20010" OrderStatusUnlocked = "20050" OrderStatusInfoChanged = "1" // 订单信息变更消息 OrderStatusPayFinishedSettle = "330901" // 订单支付完成应结 OrderStatusAdjustSettle = "330902" // 订单调整后应结 OrderStatusSwitch2SelfSettle = "330903" // 订单众包配送转自送后应结 PromotionStatusSingleOK = "35" // 单品直降活动已生效 PromotionStatusLimitTimeOK = "45" // 限时抢活动已生效 ) const ( StatusIDAddStore = "12003" // 新增门店消息 StatusIDDelStore = "12004" // 删除门店消息 StatusIDUpdateStore = "12009" // 修改门店消息 ) const ( AfsServiceStateWaiting4Audit = "10" // 待审核 AfsServiceStateWaiting4UserFeedback = "11" // 待用户反馈 AfsServiceStateWaiting4CSFeedback = "12" // 待客服反馈 AfsServiceStateWaiting4GetGoods = "20" // 待取件 AfsServiceStateRefundProcessing = "30" // 退款处理中 AfsServiceStateWaiting4MerchantReceiveGoods = "31" // 待商家收货审核 AfsServiceStateRefundSuccess = "32" // 退款成功 AfsServiceStateRefundFailed = "33" // 退款失败 AfsServiceStateAuditRefused = "40" // 审核不通过-驳回 AfsServiceStateUserCanceled = "50" // 客户取消 AfsServiceStateMerchantFailedReceiveGoods = "60" // 商家收货审核不通过 AfsServiceStateSolved = "70" // 已解决 AfsServiceStateWaiting4DirectCompensate = "90" // 待直陪 AfsServiceStateDirectCompensate = "91" // 直赔 AfsServiceStateDirectCompensateSuccess = "92" // 直赔成功 AfsServiceStateDirectCompensateFailed = "93" // 直赔失败 AfsServiceStateWaiting4ReturnGoods = "110" // 待退货 AfsServiceStateGetGoodsSuccess = "111" // 取货成功 AfsServiceStateGettingGoods = "1101" // 取货中 AfsServiceStateGetGoods2Shop = "1111" // 退货成功-商品已送至门店 AfsServiceStateGetGoodsConfirmed = "1112" // 退货成功-商家已确认收货 AfsServiceStateGetGoodsWaiting4Refund = "112" // 退货成功-待退款 AfsServiceStateReturnGoodsFailed = "113" // 退货失败 AfsServiceStateReturnGoodsSuccess = "114" // 退货成功 ) const ( // 订单 CallbackMsgDeliveryCarrierModify = "deliveryCarrierModify" // 订单转自送消息(是指转自送成功后,用处不大) CallbackMsgOrderAccounting = "orderAccounting" // 订单应结消息 CallbackMsgApplyCancelOrder = "applyCancelOrder" CallbackMsgPushDeliveryStatus = "pushDeliveryStatus" CallbackMsgVenderAuditApplyCancelOrder = "venderAuditApplyCancelOrder" CallbackMsgOrderInfoChange = "orderInfoChange" //订单售前用户改变收货地址电话等 // 账务 CallbackMsgEndOrderFinance = "endOrderFinance" // 订单金额拆分完成消息 CallbackMsgFinanceAdjustment = "financeAdjustment" // 财务调整单消息 CallbackMsgApplyInvoice = "applyOrderInvoiceStatus" // 发票消息 // 售后 CallbackMsgNewApplyAfterSaleBill = "newApplyAfterSaleBill" // 新建售后单申请消息 CallbackMsgUpdateApplyAfterSaleBill = "updateApplyAfterSaleBill" // 修改售后单申请消息 CallbackMsgNewAfterSaleBill = "newAfterSaleBill" // 新建售后单消息 CallbackMsgAfterSaleBillStatus = "afterSaleBillStatus" // 售后单状态消息 //会员 CallBackMsgMemberCreateCard = "memberCreateCard" //会员开卡 CallBackMsgMemberRenewCard = "memberRenewCard" //会员续费 CallbackMsgOrderAddTips = "orderAddTips" // 订单商家小费消息 CallbackMsgStockIsHave = "stockIsHave" ) type CallbackResponse struct { Code string `json:"code"` Msg string `json:"msg"` Data string `json:"data"` } type CallbackMsg struct { MsgURL string `json:"msgURL"` AppKey string `json:"app_key"` Token string `json:"token"` Timestamp string `json:"timestamp"` Sign string `json:"sign"` Format string `json:"format"` V string `json:"v"` JdParamJSON string `json:"jd_param_json"` Param interface{} `json:"-"` // 这里json必须是-,否则会导致json encode时死递归 } type CallbackOrderMsg struct { *CallbackMsg BillID string `json:"billId"` OutBillID string `json:"outBillId"` StatusID string `json:"statusId"` Timestamp string `json:"timestamp"` Remark string `json:"remark"` } type CallbackOrderInfoChangeMsg struct { *CallbackMsg BillID string `json:"billId"` //10003129 消息单据ID StatusID string `json:"statusId"` //1 不必做业务判断,与接口含义相同,表示订单消息变更(历史原因保留字段,不建议使用) Timestamp string `json:"timestamp"` //2015-10-16 13:23:30 日期格式为"yyyy-MM-dd HH:mm:ss" BuyerProvince string `json:"buyerProvince"` // 18 省Id(有值表示信息变更后的值) BuyerCity string `json:"buyerCity"` //1 市Id(有值表示信息变更后的值) BuyerCountry string `json:"buyerCountry"` // 123 县Id(有值表示信息变更后的值) BuyerFullAddress string `json:"buyerFullAddress"` // 用户地址 收货人详细地址(有值表示信息变更后的值) BuyerFullName string `json:"buyerFullName"` // 用户名 收货人名称(有值表示信息变更后的值) BuyerLng string `json:"buyerLng"` //1.1 收货人地址坐标纬度(有值表示信息变更后的值) BuyerLat string `json:"buyerLat"` //1.1 收货人地址坐标经度(有值表示信息变更后的值) BuyerMobile string `json:"buyerMobile"` //01058434049 收货人手机号(有值表示信息变更后的值) Midnumber string `json:"midnumber"` //01058434049 中间号(有值表示信息变更后的值) MiddleNumBindingTimestring string `json:"middleNumBindingTimestring"` // 2017-10-29 22:54:44 绑定中间号有效期截止时间(有值表示信息变更后的值) OrderBuyerRemark string `json:"orderBuyerRemark"` // 用户备注 订单买家备注(有值表示信息变更后的值) } type CallbackMemberMsg struct { *CallbackMsg Outbillid string `json:"outBillId"` Billid string `json:"billId"` Statusid string `json:"statusId"` Timestamp string `json:"timestamp"` } type CallbackDeliveryStatusMsg struct { *CallbackMsg OrderID string `json:"orderId"` DeliveryStatusTime string `json:"deliveryStatusTime"` DeliveryManNo string `json:"deliveryManNo"` DeliveryManName string `json:"deliveryManName"` DeliveryManPhone string `json:"deliveryManPhone"` DeliveryCarrierNo string `json:"deliveryCarrierNo"` DeliveryCarrierName string `json:"deliveryCarrierName"` DeliveryStatus string `json:"deliveryStatus"` Remark string `json:"remark"` FailType string `json:"failType"` CreatePin string `json:"createPin"` OpTime string `json:"opTime"` InputTime string `json:"inputTime"` } type CallbackStoreStockMsg struct { *CallbackMsg StationNo string `json:"stationNo"` SkuID int64 `json:"skuId"` Have bool `json:"have"` Vendibility int `json:"vendibility"` OperPin string `json:"operPin"` OperTime int64 `json:"operTime"` OperSource int `json:"operSource"` } type CallbackInvoiceMsg struct { *CallbackMsg BillID string `json:"billId"` // 消息单据ID Id string `json:"id"` // 主键id InvoiceStatus string `json:"invoiceStatus"` // 更新后的发票状态 1:待开票 3:开票中 4:开票成功 5:开票失败 6:冲红中 7:冲红成功 8:冲红失败 9:已驳回 11:蓝票审核失败 12:红票审核失败 13:待换开 14:换开中 15:换开驳回 16:退款关闭 17:协商关闭 Modified string `json:"modified"` // 发票状态更新时刻 StoreId string `json:"storeId"` // 门店id(非必需,当状态变化来自秒送门店的时候才会携带) } const ( OpenSourceJDLSP = 1 OpenSourceJDMedicineCity = 2 OpenSourceJDMerchantDirect = 3 OpenSourceJDOne = 4 OpenSourceStockCenter = 5 OpenSourceOrderCenter = 6 OpenSourceGoodsSystem = 7 OpenSourcePrepositionWH = 8 OpenSourceStoreSystem = 9 OpenSourceMerchantCenter = 10 OpenSourceOpenPlatform = 11 OpenSourcePickupSystem = 13 OpenSourceBatchTask = 14 ) var ( SuccessResponse = &CallbackResponse{Code: "0", Msg: "success", Data: ""} FormatErrorResponse = &CallbackResponse{Code: "-1", Msg: "failed", Data: ""} needDecodeMap = map[string]bool{ CallbackMsgApplyCancelOrder: true, CallbackMsgPushDeliveryStatus: true, CallbackMsgStockIsHave: true, CallbackMsgVenderAuditApplyCancelOrder: true, } ) func Err2CallbackResponse(err error, data string) *CallbackResponse { if err == nil { return SuccessResponse } return &CallbackResponse{ Code: ResponseCodeFailedCanAutoRetry, Msg: err.Error(), Data: data, } } func map2StockCallbackMsg(mapData map[string]interface{}) (msg *CallbackStoreStockMsg) { msg = &CallbackStoreStockMsg{ StationNo: utils.Interface2String(mapData["stationNo"]), SkuID: utils.Str2Int64(utils.Interface2String(mapData["skuId"])), Vendibility: int(utils.Str2Int64(utils.Interface2String(mapData["vendibility"]))), OperPin: utils.Interface2String(mapData["operPin"]), OperTime: utils.Str2Int64(utils.Interface2String(mapData["operTime"])), OperSource: int(utils.Str2Int64((utils.Interface2String(mapData["operSource"])))), Have: utils.Interface2String(mapData["have"]) == "true", } return msg } func getMsgURLFromRequest(request *http.Request) (msgURL string) { index := strings.Index(request.URL.Path, CallbackPrefix) if index >= 0 { msgURL = request.URL.Path[index+len(CallbackPrefix):] } return msgURL } func GetCallbackMsg(request *http.Request) (callbackMsg *CallbackMsg, mapData map[string]interface{}, callbackResponse *CallbackResponse) { msgURL := getMsgURLFromRequest(request) data, err := ioutil.ReadAll(request.Body) if err != nil { return nil, nil, Err2CallbackResponse(err, "") } values, err := utils.HTTPBody2Values(data, needDecodeMap[msgURL]) if err != nil { return nil, nil, FormatErrorResponse } mapData = utils.URLValues2Map(values) if err = utils.Map2StructByJson(mapData, &callbackMsg, false); err == nil { callbackMsg.MsgURL = msgURL if msgURL == CallbackMsgPushDeliveryStatus { var deliveryMsg *CallbackDeliveryStatusMsg if err = utils.UnmarshalUseNumber([]byte(callbackMsg.JdParamJSON), &deliveryMsg); err == nil { callbackMsg.Param = deliveryMsg deliveryMsg.CallbackMsg = callbackMsg } } else if msgURL == CallbackMsgStockIsHave { var mapData map[string]interface{} if err = utils.UnmarshalUseNumber([]byte(callbackMsg.JdParamJSON), &mapData); err == nil { stockMsg := map2StockCallbackMsg(mapData) callbackMsg.Param = stockMsg stockMsg.CallbackMsg = callbackMsg } } else if msgURL == CallbackMsgOrderInfoChange { var orderInfoMsg *CallbackOrderInfoChangeMsg if err = utils.UnmarshalUseNumber([]byte(callbackMsg.JdParamJSON), &orderInfoMsg); err == nil { callbackMsg.Param = orderInfoMsg orderInfoMsg.CallbackMsg = callbackMsg } } else if msgURL == CallBackMsgMemberCreateCard || msgURL == CallBackMsgMemberRenewCard { var orderInfoMsg *CallbackMemberMsg if err = utils.UnmarshalUseNumber([]byte(callbackMsg.JdParamJSON), &orderInfoMsg); err == nil { callbackMsg.Param = orderInfoMsg orderInfoMsg.CallbackMsg = callbackMsg } } else if msgURL == CallbackMsgApplyInvoice { var orderInfoMsg *CallbackInvoiceMsg if err = utils.UnmarshalUseNumber([]byte(callbackMsg.JdParamJSON), &orderInfoMsg); err == nil { callbackMsg.Param = orderInfoMsg orderInfoMsg.CallbackMsg = callbackMsg } fmt.Println(orderInfoMsg) } else { var orderMsg *CallbackOrderMsg if err = utils.UnmarshalUseNumber([]byte(callbackMsg.JdParamJSON), &orderMsg); err == nil { callbackMsg.Param = orderMsg orderMsg.CallbackMsg = callbackMsg } } } return callbackMsg, mapData, callbackResponse } func (a *API) CheckCallbackValidation(mapData map[string]interface{}, signInData string) (callbackResponse *CallbackResponse) { sign := a.signParams(mapData) if sign != signInData { baseapi.SugarLogger.Infof("Signature is not ok, mine:%s, signInData:%s", sign, signInData) return FormatErrorResponse } return nil }