336 lines
14 KiB
Go
336 lines
14 KiB
Go
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
|
||
}
|