添加蜂鸟配送
This commit is contained in:
@@ -1,13 +1,163 @@
|
|||||||
package fnpsapi
|
package fnpsapi
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"net/url"
|
"encoding/json"
|
||||||
|
"errors"
|
||||||
|
"git.rosy.net.cn/baseapi"
|
||||||
"git.rosy.net.cn/jx-callback/globals"
|
"git.rosy.net.cn/jx-callback/globals"
|
||||||
|
"net/http"
|
||||||
|
"net/url"
|
||||||
|
|
||||||
"git.rosy.net.cn/baseapi/utils"
|
"git.rosy.net.cn/baseapi/utils"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
OrderStatus = "orderStatusNotify" // 订单状态回调
|
||||||
|
AbnormalStatus = "abnormalReportNotify" // 异常报备回调
|
||||||
|
CookingFinishStatus = "cookingFinishNotify" // 商户出餐回调
|
||||||
|
ChainstoreStatus = "chainstoreStatusNotify" // 门店状态变更回调
|
||||||
|
ChainstoreServiceStatus = "chainstoreServiceStatusNotify" // 门店采购服务变更回调
|
||||||
|
NoServiceStatus = "noServiceNotify" // 城市屏蔽区域调整回调通知
|
||||||
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
SuccessResponse = &CallbackResponse{Code: 200}
|
||||||
|
SignatureIsNotOk = &CallbackResponse{Code: -1}
|
||||||
|
)
|
||||||
|
|
||||||
|
type CallbackResponse struct {
|
||||||
|
Code int `json:"code"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func Err2CallbackResponse(err error, data string) *CallbackResponse {
|
||||||
|
if err == nil {
|
||||||
|
return SuccessResponse
|
||||||
|
}
|
||||||
|
return &CallbackResponse{
|
||||||
|
Code: -1,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
type ShortStatus struct {
|
||||||
|
AppId string `json:"app_id"`
|
||||||
|
Signature string `json:"signature"`
|
||||||
|
Timestamp string `json:"timestamp"`
|
||||||
|
BusinessData string `json:"business_data"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// 门店状态回调
|
||||||
|
type ChainstoreStatusNotify struct {
|
||||||
|
CallbackBusinessType string `json:"callback_business_type"`
|
||||||
|
Param string `json:"param"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// 门店状态回调paramter
|
||||||
|
type ChainstoreParam struct {
|
||||||
|
MerchantId string `json:"merchant_id"` // 商户id
|
||||||
|
ChainStoreId string `json:"chain_store_id"` // 蜂鸟门店id
|
||||||
|
OutShopCode string `json:"out_shop_code"` // 外部门店编码
|
||||||
|
Status string `json:"status"` // 门店认证状态
|
||||||
|
ModifyStatus string `json:"modify_status"` // 门店修改状态
|
||||||
|
Remark string `json:"remark "` // 门店认证、修改等驳回时返回原因
|
||||||
|
}
|
||||||
|
|
||||||
|
// 订单状态回调paramter
|
||||||
|
type OrderCallbackParam struct {
|
||||||
|
OrderId int64 `json:"order_id"` // 订单号
|
||||||
|
AppId string `json:"app_id"` // 应用id
|
||||||
|
PartnerOrderCode string `json:"partner_order_code"` // 外部订单号
|
||||||
|
OrderStatus int `json:"order_status"` // 订单状态 订单生成0,运单生成成功1,20:骑手接单,80:骑手到 店,2:配送中,3:已完成,4:已取消,5:配送异常
|
||||||
|
CarrierDriverId int64 `json:"carrier_driver_id"` // 骑手id
|
||||||
|
CarrierLat string `json:"carrier_lat"` // 坐标高德(不要使用)
|
||||||
|
CarrierLng string `json:"carrier_lng"` // 坐标高德(不要使用)
|
||||||
|
CarrierDriverName string `json:"carrier_driver_name"` // 骑手姓名
|
||||||
|
CarrierDriverPhone string `json:"carrier_driver_phone"` // 骑手电话
|
||||||
|
Description string `json:"description"` // 描述
|
||||||
|
ErrorCode string `json:"error_code"` // 异常code
|
||||||
|
ErrorScene string `json:"error_scene"` // 异常描述
|
||||||
|
DetailDescription string `json:"detail_description"` // 详情描述
|
||||||
|
PushTime int64 `json:"push_time"` // 状态推送时间 (毫秒)
|
||||||
|
Transfer int `json:"transfer"` // 转单标识 转单标识 1 是转单 0非转单
|
||||||
|
}
|
||||||
|
|
||||||
|
// 出餐回调
|
||||||
|
type CookingFinishNotify struct {
|
||||||
|
OrderId int64 `json:"order_id"` // 订单号
|
||||||
|
AppId string `json:"app_id"` // 应用id
|
||||||
|
PartnerOrderCode string `json:"partner_order_code"` // 外部订单号
|
||||||
|
ChainStoreId string `json:"chain_store_id"` // 蜂鸟门店id
|
||||||
|
MerchantId string `json:"merchant_id"` // 商户id
|
||||||
|
CookingFinishTime int64 `json:"cooking_finish_time"` // 状态推送时间 (毫秒)
|
||||||
|
}
|
||||||
|
|
||||||
|
// 获取门店状态回调消息
|
||||||
|
func (a *API) GetChainstoreStatusNotify(request *http.Request) (shopStatusMsg map[string]interface{}, callbackResponse *CallbackResponse) {
|
||||||
|
storeNotify := ShortStatus{}
|
||||||
|
err := utils.Map2StructByJson(utils.URLValues2Map(request.PostForm), &storeNotify, true)
|
||||||
|
if err != nil {
|
||||||
|
baseapi.SugarLogger.Debugf("FN GetShopStatusCallbackMsg failed with err:%v", err)
|
||||||
|
callbackResponse = &CallbackResponse{Code: -1}
|
||||||
|
return nil, callbackResponse
|
||||||
|
}
|
||||||
|
|
||||||
|
fnNotify := &ChainstoreStatusNotify{}
|
||||||
|
if err := json.Unmarshal([]byte(storeNotify.BusinessData), fnNotify); err != nil {
|
||||||
|
baseapi.SugarLogger.Debugf("FN callback string to ChainstoreStatusNotify failed with err:%v", err)
|
||||||
|
callbackResponse = &CallbackResponse{Code: -1}
|
||||||
|
return nil, callbackResponse
|
||||||
|
}
|
||||||
|
|
||||||
|
// 解析蜂鸟返回值
|
||||||
|
shopStatusMsg, err = FnCallbackAnalysis(fnNotify)
|
||||||
|
if err != nil {
|
||||||
|
return nil, &CallbackResponse{Code: -1}
|
||||||
|
}
|
||||||
|
|
||||||
|
return shopStatusMsg, SuccessResponse
|
||||||
|
}
|
||||||
|
|
||||||
|
// 蜂鸟返回值解析
|
||||||
|
func FnCallbackAnalysis(notify *ChainstoreStatusNotify) (result map[string]interface{}, err error) {
|
||||||
|
switch notify.CallbackBusinessType {
|
||||||
|
case OrderStatus: // 订单回调
|
||||||
|
orderRes := &OrderCallbackParam{}
|
||||||
|
if err := json.Unmarshal([]byte(notify.Param), orderRes); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
notifyObj := utils.Struct2FlatMap(orderRes)
|
||||||
|
notifyObj["orderStatusNotify"] = ChainstoreStatus
|
||||||
|
return notifyObj, nil
|
||||||
|
case AbnormalStatus: // 异常报备回调
|
||||||
|
return nil, nil
|
||||||
|
case CookingFinishStatus: // 商户出餐回调
|
||||||
|
//cokking := &CookingFinishNotify{}
|
||||||
|
//if err := json.Unmarshal([]byte(notify.Param), cokking); err != nil {
|
||||||
|
// return nil, err
|
||||||
|
//}
|
||||||
|
//notifyObj := utils.Struct2FlatMap(cokking)
|
||||||
|
//notifyObj["cookingFinishNotify"] = ChainstoreStatus
|
||||||
|
//return notifyObj, nil
|
||||||
|
return nil, nil
|
||||||
|
case ChainstoreStatus: // 门店状态变更回调
|
||||||
|
storeRes := &ChainstoreParam{}
|
||||||
|
if err := json.Unmarshal([]byte(notify.Param), storeRes); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
notifyObj := utils.Struct2FlatMap(storeRes)
|
||||||
|
notifyObj["notifyUel"] = ChainstoreStatus
|
||||||
|
return notifyObj, nil
|
||||||
|
case ChainstoreServiceStatus: // 门店采购服务变更回调
|
||||||
|
return nil, nil
|
||||||
|
case NoServiceStatus: // 城市屏蔽区域调整回调通知
|
||||||
|
return nil, nil
|
||||||
|
default:
|
||||||
|
return nil, errors.New("回调函数,回调路径错误")
|
||||||
|
}
|
||||||
|
|
||||||
|
globals.SugarLogger.Warnf("Fn callback url func err:=[%s],dont's exits", "notify.CallbackBusinessType")
|
||||||
|
return nil, errors.New("回调函数,回调路径错误")
|
||||||
|
}
|
||||||
|
|
||||||
type CallBackInfo struct {
|
type CallBackInfo struct {
|
||||||
AppID string `json:"app_id"`
|
AppID string `json:"app_id"`
|
||||||
Data string `json:"data"`
|
Data string `json:"data"`
|
||||||
|
|||||||
451
platformapi/fnpsapi/fnps_v3.go
Normal file
451
platformapi/fnpsapi/fnps_v3.go
Normal file
@@ -0,0 +1,451 @@
|
|||||||
|
package fnpsapi
|
||||||
|
|
||||||
|
import (
|
||||||
|
"git.rosy.net.cn/baseapi/platformapi"
|
||||||
|
"net/http"
|
||||||
|
"sync"
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
//TokenURL = "https://open-anubis.ele.me/anubis-webapi/openapi/token" // 正式环境
|
||||||
|
//ApiURL = "https://open-anubis.ele.me/anubis-webapi/v3/invoke"// 正式环境
|
||||||
|
TokenURL = "https://exam-anubis.ele.me/anubis-webapi/openapi/token" // 沙箱环境
|
||||||
|
ApiURL = "https://exam-anubis.ele.me/anubis-webapi/v3/invoke" // 沙箱环境
|
||||||
|
RequestPost = "POST"
|
||||||
|
RequestGet = "GET"
|
||||||
|
)
|
||||||
|
|
||||||
|
// 注册请求api
|
||||||
|
type API struct {
|
||||||
|
grantType string `json:"grant_type"`
|
||||||
|
code string `json:"code"`
|
||||||
|
appID string `json:"app_id"`
|
||||||
|
merchantId string `json:"merchant_id"`
|
||||||
|
signature string `json:"signature"`
|
||||||
|
timestamp int64 `json:"timestamp"`
|
||||||
|
accessToken string `json:"access_token"`
|
||||||
|
appSecret string `json:"app_secret"`
|
||||||
|
version string `json:"version"`
|
||||||
|
locker sync.RWMutex
|
||||||
|
client *http.Client
|
||||||
|
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 获取授权token
|
||||||
|
|
||||||
|
// 获取token
|
||||||
|
type TokenInfo struct {
|
||||||
|
Sign string `json:"sign"` //返回值签名,详见开放平台侧返回值签名算法
|
||||||
|
Code string `json:"code"` //错误码,详见开放平台侧错误码映射表
|
||||||
|
Msg string `json:"msg"` //错误信息
|
||||||
|
BusinessData string `json:"business_data"` // string
|
||||||
|
BusinessDataObj *BusinessData // BusinessData 对象
|
||||||
|
}
|
||||||
|
|
||||||
|
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 int64 `json:"expire_in"` //access_token剩余有效时间,单位:秒,默认有效期是一年
|
||||||
|
ReExpireIn int64 `json:"re_expire_in"` //refresh_token剩余有效时间
|
||||||
|
}
|
||||||
|
|
||||||
|
//#endregion
|
||||||
|
|
||||||
|
//<---------------------------------------------------门店--------------------------------------------------------------------------------------->
|
||||||
|
//#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 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"` // 门店认证状态描述
|
||||||
|
}
|
||||||
|
|
||||||
|
// 更新蜂鸟门店信息
|
||||||
|
type UpdateStoreParam struct {
|
||||||
|
// 必填
|
||||||
|
ChainStoreID string `json:"chain_store_id"` // 蜂鸟门店id,创建接口返回的id
|
||||||
|
HeadShopName string `json:"head_shop_name"` // 门店主店名
|
||||||
|
ContactPhone string `json:"contact_phone"` // 门店联系方式
|
||||||
|
Address string `json:"address"` // 门店地址
|
||||||
|
Longitude float64 `json:"longitude"` // 纬度
|
||||||
|
Latitude float64 `json:"latitude"` // 门店纬度
|
||||||
|
PositionSource int `json:"position_source"` // 经纬度来源 坐标属性:高德地图:3;目前只支持高德地图坐标
|
||||||
|
OutShopCode string `json:"out_shop_code"` // 外部门店编码
|
||||||
|
CategoryID string `json:"category_id"` // 门店类目
|
||||||
|
OwnerName string `json:"owner_name"` // 门店主店名
|
||||||
|
OwnerIDNum string `json:"owner_id_num"` // 门店拥有人身份证号
|
||||||
|
HandheldLicencePicHash string `json:"handheld_licence_pic_hash"` // 门店拥有人手持身份证、营业执照图片
|
||||||
|
OwnerIDPicFrontHash string `json:"owner_id_pic_front_hash"` // 身份证正面
|
||||||
|
OwnerIDPicBackHash string `json:"owner_id_pic_back_hash"` // 身份证反面
|
||||||
|
CreditCode string `json:"credit_code"` // 统一社会信用代码
|
||||||
|
BusinessLicencePicHash string `json:"business_licence_pic_hash"` // 营业执照图片
|
||||||
|
|
||||||
|
// 选填
|
||||||
|
BranchShopName string `json:"branch_shop_name"` // 门店主店名
|
||||||
|
ChainstoreType int `json:"chainstore_type"`
|
||||||
|
FoodLicensePicHash string `json:"food_license_pic_hash"` // 食品安全执照图片
|
||||||
|
SecondMedicalEquipmentLicensePicHash string `json:"second_medical_equipment_license_pic_hash"` // 第二类医疗器械类目必传
|
||||||
|
MedicalInstitutionLicensePicHash string `json:"medical_institution_license_pic_hash"` // 医疗机构必传
|
||||||
|
MedicalEquipmentLicensePicHash string `json:"medical_equipment_license_pic_hash"` // 经营医疗器械必传
|
||||||
|
MedicineLicensePicHash string `json:"medicine_license_pic_hash"` // 药品经营许可证
|
||||||
|
TabacooLicensePicHash string `json:"tabacoo_license_pic_hash"` // 烟草经营许可证图片
|
||||||
|
}
|
||||||
|
|
||||||
|
// 创建门店基础数据
|
||||||
|
type CreateStoreBaseInfo struct {
|
||||||
|
// 必填
|
||||||
|
HeadShopName string `json:"head_shop_name"` // 门店主店名
|
||||||
|
ContactPhone string `json:"contact_phone"` // 门店联系方式
|
||||||
|
Address string `json:"address"` // 门店地址
|
||||||
|
Longitude float64 `json:"longitude"` // 门店经度(0-18)
|
||||||
|
Latitude float64 `json:"latitude"` // 门店纬度(0-90)
|
||||||
|
PositionSource int `json:"position_source"` // 经纬度来源只支持高德(默认值3)
|
||||||
|
OutShopCode string `json:"out_shop_code"` // 外部门店编码
|
||||||
|
CategoryID string `json:"category_id"` // 门店类目
|
||||||
|
OwnerName string `json:"owner_name"` // 门店拥有人姓名
|
||||||
|
OwnerIDNum string `json:"owner_id_num"` // 门店拥有人身份证号
|
||||||
|
HandheldLicencePicHash string `json:"handheld_licence_pic_hash"` // 门店拥有人手持身份证、营业执照图片
|
||||||
|
OwnerIDPicFrontHash string `json:"owner_id_pic_front_hash"` // 身份证正面
|
||||||
|
OwnerIDPicBackHash string `json:"owner_id_pic_back_hash"` // 身份证反面
|
||||||
|
CreditCode string `json:"credit_code"` // 统一社会信用代码
|
||||||
|
BusinessLicencePicHash string `json:"business_licence_pic_hash"` // 营业执照图片
|
||||||
|
|
||||||
|
// 非必填
|
||||||
|
BranchShopName string `json:"branch_shop_name"` // 门店分店名
|
||||||
|
ChainstoreType int `json:"chainstore_type"` // 门店类型 1:正式门店;2:测试门店;默认为1
|
||||||
|
SettlementModel string `json:"settlement_model"` // 1:实时结算; 2:账期结算;默认为1,若为账期结算,需额外传入结算账号id
|
||||||
|
SettlementAccountID string `json:"settlement_account_id"` // 门店结算账号id
|
||||||
|
|
||||||
|
// 经营类目包含食品必传
|
||||||
|
FoodLicensePicHash string `json:"food_license_pic_hash"` // 食品安全执照图片(食品经营必传)
|
||||||
|
SecondMedicalEquipmentLicensePicHash string `json:"second_medical_equipment_license_pic_hash"` // 第二类医疗器械类目必传
|
||||||
|
MedicalInstitutionLicensePicHash string `json:"medical_institution_license_pic_hash"` // 医疗机构必传
|
||||||
|
MedicalEquipmentLicensePicHash string `json:"medical_equipment_license_pic_hash"` // 经营医疗器械必传
|
||||||
|
MedicineLicensePicHash string `json:"medicine_license_pic_hash"` // 药品经营许可证
|
||||||
|
TabacooLicensePicHash string `json:"tabacoo_license_pic_hash"` // 烟草经营许可证图片
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
//#endregion
|
||||||
|
|
||||||
|
// <--------------------------------------------------订单------------------------------------------------------------------->
|
||||||
|
//#region 预请求获取订单
|
||||||
|
type PreCreateOrder struct {
|
||||||
|
// 必填参数
|
||||||
|
PartnerOrderCode string `json:"partner_order_code"` // 外部订单号
|
||||||
|
OrderType int `json:"order_type"` // 订单类型(1:即时单,3:预约单)
|
||||||
|
PositionSource int `json:"position_source"` // 经纬度来源
|
||||||
|
ReceiverAddress string `json:"receiver_address"` // 收货人地址 文字描述
|
||||||
|
ReceiverLongitude float64 `json:"receiver_longitude"` // 收货人经度
|
||||||
|
ReceiverLatitude float64 `json:"receiver_latitude"` // 收货人纬度
|
||||||
|
GoodsTotalAmountCent int64 `json:"goods_total_amount_cent"` // 订单商品总金额(分)
|
||||||
|
GoodsActualAmountCent int64 `json:"goods_actual_amount_cent"` // 订单商品客户实际支付金额
|
||||||
|
GoodsWeight float64 `json:"goods_weight"` // 订单总重量(kg)
|
||||||
|
GoodsCount int `json:"goods_count"` // 货物件数
|
||||||
|
GoodsItemList []*GoodsItemsList // 货物列表
|
||||||
|
|
||||||
|
// 非必填参数
|
||||||
|
TransportLongitude float64 `json:"transport_longitude,omitempty"` // 取货经度
|
||||||
|
TransportLatitude float64 `json:"transport_latitude,omitempty"` // 取货纬度
|
||||||
|
TransportTel string `json:"transport_tel,omitempty"` // 取货点联系人电话
|
||||||
|
OutShopCode string `json:"out_shop_code,omitempty"` // 外部门店id 当使用门店发单 out_shop_code和chain_store_id必填1个
|
||||||
|
ChainStoreID string `json:"chain_store_id"` // 门店id
|
||||||
|
OrderSource string `json:"order_source,omitempty"` // 饿百订单传109 商户订单来源(如饿了么、美团等)手发单/未知来源: 0 或不传 美团: 2 口碑: 4 饿了么: 6支付宝: 7 饿百: 8
|
||||||
|
ServiceGoodsId int64 `json:"service_goods_id"` // 服务商品id
|
||||||
|
BaseGoodsId int64 `json:"base_goods_id"` // 基础商品id
|
||||||
|
RequireReceiveTime string `json:"require_receive_time"` // 需要送达时间 预约单如(需要送达时间 – 推单时间) < 60min
|
||||||
|
OrderAddTime int64 `json:"order_add_time,omitempty"` // 下单时间毫秒
|
||||||
|
UseCoupon int `json:"use_coupon,omitempty"` // 是否使用优惠券 0:不使用, 1:使用 默认使用
|
||||||
|
ExpectFetchTime int64 `json:"expect_fetch_time,omitempty"` // 预计出餐时间(毫秒) (预约单该字段必填)建议和商务合同里约定的承诺出货时长保持一致,否则影响考核结算
|
||||||
|
TransportAddress string `json:"transport_address"` // 取货点地址描述
|
||||||
|
OrderTipAmountCent int64 `json:"order_tip_amount_cent,omitempty"` // 取货点地址描述
|
||||||
|
//OrderRemark string `json:"order_remark"`
|
||||||
|
//FetchCode string `json:"fetch_code"`
|
||||||
|
//WriteOffCode string `json:"write_off_code"`
|
||||||
|
//CustomerExtTel string `json:"customer_ext_tel"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// 货物明细
|
||||||
|
type GoodsItemsList struct {
|
||||||
|
ItemName string `json:"item_name"` // 商品名字
|
||||||
|
ItemQuantity int `json:"item_quantity"` // 商品数量
|
||||||
|
ItemAmountCent int64 `json:"item_amount_cent"` // 商品原价分
|
||||||
|
ItemActualAmountCent int64 `json:"item_actual_amount_cent"` // 商品实际支付金额,必须是乘以数量后的金额,否则影响售后环节的赔付标准
|
||||||
|
|
||||||
|
// 非必填
|
||||||
|
ItemId string `json:"item_id"` // 商品编号
|
||||||
|
ItemSize int `json:"item_size"` // 商品尺寸 1:小, 2:中, 3:大
|
||||||
|
ItemRemark string `json:"item_remark"` // 品备注(不超过255个字符)
|
||||||
|
}
|
||||||
|
|
||||||
|
// 蜂鸟请求预下单返回值
|
||||||
|
type PreCreateOrderResp struct {
|
||||||
|
Distance int64 `json:"distance"` //配送距离
|
||||||
|
CityId int64 `json:"city_id"` // 城市id
|
||||||
|
Time int64 `json:"time"` // 预询时间戳
|
||||||
|
GoodsInfos []*GoodsInfos `json:"goods_infos"` // 服务商品明细
|
||||||
|
//GoodsInfos string `json:"goods_infos"` // 服务商品明细
|
||||||
|
}
|
||||||
|
|
||||||
|
// 预下单商品服务明细
|
||||||
|
type GoodsInfos struct {
|
||||||
|
ServiceGoodsId int64 `json:"service_goods_id"` // 服务商品id
|
||||||
|
BaseGoodsId int64 `json:"base_goods_id"` // 基础商品id
|
||||||
|
IsValid int `json:"is_valid"` // 是否可用0不可,1可
|
||||||
|
DisableReason string `json:"disable_reason"` // 不可用原因描述
|
||||||
|
PredictDeliveryTime int64 `json:"predict_delivery_time"` // 预计送达时间戳
|
||||||
|
PredictDeliveryMinutes int `json:"predict_delivery_minutes"` // 预计送达时长分钟
|
||||||
|
CanAddTip int `json:"can_add_tip"` // 服务商品是否支持加小费0否1是
|
||||||
|
Slogan string `json:"slogan"` // 商品介绍
|
||||||
|
TotalDeliveryAmountCent int64 `json:"total_delivery_amount_cent"` // 原始配送费总价格(含入参小费金额) 分
|
||||||
|
ActualDeliveryAmountCent int64 `json:"actual_delivery_amount_cent"` // 优惠后配送费总价格(含入参小费金额) 入单实际价格 关注这一个字段就行!!!
|
||||||
|
PriceDetail *PriceOpenapiDetail `json:"price_detail"` // 加价说明
|
||||||
|
WarehouseId int64 `json:"warehouse_id"` // 优惠券记录id
|
||||||
|
TIndexid string `json:"t_indexid"` // 预询标识 入单时需传入,标识本次预询
|
||||||
|
}
|
||||||
|
|
||||||
|
// 订单加价说明
|
||||||
|
type PriceOpenapiDetail struct {
|
||||||
|
StartPriceCent int `json:"start_price_cent"` // 起送价 分
|
||||||
|
DistancePriceCent int `json:"distance_price_cent"` // 距离加价
|
||||||
|
WeightPriceCent int `json:"weight_price_cent"` // 重量加价
|
||||||
|
TimePeriodSurchargeCent int `json:"time_period_surcharge_cent"` // 时段加价
|
||||||
|
TemporarySurchargeCent int `json:"temporary_surcharge_cent"` // 临时加价
|
||||||
|
CategorySurchargeCent int `json:"category_surcharge_cent"` // 品类加价
|
||||||
|
OrderPriceSurchargeCent int `json:"order_price_surcharge_cent"` // 客单价加价
|
||||||
|
PressureSurchargeCent int `json:"pressure_surcharge_cent"` // 运力紧张加价
|
||||||
|
RiverCrossingSurchargeCent int `json:"river_crossing_surcharge_cent"` // 跨江单加价
|
||||||
|
}
|
||||||
|
|
||||||
|
//#endregion
|
||||||
|
|
||||||
|
//#region 正式下单(订单查询,骑手查询,账户查询)
|
||||||
|
|
||||||
|
// 创建订单
|
||||||
|
type CreateOrderReqParam struct {
|
||||||
|
// 必传参数
|
||||||
|
PartnerOrderCode string `json:"partner_order_code,omitempty"` // 外部订单号
|
||||||
|
OrderType int `json:"order_type,omitempty"` // 订单类型(1:即时单,3:预约单)
|
||||||
|
PositionSource int `json:"position_source,omitempty"` // 坐标经纬度来源(1:腾讯地 图, 2:百度地图, 3:高德地图)蜂鸟建议使用高德地图
|
||||||
|
ReceiverAddress string `json:"receiver_address,omitempty"` // 收货人地址 文字描述
|
||||||
|
ReceiverLongitude float64 `json:"receiver_longitude,omitempty"` // 收货人经度
|
||||||
|
ReceiverLatitude float64 `json:"receiver_latitude,omitempty"` // 收货人纬度
|
||||||
|
GoodsTotalAmountCent int64 `json:"goods_total_amount_cent,omitempty"` // 订单商品总金额(分)
|
||||||
|
GoodsActualAmountCent int64 `json:"goods_actual_amount_cent,omitempty"` // 订单商品客户实际支付金额
|
||||||
|
GoodsWeight float64 `json:"goods_weight,omitempty"` // 订单总重量(kg)
|
||||||
|
GoodsCount int `json:"goods_count,omitempty"` // 货物件数
|
||||||
|
GoodsItemList []*GoodsItemsList `json:"goods_item_list,omitempty"` // 货物明细
|
||||||
|
ReceiverName string `json:"receiver_name,omitempty"` // 收货人姓名
|
||||||
|
ReceiverPrimaryPhone string `json:"receiver_primary_phone,omitempty"` // 只支持手机号,400开头电话,座机号码以及95013开头、长度13位的虚拟电话
|
||||||
|
OutShopCode string `json:"out_shop_code,omitempty"` // 外部门店id 当使用门店发单 out_shop_code和chain_store_id必填1个
|
||||||
|
ChainStoreId string `json:"chain_store_id,omitempty"` // 门店id
|
||||||
|
|
||||||
|
// 选传参数
|
||||||
|
TransportLongitude float64 `json:"transport_longitude,omitempty"` // 取货经度
|
||||||
|
TransportLatitude float64 `json:"transport_latitude,omitempty"` // 取货纬度
|
||||||
|
TransportTel string `json:"transport_tel,omitempty"` // 取货点联系人电话
|
||||||
|
OrderSource string `json:"order_source,omitempty"` // 饿百订单传109 商户订单来源(如饿了么、美团等)手发单/未知来源: 0 或不传 美团: 2 口碑: 4 饿了么: 6支付宝: 7 饿百: 8
|
||||||
|
ServiceGoodsId int64 `json:"service_goods_id,omitempty"` // 服务商品id 校验预询配送费价格时 必传
|
||||||
|
BaseGoodsId int64 `json:"base_goods_id,omitempty"` // 基础商品id 校验预询配送费价格时 必传
|
||||||
|
RequireReceiveTime int64 `json:"require_receive_time,omitempty"` // 需要送达时间 需要送达时间(毫秒); 订单类型为预约单时必传,如(需要送达时间 – 推单时间)< 60min,则蜂鸟配送开放平台自动将订单类型置为即时单 ,反之则置为预约单
|
||||||
|
OrderAddTime int64 `json:"order_add_time,omitempty"` // 下单时间毫秒
|
||||||
|
UseCoupon int `json:"use_coupon,omitempty"` // 是否使用优惠券 0:不使用, 1:使用 默认使用
|
||||||
|
ExpectFetchTime int64 `json:"expect_fetch_time,omitempty"` // 预计出餐时间(毫秒) (预约单该字段必填)建议和商务合同里约定的承诺出货时长保持一致,否则影响考核结算
|
||||||
|
TransportAddress string `json:"transport_address,omitempty"` // 取货点地址描述
|
||||||
|
OrderTipAmountCent int64 `json:"order_tip_amount_cent,omitempty"` // 取货点地址描述
|
||||||
|
SerialNumber string `json:"serial_number,omitempty"` // 商家订单流水号, 方便配送骑手 到店取货, 支持数字,字母及#等常见字符. 建议填写。长度<=6。
|
||||||
|
OrderSourceOrderId string `json:"order_source_order_id,omitempty"` // 订单来源的 单号
|
||||||
|
ReceiverSecondPhone string `json:"receiver_second_phone,omitempty"` // 收货人备用联系方式
|
||||||
|
CustomerExtTel string `json:"customer_ext_tel,omitempty"` // 分机号
|
||||||
|
OrderRemark string `json:"order_remark,omitempty"` // 用户备注
|
||||||
|
PreCreateOrderTIndexId string `json:"pre_create_order_t_index_id,omitempty"` // 预询后下单标识 为null不校验配送费价格直接 入单 不为null强校验配送费价格 与入参价格不一致拒绝入单
|
||||||
|
WarehouseId int64 `json:"warehouse_id,omitempty"` // 优惠券id
|
||||||
|
ActualDeliveryAmountCent int64 `json:"actual_delivery_amount_cent,omitempty"` // 优惠后配送费总价格(含入参小费金额) 入单实际价格 取自预下单接口出参同名字段!!!不为null则校验配送费价格,不一致拒绝入单 (含入参小费)校验预询配送费价格时 必传
|
||||||
|
WriteOffCode string `json:"write_off_code,omitempty"` // 销码(贵品服务必填)骑手和商户交互 签贵品履约才生效
|
||||||
|
CancelCode string `json:"cancel_code,omitempty"` // 取消码(贵品服务必填)
|
||||||
|
FetchCode string `json:"fetch_code,omitempty"` // 取餐码 骑手和用户交互
|
||||||
|
}
|
||||||
|
|
||||||
|
// 查询余额getAmount
|
||||||
|
type GetBalanceAmountRes struct {
|
||||||
|
BalanceAmountCent int64 `json:"balance_amount_cent"` // 账户余额 分
|
||||||
|
FrozenBalanceAmountCent int64 `json:"frozen_balance_amount_cent"` // 账户冻结余额 分
|
||||||
|
BalanceStatus int `json:"balance_status"` // 账户状态 1 正常 2 冻结
|
||||||
|
}
|
||||||
|
|
||||||
|
// 查询订单详情接口 getOrderDetail
|
||||||
|
type GetOrderDetailReq struct {
|
||||||
|
OrderId string `json:"order_id"` // 订单号 订单号和外部订单号必填1个
|
||||||
|
PartnerOrderCode string `json:"partner_order_code"` // 外部订单号
|
||||||
|
}
|
||||||
|
|
||||||
|
// 查询订单详情接口返回值
|
||||||
|
type GetOrderDetailRes struct {
|
||||||
|
OrderId int64 `json:"order_id"` // 订单id
|
||||||
|
TrackingId int64 `json:"tracking_id"` // 运单id
|
||||||
|
PartnerOrderCode string `json:"partner_order_code"` // 外部订单号
|
||||||
|
SerialNumber string `json:"serial_number"` // 商家订单流水号, 方便配送骑手 到店取货, 支持数字,字母及#等常见字符. 建议填写。长度<=6。
|
||||||
|
OrderStatus int `json:"order_status"` // 订单生成0,运单生成成功1,20:骑手接单,80:骑手到店,2:配送中,3:已完成,4:已取消,5:配送异常
|
||||||
|
CarrierDriverId string `json:"carrier_driver_id"` // 配送员id
|
||||||
|
CarrierDriverName string `json:"carrier_driver_name"` // 配送员姓名
|
||||||
|
CarrierDriverPhone string `json:"carrier_driver_phone"` // 配送员电话
|
||||||
|
EstimateArriveTime int64 `json:"estimate_arrive_time"` // 预计送达时间(毫秒)
|
||||||
|
OvertimeCompensationCostCent int64 `json:"overtime_compensation_cost_cent"` // 时效赔付
|
||||||
|
IfCanAddTip int `json:"if_can_add_tip"` // 是否支持添加调度费 1可以,0不可以
|
||||||
|
OrderTipAmountCent int64 `json:"order_tip_amount_cent"` // 订单当前小费总金额 分
|
||||||
|
DeliveryFetchPhotos []interface{} `json:"delivery_fetch_photos"` // 骑手取货照片地址
|
||||||
|
OrderTotalAmountCent int64 `json:"order_total_amount_cent"` // 原始配送费金额(分)
|
||||||
|
OrderActualAmountCent int64 `json:"order_actual_amount_cent"` // 订单实际配送支付总金额关注这个字段即可(分)
|
||||||
|
PriceDetail []*PriceOpenapiDetail `json:"price_detail"` // 配送费价格明细
|
||||||
|
AbnormalCode string `json:"abnormal_code"` // 运单异常原因code
|
||||||
|
AbnormalDesc string `json:"abnormal_desc"` // 运单异常原因描述
|
||||||
|
EventLogDetails []*OrderNodeInfo `json:"event_log_details"` // 运单事件节点信息
|
||||||
|
ComplaintId int64 `json:"complaint_id"` // 投诉编号
|
||||||
|
ComplaintReasonDesc string `json:"complaint_reason_desc"` // 投诉原因描述
|
||||||
|
ComplaintStatus int `json:"complaint_status"` // 投诉状态 1待处理, 2成功,3失败
|
||||||
|
ClaimId int64 `json:"claim_id"` // 索赔id
|
||||||
|
ClaimReasonDesc string `json:"claim_reason_desc"` // 索赔原因描述
|
||||||
|
ClaimStatus int `json:"claim_status"` // 索赔状态 1待处理, 2成功,3失败
|
||||||
|
Temperature string `json:"temperature"` // 骑手体温
|
||||||
|
OrderDistance float64 `json:"order_distance"` // 配送距离(米)
|
||||||
|
}
|
||||||
|
|
||||||
|
// 点单详情信息,订单结点信息
|
||||||
|
type OrderNodeInfo struct {
|
||||||
|
OrderStatus int `json:"order_status"` // 订单状态
|
||||||
|
OccurTime int64 `json:"occur_time"` // 时间结点
|
||||||
|
CarrierDriverName string `json:"carrier_driver_name"` // 配送员姓名
|
||||||
|
CarrierDriverPhone string `json:"carrier_driver_phone"` // 配送电话
|
||||||
|
}
|
||||||
|
|
||||||
|
// getKnightInfo 查询骑手信息接口,参数 GetOrderDetailReq
|
||||||
|
type GetKnightInfoRes struct {
|
||||||
|
CarrierDriverId string `json:"carrier_driver_id"` // 配送员id
|
||||||
|
CarrierDriverName string `json:"carrier_driver_name"` // 配送员姓名
|
||||||
|
CarrierDriverPhone string `json:"carrier_driver_phone"` // 配送员电话
|
||||||
|
CarrierDriverLongitude string `json:"carrier_driver_longitude"` // 骑手坐标
|
||||||
|
CarrierDriverLatitude string `json:"carrier_driver_latitude"` // 骑手坐标
|
||||||
|
}
|
||||||
|
|
||||||
|
//#endregion
|
||||||
|
|
||||||
|
//#region 加小费接口
|
||||||
|
|
||||||
|
//追加小费,订单小费总金额为每次累加
|
||||||
|
//注:不是所有订单都支持加小费,受合同服务 & 接单运力 & 当时订单状态等多个因素影响。 订单详情接口有返回是否可加小费字段。
|
||||||
|
//另:联调环境使用加小费接口 需先使用联调工具->订单状态回调:把订单状态改为1,否则订单状态会不支持加小费
|
||||||
|
// 添加小费
|
||||||
|
type AddTipRes struct {
|
||||||
|
OrderId string `json:"order_id"` // 订单号 订单号和外部订单号必填1个
|
||||||
|
PartnerOrderCode string `json:"partner_order_code"` // 外部订单号
|
||||||
|
AddTipAmountCent int64 `json:"add_tip_amount_cent"` // 小费金额分(必填)
|
||||||
|
ThirdIndexId int64 `json:"third_index_id"` // 本次加小费唯一标识 每个订单内 不可重复, 会用来做幂等,相同third_index_id的后续请求会被忽略
|
||||||
|
}
|
||||||
|
|
||||||
|
// 业务出参 "business_data": "{\"result\":true}"
|
||||||
|
//#endregion
|
||||||
|
|
||||||
|
//#region 取消接口
|
||||||
|
|
||||||
|
// getCancelReasonList 获取可用取消原因列表接口 参数:GetOrderDetailReq
|
||||||
|
|
||||||
|
// getCancelReasonListRes 取消接口返回值
|
||||||
|
type GetCancelReasonListRes struct {
|
||||||
|
CancelReasonList []*struct {
|
||||||
|
OrderCancelCode int `json:"order_cancel_code"` // 取消原因code
|
||||||
|
OrderCancelDesc int `json:"order_cancel_desc"` // 取消原因描述
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// preCancelOrder 预取消订单接口
|
||||||
|
type PreCancelOrderReq struct {
|
||||||
|
GetOrderDetailReq
|
||||||
|
OrderCancelCode int64 `json:"order_cancel_code"` // 从可用取消原因列表接口返回结果选择(必填)
|
||||||
|
}
|
||||||
|
|
||||||
|
// cancelOrder 正式取消订单接口
|
||||||
|
type CancelOrderReq struct {
|
||||||
|
GetOrderDetailReq
|
||||||
|
OrderCancelCode int64 `json:"order_cancel_code"` // 从可用取消原因列表接口返回结果选择(必填)
|
||||||
|
ActualCancelCostCent int64 `json:"actual_cancel_cost_cent"` // 单位分 取消实际需扣金额,从预取消接口拿(非必填)
|
||||||
|
OrderCancelOtherReason string `json:"order_cancel_other_reason"` // 取消原因补充 20字以内(非必填)
|
||||||
|
OrderCancelRole int `json:"order_cancel_role"` // 1商户取消, 2 用户取消(必填)
|
||||||
|
}
|
||||||
|
|
||||||
|
//#endregion
|
||||||
|
|
||||||
|
//#region 投诉订单
|
||||||
|
|
||||||
|
// complaintOrder投诉订单
|
||||||
|
type ComplaintOrderReq struct {
|
||||||
|
GetOrderDetailReq
|
||||||
|
OrderComplaintCode int `json:"order_complaint_code"` // 投诉编码 230:其他, 150:未保持餐品完整, 160:服务态度恶劣, 190:额外索取费用,170:诱导收货人或商户退单, 140:提前点击送达,210:虚假标记异常, 220:少餐错餐,200:虚假配送, 130:未进行配送(必填)
|
||||||
|
OrderComplaintDesc string `json:"order_complaint_desc"` // 投诉原因描述(否)
|
||||||
|
}
|
||||||
|
|
||||||
|
// claimOrder 索赔订单
|
||||||
|
type ClaimOrderRes struct {
|
||||||
|
GetOrderDetailReq
|
||||||
|
OrderClaimCode int `json:"order_claim_code"` // 索赔编码150: 未保持餐品完整,160: 服务态度恶劣, 170: 诱导收货人或商户退单,210:虚假标记异常, 130: 骑手接单后未完成配送,320:少餐错餐, 190:额外索取费用,140:提前点击送达, 200:骑手点击配送成功,实际未配送
|
||||||
|
OrderClaimDesc string `json:"order_claim_desc"` // 投诉原因描述
|
||||||
|
OrderClaimPriceCent int64 `json:"order_claim_price_cent"` // 索赔金额 分
|
||||||
|
OrderClaimSku []*OrderClaimSkuDto `json:"order_claim_sku"` // 索赔明细
|
||||||
|
}
|
||||||
|
|
||||||
|
// 索赔明细
|
||||||
|
type OrderClaimSkuDto struct {
|
||||||
|
ClaimSkuName string `json:"claim_sku_name"` // 索赔商品名称
|
||||||
|
ClaimSkuGoodsCount string `json:"claim_sku_goods_count"` // 索赔商品数量
|
||||||
|
ClaimSkuPriceCent string `json:"claim_sku_price_cent"` // 索赔商品实际单价 分
|
||||||
|
ClaimSkuTotalPriceCent string `json:"claim_sku_total_price_cent"` // 索赔商品实际总价 分
|
||||||
|
}
|
||||||
|
|
||||||
|
//#endregion
|
||||||
|
|
||||||
|
//#endregion
|
||||||
@@ -1,12 +1,11 @@
|
|||||||
package fnpsapi
|
package fnpsapi
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"crypto/md5"
|
"crypto/sha256"
|
||||||
|
"encoding/hex"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"fmt"
|
"fmt"
|
||||||
"math/rand"
|
|
||||||
"net/http"
|
"net/http"
|
||||||
"net/url"
|
|
||||||
"sort"
|
"sort"
|
||||||
"strings"
|
"strings"
|
||||||
"sync"
|
"sync"
|
||||||
@@ -25,126 +24,125 @@ const (
|
|||||||
tokenAction = "get_access_token"
|
tokenAction = "get_access_token"
|
||||||
)
|
)
|
||||||
|
|
||||||
type API struct {
|
|
||||||
accessToken string
|
|
||||||
appID string
|
|
||||||
appSecret string
|
|
||||||
locker sync.RWMutex
|
|
||||||
client *http.Client
|
|
||||||
config *platformapi.APIConfig
|
|
||||||
}
|
|
||||||
|
|
||||||
func (a *API) SetToken(token string) {
|
func (a *API) SetToken(token string) {
|
||||||
a.locker.Lock()
|
a.locker.Lock()
|
||||||
defer a.locker.Unlock()
|
defer a.locker.Unlock()
|
||||||
a.accessToken = token
|
a.accessToken = token
|
||||||
}
|
}
|
||||||
|
|
||||||
func New(appID, appSecret string, config ...*platformapi.APIConfig) *API {
|
func (a *API) MakeFnRequestHead() map[string]interface{} {
|
||||||
|
requestParam := make(map[string]interface{}, 6)
|
||||||
|
requestParam["access_token"] = a.accessToken
|
||||||
|
requestParam["signature"] = a.signature
|
||||||
|
requestParam["merchant_id"] = a.merchantId
|
||||||
|
requestParam["version"] = a.version
|
||||||
|
requestParam["app_id"] = a.appID
|
||||||
|
requestParam["timestamp"] = a.timestamp
|
||||||
|
return requestParam
|
||||||
|
}
|
||||||
|
func New(appID, appSecret, merchantId, code string, config ...*platformapi.APIConfig) *API {
|
||||||
curConfig := platformapi.DefAPIConfig
|
curConfig := platformapi.DefAPIConfig
|
||||||
if len(config) > 0 {
|
if len(config) > 0 {
|
||||||
curConfig = *config[0]
|
curConfig = *config[0]
|
||||||
}
|
}
|
||||||
return &API{
|
return &API{
|
||||||
appID: appID,
|
grantType: "authorization_code", // 授权模式,填固定值authorization_code
|
||||||
appSecret: appSecret,
|
code: code,
|
||||||
client: &http.Client{Timeout: curConfig.ClientTimeout},
|
appID: appID,
|
||||||
config: &curConfig,
|
merchantId: merchantId,
|
||||||
|
signature: "",
|
||||||
|
timestamp: time.Now().UnixNano(),
|
||||||
|
accessToken: "",
|
||||||
|
version: "1.0",
|
||||||
|
appSecret: appSecret,
|
||||||
|
locker: sync.RWMutex{},
|
||||||
|
client: &http.Client{Timeout: curConfig.ClientTimeout},
|
||||||
|
config: &curConfig,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a *API) signParam(params map[string]interface{}) (sig string) {
|
func (a *API) signParam(params map[string]interface{}) (sig string) {
|
||||||
var valueList []string
|
var valueList []string
|
||||||
for k, v := range params {
|
for k, v := range params {
|
||||||
if k != sigKey {
|
if k != "signature" {
|
||||||
if str := fmt.Sprint(v); str != "" {
|
if str := fmt.Sprint(v); str != "" {
|
||||||
valueList = append(valueList, fmt.Sprintf("%s=%s", k, str))
|
valueList = append(valueList, fmt.Sprintf("%s=%s", k, str))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
sort.Sort(sort.StringSlice(valueList))
|
sort.Sort(sort.StringSlice(valueList))
|
||||||
valueList = append(valueList, fmt.Sprintf("secret_key=%s", a.appSecret))
|
|
||||||
sig = strings.Join(valueList, "&")
|
sig = strings.Join(valueList, "&")
|
||||||
binSig := md5.Sum([]byte(url.QueryEscape(sig)))
|
sig = a.appSecret + sig
|
||||||
sig = fmt.Sprintf("%x", binSig)
|
signature := sha256.Sum256([]byte(sig))
|
||||||
return sig
|
return hex.EncodeToString(signature[:])
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a *API) signParam2(params map[string]interface{}) (sig string) {
|
func (a *API) AccessAPI(baseUrl, actionApi, method string, bizParams map[string]interface{}) (retVal map[string]interface{}, err error) {
|
||||||
sb := new(strings.Builder)
|
a.signature = a.signParam(bizParams)
|
||||||
sb.WriteString("app_id=")
|
bizParams["signature"] = a.signature
|
||||||
sb.WriteString(a.appID)
|
// 序列化
|
||||||
sb.WriteString("&access_token=")
|
data, err := json.Marshal(bizParams)
|
||||||
sb.WriteString(a.accessToken)
|
if err != nil {
|
||||||
sb.WriteString("&data=")
|
return nil, err
|
||||||
sb.WriteString(params["data"].(string))
|
|
||||||
sb.WriteString("&salt=")
|
|
||||||
sb.WriteString(utils.Int64ToStr(utils.MustInterface2Int64(params["salt"])))
|
|
||||||
sig = sb.String()
|
|
||||||
binSig := md5.Sum([]byte(sig))
|
|
||||||
sig = fmt.Sprintf("%x", binSig)
|
|
||||||
return sig
|
|
||||||
}
|
|
||||||
|
|
||||||
func (a *API) AccessAPI(action string, url string, bizParams map[string]interface{}, isPost bool) (retVal map[string]interface{}, err error) {
|
|
||||||
params := make(map[string]interface{})
|
|
||||||
params["salt"] = GetSalt()
|
|
||||||
params["app_id"] = a.appID
|
|
||||||
if action != tokenAction {
|
|
||||||
data, _ := json.Marshal(bizParams)
|
|
||||||
params["data"] = string(data)
|
|
||||||
signStr := a.signParam2(params)
|
|
||||||
params[sigKey] = signStr
|
|
||||||
} else {
|
|
||||||
signStr := a.signParam(params)
|
|
||||||
params[sigKey] = signStr
|
|
||||||
}
|
}
|
||||||
data, _ := json.Marshal(params)
|
|
||||||
fullURL := utils.GenerateGetURL(url, action, nil)
|
// 全路径请求参数
|
||||||
err = platformapi.AccessPlatformAPIWithRetry(a.client,
|
fullURL := utils.GenerateGetURL(baseUrl, actionApi, nil)
|
||||||
func() *http.Request {
|
|
||||||
var request *http.Request
|
// 发送请求
|
||||||
if isPost {
|
sendUrl := func() *http.Request {
|
||||||
request, _ = http.NewRequest(http.MethodPost, fullURL, strings.NewReader(string(data)))
|
var request *http.Request
|
||||||
} else {
|
if RequestPost == method {
|
||||||
request, _ = http.NewRequest(http.MethodGet, utils.GenerateGetURL(url, action, params), nil)
|
request, _ = http.NewRequest(http.MethodPost, fullURL, strings.NewReader(string(data)))
|
||||||
}
|
} else {
|
||||||
request.Header.Set("Content-Type", "application/json")
|
request, _ = http.NewRequest(http.MethodGet, utils.GenerateGetURL(baseUrl, actionApi, bizParams), nil)
|
||||||
return request
|
}
|
||||||
},
|
request.Header.Set("Content-Type", "application/json")
|
||||||
a.config,
|
return request
|
||||||
func(response *http.Response, bodyStr string, jsonResult1 map[string]interface{}) (errLevel string, err error) {
|
}
|
||||||
if jsonResult1 == nil {
|
|
||||||
return platformapi.ErrLevelRecoverableErr, fmt.Errorf("mapData is nil")
|
// 数据解析
|
||||||
}
|
dataMarshal := func(response *http.Response, bodyStr string, jsonResult1 map[string]interface{}) (errLevel string, err error) {
|
||||||
if err == nil {
|
if jsonResult1 == nil {
|
||||||
if utils.MustInterface2Int64(jsonResult1["code"]) != 200 {
|
return platformapi.ErrLevelRecoverableErr, fmt.Errorf("mapData is nil")
|
||||||
errLevel = platformapi.ErrLevelGeneralFail
|
}
|
||||||
err = utils.NewErrorCode(jsonResult1["msg"].(string), utils.Int64ToStr(utils.MustInterface2Int64(jsonResult1["code"])))
|
if err != nil {
|
||||||
baseapi.SugarLogger.Debugf("fnps AccessAPI failed, jsonResult1:%s", utils.Format4Output(jsonResult1, true))
|
return "", err
|
||||||
}
|
}
|
||||||
retVal = jsonResult1
|
if utils.MustInterface2Int64(jsonResult1["code"]) != 200 {
|
||||||
}
|
errLevel = platformapi.ErrLevelGeneralFail
|
||||||
return errLevel, err
|
err = utils.NewErrorCode(jsonResult1["msg"].(string), utils.Int64ToStr(utils.MustInterface2Int64(jsonResult1["code"])))
|
||||||
})
|
baseapi.SugarLogger.Debugf("fnps AccessAPI failed, jsonResult1:%s", utils.Format4Output(jsonResult1, true))
|
||||||
|
}
|
||||||
|
retVal = jsonResult1
|
||||||
|
return errLevel, err
|
||||||
|
}
|
||||||
|
|
||||||
|
err = platformapi.AccessPlatformAPIWithRetry(a.client, sendUrl, a.config, dataMarshal)
|
||||||
return retVal, err
|
return retVal, err
|
||||||
}
|
}
|
||||||
|
|
||||||
func GetSalt() (salt int) {
|
// 获取access_token
|
||||||
rand.Seed(time.Now().UnixNano())
|
|
||||||
return rand.Intn(8999) + 1000
|
|
||||||
}
|
|
||||||
|
|
||||||
type TokenInfo struct {
|
|
||||||
AccessToken string `json:"access_token"`
|
|
||||||
AppID string `json:"app_id"`
|
|
||||||
ExpireTime int64 `json:"expire_time"`
|
|
||||||
}
|
|
||||||
|
|
||||||
func (a *API) GetAccessToken() (tokenInfo *TokenInfo, err error) {
|
func (a *API) GetAccessToken() (tokenInfo *TokenInfo, err error) {
|
||||||
result, err := a.AccessAPI(tokenAction, URL, nil, false)
|
parameter := make(map[string]interface{}, 6)
|
||||||
if err == nil {
|
parameter["grant_type"] = a.grantType
|
||||||
utils.Map2StructByJson(result["data"], &tokenInfo, false)
|
parameter["code"] = a.code
|
||||||
|
parameter["app_id"] = a.appID
|
||||||
|
parameter["merchant_id"] = a.merchantId
|
||||||
|
parameter["timestamp"] = utils.Int64ToStr(a.timestamp)
|
||||||
|
|
||||||
|
result, err := a.AccessAPI(TokenURL, "", RequestPost, parameter)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
}
|
}
|
||||||
|
if err := utils.Map2StructByJson(result, &tokenInfo, false); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
businessData := &BusinessData{}
|
||||||
|
if err := json.Unmarshal([]byte(utils.Interface2String(result["business_data"])), businessData); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
tokenInfo.BusinessDataObj = businessData
|
||||||
return tokenInfo, err
|
return tokenInfo, err
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,102 +1,299 @@
|
|||||||
package fnpsapi
|
package fnpsapi
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"encoding/json"
|
||||||
|
"errors"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"git.rosy.net.cn/baseapi/utils"
|
"git.rosy.net.cn/baseapi/utils"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
OrderCancelReson1 = 1 // 1:物流原因:订单长时间未分配骑手,
|
OrderCancelReson0 = 0 // 0:其它(必填原因)必须填写原因
|
||||||
OrderCancelReson2 = 2 // 2:物流原因:分配骑手后,骑手长时间未取件 ,
|
OrderCancelReson1 = 1 // 1:物流原因:订单长时间未分配骑手
|
||||||
OrderCancelReson3 = 3 // 3:物流原因:骑手告知不配送,让取消订单,
|
|
||||||
OrderCancelReson4 = 4 // 4:商品缺货/无法出货/已售完,
|
OrderCancelReson4 = 4 // 4:商品缺货/无法出货/已售完,
|
||||||
OrderCancelReson5 = 5 // 5:商户联系不上门店/门店关门了,
|
|
||||||
OrderCancelReson6 = 6 // 6:商户发错单,
|
OrderCancelReson6 = 6 // 6:商户发错单,
|
||||||
OrderCancelReson7 = 7 // 7:商户/顾客自身定位错误,
|
OrderCancelReson7 = 7 // 7:商户/顾客自身定位错误,
|
||||||
OrderCancelReson8 = 8 // 8:商户改其他第三方配送,
|
OrderCancelReson8 = 8 // 8:商户改其他第三方配送,
|
||||||
OrderCancelReson9 = 9 // 9:顾客下错单/临时不想要了,
|
OrderCancelReson9 = 9 // 9:顾客下错单/临时不想要了,
|
||||||
OrderCancelReson10 = 10 // 10:顾客自取/不在家/要求另改时间配送)(0类型已下线)
|
OrderCancelReson10 = 10 // 10:顾客自取/不在家/要求另改时间配送)(0类型已下线)
|
||||||
|
OrderCancelReson32 = 32 // 32:订单信息填写错误
|
||||||
|
OrderCancelReson36 = 36 // 36:重复下单了
|
||||||
|
OrderCancelReson2 = 2 // 2:物流原因:分配骑手后,骑手长时间未取件(类型已下线)
|
||||||
|
OrderCancelReson3 = 3 // 3:物流原因:骑手告知不配送,让取消订单(类型已下线)
|
||||||
|
OrderCancelReson5 = 5 // 5:商户联系不上门店/门店关门了(类型已下线)
|
||||||
|
|
||||||
OrderStatusAccept = 1 //系统已接单
|
OrderStatusAcceptCreate = 0 //订单生成
|
||||||
OrderStatusAssigned = 20 //已分配骑手
|
OrderStatusAcceptCacle = 4 //订单取消
|
||||||
OrderStatusArrived = 80 //已到店
|
OrderStatusAccept = 1 //系统已接单
|
||||||
OrderStatusDelivering = 2 //配送中
|
OrderStatusAssigned = 20 //已分配骑手
|
||||||
OrderStatusDelivered = 3 //已送达
|
OrderStatusArrived = 80 //已到店
|
||||||
OrderStatusException = 5 //异常
|
OrderStatusDelivering = 2 //配送中
|
||||||
|
OrderStatusDelivered = 3 //已送达
|
||||||
|
OrderStatusException = 5 //异常
|
||||||
)
|
)
|
||||||
|
|
||||||
type CreateOrderParam struct {
|
//
|
||||||
PartnerRemark string `json:"partner_remark,omitempty"`
|
//type CreateOrderParam struct {
|
||||||
PartnerOrderCode string `json:"partner_order_code,omitempty"`
|
// PartnerRemark string `json:"partner_remark,omitempty"`
|
||||||
NotifyURL string `json:"notify_url,omitempty"`
|
// PartnerOrderCode string `json:"partner_order_code,omitempty"`
|
||||||
OrderType int `json:"order_type,omitempty"`
|
// NotifyURL string `json:"notify_url,omitempty"`
|
||||||
ChainStoreCode string `json:"chain_store_code,omitempty"`
|
// OrderType int `json:"order_type,omitempty"`
|
||||||
TransportInfo *TransportInfo `json:"transport_info,omitempty"`
|
// ChainStoreCode string `json:"chain_store_code,omitempty"`
|
||||||
OrderAddTime int64 `json:"order_add_time,omitempty"`
|
// TransportInfo *TransportInfo `json:"transport_info,omitempty"`
|
||||||
OrderTotalAmount float64 `json:"order_total_amount,omitempty"`
|
// OrderAddTime int64 `json:"order_add_time,omitempty"`
|
||||||
OrderActualAmount float64 `json:"order_actual_amount,omitempty"`
|
// OrderTotalAmount float64 `json:"order_total_amount,omitempty"`
|
||||||
OrderWeight float64 `json:"order_weight,omitempty"`
|
// OrderActualAmount float64 `json:"order_actual_amount,omitempty"`
|
||||||
OrderRemark string `json:"order_remark,omitempty"`
|
// OrderWeight float64 `json:"order_weight,omitempty"`
|
||||||
IsInvoiced int `json:"is_invoiced"`
|
// OrderRemark string `json:"order_remark,omitempty"`
|
||||||
Invoice string `json:"invoice,omitempty"`
|
// IsInvoiced int `json:"is_invoiced"`
|
||||||
OrderPaymentStatus int `json:"order_payment_status,omitempty"`
|
// Invoice string `json:"invoice,omitempty"`
|
||||||
OrderPaymentMethod int `json:"order_payment_method,omitempty"`
|
// OrderPaymentStatus int `json:"order_payment_status,omitempty"`
|
||||||
IsAgentPayment int `json:"is_agent_payment"`
|
// OrderPaymentMethod int `json:"order_payment_method,omitempty"`
|
||||||
RequirePaymentPay float64 `json:"require_payment_pay,omitempty"`
|
// IsAgentPayment int `json:"is_agent_payment"`
|
||||||
GoodsCount int `json:"goods_count,omitempty"`
|
// RequirePaymentPay float64 `json:"require_payment_pay,omitempty"`
|
||||||
RequireReceiveTime int64 `json:"require_receive_time,omitempty"`
|
// GoodsCount int `json:"goods_count,omitempty"`
|
||||||
SerialNumber string `json:"serial_number,omitempty"`
|
// RequireReceiveTime int64 `json:"require_receive_time,omitempty"`
|
||||||
ReceiverInfo *ReceiverInfo `json:"receiver_info,omitempty"`
|
// SerialNumber string `json:"serial_number,omitempty"`
|
||||||
ItemsJSON []*ItemsJSON `json:"items_json,omitempty"`
|
// ReceiverInfo *ReceiverInfo `json:"receiver_info,omitempty"`
|
||||||
OrderSource string `json:"order_source,omitempty"` //饿百订单传109
|
// ItemsJSON []*ItemsJSON `json:"items_json,omitempty"`
|
||||||
ChannelOrderCode string `json:"channel_order_code,omitempty"`
|
// OrderSource string `json:"order_source,omitempty"` //饿百订单传109
|
||||||
CookingTime int64 `json:"cooking_time,omitempty"`
|
// ChannelOrderCode string `json:"channel_order_code,omitempty"`
|
||||||
PlatformPaidTime int64 `json:"platform_paid_time,omitempty"`
|
// CookingTime int64 `json:"cooking_time,omitempty"`
|
||||||
PlatformCreatedTime int64 `json:"platform_created_time,omitempty"`
|
// PlatformPaidTime int64 `json:"platform_paid_time,omitempty"`
|
||||||
MerchantCode string `json:"merchant_code,omitempty"`
|
// PlatformCreatedTime int64 `json:"platform_created_time,omitempty"`
|
||||||
|
// MerchantCode string `json:"merchant_code,omitempty"`
|
||||||
|
//}
|
||||||
|
//
|
||||||
|
//type ReceiverInfo struct {
|
||||||
|
// ReceiverName string `json:"receiver_name,omitempty"`
|
||||||
|
// ReceiverPrimaryPhone string `json:"receiver_primary_phone,omitempty"`
|
||||||
|
// ReceiverSecondPhone string `json:"receiver_second_phone,omitempty"`
|
||||||
|
// ReceiverAddress string `json:"receiver_address,omitempty"`
|
||||||
|
// ReceiverLongitude float64 `json:"receiver_longitude,omitempty"`
|
||||||
|
// ReceiverLatitude float64 `json:"receiver_latitude,omitempty"`
|
||||||
|
// PositionSource int `json:"position_source,omitempty"`
|
||||||
|
//}
|
||||||
|
//
|
||||||
|
//type TransportInfo struct {
|
||||||
|
// TransportName string `json:"transport_name,omitempty"`
|
||||||
|
// TransportAddress string `json:"transport_address,omitempty"`
|
||||||
|
// TransportLongitude float64 `json:"transport_longitude,omitempty"`
|
||||||
|
// TransportLatitude float64 `json:"transport_latitude,omitempty"`
|
||||||
|
// PositionSource int `json:"position_source,omitempty"`
|
||||||
|
// TransportTel string `json:"transport_tel,omitempty"`
|
||||||
|
// TransportRemark string `json:"transport_remark,omitempty"`
|
||||||
|
//}
|
||||||
|
//
|
||||||
|
//type ItemsJSON struct {
|
||||||
|
// ItemID string `json:"item_id,omitempty"`
|
||||||
|
// ItemName string `json:"item_name,omitempty"`
|
||||||
|
// ItemQuantity int `json:"item_quantity,omitempty"`
|
||||||
|
// ItemPrice float64 `json:"item_price"`
|
||||||
|
// ItemActualPrice float64 `json:"item_actual_price"`
|
||||||
|
// ItemSize int `json:"item_size,omitempty"`
|
||||||
|
// ItemRemark string `json:"item_remark,omitempty"`
|
||||||
|
// IsNeedPackage int `json:"is_need_package"`
|
||||||
|
// IsAgentPurchase int `json:"is_agent_purchase"`
|
||||||
|
// AgentPurchasePrice float64 `json:"agent_purchase_price,omitempty"`
|
||||||
|
//}
|
||||||
|
|
||||||
|
// 蜂鸟预下单
|
||||||
|
func (a *API) PreCreateByShopFn(basicParams *PreCreateOrder) (deliveryFee, baseDeliveryFee int64, err error) {
|
||||||
|
preOrder := a.MakeFnRequestHead()
|
||||||
|
|
||||||
|
bytes, err := json.Marshal(basicParams)
|
||||||
|
if err != nil {
|
||||||
|
return 0, 0, err
|
||||||
|
}
|
||||||
|
preOrder["business_data"] = string(bytes)
|
||||||
|
result, err := a.AccessAPI(ApiURL, "preCreateOrder", RequestPost, preOrder)
|
||||||
|
if err != nil {
|
||||||
|
return 0, 0, err
|
||||||
|
}
|
||||||
|
|
||||||
|
preOrderResult := PreCreateOrderResp{}
|
||||||
|
if err := json.Unmarshal([]byte(result["business_data"].(string)), &preOrderResult); err != nil {
|
||||||
|
return 0, 0, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// 返回所有可选的商品列表,每项包含当前使用该商品下单时对应的价格等信息,(其中不可用的商品会返回不可用原因) 可挑选其中一个可用的商品进行正式下单。
|
||||||
|
for _, v := range preOrderResult.GoodsInfos {
|
||||||
|
if v.IsValid != 1 {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
deliveryFee = v.ActualDeliveryAmountCent
|
||||||
|
baseDeliveryFee = v.TotalDeliveryAmountCent
|
||||||
|
}
|
||||||
|
|
||||||
|
// 异常检测
|
||||||
|
if deliveryFee == 0 && baseDeliveryFee == 0 {
|
||||||
|
err = errors.New("门店数据异常")
|
||||||
|
}
|
||||||
|
return deliveryFee, baseDeliveryFee, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
type ReceiverInfo struct {
|
// 蜂鸟正式下单
|
||||||
ReceiverName string `json:"receiver_name,omitempty"`
|
func (a *API) CreateOrder(createOrderParam *CreateOrderReqParam) (err error) {
|
||||||
ReceiverPrimaryPhone string `json:"receiver_primary_phone,omitempty"`
|
orderHead := a.MakeFnRequestHead()
|
||||||
ReceiverSecondPhone string `json:"receiver_second_phone,omitempty"`
|
bytes, err := json.Marshal(createOrderParam)
|
||||||
ReceiverAddress string `json:"receiver_address,omitempty"`
|
if err != nil {
|
||||||
ReceiverLongitude float64 `json:"receiver_longitude,omitempty"`
|
return err
|
||||||
ReceiverLatitude float64 `json:"receiver_latitude,omitempty"`
|
}
|
||||||
PositionSource int `json:"position_source,omitempty"`
|
orderHead["business_data"] = string(bytes)
|
||||||
}
|
_, err = a.AccessAPI(ApiURL, "createOrder", RequestPost, orderHead)
|
||||||
|
|
||||||
type TransportInfo struct {
|
|
||||||
TransportName string `json:"transport_name,omitempty"`
|
|
||||||
TransportAddress string `json:"transport_address,omitempty"`
|
|
||||||
TransportLongitude float64 `json:"transport_longitude,omitempty"`
|
|
||||||
TransportLatitude float64 `json:"transport_latitude,omitempty"`
|
|
||||||
PositionSource int `json:"position_source,omitempty"`
|
|
||||||
TransportTel string `json:"transport_tel,omitempty"`
|
|
||||||
TransportRemark string `json:"transport_remark,omitempty"`
|
|
||||||
}
|
|
||||||
|
|
||||||
type ItemsJSON struct {
|
|
||||||
ItemID string `json:"item_id,omitempty"`
|
|
||||||
ItemName string `json:"item_name,omitempty"`
|
|
||||||
ItemQuantity int `json:"item_quantity,omitempty"`
|
|
||||||
ItemPrice float64 `json:"item_price"`
|
|
||||||
ItemActualPrice float64 `json:"item_actual_price"`
|
|
||||||
ItemSize int `json:"item_size,omitempty"`
|
|
||||||
ItemRemark string `json:"item_remark,omitempty"`
|
|
||||||
IsNeedPackage int `json:"is_need_package"`
|
|
||||||
IsAgentPurchase int `json:"is_agent_purchase"`
|
|
||||||
AgentPurchasePrice float64 `json:"agent_purchase_price,omitempty"`
|
|
||||||
}
|
|
||||||
|
|
||||||
//https://open.ele.me/documents/%E5%88%9B%E5%BB%BA%E8%9C%82%E9%B8%9F%E8%AE%A2%E5%8D%95
|
|
||||||
func (a *API) CreateOrder(createOrderParam *CreateOrderParam) (err error) {
|
|
||||||
params := utils.Struct2FlatMap(createOrderParam)
|
|
||||||
_, err = a.AccessAPI("v2/order", URL, params, true)
|
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// addTip 加小费接口
|
||||||
|
func (a *API) AddTip(req *AddTipRes) (err error) {
|
||||||
|
if req.PartnerOrderCode == "" && req.OrderId == "" {
|
||||||
|
return errors.New("内部订单号或者外部订单号比填写一个")
|
||||||
|
}
|
||||||
|
|
||||||
|
orderHead := a.MakeFnRequestHead()
|
||||||
|
addTipString, err := json.Marshal(req)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
orderHead["businessData"] = string(addTipString)
|
||||||
|
if _, err = a.AccessAPI(ApiURL, "addTip", RequestPost, orderHead); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// getCancelReasonList 获取可用取消原因列表(暂油前端写死)
|
||||||
|
func (a *API) GetCancelReasonList(req *GetOrderDetailReq) (result *GetCancelReasonListRes, err error) {
|
||||||
|
if req.PartnerOrderCode == "" && req.OrderId == "" {
|
||||||
|
return nil, errors.New("内部订单号或者外部订单号比填写一个")
|
||||||
|
}
|
||||||
|
|
||||||
|
a.timestamp = time.Now().Unix() * 1000
|
||||||
|
orderHead := a.MakeFnRequestHead()
|
||||||
|
business, err := json.Marshal(req)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
orderHead["businessData"] = string(business)
|
||||||
|
data, err := a.AccessAPI(ApiURL, "getCancelReasonList", RequestPost, orderHead)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
cancel := make(map[string]*GetCancelReasonListRes, 0)
|
||||||
|
if k, ok := data["business_data"]; ok {
|
||||||
|
if err := json.Unmarshal([]byte(utils.Interface2String(k)), cancel); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return cancel["cancel_reason_list"], nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// preCancelOrder 预取消订单接口,获取取消订单需要扣除的金额
|
||||||
|
func (a *API) PreCancelOrder(req *PreCancelOrderReq) (actualCancelCostCent int64, err error) {
|
||||||
|
if req.PartnerOrderCode == "" && req.OrderId == "" {
|
||||||
|
return 0, errors.New("内部订单号或者外部订单号比填写一个")
|
||||||
|
}
|
||||||
|
orderHead := a.MakeFnRequestHead()
|
||||||
|
business, err := json.Marshal(req)
|
||||||
|
if err != nil {
|
||||||
|
return 0, err
|
||||||
|
}
|
||||||
|
orderHead["businessData"] = string(business)
|
||||||
|
|
||||||
|
data, err := a.AccessAPI(ApiURL, "preCancelOrder", RequestPost, orderHead)
|
||||||
|
if err != nil {
|
||||||
|
return 0, err
|
||||||
|
}
|
||||||
|
|
||||||
|
if k, ok := data["businessData"]; ok {
|
||||||
|
respParam := struct {
|
||||||
|
ActualCancelCostCent int64 `json:"actual_cancel_cost_cent"`
|
||||||
|
}{}
|
||||||
|
if err := json.Unmarshal([]byte(utils.Interface2String(k)), respParam); err != nil {
|
||||||
|
return 0, err
|
||||||
|
}
|
||||||
|
return respParam.ActualCancelCostCent, nil
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// cancelOrder 取消订单
|
||||||
|
func (a *API) CancelOrder(req *CancelOrderReq) (err error) {
|
||||||
|
if req.PartnerOrderCode == "" && req.OrderId == "" {
|
||||||
|
return errors.New("内部订单号或者外部订单号比填写一个")
|
||||||
|
}
|
||||||
|
if req.OrderCancelCode == 0 && req.OrderCancelOtherReason == "" {
|
||||||
|
return errors.New("请补充退单原因")
|
||||||
|
}
|
||||||
|
|
||||||
|
orderHead := a.MakeFnRequestHead()
|
||||||
|
business, err := json.Marshal(req)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
orderHead["business_data"] = string(business)
|
||||||
|
|
||||||
|
if _, err := a.AccessAPI(ApiURL, "cancelOrder", RequestPost, orderHead); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// 查询订单详情接口 todo
|
||||||
|
func (a *API) QueryOrder(partnerOrderCode string) (result *GetOrderDetailRes, err error) {
|
||||||
|
orderHead := a.MakeFnRequestHead()
|
||||||
|
orderHead["business_data"] = partnerOrderCode
|
||||||
|
|
||||||
|
data, err := a.AccessAPI(ApiURL, "getOrderDetail", RequestPost, orderHead)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := json.Unmarshal([]byte(data["business_data"].(string)), &result); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// 查询骑手信息
|
||||||
|
func (a *API) GetKnightInfo(req *GetOrderDetailReq) (result *GetKnightInfoRes, err error) {
|
||||||
|
if req.PartnerOrderCode == "" && req.OrderId == "" {
|
||||||
|
return nil, errors.New("内部订单号或者外部订单号比填写一个")
|
||||||
|
}
|
||||||
|
|
||||||
|
orderHead := a.MakeFnRequestHead()
|
||||||
|
bytes, err := json.Marshal(req)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
orderHead["business_data"] = string(bytes)
|
||||||
|
|
||||||
|
data, err := a.AccessAPI(ApiURL, "getKnightInfo", RequestPost, orderHead)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := json.Unmarshal([]byte(utils.Interface2String(data["business_data"])), &result); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// 余额查询
|
||||||
|
func (a *API) GetAmount() (outAmount map[string]interface{}, err error) {
|
||||||
|
orderHead := a.MakeFnRequestHead()
|
||||||
|
result, err := a.AccessAPI(ApiURL, "getAmount", RequestPost, orderHead)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return result, err
|
||||||
|
}
|
||||||
|
|
||||||
//order_cancel_reason_code 订单取消原因代码(1:用户取消,2:商家取消)
|
//order_cancel_reason_code 订单取消原因代码(1:用户取消,2:商家取消)
|
||||||
// order_cancel_code 订单取消编码(
|
// order_cancel_code 订单取消编码(
|
||||||
// 1:物流原因:订单长时间未分配骑手,
|
// 1:物流原因:订单长时间未分配骑手,
|
||||||
@@ -106,70 +303,69 @@ func (a *API) CreateOrder(createOrderParam *CreateOrderParam) (err error) {
|
|||||||
// 7:商户/顾客自身定位错误, 8:商户改其他第三方配送, 9:顾客下错单/临时不想要了,
|
// 7:商户/顾客自身定位错误, 8:商户改其他第三方配送, 9:顾客下错单/临时不想要了,
|
||||||
// 10:顾客自取/不在家/要求另改时间配送)(0类型已下线)
|
// 10:顾客自取/不在家/要求另改时间配送)(0类型已下线)
|
||||||
|
|
||||||
type CancelOrderParam struct {
|
//type CancelOrderParam struct {
|
||||||
PartnerOrderCode string `json:"partner_order_code,omitempty"`
|
// PartnerOrderCode string `json:"partner_order_code,omitempty"`
|
||||||
OrderCancelReasonCode int `json:"order_cancel_reason_code,omitempty"`
|
// OrderCancelReasonCode int `json:"order_cancel_reason_code,omitempty"`
|
||||||
OrderCancelCode int `json:"order_cancel_code,omitempty"`
|
// OrderCancelCode int `json:"order_cancel_code,omitempty"`
|
||||||
OrderCancelDescription string `json:"order_cancel_description,omitempty"`
|
// OrderCancelDescription string `json:"order_cancel_description,omitempty"`
|
||||||
OrderCancelTime int64 `json:"order_cancel_time,omitempty"`
|
// OrderCancelTime int64 `json:"order_cancel_time,omitempty"`
|
||||||
}
|
//}
|
||||||
|
|
||||||
func (a *API) CancelOrder(cancelOrderParam *CancelOrderParam) (err error) {
|
func (a *API) ComplaintOrder(req *ComplaintOrderReq) (err error) {
|
||||||
params := utils.Struct2FlatMap(cancelOrderParam)
|
if req.PartnerOrderCode == "" && req.OrderId == "" {
|
||||||
_, err = a.AccessAPI("v2/order/cancel", URL, params, true)
|
return errors.New("内部订单号或者外部订单号比填写一个")
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
func (a *API) ComplaintOrder(cancelOrderParam *CancelOrderParam) (err error) {
|
|
||||||
params := utils.Struct2FlatMap(cancelOrderParam)
|
|
||||||
_, err = a.AccessAPI("v2/order/complaint", URL, params, true)
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
type QueryOrderResult struct {
|
|
||||||
AbnormalCode string `json:"abnormal_code"`
|
|
||||||
AbnormalDesc string `json:"abnormal_desc"`
|
|
||||||
CarrierDriverID int `json:"carrier_driver_id"`
|
|
||||||
CarrierDriverName string `json:"carrier_driver_name"`
|
|
||||||
CarrierDriverPhone string `json:"carrier_driver_phone"`
|
|
||||||
ComplaintDescription interface{} `json:"complaintDescription"`
|
|
||||||
ComplaintStatus interface{} `json:"complaintStatus"`
|
|
||||||
EstimateArriveTime int64 `json:"estimate_arrive_time"`
|
|
||||||
EventLogDetails []struct {
|
|
||||||
CarrierDriverName string `json:"carrier_driver_name"`
|
|
||||||
CarrierDriverPhone string `json:"carrier_driver_phone"`
|
|
||||||
OccurTime int64 `json:"occur_time"`
|
|
||||||
OrderStatus int `json:"order_status"`
|
|
||||||
} `json:"event_log_details"`
|
|
||||||
HandleID interface{} `json:"handleId"`
|
|
||||||
OrderID interface{} `json:"orderId"`
|
|
||||||
OrderStatus int `json:"order_status"`
|
|
||||||
OrderTotalDeliveryCost float64 `json:"order_total_delivery_cost"`
|
|
||||||
OrderTotalDeliveryDiscount interface{} `json:"order_total_delivery_discount"`
|
|
||||||
OvertimeCompensationCost float64 `json:"overtime_compensation_cost"`
|
|
||||||
Reason string `json:"reason"`
|
|
||||||
SupportClaims bool `json:"support_claims"`
|
|
||||||
TrackingID int64 `json:"trackingId"`
|
|
||||||
TrackingID2 int64 `json:"tracking_id"`
|
|
||||||
TransportStationID string `json:"transport_station_id"`
|
|
||||||
TransportStationTel string `json:"transport_station_tel"`
|
|
||||||
}
|
|
||||||
|
|
||||||
func (a *API) QueryOrder(partnerOrderCode string) (queryOrderResult *QueryOrderResult, err error) {
|
|
||||||
result, err := a.AccessAPI("v2/order/query", URL, map[string]interface{}{
|
|
||||||
"partner_order_code": partnerOrderCode,
|
|
||||||
}, true)
|
|
||||||
if err == nil {
|
|
||||||
utils.Map2StructByJson(result["data"], &queryOrderResult, false)
|
|
||||||
}
|
}
|
||||||
return queryOrderResult, err
|
orderHead := a.MakeFnRequestHead()
|
||||||
|
bytes, err := json.Marshal(req)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
orderHead["businessData"] = string(bytes)
|
||||||
|
_, err = a.AccessAPI(ApiURL, "cancelOrder", RequestPost, orderHead)
|
||||||
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
//type QueryOrderResult struct {
|
||||||
|
// AbnormalCode string `json:"abnormal_code"`
|
||||||
|
// AbnormalDesc string `json:"abnormal_desc"`
|
||||||
|
// CarrierDriverID int `json:"carrier_driver_id"`
|
||||||
|
// CarrierDriverName string `json:"carrier_driver_name"`
|
||||||
|
// CarrierDriverPhone string `json:"carrier_driver_phone"`
|
||||||
|
// ComplaintDescription interface{} `json:"complaintDescription"`
|
||||||
|
// ComplaintStatus interface{} `json:"complaintStatus"`
|
||||||
|
// EstimateArriveTime int64 `json:"estimate_arrive_time"`
|
||||||
|
// EventLogDetails []struct {
|
||||||
|
// CarrierDriverName string `json:"carrier_driver_name"`
|
||||||
|
// CarrierDriverPhone string `json:"carrier_driver_phone"`
|
||||||
|
// OccurTime int64 `json:"occur_time"`
|
||||||
|
// OrderStatus int `json:"order_status"`
|
||||||
|
// } `json:"event_log_details"`
|
||||||
|
// HandleID interface{} `json:"handleId"`
|
||||||
|
// OrderID interface{} `json:"orderId"`
|
||||||
|
// OrderStatus int `json:"order_status"`
|
||||||
|
// OrderTotalDeliveryCost float64 `json:"order_total_delivery_cost"`
|
||||||
|
// OrderTotalDeliveryDiscount interface{} `json:"order_total_delivery_discount"`
|
||||||
|
// OvertimeCompensationCost float64 `json:"overtime_compensation_cost"`
|
||||||
|
// Reason string `json:"reason"`
|
||||||
|
// SupportClaims bool `json:"support_claims"`
|
||||||
|
// TrackingID int64 `json:"trackingId"`
|
||||||
|
// TrackingID2 int64 `json:"tracking_id"`
|
||||||
|
// TransportStationID string `json:"transport_station_id"`
|
||||||
|
// TransportStationTel string `json:"transport_station_tel"`
|
||||||
|
//}
|
||||||
|
|
||||||
func (a *API) ComplaintRider(partnerOrderCode string, orderComplaintCode int) (err error) {
|
func (a *API) ComplaintRider(partnerOrderCode string, orderComplaintCode int) (err error) {
|
||||||
_, err = a.AccessAPI("v2/order/complaint", URL, map[string]interface{}{
|
orderHead := a.MakeFnRequestHead()
|
||||||
|
|
||||||
|
bytes, err := json.Marshal(map[string]interface{}{
|
||||||
"partner_order_code": partnerOrderCode,
|
"partner_order_code": partnerOrderCode,
|
||||||
"order_complaint_code": orderComplaintCode,
|
"order_complaint_code": orderComplaintCode,
|
||||||
"order_complaint_time": time.Now().UnixNano() / 1e6,
|
})
|
||||||
}, true)
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
orderHead["businessData"] = string(bytes)
|
||||||
|
_, err = a.AccessAPI(ApiURL, "cancelOrder", RequestPost, orderHead)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
package fnpsapi
|
package fnpsapi
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"encoding/json"
|
||||||
"fmt"
|
"fmt"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
@@ -12,24 +13,51 @@ const (
|
|||||||
StoreExist = "该门店已存在"
|
StoreExist = "该门店已存在"
|
||||||
)
|
)
|
||||||
|
|
||||||
type CreateStoreParam struct {
|
const (
|
||||||
ChainStoreCode string `json:"chain_store_code,omitempty"`
|
// 创建状态
|
||||||
ChainStoreName string `json:"chain_store_name,omitempty"`
|
ShopCreateStatusAuditRejected = 10 // 上架审核中
|
||||||
ChainStoreType int `json:"chain_store_type,omitempty"`
|
ShopCreateStatusAuditPassed = 20 // 正常(已上架)
|
||||||
MerchantCode string `json:"merchant_code,omitempty"`
|
ShopCreateStatusAuditCreated = 30 // 上架审核失败
|
||||||
ContactPhone string `json:"contact_phone,omitempty"`
|
ShopCreateStatusAuditOnline = 40 // 已冻结
|
||||||
Address string `json:"address,omitempty"`
|
ShopCreateStatusAuditUpdateRejected = 50 // 已下架
|
||||||
PositionSource int `json:"position_source,omitempty"`
|
// 修改状态
|
||||||
Longitude string `json:"longitude,omitempty"`
|
ShopUpdateStatusAuditRejected = 0 // 无修改
|
||||||
Latitude string `json:"latitude,omitempty"`
|
ShopUpdateStatusAuditPassed = 10 // 资料修改审核中
|
||||||
ServiceCode string `json:"service_code,omitempty"`
|
ShopUpdateStatusAuditCreated = 20 // 审核通过
|
||||||
|
ShopUpdateStatusAuditOnline = 30 // 审核驳回
|
||||||
|
)
|
||||||
|
|
||||||
|
func (a *API) CreateStore(createStoreParam *CreateStoreBaseInfo) (result1 string, err error) {
|
||||||
|
requestHead := a.MakeFnRequestHead()
|
||||||
|
storeByte, err := json.Marshal(createStoreParam)
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
requestHead["business_data"] = string(storeByte)
|
||||||
|
result, err := a.AccessAPI(ApiURL, "chainstoreCreate", RequestPost, requestHead)
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
|
||||||
|
createShop := struct {
|
||||||
|
ChainStoreId string `json:"chain_store_id"`
|
||||||
|
}{}
|
||||||
|
if err := json.Unmarshal([]byte(utils.Interface2String(result["business_data"])), &createShop); err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
|
||||||
|
return createShop.ChainStoreId, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a *API) CreateStore(createStoreParam *CreateStoreParam) (err error) {
|
func (a *API) UpdateStore(updateStore *UpdateStoreParam) (err error) {
|
||||||
createStoreParam.ServiceCode = "1"
|
requestHead := a.MakeFnRequestHead()
|
||||||
params := utils.Struct2FlatMap(createStoreParam)
|
storeByte, err := json.Marshal(updateStore)
|
||||||
_, err = a.AccessAPI("v2/chain_store", URL, params, true)
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
|
}
|
||||||
|
requestHead["business_data"] = string(storeByte)
|
||||||
|
_, err = a.AccessAPI(ApiURL, "chainstoreUpdate", RequestPost, requestHead)
|
||||||
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
type GetStoreResult struct {
|
type GetStoreResult struct {
|
||||||
@@ -46,15 +74,41 @@ type GetStoreResult struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
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", RequestPost, paramsMap)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
if result["code"] != "200" {
|
||||||
|
return nil, fmt.Errorf("%s", result["msg"])
|
||||||
|
}
|
||||||
|
|
||||||
|
if storeData, ok := result["business_data"]; ok {
|
||||||
|
if err := json.Unmarshal([]byte(utils.Interface2String(storeData)), &getStoreResult); err != nil {
|
||||||
|
return nil, err
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
err = fmt.Errorf(result["msg"].(string))
|
||||||
}
|
}
|
||||||
return getStoreResult, err
|
return getStoreResult, err
|
||||||
}
|
}
|
||||||
@@ -76,9 +130,3 @@ func IsErrShopExist(err error) bool {
|
|||||||
}
|
}
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a *API) UpdateStore(createStoreParam *CreateStoreParam) (err error) {
|
|
||||||
params := utils.Struct2FlatMap(createStoreParam)
|
|
||||||
_, err = a.AccessAPI("v2/chain_store/update", URL, params, true)
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|||||||
54
platformapi/fnpsapi_old/callback.go
Normal file
54
platformapi/fnpsapi_old/callback.go
Normal file
@@ -0,0 +1,54 @@
|
|||||||
|
package fnpsapi
|
||||||
|
|
||||||
|
import (
|
||||||
|
"net/url"
|
||||||
|
|
||||||
|
"git.rosy.net.cn/jx-callback/globals"
|
||||||
|
|
||||||
|
"git.rosy.net.cn/baseapi/utils"
|
||||||
|
)
|
||||||
|
|
||||||
|
type CallBackInfo struct {
|
||||||
|
AppID string `json:"app_id"`
|
||||||
|
Data string `json:"data"`
|
||||||
|
Salt int `json:"salt"`
|
||||||
|
Signature string `json:"signature"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type WayBillInfo struct {
|
||||||
|
PartnerOrderCode string `json:"partner_order_code"`
|
||||||
|
OrderStatus int `json:"order_status"`
|
||||||
|
PushTime int64 `json:"push_time"`
|
||||||
|
CarrierDriverName string `json:"carrier_driver_name"`
|
||||||
|
CarrierDriverPhone string `json:"carrier_driver_phone"`
|
||||||
|
OpenOrderCode int64 `json:"open_order_code"`
|
||||||
|
PlatformCode string `json:"platform_code"`
|
||||||
|
ErrorScene string `json:"error_scene"`
|
||||||
|
Description string `json:"description"`
|
||||||
|
ErrorCode string `json:"error_code"`
|
||||||
|
DetailDescription string `json:"detail_description"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a *API) GetOrderCallbackMsg(data []byte) (orderMsg *WayBillInfo) {
|
||||||
|
callbackInfo := &CallBackInfo{}
|
||||||
|
err := utils.UnmarshalUseNumber(data, callbackInfo)
|
||||||
|
if err != nil {
|
||||||
|
globals.SugarLogger.Debugf("fn msg faild %v, err : %v", string(data), err)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
if err == nil {
|
||||||
|
if str, err := url.QueryUnescape(callbackInfo.Data); err == nil {
|
||||||
|
orderMsg = &WayBillInfo{}
|
||||||
|
if err := utils.UnmarshalUseNumber([]byte(str), orderMsg); err == nil {
|
||||||
|
return orderMsg
|
||||||
|
} else {
|
||||||
|
globals.SugarLogger.Debugf("fn msg faild3 %v", err)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
globals.SugarLogger.Debugf("fn msg faild2 %v", err)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return orderMsg
|
||||||
|
}
|
||||||
150
platformapi/fnpsapi_old/fnpsapi.go
Normal file
150
platformapi/fnpsapi_old/fnpsapi.go
Normal file
@@ -0,0 +1,150 @@
|
|||||||
|
package fnpsapi
|
||||||
|
|
||||||
|
import (
|
||||||
|
"crypto/md5"
|
||||||
|
"encoding/json"
|
||||||
|
"fmt"
|
||||||
|
"math/rand"
|
||||||
|
"net/http"
|
||||||
|
"net/url"
|
||||||
|
"sort"
|
||||||
|
"strings"
|
||||||
|
"sync"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"git.rosy.net.cn/baseapi"
|
||||||
|
"git.rosy.net.cn/baseapi/platformapi"
|
||||||
|
"git.rosy.net.cn/baseapi/utils"
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
sigKey = "signature"
|
||||||
|
|
||||||
|
TestURL = "https://exam-anubis.ele.me/anubis-webapi"
|
||||||
|
URL = "https://open-anubis.ele.me/anubis-webapi"
|
||||||
|
tokenAction = "get_access_token"
|
||||||
|
)
|
||||||
|
|
||||||
|
type API struct {
|
||||||
|
accessToken string
|
||||||
|
appID string
|
||||||
|
appSecret string
|
||||||
|
locker sync.RWMutex
|
||||||
|
client *http.Client
|
||||||
|
config *platformapi.APIConfig
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a *API) SetToken(token string) {
|
||||||
|
a.locker.Lock()
|
||||||
|
defer a.locker.Unlock()
|
||||||
|
a.accessToken = token
|
||||||
|
}
|
||||||
|
|
||||||
|
func New(appID, appSecret string, config ...*platformapi.APIConfig) *API {
|
||||||
|
curConfig := platformapi.DefAPIConfig
|
||||||
|
if len(config) > 0 {
|
||||||
|
curConfig = *config[0]
|
||||||
|
}
|
||||||
|
return &API{
|
||||||
|
appID: appID,
|
||||||
|
appSecret: appSecret,
|
||||||
|
client: &http.Client{Timeout: curConfig.ClientTimeout},
|
||||||
|
config: &curConfig,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a *API) signParam(params map[string]interface{}) (sig string) {
|
||||||
|
var valueList []string
|
||||||
|
for k, v := range params {
|
||||||
|
if k != sigKey {
|
||||||
|
if str := fmt.Sprint(v); str != "" {
|
||||||
|
valueList = append(valueList, fmt.Sprintf("%s=%s", k, str))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
sort.Sort(sort.StringSlice(valueList))
|
||||||
|
valueList = append(valueList, fmt.Sprintf("secret_key=%s", a.appSecret))
|
||||||
|
sig = strings.Join(valueList, "&")
|
||||||
|
binSig := md5.Sum([]byte(url.QueryEscape(sig)))
|
||||||
|
sig = fmt.Sprintf("%x", binSig)
|
||||||
|
return sig
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a *API) signParam2(params map[string]interface{}) (sig string) {
|
||||||
|
sb := new(strings.Builder)
|
||||||
|
sb.WriteString("app_id=")
|
||||||
|
sb.WriteString(a.appID)
|
||||||
|
sb.WriteString("&access_token=")
|
||||||
|
sb.WriteString(a.accessToken)
|
||||||
|
sb.WriteString("&data=")
|
||||||
|
sb.WriteString(params["data"].(string))
|
||||||
|
sb.WriteString("&salt=")
|
||||||
|
sb.WriteString(utils.Int64ToStr(utils.MustInterface2Int64(params["salt"])))
|
||||||
|
sig = sb.String()
|
||||||
|
binSig := md5.Sum([]byte(sig))
|
||||||
|
sig = fmt.Sprintf("%x", binSig)
|
||||||
|
return sig
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a *API) AccessAPI(action string, url string, bizParams map[string]interface{}, isPost bool) (retVal map[string]interface{}, err error) {
|
||||||
|
params := make(map[string]interface{})
|
||||||
|
params["salt"] = GetSalt()
|
||||||
|
params["app_id"] = a.appID
|
||||||
|
if action != tokenAction {
|
||||||
|
data, _ := json.Marshal(bizParams)
|
||||||
|
params["data"] = string(data)
|
||||||
|
signStr := a.signParam2(params)
|
||||||
|
params[sigKey] = signStr
|
||||||
|
} else {
|
||||||
|
signStr := a.signParam(params)
|
||||||
|
params[sigKey] = signStr
|
||||||
|
}
|
||||||
|
data, _ := json.Marshal(params)
|
||||||
|
fullURL := utils.GenerateGetURL(url, action, nil)
|
||||||
|
err = platformapi.AccessPlatformAPIWithRetry(a.client,
|
||||||
|
func() *http.Request {
|
||||||
|
var request *http.Request
|
||||||
|
if isPost {
|
||||||
|
request, _ = http.NewRequest(http.MethodPost, fullURL, strings.NewReader(string(data)))
|
||||||
|
} else {
|
||||||
|
request, _ = http.NewRequest(http.MethodGet, utils.GenerateGetURL(url, action, params), nil)
|
||||||
|
}
|
||||||
|
request.Header.Set("Content-Type", "application/json")
|
||||||
|
return request
|
||||||
|
},
|
||||||
|
a.config,
|
||||||
|
func(response *http.Response, bodyStr string, jsonResult1 map[string]interface{}) (errLevel string, err error) {
|
||||||
|
if jsonResult1 == nil {
|
||||||
|
return platformapi.ErrLevelRecoverableErr, fmt.Errorf("mapData is nil")
|
||||||
|
}
|
||||||
|
if err == nil {
|
||||||
|
if utils.MustInterface2Int64(jsonResult1["code"]) != 200 {
|
||||||
|
errLevel = platformapi.ErrLevelGeneralFail
|
||||||
|
err = utils.NewErrorCode(jsonResult1["msg"].(string), utils.Int64ToStr(utils.MustInterface2Int64(jsonResult1["code"])))
|
||||||
|
baseapi.SugarLogger.Debugf("fnps AccessAPI failed, jsonResult1:%s", utils.Format4Output(jsonResult1, true))
|
||||||
|
}
|
||||||
|
retVal = jsonResult1
|
||||||
|
}
|
||||||
|
return errLevel, err
|
||||||
|
})
|
||||||
|
return retVal, err
|
||||||
|
}
|
||||||
|
|
||||||
|
func GetSalt() (salt int) {
|
||||||
|
rand.Seed(time.Now().UnixNano())
|
||||||
|
return rand.Intn(8999) + 1000
|
||||||
|
}
|
||||||
|
|
||||||
|
type TokenInfo struct {
|
||||||
|
AccessToken string `json:"access_token"`
|
||||||
|
AppID string `json:"app_id"`
|
||||||
|
ExpireTime int64 `json:"expire_time"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a *API) GetAccessToken() (tokenInfo *TokenInfo, err error) {
|
||||||
|
result, err := a.AccessAPI(tokenAction, URL, nil, false)
|
||||||
|
if err == nil {
|
||||||
|
utils.Map2StructByJson(result["data"], &tokenInfo, false)
|
||||||
|
}
|
||||||
|
return tokenInfo, err
|
||||||
|
}
|
||||||
175
platformapi/fnpsapi_old/order.go
Normal file
175
platformapi/fnpsapi_old/order.go
Normal file
@@ -0,0 +1,175 @@
|
|||||||
|
package fnpsapi
|
||||||
|
|
||||||
|
import (
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"git.rosy.net.cn/baseapi/utils"
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
OrderCancelReson1 = 1 // 1:物流原因:订单长时间未分配骑手,
|
||||||
|
OrderCancelReson2 = 2 // 2:物流原因:分配骑手后,骑手长时间未取件 ,
|
||||||
|
OrderCancelReson3 = 3 // 3:物流原因:骑手告知不配送,让取消订单,
|
||||||
|
OrderCancelReson4 = 4 // 4:商品缺货/无法出货/已售完,
|
||||||
|
OrderCancelReson5 = 5 // 5:商户联系不上门店/门店关门了,
|
||||||
|
OrderCancelReson6 = 6 // 6:商户发错单,
|
||||||
|
OrderCancelReson7 = 7 // 7:商户/顾客自身定位错误,
|
||||||
|
OrderCancelReson8 = 8 // 8:商户改其他第三方配送,
|
||||||
|
OrderCancelReson9 = 9 // 9:顾客下错单/临时不想要了,
|
||||||
|
OrderCancelReson10 = 10 // 10:顾客自取/不在家/要求另改时间配送)(0类型已下线)
|
||||||
|
|
||||||
|
OrderStatusAccept = 1 //系统已接单
|
||||||
|
OrderStatusAssigned = 20 //已分配骑手
|
||||||
|
OrderStatusArrived = 80 //已到店
|
||||||
|
OrderStatusDelivering = 2 //配送中
|
||||||
|
OrderStatusDelivered = 3 //已送达
|
||||||
|
OrderStatusException = 5 //异常
|
||||||
|
)
|
||||||
|
|
||||||
|
type CreateOrderParam struct {
|
||||||
|
PartnerRemark string `json:"partner_remark,omitempty"`
|
||||||
|
PartnerOrderCode string `json:"partner_order_code,omitempty"`
|
||||||
|
NotifyURL string `json:"notify_url,omitempty"`
|
||||||
|
OrderType int `json:"order_type,omitempty"`
|
||||||
|
ChainStoreCode string `json:"chain_store_code,omitempty"`
|
||||||
|
TransportInfo *TransportInfo `json:"transport_info,omitempty"`
|
||||||
|
OrderAddTime int64 `json:"order_add_time,omitempty"`
|
||||||
|
OrderTotalAmount float64 `json:"order_total_amount,omitempty"`
|
||||||
|
OrderActualAmount float64 `json:"order_actual_amount,omitempty"`
|
||||||
|
OrderWeight float64 `json:"order_weight,omitempty"`
|
||||||
|
OrderRemark string `json:"order_remark,omitempty"`
|
||||||
|
IsInvoiced int `json:"is_invoiced"`
|
||||||
|
Invoice string `json:"invoice,omitempty"`
|
||||||
|
OrderPaymentStatus int `json:"order_payment_status,omitempty"`
|
||||||
|
OrderPaymentMethod int `json:"order_payment_method,omitempty"`
|
||||||
|
IsAgentPayment int `json:"is_agent_payment"`
|
||||||
|
RequirePaymentPay float64 `json:"require_payment_pay,omitempty"`
|
||||||
|
GoodsCount int `json:"goods_count,omitempty"`
|
||||||
|
RequireReceiveTime int64 `json:"require_receive_time,omitempty"`
|
||||||
|
SerialNumber string `json:"serial_number,omitempty"`
|
||||||
|
ReceiverInfo *ReceiverInfo `json:"receiver_info,omitempty"`
|
||||||
|
ItemsJSON []*ItemsJSON `json:"items_json,omitempty"`
|
||||||
|
OrderSource string `json:"order_source,omitempty"` //饿百订单传109
|
||||||
|
ChannelOrderCode string `json:"channel_order_code,omitempty"`
|
||||||
|
CookingTime int64 `json:"cooking_time,omitempty"`
|
||||||
|
PlatformPaidTime int64 `json:"platform_paid_time,omitempty"`
|
||||||
|
PlatformCreatedTime int64 `json:"platform_created_time,omitempty"`
|
||||||
|
MerchantCode string `json:"merchant_code,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type ReceiverInfo struct {
|
||||||
|
ReceiverName string `json:"receiver_name,omitempty"`
|
||||||
|
ReceiverPrimaryPhone string `json:"receiver_primary_phone,omitempty"`
|
||||||
|
ReceiverSecondPhone string `json:"receiver_second_phone,omitempty"`
|
||||||
|
ReceiverAddress string `json:"receiver_address,omitempty"`
|
||||||
|
ReceiverLongitude float64 `json:"receiver_longitude,omitempty"`
|
||||||
|
ReceiverLatitude float64 `json:"receiver_latitude,omitempty"`
|
||||||
|
PositionSource int `json:"position_source,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type TransportInfo struct {
|
||||||
|
TransportName string `json:"transport_name,omitempty"`
|
||||||
|
TransportAddress string `json:"transport_address,omitempty"`
|
||||||
|
TransportLongitude float64 `json:"transport_longitude,omitempty"`
|
||||||
|
TransportLatitude float64 `json:"transport_latitude,omitempty"`
|
||||||
|
PositionSource int `json:"position_source,omitempty"`
|
||||||
|
TransportTel string `json:"transport_tel,omitempty"`
|
||||||
|
TransportRemark string `json:"transport_remark,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type ItemsJSON struct {
|
||||||
|
ItemID string `json:"item_id,omitempty"`
|
||||||
|
ItemName string `json:"item_name,omitempty"`
|
||||||
|
ItemQuantity int `json:"item_quantity,omitempty"`
|
||||||
|
ItemPrice float64 `json:"item_price"`
|
||||||
|
ItemActualPrice float64 `json:"item_actual_price"`
|
||||||
|
ItemSize int `json:"item_size,omitempty"`
|
||||||
|
ItemRemark string `json:"item_remark,omitempty"`
|
||||||
|
IsNeedPackage int `json:"is_need_package"`
|
||||||
|
IsAgentPurchase int `json:"is_agent_purchase"`
|
||||||
|
AgentPurchasePrice float64 `json:"agent_purchase_price,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
//https://open.ele.me/documents/%E5%88%9B%E5%BB%BA%E8%9C%82%E9%B8%9F%E8%AE%A2%E5%8D%95
|
||||||
|
func (a *API) CreateOrder(createOrderParam *CreateOrderParam) (err error) {
|
||||||
|
params := utils.Struct2FlatMap(createOrderParam)
|
||||||
|
_, err = a.AccessAPI("v2/order", URL, params, true)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
//order_cancel_reason_code 订单取消原因代码(1:用户取消,2:商家取消)
|
||||||
|
// order_cancel_code 订单取消编码(
|
||||||
|
// 1:物流原因:订单长时间未分配骑手,
|
||||||
|
// 2:物流原因:分配骑手后,骑手长时间未取件 ,
|
||||||
|
// 3:物流原因:骑手告知不配送,让取消订单,
|
||||||
|
// 4:商品缺货/无法出货/已售完, 5:商户联系不上门店/门店关门了, 6:商户发错单,
|
||||||
|
// 7:商户/顾客自身定位错误, 8:商户改其他第三方配送, 9:顾客下错单/临时不想要了,
|
||||||
|
// 10:顾客自取/不在家/要求另改时间配送)(0类型已下线)
|
||||||
|
|
||||||
|
type CancelOrderParam struct {
|
||||||
|
PartnerOrderCode string `json:"partner_order_code,omitempty"`
|
||||||
|
OrderCancelReasonCode int `json:"order_cancel_reason_code,omitempty"`
|
||||||
|
OrderCancelCode int `json:"order_cancel_code,omitempty"`
|
||||||
|
OrderCancelDescription string `json:"order_cancel_description,omitempty"`
|
||||||
|
OrderCancelTime int64 `json:"order_cancel_time,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a *API) CancelOrder(cancelOrderParam *CancelOrderParam) (err error) {
|
||||||
|
params := utils.Struct2FlatMap(cancelOrderParam)
|
||||||
|
_, err = a.AccessAPI("v2/order/cancel", URL, params, true)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a *API) ComplaintOrder(cancelOrderParam *CancelOrderParam) (err error) {
|
||||||
|
params := utils.Struct2FlatMap(cancelOrderParam)
|
||||||
|
_, err = a.AccessAPI("v2/order/complaint", URL, params, true)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
type QueryOrderResult struct {
|
||||||
|
AbnormalCode string `json:"abnormal_code"`
|
||||||
|
AbnormalDesc string `json:"abnormal_desc"`
|
||||||
|
CarrierDriverID int `json:"carrier_driver_id"`
|
||||||
|
CarrierDriverName string `json:"carrier_driver_name"`
|
||||||
|
CarrierDriverPhone string `json:"carrier_driver_phone"`
|
||||||
|
ComplaintDescription interface{} `json:"complaintDescription"`
|
||||||
|
ComplaintStatus interface{} `json:"complaintStatus"`
|
||||||
|
EstimateArriveTime int64 `json:"estimate_arrive_time"`
|
||||||
|
EventLogDetails []struct {
|
||||||
|
CarrierDriverName string `json:"carrier_driver_name"`
|
||||||
|
CarrierDriverPhone string `json:"carrier_driver_phone"`
|
||||||
|
OccurTime int64 `json:"occur_time"`
|
||||||
|
OrderStatus int `json:"order_status"`
|
||||||
|
} `json:"event_log_details"`
|
||||||
|
HandleID interface{} `json:"handleId"`
|
||||||
|
OrderID interface{} `json:"orderId"`
|
||||||
|
OrderStatus int `json:"order_status"`
|
||||||
|
OrderTotalDeliveryCost float64 `json:"order_total_delivery_cost"`
|
||||||
|
OrderTotalDeliveryDiscount interface{} `json:"order_total_delivery_discount"`
|
||||||
|
OvertimeCompensationCost float64 `json:"overtime_compensation_cost"`
|
||||||
|
Reason string `json:"reason"`
|
||||||
|
SupportClaims bool `json:"support_claims"`
|
||||||
|
TrackingID int64 `json:"trackingId"`
|
||||||
|
TrackingID2 int64 `json:"tracking_id"`
|
||||||
|
TransportStationID string `json:"transport_station_id"`
|
||||||
|
TransportStationTel string `json:"transport_station_tel"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a *API) QueryOrder(partnerOrderCode string) (queryOrderResult *QueryOrderResult, err error) {
|
||||||
|
result, err := a.AccessAPI("v2/order/query", URL, map[string]interface{}{
|
||||||
|
"partner_order_code": partnerOrderCode,
|
||||||
|
}, true)
|
||||||
|
if err == nil {
|
||||||
|
utils.Map2StructByJson(result["data"], &queryOrderResult, false)
|
||||||
|
}
|
||||||
|
return queryOrderResult, err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a *API) ComplaintRider(partnerOrderCode string, orderComplaintCode int) (err error) {
|
||||||
|
_, err = a.AccessAPI("v2/order/complaint", URL, map[string]interface{}{
|
||||||
|
"partner_order_code": partnerOrderCode,
|
||||||
|
"order_complaint_code": orderComplaintCode,
|
||||||
|
"order_complaint_time": time.Now().UnixNano() / 1e6,
|
||||||
|
}, true)
|
||||||
|
return err
|
||||||
|
}
|
||||||
84
platformapi/fnpsapi_old/store.go
Normal file
84
platformapi/fnpsapi_old/store.go
Normal file
@@ -0,0 +1,84 @@
|
|||||||
|
package fnpsapi
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"git.rosy.net.cn/baseapi/utils"
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
StoreNotExist = "门店信息不存在"
|
||||||
|
StoreExist = "该门店已存在"
|
||||||
|
)
|
||||||
|
|
||||||
|
type CreateStoreParam struct {
|
||||||
|
ChainStoreCode string `json:"chain_store_code,omitempty"`
|
||||||
|
ChainStoreName string `json:"chain_store_name,omitempty"`
|
||||||
|
ChainStoreType int `json:"chain_store_type,omitempty"`
|
||||||
|
MerchantCode string `json:"merchant_code,omitempty"`
|
||||||
|
ContactPhone string `json:"contact_phone,omitempty"`
|
||||||
|
Address string `json:"address,omitempty"`
|
||||||
|
PositionSource int `json:"position_source,omitempty"`
|
||||||
|
Longitude string `json:"longitude,omitempty"`
|
||||||
|
Latitude string `json:"latitude,omitempty"`
|
||||||
|
ServiceCode string `json:"service_code,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a *API) CreateStore(createStoreParam *CreateStoreParam) (err error) {
|
||||||
|
createStoreParam.ServiceCode = "1"
|
||||||
|
params := utils.Struct2FlatMap(createStoreParam)
|
||||||
|
_, err = a.AccessAPI("v2/chain_store", URL, params, true)
|
||||||
|
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) {
|
||||||
|
result, err := a.AccessAPI("v2/chain_store/query", URL, map[string]interface{}{
|
||||||
|
"chain_store_code": []string{storeID},
|
||||||
|
}, true)
|
||||||
|
if err == nil {
|
||||||
|
if data, ok := result["data"].([]interface{}); ok {
|
||||||
|
utils.Map2StructByJson(data[0], &getStoreResult, false)
|
||||||
|
} else {
|
||||||
|
err = fmt.Errorf(result["msg"].(string))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return getStoreResult, err
|
||||||
|
}
|
||||||
|
|
||||||
|
func IsErrShopNotExist(err error) bool {
|
||||||
|
if err != nil {
|
||||||
|
if strings.Contains(err.Error(), StoreNotExist) {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
func IsErrShopExist(err error) bool {
|
||||||
|
if err != nil {
|
||||||
|
if strings.Contains(err.Error(), StoreExist) {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a *API) UpdateStore(createStoreParam *CreateStoreParam) (err error) {
|
||||||
|
params := utils.Struct2FlatMap(createStoreParam)
|
||||||
|
_, err = a.AccessAPI("v2/chain_store/update", URL, params, true)
|
||||||
|
return err
|
||||||
|
}
|
||||||
102
platformapi/fnpsapi_v3/fnClient_test.go
Normal file
102
platformapi/fnpsapi_v3/fnClient_test.go
Normal file
@@ -0,0 +1,102 @@
|
|||||||
|
package fnpsapi
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"testing"
|
||||||
|
)
|
||||||
|
|
||||||
|
var api *API
|
||||||
|
|
||||||
|
func Init() {
|
||||||
|
api = New("6705486294797503379", "c1e6c280-e618-4103-9d0a-673bc54fb22e", "5375691", "cabrXQf9eFMVWVYg4hNlwu")
|
||||||
|
token, _ := api.GetAccessToken()
|
||||||
|
api.accessToken = token.BusinessDataObj.AccessToken
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestClient(t *testing.T) {
|
||||||
|
api = New("6705486294797503379", "c1e6c280-e618-4103-9d0a-673bc54fb22e", "5375691", "cabrXQf9eFMVWVYg4hNlwu")
|
||||||
|
token, err := api.GetAccessToken()
|
||||||
|
api.accessToken = token.BusinessDataObj.AccessToken
|
||||||
|
fmt.Println("token===", token.BusinessDataObj.AccessToken)
|
||||||
|
fmt.Println("err=====", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// 创建门店,
|
||||||
|
func TestCreateStore(t *testing.T) {
|
||||||
|
api = New("6705486294797503379", "c1e6c280-e618-4103-9d0a-673bc54fb22e", "5375691", "cabrXQf9eFMVWVYg4hNlwu")
|
||||||
|
token, _ := api.GetAccessToken()
|
||||||
|
api.accessToken = token.BusinessDataObj.AccessToken
|
||||||
|
err := api.CreateStore(&CreateStoreBaseInfo{
|
||||||
|
HeadShopName: "刘磊测试门店",
|
||||||
|
ContactPhone: "18981810340",
|
||||||
|
Address: "四川成都",
|
||||||
|
Longitude: 104.094555,
|
||||||
|
Latitude: 30.661382,
|
||||||
|
PositionSource: 3,
|
||||||
|
OutShopCode: "637910",
|
||||||
|
CategoryID: "12",
|
||||||
|
OwnerName: "刘磊",
|
||||||
|
OwnerIDNum: "511324199308263974",
|
||||||
|
HandheldLicencePicHash: "d7c64022f6458f9aa76968e01f5686c5.jpeg",
|
||||||
|
OwnerIDPicFrontHash: "d7c64022f6458f9aa76968e01f5686c5.jpeg",
|
||||||
|
OwnerIDPicBackHash: "d7c64022f6458f9aa76968e01f5686c5.jpeg",
|
||||||
|
CreditCode: "12345",
|
||||||
|
BusinessLicencePicHash: "d7c64022f6458f9aa76968e01f5686c5.jpeg",
|
||||||
|
|
||||||
|
BranchShopName: "",
|
||||||
|
ChainstoreType: 2,
|
||||||
|
SettlementModel: "1",
|
||||||
|
SettlementAccountID: "",
|
||||||
|
FoodLicensePicHash: "d7c64022f6458f9aa76968e01f5686c5.jpeg",
|
||||||
|
SecondMedicalEquipmentLicensePicHash: "",
|
||||||
|
MedicalInstitutionLicensePicHash: "",
|
||||||
|
MedicalEquipmentLicensePicHash: "",
|
||||||
|
MedicineLicensePicHash: "",
|
||||||
|
TabacooLicensePicHash: "",
|
||||||
|
})
|
||||||
|
fmt.Println(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestUpdataStore(t *testing.T) {
|
||||||
|
api = New("6705486294797503379", "c1e6c280-e618-4103-9d0a-673bc54fb22e", "5375691", "cabrXQf9eFMVWVYg4hNlwu")
|
||||||
|
token, _ := api.GetAccessToken()
|
||||||
|
api.accessToken = token.BusinessDataObj.AccessToken
|
||||||
|
err := api.UpdateStore(&UpdateStoreParam{
|
||||||
|
ChainStoreID: "209636747",
|
||||||
|
HeadShopName: "刘磊测试门店",
|
||||||
|
ContactPhone: "18981810340",
|
||||||
|
Address: "四川成都",
|
||||||
|
Longitude: 104.094555,
|
||||||
|
Latitude: 30.661382,
|
||||||
|
PositionSource: 3,
|
||||||
|
OutShopCode: "637910",
|
||||||
|
CategoryID: "12",
|
||||||
|
OwnerName: "刘磊",
|
||||||
|
OwnerIDNum: "511324199308263974",
|
||||||
|
HandheldLicencePicHash: "d7c64022f6458f9aa76968e01f5686c5.jpeg",
|
||||||
|
OwnerIDPicFrontHash: "d7c64022f6458f9aa76968e01f5686c5.jpeg",
|
||||||
|
OwnerIDPicBackHash: "d7c64022f6458f9aa76968e01f5686c5.jpeg",
|
||||||
|
CreditCode: "12345",
|
||||||
|
BusinessLicencePicHash: "d7c64022f6458f9aa76968e01f5686c5.jpeg",
|
||||||
|
|
||||||
|
BranchShopName: "",
|
||||||
|
ChainstoreType: 2,
|
||||||
|
FoodLicensePicHash: "d7c64022f6458f9aa76968e01f5686c5.jpeg",
|
||||||
|
SecondMedicalEquipmentLicensePicHash: "",
|
||||||
|
MedicalInstitutionLicensePicHash: "",
|
||||||
|
MedicalEquipmentLicensePicHash: "",
|
||||||
|
MedicineLicensePicHash: "",
|
||||||
|
TabacooLicensePicHash: "",
|
||||||
|
})
|
||||||
|
fmt.Println(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// 查询单个门店
|
||||||
|
func TestQueryOneStore(t *testing.T) {
|
||||||
|
api = New("6705486294797503379", "c1e6c280-e618-4103-9d0a-673bc54fb22e", "5375691", "cabrXQf9eFMVWVYg4hNlwu")
|
||||||
|
token, _ := api.GetAccessToken()
|
||||||
|
api.accessToken = token.BusinessDataObj.AccessToken
|
||||||
|
data, err := api.GetStore("637910")
|
||||||
|
fmt.Println(data)
|
||||||
|
fmt.Println(err)
|
||||||
|
}
|
||||||
@@ -7,8 +7,10 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
TokenURL = "https://open-anubis.ele.me/anubis-webapi/openapi/token"
|
//TokenURL = "https://open-anubis.ele.me/anubis-webapi/openapi/token" // 正式环境
|
||||||
ApiURL = "https://open-anubis.ele.me/anubis-webapi/v3/invoke/"
|
//ApiURL = "https://open-anubis.ele.me/anubis-webapi/v3/invoke"// 正式环境
|
||||||
|
TokenURL = "https://exam-anubis.ele.me/anubis-webapi/openapi/token" // 沙箱环境
|
||||||
|
ApiURL = "https://exam-anubis.ele.me/anubis-webapi/v3/invoke" // 沙箱环境
|
||||||
RequestPost = "POST"
|
RequestPost = "POST"
|
||||||
RequestGet = "GET"
|
RequestGet = "GET"
|
||||||
)
|
)
|
||||||
@@ -43,10 +45,11 @@ type BaseInfo struct {
|
|||||||
|
|
||||||
// 获取token
|
// 获取token
|
||||||
type TokenInfo struct {
|
type TokenInfo struct {
|
||||||
Sign string `json:"sign"` //返回值签名,详见开放平台侧返回值签名算法
|
Sign string `json:"sign"` //返回值签名,详见开放平台侧返回值签名算法
|
||||||
Code string `json:"code"` //错误码,详见开放平台侧错误码映射表
|
Code string `json:"code"` //错误码,详见开放平台侧错误码映射表
|
||||||
Msg string `json:"msg"` //错误信息
|
Msg string `json:"msg"` //错误信息
|
||||||
BusinessData string `json:"business_data"` // string
|
BusinessData string `json:"business_data"` // string
|
||||||
|
BusinessDataObj *BusinessData // BusinessData 对象
|
||||||
}
|
}
|
||||||
|
|
||||||
type BusinessData struct {
|
type BusinessData struct {
|
||||||
@@ -54,13 +57,13 @@ type BusinessData struct {
|
|||||||
MerchantID string `json:"merchant_id"` //商户id
|
MerchantID string `json:"merchant_id"` //商户id
|
||||||
AccessToken string `json:"access_token"` //凭证token
|
AccessToken string `json:"access_token"` //凭证token
|
||||||
RefreshToken string `json:"refresh_token"` //刷新token
|
RefreshToken string `json:"refresh_token"` //刷新token
|
||||||
ExpireIn string `json:"expire_in"` //access_token剩余有效时间,单位:秒,默认有效期是一年
|
ExpireIn int64 `json:"expire_in"` //access_token剩余有效时间,单位:秒,默认有效期是一年
|
||||||
ReExpireIn string `json:"re_expire_in"` //refresh_token剩余有效时间
|
ReExpireIn int64 `json:"re_expire_in"` //refresh_token剩余有效时间
|
||||||
}
|
}
|
||||||
|
|
||||||
//#endregion
|
//#endregion
|
||||||
|
|
||||||
//<------------------------------------门店--------------------------------------------------------------------------------------->
|
//<---------------------------------------------------门店--------------------------------------------------------------------------------------->
|
||||||
//#region 获取蜂鸟门店信息
|
//#region 获取蜂鸟门店信息
|
||||||
|
|
||||||
// 获取单个门店查询
|
// 获取单个门店查询
|
||||||
@@ -106,26 +109,26 @@ type GetOneStoreRespData struct {
|
|||||||
// 更新蜂鸟门店信息
|
// 更新蜂鸟门店信息
|
||||||
type UpdateStoreParam struct {
|
type UpdateStoreParam struct {
|
||||||
// 必填
|
// 必填
|
||||||
ChainStoreID string `json:"chain_store_id"`
|
ChainStoreID string `json:"chain_store_id"`
|
||||||
HeadShopName string `json:"head_shop_name"` // 门店主店名
|
HeadShopName string `json:"head_shop_name"` // 门店主店名
|
||||||
ContactPhone string `json:"contact_phone"` // 门店联系方式
|
ContactPhone string `json:"contact_phone"` // 门店联系方式
|
||||||
Address string `json:"address"` // 门店地址
|
Address string `json:"address"` // 门店地址
|
||||||
Longitude string `json:"longitude"` // 纬度
|
Longitude float64 `json:"longitude"` // 纬度
|
||||||
Latitude string `json:"latitude"` // 门店纬度
|
Latitude float64 `json:"latitude"` // 门店纬度
|
||||||
PositionSource string `json:"position_source"` // 经纬度来源 坐标属性:高德地图:3;目前只支持高德地图坐标
|
PositionSource int `json:"position_source"` // 经纬度来源 坐标属性:高德地图:3;目前只支持高德地图坐标
|
||||||
OutShopCode string `json:"out_shop_code"` // 外部门店编码
|
OutShopCode string `json:"out_shop_code"` // 外部门店编码
|
||||||
CategoryID string `json:"category_id"` // 门店类目
|
CategoryID string `json:"category_id"` // 门店类目
|
||||||
OwnerName string `json:"owner_name"` // 门店主店名
|
OwnerName string `json:"owner_name"` // 门店主店名
|
||||||
OwnerIDNum string `json:"owner_id_num"` // 门店拥有人身份证号
|
OwnerIDNum string `json:"owner_id_num"` // 门店拥有人身份证号
|
||||||
HandheldLicencePicHash string `json:"handheld_licence_pic_hash"` // 门店拥有人手持身份证、营业执照图片
|
HandheldLicencePicHash string `json:"handheld_licence_pic_hash"` // 门店拥有人手持身份证、营业执照图片
|
||||||
OwnerIDPicFrontHash string `json:"owner_id_pic_front_hash"` // 身份证正面
|
OwnerIDPicFrontHash string `json:"owner_id_pic_front_hash"` // 身份证正面
|
||||||
OwnerIDPicBackHash string `json:"owner_id_pic_back_hash"` // 身份证反面
|
OwnerIDPicBackHash string `json:"owner_id_pic_back_hash"` // 身份证反面
|
||||||
CreditCode string `json:"credit_code"` // 统一社会信用代码
|
CreditCode string `json:"credit_code"` // 统一社会信用代码
|
||||||
BusinessLicencePicHash string `json:"business_licence_pic_hash"` // 营业执照图片
|
BusinessLicencePicHash string `json:"business_licence_pic_hash"` // 营业执照图片
|
||||||
|
|
||||||
// 选填
|
// 选填
|
||||||
BranchShopName string `json:"branch_shop_name"` // 门店主店名
|
BranchShopName string `json:"branch_shop_name"` // 门店主店名
|
||||||
ChainstoreType string `json:"chainstore_type"`
|
ChainstoreType int `json:"chainstore_type"`
|
||||||
FoodLicensePicHash string `json:"food_license_pic_hash"` // 食品安全执照图片
|
FoodLicensePicHash string `json:"food_license_pic_hash"` // 食品安全执照图片
|
||||||
SecondMedicalEquipmentLicensePicHash string `json:"second_medical_equipment_license_pic_hash"` // 第二类医疗器械类目必传
|
SecondMedicalEquipmentLicensePicHash string `json:"second_medical_equipment_license_pic_hash"` // 第二类医疗器械类目必传
|
||||||
MedicalInstitutionLicensePicHash string `json:"medical_institution_license_pic_hash"` // 医疗机构必传
|
MedicalInstitutionLicensePicHash string `json:"medical_institution_license_pic_hash"` // 医疗机构必传
|
||||||
@@ -179,11 +182,11 @@ type PreCreateOrder struct {
|
|||||||
OrderType int `json:"order_type"` // 订单类型(1:即时单,3:预约单)
|
OrderType int `json:"order_type"` // 订单类型(1:即时单,3:预约单)
|
||||||
PositionSource int `json:"position_source"` // 经纬度来源
|
PositionSource int `json:"position_source"` // 经纬度来源
|
||||||
ReceiverAddress string `json:"receiver_address"` // 收货人地址 文字描述
|
ReceiverAddress string `json:"receiver_address"` // 收货人地址 文字描述
|
||||||
ReceiverLongitude string `json:"receiver_longitude"` // 收货人经度
|
ReceiverLongitude float64 `json:"receiver_longitude"` // 收货人经度
|
||||||
ReceiverLatitude string `json:"receiver_latitude"` // 收货人纬度
|
ReceiverLatitude float64 `json:"receiver_latitude"` // 收货人纬度
|
||||||
GoodsTotalAmountCent int `json:"goods_total_amount_cent"` // 订单商品总金额(分)
|
GoodsTotalAmountCent int `json:"goods_total_amount_cent"` // 订单商品总金额(分)
|
||||||
GoodsActualAmountCent int64 `json:"goods_actual_amount_cent"` // 订单商品客户实际支付金额
|
GoodsActualAmountCent int64 `json:"goods_actual_amount_cent"` // 订单商品客户实际支付金额
|
||||||
GoodsWeight string `json:"goods_weight"` // 订单总重量(kg)
|
GoodsWeight float64 `json:"goods_weight"` // 订单总重量(kg)
|
||||||
GoodsCount int `json:"goods_count"` // 货物件数
|
GoodsCount int `json:"goods_count"` // 货物件数
|
||||||
GoodsItemList []*GoodsItemsList // 货物列表
|
GoodsItemList []*GoodsItemsList // 货物列表
|
||||||
|
|
||||||
@@ -223,10 +226,11 @@ type GoodsItemsList struct {
|
|||||||
|
|
||||||
// 蜂鸟请求预下单返回值
|
// 蜂鸟请求预下单返回值
|
||||||
type PreCreateOrderResp struct {
|
type PreCreateOrderResp struct {
|
||||||
Distance int64 `json:"distance"` //配送距离
|
Distance int64 `json:"distance"` //配送距离
|
||||||
CityId int64 `json:"city_id"` // 城市id
|
CityId int64 `json:"city_id"` // 城市id
|
||||||
Time int64 `json:"time"` // 预询时间戳
|
Time int64 `json:"time"` // 预询时间戳
|
||||||
GoodsInfos []*GoodsInfos // 服务商品明细
|
GoodsInfos []*GoodsInfos `json:"goods_infos"` // 服务商品明细
|
||||||
|
//GoodsInfos string `json:"goods_infos"` // 服务商品明细
|
||||||
}
|
}
|
||||||
|
|
||||||
// 预下单商品服务明细
|
// 预下单商品服务明细
|
||||||
@@ -279,13 +283,13 @@ type CreateOrderReqParam struct {
|
|||||||
GoodsItemList []*GoodsItemsList `json:"goods_item_list,omitempty"` // 货物明细
|
GoodsItemList []*GoodsItemsList `json:"goods_item_list,omitempty"` // 货物明细
|
||||||
ReceiverName string `json:"receiver_name,omitempty"` // 收货人姓名
|
ReceiverName string `json:"receiver_name,omitempty"` // 收货人姓名
|
||||||
ReceiverPrimaryPhone string `json:"receiver_primary_phone,omitempty"` // 只支持手机号,400开头电话,座机号码以及95013开头、长度13位的虚拟电话
|
ReceiverPrimaryPhone string `json:"receiver_primary_phone,omitempty"` // 只支持手机号,400开头电话,座机号码以及95013开头、长度13位的虚拟电话
|
||||||
|
OutShopCode string `json:"out_shop_code,omitempty"` // 外部门店id 当使用门店发单 out_shop_code和chain_store_id必填1个
|
||||||
|
ChainStoreId string `json:"chain_store_id,omitempty"` // 门店id
|
||||||
|
|
||||||
// 选传参数
|
// 选传参数
|
||||||
TransportLongitude float64 `json:"transport_longitude,omitempty"` // 取货经度
|
TransportLongitude float64 `json:"transport_longitude,omitempty"` // 取货经度
|
||||||
TransportLatitude float64 `json:"transport_latitude,omitempty"` // 取货纬度
|
TransportLatitude float64 `json:"transport_latitude,omitempty"` // 取货纬度
|
||||||
TransportTel string `json:"transport_tel,omitempty"` // 取货点联系人电话
|
TransportTel string `json:"transport_tel,omitempty"` // 取货点联系人电话
|
||||||
OutShopCode string `json:"out_shop_code,omitempty"` // 外部门店id 当使用门店发单 out_shop_code和chain_store_id必填1个
|
|
||||||
ChainStoreId int64 `json:"chain_store_id,omitempty"` // 门店id
|
|
||||||
OrderSource string `json:"order_source,omitempty"` // 饿百订单传109 商户订单来源(如饿了么、美团等)手发单/未知来源: 0 或不传 美团: 2 口碑: 4 饿了么: 6支付宝: 7 饿百: 8
|
OrderSource string `json:"order_source,omitempty"` // 饿百订单传109 商户订单来源(如饿了么、美团等)手发单/未知来源: 0 或不传 美团: 2 口碑: 4 饿了么: 6支付宝: 7 饿百: 8
|
||||||
ServiceGoodsId int64 `json:"service_goods_id,omitempty"` // 服务商品id 校验预询配送费价格时 必传
|
ServiceGoodsId int64 `json:"service_goods_id,omitempty"` // 服务商品id 校验预询配送费价格时 必传
|
||||||
BaseGoodsId int64 `json:"base_goods_id,omitempty"` // 基础商品id 校验预询配送费价格时 必传
|
BaseGoodsId int64 `json:"base_goods_id,omitempty"` // 基础商品id 校验预询配送费价格时 必传
|
||||||
@@ -323,33 +327,41 @@ type GetOrderDetailReq struct {
|
|||||||
|
|
||||||
// 查询订单详情接口返回值
|
// 查询订单详情接口返回值
|
||||||
type GetOrderDetailRes struct {
|
type GetOrderDetailRes struct {
|
||||||
OrderId int64 `json:"order_id"` // 订单id
|
OrderId int64 `json:"order_id"` // 订单id
|
||||||
TrackingId int64 `json:"tracking_id"` // 运单id
|
TrackingId int64 `json:"tracking_id"` // 运单id
|
||||||
PartnerOrderCode string `json:"partner_order_code"` // 外部订单号
|
PartnerOrderCode string `json:"partner_order_code"` // 外部订单号
|
||||||
SerialNumber string `json:"serial_number"` // 商家订单流水号, 方便配送骑手 到店取货, 支持数字,字母及#等常见字符. 建议填写。长度<=6。
|
SerialNumber string `json:"serial_number"` // 商家订单流水号, 方便配送骑手 到店取货, 支持数字,字母及#等常见字符. 建议填写。长度<=6。
|
||||||
OrderStatus int `json:"order_status"` // 订单生成0,运单生成成功1,20:骑手接单,80:骑手到店,2:配送中,3:已完成,4:已取消,5:配送异常
|
OrderStatus int `json:"order_status"` // 订单生成0,运单生成成功1,20:骑手接单,80:骑手到店,2:配送中,3:已完成,4:已取消,5:配送异常
|
||||||
CarrierDriverId string `json:"carrier_driver_id"` // 配送员id
|
CarrierDriverId string `json:"carrier_driver_id"` // 配送员id
|
||||||
CarrierDriverName string `json:"carrier_driver_name"` // 配送员姓名
|
CarrierDriverName string `json:"carrier_driver_name"` // 配送员姓名
|
||||||
CarrierDriverPhone string `json:"carrier_driver_phone"` // 配送员电话
|
CarrierDriverPhone string `json:"carrier_driver_phone"` // 配送员电话
|
||||||
EstimateArriveTime int64 `json:"estimate_arrive_time"` // 预计送达时间(毫秒)
|
EstimateArriveTime int64 `json:"estimate_arrive_time"` // 预计送达时间(毫秒)
|
||||||
OvertimeCompensationCostCent int64 `json:"overtime_compensation_cost_cent"` // 时效赔付
|
OvertimeCompensationCostCent int64 `json:"overtime_compensation_cost_cent"` // 时效赔付
|
||||||
IfCanAddTip int `json:"if_can_add_tip"` // 是否支持添加调度费 1可以,0不可以
|
IfCanAddTip int `json:"if_can_add_tip"` // 是否支持添加调度费 1可以,0不可以
|
||||||
OrderTipAmountCent int64 `json:"order_tip_amount_cent"` // 订单当前小费总金额 分
|
OrderTipAmountCent int64 `json:"order_tip_amount_cent"` // 订单当前小费总金额 分
|
||||||
DeliveryFetchPhotos []interface{} `json:"delivery_fetch_photos"` // 骑手取货照片地址
|
DeliveryFetchPhotos []interface{} `json:"delivery_fetch_photos"` // 骑手取货照片地址
|
||||||
OrderTotalAmountCent int64 `json:"order_total_amount_cent"` // 原始配送费金额(分)
|
OrderTotalAmountCent int64 `json:"order_total_amount_cent"` // 原始配送费金额(分)
|
||||||
OrderActualAmountCent int64 `json:"order_actual_amount_cent"` // 订单实际配送支付总金额关注这个字段即可(分)
|
OrderActualAmountCent int64 `json:"order_actual_amount_cent"` // 订单实际配送支付总金额关注这个字段即可(分)
|
||||||
PriceDetail []*struct{} `json:"price_detail"` // 配送费价格明细
|
PriceDetail []*PriceOpenapiDetail `json:"price_detail"` // 配送费价格明细
|
||||||
AbnormalCode string `json:"abnormal_code"` // 运单异常原因code
|
AbnormalCode string `json:"abnormal_code"` // 运单异常原因code
|
||||||
AbnormalDesc string `json:"abnormal_desc"` // 运单异常原因描述
|
AbnormalDesc string `json:"abnormal_desc"` // 运单异常原因描述
|
||||||
EventLogDetails []*struct{} `json:"event_log_details"` // 运单事件节点信息
|
EventLogDetails []*OrderNodeInfo `json:"event_log_details"` // 运单事件节点信息
|
||||||
ComplaintId int64 `json:"complaint_id"` // 投诉编号
|
ComplaintId int64 `json:"complaint_id"` // 投诉编号
|
||||||
ComplaintReasonDesc string `json:"complaint_reason_desc"` // 投诉原因描述
|
ComplaintReasonDesc string `json:"complaint_reason_desc"` // 投诉原因描述
|
||||||
ComplaintStatus int `json:"complaint_status"` // 投诉状态 1待处理, 2成功,3失败
|
ComplaintStatus int `json:"complaint_status"` // 投诉状态 1待处理, 2成功,3失败
|
||||||
ClaimId int64 `json:"claim_id"` // 索赔id
|
ClaimId int64 `json:"claim_id"` // 索赔id
|
||||||
ClaimReasonDesc string `json:"claim_reason_desc"` // 索赔原因描述
|
ClaimReasonDesc string `json:"claim_reason_desc"` // 索赔原因描述
|
||||||
ClaimStatus int `json:"claim_status"` // 索赔状态 1待处理, 2成功,3失败
|
ClaimStatus int `json:"claim_status"` // 索赔状态 1待处理, 2成功,3失败
|
||||||
Temperature string `json:"temperature"` // 骑手体温
|
Temperature string `json:"temperature"` // 骑手体温
|
||||||
OrderDistance float64 `json:"order_distance"` // 配送距离(米)
|
OrderDistance float64 `json:"order_distance"` // 配送距离(米)
|
||||||
|
}
|
||||||
|
|
||||||
|
// 点单详情信息,订单结点信息
|
||||||
|
type OrderNodeInfo struct {
|
||||||
|
OrderStatus int `json:"order_status"` // 订单状态
|
||||||
|
OccurTime int64 `json:"occur_time"` // 时间结点
|
||||||
|
CarrierDriverName string `json:"carrier_driver_name"` // 配送员姓名
|
||||||
|
CarrierDriverPhone string `json:"carrier_driver_phone"` // 配送电话
|
||||||
}
|
}
|
||||||
|
|
||||||
// getKnightInfo 查询骑手信息接口,参数 GetOrderDetailReq
|
// getKnightInfo 查询骑手信息接口,参数 GetOrderDetailReq
|
||||||
@@ -370,9 +382,10 @@ type GetKnightInfoRes struct {
|
|||||||
//另:联调环境使用加小费接口 需先使用联调工具->订单状态回调:把订单状态改为1,否则订单状态会不支持加小费
|
//另:联调环境使用加小费接口 需先使用联调工具->订单状态回调:把订单状态改为1,否则订单状态会不支持加小费
|
||||||
// 添加小费
|
// 添加小费
|
||||||
type AddTipRes struct {
|
type AddTipRes struct {
|
||||||
GetOrderDetailReq
|
OrderId string `json:"order_id"` // 订单号 订单号和外部订单号必填1个
|
||||||
AddTipAmountCent int64 `json:"add_tip_amount_cent"` // 小费金额分(必填)
|
PartnerOrderCode string `json:"partner_order_code"` // 外部订单号
|
||||||
ThirdIndexId int64 `json:"third_index_id"` // 本次加小费唯一标识 每个订单内 不可重复, 会用来做幂等,相同third_index_id的后续请求会被忽略
|
AddTipAmountCent int64 `json:"add_tip_amount_cent"` // 小费金额分(必填)
|
||||||
|
ThirdIndexId int64 `json:"third_index_id"` // 本次加小费唯一标识 每个订单内 不可重复, 会用来做幂等,相同third_index_id的后续请求会被忽略
|
||||||
}
|
}
|
||||||
|
|
||||||
// 业务出参 "business_data": "{\"result\":true}"
|
// 业务出参 "business_data": "{\"result\":true}"
|
||||||
@@ -390,6 +403,12 @@ type GetCancelReasonListRes struct {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// preCancelOrder 预取消订单接口
|
||||||
|
type PreCancelOrderReq struct {
|
||||||
|
GetOrderDetailReq
|
||||||
|
OrderCancelCode int64 `json:"order_cancel_code"` // 从可用取消原因列表接口返回结果选择(必填)
|
||||||
|
}
|
||||||
|
|
||||||
// cancelOrder 正式取消订单接口
|
// cancelOrder 正式取消订单接口
|
||||||
type CancelOrderReq struct {
|
type CancelOrderReq struct {
|
||||||
GetOrderDetailReq
|
GetOrderDetailReq
|
||||||
@@ -428,3 +447,5 @@ type OrderClaimSkuDto struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
//#endregion
|
//#endregion
|
||||||
|
|
||||||
|
//#endregion
|
||||||
|
|||||||
@@ -2,17 +2,17 @@ package fnpsapi
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"crypto/sha256"
|
"crypto/sha256"
|
||||||
"encoding/base64"
|
"encoding/hex"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"fmt"
|
"fmt"
|
||||||
"git.rosy.net.cn/baseapi"
|
"git.rosy.net.cn/baseapi"
|
||||||
|
"git.rosy.net.cn/baseapi/platformapi"
|
||||||
|
"git.rosy.net.cn/baseapi/utils"
|
||||||
"net/http"
|
"net/http"
|
||||||
|
"sort"
|
||||||
"strings"
|
"strings"
|
||||||
"sync"
|
"sync"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"git.rosy.net.cn/baseapi/platformapi"
|
|
||||||
"git.rosy.net.cn/baseapi/utils"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
func (a *API) SetToken(token string) {
|
func (a *API) SetToken(token string) {
|
||||||
@@ -32,19 +32,20 @@ func (a *API) MakeFnRequestHead() map[string]interface{} {
|
|||||||
return requestParam
|
return requestParam
|
||||||
}
|
}
|
||||||
|
|
||||||
func New(appID, appSecret, merchantId string, config ...*platformapi.APIConfig) *API {
|
func New(appID, appSecret, merchantId, code string, config ...*platformapi.APIConfig) *API {
|
||||||
curConfig := platformapi.DefAPIConfig
|
curConfig := platformapi.DefAPIConfig
|
||||||
if len(config) > 0 {
|
if len(config) > 0 {
|
||||||
curConfig = *config[0]
|
curConfig = *config[0]
|
||||||
}
|
}
|
||||||
return &API{
|
return &API{
|
||||||
grantType: "authorization_code", // 授权模式,填固定值authorization_code
|
grantType: "authorization_code", // 授权模式,填固定值authorization_code
|
||||||
code: "cod3",
|
code: code,
|
||||||
appID: appID,
|
appID: appID,
|
||||||
merchantId: merchantId,
|
merchantId: merchantId,
|
||||||
signature: "",
|
signature: "",
|
||||||
timestamp: time.Now().UnixNano(),
|
timestamp: time.Now().UnixNano(),
|
||||||
accessToken: "",
|
accessToken: "",
|
||||||
|
version: "1.0",
|
||||||
appSecret: appSecret,
|
appSecret: appSecret,
|
||||||
locker: sync.RWMutex{},
|
locker: sync.RWMutex{},
|
||||||
client: &http.Client{Timeout: curConfig.ClientTimeout},
|
client: &http.Client{Timeout: curConfig.ClientTimeout},
|
||||||
@@ -52,25 +53,50 @@ func New(appID, appSecret, merchantId string, config ...*platformapi.APIConfig)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// signParam2 apiV3签名算法SHA-256
|
func (a *API) signParam(params map[string]interface{}) (sig string) {
|
||||||
func (a *API) signParam2() (sig string) {
|
var valueList []string
|
||||||
sb := new(strings.Builder)
|
for k, v := range params {
|
||||||
sb.WriteString("grant_type=")
|
if k != "signature" {
|
||||||
sb.WriteString(a.grantType)
|
if str := fmt.Sprint(v); str != "" {
|
||||||
sb.WriteString("&code=")
|
valueList = append(valueList, fmt.Sprintf("%s=%s", k, str))
|
||||||
sb.WriteString(a.code) //todo
|
}
|
||||||
sb.WriteString("&app_id=")
|
}
|
||||||
sb.WriteString(a.appID)
|
}
|
||||||
sb.WriteString("&merchant_id=")
|
sort.Sort(sort.StringSlice(valueList))
|
||||||
sb.WriteString(a.merchantId)
|
sig = strings.Join(valueList, "&")
|
||||||
sb.WriteString("×tamp=")
|
sig = a.appSecret + sig
|
||||||
sb.WriteString(utils.Int64ToStr(a.timestamp))
|
signature := sha256.Sum256([]byte(sig))
|
||||||
sig = sb.String()
|
return hex.EncodeToString(signature[:])
|
||||||
sig = base64.StdEncoding.EncodeToString(sha256.New().Sum([]byte(sig)))
|
}
|
||||||
return sig
|
|
||||||
|
// 获取access_token
|
||||||
|
func (a *API) GetAccessToken() (tokenInfo *TokenInfo, err error) {
|
||||||
|
parameter := make(map[string]interface{}, 6)
|
||||||
|
parameter["grant_type"] = a.grantType
|
||||||
|
parameter["code"] = a.code
|
||||||
|
parameter["app_id"] = a.appID
|
||||||
|
parameter["merchant_id"] = a.merchantId
|
||||||
|
parameter["timestamp"] = utils.Int64ToStr(a.timestamp)
|
||||||
|
|
||||||
|
result, err := a.AccessAPI(TokenURL, "", RequestPost, parameter)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
if err := utils.Map2StructByJson(result, &tokenInfo, false); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
businessData := &BusinessData{}
|
||||||
|
if err := json.Unmarshal([]byte(utils.Interface2String(result["business_data"])), businessData); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
tokenInfo.BusinessDataObj = businessData
|
||||||
|
return tokenInfo, err
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a *API) AccessAPI(baseUrl, actionApi, method string, bizParams map[string]interface{}) (retVal map[string]interface{}, err error) {
|
func (a *API) AccessAPI(baseUrl, actionApi, method string, bizParams map[string]interface{}) (retVal map[string]interface{}, err error) {
|
||||||
|
a.signature = a.signParam(bizParams)
|
||||||
|
bizParams["signature"] = a.signature
|
||||||
// 序列化
|
// 序列化
|
||||||
data, err := json.Marshal(bizParams)
|
data, err := json.Marshal(bizParams)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -83,7 +109,7 @@ func (a *API) AccessAPI(baseUrl, actionApi, method string, bizParams map[string]
|
|||||||
// 发送请求
|
// 发送请求
|
||||||
sendUrl := func() *http.Request {
|
sendUrl := func() *http.Request {
|
||||||
var request *http.Request
|
var request *http.Request
|
||||||
if method == "POST" {
|
if RequestPost == method {
|
||||||
request, _ = http.NewRequest(http.MethodPost, fullURL, strings.NewReader(string(data)))
|
request, _ = http.NewRequest(http.MethodPost, fullURL, strings.NewReader(string(data)))
|
||||||
} else {
|
} else {
|
||||||
request, _ = http.NewRequest(http.MethodGet, utils.GenerateGetURL(baseUrl, actionApi, bizParams), nil)
|
request, _ = http.NewRequest(http.MethodGet, utils.GenerateGetURL(baseUrl, actionApi, bizParams), nil)
|
||||||
|
|||||||
@@ -2,7 +2,9 @@ package fnpsapi
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
|
"errors"
|
||||||
"git.rosy.net.cn/baseapi/utils"
|
"git.rosy.net.cn/baseapi/utils"
|
||||||
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
@@ -28,9 +30,13 @@ const (
|
|||||||
// 蜂鸟预下单
|
// 蜂鸟预下单
|
||||||
func (a *API) PreCreateByShopFn(basicParams *PreCreateOrder) (deliveryFee, baseDeliveryFee int64, err error) {
|
func (a *API) PreCreateByShopFn(basicParams *PreCreateOrder) (deliveryFee, baseDeliveryFee int64, err error) {
|
||||||
preOrder := a.MakeFnRequestHead()
|
preOrder := a.MakeFnRequestHead()
|
||||||
params := utils.Struct2MapByJson(basicParams)
|
|
||||||
preOrder["business_data"] = params
|
bytes, err := json.Marshal(basicParams)
|
||||||
result, err := a.AccessAPI(ApiURL, "preCreateOrder", RequestPost, params)
|
if err != nil {
|
||||||
|
return 0, 0, err
|
||||||
|
}
|
||||||
|
preOrder["business_data"] = string(bytes)
|
||||||
|
result, err := a.AccessAPI(ApiURL, "preCreateOrder", RequestPost, preOrder)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return 0, 0, err
|
return 0, 0, err
|
||||||
}
|
}
|
||||||
@@ -40,8 +46,19 @@ func (a *API) PreCreateByShopFn(basicParams *PreCreateOrder) (deliveryFee, baseD
|
|||||||
return 0, 0, err
|
return 0, 0, err
|
||||||
}
|
}
|
||||||
|
|
||||||
deliveryFee = utils.Float64TwoInt64(utils.MustInterface2Float64(preOrderResult.GoodsInfos[0].ActualDeliveryAmountCent)) // 订单配送价格
|
// 返回所有可选的商品列表,每项包含当前使用该商品下单时对应的价格等信息,(其中不可用的商品会返回不可用原因) 可挑选其中一个可用的商品进行正式下单。
|
||||||
baseDeliveryFee = utils.Float64TwoInt64(utils.MustInterface2Float64(preOrderResult.GoodsInfos[0].TotalDeliveryAmountCent)) // 订单优惠价格
|
for _, v := range preOrderResult.GoodsInfos {
|
||||||
|
if v.IsValid != 1 {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
deliveryFee = v.ActualDeliveryAmountCent
|
||||||
|
baseDeliveryFee = v.TotalDeliveryAmountCent
|
||||||
|
}
|
||||||
|
|
||||||
|
// 异常检测
|
||||||
|
if deliveryFee == 0 && baseDeliveryFee == 0 {
|
||||||
|
err = errors.New("门店数据异常")
|
||||||
|
}
|
||||||
return deliveryFee, baseDeliveryFee, nil
|
return deliveryFee, baseDeliveryFee, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -57,114 +74,193 @@ func (a *API) CreateOrder(createOrderParam *CreateOrderReqParam) (err error) {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
type ReceiverInfo struct {
|
// addTip 加小费接口
|
||||||
ReceiverName string `json:"receiver_name,omitempty"`
|
func (a *API) AddTip(req *AddTipRes) (err error) {
|
||||||
ReceiverPrimaryPhone string `json:"receiver_primary_phone,omitempty"`
|
if req.PartnerOrderCode == "" && req.OrderId == "" {
|
||||||
ReceiverSecondPhone string `json:"receiver_second_phone,omitempty"`
|
return errors.New("内部订单号或者外部订单号比填写一个")
|
||||||
ReceiverAddress string `json:"receiver_address,omitempty"`
|
}
|
||||||
ReceiverLongitude float64 `json:"receiver_longitude,omitempty"`
|
|
||||||
ReceiverLatitude float64 `json:"receiver_latitude,omitempty"`
|
orderHead := a.MakeFnRequestHead()
|
||||||
PositionSource int `json:"position_source,omitempty"` // 经纬度来源
|
addTipString, err := json.Marshal(req)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
orderHead["businessData"] = string(addTipString)
|
||||||
|
if _, err = a.AccessAPI(ApiURL, "addTip", RequestPost, orderHead); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
type TransportInfo struct {
|
// getCancelReasonList 获取可用取消原因列表(暂油前端写死)
|
||||||
TransportName string `json:"transport_name,omitempty"`
|
func (a *API) GetCancelReasonList(req *GetOrderDetailReq) (result *GetCancelReasonListRes, err error) {
|
||||||
TransportAddress string `json:"transport_address,omitempty"`
|
if req.PartnerOrderCode == "" && req.OrderId == "" {
|
||||||
TransportLongitude float64 `json:"transport_longitude,omitempty"`
|
return nil, errors.New("内部订单号或者外部订单号比填写一个")
|
||||||
TransportLatitude float64 `json:"transport_latitude,omitempty"`
|
}
|
||||||
PositionSource int `json:"position_source,omitempty"` // 经纬度来源
|
|
||||||
TransportTel string `json:"transport_tel,omitempty"`
|
a.timestamp = time.Now().Unix() * 1000
|
||||||
TransportRemark string `json:"transport_remark,omitempty"`
|
orderHead := a.MakeFnRequestHead()
|
||||||
|
business, err := json.Marshal(req)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
orderHead["businessData"] = string(business)
|
||||||
|
data, err := a.AccessAPI(ApiURL, "getCancelReasonList", RequestPost, orderHead)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
cancel := make(map[string]*GetCancelReasonListRes, 0)
|
||||||
|
if k, ok := data["business_data"]; ok {
|
||||||
|
if err := json.Unmarshal([]byte(utils.Interface2String(k)), cancel); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return cancel["cancel_reason_list"], nil
|
||||||
}
|
}
|
||||||
|
|
||||||
type ItemsJSON struct {
|
// preCancelOrder 预取消订单接口,获取取消订单需要扣除的金额
|
||||||
ItemID string `json:"item_id,omitempty"`
|
func (a *API) PreCancelOrder(req *PreCancelOrderReq) (actualCancelCostCent int64, err error) {
|
||||||
ItemName string `json:"item_name,omitempty"`
|
if req.PartnerOrderCode == "" && req.OrderId == "" {
|
||||||
ItemQuantity int `json:"item_quantity,omitempty"`
|
return 0, errors.New("内部订单号或者外部订单号比填写一个")
|
||||||
ItemPrice float64 `json:"item_price"`
|
}
|
||||||
ItemActualPrice float64 `json:"item_actual_price"`
|
orderHead := a.MakeFnRequestHead()
|
||||||
ItemSize int `json:"item_size,omitempty"`
|
business, err := json.Marshal(req)
|
||||||
ItemRemark string `json:"item_remark,omitempty"`
|
if err != nil {
|
||||||
IsNeedPackage int `json:"is_need_package"`
|
return 0, err
|
||||||
IsAgentPurchase int `json:"is_agent_purchase"`
|
}
|
||||||
AgentPurchasePrice float64 `json:"agent_purchase_price,omitempty"`
|
orderHead["businessData"] = string(business)
|
||||||
|
|
||||||
|
data, err := a.AccessAPI(ApiURL, "preCancelOrder", RequestPost, orderHead)
|
||||||
|
if err != nil {
|
||||||
|
return 0, err
|
||||||
|
}
|
||||||
|
|
||||||
|
if k, ok := data["businessData"]; ok {
|
||||||
|
respParam := struct {
|
||||||
|
ActualCancelCostCent int64 `json:"actual_cancel_cost_cent"`
|
||||||
|
}{}
|
||||||
|
if err := json.Unmarshal([]byte(utils.Interface2String(k)), respParam); err != nil {
|
||||||
|
return 0, err
|
||||||
|
}
|
||||||
|
return respParam.ActualCancelCostCent, nil
|
||||||
|
}
|
||||||
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
//order_cancel_reason_code 订单取消原因代码(1:用户取消,2:商家取消)
|
// cancelOrder 取消订单
|
||||||
// order_cancel_code 订单取消编码(
|
func (a *API) CancelOrder(req *CancelOrderReq) (err error) {
|
||||||
// 1:物流原因:订单长时间未分配骑手,
|
if req.PartnerOrderCode == "" && req.OrderId == "" {
|
||||||
// 2:物流原因:分配骑手后,骑手长时间未取件 ,
|
return errors.New("内部订单号或者外部订单号比填写一个")
|
||||||
// 3:物流原因:骑手告知不配送,让取消订单,
|
}
|
||||||
// 4:商品缺货/无法出货/已售完, 5:商户联系不上门店/门店关门了, 6:商户发错单,
|
if req.OrderCancelCode == 0 && req.OrderCancelOtherReason == "" {
|
||||||
// 7:商户/顾客自身定位错误, 8:商户改其他第三方配送, 9:顾客下错单/临时不想要了,
|
return errors.New("请补充退单原因")
|
||||||
// 10:顾客自取/不在家/要求另改时间配送)(0类型已下线)
|
}
|
||||||
|
|
||||||
type CancelOrderParam struct {
|
orderHead := a.MakeFnRequestHead()
|
||||||
PartnerOrderCode string `json:"partner_order_code,omitempty"`
|
business, err := json.Marshal(req)
|
||||||
OrderCancelReasonCode int `json:"order_cancel_reason_code,omitempty"`
|
if err != nil {
|
||||||
OrderCancelCode int `json:"order_cancel_code,omitempty"`
|
return err
|
||||||
OrderCancelDescription string `json:"order_cancel_description,omitempty"`
|
}
|
||||||
OrderCancelTime int64 `json:"order_cancel_time,omitempty"`
|
orderHead["business_data"] = string(business)
|
||||||
|
|
||||||
|
if _, err := a.AccessAPI(ApiURL, "cancelOrder", RequestPost, orderHead); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
// 查询订单详情接口
|
||||||
//func (a *API) CancelOrder(cancelOrderParam *CancelOrderParam) (err error) {
|
func (a *API) QueryOrderDaile(req *GetOrderDetailReq) (result *GetOrderDetailRes, err error) {
|
||||||
// params := utils.Struct2FlatMap(cancelOrderParam)
|
if req.PartnerOrderCode == "" && req.OrderId == "" {
|
||||||
// _, err = a.AccessAPI("v2/order/cancel", URL, params, true)
|
return nil, errors.New("内部订单号或者外部订单号比填写一个")
|
||||||
// return err
|
}
|
||||||
//}
|
|
||||||
//
|
|
||||||
//func (a *API) ComplaintOrder(cancelOrderParam *CancelOrderParam) (err error) {
|
|
||||||
// params := utils.Struct2FlatMap(cancelOrderParam)
|
|
||||||
// _, err = a.AccessAPI("v2/order/complaint", URL, params, true)
|
|
||||||
// return err
|
|
||||||
//}
|
|
||||||
|
|
||||||
type QueryOrderResult struct {
|
orderHead := a.MakeFnRequestHead()
|
||||||
AbnormalCode string `json:"abnormal_code"`
|
bytes, err := json.Marshal(req)
|
||||||
AbnormalDesc string `json:"abnormal_desc"`
|
if err != nil {
|
||||||
CarrierDriverID int `json:"carrier_driver_id"`
|
return nil, err
|
||||||
CarrierDriverName string `json:"carrier_driver_name"`
|
}
|
||||||
CarrierDriverPhone string `json:"carrier_driver_phone"`
|
orderHead["business_data"] = string(bytes)
|
||||||
ComplaintDescription interface{} `json:"complaintDescription"`
|
|
||||||
ComplaintStatus interface{} `json:"complaintStatus"`
|
data, err := a.AccessAPI(ApiURL, "getOrderDetail", RequestPost, orderHead)
|
||||||
EstimateArriveTime int64 `json:"estimate_arrive_time"`
|
if err != nil {
|
||||||
EventLogDetails []struct {
|
return nil, err
|
||||||
CarrierDriverName string `json:"carrier_driver_name"`
|
}
|
||||||
CarrierDriverPhone string `json:"carrier_driver_phone"`
|
|
||||||
OccurTime int64 `json:"occur_time"`
|
if err := json.Unmarshal([]byte(data["business_data"].(string)), &result); err != nil {
|
||||||
OrderStatus int `json:"order_status"`
|
return nil, err
|
||||||
} `json:"event_log_details"`
|
}
|
||||||
HandleID interface{} `json:"handleId"`
|
|
||||||
OrderID interface{} `json:"orderId"`
|
return
|
||||||
OrderStatus int `json:"order_status"`
|
|
||||||
OrderTotalDeliveryCost float64 `json:"order_total_delivery_cost"`
|
|
||||||
OrderTotalDeliveryDiscount interface{} `json:"order_total_delivery_discount"`
|
|
||||||
OvertimeCompensationCost float64 `json:"overtime_compensation_cost"`
|
|
||||||
Reason string `json:"reason"`
|
|
||||||
SupportClaims bool `json:"support_claims"`
|
|
||||||
TrackingID int64 `json:"trackingId"`
|
|
||||||
TrackingID2 int64 `json:"tracking_id"`
|
|
||||||
TransportStationID string `json:"transport_station_id"`
|
|
||||||
TransportStationTel string `json:"transport_station_tel"`
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
// 查询骑手信息
|
||||||
//func (a *API) QueryOrder(partnerOrderCode string) (queryOrderResult *QueryOrderResult, err error) {
|
func (a *API) GetKnightInfo(req *GetOrderDetailReq) (result *GetKnightInfoRes, err error) {
|
||||||
// result, err := a.AccessAPI("v2/order/query", URL, map[string]interface{}{
|
if req.PartnerOrderCode == "" && req.OrderId == "" {
|
||||||
// "partner_order_code": partnerOrderCode,
|
return nil, errors.New("内部订单号或者外部订单号比填写一个")
|
||||||
// }, true)
|
}
|
||||||
// if err == nil {
|
|
||||||
// utils.Map2StructByJson(result["data"], &queryOrderResult, false)
|
orderHead := a.MakeFnRequestHead()
|
||||||
// }
|
bytes, err := json.Marshal(req)
|
||||||
// return queryOrderResult, err
|
if err != nil {
|
||||||
//}
|
return nil, err
|
||||||
//
|
}
|
||||||
//func (a *API) ComplaintRider(partnerOrderCode string, orderComplaintCode int) (err error) {
|
orderHead["business_data"] = string(bytes)
|
||||||
// _, err = a.AccessAPI("v2/order/complaint", URL, map[string]interface{}{
|
|
||||||
// "partner_order_code": partnerOrderCode,
|
data, err := a.AccessAPI(ApiURL, "getKnightInfo", RequestPost, orderHead)
|
||||||
// "order_complaint_code": orderComplaintCode,
|
if err != nil {
|
||||||
// "order_complaint_time": time.Now().UnixNano() / 1e6,
|
return nil, err
|
||||||
// }, true)
|
}
|
||||||
// return err
|
|
||||||
//}
|
if err := json.Unmarshal([]byte(utils.Interface2String(data["business_data"])), &result); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// 余额查询
|
||||||
|
func (a *API) GetAmount() (outAmount map[string]interface{}, err error) {
|
||||||
|
orderHead := a.MakeFnRequestHead()
|
||||||
|
result, err := a.AccessAPI(ApiURL, "getAmount", RequestPost, orderHead)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return result, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// complaintOrder 投诉订单
|
||||||
|
func (a *API) ComplaintOrder(req *ComplaintOrderReq) (err error) {
|
||||||
|
if req.PartnerOrderCode == "" && req.OrderId == "" {
|
||||||
|
return errors.New("内部订单号或者外部订单号比填写一个")
|
||||||
|
}
|
||||||
|
orderHead := a.MakeFnRequestHead()
|
||||||
|
bytes, err := json.Marshal(req)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
orderHead["businessData"] = string(bytes)
|
||||||
|
_, err = a.AccessAPI(ApiURL, "cancelOrder", RequestPost, orderHead)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// claimOrder 索赔订单
|
||||||
|
func (a *API) ClaimOrder(req *ClaimOrderRes) (err error) {
|
||||||
|
if req.PartnerOrderCode == "" && req.OrderId == "" {
|
||||||
|
return errors.New("内部订单号或者外部订单号比填写一个")
|
||||||
|
}
|
||||||
|
orderHead := a.MakeFnRequestHead()
|
||||||
|
bytes, err := json.Marshal(req)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
orderHead["business_data"] = string(bytes)
|
||||||
|
_, err = a.AccessAPI(ApiURL, "claimOrder", RequestPost, orderHead)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|||||||
98
platformapi/fnpsapi_v3/order_test.go
Normal file
98
platformapi/fnpsapi_v3/order_test.go
Normal file
@@ -0,0 +1,98 @@
|
|||||||
|
package fnpsapi
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"testing"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
// 预下单
|
||||||
|
func TestPreOrder(t *testing.T) {
|
||||||
|
api = New("6705486294797503379", "c1e6c280-e618-4103-9d0a-673bc54fb22e", "5375691")
|
||||||
|
token, _ := api.GetAccessToken()
|
||||||
|
api.accessToken = token.BusinessDataObj.AccessToken
|
||||||
|
|
||||||
|
aa := []*GoodsItemsList{
|
||||||
|
{"白菜", 1, 100, 100, "30011", 1, "备注:大白菜"},
|
||||||
|
{"白菜2", 1, 100, 100, "30012", 1, "备注:大白菜2"},
|
||||||
|
// {"白菜3", 1, 100, 100, "1004", 1, "备注:大白菜2"},
|
||||||
|
}
|
||||||
|
deliveryFee, baseDeliveryFee, err := api.PreCreateByShopFn(&PreCreateOrder{
|
||||||
|
PartnerOrderCode: "817102016000041",
|
||||||
|
OrderType: 1,
|
||||||
|
PositionSource: 3,
|
||||||
|
ReceiverAddress: "四川成都",
|
||||||
|
ReceiverLongitude: 104.093445,
|
||||||
|
ReceiverLatitude: 30.661585,
|
||||||
|
GoodsTotalAmountCent: 100,
|
||||||
|
GoodsActualAmountCent: 100,
|
||||||
|
GoodsWeight: 0.25,
|
||||||
|
GoodsCount: 1,
|
||||||
|
GoodsItemList: aa,
|
||||||
|
//OutShopCode: "637910",
|
||||||
|
ChainStoreID: "209476483",
|
||||||
|
})
|
||||||
|
fmt.Println(err)
|
||||||
|
fmt.Println(deliveryFee)
|
||||||
|
fmt.Println(baseDeliveryFee)
|
||||||
|
}
|
||||||
|
|
||||||
|
// 正式下单
|
||||||
|
func TestCreateOrder(t *testing.T) {
|
||||||
|
api = New("6705486294797503379", "c1e6c280-e618-4103-9d0a-673bc54fb22e", "5375691")
|
||||||
|
token, _ := api.GetAccessToken()
|
||||||
|
api.accessToken = token.BusinessDataObj.AccessToken
|
||||||
|
|
||||||
|
aa := []*GoodsItemsList{
|
||||||
|
{"白菜", 1, 100, 100, "30011", 1, "备注:大白菜"},
|
||||||
|
//{"白菜2", 1, 100, 100, "30012", 1, "备注:大白菜2"},
|
||||||
|
// {"白菜3", 1, 100, 100, "1004", 1, "备注:大白菜2"},
|
||||||
|
}
|
||||||
|
err := api.CreateOrder(&CreateOrderReqParam{
|
||||||
|
PartnerOrderCode: "232232999uue21",
|
||||||
|
OrderType: 1,
|
||||||
|
PositionSource: 3,
|
||||||
|
ReceiverAddress: "四川成都",
|
||||||
|
ReceiverLongitude: 113.546508,
|
||||||
|
ReceiverLatitude: 22.188382,
|
||||||
|
GoodsTotalAmountCent: 100,
|
||||||
|
GoodsActualAmountCent: 100,
|
||||||
|
GoodsWeight: 0.25,
|
||||||
|
GoodsCount: 1,
|
||||||
|
GoodsItemList: aa,
|
||||||
|
ReceiverName: "刘磊",
|
||||||
|
ReceiverPrimaryPhone: "18981810340",
|
||||||
|
OutShopCode: "",
|
||||||
|
ChainStoreId: "200008235",
|
||||||
|
})
|
||||||
|
fmt.Println(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// 添加小费
|
||||||
|
func TestAddTip(t *testing.T) {
|
||||||
|
api = New("6705486294797503379", "c1e6c280-e618-4103-9d0a-673bc54fb22e", "5375691")
|
||||||
|
token, _ := api.GetAccessToken()
|
||||||
|
api.accessToken = token.BusinessDataObj.AccessToken
|
||||||
|
|
||||||
|
param := &AddTipRes{}
|
||||||
|
param.OrderId = "817102016000041"
|
||||||
|
param.PartnerOrderCode = "817102016000041"
|
||||||
|
param.AddTipAmountCent = 100
|
||||||
|
param.ThirdIndexId = time.Now().Unix()
|
||||||
|
err := api.AddTip(param)
|
||||||
|
fmt.Println(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// 获取可用取消订单原因
|
||||||
|
func TestGetCancelReasonList(t *testing.T) {
|
||||||
|
api = New("6705486294797503379", "c1e6c280-e618-4103-9d0a-673bc54fb22e", "5375691")
|
||||||
|
token, _ := api.GetAccessToken()
|
||||||
|
api.accessToken = token.BusinessDataObj.AccessToken
|
||||||
|
|
||||||
|
data, err := api.GetCancelReasonList(&GetOrderDetailReq{
|
||||||
|
OrderId: "300000219758073736",
|
||||||
|
//PartnerOrderCode: "817102016000041",
|
||||||
|
})
|
||||||
|
fmt.Println(err)
|
||||||
|
fmt.Println(data)
|
||||||
|
}
|
||||||
@@ -4,43 +4,29 @@ import (
|
|||||||
"encoding/json"
|
"encoding/json"
|
||||||
"fmt"
|
"fmt"
|
||||||
"git.rosy.net.cn/baseapi/utils"
|
"git.rosy.net.cn/baseapi/utils"
|
||||||
"strings"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
|
||||||
StoreNotExist = "门店信息不存在"
|
|
||||||
StoreExist = "该门店已存在"
|
|
||||||
)
|
|
||||||
|
|
||||||
// 获取access_token
|
|
||||||
func (a *API) GetAccessToken() (tokenInfo *TokenInfo, err error) {
|
|
||||||
a.grantType = "authorization_code"
|
|
||||||
a.signature = a.signParam2()
|
|
||||||
result, err := a.AccessAPI(TokenURL, "", RequestPost, nil)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
if err := utils.Map2StructByJson(result["data"], &tokenInfo, false); err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
return tokenInfo, err
|
|
||||||
}
|
|
||||||
|
|
||||||
// 创建门店.
|
// 创建门店.
|
||||||
func (a *API) CreateStore(createStoreParam *CreateStoreBaseInfo) (err error) {
|
func (a *API) CreateStore(createStoreParam *CreateStoreBaseInfo) (err error) {
|
||||||
requestHead := a.MakeFnRequestHead()
|
requestHead := a.MakeFnRequestHead()
|
||||||
params := utils.Struct2FlatMap(createStoreParam)
|
storeByte, err := json.Marshal(createStoreParam)
|
||||||
requestHead["business_data"] = params
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
requestHead["business_data"] = string(storeByte)
|
||||||
_, err = a.AccessAPI(ApiURL, "chainstoreCreate", RequestPost, requestHead)
|
_, err = a.AccessAPI(ApiURL, "chainstoreCreate", RequestPost, requestHead)
|
||||||
|
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
// 更新门店
|
// 更新门店 209636747
|
||||||
func (a *API) UpdateStore(updateStore *UpdateStoreParam) (err error) {
|
func (a *API) UpdateStore(updateStore *UpdateStoreParam) (err error) {
|
||||||
requestHead := a.MakeFnRequestHead()
|
requestHead := a.MakeFnRequestHead()
|
||||||
params := utils.Struct2FlatMap(updateStore)
|
storeByte, err := json.Marshal(updateStore)
|
||||||
requestHead["business_data"] = params
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
requestHead["business_data"] = string(storeByte)
|
||||||
_, err = a.AccessAPI(ApiURL, "chainstoreUpdate", RequestPost, requestHead)
|
_, err = a.AccessAPI(ApiURL, "chainstoreUpdate", RequestPost, requestHead)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@@ -67,7 +53,7 @@ func (a *API) GetStore(storeID string) (getStoreResult *GetOneStoreRespData, err
|
|||||||
params.BusinessData = string(data)
|
params.BusinessData = string(data)
|
||||||
paramsMap := utils.Struct2FlatMap(params)
|
paramsMap := utils.Struct2FlatMap(params)
|
||||||
|
|
||||||
result, err := a.AccessAPI(ApiURL, "chainstoreQuery", RequestGet, paramsMap)
|
result, err := a.AccessAPI(ApiURL, "chainstoreQuery", RequestPost, paramsMap)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@@ -76,30 +62,12 @@ func (a *API) GetStore(storeID string) (getStoreResult *GetOneStoreRespData, err
|
|||||||
return nil, fmt.Errorf("%s", result["msg"])
|
return nil, fmt.Errorf("%s", result["msg"])
|
||||||
}
|
}
|
||||||
|
|
||||||
if data, ok := result["business_data"].([]interface{}); ok {
|
if storeData, ok := result["business_data"]; ok {
|
||||||
utils.Map2StructByJson(data[0], &getStoreResult, false)
|
if err := json.Unmarshal([]byte(utils.Interface2String(storeData)), &getStoreResult); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
err = fmt.Errorf(result["msg"].(string))
|
err = fmt.Errorf(result["msg"].(string))
|
||||||
}
|
}
|
||||||
return getStoreResult, err
|
return getStoreResult, err
|
||||||
}
|
}
|
||||||
|
|
||||||
func IsErrShopNotExist(err error) bool {
|
|
||||||
if err != nil {
|
|
||||||
if strings.Contains(err.Error(), StoreNotExist) {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
func IsErrShopExist(err error) bool {
|
|
||||||
if err != nil {
|
|
||||||
if strings.Contains(err.Error(), StoreExist) {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
//todo商户门店接口,图片上传接口
|
|
||||||
|
|||||||
@@ -432,7 +432,7 @@ type PreCreateByShopParam struct {
|
|||||||
PayTypeCode int `json:"pay_type_code"`
|
PayTypeCode int `json:"pay_type_code"`
|
||||||
GoodsValue float64 `json:"goods_value"`
|
GoodsValue float64 `json:"goods_value"`
|
||||||
GoodsWeight float64 `json:"goods_weight"`
|
GoodsWeight float64 `json:"goods_weight"`
|
||||||
ExpectedDeliveryTime int64 `json:"expected_delivery_time,omitempty"`
|
ExpectedDeliveryTime int64 `json:"expected_delivery_time"`
|
||||||
|
|
||||||
// 以下为可选参数
|
// 以下为可选参数
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user