Files
baseapi/platform/mtpsapi/mtpsapi.go
gazebo 851b2c1eeb - dadaapi added.
- refactor.
2018-06-21 14:23:01 +08:00

292 lines
8.1 KiB
Go

package mtpsapi
import (
"crypto/sha1"
"fmt"
"net/http"
"net/url"
"sort"
"strconv"
"strings"
"time"
"github.com/fatih/structs"
"git.rosy.net.cn/baseapi"
"git.rosy.net.cn/baseapi/platform/common"
"git.rosy.net.cn/baseapi/utils"
)
const (
clientTimeout = time.Second * 10
sleepSecondWhenLimited = 6 * time.Second
maxRetryCountWhenNetworkException = 3
maxRetryCountWhenReachLimited = 10
)
const (
mtpsAPIURL = "https://peisongopen.meituan.com/api"
signKey = "sign"
)
const (
OrderStatusWaitingForSchedule = 0
OrderStatusAccepted = 20
OrderStatusPickedUp = 30
OrderStatusDeliverred = 50
OrderStatusCanceled = 99
)
const (
DSCRapid = 4011
DSCIntime = 4012
DSCTogether = 4013
)
const (
PickupTypeClientSendToStation = 1
PickupTypeMtPick = 2
)
const (
OrderTypeASAP = 0
OrderTypeBook = 1
)
const (
CoordinateTypeMars = 0
CoordinateTypeBaidu = 1
)
// 错误码
const (
ResponseCodeSuccess = 0
)
// 取消原因
const (
CancelReasonClientActive = 101
CancelReasonClientChangeTimeOrAddress = 102
CancelReasonGoodRelated = 103
CancelReasonMerchantOther = 199
CancelReasonMtpsAttitude = 201
CancelReasonRidderSendNotIntime = 202
CancelReasonRideerGetGoodNotIntime = 203
CancelReasonRideerMtpsOther = 299
CancelReasonRideerOther = 399
)
type MtpsOrderInfoCommon struct {
DeliveryId int64
MtPeisongId string
OrderId string
CourierName string
CourierPhone string
}
type MtpsOrderInfo struct {
MtpsOrderInfoCommon
Status int
OperateTime int
CancelReasonId int
CancelReason string
}
type MtpsOrderResponse struct {
MtPeisongId string `json:"mt_peisong_id`
DeliveryId int64 `json:"delivery_id`
OrderId string `json:"order_id`
}
type MTPSResult struct {
Code int `json:"code"`
Message string `json:"message"`
Data map[string]interface{} `json:"data"`
}
type MtpsCreateOrderByShopInfo struct {
DeliveryId int64 `json:"delivery_id"`
OrderId string `json:"order_id"`
ShopId string `json:"shop_id"`
DeliveryServiceCode int `json:"delivery_service_code"`
ReceiverName string `json:"receiver_name"`
ReceiverAddress string `json:"receiver_address"`
ReceiverPhone string `json:"receiver_phone"`
ReceiverLng int `json:"receiver_lng"`
ReceiverLat int `json:"receiver_lat"`
CoordinateType int `json:"coordinate_type"`
GoodsValue float64 `json:"goods_value"`
GoodsWeight float64 `json:"goods_weight"`
ExpectedDeliveryTime int64 `json:"expected_delivery_time"`
OrderType int `json:"order_type"`
}
type MTPSAPI struct {
appKey string
secret string
client *http.Client
}
func NewMTPSAPI(appKey, secret string) *MTPSAPI {
api := &MTPSAPI{
appKey: appKey,
secret: secret,
client: &http.Client{Timeout: clientTimeout},
}
return api
}
func (m *MTPSAPI) signParams(params url.Values) string {
keys := make([]string, 0)
for k := range params {
if k != signKey {
keys = append(keys, k)
}
}
sort.Strings(keys)
finalStr := m.secret
for _, key := range keys {
valStr := strings.Join(params[key], "")
if valStr != "" {
finalStr += key + valStr
}
}
// baseapi.SugarLogger.Debug(finalStr)
return fmt.Sprintf("%x", sha1.Sum([]byte(finalStr)))
}
func (m *MTPSAPI) AccessMTPS(action string, params map[string]interface{}) (retVal *MTPSResult, err error) {
if params == nil {
panic("params is nil!")
}
params2 := make(url.Values)
for k, v := range params {
params2[k] = []string{fmt.Sprint(v)}
}
params2["appkey"] = []string{m.appKey}
params2["timestamp"] = []string{utils.Int64ToStr(utils.GetCurTimestamp())}
params2["version"] = []string{"1.0"}
params2[signKey] = []string{m.signParams(params2)}
// baseapi.SugarLogger.Debug(params2.Encode())
request, _ := http.NewRequest("POST", mtpsAPIURL+"/"+action, strings.NewReader(params2.Encode()))
request.Header.Set("Content-Type", "application/x-www-form-urlencoded")
apiAccess := &common.AccessPlatformAPIWithRetryParams{
MaxExceedLimitRetryCount: maxRetryCountWhenReachLimited,
MaxRecoverableRetryCount: maxRetryCountWhenNetworkException,
SleepSecondWhenExceedLimit: sleepSecondWhenLimited,
Client: m.client,
Request: request,
}
err = common.AccessPlatformAPIWithRetry(apiAccess, func(response *http.Response) (result string, err error) {
jsonResult1, err := utils.HttpResponse2Json(response)
if err != nil {
baseapi.SugarLogger.Warnf("HttpResponse2Json return:%v", err)
return common.PAErrorLevelGeneralFail, err
}
code := int(utils.MustInterface2Int64(jsonResult1["code"]))
retVal = &MTPSResult{
Code: code,
}
if code == ResponseCodeSuccess {
if innerData, ok := jsonResult1["data"]; ok {
retVal.Data, _ = innerData.(map[string]interface{})
}
return common.PAErrorLevelSuccess, nil
}
baseapi.SugarLogger.Debug(jsonResult1)
retVal.Message = jsonResult1["message"].(string)
return common.PAErrorLevelGeneralFail, utils.NewErrorIntCode(retVal.Message, code)
})
return retVal, err
}
func (m *MTPSAPI) result2OrderResponse(result *MTPSResult) (order *MtpsOrderResponse) {
order = new(MtpsOrderResponse)
order.MtPeisongId = result.Data["mt_peisong_id"].(string)
order.DeliveryId = utils.MustInterface2Int64(result.Data["delivery_id"])
order.OrderId = result.Data["order_id"].(string)
return order
}
func (m *MTPSAPI) CreateOrderByShop(basicParams *MtpsCreateOrderByShopInfo, addParams map[string]interface{}) (order *MtpsOrderResponse, err error) {
params := structs.Map(basicParams)
params["goods_value"] = strconv.FormatFloat(basicParams.GoodsValue, 'f', 2, 64)
params["goods_weight"] = strconv.FormatFloat(basicParams.GoodsWeight, 'f', 2, 64)
allParams := utils.MergeMaps(params, addParams)
if params["order_type"] != utils.Int2Str(OrderTypeBook) {
delete(params, "expected_delivery_time")
}
if result, err := m.AccessMTPS("order/createByShop", allParams); err != nil {
baseapi.SugarLogger.Debugf("result:%v", result)
return nil, utils.NewErrorIntCode(err.Error(), result.Code)
} else {
return m.result2OrderResponse(result), nil
}
}
func (m *MTPSAPI) QueryOrderStatus(deliveryId int64, mtPeiSongId string) (retVal map[string]interface{}, err error) {
params := map[string]interface{}{
"delivery_id": deliveryId,
"mt_peisong_id": mtPeiSongId,
}
if result, err := m.AccessMTPS("order/status/query", params); err != nil {
return nil, err
} else {
return result.Data, nil
}
}
func (m *MTPSAPI) CancelOrder(deliveryId int64, mtPeiSongId string, cancelReasonId int, cancelReason string) (result *MtpsOrderResponse, err error) {
params := map[string]interface{}{
"delivery_id": deliveryId,
"mt_peisong_id": mtPeiSongId,
"cancel_reason_id": cancelReasonId,
"cancel_reason": cancelReason,
}
if result, err := m.AccessMTPS("order/delete", params); err != nil {
baseapi.SugarLogger.Debugf("result:%v", result)
return nil, err
} else {
return m.result2OrderResponse(result), nil
}
}
func (m *MTPSAPI) simulateOrderBehavior(action string, deliveryId int64, mtPeiSongId string) (err error) {
params := map[string]interface{}{
"delivery_id": deliveryId,
"mt_peisong_id": mtPeiSongId,
}
_, err = m.AccessMTPS("test/order/"+action, params)
return err
}
func (m *MTPSAPI) SimulateArrange(deliveryId int64, mtPeiSongId string) (err error) {
return m.simulateOrderBehavior("arrange", deliveryId, mtPeiSongId)
}
func (m *MTPSAPI) SimulatePickup(deliveryId int64, mtPeiSongId string) (err error) {
return m.simulateOrderBehavior("pickup", deliveryId, mtPeiSongId)
}
func (m *MTPSAPI) SimulateDeliver(deliveryId int64, mtPeiSongId string) (err error) {
return m.simulateOrderBehavior("deliver", deliveryId, mtPeiSongId)
}
func (m *MTPSAPI) SimulateRearrange(deliveryId int64, mtPeiSongId string) (err error) {
return m.simulateOrderBehavior("rearrange", deliveryId, mtPeiSongId)
}
func (m *MTPSAPI) SimulateReportException(deliveryId int64, mtPeiSongId string) (err error) {
return m.simulateOrderBehavior("reportException", deliveryId, mtPeiSongId)
}