package ebaiapi import ( "errors" "fmt" "git.rosy.net.cn/baseapi" "git.rosy.net.cn/baseapi/utils" "net/http" "net/url" ) const ( CmdOrderCreate = "order.create" CmdOrderDeliveryStatus = "order.deliveryStatus.push" CmdOrderPartRefund = "order.partrefund.push" // 售前只能是商户发起 售后是用户, 你看是由谁发起的就可以知道,来自惠焕 CmdOrderStatus = "order.status.push" CmdOrderUserCancel = "order.user.cancel" CmdShopMsgPush = "shop.msg.push" CmdShopBindMsg = "shop.bind.msg" CmdShopUnbindMsg = "shop.unbind.msg" //IM消息回调通知 CmdImMessageSendEvent = "im.message.send.event" //用户/骑手消息通知 CmdImMessageReadEvent = "im.message.read.event" //用户/骑手已读通知 ) type CallbackResponse struct { Cmd string `json:"cmd"` Sign string `json:"sign"` Source string `json:"source"` Ticket string `json:"ticket"` Encrypt string `json:"encrypt"` Timestamp int64 `json:"timestamp"` Version int `json:"version"` Body *ResponseResult `json:"body"` } type CallbackMsg struct { Cmd string `json:"cmd"` Version string `json:"version"` Timestamp int64 `json:"timestamp"` Ticket string `json:"ticket"` Source string `json:"source"` Sign string `json:"sign"` Encrypt string `json:"encrypt"` Body map[string]interface{} `json:"body"` Data interface{} `json:"data"` } type EBaiShopList struct { BaiduShopID string `json:"baidu_shop_id"` ShopID string `json:"shop_id"` Name string `json:"name"` Source string `json:"source"` SupplierID string `json:"supplier_id"` } type CBPartRefundInfo struct { OrderID int64 `json:"order_id"` RefundID string `json:"refund_id"` Type int `json:"type"` Status int `json:"status"` AdditionReason string `json:"addition_reason"` Photos []string `json:"photos"` ReasonType string `json:"reason_type"` Reason string `json:"reason"` RefundProducts []*struct { SkuID string `json:"sku_id"` Upc string `json:"upc"` CustomSkuID string `json:"custom_sku_id"` Name string `json:"name"` Number int `json:"number"` TotalRefund int64 `json:"total_refund"` ShopEleRefund int64 `json:"shop_ele_refund"` } `json:"refund_products"` RefundPrice int64 `json:"refund_price"` } type CBUserCancelInfo struct { OrderID int64 `json:"order_id"` CancelReason string `json:"cancel_reason"` AdditionReason string `json:"addition_reason"` RefuseReason string `json:"refuse_reason"` Pictures []string `json:"pictures"` Type int `json:"type"` CancelType int `json:"cancel_type"` } //temp IM 用户/骑手消息通知 type TempSent struct { SubBizType string `json:"subBizType"` //业务子类型,枚举值:SEND_MESSAGE-发送消息 BizType string `json:"bizType"` //业务类型,枚举值:IM-消息 PayLoad struct { SenderID string `json:"senderId"` //角色+随机数字串;角色:10(用户)、20(骑手)、30(商家)、32(连锁账号登录) ReceiverIDs []string `json:"receiverIds"` //角色+随机数字串;角色:10(用户)、20(骑手)、30(商家)、32(连锁账号登录) CreateTime int64 `json:"createTime"` //时间戳 GroupID string `json:"groupId"` //会话id MsgID string `json:"msgId"` //消息ID ContentType int `json:"contentType"` //消息类型,枚举值:1-普通文本 } `json:"payload"` PlatformShopID string `json:"platformShopId"` //平台门店ID } //IM 用户/骑手消息通知 type ImMessageSend struct { SubBizType string `json:"subBizType"` //业务子类型,枚举值:SEND_MESSAGE-发送消息 BizType string `json:"bizType"` //业务类型,枚举值:IM-消息 PayLoad PayLoad `json:"payLoad"` PlatformShopID string `json:"platformShopId"` //平台门店ID } type PayLoad struct { SenderID string `json:"senderId"` //角色+随机数字串;角色:10(用户)、20(骑手)、30(商家)、32(连锁账号登录) ReceiverIDs []string `json:"receiverIds"` //角色+随机数字串;角色:10(用户)、20(骑手)、30(商家)、32(连锁账号登录) CreateTime int64 `json:"createTime"` //时间戳 GroupID string `json:"groupId"` //会话id MsgID string `json:"msgId"` //消息ID ContentType int `json:"contentType"` //消息类型,枚举值:1-普通文本 Content string `json:"content"` } //ContentType =1-普通文本,8-@消息 type Content struct { Text string `json:"text"` } //IM 用户/骑手已读通知 type ImMessageRead struct { PlatformShopID string `json:"platformShopId"` //平台门店ID BizType string `json:"bizType"` //业务类型,枚举值:IM-消息 SubBizType string `json:"subBizType"` //业务子类型,枚举值:READ_MESSAGE-读取消息 PayLoad struct { MsgIDs string `json:"msgIds"` //消息ID 列表 CID string `json:"cid"` //会话id UID string `json:"uid"` //已读操作人 } `json:"payLoad"` } func (a *API) Err2CallbackResponse(cmd string, err error, data interface{}) *CallbackResponse { response := &CallbackResponse{ Cmd: "resp." + cmd, Source: a.source, Ticket: utils.GetUpperUUID(), Timestamp: utils.GetCurTimestamp(), Version: 3, } if err == nil { response.Body = &ResponseResult{ Error: "success", ErrNo: 0, Data: data, } } else { response.Body = &ResponseResult{ Error: fmt.Sprintf("error:%v, data:%v", err, data), ErrNo: -1, Data: data, } } params := url.Values{ "cmd": []string{response.Cmd}, "version": []string{utils.Int2Str(response.Version)}, "timestamp": []string{utils.Int64ToStr(response.Timestamp)}, "ticket": []string{response.Ticket}, "source": []string{response.Source}, "body": []string{string(utils.MustMarshal(response.Body))}, "encrypt": []string{""}, } response.Sign = a.signParams(params) return response } func (a *API) unmarshalData(cmd string, data []byte, msg interface{}) (callbackResponse *CallbackResponse) { err := utils.UnmarshalUseNumber(data, msg) if err != nil { return a.Err2CallbackResponse(cmd, err, nil) } return nil } func (a *API) CheckCallbackValidation(cmd string, params url.Values) (callbackResponse *CallbackResponse) { sign := a.signParams(params) if sign != params.Get(signKey) { msg := fmt.Sprintf("Signature is not ok, mine:%v, get:%v", sign, params.Get(signKey)) baseapi.SugarLogger.Info(msg) return a.Err2CallbackResponse(cmd, errors.New(msg), nil) } return nil } func (a *API) GetCallbackMsg(request *http.Request) (msg *CallbackMsg, callbackResponse *CallbackResponse) { err := request.ParseForm() if err == nil { params := make(url.Values) for k := range request.PostForm { decodedValue, _ := url.QueryUnescape(request.PostFormValue(k)) params.Set(k, decodedValue) } msg = new(CallbackMsg) msg.Cmd = GetCmd(request) if callbackResponse = a.CheckCallbackValidation(msg.Cmd, params); callbackResponse != nil { return nil, callbackResponse } if callbackResponse = a.unmarshalData(msg.Cmd, []byte(params.Get("body")), &msg.Body); callbackResponse != nil { return nil, callbackResponse } msg.Timestamp = utils.Str2Int64(params.Get("timestamp")) msg.Version = params.Get("version") msg.Ticket = params.Get("ticket") msg.Source = params.Get("source") msg.Sign = params.Get("sign") msg.Encrypt = params.Get("encrypt") var tmpObj interface{} switch msg.Cmd { case CmdOrderPartRefund: var partRefundData CBPartRefundInfo tmpObj = &partRefundData case CmdOrderUserCancel: var userCancelData CBUserCancelInfo tmpObj = &userCancelData case CmdImMessageSendEvent: tmpObj = &ImMessageSend{} case CmdImMessageReadEvent: tmpObj = &ImMessageRead{} } if tmpObj != nil { if utils.Map2StructByJson(msg.Body, tmpObj, true) == nil { msg.Data = tmpObj } } return msg, nil } return nil, a.Err2CallbackResponse("", err, nil) } func GetCmd(request *http.Request) (cmd string) { cmd, _ = url.QueryUnescape(request.FormValue("cmd")) return cmd }