新增抖音授权登录
This commit is contained in:
@@ -204,4 +204,8 @@ func TestDaDa(t *testing.T) {
|
||||
fmt.Println("美团", 1&0)
|
||||
fmt.Println("达达", 2&0)
|
||||
fmt.Println("蜂鸟", 4&0)
|
||||
fmt.Println("蜂鸟", 19&16 != 0)
|
||||
fmt.Println("蜂鸟", 23&16 != 0)
|
||||
fmt.Println("蜂鸟", 21&16 != 0)
|
||||
fmt.Println("蜂鸟", 11&16 != 0)
|
||||
}
|
||||
|
||||
@@ -228,10 +228,6 @@ func (a *API) signParams(params url.Values) string {
|
||||
}
|
||||
|
||||
func (a *API) AccessAPI2(baseURL, action string, params map[string]interface{}) (retVal *ResponseResult, err error) {
|
||||
// if params == nil {
|
||||
// panic("params is nil!")
|
||||
// }
|
||||
|
||||
params2 := utils.Map2URLValues(params)
|
||||
if baseURL == mtpsAPIURL {
|
||||
params2.Set("appkey", a.appKey)
|
||||
@@ -241,7 +237,6 @@ func (a *API) AccessAPI2(baseURL, action string, params map[string]interface{})
|
||||
} else if a.GetCookieCount() == 0 {
|
||||
return nil, fmt.Errorf("需要设置Store Cookie才能使用此方法")
|
||||
}
|
||||
// baseapi.SugarLogger.Debug(params2.Encode())
|
||||
|
||||
err = platformapi.AccessPlatformAPIWithRetry(a.client,
|
||||
func() *http.Request {
|
||||
|
||||
19
platformapi/mtpsapi/riderInfo.go
Normal file
19
platformapi/mtpsapi/riderInfo.go
Normal file
@@ -0,0 +1,19 @@
|
||||
package mtpsapi
|
||||
|
||||
const (
|
||||
DaDaCode = 10002 // 达达配送
|
||||
FnPsCode = 10004 // 蜂鸟配送
|
||||
MTPsCode = 10032 // 美团配送
|
||||
MyselfPsCode = 10015 // 自送
|
||||
)
|
||||
|
||||
type RiderInfo struct {
|
||||
OrderId string `json:"order_id"` // 发单平台订单id(美团,京西,京,京东)
|
||||
ThirdCarrierOrderId string `json:"third_carrier_order_id"` // 京西平台id
|
||||
CourierName string `json:"courier_name"` // 骑手名称
|
||||
CourierPhone string `json:"courier_phone"` // 骑手电话
|
||||
LogisticsProviderCode string `json:"logistics_provider_code"` // 配送平台code 10001-顺丰, 10002-达达, 10003-闪送, 10004-蜂鸟, 10005 UU跑腿,10006 快跑者, 10007 极客快送,10008-点我达,10009 同达, 10010-生活半径,10011 邻趣,10012 趣送, 10013 快服务 10014 菜鸟新配盟 10015 商家自建配送 10016 风先生,10017-其他,10032-美团跑腿
|
||||
LogisticsStatus int `json:"logistics_status"` // 配送状态
|
||||
Latitude string `json:"latitude"` // 骑手当前的纬度,美团使用的是高德坐标系。
|
||||
Longitude string `json:"longitude"` // 骑手当前的经度,美团使用的是高德坐标系。
|
||||
}
|
||||
@@ -659,3 +659,10 @@ func (a *API) OrderUpdateTip(orderID int64, tipAmount float64) (err error) {
|
||||
_, err = a.AccessAPI("order/zhongbao/update/tip", true, params)
|
||||
return err
|
||||
}
|
||||
|
||||
// 美团外卖自配送商家同步发货状态和配送信息(推荐)
|
||||
// https://waimaiopen.meituan.com/api/v1/ecommerce/order/logistics/sync
|
||||
func (a *API) OrderStatusAndPsInfo(params map[string]interface{}) (err error) {
|
||||
_, err = a.AccessAPI("ecommerce/order/logistics/sync", false, params)
|
||||
return err
|
||||
}
|
||||
|
||||
198
platformapi/sfps/callback.go
Normal file
198
platformapi/sfps/callback.go
Normal file
@@ -0,0 +1,198 @@
|
||||
package fnpsapi
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"git.rosy.net.cn/baseapi"
|
||||
"io/ioutil"
|
||||
"net/http"
|
||||
)
|
||||
|
||||
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"`
|
||||
}
|
||||
|
||||
//#region 订单
|
||||
|
||||
// 订单状态
|
||||
type OrderStatusNottify struct {
|
||||
CallbackBusinessType string `json:"callback_business_type"`
|
||||
Param *OrderCallbackParam `json:"param"`
|
||||
}
|
||||
|
||||
// 订单状态回调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非转单
|
||||
}
|
||||
|
||||
//#endregion
|
||||
// 门店状态回调
|
||||
type ChainstoreStatusNotify struct {
|
||||
CallbackBusinessType string `json:"callback_business_type"`
|
||||
Param *ChainstoreParam `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"` // 门店认证、修改等驳回时返回原因
|
||||
}
|
||||
|
||||
// 出餐回调
|
||||
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"` // 状态推送时间 (毫秒)
|
||||
}
|
||||
|
||||
// 异常状态回掉
|
||||
type AbnormalStatusNotify struct {
|
||||
CallbackBusinessType string `json:"callback_business_type"`
|
||||
Param *AbnormalReportNotify `json:"param"`
|
||||
}
|
||||
|
||||
// 异常状态回调
|
||||
type AbnormalReportNotify struct {
|
||||
OrderId int64 `json:"order_id"` // 订单号
|
||||
AppId string `json:"app_id"` // 应用id
|
||||
PartnerOrderCode string `json:"partner_order_code"` // 外部订单号
|
||||
CarrierDriverId int64 `json:"carrier_driver_id"` // 骑手id
|
||||
Longitude string `json:"longitude"` // 纬度
|
||||
Latitude string `json:"latitude"` // 门店纬度
|
||||
AbnormalCode string `json:"abnormal_code"` // 异常报备code
|
||||
AbnormalDesc string `json:"abnormal_desc"` // 异常报备描述
|
||||
AbnormalReportTime int64 `json:"abnormal_report_time"` // 异常报备时间 毫秒
|
||||
|
||||
}
|
||||
|
||||
// 获取门店状态回调消息
|
||||
func (a *API) GetChainstoreStatusNotify(request *http.Request) (shopStatusMsg *ChainstoreStatusNotify, callbackResponse *CallbackResponse) {
|
||||
data, err := ioutil.ReadAll(request.Body)
|
||||
if err != nil {
|
||||
callbackResponse = &CallbackResponse{Code: -1}
|
||||
return nil, callbackResponse
|
||||
}
|
||||
|
||||
storeNotify := &ShortStatus{}
|
||||
if err := json.Unmarshal(data, &storeNotify); err != nil {
|
||||
baseapi.SugarLogger.Debugf("FN GetChainstoreStatusNotify 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 GetChainstoreStatusNotify failed with err:%v", err)
|
||||
callbackResponse = &CallbackResponse{Code: -1}
|
||||
return nil, callbackResponse
|
||||
}
|
||||
|
||||
return fnNotify, SuccessResponse
|
||||
}
|
||||
|
||||
// 获取订单状态回调消息
|
||||
func (a *API) GetChainOrderStatusNotify(request *http.Request) (shopStatusMsg *OrderStatusNottify, callbackResponse *CallbackResponse) {
|
||||
data, err := ioutil.ReadAll(request.Body)
|
||||
if err != nil {
|
||||
baseapi.SugarLogger.Debugf("FN GetChainOrderStatusNotify failed with No result msg err:%v", err)
|
||||
callbackResponse = &CallbackResponse{Code: -1}
|
||||
return nil, callbackResponse
|
||||
}
|
||||
|
||||
result := &ShortStatus{}
|
||||
if err := json.Unmarshal(data, &result); err != nil {
|
||||
callbackResponse = &CallbackResponse{Code: -1}
|
||||
return nil, callbackResponse
|
||||
}
|
||||
|
||||
orderResult := &OrderStatusNottify{}
|
||||
if err := json.Unmarshal([]byte(result.BusinessData), orderResult); err != nil {
|
||||
callbackResponse = &CallbackResponse{Code: -1}
|
||||
return nil, callbackResponse
|
||||
}
|
||||
return orderResult, SuccessResponse
|
||||
}
|
||||
|
||||
// 异常配送
|
||||
func (a *API) GetChainAbnormaltatusNotify(request *http.Request) (shopStatusMsg *AbnormalStatusNotify, callbackResponse *CallbackResponse) {
|
||||
data, err := ioutil.ReadAll(request.Body)
|
||||
if err != nil {
|
||||
baseapi.SugarLogger.Debugf("FN GetChainOrderStatusNotify failed with No result msg err:%v", err)
|
||||
callbackResponse = &CallbackResponse{Code: -1}
|
||||
return nil, callbackResponse
|
||||
}
|
||||
|
||||
storeNotify := &ShortStatus{}
|
||||
if err := json.Unmarshal(data, &storeNotify); err != nil {
|
||||
baseapi.SugarLogger.Debugf("FN GetShopStatusCallbackMsg failed with err:%v", err)
|
||||
callbackResponse = &CallbackResponse{Code: -1}
|
||||
return nil, callbackResponse
|
||||
}
|
||||
|
||||
fnNotify := &AbnormalStatusNotify{}
|
||||
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
|
||||
}
|
||||
|
||||
return fnNotify, SuccessResponse
|
||||
}
|
||||
|
||||
func (a *API) CheckCallbackValidation(request *http.Request) (callbackResponse *CallbackResponse) {
|
||||
err := request.ParseForm()
|
||||
if err != nil {
|
||||
callbackResponse = Err2CallbackResponse(err, "")
|
||||
}
|
||||
return callbackResponse
|
||||
}
|
||||
274
platformapi/sfps/order.go
Normal file
274
platformapi/sfps/order.go
Normal file
@@ -0,0 +1,274 @@
|
||||
package fnpsapi
|
||||
|
||||
//
|
||||
//import (
|
||||
// "encoding/json"
|
||||
// "errors"
|
||||
// "git.rosy.net.cn/baseapi/utils"
|
||||
// "time"
|
||||
//)
|
||||
//
|
||||
//const (
|
||||
// OrderCancelReson0 = 0 // 0:其它(必填原因)必须填写原因
|
||||
// OrderCancelReson1 = 1 // 1:物流原因:订单长时间未分配骑手
|
||||
// OrderCancelReson4 = 4 // 4:商品缺货/无法出货/已售完,
|
||||
// OrderCancelReson6 = 6 // 6:商户发错单,
|
||||
// OrderCancelReson7 = 7 // 7:商户/顾客自身定位错误,
|
||||
// OrderCancelReson8 = 8 // 8:商户改其他第三方配送,
|
||||
// OrderCancelReson9 = 9 // 9:顾客下错单/临时不想要了,
|
||||
// OrderCancelReson10 = 10 // 10:顾客自取/不在家/要求另改时间配送)(0类型已下线)
|
||||
// OrderCancelReson32 = 32 // 32:订单信息填写错误
|
||||
// OrderCancelReson36 = 36 // 36:重复下单了
|
||||
// OrderCancelReson2 = 2 // 2:物流原因:分配骑手后,骑手长时间未取件(类型已下线)
|
||||
// OrderCancelReson3 = 3 // 3:物流原因:骑手告知不配送,让取消订单(类型已下线)
|
||||
// OrderCancelReson5 = 5 // 5:商户联系不上门店/门店关门了(类型已下线)
|
||||
//
|
||||
// OrderStatusAcceptCreate = 0 //订单生成
|
||||
// OrderStatusAcceptCacle = 4 //订单取消
|
||||
// OrderStatusAccept = 1 //系统已接单
|
||||
// OrderStatusAssigned = 20 //已分配骑手
|
||||
// OrderStatusArrived = 80 //已到店
|
||||
// OrderStatusDelivering = 2 //配送中
|
||||
// OrderStatusDelivered = 3 //已送达
|
||||
// OrderStatusException = 5 //异常
|
||||
//)
|
||||
//
|
||||
//// 蜂鸟预下单
|
||||
//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
|
||||
// }
|
||||
//
|
||||
// // 返回所有可选的商品列表,每项包含当前使用该商品下单时对应的价格等信息,(其中不可用的商品会返回不可用原因) 可挑选其中一个可用的商品进行正式下单。
|
||||
// var deliveryFeeFn int64
|
||||
// var baseDeliveryFeeFn int64
|
||||
// for _, v := range preOrderResult.GoodsInfos {
|
||||
// if v.IsValid != 1 {
|
||||
// continue
|
||||
// }
|
||||
// deliveryFeeFn = v.ActualDeliveryAmountCent
|
||||
// baseDeliveryFeeFn = v.TotalDeliveryAmountCent
|
||||
// }
|
||||
//
|
||||
// // 异常检测
|
||||
// if deliveryFeeFn == 0 && baseDeliveryFeeFn == 0 {
|
||||
// return 0, 0, errors.New(preOrderResult.GoodsInfos[0].DisableReason)
|
||||
// }
|
||||
// return deliveryFeeFn, baseDeliveryFeeFn, nil
|
||||
//}
|
||||
//
|
||||
//// 蜂鸟正式下单
|
||||
//func (a *API) CreateOrder(createOrderParam *CreateOrderReqParam) (result string, err error) {
|
||||
// orderHead := a.MakeFnRequestHead()
|
||||
// bytes, err := json.Marshal(createOrderParam)
|
||||
// if err != nil {
|
||||
// return "", err
|
||||
// }
|
||||
// orderHead["business_data"] = string(bytes)
|
||||
// resultData, err := a.AccessAPI(ApiURL, "createOrder", RequestPost, orderHead)
|
||||
// if orderId, ok := resultData["business_data"]; ok {
|
||||
// res := &CreateOrderRes{}
|
||||
// if err := json.Unmarshal([]byte(utils.Interface2String(orderId)), res); err != nil {
|
||||
// return "", err
|
||||
// }
|
||||
// return utils.Int64ToStr(res.OrderId), nil
|
||||
// }
|
||||
// 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 {
|
||||
// return utils.MustInterface2Int64(k), 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 == "" {
|
||||
// req.OrderCancelOtherReason = "暂时不想要了"
|
||||
// }
|
||||
//
|
||||
// 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
|
||||
//}
|
||||
//
|
||||
//// 查询订单详情接口
|
||||
//func (a *API) QueryOrder(partnerOrderCode string) (result *GetOrderDetailRes, err error) {
|
||||
// orderHead := a.MakeFnRequestHead()
|
||||
// bytes, err := json.Marshal(&GetOrderDetailReq{PartnerOrderCode: partnerOrderCode})
|
||||
// if err != nil {
|
||||
// return nil, err
|
||||
// }
|
||||
//
|
||||
// orderHead["business_data"] = string(bytes)
|
||||
// data, err := a.AccessAPI(ApiURL, "getOrderDetail", RequestPost, orderHead)
|
||||
// if err != nil {
|
||||
// return nil, err
|
||||
// }
|
||||
//
|
||||
// fnResult := &GetOrderDetailRes{}
|
||||
// if err := json.Unmarshal([]byte(data["business_data"].(string)), &fnResult); err != nil {
|
||||
// return nil, err
|
||||
// }
|
||||
// return fnResult, nil
|
||||
//}
|
||||
//
|
||||
//// 查询骑手信息
|
||||
//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
|
||||
// }
|
||||
//
|
||||
// fnResult := &GetKnightInfoRes{}
|
||||
// if err := json.Unmarshal([]byte(utils.Interface2String(data["business_data"])), &fnResult); err != nil {
|
||||
// return nil, err
|
||||
// }
|
||||
// return fnResult, nil
|
||||
//}
|
||||
//
|
||||
//// 余额查询
|
||||
//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_code 订单取消编码(
|
||||
//// 1:物流原因:订单长时间未分配骑手,
|
||||
//// 2:物流原因:分配骑手后,骑手长时间未取件 ,
|
||||
//// 3:物流原因:骑手告知不配送,让取消订单,
|
||||
//// 4:商品缺货/无法出货/已售完, 5:商户联系不上门店/门店关门了, 6:商户发错单,
|
||||
//// 7:商户/顾客自身定位错误, 8:商户改其他第三方配送, 9:顾客下错单/临时不想要了,
|
||||
//// 10:顾客自取/不在家/要求另改时间配送)(0类型已下线)
|
||||
//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
|
||||
//}
|
||||
//
|
||||
//func (a *API) ComplaintRider(partnerOrderCode string, orderComplaintCode int) (err error) {
|
||||
// orderHead := a.MakeFnRequestHead()
|
||||
//
|
||||
// bytes, err := json.Marshal(map[string]interface{}{
|
||||
// "partner_order_code": partnerOrderCode,
|
||||
// "order_complaint_code": orderComplaintCode,
|
||||
// })
|
||||
// if err != nil {
|
||||
// return err
|
||||
// }
|
||||
// orderHead["businessData"] = string(bytes)
|
||||
// _, err = a.AccessAPI(ApiURL, "cancelOrder", RequestPost, orderHead)
|
||||
// return err
|
||||
//}
|
||||
159
platformapi/sfps/sf_base.go
Normal file
159
platformapi/sfps/sf_base.go
Normal file
@@ -0,0 +1,159 @@
|
||||
package fnpsapi
|
||||
|
||||
import (
|
||||
"git.rosy.net.cn/baseapi/platformapi"
|
||||
"net/http"
|
||||
"sync"
|
||||
)
|
||||
|
||||
const (
|
||||
ApiURL = "https://openic.sf-express.com" // 正式环境
|
||||
RequestPost = "POST"
|
||||
)
|
||||
|
||||
// 物品类型product_type枚举值:
|
||||
const (
|
||||
FastFood = 1 // 快餐
|
||||
Drugs = 2 // 药品
|
||||
DepartmentStore = 3 // 百货
|
||||
OldClothes = 4 // 脏衣服收
|
||||
NewClothes = 5 // 干净衣服派
|
||||
Fresh = 6 // 生鲜
|
||||
HighDrinks = 8 // 高端饮品
|
||||
SiteInspection = 9 // 现场勘验
|
||||
Express = 10 // 快递
|
||||
File = 12 // 文件
|
||||
Cake = 13 // 蛋糕
|
||||
Flower = 14 // 鲜花
|
||||
Digital = 15 // 数码
|
||||
Clothing = 16 // 服装
|
||||
Car = 17 // 汽配
|
||||
Jewellery = 18 // 珠宝
|
||||
Pizza = 20 // 披萨
|
||||
ChineseFood = 21 // 中餐
|
||||
FreshwaterFresh = 22 // 水产
|
||||
DirectDelivery = 27 // 专人直送
|
||||
MidRangeDrinks = 32 // 中端饮品
|
||||
ConvenienceStore = 33 // 便利店
|
||||
Bakeries = 34 // 面包糕点
|
||||
HotPot = 35 // 火锅
|
||||
licence = 36 // 证照
|
||||
Crayfish = 40 // 烧烤小龙虾
|
||||
OtherInfo = 41 // 外部落地配
|
||||
AlcoholAndTobacco = 47 // 烟酒行
|
||||
AdultEroticaProducts = 48 // 成人用品
|
||||
Other = 99 // 其他
|
||||
)
|
||||
|
||||
// 注册请求api
|
||||
type API struct {
|
||||
devId string `json:"dev_id"`
|
||||
devKey string `json:"dev_key"`
|
||||
signature string `json:"sign"`
|
||||
pushTime int64 `json:"push_time"`
|
||||
locker sync.RWMutex
|
||||
client *http.Client
|
||||
config *platformapi.APIConfig
|
||||
}
|
||||
|
||||
/************************************************订单*****************************************************/
|
||||
//#region 获取蜂鸟门店信息
|
||||
|
||||
// 创建订单
|
||||
type CreateOrder struct {
|
||||
// 必填
|
||||
DevId int64 `json:"dev_id"` // 同城开发者ID
|
||||
ShopId string `json:"shop_id"` // 店铺ID
|
||||
ShopOrderId string `json:"shop_order_id"` // 商家订单号不允许重复
|
||||
OrderSource string `json:"order_source"` // 订单接入来源 1:美团;2:饿了么;3:百度;4:口碑;其他请直接填写中文字符串值
|
||||
LbsType int `json:"lbs_type"` // 坐标类型 1:百度坐标,2:高德坐标
|
||||
PayType int64 `json:"pay_type"` // 用户支付方式 1:已付款 0:货到付款
|
||||
OrderTime int64 `json:"order_time"` // 用户下单时间 秒级时间戳
|
||||
IsAppoint int `json:"is_appoint"` // 是否是预约单 0:非预约单;1:预约单
|
||||
IsInsured int64 `json:"is_insured"` // 是否保价,0:非保价;1:保价
|
||||
IsPriorityAssign int64 `json:"is_priority_assign"` // 是否优先派单,0:否 1:是
|
||||
IsPersonDirect int64 `json:"is_person_direct"` // 是否是专人直送订单,0:否;1:是
|
||||
PushTime int64 `json:"push_time"` // 推单时间 秒级时间戳
|
||||
Version int64 `json:"version"` // 版本号 参照文档主版本号填写 如:文档版本号1.7,version=17
|
||||
Receive *ReceiveAddress `json:"receive"` // 收货人信息
|
||||
Shop *SfShopInfo `json:"shop"` // 发货店铺信息 Obj,详见shop结构, 平台级开发者(如饿了么)需传入如无特殊说明此字段可忽略
|
||||
OrderDetail *OrderDetails `json:"order_detail"` // 订单详情
|
||||
MultiPickupInfo []*MultiPickupDetails `json:"multi_pickup_info"` // 多点取货信息
|
||||
// 非必填
|
||||
ShopType int64 `json:"shop_type"` // 店铺ID类型 1:顺丰店铺ID ;2:接入方店铺ID
|
||||
ShopPreparationTime int64 `json:"shop_preparation_time"` // 商家预计备餐时长(分10)
|
||||
OrderSequence string `json:"order_sequence"` // 取货序号 与order_source配合使用 如:饿了么10号单,表示如下:order_source=2;order_sequence=10。用于骑士快速寻找配送物
|
||||
AppointType int `json:"appoint_type"` // 预约单类型 预约单的时候传入,1:预约单送达单;2:预约单上门单
|
||||
ExpectTime int64 `json:"expect_time"` // 用户期望送达时间 若传入自此段且时间大于配送时效,则按照预约送达单处理,时间小于配送时效按照立即单处理;appoint_type=1时需必传,秒级时间戳;
|
||||
ExpectPickupTime int64 `json:"expect_pickup_time"` // 用户期望上门时间 appoint_type=2时需必传,秒级时间戳
|
||||
ShopExpectTime int64 `json:"shop_expect_time"` // 商家期望送达时间 只展示给骑士,不参与时效考核;秒级时间戳
|
||||
Vehicle int `json:"vehicle"` // 配送交通工具,0:否;1:电动车;2:小轿车
|
||||
DeclaredValue int64 `json:"declared_value"` // 保价金额(单位:分)
|
||||
GratuityFee int64 `json:"gratuity_fee"` // 订单小费,不传或者传0为不加小费 单位分,加小费最低不能少于100分
|
||||
Remark string `json:"remark"` // 订单备注
|
||||
RiderPickMethod int64 `json:"rider_pick_method"` // 物流流向 1:从门店取件送至用户; 2:从用户取件送至门店
|
||||
ReturnFlag int `json:"return_flag"` // 返回字段控制标志位(二进制) 1:商品总价格,2:配送距离,4:物品重量,8:起送时间,16:期望送达时间,32:支付费用,64:实际支付金额,128:优惠券总金额,256:结算方式 例如全部返回为填入511
|
||||
|
||||
}
|
||||
|
||||
// 发货店铺信息,必填
|
||||
type SfShopInfo struct {
|
||||
ShopName string `json:"shop_name"` // 店铺名称
|
||||
ShopPhone string `json:"shop_phone"` // 店铺电话
|
||||
ShopAddress string `json:"shop_address"` // 店铺地址
|
||||
ShopLng string `json:"shop_lng"` // 店铺经度
|
||||
ShopLat string `json:"shop_lat"` // 店铺纬度
|
||||
}
|
||||
|
||||
// 收货人信息
|
||||
type ReceiveAddress struct {
|
||||
// 必填
|
||||
UserName string `json:"user_name"` // 用户姓名
|
||||
UserPhone string `json:"user_phone"` // 用户电话
|
||||
UserAddress string `json:"user_address"` // 用户地址
|
||||
UserLng string `json:"user_lng"` // 用户经度
|
||||
UserLat string `json:"user_lat"` // 用户纬度
|
||||
// 非必填
|
||||
CityName string `json:"city_name"` // 发单城市
|
||||
}
|
||||
|
||||
// 订单详情
|
||||
type OrderDetails struct {
|
||||
// 必填
|
||||
TotalPrice int64 `json:"total_price"` // 订单金额 分
|
||||
ProductType int64 `json:"product_type"` // 物品类型 枚举值见下面定义
|
||||
WeightGram int64 `json:"weight_gram"` // 物品重量(单位:克)
|
||||
ProductNum int64 `json:"product_num"` // 物品个数
|
||||
ProductTypeNum int64 `json:"product_type_num"` // 物品种类个数
|
||||
ProductDetail []*ProductDetail `json:"product_detail"` // 物品详情;数组结构,详见product_detail结构
|
||||
// 非必填
|
||||
UserMoney int64 `json:"user_money"` // 用户实付商家金额(单位:分)
|
||||
ShopMoney int `json:"shop_money"` // 商家实收用户金额(单位:分)
|
||||
VolumeLitre int64 `json:"volume_litre"` // 物品体积(单位:升)
|
||||
DeliveryMoney int64 `json:"delivery_money"` // 商家收取用户的配送费(单位:分)
|
||||
}
|
||||
|
||||
// 购买物品详情清单
|
||||
type ProductDetail struct {
|
||||
// 必填
|
||||
ProductName string `json:"product_name"` // 物品名称
|
||||
ProductNum int64 `json:"product_num"` // 物品数量
|
||||
// 非必填
|
||||
ProductId int64 `json:"product_id"` // 物品ID
|
||||
ProductPrice int64 `json:"product_price"` // 物品价格
|
||||
ProductUnit string `json:"product_unit"` // 物品单位
|
||||
ProductRemark string `json:"product_remark"` // 备注
|
||||
ItemDetail string `json:"item_detail"` // 详情
|
||||
}
|
||||
|
||||
// 取货地址详情
|
||||
type MultiPickupDetails struct {
|
||||
PickupShopAddress string `json:"pickup_shop_address"` // 取货点地址
|
||||
PickupShopPhone string `json:"pickup_shop_phone"` // 取货点店铺手机号
|
||||
PickupShopName string `json:"pickup_shop_name"` // 取货点店铺名称
|
||||
PickupLng string `json:"pickup_lng"` // 取货点经度
|
||||
PickupLat string `json:"pickup_lat"` // 取货点纬度
|
||||
PickupProducts string `json:"pickup_products"` // 取货点店铺物品信息
|
||||
}
|
||||
|
||||
//#endregion
|
||||
208
platformapi/sfps/sf_test.go
Normal file
208
platformapi/sfps/sf_test.go
Normal file
@@ -0,0 +1,208 @@
|
||||
package fnpsapi
|
||||
|
||||
//
|
||||
//import (
|
||||
// "encoding/json"
|
||||
// "fmt"
|
||||
// "git.rosy.net.cn/baseapi"
|
||||
// "go.uber.org/zap"
|
||||
// "testing"
|
||||
//)
|
||||
//
|
||||
//var (
|
||||
// api *API
|
||||
// sugarLogger *zap.SugaredLogger
|
||||
//)
|
||||
//
|
||||
//func init() {
|
||||
// logger, _ := zap.NewDevelopment()
|
||||
// sugarLogger = logger.Sugar()
|
||||
// baseapi.Init(sugarLogger)
|
||||
//
|
||||
// //api = New("6705486294797503379", "c1e6c280-e618-4103-9d0a-673bc54fb22e", "5375691", "cabrXQf9eFMVWVYg4hNlwu")
|
||||
// //token, _ := api.GetAccessToken()
|
||||
// //api.accessToken = token.BusinessDataObj.AccessToken
|
||||
//}
|
||||
//
|
||||
//// 查询单个门店
|
||||
//func TestQueryOneStore(t *testing.T) {
|
||||
// api = New("6705486294797503379", "c1e6c280-e618-4103-9d0a-673bc54fb22e", "5375691", "")
|
||||
// token, err := api.GetAccessToken()
|
||||
// api.accessToken = token.BusinessDataObj.AccessToken
|
||||
// data, err := api.GetStore("209476483")
|
||||
// fmt.Println(data)
|
||||
// fmt.Println(err)
|
||||
//}
|
||||
//
|
||||
//// 正式下单
|
||||
//func TestCreateOrder(t *testing.T) {
|
||||
// api = New("6705486294797503379", "c1e6c280-e618-4103-9d0a-673bc54fb22e", "5375691", "")
|
||||
// token, err := api.GetAccessToken()
|
||||
// fmt.Println("22222222222", err)
|
||||
// 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: "232232992229uue21",
|
||||
// OrderType: 1,
|
||||
// PositionSource: 3,
|
||||
// ReceiverAddress: "四川成都",
|
||||
// ReceiverLongitude: 116.307892,
|
||||
// ReceiverLatitude: 40.039115,
|
||||
// GoodsTotalAmountCent: 100,
|
||||
// GoodsActualAmountCent: 100,
|
||||
// GoodsWeight: 0.25,
|
||||
// GoodsCount: 1,
|
||||
// GoodsItemList: aa,
|
||||
// ReceiverName: "刘磊",
|
||||
// ReceiverPrimaryPhone: "18981810340",
|
||||
// OutShopCode: "",
|
||||
// ChainStoreId: "209476483",
|
||||
// })
|
||||
// fmt.Println(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 TestClient(t *testing.T) {
|
||||
// api = New("6705486294797503379", "c1e6c280-e618-4103-9d0a-673bc54fb22e", "51658", "4W4hqacKND6NOct5gCyjbT")
|
||||
// token, err := api.GetAccessToken()
|
||||
// api.accessToken = token.BusinessDataObj.AccessToken
|
||||
// fmt.Println("token===", token.BusinessDataObj.AccessToken)
|
||||
// fmt.Println("err=====", err)
|
||||
//}
|
||||
//
|
||||
//// 预下单
|
||||
//func TestGetOrder(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,
|
||||
// //ServiceGoodsId: nil,
|
||||
// //BaseGoodsId: nil,
|
||||
// //OutShopCode: "637910",
|
||||
// ChainStoreID: "209476483",
|
||||
// })
|
||||
// fmt.Println(err)
|
||||
// fmt.Println(deliveryFee)
|
||||
// fmt.Println(baseDeliveryFee)
|
||||
//}
|
||||
//
|
||||
//func TestDataUnmas(t *testing.T) {
|
||||
// data := `{"signature":"5a4270c8fb3c4a3a641d2f5f66990c503c7248ecd51248b020e0b44db75a6761","app_id":"6705486294797503379","timestamp":"1648861445686","business_data":"{\"callback_business_type\":\"orderStatusNotify\",\"param\":{\"app_id\":\"6705486294797503379\",\"carrier_driver_name\":\"\",\"carrier_driver_phone\":\"\",\"order_id\":300000388333833530,\"order_status\":1,\"partner_order_code\":\"88386523916938\",\"push_time\":1648861445686,\"transfer\":0}}"}`
|
||||
// fnNotify := &ShortStatus{}
|
||||
// if err := json.Unmarshal([]byte(data), fnNotify); err != nil {
|
||||
// baseapi.SugarLogger.Debugf("FN callback string to ChainstoreStatusNotify failed with err:%v", err)
|
||||
// }
|
||||
//
|
||||
// fmt.Println("data", fnNotify.BusinessData)
|
||||
// fmt.Println("data", fnNotify.AppId)
|
||||
// fmt.Println("data", fnNotify.Signature)
|
||||
//
|
||||
// retsult := &OrderStatusNottify{}
|
||||
// err := json.Unmarshal([]byte(fnNotify.BusinessData), retsult)
|
||||
// fmt.Println("err1======", err)
|
||||
// fmt.Println("retsult", retsult)
|
||||
// fmt.Println("retsult", retsult.Param)
|
||||
// fmt.Println("retsult", retsult.CallbackBusinessType)
|
||||
// fmt.Println("retsult", retsult.Param.PartnerOrderCode)
|
||||
//}
|
||||
//
|
||||
//func TestDaDa(t *testing.T) {
|
||||
// fmt.Println("美团", 1&1)
|
||||
// fmt.Println("达达", 2&1)
|
||||
// fmt.Println("蜂鸟", 4&1)
|
||||
//
|
||||
// fmt.Println("美团", 1&0)
|
||||
// fmt.Println("达达", 2&0)
|
||||
// fmt.Println("蜂鸟", 4&0)
|
||||
//}
|
||||
141
platformapi/sfps/sfpsapi.go
Normal file
141
platformapi/sfps/sfpsapi.go
Normal file
@@ -0,0 +1,141 @@
|
||||
package fnpsapi
|
||||
|
||||
import (
|
||||
"crypto/md5"
|
||||
"encoding/base64"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"net/http"
|
||||
"strings"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"git.rosy.net.cn/baseapi"
|
||||
"git.rosy.net.cn/baseapi/platformapi"
|
||||
"git.rosy.net.cn/baseapi/utils"
|
||||
)
|
||||
|
||||
//func (a *API) SetToken(token string) {
|
||||
// a.locker.Lock()
|
||||
// defer a.locker.Unlock()
|
||||
// a.accessToken = token
|
||||
//}
|
||||
//
|
||||
//func (a *API) SetRefreshToken(token string) {
|
||||
// a.locker.Lock()
|
||||
// defer a.locker.Unlock()
|
||||
// a.refreshToken = token
|
||||
//}
|
||||
//
|
||||
//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(devId, devKey string, config ...*platformapi.APIConfig) *API {
|
||||
curConfig := platformapi.DefAPIConfig
|
||||
if len(config) > 0 {
|
||||
curConfig = *config[0]
|
||||
}
|
||||
|
||||
// 查询蜂鸟refeshToken
|
||||
return &API{
|
||||
devId: devId,
|
||||
devKey: devKey,
|
||||
locker: sync.RWMutex{},
|
||||
client: &http.Client{Timeout: curConfig.ClientTimeout},
|
||||
config: &curConfig,
|
||||
}
|
||||
}
|
||||
|
||||
func (a *API) signParam(params []byte) (sig string) {
|
||||
sign := fmt.Sprintf("%s&%s&%s", string(params), a.devId, a.devKey)
|
||||
md2sign := md5.Sum([]byte(sign))
|
||||
return base64.StdEncoding.EncodeToString(md2sign[:])
|
||||
}
|
||||
|
||||
func (a *API) AccessAPI(baseUrl, actionApi, method string, bizParams map[string]interface{}) (retVal map[string]interface{}, err error) {
|
||||
bizParams["push_time"] = utils.Int64ToStr(time.Now().Unix())
|
||||
signParam, err := json.Marshal(bizParams)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
//bizParams["sign"] = a.signParam(signParam)
|
||||
//data, err := json.Marshal(bizParams)
|
||||
//if err != nil {
|
||||
// return nil, err
|
||||
//}
|
||||
|
||||
// 全路径请求参数
|
||||
fullURL := utils.GenerateGetURL(baseUrl, actionApi, map[string]interface{}{"sign": a.signParam(signParam)})
|
||||
|
||||
// 发送请求
|
||||
sendUrl := func() *http.Request {
|
||||
var request *http.Request
|
||||
request, _ = http.NewRequest(http.MethodPost, fullURL, strings.NewReader(string(signParam)))
|
||||
request.Header.Set("Content-Type", "application/json")
|
||||
return request
|
||||
}
|
||||
|
||||
// 数据解析
|
||||
dataMarshal := 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 {
|
||||
return "", err
|
||||
}
|
||||
if utils.MustInterface2Int64(jsonResult1["code"]) != 200 {
|
||||
errLevel = platformapi.ErrLevelGeneralFail
|
||||
err = utils.NewErrorCode(jsonResult1["msg"].(string), utils.Int64ToStr(utils.MustInterface2Int64(jsonResult1["code"])))
|
||||
baseapi.SugarLogger.Debugf("sfps 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
|
||||
}
|
||||
|
||||
//
|
||||
//// 获取access_token
|
||||
//func (a *API) GetAccessToken() (tokenInfo *TokenInfo, err error) {
|
||||
// parameter := make(map[string]interface{}, 6)
|
||||
// parameter["grant_type"] = "refresh_token"
|
||||
// parameter["app_id"] = a.appID
|
||||
// parameter["merchant_id"] = a.merchantId
|
||||
//
|
||||
// // 先去刷新token,没有的话再去获取token(code只能使用一次,生成的token管一年)
|
||||
// var result map[string]interface{}
|
||||
// switch {
|
||||
// case a.accessToken != "" && a.refreshToken != "":
|
||||
// parameter["refresh_token"] = a.refreshToken
|
||||
// result, err = a.AccessAPI(RefreshTokenUrl, "", RequestPost, parameter)
|
||||
// case a.accessToken == "" && a.refreshToken == "":
|
||||
// parameter["grant_type"] = "authorization_code"
|
||||
// parameter["code"] = a.code
|
||||
// result, err = a.AccessAPI(TokenURL, "", RequestPost, parameter)
|
||||
// default:
|
||||
// return nil, errors.New("更换code,请在配置表中删除原蜂鸟token")
|
||||
// }
|
||||
// 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
|
||||
//}
|
||||
119
platformapi/sfps/store.go
Normal file
119
platformapi/sfps/store.go
Normal file
@@ -0,0 +1,119 @@
|
||||
package fnpsapi
|
||||
|
||||
//
|
||||
//import (
|
||||
// "encoding/json"
|
||||
// "fmt"
|
||||
// "strings"
|
||||
//
|
||||
// "git.rosy.net.cn/baseapi/utils"
|
||||
//)
|
||||
//
|
||||
//const (
|
||||
// StoreNotExist = "门店信息不存在"
|
||||
// StoreExist = "该门店已存在"
|
||||
//)
|
||||
//
|
||||
//const (
|
||||
// // 创建状态
|
||||
// ShopCreateStatusAuditRejected = 10 // 上架审核中
|
||||
// ShopCreateStatusAuditPassed = 20 // 正常(已上架)
|
||||
// ShopCreateStatusAuditCreated = 30 // 上架审核失败
|
||||
// ShopCreateStatusAuditOnline = 40 // 已冻结
|
||||
// ShopCreateStatusAuditUpdateRejected = 50 // 已下架
|
||||
// // 修改状态
|
||||
// ShopUpdateStatusAuditRejected = 0 // 无修改
|
||||
// ShopUpdateStatusAuditPassed = 10 // 资料修改审核中
|
||||
// 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) UpdateStore(updateStore *UpdateStoreParam) (err error) {
|
||||
// requestHead := a.MakeFnRequestHead()
|
||||
// storeByte, err := json.Marshal(updateStore)
|
||||
// if err != nil {
|
||||
// return err
|
||||
// }
|
||||
// requestHead["business_data"] = string(storeByte)
|
||||
// _, err = a.AccessAPI(ApiURL, "chainstoreUpdate", RequestPost, requestHead)
|
||||
// return
|
||||
//}
|
||||
//
|
||||
//func (a *API) GetStore(storeID string) (getStoreResult *GetOneStoreRespData, err error) {
|
||||
// params := GetOneStoreParam{
|
||||
// BaseInfo: BaseInfo{
|
||||
// AccessToken: a.accessToken,
|
||||
// Signature: a.signature,
|
||||
// MerchantID: a.merchantId,
|
||||
// Version: a.version,
|
||||
// AppID: a.appID,
|
||||
// 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"].(string) != "200" {
|
||||
// return nil, fmt.Errorf("%s", result["msg"])
|
||||
// }
|
||||
//
|
||||
// fnResult := &GetOneStoreRespData{}
|
||||
// if storeData, ok := result["business_data"]; ok {
|
||||
// if err := json.Unmarshal([]byte(utils.Interface2String(storeData)), fnResult); err != nil {
|
||||
// return nil, err
|
||||
// }
|
||||
// } else {
|
||||
// return nil, fmt.Errorf("暂无数据")
|
||||
// }
|
||||
//
|
||||
// return fnResult, 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
|
||||
//}
|
||||
73
platformapi/tiktok/tiktok.go
Normal file
73
platformapi/tiktok/tiktok.go
Normal file
@@ -0,0 +1,73 @@
|
||||
package tiktok
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"git.rosy.net.cn/baseapi/platformapi"
|
||||
"git.rosy.net.cn/baseapi/utils"
|
||||
"net/http"
|
||||
"strings"
|
||||
)
|
||||
|
||||
func (a *API) GetAppID() string {
|
||||
return a.clientKey
|
||||
}
|
||||
|
||||
func (a *API) GetSecret() string {
|
||||
return a.clientSecret
|
||||
}
|
||||
|
||||
func New(clientSecret, clientKey string, config ...*platformapi.APIConfig) *API {
|
||||
curConfig := platformapi.DefAPIConfig
|
||||
if len(config) > 0 {
|
||||
curConfig = *config[0]
|
||||
}
|
||||
return &API{
|
||||
clientSecret: clientSecret,
|
||||
clientKey: clientKey,
|
||||
client: &http.Client{Timeout: curConfig.ClientTimeout},
|
||||
config: &curConfig,
|
||||
}
|
||||
}
|
||||
|
||||
func (a *API) AccessAPI(baseUrl, actionApi, method string, bizParams map[string]interface{}) (retVal map[string]interface{}, err error) {
|
||||
// 序列化
|
||||
data, err := json.Marshal(bizParams)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// 全路径请求参数
|
||||
fullURL := utils.GenerateGetURL(baseUrl, actionApi, nil)
|
||||
|
||||
// 发送请求
|
||||
sendUrl := func() *http.Request {
|
||||
var request *http.Request
|
||||
if http.MethodPost == method {
|
||||
request, _ = http.NewRequest(http.MethodPost, fullURL, strings.NewReader(string(data)))
|
||||
} else {
|
||||
request, _ = http.NewRequest(http.MethodGet, utils.GenerateGetURL(baseUrl, actionApi, bizParams), nil)
|
||||
}
|
||||
switch actionApi {
|
||||
case TiktokTokenUrl:
|
||||
request.Header.Set("Content-Type", "application/x-www-form-urlencoded")
|
||||
case TiktokRefreshTokenUrl:
|
||||
request.Header.Set("Content-Type", "multipart/form-data")
|
||||
}
|
||||
|
||||
return request
|
||||
}
|
||||
|
||||
// 数据解析
|
||||
dataMarshal := 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")
|
||||
}
|
||||
|
||||
retVal = jsonResult1
|
||||
return errLevel, err
|
||||
}
|
||||
|
||||
err = platformapi.AccessPlatformAPIWithRetry(a.client, sendUrl, a.config, dataMarshal)
|
||||
return retVal, err
|
||||
}
|
||||
24
platformapi/tiktok/tiktok_const.go
Normal file
24
platformapi/tiktok/tiktok_const.go
Normal file
@@ -0,0 +1,24 @@
|
||||
package tiktok
|
||||
|
||||
import (
|
||||
"git.rosy.net.cn/baseapi/platformapi"
|
||||
"net/http"
|
||||
"sync"
|
||||
)
|
||||
|
||||
const (
|
||||
BaseURL = "https://open.douyin.com"
|
||||
TiktokTokenUrl = "/oauth/access_token/"
|
||||
TiktokRefreshTokenUrl = "/oauth/renew_refresh_token/"
|
||||
)
|
||||
|
||||
type API struct {
|
||||
clientSecret string // 应用唯一标识对应的密钥
|
||||
clientKey string // 应用唯一标识
|
||||
client *http.Client
|
||||
config *platformapi.APIConfig
|
||||
locker sync.RWMutex
|
||||
|
||||
msgToken string
|
||||
msgKey string
|
||||
}
|
||||
81
platformapi/tiktok/tiktok_token.go
Normal file
81
platformapi/tiktok/tiktok_token.go
Normal file
@@ -0,0 +1,81 @@
|
||||
package tiktok
|
||||
|
||||
import (
|
||||
"git.rosy.net.cn/baseapi/utils"
|
||||
"net/http"
|
||||
)
|
||||
|
||||
// OauthAccessTokenResData access_token
|
||||
type OauthAccessTokenResData struct {
|
||||
AccessToken string `json:"access_token"` // 接口调用凭证
|
||||
UnionId string `json:"union_id"` // 当且仅当该网站应用已获得该用户的userinfo授权时,才会出现该字段。
|
||||
Scope string `json:"scope"` // 用户授权的作用域(Scope),使用逗号(,)分隔,开放平台几乎几乎每个接口都需要特定的Scope。
|
||||
ExpiresIn uint64 `json:"expires_in"` // access_token接口调用凭证超时时间,单位(秒)
|
||||
OpenId string `json:"open_id"` // 授权用户唯一标识
|
||||
RefreshToken string `json:"refresh_token"` // 用户刷新access_token
|
||||
DYError
|
||||
}
|
||||
|
||||
// DYError 错误结构体
|
||||
type DYError struct {
|
||||
ErrorCode int64 `json:"error_code,omitempty"` // 错误码
|
||||
Description string `json:"description,omitempty"` // 错误码描述
|
||||
}
|
||||
|
||||
// OauthAccessTokenRes access_token
|
||||
type OauthAccessTokenRes struct {
|
||||
Data OauthAccessTokenResData `json:"data"`
|
||||
Message string `json:"message"`
|
||||
}
|
||||
|
||||
// 获取抖音token
|
||||
func (a *API) GetTiktokToken(code string) (*OauthAccessTokenRes, error) {
|
||||
tokenReq := make(map[string]interface{}, 4)
|
||||
tokenReq["client_secret"] = a.clientSecret
|
||||
tokenReq["code"] = code
|
||||
tokenReq["grant_type"] = "authorization_code"
|
||||
tokenReq["client_key"] = a.clientKey
|
||||
result, err := a.AccessAPI(BaseURL, TiktokTokenUrl, http.MethodPost, tokenReq)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
oauthAccessToken := &OauthAccessTokenRes{}
|
||||
if err := utils.Map2StructByJson(result, oauthAccessToken, false); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return oauthAccessToken, nil
|
||||
}
|
||||
|
||||
// OauthRefreshTokenResData 刷新access_token
|
||||
type OauthRefreshTokenResData struct {
|
||||
AccessToken string `json:"access_token"` // 接口调用凭证
|
||||
Scope string `json:"scope"` // 用户授权的作用域
|
||||
ExpiresIn uint64 `json:"expires_in"` // 过期时间,单位(秒)
|
||||
OpenId string `json:"open_id"` // 当前应用下,授权用户唯一标识
|
||||
RefreshToken string `json:"refresh_token"` // 用户刷新
|
||||
DYError
|
||||
}
|
||||
|
||||
// OauthRefreshTokenRes 刷新access_token
|
||||
type OauthRefreshTokenRes struct {
|
||||
Data OauthRefreshTokenResData `json:"data"`
|
||||
Message string `json:"message"`
|
||||
}
|
||||
|
||||
// 刷新用户Refresh token
|
||||
func (a *API) RefreshToken(refreshToken string) (*OauthRefreshTokenRes, error) {
|
||||
tokenReq := make(map[string]interface{}, 2)
|
||||
tokenReq["client_key"] = a.clientKey
|
||||
tokenReq["refresh_token"] = refreshToken
|
||||
// 通过旧的refresh_token获取新的refresh_token,调用后旧refresh_token会失效,新refresh_token有30天有效期。最多只能获取5次新的refresh_token,5次过后需要用户重新授权。
|
||||
result, err := a.AccessAPI(BaseURL, TiktokRefreshTokenUrl, http.MethodPost, tokenReq)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
oauthRefreshToken := &OauthRefreshTokenRes{}
|
||||
if err := utils.Map2StructByJson(result, oauthRefreshToken, false); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return oauthRefreshToken, nil
|
||||
}
|
||||
Reference in New Issue
Block a user