Files
baseapi/platformapi/jdapi/callback.go
suyl aaba962e3e aa
2021-05-13 16:44:07 +08:00

319 lines
13 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 jdapi
import (
"io/ioutil"
"net/http"
"strings"
"git.rosy.net.cn/baseapi"
"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" // 财务调整单消息
// 售后
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"`
}
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 {
var orderMsg *CallbackOrderMsg
if err = utils.UnmarshalUseNumber([]byte(callbackMsg.JdParamJSON), &orderMsg); err == nil {
callbackMsg.Param = orderMsg
orderMsg.CallbackMsg = callbackMsg
}
}
}
if err != nil {
return nil, nil, Err2CallbackResponse(err, "")
}
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
}