Merge branch 'master' into get-store

This commit is contained in:
gazebo
2019-06-24 10:12:27 +08:00
67 changed files with 3112 additions and 729 deletions

View File

@@ -2,19 +2,102 @@ package jdapi
import (
"fmt"
"io/ioutil"
"net/http"
"net/url"
"strings"
"git.rosy.net.cn/baseapi"
"git.rosy.net.cn/baseapi/platformapi"
"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"
OrderStatusUserApplyCancel = "20030" // 这个其实不是一个状态,是一个动作
OrderStatusLocked = "20010"
OrderStatusUnlocked = "20050"
OrderStatusInfoChanged = "1" // 订单信息变更消息
OrderStatusPayFinishedSettle = "330901" // 订单支付完成应结
OrderStatusAdjustSettle = "330902" // 订单调整后应结
OrderStatusSwitch2SelfSettle = "330903" // 订单众包配送转自送后应结
)
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" // 订单应结消息
// 账务
CallbackMsgEndOrderFinance = "endOrderFinance" // 订单金额拆分完成消息
CallbackMsgFinanceAdjustment = "financeAdjustment" // 财务调整单消息
// 售后
CallbackMsgNewApplyAfterSaleBill = "newApplyAfterSaleBill" // 新建售后单申请消息
CallbackMsgUpdateApplyAfterSaleBill = "updateApplyAfterSaleBill" // 修改售后单申请消息
CallbackMsgNewAfterSaleBill = "newAfterSaleBill" // 新建售后单消息
CallbackMsgAfterSaleBillStatus = "afterSaleBillStatus" // 售后单状态消息
)
type CallbackResponse struct {
Code string `json:"code"`
Msg string `json:"msg"`
@@ -22,7 +105,7 @@ type CallbackResponse struct {
}
type CallbackOrderMsg struct {
ID int `json:"-"` // 用于传递Jdorder的主键值减少一次读库操作
MsgURL string `json:"msgURL"`
BillID string `json:"billId"`
OutBillID string `json:"outBillId"`
StatusID string `json:"statusId"`
@@ -31,6 +114,7 @@ type CallbackOrderMsg struct {
}
type CallbackDeliveryStatusMsg struct {
MsgURL string `json:"msgURL"`
OrderID string `json:"orderId"`
DeliveryStatusTime string `json:"deliveryStatusTime"`
DeliveryManNo string `json:"deliveryManNo"`
@@ -62,12 +146,8 @@ const (
OpenSourceBatchTask = 14
)
const (
SaleBillStatusRefundSuccess = "32"
SaleBillStatusSaleReturnSuccess = "114"
)
type CallbackStoreStockMsg struct {
MsgURL string `json:"msgURL"`
StationNo string `json:"stationNo"`
SkuId int64 `json:"skuId"`
Have bool `json:"have"`
@@ -115,7 +195,12 @@ func (a *API) CheckCallbackValidation(values url.Values) (callbackResponse *Call
return nil
}
func (a *API) getCommonOrderCallbackMsg(data []byte, msg interface{}, needDecode bool) (callbackResponse *CallbackResponse) {
func (a *API) getCommonOrderCallbackMsg(request *http.Request, msg interface{}, needDecode bool) (callbackResponse *CallbackResponse) {
data, err := ioutil.ReadAll(request.Body)
if err != nil {
return Err2CallbackResponse(err, "")
}
// baseapi.SugarLogger.Debug(string(data))
result, err := utils.HTTPBody2Values(data, needDecode)
if err != nil {
return FormatErrorResponse
@@ -132,28 +217,34 @@ func (a *API) getCommonOrderCallbackMsg(data []byte, msg interface{}, needDecode
return nil
}
func (a *API) GetOrderCallbackMsg(data []byte) (msg *CallbackOrderMsg, callbackResponse *CallbackResponse) {
func (a *API) GetOrderCallbackMsg(request *http.Request) (msg *CallbackOrderMsg, callbackResponse *CallbackResponse) {
msg = new(CallbackOrderMsg)
callbackResponse = a.getCommonOrderCallbackMsg(data, msg, false)
if callbackResponse = a.getCommonOrderCallbackMsg(request, msg, false); callbackResponse == nil {
msg.MsgURL = getMsgURLFromRequest(request)
}
return msg, callbackResponse
}
func (a *API) GetOrderApplyCancelCallbackMsg(data []byte) (msg *CallbackOrderMsg, callbackResponse *CallbackResponse) {
func (a *API) GetOrderApplyCancelCallbackMsg(request *http.Request) (msg *CallbackOrderMsg, callbackResponse *CallbackResponse) {
msg = new(CallbackOrderMsg)
callbackResponse = a.getCommonOrderCallbackMsg(data, msg, true)
if callbackResponse = a.getCommonOrderCallbackMsg(request, msg, true); callbackResponse == nil {
msg.MsgURL = getMsgURLFromRequest(request)
}
return msg, callbackResponse
}
func (a *API) GetOrderDeliveryCallbackMsg(data []byte) (msg *CallbackDeliveryStatusMsg, callbackResponse *CallbackResponse) {
msg = new(CallbackDeliveryStatusMsg)
callbackResponse = a.getCommonOrderCallbackMsg(data, msg, true)
func (a *API) GetOrderDeliveryCallbackMsg(request *http.Request) (msg *CallbackDeliveryStatusMsg, callbackResponse *CallbackResponse) {
if callbackResponse = a.getCommonOrderCallbackMsg(request, &msg, true); callbackResponse == nil {
msg.MsgURL = getMsgURLFromRequest(request)
}
return msg, callbackResponse
}
func (a *API) GetStoreStockCallbackMsg(data []byte) (msg *CallbackStoreStockMsg, callbackResponse *CallbackResponse) {
func (a *API) GetStoreStockCallbackMsg(request *http.Request) (msg *CallbackStoreStockMsg, callbackResponse *CallbackResponse) {
msg = new(CallbackStoreStockMsg)
msg.MsgURL = getMsgURLFromRequest(request)
var tmpMsg map[string]interface{}
callbackResponse = a.getCommonOrderCallbackMsg(data, &tmpMsg, true)
callbackResponse = a.getCommonOrderCallbackMsg(request, &tmpMsg, true)
if callbackResponse == nil {
msg.StationNo = utils.Interface2String(tmpMsg["stationNo"])
msg.SkuId = utils.Str2Int64(utils.Interface2String(tmpMsg["skuId"]))
@@ -161,12 +252,15 @@ func (a *API) GetStoreStockCallbackMsg(data []byte) (msg *CallbackStoreStockMsg,
msg.OperPin = utils.Interface2String(tmpMsg["operPin"])
msg.OperTime = utils.Str2Int64(utils.Interface2String(tmpMsg["operTime"]))
msg.OperSource = int(utils.Str2Int64((utils.Interface2String(tmpMsg["operSource"]))))
have := utils.Interface2String(tmpMsg["have"])
if have == "true" {
msg.Have = true
} else {
msg.Have = false
}
msg.Have = utils.Interface2String(tmpMsg["have"]) == "true"
}
return msg, callbackResponse
}
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
}

View File

@@ -184,7 +184,7 @@ func (a *API) AccessAPI(apiStr string, jdParams map[string]interface{}) (retVal
return request
},
a.config,
func(jsonResult1 map[string]interface{}) (errLevel string, err error) {
func(response *http.Response, jsonResult1 map[string]interface{}) (errLevel string, err error) {
code := jsonResult1["code"].(string)
if code == ResponseCodeSuccess {
retVal = jsonResult1

View File

@@ -27,7 +27,7 @@ func init() {
// 天天果园
// api = New("84541069-fbe2-424b-b625-9b2ba1d4c9e6", "5d5577a2506f41b8b4ec520ba83490f5", "0b01b9eeb15b41dab1c3d05d95c17a26")
api.SetStoreCookie("YYJV3NHVBPHLD36FWP6F3EM5PTXJ2XZQS7U4HWRIDPP4IWGUKUIB4XG5N26CZRDLDF7PKOXBPD6BNTUAJLETLZOIWMCVFI3K6MYZIY4QBIXIMXYDJNUKFGJVQTN5356SAD6WPCIHWNQAG7DDMF7L7S3SHBUOPCIUXDX4MQEAYEPUFFOAD4WJECT4R3K22T24MKC7OMIRDLX7S55243TDVXLO25PP4UYSPTTPMNRUFXDNP4WPE566Q6V4AH32F7HT")
api.SetStoreCookie("YYJV3NHVBPHLD36FWP6F3EM5PTXJ2XZQS7U4HWRIDPP4IWGUKUIB4XG5N26CZRDLDF7PKOXBPD6BNTUAJLETLZOIWMCVFI3K6MYZIY4QBIXIMXYDJNUKFGJVQTN5356SAD6WPCIHWNQAG7DDMF7L7S3SHDYZP7PPVMRGO4VWG2JRBMKFTOGIWZ5L2XHXC3SXQ4OLX7EL4RKUPZQT6GOH63KE3EVK37L5LG7TGSDGXFQP4377YK72UB5YZG6IJH6PY25YLLCJYPMDSHKPGYBUFJ4MMMKGN6MWB37CP7XVDBBZJ3U462ENTEXH744AWCQCIG2AAE2PKYVHC")
}
func TestTest(t *testing.T) {

View File

@@ -2,34 +2,15 @@ package jdapi
import (
"errors"
"strings"
"git.rosy.net.cn/baseapi"
"git.rosy.net.cn/baseapi/utils"
)
const (
OrderStatusAddComment = "12001"
OrderStatusModifyComment = "12006"
OrderStatusTipChanged = "12008"
OrderStatusPurchased = "41000" // 也即待处理JD的消息很怪新订单消息发过来是32000但如果不是自动接单的去查却是41000接单后才变为32000
OrderStatusNew = "32000"
OrderStatusAdjust = "33080"
OrderStatusWaitOutStore = "32001"
OrderStatusFinishedPickup = "2"
OrderStatusDelivering = "33040"
OrderStatusDelivered = "33060"
OrderStatusFinished = "90000"
OrderStatusCanceled = "20020"
OrderStatusUserApplyCancel = "20030" // 这个其实不是一个状态,是一个动作
OrderStatusLocked = "20010"
OrderStatusUnlocked = "20050"
OrderStatusInfoChanged = "1"
OrderStatusPayFinishedSettle = "330901" // 订单支付完成应结
OrderStatusAdjustSettle = "330902" // 订单调整后应结
OrderStatusSwitch2SelfSettle = "330903" // 订单众包配送转自送后应结
AfsPicPrefix = "http://img10.360buyimg.com/o2o"
)
const (
@@ -71,20 +52,139 @@ const (
QueryOrderRetryCount = 1 // 因为京东到家当前不存在的订单也返回-4暂时不重试
)
var (
ErrCanNotFindOrder = errors.New("can not find order")
const (
AfsApproveTypeRefund = 1 // 退款
AfsApproveTypeReturnGoods = 2 // 退货
AfsApproveTypeRefused = 3 // 驳回
)
var (
orderOperationResultParser = genNoPageResultParser("code", "msg", "detail", "0")
const (
AfsReasonTypeGoodsQuality = 201 // 商品质量问题/做工粗糙/有瑕疵
AfsReasonTypeWrongGoods = 202 // 发错货
AfsReasonTypeMissingGoods = 203 // 部分商品未收到
AfsReasonTypeNoGoods = 501 // 全部商品未收到
AfsReasonTypeDamagedGoods = 208 // 外表损伤(压坏,磕坏等)
AfsReasonTypeGoodsQuantity = 207 // 缺斤少两
AfsReasonTypeAgreedByMerchant = 209 // 与商家协商一致
AfsReasonTypeGoodsSizeNoSame = 302 // 大小尺寸与商品描述不符
AfsReasonTypeGoodsColorNoSame = 303 // 颜色/款式/图案与描述不符
AfsReasonWrongPurchase = 402 // 误购
AfsReasonNotReceivedIntime = 502 // 未在时效内送达
)
const (
AfsDealTypeRefund = "10" // 仅退款
AfsDealTypeDirectCompensate = "30" // 直赔
AfsDealTypeReturnGoodsRefund = "40" // 退货退款
)
type AfsSkuDiscount struct {
DetailDiscountType int `json:"detailDiscountType"`
DiscountType int `json:"discountType"`
PlatPayMoney int64 `json:"platPayMoney"`
VenderPayMoney int64 `json:"venderPayMoney"`
}
type AfsServiceDetail struct {
SkuIDIsv string `json:"skuIdIsv"`
WareID int64 `json:"wareId"`
WareName string `json:"wareName"`
WareNum int `json:"wareNum"`
SkuCount int `json:"skuCount"`
PromotionType int `json:"promotionType"`
Weight float64 `json:"weight"`
AfsMoney int64 `json:"afsMoney"`
PlatPayMoney int64 `json:"platPayMoney"`
AfsSkuDiscountList []*AfsSkuDiscount `json:"afsSkuDiscountList"`
}
type AfsServiceResponse struct {
AfsServiceID int64 `json:"afsServiceId"`
AfsServiceOrder string `json:"afsServiceOrder"`
AfsServiceState int `json:"afsServiceState"`
CreateTime *utils.JavaDate `json:"createTime"`
UpdateTime *utils.JavaDate `json:"updateTime"`
CustomerMobilePhone string `json:"customerMobilePhone"`
CustomerName string `json:"customerName"`
OrderID string `json:"orderId"`
OrderSource int `json:"orderSource"`
OrderStatus int `json:"orderStatus"`
OrderType int `json:"orderType"`
PickwareAddress string `json:"pickwareAddress"`
OrderFreightMoney int64 `json:"orderFreightMoney"`
AfsFreight int64 `json:"afsFreight"`
PackagingMoney int64 `json:"packagingMoney"`
TongchengFreightMoney int64 `json:"tongchengFreightMoney"`
MealBoxMoney int64 `json:"mealBoxMoney"`
QuestionDesc string `json:"questionDesc"`
QuestionPic string `json:"questionPic"`
QuestionTypeCid int `json:"questionTypeCid"`
ApplyDeal string `json:"applyDeal"`
DeliveryState string `json:"deliveryState"`
DeliveryMan string `json:"deliveryMan"`
DeliveryMobile string `json:"deliveryMobile"`
StationID string `json:"stationId"`
StationName string `json:"stationName"`
StationNumOutSystem string `json:"stationNumOutSystem"`
VenderID string `json:"venderId"`
AfsDetailList []*AfsServiceDetail `json:"afsDetailList"`
}
type OAOSAdjustDTO struct {
SkuID int64 `json:"skuId,omitempty"`
OutSkuID string `json:"outSkuId,omitempty"`
SkuCount int `json:"skuCount"`
}
type VenderAfsSkuDTO struct {
SkuID int64 `json:"skuId"`
SkuCount int `json:"skuCount"`
PromotionType int `json:"promotionType"`
}
type OrderSettlementInfo struct {
AllAfterSaleFreight int64 `json:"allAfterSaleFreight"`
AllAfterSalePackageMoney int64 `json:"allAfterSalePackageMoney"`
BillTime *utils.JavaDate `json:"billTime"`
DistanceFreightMoney int64 `json:"distanceFreightMoney"`
FreightCommission int64 `json:"freightCommission"`
GoodsCommission int64 `json:"goodsCommission"`
GuaranteedCommission int64 `json:"guaranteedCommission"`
OrderCashOnDeliveryMoney int64 `json:"orderCashOnDeliveryMoney"`
OrderGiftCardMoney int64 `json:"orderGiftCardMoney"`
OrderID int64 `json:"orderId"`
OrgCode string `json:"orgCode"`
PackageCommission int64 `json:"packageCommission"`
PackageMoney int64 `json:"packageMoney"`
PlatDeliveryFreight int64 `json:"platDeliveryFreight"`
PlatFreightDiscountMoney int64 `json:"platFreightDiscountMoney"`
PlatOrderGoodsDiscountMoney int64 `json:"platOrderGoodsDiscountMoney"`
PlatSkuGoodsDiscountMoney int64 `json:"platSkuGoodsDiscountMoney"`
SettlementAmount int64 `json:"settlementAmount"`
StationNo string `json:"stationNo"`
UserActualPaidGoodsMoney int64 `json:"userActualPaidGoodsMoney"`
VenderDeliveryFreight int64 `json:"venderDeliveryFreight"`
VenderFreightDiscountMoney int64 `json:"venderFreightDiscountMoney"`
VenderOrderGoodsDiscountMoney int64 `json:"venderOrderGoodsDiscountMoney"`
VenderPaidTips int64 `json:"venderPaidTips"`
VenderSkuGoodsDiscountMoney int64 `json:"venderSkuGoodsDiscountMoney"`
}
var (
ErrCanNotFindOrder = errors.New("can not find order")
)
var (
orderOperationResultParser = genNoPageResultParser("code", "detail", "detail", "0")
)
// 订单列表查询接口
// https://opendj.jd.com/staticnew/widgets/resources.html?groupid=169&apiid=ba3027848c3c4fda9674966e2a466482
func (a *API) OrderQuery(jdParams map[string]interface{}) (retVal []interface{}, totalCount int, err error) {
@@ -226,6 +326,14 @@ func (a *API) OrderShoudSettlementService(orderId string) (map[string]interface{
return result.(map[string]interface{}), nil
}
func (a *API) OrderShoudSettlementService2(orderId string) (orderSettlement *OrderSettlementInfo, err error) {
result, err := a.OrderShoudSettlementService(orderId)
if err == nil {
err = utils.Map2StructByJson(result, &orderSettlement, false)
}
return orderSettlement, err
}
// 查询售后单详情接口
// https://openo2o.jddj.com/staticnew/widgets/resources.html?groupid=170&apiid=6805ed690b7b4776b058067312c57d98
func (a *API) GetAfsService(orderId string) (map[string]interface{}, error) {
@@ -239,23 +347,35 @@ func (a *API) GetAfsService(orderId string) (map[string]interface{}, error) {
return result.(map[string]interface{}), nil
}
func (a *API) GetAfsService2(afsOrderID string) (afsOrderInfo *AfsServiceResponse, err error) {
result, err := a.GetAfsService(afsOrderID)
if err == nil {
if err = utils.Map2StructByJson(result, &afsOrderInfo, false); err != nil {
baseapi.SugarLogger.Warnf("GetAfsService2, result:%s failed with error:%v", utils.Format4Output(result, true), err)
}
}
return afsOrderInfo, err
}
// 商家审核用户取消申请接口
// https://openo2o.jddj.com/staticnew/widgets/resources.html?groupid=169&apiid=906b430307764a3ca3698c05c72f33d0
func (a *API) OrderCancelOperate(orderId string, isAgreed bool, operator, remark string) (err error) {
jdParams := map[string]interface{}{
"orderId": orderId,
"isAgreed": isAgreed,
"operator": operator,
"operator": utils.GetAPIOperator(operator),
"remark": remark,
}
_, err = a.AccessAPINoPage("ocs/orderCancelOperate", jdParams, nil, nil, nullResultParser)
return err
}
// 订单调整接口
// https://openo2o.jddj.com/staticnew/widgets/resources.html?groupid=169&apiid=a7378109fd7243eea9efbb6231a7401c
func (a *API) AdjustOrder(orderId, operPin, remark string, oaosAdjustDTOList []*OAOSAdjustDTO) (err error) {
jdParams := map[string]interface{}{
"orderId": orderId,
"operPin": operPin,
"operPin": utils.GetAPIOperator(operPin),
"remark": remark,
"oaosAdjustDTOList": oaosAdjustDTOList,
}
@@ -269,7 +389,7 @@ func (a *API) ReceiveFailedAudit(orderId string, isAgreed bool, operator, remark
jdParams := map[string]interface{}{
"orderId": orderId,
"isAgreed": isAgreed,
"operator": operator,
"operator": utils.GetAPIOperator(operator),
"remark": remark,
}
_, err = a.AccessAPINoPage("order/receiveFailedAudit", jdParams, nil, nil, nullResultParser)
@@ -281,7 +401,7 @@ func (a *API) ReceiveFailedAudit(orderId string, isAgreed bool, operator, remark
func (a *API) UrgeDispatching(orderId, updatePin string) (err error) {
jdParams := map[string]interface{}{
"orderId": orderId,
"updatePin": updatePin,
"updatePin": utils.GetAPIOperator(updatePin),
}
_, err = a.AccessAPINoPage("bm/urgeDispatching", jdParams, nil, nil, nullResultParser)
return err
@@ -297,3 +417,71 @@ func (a *API) ConfirmReceiveGoods(orderId string) (err error) {
_, err = a.AccessAPINoPage("order/confirmReceiveGoods", jdParams, nil, nil, nullResultParser)
return err
}
// 申请售后单审核接口
// https://openo2o.jddj.com/staticnew/widgets/resources.html?groupid=170&apiid=1690f6efc0144d59823b236e0d8506a1
func (a *API) AfsOpenApprove(afsOrderID string, afsApproveType int, rejectReason string, optPin string) (err error) {
jdParams := map[string]interface{}{
"serviceOrder": afsOrderID,
"approveType": afsApproveType,
"optPin": utils.GetAPIOperator(optPin),
}
if rejectReason != "" {
jdParams["rejectReason"] = rejectReason
}
_, err = a.AccessAPINoPage("afs/afsOpenApprove", jdParams, nil, nil, nullResultParser)
return err
}
// 售后单确认收货接口
// https://openo2o.jddj.com/staticnew/widgets/resources.html?groupid=170&apiid=4826086e81934405980ae26f80d956e0
func (a *API) ConfirmReceipt(afsOrderID, pin string) (err error) {
jdParams := map[string]interface{}{
"serviceOrder": afsOrderID,
"pin": utils.GetAPIOperator(pin),
}
_, err = a.AccessAPINoPage("afs/confirmReceipt", jdParams, nil, nil, nullResultParser)
return err
}
// 商家自主发起售后接口
// https://openo2o.jddj.com/staticnew/widgets/resources.html?groupid=170&apiid=b8d1ddacb03846a8a2e78c79723c752f
func (a *API) AfsSubmit(OrderID, pin, questionTypeCode, questionDesc, questionPic, customerName, customerMobilePhone, address string, skuList []*VenderAfsSkuDTO) (afsOrderID string, err error) {
jdParams := map[string]interface{}{
"orderId": OrderID,
"pin": utils.GetAPIOperator(pin),
"questionTypeCode": questionTypeCode,
}
if questionDesc != "" {
jdParams["questionDesc"] = questionDesc
}
if questionPic != "" {
jdParams["questionPic"] = questionPic
}
if customerName != "" {
jdParams["customerName"] = customerName
}
if customerMobilePhone != "" {
jdParams["customerMobilePhone"] = customerMobilePhone
}
if address != "" {
jdParams["address"] = address
}
result, err := a.AccessAPINoPage("afs/submit", jdParams, nil, nil, genNoPageResultParser("code", "msg", "result", "0"))
if err == nil {
afsOrderID = utils.Interface2String(result.(map[string]interface{})["serviceOrder"])
}
return afsOrderID, err
}
func ProcessQuestionPic(questionPic string) (outQuestionPic string) {
if questionPic != "" {
picList := strings.Split(questionPic, ",")
picList2 := make([]string, len(picList))
for index, pic := range picList {
picList2[index] = AfsPicPrefix + "/" + pic
}
outQuestionPic = strings.Join(picList2, ",")
}
return outQuestionPic
}

View File

@@ -50,7 +50,7 @@ func TestOrderQuery(t *testing.T) {
func TestGetOrderCallbackMsg(t *testing.T) {
callbackStr := "timestamp=2018-06-27+12%3A43%3A51&sign=84096ADFAB81E224D6231269AD1F6AAB&v=1.0&jd_param_json=%7B%22billId%22%3A%22815338526000221%22%2C%22statusId%22%3A%2232000%22%2C%22timestamp%22%3A%222018-06-27+12%3A42%3A34%22%7D&token=91633f2a-c5f5-4982-a925-a220d19095c3&app_key=1dba76d40cac446ca500c0391a0b6c9d&format=json"
result, resp := api.GetOrderCallbackMsg([]byte(callbackStr))
result, resp := api.GetOrderCallbackMsg(utils.BuildRequest(http.MethodPost, "", callbackStr, ""))
if resp != nil {
t.Fatal(resp)
@@ -60,7 +60,7 @@ func TestGetOrderCallbackMsg(t *testing.T) {
func TestGetOrderDeliveryCallbackMsg(t *testing.T) {
callbackStr := "timestamp=2018-06-27%2B09%253A08%253A41&sign=54D9A8515BB5650DC3B81366E3286570&v=1.0&jd_param_json=%257B%2522createPin%2522%253A%2522JD_21134dac1c251d2%2522%252C%2522deliveryCarrierName%2522%253A%2522%25E8%25BE%25BE%25E8%25BE%25BE%25E4%25B8%2593%25E9%2580%2581%2522%252C%2522deliveryCarrierNo%2522%253A%25229966%2522%252C%2522deliveryStatus%2522%253A%252210%2522%252C%2522deliveryStatusTime%2522%253A%25222018-06-27%2B09%253A08%253A41%2522%252C%2522inputTime%2522%253A%25222018-06-27%2B09%253A08%253A41%2522%252C%2522orderId%2522%253A%2522815324888000121%2522%257D&token=91633f2a-c5f5-4982-a925-a220d19095c3&app_key=1dba76d40cac446ca500c0391a0b6c9d&format=json"
result, resp := api.GetOrderDeliveryCallbackMsg([]byte(callbackStr))
result, resp := api.GetOrderDeliveryCallbackMsg(utils.BuildRequest(http.MethodPost, "", callbackStr, ""))
if resp != nil {
t.Fatal(resp)
@@ -70,7 +70,7 @@ func TestGetOrderDeliveryCallbackMsg(t *testing.T) {
func TestGetOrderApplyCancelCallbackMsg(t *testing.T) {
callbackStr := "timestamp=2018-06-27%2B13%253A35%253A29&sign=F1398D658514D8864FFB56F5EF2C4792&v=1.0&jd_param_json=%257B%2522billId%2522%253A%2522815339944000322%2522%252C%2522remark%2522%253A%2522%25E5%2595%2586%25E5%25AE%25B6%25E7%25BC%25BA%25E8%25B4%25A7%2522%252C%2522statusId%2522%253A%252220030%2522%252C%2522timestamp%2522%253A%25222018-06-27%2B13%253A35%253A24%2522%257D&token=91633f2a-c5f5-4982-a925-a220d19095c3&app_key=1dba76d40cac446ca500c0391a0b6c9d&format=json"
result, resp := api.GetOrderApplyCancelCallbackMsg([]byte(callbackStr))
result, resp := api.GetOrderApplyCancelCallbackMsg(utils.BuildRequest(http.MethodPost, "", callbackStr, ""))
if resp != nil {
t.Fatal(resp)
@@ -81,7 +81,7 @@ func TestGetOrderApplyCancelCallbackMsg(t *testing.T) {
func TestSimulateSendNewOrderMsg(t *testing.T) {
orderInfo := &CallbackOrderMsg{
BillID: "813344594000041",
StatusID: OrderStatusNew,
StatusID: OrderStatusPurchased,
Timestamp: utils.GetCurTimeStr(),
}
params := make(url.Values)
@@ -163,7 +163,7 @@ func TestOrderAcceptOperate(t *testing.T) {
}
func TestOrderJDZBDelivery(t *testing.T) {
result, err := api.OrderJDZBDelivery("813344594000041", "")
result, err := api.OrderJDZBDelivery("911350836000622", "")
if err != nil {
t.Fatal(err.Error())
}
@@ -171,7 +171,7 @@ func TestOrderJDZBDelivery(t *testing.T) {
}
func TestModifySellerDelivery(t *testing.T) {
result, err := api.ModifySellerDelivery("813344594000041", "")
result, err := api.ModifySellerDelivery("914376668000422", "")
if err != nil {
t.Fatal(err.Error())
}
@@ -193,3 +193,27 @@ func TestDeliveryEndOrder(t *testing.T) {
}
sugarLogger.Debug(result)
}
func TestGetAfsService(t *testing.T) {
result, err := api.GetAfsService("22565438")
if err != nil {
t.Fatal(err.Error())
}
sugarLogger.Debug(utils.Format4Output(result, false))
}
func TestGetAfsService2(t *testing.T) {
result, err := api.GetAfsService2("22565438")
if err != nil {
t.Fatal(err.Error())
}
sugarLogger.Debug(utils.Format4Output(result, false))
}
func TestOrderShoudSettlementService2(t *testing.T) {
result, err := api.OrderShoudSettlementService2("914508761000241")
if err != nil {
t.Fatal(err.Error())
}
sugarLogger.Debug(utils.Format4Output(result, false))
}

View File

@@ -0,0 +1,108 @@
package jdapi
import (
"time"
"git.rosy.net.cn/baseapi/utils"
)
const (
AuditPromotionStateNew = 101 // 待开始
AuditPromotionStateOnGoing = 102 // 进行中
AuditPromotionStateEnded = 103 // 结束
AuditPromotionStateCanceled = 104 // 取消
AuditPromotionStateAll = 105 // 全部
)
type OpenPlatActivityQResponse struct {
AddLadderList []struct {
BenefitMaxCount int `json:"benefitMaxCount"`
DiscountAmount int `json:"discountAmount"`
DiscountRate float32 `json:"discountRate"`
LowMoney int `json:"lowMoney"`
LowerLimitCount int `json:"lowerLimitCount"`
OrderLadder string `json:"orderLadder"`
} `json:"addLadderList"`
Awords string `json:"awords"`
BeginDate *utils.JavaDate `json:"beginDate"`
CostRadios int `json:"costRadios"`
EndDate *utils.JavaDate `json:"endDate"`
ID int `json:"id"`
IsMerchant int `json:"isMerchant"`
OrderLadder string `json:"orderLadder"`
OrgCode string `json:"orgCode"`
OutActivityID string `json:"outActivityId"`
PromotionName string `json:"promotionName"`
SkuBeanList []struct {
SkuID int64 `json:"skuId"`
SkuName int64 `json:"skuName"`
} `json:"skuBeanList"`
State int `json:"state"`
StationBeanList []struct {
OrgCode interface{} `json:"orgCode"`
OrgName string `json:"orgName"`
OutStationNo string `json:"outStationNo"`
StationName string `json:"stationName"`
StationNo int `json:"stationNo"`
} `json:"stationBeanList"`
}
type PromotionLspQuerySkuResult struct {
BeginTime *utils.JavaDate `json:"beginTime"`
EndTime *utils.JavaDate `json:"endTime"`
LimitDaily int `json:"limitDaily"`
LimitDevice int `json:"limitDevice"`
LimitPin int `json:"limitPin"`
PlatformRatio int `json:"platformRatio"`
PromotionPrice int `json:"promotionPrice"`
PromotionState int `json:"promotionState"`
PromotionType int `json:"promotionType"`
SkuID int64 `json:"skuId"`
Source string `json:"source"`
StationNo int64 `json:"stationNo"`
StoreRatio int `json:"storeRatio"`
}
type PromotionLspQueryInfoResult struct {
BeginTime *utils.JavaDate `json:"beginTime"`
EndTime *utils.JavaDate `json:"endTime"`
PromotionInfoID int64 `json:"promotionInfoId"`
PromotionState int `json:"promotionState"`
PromotionType int `json:"promotionType"`
SkuResultList []*PromotionLspQuerySkuResult `json:"skuResultList"`
Source string `json:"source"`
}
// 此接口逐渐会被[新版订单级促销]中相应接口替换
// 根据到家活动ID查询订单级活动明细接口
// https://openo2o.jddj.com/staticnew/widgets/resources.html?groupid=196&apiid=ff1ade31ac1b4a50be760854c777b567
func (a *API) OrderDiscountQueryActivityInfoById(activityID int64, promotionType, state int, operator string) (response *OpenPlatActivityQResponse, err error) {
params := map[string]interface{}{
"activityId": activityID,
"type": promotionType,
"traceId": utils.GetUUID(),
"operator": operator,
"requestTime": time.Now().UnixNano() / 1000000,
}
if state > 0 {
params["state"] = state
}
result, err := a.AccessAPINoPage("orderdiscount/queryActivityInfoById", params, nil, nil, genNoPageResultParser("errorCode", "errorInfos", "data", "10000"))
if err == nil {
err = utils.Map2StructByJson(result, &response, false)
}
return response, err
}
// 根据到家活动ID查询单品级促销活动接口
// https://openo2o.jddj.com/staticnew/widgets/resources.html?groupid=196&apiid=a47520a9757f4b0dbac1e6d36fd1103d
func (a *API) QueryPromotionInfo(promotionInfoId int64) (promotionInfo *PromotionLspQueryInfoResult, err error) {
jdParams := map[string]interface{}{
"promotionInfoId": promotionInfoId,
}
result, err := a.AccessAPINoPage("singlePromote/queryPromotionInfo", jdParams, nil, nil, genNoPageResultParser("errorCode", "errorInfos", "data", "0"))
if err == nil {
err = utils.Map2StructByJson(result, &promotionInfo, false)
}
return promotionInfo, err
}

View File

@@ -0,0 +1,23 @@
package jdapi
import (
"testing"
"git.rosy.net.cn/baseapi/utils"
)
func TestOrderDiscountQueryActivityInfoById(t *testing.T) {
result, err := api.OrderDiscountQueryActivityInfoById(1297945, OrderDiscountActivityTypeManJian, 0, "test")
if err != nil {
t.Fatal(err)
}
t.Log(utils.Format4Output(result, false))
}
func TestQueryPromotionInfo(t *testing.T) {
result, err := api.QueryPromotionInfo(43430316)
if err != nil {
t.Fatal(err)
}
t.Log(utils.Format4Output(result, false))
}

View File

@@ -1,11 +1,11 @@
package jdapi
import (
"time"
"git.rosy.net.cn/baseapi/utils"
)
// 新版订单级促销
const (
OrderDiscountActivityTypeManJian = 1 // 满减
OrderDiscountActivityTypeHuanGou = 1202 // 换购
@@ -32,7 +32,7 @@ type OrderDiscountRuleRequest struct {
DiscountRate float32 `json:"discountRate,omitempty"`
AddPrice int `json:"addPrice,omitempty"` // 分
GiftList []*OrderDiscountGift `json:"giftList,omitempty"`
LadderLimit int `json:"ladderLimit,omitempty"`
LadderLimit int `json:"ladderLimit"`
}
type OrderDiscountActivity struct {
@@ -44,11 +44,11 @@ type OrderDiscountActivity struct {
ParticipationMode int `json:"participationMode"` // 必须
OutStationNos []string `json:"outStationNos,omitempty"`
StationNos []string `json:"stationNos,omitempty"`
OutSkuIds []string `json:"outSkuIds,omitempty"`
SkuIds []string `json:"skuIds,omitempty"`
LimitOrderTotalNumber int `json:"limitOrderTotalNumber"` // 必须
LimitUserTotalNumber int `json:"limitUserTotalNumber,omitempty"`
Display string `json:"display"` // 必须
OutSkuIDs []string `json:"outSkuIds,omitempty"`
SkuIDs []string `json:"skuIds,omitempty"`
LimitOrderTotalNumber int `json:"limitOrderTotalNumber"` // 必须, 活动限购单量(0为不限不超过10万)
LimitUserTotalNumber int `json:"limitUserTotalNumber,omitempty"` // 用户限购单量(0为不限不超过100仅满减和每满减有效)
Display string `json:"display"` // 必须
RuleRequestList []*OrderDiscountRuleRequest `json:"ruleRequestList,omitempty"`
}
@@ -69,19 +69,45 @@ type ActivityOpQueryResultResponse struct {
}
type ActivityOpQueryInfoResponse struct {
ActivityID int64 `json:"activityID"`
OutActivityID string `json:"outActivityId"`
PromotionName string `json:"promotionName"`
BeginDate time.Time `json:"beginDate"`
EndDate time.Time `json:"endDate"`
Awords string `json:"awords"`
State int `json:"state"`
OrderLadder string `json:"orderLadder"`
StationList []int `json:"stationList"`
SkuList []int `json:"skuList"`
LadderList []int `json:"ladderList"`
ActivityID int64 `json:"activityID"`
OutActivityID string `json:"outActivityId"`
PromotionName string `json:"promotionName"`
BeginDate *utils.JavaDate `json:"beginDate"`
EndDate *utils.JavaDate `json:"endDate"`
Awords string `json:"awords"`
State int `json:"state"`
OrderLadder string `json:"orderLadder"`
StationList []struct {
OrgName string `json:"orgName"`
StationNo int64 `json:"stationNo"`
OutStationNo string `json:"outStationNo"`
StationName string `json:"stationName"`
} `json:"stationList"`
SkuList []struct {
OrgName string `json:"orgName"`
SkuID int64 `json:"skuId"`
OutSkuID string `json:"outSkuId"`
SkuName string `json:"skuName"`
} `json:"skuList"`
LadderList []struct {
BenefitMaxCount int `json:"benefitMaxCount"`
DiscountAmount int `json:"discountAmount"`
DiscountRate float32 `json:"discountRate"`
LowMoney int `json:"lowMoney"`
LowerLimitCount int `json:"lowerLimitCount"`
OpGiftSkuList []struct {
OrgName string `json:"orgName"`
SkuID int64 `json:"skuId"`
OutSkuID string `json:"outSkuId"`
SkuName string `json:"skuName"`
StockCount int `json:"stockCount"`
} `json:"opGiftSkuList"`
OrderLadder string `json:"orderLadder"`
} `json:"ladderList"`
}
// 订单级促销活动提交接口
// https://openo2o.jddj.com/staticnew/widgets/resources.html?groupid=211&apiid=cf98af94d4124ca287af6cfe48f0f3aa
func (a *API) OrderDiscountSubmitActivity(actInfo *OrderDiscountActivity) (activityID int64, err error) {
result, err := a.AccessAPINoPage("orderdiscount/submitActivity", utils.Struct2FlatMap(actInfo), nil, nil, nil)
if err == nil {
@@ -90,60 +116,46 @@ func (a *API) OrderDiscountSubmitActivity(actInfo *OrderDiscountActivity) (activ
return 0, err
}
// 订单级促销活动查询活动提交处理结果接口
// https://openo2o.jddj.com/staticnew/widgets/resources.html?groupid=211&apiid=b04e5426948349a78db1c5c9585d8df7
func (a *API) OrderDiscountQuerySubmitActivityResult(activityID int64) (response *ActivityOpQueryResultResponse, err error) {
result, err := a.AccessAPINoPage("orderdiscount/querySubmitActivityResult", map[string]interface{}{
"activityId": activityID,
"operator": "jxc4",
"operator": utils.APIPin,
"traceId": utils.GetUUID(),
}, nil, nil, nil)
}, nil, nil, genNoPageResultParser("code", "detail", "result", "0"))
if err == nil {
resultMap := result.(map[string]interface{})
response = &ActivityOpQueryResultResponse{
SubCode: utils.Interface2String(resultMap["subCode"]),
SubMsg: utils.Interface2String(resultMap["subMsg"]),
}
for _, v := range resultMap["resultList"].([]interface{}) {
vMap := v.(map[string]interface{})
response.ResultList = append(response.ResultList, &ActivityOpResultInfo{
ActivityID: utils.MustInterface2Int64(vMap["activityId"]),
PromName: utils.Interface2String(vMap["promName"]),
StationNo: utils.MustInterface2Int64(vMap["stationNo"]),
SkuID: utils.MustInterface2Int64(vMap["skuId"]),
OutActivityID: utils.Interface2String(vMap["outActivityId"]),
OutSkuID: utils.Interface2String(vMap["outSkuId"]),
OutStationNo: utils.Interface2String(vMap["outStationNo"]),
})
}
err = utils.Map2StructByJson(result.([]interface{})[0], &response, true) // todo只取第一个
}
return response, err
}
// func (a *API) OrderDiscountQueryActivityInfo(activityID int64) (response *OrderDiscountResultResponse, err error) {
// result, err := a.AccessAPINoPage("orderdiscount/queryActivityInfo", map[string]interface{}{
// "activityId": activityID,
// "sourceFrom": 3,
// "operator": "",
// "traceId": "",
// "version": "",
// }, nil, nil, nil)
// if err == nil {
// resultMap := result.(map[string]interface{})
// response = &OrderDiscountResultResponse{
// SubCode: utils.Interface2String(resultMap["subCode"]),
// SubMsg: utils.Interface2String(resultMap["subMsg"]),
// }
// for _, v := range resultMap["resultList"].([]interface{}) {
// vMap := v.(map[string]interface{})
// response.ResultList = append(response.ResultList, &OrderDiscountResultInfo{
// ActivityID: utils.MustInterface2Int64(vMap["activityId"]),
// PromName: utils.Interface2String(vMap["promName"]),
// StationNo: utils.MustInterface2Int64(vMap["stationNo"]),
// SkuID: utils.MustInterface2Int64(vMap["skuId"]),
// OutActivityId: utils.Interface2String(vMap["outActivityId"]),
// OutSkuId: utils.Interface2String(vMap["outSkuId"]),
// OutStationNo: utils.Interface2String(vMap["outStationNo"]),
// })
// }
// }
// return response, err
// }
// 订单级促销活动查询促销详情接口
// https://openo2o.jddj.com/staticnew/widgets/resources.html?groupid=211&apiid=116d7dfe0b4e4122be300ce26b4e5381
func (a *API) OrderDiscountQueryActivityInfo(activityID int64) (response *ActivityOpQueryInfoResponse, err error) {
result, err := a.AccessAPINoPage("orderdiscount/queryActivityInfo", map[string]interface{}{
"activityId": activityID,
"sourceFrom": 3,
"operator": utils.APIPin,
"traceId": "",
"version": "",
}, nil, nil, genNoPageResultParser("code", "detail", "result", "0"))
if err == nil {
err = utils.Map2StructByJson(result, &response, true)
}
return response, err
}
// 订单级促销活动取消接口
// https://openo2o.jddj.com/staticnew/widgets/resources.html?groupid=211&apiid=42509fdfeec14105a516b07b774a3055
func (a *API) OrderDiscountCancelActivity(activityID int64, operator, traceID string) (err error) {
if traceID == "" {
traceID = utils.GetUUID()
}
_, err = a.AccessAPINoPage("orderdiscount/cancelActivity", map[string]interface{}{
"activityId": activityID,
"operator": utils.GetAPIOperator(operator),
"traceId": traceID,
}, nil, nil, nil)
return err
}

View File

@@ -9,21 +9,22 @@ import (
func TestOrderDiscountSubmitActivity(t *testing.T) {
actInfo := &OrderDiscountActivity{
OutActivityID: utils.GetUUID(),
PromName: "测试0404",
PromType: OrderDiscountActivityTypeManJian,
BeginTime: utils.Time2Str(time.Now().Add(1 * time.Hour)),
EndTime: utils.Time2Str(time.Now().Add(48 * time.Hour)),
ParticipationMode: ParticipationModeAllSku,
Display: "hello",
OutStationNos: []string{"25"},
OutSkuIds: []string{"5199"},
OutActivityID: utils.GetUUID(),
PromName: "测试0404",
PromType: OrderDiscountActivityTypeManJian,
BeginTime: utils.Time2Str(time.Now().Add(1 * time.Hour)),
EndTime: utils.Time2Str(time.Now().Add(48 * time.Hour)),
ParticipationMode: ParticipationModePartSku,
Display: "hello",
OutStationNos: []string{"2"},
// OutSkuIDs: []string{"5199"},
SkuIDs: []string{"2023747677"},
LimitUserTotalNumber: 1,
RuleRequestList: []*OrderDiscountRuleRequest{
&OrderDiscountRuleRequest{
LowerLimitAmount: 100,
DiscountAmount: 1000,
DiscountRate: 0.5,
LowerLimitAmount: 1000,
DiscountAmount: 100,
DiscountRate: 8.5,
},
},
}
@@ -35,9 +36,24 @@ func TestOrderDiscountSubmitActivity(t *testing.T) {
}
func TestOrderDiscountQuerySubmitActivityResult(t *testing.T) {
result, err := api.OrderDiscountQuerySubmitActivityResult(3)
result, err := api.OrderDiscountQuerySubmitActivityResult(10000051)
if err != nil {
t.Fatal(err)
}
t.Log(result)
}
func TestOrderDiscountQueryActivityInfo(t *testing.T) {
result, err := api.OrderDiscountQueryActivityInfo(10000051)
if err != nil {
t.Fatal(err)
}
t.Log(utils.Format4Output(result, false))
}
func TestOrderDiscountCancelActivity(t *testing.T) {
err := api.OrderDiscountCancelActivity(10000049, "test", "")
if err != nil {
t.Fatal(err)
}
}

View File

@@ -29,30 +29,24 @@ const (
PromotionStateEnded = 9
)
type PromotionSkuResult struct {
LimitDaily int
LimitDevice int
LimitPin int
PlatformRatio int
PromotionPrice int
SkuId int64
StationNo int64
StoreRatio int
}
type PromotionSku struct {
SkuID int64 `json:"skuId,omitempty"`
OutSkuID string `json:"outSkuId,omitempty"`
StationNo int64 `json:"stationNo,omitempty"`
OutStationNo string `json:"outStationNo,omitempty"`
type PromotionInfo struct {
BeginTime time.Time
EndTime time.Time
PromotionInfoId int64
PromotionState int
PromotionType int
Source string
SkuResultList []*PromotionSkuResult
PromotionPrice int64 `json:"promotionPrice,omitempty"`
LimitSkuCount int `json:"limitSkuCount,omitempty"`
FailReason string `json:"failReason,omitempty"`
}
func getPromotionCmd(inCmd string, promotionType int) (outCmd string) {
if promotionType == PromotionTypeDirectDown {
outCmd = "singlePromote/" + inCmd
if inCmd == "adjustPromotionSku" || inCmd == "adjustPromotionTime" {
outCmd = "promotesku/" + inCmd
} else {
outCmd = "singlePromote/" + inCmd
}
} else if promotionType == PromotionTypeLimitedTime {
outCmd = "limitTime/" + inCmd
} else {
@@ -63,86 +57,115 @@ func getPromotionCmd(inCmd string, promotionType int) (outCmd string) {
// 单品直降添加主活动信息接口
// https://opendj.jd.com/staticnew/widgets/resources.html?groupid=178&apiid=ee8685c9be9b4aa5bdc41468c5ebc33b
func (a *API) CreatePromotionInfosSingle(name string, beginDate, endDate time.Time, outInfoId, advertising string) (infoId int64, err error) {
return a.createPromotionInfos(PromotionTypeDirectDown, name, beginDate, endDate, outInfoId, advertising)
func (a *API) CreatePromotionInfosSingle(name string, beginDate, endDate time.Time, outInfoId, advertising, traceId string) (infoId int64, err error) {
return a.createPromotionInfos(PromotionTypeDirectDown, name, beginDate, endDate, outInfoId, advertising, traceId)
}
// 单品直降添加活动规则信息接口
// https://openo2o.jddj.com/staticnew/widgets/resources.html?groupid=178&apiid=900a9577cb304bbbb59abb7c2c33854d
func (a *API) CreatePromotionRulesSingle(infoId int64, outInfoId string, limitDevice, limitPin, limitCount, limitDaily int, traceId string) (err error) {
return a.createPromotionRules(PromotionTypeDirectDown, infoId, outInfoId, limitDevice, limitPin, limitCount, limitDaily, traceId)
}
// 单品直降添加活动商品信息接口
// 最多200条
// https://opendj.jd.com/staticnew/widgets/resources.html?groupid=178&apiid=0ad0715e0aaa42489cbeac36398e916d
func (a *API) CreatePromotionSkuSingle(infoId int64, outInfoId string, skus []map[string]interface{}) (skusResult []map[string]interface{}, err error) {
return a.createPromotionSku(PromotionTypeDirectDown, infoId, outInfoId, skus)
func (a *API) CreatePromotionSkuSingle(infoId int64, outInfoId string, skus []*PromotionSku, traceId string) (skusResult []*PromotionSku, err error) {
return a.createPromotionSku(PromotionTypeDirectDown, infoId, outInfoId, skus, traceId)
}
// 单品直降活动提交保存接口
// https://opendj.jd.com/staticnew/widgets/resources.html?groupid=178&apiid=b84e14eb341e470db8ed9b60f78edb16
func (a *API) ConfirmPromotionSingle(infoId int64, outInfoId string) (err error) {
return a.confirmPromotion(PromotionTypeDirectDown, infoId, outInfoId)
func (a *API) ConfirmPromotionSingle(infoId int64, outInfoId, traceId string) (err error) {
return a.confirmPromotion(PromotionTypeDirectDown, infoId, outInfoId, traceId)
}
// 单品直降活动部分商品取消接口
// https://openo2o.jddj.com/staticnew/widgets/resources.html?groupid=178&apiid=cfd14470b3fe4625bd2405b20bf8cec4
func (a *API) CancelPromotionSkuSingle(infoId int64, outInfoId string, cancelSkus []*PromotionSku, traceId string) (err error) {
return a.cancelPromotionSku(PromotionTypeDirectDown, infoId, outInfoId, cancelSkus, traceId)
}
// 单品直降整个活动取消接口
// https://opendj.jd.com/staticnew/widgets/resources.html?groupid=178&apiid=3d02c2acad714bea86d20d498a1aa074
func (a *API) CancelPromotionSingle(infoId int64, outInfoId string) (err error) {
return a.cancelPromotion(PromotionTypeDirectDown, infoId, outInfoId)
func (a *API) CancelPromotionSingle(infoId int64, outInfoId, traceId string) (err error) {
return a.cancelPromotion(PromotionTypeDirectDown, infoId, outInfoId, traceId)
}
// 单品实时促销活动结束时间调整接口
// https://openo2o.jddj.com/staticnew/widgets/resources.html?groupid=178&apiid=0abab0c4b81d45e5bc555cc7dfbeb1ad
func (a *API) AdjustPromotionTimeSingle(infoId int64, outInfoId string, endDate time.Time, traceId string) (err error) {
return a.adjustPromotionTime(PromotionTypeDirectDown, infoId, outInfoId, endDate, traceId)
}
// 单品实时促销商品促销数量调整接口
// https://openo2o.jddj.com/staticnew/widgets/resources.html?groupid=178&apiid=82964e5e0f9c448db072a54ed20e00c4
func (a *API) AdjustPromotionSkuSingle(infoId int64, outInfoId string, skus []*PromotionSku, traceId string) (skusResult []*PromotionSku, err error) {
return a.adjustPromotionSku(PromotionTypeDirectDown, infoId, outInfoId, skus, traceId)
}
// 以下为限时抢
// 限时抢添加活动主信息接口
// https://opendj.jd.com/staticnew/widgets/resources.html?groupid=184&apiid=7d8b7ff86c9e457bb8a46963cb575769
func (a *API) CreatePromotionInfosLimitTime(name string, beginDate, endDate time.Time, outInfoId, advertising string) (infoId int64, err error) {
return a.createPromotionInfos(PromotionTypeLimitedTime, name, beginDate, endDate, outInfoId, advertising)
func (a *API) CreatePromotionInfosLimitTime(name string, beginDate, endDate time.Time, outInfoId, advertising, traceId string) (infoId int64, err error) {
return a.createPromotionInfos(PromotionTypeLimitedTime, name, beginDate, endDate, outInfoId, advertising, traceId)
}
// 限时抢添加活动规则信息接口(直降也是调用此接口)
// 限时抢添加活动规则信息接口
// https://opendj.jd.com/staticnew/widgets/resources.html?groupid=184&apiid=e80674791d3542f0a87502753c0d0592
func (a *API) CreatePromotionRules(infoId int64, outInfoId string, limitDevice, limitPin, limitCount, limitDaily int) (err error) {
jdParams := map[string]interface{}{
"limitDevice": limitDevice,
"limitPin": limitPin,
"limitCount": limitCount,
"limitDaily": limitDaily,
"timeStamp": utils.GetCurTimeStr(),
}
if infoId != 0 {
jdParams[KeyInfoId] = infoId
} else {
jdParams[KeyOutInfoId] = outInfoId
}
_, err = a.AccessAPINoPage("limitTime/createPromotionRules", jdParams, nil, nil, genNoPageResultParser("errorCode", "errorInfos", "", "0"))
return err
func (a *API) CreatePromotionRulesLimitTime(infoId int64, outInfoId string, limitDevice, limitPin, limitCount, limitDaily int, traceId string) (err error) {
return a.createPromotionRules(PromotionTypeLimitedTime, infoId, outInfoId, limitDevice, limitPin, limitCount, limitDaily, traceId)
}
// 限时抢添加活动商品信息接口
// 最多200条
// https://opendj.jd.com/staticnew/widgets/resources.html?groupid=184&apiid=65fecef4883c40c6b23bbdb6123f5d80
func (a *API) CreatePromotionSkuLimitTime(infoId int64, outInfoId string, skus []map[string]interface{}) (skusResult []map[string]interface{}, err error) {
return a.createPromotionSku(PromotionTypeLimitedTime, infoId, outInfoId, skus)
func (a *API) CreatePromotionSkuLimitTime(infoId int64, outInfoId string, skus []*PromotionSku, traceId string) (skusResult []*PromotionSku, err error) {
return a.createPromotionSku(PromotionTypeLimitedTime, infoId, outInfoId, skus, traceId)
}
// 限时抢活动提交保存接口
// https://opendj.jd.com/staticnew/widgets/resources.html?groupid=184&apiid=3991063e2f0d435094e9fe44754f3490
func (a *API) ConfirmPromotionLimitTime(infoId int64, outInfoId string) (err error) {
return a.confirmPromotion(PromotionTypeLimitedTime, infoId, outInfoId)
func (a *API) ConfirmPromotionLimitTime(infoId int64, outInfoId, traceId string) (err error) {
return a.confirmPromotion(PromotionTypeLimitedTime, infoId, outInfoId, traceId)
}
// 限时抢活动取消部分商品接口
// https://openo2o.jddj.com/staticnew/widgets/resources.html?groupid=184&apiid=01bd37df882749af91be4b040873ccc6
func (a *API) CancelPromotionSkuLimitTime(infoId int64, outInfoId string, cancelSkus []*PromotionSku, traceId string) (err error) {
return a.cancelPromotionSku(PromotionTypeLimitedTime, infoId, outInfoId, cancelSkus, traceId)
}
// 限时抢整个活动取消接口
// https://opendj.jd.com/staticnew/widgets/resources.html?groupid=184&apiid=97b6678d30624f73bc13cb68987e6a6d
func (a *API) CancelPromotionLimitTime(infoId int64, outInfoId string) (err error) {
return a.cancelPromotion(PromotionTypeLimitedTime, infoId, outInfoId)
func (a *API) CancelPromotionLimitTime(infoId int64, outInfoId, traceId string) (err error) {
return a.cancelPromotion(PromotionTypeLimitedTime, infoId, outInfoId, traceId)
}
func (a *API) createPromotionInfos(promotionType int, name string, beginDate, endDate time.Time, outInfoId, advertising string) (infoId int64, err error) {
// 限时抢活动结束时间调整接口
// https://openo2o.jddj.com/staticnew/widgets/resources.html?groupid=184&apiid=f91035295cd54a9bbd2db9dfc800484c
func (a *API) AdjustPromotionTimeLimitTime(infoId int64, outInfoId string, endDate time.Time, traceId string) (err error) {
return a.adjustPromotionTime(PromotionTypeLimitedTime, infoId, outInfoId, endDate, traceId)
}
// 限时抢商品促销数量调整接口
// https://openo2o.jddj.com/staticnew/widgets/resources.html?groupid=184&apiid=aa878a000dfb4a248634ee755af1f1d3
func (a *API) AdjustPromotionSkuLimitTime(infoId int64, outInfoId string, skus []*PromotionSku, traceId string) (skusResult []*PromotionSku, err error) {
return a.adjustPromotionSku(PromotionTypeLimitedTime, infoId, outInfoId, skus, traceId)
}
func (a *API) createPromotionInfos(promotionType int, name string, beginDate, endDate time.Time, outInfoId, advertising, traceId string) (infoId int64, err error) {
if outInfoId == "" {
outInfoId = fmt.Sprintf("%X", md5.Sum([]byte(name)))
}
jdParams := map[string]interface{}{
"promotionName": name,
"beginDate": utils.Time2Str(beginDate),
"endDate": utils.Time2Str(endDate),
"advertising": advertising,
"promotionType": promotionType,
"timeStamp": utils.GetCurTimeStr(),
KeyOutInfoId: outInfoId,
}
jdParams := getCommonSkuPromotionParams(0, outInfoId, traceId)
jdParams["promotionName"] = name
jdParams["beginDate"] = utils.Time2Str(beginDate)
jdParams["endDate"] = utils.Time2Str(endDate)
jdParams["advertising"] = advertising
jdParams["promotionType"] = promotionType
jdParams["advertising"] = advertising
result, err := a.AccessAPINoPage(getPromotionCmd("createPromotionInfos", promotionType), jdParams, nil, nil, genNoPageResultParser("errorCode", "errorInfos", "data", "0"))
if err == nil {
return utils.MustInterface2Int64(result), nil
@@ -150,35 +173,64 @@ func (a *API) createPromotionInfos(promotionType int, name string, beginDate, en
return 0, err
}
// todo skusResult 返回值没有意义,为了兼容暂时保留
func (a *API) createPromotionSku(promotionType int, infoId int64, outInfoId string, skus []map[string]interface{}) (skusResult []map[string]interface{}, err error) {
jdParams := map[string]interface{}{
"skus": skus,
"timeStamp": utils.GetCurTimeStr(),
}
if infoId != 0 {
jdParams[KeyInfoId] = infoId
} else {
jdParams[KeyOutInfoId] = outInfoId
}
_, err = a.AccessAPINoPage(getPromotionCmd("createPromotionSku", promotionType), jdParams, nil, nil, genNoPageResultParser("errorCode", "data", "", "0"))
return nil, err
func (a *API) createPromotionRules(promotionType int, infoId int64, outInfoId string, limitDevice, limitPin, limitCount, limitDaily int, traceId string) (err error) {
jdParams := getCommonSkuPromotionParams(infoId, outInfoId, traceId)
jdParams["limitDevice"] = limitDevice
jdParams["limitPin"] = limitPin
jdParams["limitCount"] = limitCount
jdParams["limitDaily"] = limitDaily
_, err = a.AccessAPINoPage(getPromotionCmd("createPromotionRules", promotionType), jdParams, nil, nil, genNoPageResultParser("errorCode", "errorInfos", "", "0"))
return err
}
func (a *API) confirmPromotion(promotionType int, infoId int64, outInfoId string) (err error) {
jdParams := map[string]interface{}{
"timeStamp": utils.GetCurTimeStr(),
}
if infoId != 0 {
jdParams[KeyInfoId] = infoId
} else {
jdParams[KeyOutInfoId] = outInfoId
// todo skusResult 返回值没有意义,为了兼容暂时保留
func (a *API) createPromotionSku(promotionType int, infoId int64, outInfoId string, skus []*PromotionSku, traceId string) (skusResult []*PromotionSku, err error) {
jdParams := getCommonSkuPromotionParams(infoId, outInfoId, traceId)
jdParams["skus"] = skus
// todo 当前是在出错时把data中的数据当成错误信息处理的
result, err := a.AccessAPINoPage(getPromotionCmd("createPromotionSku", promotionType), jdParams, nil, nil, genNoPageResultParser("errorCode", "data", "", "0"))
if err == nil && result != nil {
err = utils.Map2StructByJson(result, &skusResult, false)
}
return skusResult, err
}
func (a *API) confirmPromotion(promotionType int, infoId int64, outInfoId, traceId string) (err error) {
jdParams := getCommonSkuPromotionParams(infoId, outInfoId, traceId)
_, err = a.AccessAPINoPage(getPromotionCmd("confirmPromotion", promotionType), jdParams, nil, nil, genNoPageResultParser("errorCode", "errorInfos", "", "0"))
return err
}
func (a *API) cancelPromotion(promotionType int, infoId int64, outInfoId string) (err error) {
func (a *API) cancelPromotionSku(promotionType int, infoId int64, outInfoId string, cancelSkus []*PromotionSku, traceId string) (err error) {
jdParams := getCommonSkuPromotionParams(infoId, outInfoId, traceId)
jdParams["cancelSkus"] = cancelSkus
_, err = a.AccessAPINoPage(getPromotionCmd("cancelPromotionSku", promotionType), jdParams, nil, nil, genNoPageResultParser("errorCode", "errorInfos", "", "0"))
return err
}
func (a *API) cancelPromotion(promotionType int, infoId int64, outInfoId, traceId string) (err error) {
jdParams := getCommonSkuPromotionParams(infoId, outInfoId, traceId)
_, err = a.AccessAPINoPage(getPromotionCmd("cancelPromotion", promotionType), jdParams, nil, nil, genNoPageResultParser("errorCode", "errorInfos", "", "0"))
return err
}
func (a *API) adjustPromotionTime(promotionType int, infoId int64, outInfoId string, endDate time.Time, traceId string) (err error) {
jdParams := getCommonSkuPromotionParams(infoId, outInfoId, traceId)
_, err = a.AccessAPINoPage(getPromotionCmd("adjustPromotionTime", promotionType), jdParams, nil, nil, genNoPageResultParser("errorCode", "errorInfos", "", "0"))
return err
}
func (a *API) adjustPromotionSku(promotionType int, infoId int64, outInfoId string, skus []*PromotionSku, traceId string) (skusResult []*PromotionSku, err error) {
jdParams := getCommonSkuPromotionParams(infoId, outInfoId, traceId)
jdParams["skus"] = skus
result, err := a.AccessAPINoPage(getPromotionCmd("adjustPromotionSku", promotionType), jdParams, nil, nil, genNoPageResultParser("errorCode", "data", "", "0"))
if err == nil && result != nil {
err = utils.Map2StructByJson(result, &skusResult, false)
}
return skusResult, err
}
func getCommonSkuPromotionParams(infoId int64, outInfoId, traceId string) map[string]interface{} {
jdParams := map[string]interface{}{
"timeStamp": utils.GetCurTimeStr(),
}
@@ -187,42 +239,8 @@ func (a *API) cancelPromotion(promotionType int, infoId int64, outInfoId string)
} else {
jdParams[KeyOutInfoId] = outInfoId
}
_, err = a.AccessAPINoPage(getPromotionCmd("cancelPromotion", promotionType), jdParams, nil, nil, genNoPageResultParser("errorCode", "errorInfos", "", "0"))
return err
}
func (a *API) QueryPromotionInfo(promotionInfoId int64) (promotionInfo *PromotionInfo, err error) {
jdParams := map[string]interface{}{
"promotionInfoId": promotionInfoId,
if traceId != "" {
jdParams["traceId"] = traceId
}
result, err := a.AccessAPINoPage("singlePromote/queryPromotionInfo", jdParams, nil, nil, genNoPageResultParser("errorCode", "errorInfos", "data", "0"))
if err == nil {
data := result.(map[string]interface{})
// baseapi.SugarLogger.Debug(utils.Format4Output(data, false))
promotionInfo = &PromotionInfo{
BeginTime: utils.Timestamp2Time(utils.MustInterface2Int64(data["beginTime"].(map[string]interface{})["time"]) / 1000),
EndTime: utils.Timestamp2Time(utils.MustInterface2Int64(data["endTime"].(map[string]interface{})["time"]) / 1000),
PromotionInfoId: utils.MustInterface2Int64(data["promotionInfoId"]),
PromotionState: int(utils.MustInterface2Int64(data["promotionState"])),
PromotionType: int(utils.MustInterface2Int64(data["promotionType"])),
Source: utils.Interface2String(data["source"]),
}
skuResultList := data["skuResultList"].([]interface{})
promotionInfo.SkuResultList = make([]*PromotionSkuResult, len(skuResultList))
for k, v := range skuResultList {
skuResult := v.(map[string]interface{})
promotionInfo.SkuResultList[k] = &PromotionSkuResult{
LimitDaily: int(utils.MustInterface2Int64(skuResult["limitDaily"])),
LimitDevice: int(utils.MustInterface2Int64(skuResult["limitDevice"])),
LimitPin: int(utils.MustInterface2Int64(skuResult["limitPin"])),
PlatformRatio: int(utils.MustInterface2Int64(skuResult["platformRatio"])),
PromotionPrice: int(utils.MustInterface2Int64(skuResult["promotionPrice"])),
SkuId: utils.MustInterface2Int64(skuResult["skuId"]),
StationNo: utils.MustInterface2Int64(skuResult["stationNo"]),
StoreRatio: int(utils.MustInterface2Int64(skuResult["storeRatio"])),
}
}
return promotionInfo, nil
}
return nil, err
return jdParams
}

View File

@@ -6,67 +6,57 @@ import (
)
func TestCreatePromotionSingle(t *testing.T) {
infoId, err := api.CreatePromotionInfosSingle("测试1", time.Now(), time.Now().Add(24*time.Hour), "", "")
infoId, err := api.CreatePromotionInfosSingle("测试1", time.Now(), time.Now().Add(24*time.Hour), "", "", "")
if err != nil {
t.Fatal(err)
}
t.Log(infoId)
err = api.CreatePromotionRules(infoId, "", 1, 1, 1, 1)
err = api.CreatePromotionRulesSingle(infoId, "", 1, 1, 1, 1, "")
if err != nil {
t.Fatal(err)
}
skuInfos, err := api.CreatePromotionSkuSingle(infoId, "", []map[string]interface{}{
{
KeyOutSkuId: "2216",
KeyStationNo: 11682042,
KeyPromotionPrice: 500,
KeyLimitSkuCount: 2,
skuInfos, err := api.CreatePromotionSkuSingle(infoId, "", []*PromotionSku{
&PromotionSku{
OutSkuID: "2216",
StationNo: 11682042,
PromotionPrice: 500,
LimitSkuCount: 2,
},
})
}, "")
if err != nil {
t.Fatal(err)
}
t.Log(skuInfos)
err = api.ConfirmPromotionSingle(infoId, "")
err = api.ConfirmPromotionSingle(infoId, "", "")
if err != nil {
t.Fatal(err)
}
}
func TestCreatePromotionLimitTime(t *testing.T) {
infoId, err := api.CreatePromotionInfosLimitTime("测试1", time.Now(), time.Now().Add(24*time.Hour), "", "")
infoId, err := api.CreatePromotionInfosLimitTime("测试1", time.Now(), time.Now().Add(24*time.Hour), "", "", "")
if err != nil {
t.Fatal(err)
}
t.Log(infoId)
err = api.CreatePromotionRules(infoId, "", 1, 1, 5, 1)
err = api.CreatePromotionRulesLimitTime(infoId, "", 1, 1, 5, 1, "")
if err != nil {
t.Fatal(err)
}
skuInfos, err := api.CreatePromotionSkuLimitTime(infoId, "", []map[string]interface{}{
{
KeyOutSkuId: "2216",
KeyStationNo: 11682042,
KeyPromotionPrice: 300,
KeyLimitSkuCount: 2,
skuInfos, err := api.CreatePromotionSkuLimitTime(infoId, "", []*PromotionSku{
&PromotionSku{
OutSkuID: "2216",
StationNo: 11682042,
PromotionPrice: 300,
LimitSkuCount: 2,
},
})
}, "")
if err != nil {
t.Fatal(err)
}
t.Log(skuInfos)
err = api.ConfirmPromotionLimitTime(infoId, "")
err = api.ConfirmPromotionLimitTime(infoId, "", "")
if err != nil {
t.Fatal(err)
}
}
func TestQueryPromotionInfo(t *testing.T) {
result, err := api.QueryPromotionInfo(14885272)
if err != nil {
t.Fatal(err)
}
if len(result.SkuResultList) == 0 {
t.Fatal("should have SkuResultList")
}
}

View File

@@ -80,7 +80,7 @@ const (
)
const (
MaxSkuNameLen = 45 // skuname最长字符数
MaxSkuNameCharCount = 45 // skuname最长字符数
SaleAttrIDBase = 1001
SaleAttrValueIDBase = 10
)
@@ -399,13 +399,7 @@ func (a *API) QueryKeyWordDicInfo(pageNo, pageSize int, keyValue string) (values
// 商家商品状态同步接口
// https://opendj.jd.com/staticnew/widgets/resources.html?groupid=180&apiid=5e29d6c9317847e58b8cbcc70702fd52
func (a *API) SyncProduct(storeId, skuId string) (retVal bool, err error) {
result, err := a.AccessAPINoPage("search/syncProduct", utils.Params2Map(KeyStoreId, storeId, KeySkuId, skuId), nil, nil, func(data map[string]interface{}) (interface{}, error) {
status := utils.MustInterface2Int64(data["status"])
if status == 200 {
return data["synchronized"].(bool), nil
}
return nil, utils.NewErrorIntCode(data["message"].(string), int(status))
})
result, err := a.AccessAPINoPage("search/syncProduct", utils.Params2Map(KeyStoreId, storeId, KeySkuId, skuId), nil, nil, genNoPageResultParser("status", "message", "synchronized", "200"))
if err == nil {
return result.(bool), nil
}

View File

@@ -58,12 +58,12 @@ func TestBatchUpdateOutSkuId(t *testing.T) {
func TestQuerySkuInfos(t *testing.T) {
pageSize := 20
result, totalCount, err := api.QuerySkuInfos("", 0, 0, pageSize, true)
result, totalCount, err := api.QuerySkuInfos("一个高级商品", 0, 0, pageSize, true)
if err != nil {
t.Fatal(err)
}
if len(result) != pageSize || totalCount == 0 {
baseapi.SugarLogger.Debug(result)
baseapi.SugarLogger.Debug(utils.Format4Output(result, false))
t.Fatalf("QuerySkuInfos result size is not same as requested:%d", pageSize)
}
}
@@ -95,32 +95,32 @@ func TestQueryKeyWordDicInfo(t *testing.T) {
}
func TestSyncProduct(t *testing.T) {
result, err := api.SyncProduct("11732425", "2015717812")
result, err := api.SyncProduct(mustExistStoreID, "2022250244")
if err != nil {
t.Fatal(err)
}
baseapi.SugarLogger.Debug(result)
result, err = api.SyncProduct("wrongstoreid", "2015717812")
result, err = api.SyncProduct("wrongstoreid", "2022250244")
if err == nil {
t.Fatal("SyncProduct should return error")
}
result, err = api.SyncProduct("11732425", "wrongskuid")
result, err = api.SyncProduct(mustExistStoreID, "wrongskuid")
if err == nil {
t.Fatal("SyncProduct should return error")
}
}
func TestGetProductStatust(t *testing.T) {
result, err := api.GetProductStatus("11732425", "2015717812")
result, err := api.GetProductStatus(mustExistStoreID, "2022250244")
if err != nil || result == nil {
t.Fatal(err)
}
// baseapi.SugarLogger.Debug(result)
result, err = api.GetProductStatus("wrongstoreid", "2015717812")
result, err = api.GetProductStatus("wrongstoreid", "2022250244")
if err == nil {
t.Fatal("GetProductStatus should return error")
}
result, err = api.GetProductStatus("11732425", "wrongskuid")
result, err = api.GetProductStatus(mustExistStoreID, "wrongskuid")
if err == nil {
t.Fatal("GetProductStatus should return error")
}

View File

@@ -35,6 +35,23 @@ type CreateShopResult struct {
StationNo string `json:"stationNo"`
}
type CityInfo struct {
AreaCode int `json:"areaCode"`
AreaLevel int `json:"areaLevel"`
AreaName string `json:"areaName"`
ParentAreaID int `json:"parentAreaId"`
TencentAddressCode int `json:"tencentAddressCode"`
Yn int `json:"yn"`
}
func (a *API) GetAllCities() (cities []*CityInfo, err error) {
result, err := a.AccessAPINoPage("address/allcities", nil, nil, nil, genNoPageResultParser("code", "msg", "result", "0"))
if err == nil {
err = utils.Map2StructByJson(result, &cities, false)
}
return cities, err
}
// 获取门店编码列表接口
// https://opendj.jd.com/staticnew/widgets/resources.html?groupid=194&apiid=138426aa19b54c48ae8464af1ca3b681
func (a *API) GetStationsByVenderId() ([]string, error) {
@@ -125,7 +142,7 @@ func (a *API) OrgReplyComment(orderID int64, storeID, content, replayPin string)
"orderId": orderID,
"storeId": storeID,
"content": content,
"replyPin": replayPin,
"replyPin": utils.GetAPIOperator(replayPin),
}
_, err := a.AccessAPINoPage("commentOutApi/orgReplyComment", jdParams, nil, nil, genNoPageResultParser("code", "msg", "result", "200"))
return err

View File

@@ -4,6 +4,7 @@ import (
"fmt"
"net/http"
"net/url"
"strings"
"git.rosy.net.cn/baseapi"
"git.rosy.net.cn/baseapi/platformapi"
@@ -11,8 +12,9 @@ import (
)
const (
accessStorePageCookieName = "shop.o2o.jd.com1"
getStoreURL = "https://daojia.jd.com"
getStoreURL = "https://daojia.jd.com"
accessStorePageCookieName = "shop.o2o.jd.com1"
accessStorePageCookieName2 = "lsp-store1.jddj.com"
)
type SkuPageImg struct {
@@ -21,6 +23,48 @@ type SkuPageImg struct {
Small string `json:"small"`
}
type CorporationInfo struct {
Scope string `json:"scope"`
OperName string `json:"oper_name"`
Status string `json:"status"`
BelongOrg string `json:"belong_org"`
CreditNo string `json:"credit_no"`
RegNo string `json:"reg_no"`
ID string `json:"id"`
OrgNo string `json:"org_no"`
EconKind string `json:"econ_kind"`
EndDate string `json:"end_date"`
TermEnd string `json:"term_end"`
NeedID bool `json:"needID"`
Address string `json:"address"`
Partners []struct {
IdentifyType string `json:"identify_type"`
ShouldCapiItems []interface{} `json:"should_capi_items"`
StockType string `json:"stock_type"`
IdentifyNo string `json:"identify_no"`
RealCapiItems []interface{} `json:"real_capi_items"`
Name string `json:"name"`
} `json:"partners"`
Name string `json:"name"`
Province string `json:"province"`
TermStart string `json:"term_start"`
AbnormalItems []interface{} `json:"abnormal_items"`
CheckDate string `json:"check_date"`
RegistCapi string `json:"regist_capi"`
StartDate string `json:"start_date"`
Changerecords []struct {
BeforeContent string `json:"before_content"`
ChangeDate string `json:"change_date"`
ChangeItem string `json:"change_item"`
AfterContent string `json:"after_content"`
} `json:"changerecords"`
Branches []interface{} `json:"branches"`
Employees []struct {
JobTitle string `json:"job_title"`
Name string `json:"name"`
} `json:"employees"`
}
func (a *API) SetStoreCookie(storeCookie string) {
a.locker.Lock()
defer a.locker.Unlock()
@@ -33,14 +77,21 @@ func (a *API) GetStoreCookie() string {
return a.storeCookie
}
func (a *API) AccessStorePage(fullURL string) (retVal map[string]interface{}, err error) {
func (a *API) AccessStorePage(fullURL string, formData map[string]interface{}) (retVal map[string]interface{}, err error) {
storeCookie := a.GetStoreCookie()
if storeCookie == "" {
return nil, fmt.Errorf("需要设置Store Cookie才能使用此方法")
}
err = platformapi.AccessPlatformAPIWithRetry(a.client,
func() *http.Request {
request, _ := http.NewRequest(http.MethodGet, fullURL, nil)
var request *http.Request
if formData == nil {
request, _ = http.NewRequest(http.MethodGet, fullURL, nil)
} else {
request, _ = http.NewRequest(http.MethodPost, fullURL, strings.NewReader(utils.Map2URLValues(formData).Encode()))
request.Header.Set("charset", "UTF-8")
request.Header.Set("Content-Type", "application/x-www-form-urlencoded")
}
if err != nil {
return nil
}
@@ -48,10 +99,14 @@ func (a *API) AccessStorePage(fullURL string) (retVal map[string]interface{}, er
Name: accessStorePageCookieName,
Value: storeCookie,
})
request.AddCookie(&http.Cookie{
Name: accessStorePageCookieName2,
Value: storeCookie,
})
return request
},
a.config,
func(jsonResult1 map[string]interface{}) (errLevel string, err error) {
func(response *http.Response, jsonResult1 map[string]interface{}) (errLevel string, err error) {
retVal = jsonResult1
code := jsonResult1["code"].(string)
if code == ResponseCodeSuccess {
@@ -84,7 +139,7 @@ func (a *API) GetStoreOrderInfo(orderId, stationNo string) (storeOrderInfo map[s
if stationNo != "" {
urlStr += "&stationNo=" + stationNo
}
retVal, err := a.AccessStorePage(urlStr)
retVal, err := a.AccessStorePage(urlStr, nil)
// baseapi.SugarLogger.Debug(utils.Format4Output(retVal, false))
if err == nil {
newOrderinfoMains := retVal["newOrderinfoMains"].(map[string]interface{})
@@ -102,7 +157,7 @@ func (a *API) GetStoreOrderInfoList(fromTime, toTime string) (storeOrderList []m
pageNo := 1
urlTemplate := "http://store.jddj.com/order/newManager/tabQuery/all?o2oOrderType=10000&pageNo=%d&pageSize=%d&orderBy=&desc=true&startTimeQuery=%s&endTimeQuery=%s&stationNo="
for {
retVal, err := a.AccessStorePage(fmt.Sprintf(urlTemplate, pageNo, pageSize, url.QueryEscape(fromTime), url.QueryEscape(toTime)))
retVal, err := a.AccessStorePage(fmt.Sprintf(urlTemplate, pageNo, pageSize, url.QueryEscape(fromTime), url.QueryEscape(toTime)), nil)
// baseapi.SugarLogger.Debug(utils.Format4Output(retVal, false))
if err == nil {
newOrderinfoMains := retVal["newOrderinfoMains"].(map[string]interface{})
@@ -124,10 +179,7 @@ func (a *API) GetSkuPageInfo(skuId int64) (skuPageInfo map[string]interface{}, e
"skuId": utils.Int64ToStr(skuId),
"storeId": "0",
}
skuPageInfo, err = a.AccessStorePage(fmt.Sprintf("https://daojia.jd.com/client?platCode=H5&functionId=product/detailV6_0&body=%s", utils.Format4Output(skuIDMap, true)))
if err == nil {
baseapi.SugarLogger.Debug(utils.Format4Output(skuPageInfo, false))
}
skuPageInfo, err = a.AccessStorePage(fmt.Sprintf("https://daojia.jd.com/client?platCode=H5&functionId=product/detailV6_0&body=%s", utils.Format4Output(skuIDMap, true)), nil)
return skuPageInfo, err
}
@@ -140,34 +192,22 @@ func (a *API) GetSkuPageImageInfo(skuId int64) (imgList []*SkuPageImg, err error
}
func (a *API) GetStoreInfo(storeId string) (storeInfo map[string]interface{}, err error) {
retVal, err := a.AccessStorePage2(fmt.Sprintf("client?functionId=store/storeDetailV220&body={\"storeId\":\"%s\"}&appVersion=6.1.0", storeId))
return retVal, err
}
func (a *API) AccessStorePage2(subURL string) (retVal map[string]interface{}, err error) {
err = platformapi.AccessPlatformAPIWithRetry(a.client,
func() *http.Request {
fullURL := utils.GenerateGetURL(getStoreURL, subURL, nil)
request, _ := http.NewRequest(http.MethodGet, fullURL, nil)
if err != nil {
return nil
}
return request
},
a.config,
func(jsonResult1 map[string]interface{}) (errLevel string, err error) {
code := jsonResult1["code"].(string)
if code == ResponseCodeSuccess && jsonResult1["result"] != nil {
retVal = jsonResult1["result"].(map[string]interface{})
return platformapi.ErrLevelSuccess, nil
}
newErr := utils.NewErrorCode(jsonResult1["msg"].(string), code)
return platformapi.ErrLevelCodeIsNotOK, newErr
})
retVal, err := a.AccessStorePage(fmt.Sprintf("https://daojia.jd.com/client?functionId=store/storeDetailV220&body={\"storeId\":\"%s\"}&appVersion=6.1.0", storeId), nil)
return retVal, err
}
func (a *API) GetStoreList(lng string, lat string) (retVal map[string]interface{}, err error) {
retVal, err = a.AccessStorePage2(fmt.Sprintf("client?platCode=h5&appVersion=6.5.0&functionId=zone/recommendStoreList&body={\"channelId\":\"3997\",\"currentPage\":1,\"pageSize\":999,\"coordType\":\"2\",\"platform\":\"1\"}&signKey=b63f63fa9e27123b84a0c80ef5cd210d&lng=%s&lat=%s", lng, lat))
retVal, err = a.AccessStorePage(fmt.Sprintf("https://daojia.jd.com/client?platCode=h5&appVersion=6.5.0&functionId=zone/recommendStoreList&body={\"channelId\":\"3997\",\"currentPage\":1,\"pageSize\":999,\"coordType\":\"2\",\"platform\":\"1\"}&signKey=b63f63fa9e27123b84a0c80ef5cd210d&lng=%s&lat=%s", lng, lat), nil)
return retVal, err
}
func (a *API) GetCorporationInfo(stationNo, qualifyNumber string) (corporatonInfo *CorporationInfo, err error) {
result, err := a.AccessStorePage("https://sta-store.jddj.com/store/requestQualify.o2o", map[string]interface{}{
"stationNo": stationNo,
"qualifyNumber": qualifyNumber,
})
if err == nil {
err = utils.Map2StructByJson(result, &corporatonInfo, false)
}
return corporatonInfo, err
}

View File

@@ -54,3 +54,27 @@ func TestGetSkuPageImageInfo(t *testing.T) {
}
baseapi.SugarLogger.Debug(utils.Format4Output(imgList, false))
}
func TestGetCorporationInfo(t *testing.T) {
imgList, err := api.GetCorporationInfo("", "915101003431062533")
if err != nil {
t.Fatal(err)
}
baseapi.SugarLogger.Debug(utils.Format4Output(imgList, false))
}
func TestGetStoreList(t *testing.T) {
result, err := api.GetStoreList("104.057218", "30.6949")
if err != nil {
t.Fatal(err)
}
t.Log(utils.Format4Output(result, false))
}
func TestGetStoreInfo(t *testing.T) {
result, err := api.GetStoreInfo("11750116")
if err != nil {
t.Fatal(err)
}
t.Log(utils.Format4Output(result, false))
}

View File

@@ -41,6 +41,38 @@ type SkuIdEntity struct {
OutSkuId string `json:"outSkuId"`
}
type StorePriceInfo struct {
MarketPrice int64 `json:"marketPrice"`
Pin string `json:"pin"`
Price int64 `json:"price"`
PromoteVipPrice int64 `json:"promoteVipPrice"`
SkuID int64 `json:"skuId"`
StationNo string `json:"stationNo"`
VenderID string `json:"venderId"`
VipPrice int64 `json:"vipPrice"`
}
type QueryStockResponse struct {
SkuID int64 `json:"skuId"`
StationNo string `json:"stationNo"`
UsableQty int `json:"usableQty"`
LockQty int `json:"lockQty"`
OrderQty int `json:"orderQty"`
Vendibility int `json:"vendibility"`
}
type UpdateVendibilityResponse struct {
Code int `json:"code"`
CurrentQty int `json:"currentQty"`
LockQty int `json:"lockQty"`
Msg string `json:"msg"`
OrderQty int `json:"orderQty"`
OutSkuID string `json:"outSkuId"`
SkuID int64 `json:"skuId"`
UsableQty int `json:"usableQty"`
Vendibility int `json:"vendibility"`
}
// 传入为数组的最多一次为50个
// 有好些功能有两个类似的函数一个为到家ID一个为商家ID建议都只用商家ID的那个因为
// 1这类函数一般可以批量操作
@@ -85,16 +117,16 @@ func (a *API) UpdateStationPrice(skuId int64, stationNo string, price int) (stri
// 根据到家商品编码和到家门店编码批量查询商品门店价格信息接口
// https://opendj.jd.com/staticnew/widgets/resources.html?groupid=205&apiid=21ccd5a00d3a4582b4c9a8ef0ae238fc
func (a *API) GetStationInfoList(stationNo string, skuIds []int64) ([]map[string]interface{}, error) {
func (a *API) GetStationInfoList(stationNo string, skuIds []int64) (priceInfo []*StorePriceInfo, err error) {
jdParams := map[string]interface{}{
"skuIds": skuIds,
"stationNo": stationNo,
}
result, err := a.AccessAPINoPage("price/getStationInfoList", jdParams, nil, nil, nil)
result, err := a.AccessAPINoPage("price/getStationInfoList", jdParams, nil, nil, genNoPageResultParser("code", "detail", "result", "0"))
if err == nil && result != nil {
return utils.Slice2MapSlice(result.([]interface{})), nil
err = utils.Map2StructByJson(result, &priceInfo, false)
}
return nil, err
return priceInfo, err
}
// 根据商家商品编码和商家门店编码批量修改现货库存接口
@@ -105,7 +137,7 @@ func (a *API) BatchUpdateCurrentQtys(outStationNo, stationNo string, skuStockLis
}
jdParams := map[string]interface{}{
"skuStockList": skuStockList,
"userPin": userPin,
"userPin": utils.GetAPIOperator(userPin),
}
if outStationNo != "" {
jdParams["outStationNo"] = outStationNo
@@ -157,7 +189,7 @@ func (a *API) BatchUpdateVendibility(outStationNo, stationNo string, stockVendib
}
jdParams := map[string]interface{}{
"stockVendibilityList": stockVendibilityList,
"userPin": userPin,
"userPin": utils.GetAPIOperator(userPin),
}
if outStationNo != "" {
jdParams["outStationNo"] = outStationNo
@@ -174,28 +206,28 @@ func (a *API) BatchUpdateVendibility(outStationNo, stationNo string, stockVendib
// 根据到家商品编码和门店编码批量查询商品库存及可售状态信息接口
// https://opendj.jd.com/staticnew/widgets/resources.html?groupid=200&apiid=bc6ad75e8fd34580856e06b5eb149aad
// 尽量不用这个接口,用下面那个
func (a *API) QueryOpenUseable(listBaseStockCenterRequest []*BaseStockCenterRequest) ([]map[string]interface{}, error) {
func (a *API) QueryOpenUseable(listBaseStockCenterRequest []*BaseStockCenterRequest) (stockResponse []*QueryStockResponse, err error) {
jdParams := map[string]interface{}{
"listBaseStockCenterRequest": listBaseStockCenterRequest,
}
result, err := a.AccessAPINoPage("stock/queryOpenUseable", jdParams, nil, nil, genNoPageResultParser("retCode", "retMsg", "data", "0"))
if err == nil && result != nil {
return utils.Slice2MapSlice(result.([]interface{})), nil
err = utils.Map2StructByJson(result, &stockResponse, false)
}
return nil, err
return stockResponse, err
}
// 根据商家商品编码和门店编码批量查询商品库存及可售状态信息接口
// https://opendj.jd.com/staticnew/widgets/resources.html?groupid=200&apiid=ba70316bb84f425f8c088d3c19b2570d
func (a *API) QueryStockCenter(outStationNo string, skuIds []*SkuIdEntity, userPin string) ([]map[string]interface{}, error) {
func (a *API) QueryStockCenter(outStationNo string, skuIds []*SkuIdEntity, userPin string) (vendibilityResponse []*UpdateVendibilityResponse, err error) {
jdParams := map[string]interface{}{
"outStationNo": outStationNo,
"skuIds": skuIds,
"userPin": userPin,
"userPin": utils.GetAPIOperator(userPin),
}
result, err := a.AccessAPINoPage("stock/queryStockCenter", jdParams, nil, nil, genNoPageResultParser("retCode", "retMsg", "data", "0"))
if err == nil && result != nil {
return utils.Slice2MapSlice(result.([]interface{})), nil
err = utils.Map2StructByJson(result, &vendibilityResponse, false)
}
return nil, err
return vendibilityResponse, err
}

View File

@@ -8,8 +8,8 @@ import (
)
const (
mustExistSkuID = 2017194325
mustExistSkuJXID = "21206"
mustExistSkuID = 2023747677
mustExistSkuJXID = "5246"
)
func TestGetStationInfoList(t *testing.T) {
@@ -17,9 +17,7 @@ func TestGetStationInfoList(t *testing.T) {
if err != nil {
t.Fatal(err)
}
for _, v := range result {
baseapi.SugarLogger.Debug(v)
}
t.Log(utils.Format4Output(result, false))
}
func TestQueryOpenUseable(t *testing.T) {
@@ -32,9 +30,7 @@ func TestQueryOpenUseable(t *testing.T) {
if err != nil {
t.Fatal(err)
}
for _, v := range result {
baseapi.SugarLogger.Debug(v)
}
t.Log(utils.Format4Output(result, false))
}
func TestQueryStockCenter(t *testing.T) {
@@ -46,9 +42,7 @@ func TestQueryStockCenter(t *testing.T) {
if err != nil {
t.Fatal(err)
}
for _, v := range result {
baseapi.SugarLogger.Debug(v)
}
t.Log(utils.Format4Output(result, false))
}
func TestBatchUpdateVendibility(t *testing.T) {

View File

@@ -9,10 +9,18 @@ import (
)
const (
mustExistStoreID = "11738324"
mustExistStoreJXID = "100285"
mustExistStoreID = "11053496"
mustExistStoreJXID = "2"
)
func TestGetAllCities(t *testing.T) {
result, err := api.GetAllCities()
if err != nil {
t.Fatal(err)
}
t.Log(utils.Format4Output(result, false))
}
func TestGetStationsByVenderId(t *testing.T) {
result, err := api.GetStationsByVenderId()
if err != nil {