回滚美团外卖
This commit is contained in:
@@ -16,10 +16,27 @@ const (
|
|||||||
)
|
)
|
||||||
|
|
||||||
//todo 返回参数没做玩
|
//todo 返回参数没做玩
|
||||||
|
//type TokenInfo struct {
|
||||||
|
// AccessToken string `json:"access_token"`
|
||||||
|
// AppID string `json:"app_id"`
|
||||||
|
// ExpireTime int64 `json:"expire_time"`
|
||||||
|
//}
|
||||||
|
|
||||||
|
// 获取token
|
||||||
type TokenInfo struct {
|
type TokenInfo struct {
|
||||||
AccessToken string `json:"access_token"`
|
Sign string `json:"sign"` //返回值签名,详见开放平台侧返回值签名算法
|
||||||
AppID string `json:"app_id"`
|
Code string `json:"code"` //错误码,详见开放平台侧错误码映射表
|
||||||
ExpireTime int64 `json:"expire_time"`
|
Msg string `json:"msg"` //错误信息
|
||||||
|
BusinessData string `json:"business_data"` // string
|
||||||
|
}
|
||||||
|
|
||||||
|
type BusinessData struct {
|
||||||
|
AppID string `json:"app_id"` //应用id
|
||||||
|
MerchantID string `json:"merchant_id"` //商户id
|
||||||
|
AccessToken string `json:"access_token"` //凭证token
|
||||||
|
RefreshToken string `json:"refresh_token"` //刷新token
|
||||||
|
ExpireIn string `json:"expire_in"` //access_token剩余有效时间,单位:秒,默认有效期是一年
|
||||||
|
ReExpireIn string `json:"re_expire_in"` //refresh_token剩余有效时间
|
||||||
}
|
}
|
||||||
|
|
||||||
// 注册请求api
|
// 注册请求api
|
||||||
@@ -32,14 +49,79 @@ type API struct {
|
|||||||
timestamp int64 `json:"timestamp"`
|
timestamp int64 `json:"timestamp"`
|
||||||
accessToken string `json:"access_token"`
|
accessToken string `json:"access_token"`
|
||||||
appSecret string `json:"app_secret"`
|
appSecret string `json:"app_secret"`
|
||||||
|
version string `json:"version"`
|
||||||
locker sync.RWMutex
|
locker sync.RWMutex
|
||||||
client *http.Client
|
client *http.Client
|
||||||
config *platformapi.APIConfig
|
config *platformapi.APIConfig
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//<------------------------------------------------------------->
|
||||||
|
// 请求基础结构体
|
||||||
|
type BaseInfo struct {
|
||||||
|
AccessToken string `json:"access_token"` //凭证token
|
||||||
|
Signature string `json:"signature"`
|
||||||
|
MerchantID string `json:"merchant_id"` //商户id
|
||||||
|
Version string `json:"version"` // 版本固定1.0
|
||||||
|
AppID string `json:"app_id"` //应用id
|
||||||
|
Timestamp int64 `json:"timestamp"` // 当前时间戳
|
||||||
|
}
|
||||||
|
|
||||||
|
//#region 获取蜂鸟门店信息
|
||||||
|
|
||||||
|
// 获取单个门店查询
|
||||||
|
type GetOneStoreParam struct {
|
||||||
|
BaseInfo
|
||||||
|
BusinessData string `json:"business_data"` // 门店基础数据
|
||||||
|
}
|
||||||
|
|
||||||
|
// 获取单个门店基础参数
|
||||||
|
type GetOneStore struct {
|
||||||
|
MerchantID string `json:"merchant_id"` // 商户id
|
||||||
|
OutShopCode string `json:"out_shop_code"` // 外部门店编码
|
||||||
|
}
|
||||||
|
|
||||||
|
// 获取门店返回值信息
|
||||||
|
type GetStoreResp struct {
|
||||||
|
TokenInfo
|
||||||
|
}
|
||||||
|
|
||||||
|
type GetOneStoreRespData struct {
|
||||||
|
Address string `json:"address"` // 门店地址
|
||||||
|
BranchName string `json:"branch_name"` // 门店分店名
|
||||||
|
CategoryID int `json:"category_id"` // 门店类目
|
||||||
|
ChainStoreID int `json:"chain_store_id"` // 蜂鸟门店id,创建接口返回的id
|
||||||
|
ChainstoreType int `json:"chainstore_type"` // 门店类型 1-正式门店;2-测试门店
|
||||||
|
ChainstoreTypeDesc string `json:"chainstore_type_desc"` // 门店类型描述
|
||||||
|
ContactPhone string `json:"contact_phone"` // 门店联系方式
|
||||||
|
CreditCode string `json:"credit_code"` // 统一社会信用代码
|
||||||
|
Latitude float64 `json:"latitude"` // 门店纬度[0,90]
|
||||||
|
Longitude float64 `json:"longitude"` // 门店经度[0,180]
|
||||||
|
MerchantID int `json:"merchant_id"` // 所属商户id
|
||||||
|
ModifyStatus int `json:"modify_status"` // 0-无修改,10-资料修改审核中,20-审核通过,30-a审核驳回
|
||||||
|
ModifyStatusDesc string `json:"modify_status_desc"` // 门店修改状态描述
|
||||||
|
Name string `json:"name"` // 门店主店名
|
||||||
|
OutShopCode string `json:"out_shop_code"` // 外部门店编码
|
||||||
|
OwnerIDNum string `json:"owner_id_num"` // 门店拥有人身份证号
|
||||||
|
OwnerName string `json:"owner_name"` // 门店拥有人姓名
|
||||||
|
PositionSource int `json:"position_source"` // 经纬度来源 坐标属性(1:腾讯地图, 2:百度地图, 3:高德地图),蜂鸟建议使用高德地图
|
||||||
|
PositionSourceDesc string `json:"position_source_desc"` // 经纬度来源说明
|
||||||
|
SettlementAccountID int `json:"settlement_account_id"` // 门店结算账号id
|
||||||
|
SettlementMode int `json:"settlement_mode"` // 门店结算方式 1:实时结算; 2:账期结算;
|
||||||
|
SettlementModeDesc string `json:"settlement_mode_desc"` // 结算说明?
|
||||||
|
Status int `json:"status"` // 0-上架审核中,20-正常(已上架),30-上架审核失败,40-已冻结,50-已下架
|
||||||
|
StatusDesc string `json:"status_desc"` // 门店认证状态描述
|
||||||
|
}
|
||||||
|
|
||||||
|
//#endregion
|
||||||
|
|
||||||
// CreateStoreParam 创建门店请求参数
|
// CreateStoreParam 创建门店请求参数
|
||||||
type CreateStoreParam struct {
|
type CreateStoreParam struct {
|
||||||
|
BaseInfo
|
||||||
|
BusinessData string `json:"business_data"` // 门店基础数据
|
||||||
|
}
|
||||||
|
|
||||||
|
// 创建门店基础数据
|
||||||
|
type CreateStoreBaseInfo struct {
|
||||||
BranchShopName string `json:"branch_shop_name"` // 门店主店名 必填
|
BranchShopName string `json:"branch_shop_name"` // 门店主店名 必填
|
||||||
ContactPhone string `json:"contact_phone"` // 门店联系方式
|
ContactPhone string `json:"contact_phone"` // 门店联系方式
|
||||||
OwnerIDPicFrontHash string `json:"owner_id_pic_front_hash"` // 身份证正面
|
OwnerIDPicFrontHash string `json:"owner_id_pic_front_hash"` // 身份证正面
|
||||||
@@ -61,3 +143,16 @@ type CreateStoreParam struct {
|
|||||||
OwnerIDPicBackHash string `json:"owner_id_pic_back_hash"` // 身份证反面
|
OwnerIDPicBackHash string `json:"owner_id_pic_back_hash"` // 身份证反面
|
||||||
PositionSource int `json:"position_source"` // 经纬度来源只支持高德(默认值3)
|
PositionSource int `json:"position_source"` // 经纬度来源只支持高德(默认值3)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type GetStoreResult struct {
|
||||||
|
ChainStoreCode string `json:"chain_store_code"`
|
||||||
|
ChainStoreName string `json:"chain_store_name"`
|
||||||
|
Address string `json:"address"`
|
||||||
|
Latitude string `json:"latitude"`
|
||||||
|
Longitude string `json:"longitude"`
|
||||||
|
PositionSource int `json:"position_source"`
|
||||||
|
City string `json:"city"`
|
||||||
|
ContactPhone string `json:"contact_phone"`
|
||||||
|
ServiceCode string `json:"service_code"`
|
||||||
|
Status int `json:"status"` //1关店,2开店
|
||||||
|
}
|
||||||
|
|||||||
@@ -45,7 +45,7 @@ func New(appID, appSecret, merchantId string, config ...*platformapi.APIConfig)
|
|||||||
func (a *API) signParam2() (sig string) {
|
func (a *API) signParam2() (sig string) {
|
||||||
sb := new(strings.Builder)
|
sb := new(strings.Builder)
|
||||||
sb.WriteString("grant_type=")
|
sb.WriteString("grant_type=")
|
||||||
sb.WriteString("CODE") //todo
|
sb.WriteString(a.grantType)
|
||||||
sb.WriteString("&code=")
|
sb.WriteString("&code=")
|
||||||
sb.WriteString(a.code) //todo
|
sb.WriteString(a.code) //todo
|
||||||
sb.WriteString("&app_id=")
|
sb.WriteString("&app_id=")
|
||||||
@@ -104,6 +104,8 @@ func (a *API) AccessAPI(baseUrl, actionApi, method string, bizParams map[string]
|
|||||||
|
|
||||||
// 获取access_token
|
// 获取access_token
|
||||||
func (a *API) GetAccessToken() (tokenInfo *TokenInfo, err error) {
|
func (a *API) GetAccessToken() (tokenInfo *TokenInfo, err error) {
|
||||||
|
a.grantType = "authorization_code"
|
||||||
|
a.signature = a.signParam2()
|
||||||
result, err := a.AccessAPI(TokenURL, "", RequestPost, nil)
|
result, err := a.AccessAPI(TokenURL, "", RequestPost, nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
package fnpsapi
|
package fnpsapi
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"encoding/json"
|
||||||
"fmt"
|
"fmt"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
@@ -19,29 +20,41 @@ func (a *API) CreateStore(createStoreParam *CreateStoreParam) (err error) {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
type GetStoreResult struct {
|
// 获取门店(单个)
|
||||||
ChainStoreCode string `json:"chain_store_code"`
|
|
||||||
ChainStoreName string `json:"chain_store_name"`
|
|
||||||
Address string `json:"address"`
|
|
||||||
Latitude string `json:"latitude"`
|
|
||||||
Longitude string `json:"longitude"`
|
|
||||||
PositionSource int `json:"position_source"`
|
|
||||||
City string `json:"city"`
|
|
||||||
ContactPhone string `json:"contact_phone"`
|
|
||||||
ServiceCode string `json:"service_code"`
|
|
||||||
Status int `json:"status"` //1关店,2开店
|
|
||||||
}
|
|
||||||
|
|
||||||
func (a *API) GetStore(storeID string) (getStoreResult *GetStoreResult, err error) {
|
func (a *API) GetStore(storeID string) (getStoreResult *GetStoreResult, err error) {
|
||||||
result, err := a.AccessAPI("v2/chain_store/query", URL, map[string]interface{}{
|
params := GetOneStoreParam{
|
||||||
"chain_store_code": []string{storeID},
|
BaseInfo: BaseInfo{
|
||||||
}, true)
|
AccessToken: a.accessToken,
|
||||||
if err == nil {
|
Signature: a.signature,
|
||||||
if data, ok := result["data"].([]interface{}); ok {
|
MerchantID: a.merchantId,
|
||||||
utils.Map2StructByJson(data[0], &getStoreResult, false)
|
Version: a.version,
|
||||||
} else {
|
AppID: a.appID,
|
||||||
err = fmt.Errorf(result["msg"].(string))
|
Timestamp: a.timestamp,
|
||||||
}
|
},
|
||||||
|
BusinessData: "",
|
||||||
|
}
|
||||||
|
|
||||||
|
// 序列化请求参数
|
||||||
|
data, err := json.Marshal(GetOneStore{MerchantID: a.merchantId, OutShopCode: storeID})
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
params.BusinessData = string(data)
|
||||||
|
paramsMap := utils.Struct2FlatMap(params)
|
||||||
|
|
||||||
|
result, err := a.AccessAPI(ApiURL, "chainstoreQuery", RequestGet, paramsMap)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
if result["code"] != "200" {
|
||||||
|
return nil, fmt.Errorf("%s", result["msg"])
|
||||||
|
}
|
||||||
|
|
||||||
|
if data, ok := result["business_data"].([]interface{}); ok {
|
||||||
|
utils.Map2StructByJson(data[0], &getStoreResult, false)
|
||||||
|
} else {
|
||||||
|
err = fmt.Errorf(result["msg"].(string))
|
||||||
}
|
}
|
||||||
return getStoreResult, err
|
return getStoreResult, err
|
||||||
}
|
}
|
||||||
@@ -65,7 +78,7 @@ func IsErrShopExist(err error) bool {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (a *API) UpdateStore(createStoreParam *CreateStoreParam) (err error) {
|
func (a *API) UpdateStore(createStoreParam *CreateStoreParam) (err error) {
|
||||||
params := utils.Struct2FlatMap(createStoreParam)
|
//params := utils.Struct2FlatMap(createStoreParam)
|
||||||
_, err = a.AccessAPI("v2/chain_store/update", URL, params, true)
|
//_, err = a.AccessAPI("v2/chain_store/update", URL, params, true)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -91,51 +91,57 @@ func Err2CallbackResponse(err error, data string) *CallbackResponse {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (a *API) GetCallbackMsg(request *http.Request) (msg *CallbackMsg, callbackResponse *CallbackResponse) {
|
func (a *API) GetCallbackMsg(request *http.Request) (msg *CallbackMsg, callbackResponse *CallbackResponse) {
|
||||||
if err := request.ParseForm(); err != nil {
|
err := request.ParseForm()
|
||||||
baseapi.SugarLogger.Warnf("mtwm GetCallbackMsg ParseForm failed with error:%v", err)
|
if err == nil {
|
||||||
callbackResponse = Err2CallbackResponse(err, "")
|
data := utils.URLValues2Map(request.Form)
|
||||||
return nil, callbackResponse
|
if dataSign, ok := data[signKey]; ok {
|
||||||
}
|
// fullURL := strings.TrimRight(a.callbackURL+request.URL.Path, "/")
|
||||||
|
// sign := a.signParams(fullURL+"?", data)
|
||||||
|
cmd := strings.Trim(request.URL.EscapedPath(), "/")
|
||||||
|
cmd = cmd[strings.LastIndex(cmd, "/")+1:]
|
||||||
|
// if sign != dataSign.(string) && cmd != MsgTypeStoreStatusChanged {
|
||||||
|
// baseapi.SugarLogger.Debugf("mtwm GetCallbackMsg my sign:%v, data sign:%v", sign, dataSign.(string))
|
||||||
|
// callbackResponse = SignatureIsNotOk
|
||||||
|
// } else {
|
||||||
|
msg = &CallbackMsg{
|
||||||
|
Cmd: cmd,
|
||||||
|
}
|
||||||
|
msg.FormData = make(url.Values)
|
||||||
|
for k, v := range data {
|
||||||
|
// 美团外卖的用户催单信息的timestamp是毫秒(其它的事件是秒),统一归一化为秒
|
||||||
|
if cmd == MsgTypeUserUrgeOrder && k == "timestamp" {
|
||||||
|
intV := utils.Str2Int64(v.(string))
|
||||||
|
if intV > time.Now().Unix()*2 {
|
||||||
|
v = utils.Int64ToStr(intV / 1000)
|
||||||
|
data[k] = v
|
||||||
|
}
|
||||||
|
}
|
||||||
|
msg.FormData.Set(k, v.(string))
|
||||||
|
}
|
||||||
|
msg.Timestamp = utils.Str2Int64(msg.FormData.Get("timestamp"))
|
||||||
|
msg.Sig = dataSign.(string)
|
||||||
|
msg.AppID = msg.FormData.Get("app_id")
|
||||||
|
|
||||||
data := utils.URLValues2Map(request.Form)
|
if msg.Cmd == MsgTypeOrderRefund || msg.Cmd == MsgTypeOrderPartialRefund {
|
||||||
if dataSign, ok := data[signKey]; ok {
|
var refundData *CallbackRefundInfo
|
||||||
cmd := strings.Trim(request.URL.EscapedPath(), "/")
|
if err = utils.Map2StructByJson(data, &refundData, true); err == nil {
|
||||||
cmd = cmd[strings.LastIndex(cmd, "/")+1:]
|
if refundData.Food != "" {
|
||||||
msg = &CallbackMsg{
|
utils.UnmarshalUseNumber([]byte(refundData.Food), &refundData.FoodList)
|
||||||
Cmd: cmd,
|
}
|
||||||
}
|
if refundData.Pictures != "" {
|
||||||
msg.FormData = make(url.Values)
|
utils.UnmarshalUseNumber([]byte(refundData.Pictures), &refundData.PictureList)
|
||||||
for k, v := range data {
|
}
|
||||||
// 美团外卖的用户催单信息的timestamp是毫秒(其它的事件是秒),统一归一化为秒
|
msg.Data = refundData
|
||||||
if cmd == MsgTypeUserUrgeOrder && k == "timestamp" {
|
|
||||||
intV := utils.Str2Int64(v.(string))
|
|
||||||
if intV > time.Now().Unix()*2 {
|
|
||||||
v = utils.Int64ToStr(intV / 1000)
|
|
||||||
data[k] = v
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
msg.FormData.Set(k, v.(string))
|
// }
|
||||||
}
|
} else {
|
||||||
msg.Timestamp = utils.Str2Int64(msg.FormData.Get("timestamp"))
|
callbackResponse = SuccessResponse // 美团外卖PING消息没有sign
|
||||||
msg.Sig = dataSign.(string)
|
|
||||||
msg.AppID = msg.FormData.Get("app_id")
|
|
||||||
|
|
||||||
if msg.Cmd == MsgTypeOrderRefund || msg.Cmd == MsgTypeOrderPartialRefund {
|
|
||||||
var refundData *CallbackRefundInfo
|
|
||||||
if err := utils.Map2StructByJson(data, &refundData, true); err == nil {
|
|
||||||
if refundData.Food != "" {
|
|
||||||
utils.UnmarshalUseNumber([]byte(refundData.Food), &refundData.FoodList)
|
|
||||||
}
|
|
||||||
if refundData.Pictures != "" {
|
|
||||||
utils.UnmarshalUseNumber([]byte(refundData.Pictures), &refundData.PictureList)
|
|
||||||
}
|
|
||||||
msg.Data = refundData
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
callbackResponse = SuccessResponse // 美团外卖PING消息没有sign
|
baseapi.SugarLogger.Warnf("mtwm GetCallbackMsg ParseForm failed with error:%v", err)
|
||||||
|
callbackResponse = Err2CallbackResponse(err, "")
|
||||||
}
|
}
|
||||||
|
|
||||||
return msg, callbackResponse
|
return msg, callbackResponse
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user