Files
baseapi/platformapi/ebaiapi/callback.go
邹宗楠 36d38162dc 1
2024-12-04 09:15:27 +08:00

274 lines
11 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 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" // 售前只能是商户发起 售后是用户, 你看是由谁发起的就可以知道,来自惠焕(部分退款,饿百废弃了)
CmdOrderReversePush = "order.reverse.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 CBOrderReversePush struct {
EventId string `json:"event_id"` // 操作事件全局唯一事件
PlatformShopId int `json:"platform_shop_id"` // 平台门店ID
OrderId string `json:"order_id"` // 订单ID
RefundOrderId int64 `json:"refund_order_id"` // 逆向单号
CurReverseEvent struct {
EventId string `json:"event_id"` // 操作事件全局唯一事件
ImageList []string `json:"image_list"` // 操作凭证列表
LastRefundStatus int `json:"last_refund_status"` // 逆向单操作前的退货状态0-无效状态1001-买家已申请退货等待审批处理1002-商家拒绝退货申请1003-退货仲裁已发起客服介入中1004-已同意退货等待发货1005-已发货等待卖家确认收货1006-已收到货,并同意退款, 1007-未收到货不同意退款1008-退货关闭
LastReturnGoodsStatus int `json:"last_return_goods_status"` // 逆向单操作前的逆向单状态0-初始化10-申请20-拒绝30-仲裁40-关闭50-成功60-失败
OccurTime int64 `json:"occur_time"` // 逆向单操作事件发生时间 单位:毫秒
OperatorRole int `json:"operator_role"` // 逆向单操作者角色10 用户 ,20商户,30客服 ,25 API商家代客发起,40系统
OrderId string `json:"order_id"` // 订单ID
ReasonCode int `json:"reason_code"` // 逆向单操作原因对应code具体原因枚举详见文档https://open-retail.ele.me/#/guide?topic=ntmt8f
ReasonContent string `json:"reason_content"` // 逆向单操作原因备注内容
RefundOrderId int64 `json:"refund_order_id"` // 逆向单号
RefundReasonDesc string `json:"refund_reason_desc"` // 逆向单操作原因code对应的文案
RefundStatus int `json:"refund_status"` // 即当前的逆向单状态0-初始化10-申请20-拒绝30-仲裁40-关闭50-成功60-失败
ReturnGoodsStatus int `json:"return_goods_status"` // 即当前的退货状态0-无效状态1001-买家已申请退货等待审批处理1002-商家拒绝退货申请1003-退货仲裁已发起客服介入中1004-已同意退货等待发货1005-已发货等待卖家确认收货1006-已收到货,并同意退款, 1007-未收到货不同意退款1008-退货关闭
} `json:"cur_reverse_event"` // 逆向单当前操作信息
}
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"`
ReasonCodeDesc string `json:"reason_code_desc"`
PlatformShopId int `json:"platform_shop_id"`
ReasonCode int `json:"reason_code"`
RefundOrderId string `json:"refund_order_id"`
IsReturnGoods string `json:"is_return_goods"`
}
//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 int `json:"createTime"` //时间戳
GroupID string `json:"groupId"` //会话id
MsgID string `json:"msgId"` //消息ID
ContentType string `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{}
case CmdOrderReversePush:
var reversePush CBOrderReversePush
tmpObj = &reversePush
}
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
}