添加国美api,删除老版本蜂鸟API,添加抖音授权api、

This commit is contained in:
邹宗楠
2022-05-13 16:03:37 +08:00
parent 56ef57fae5
commit ff5b116ce5
35 changed files with 2346 additions and 1191 deletions

View File

@@ -18,16 +18,17 @@ const (
)
const (
OrderStatusWaitingForAccept = 1
OrderStatusAccepted = 2 // 待取货
OrderStatusDelivering = 3
OrderStatusFinished = 4
OrderStatusCanceled = 5
OrderStatusExpired = 7
OrderStatusAssignment = 8
OrderStatusReturning = 9
OrderStatusReturningFinished = 10
OrderStatusAddOrderFailed = 1000
OrderStatusWaitingForAccept = 1 // 待接单
OrderStatusAccepted = 2 // 待取货
OrderStatusDelivering = 3 // 配送中
OrderStatusFinished = 4 // 已完成
OrderStatusCanceled = 5 // 已取消
OrderStatusExpired = 7 //
OrderStatusAssignment = 8 // 指派单
OrderStatusReturning = 9 // 妥投异常之物品返回中
OrderStatusReturningFinished = 10 // 妥投异常之物品返回完成
OrderStatusReturningInOrder = 100 // 妥投异常之物品返回完成
OrderStatusAddOrderFailed = 1000 // ,创建达达运单失败
)
const (

View File

@@ -70,14 +70,14 @@ 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: "刘磊测试门店",
data, err := api.CreateStore(&CreateStoreBaseInfo{
HeadShopName: "刘磊测试门店10",
ContactPhone: "18981810340",
Address: "四川成都",
Longitude: 104.094555,
Latitude: 30.661382,
PositionSource: 3,
OutShopCode: "637910",
OutShopCode: "6379110",
CategoryID: "12",
OwnerName: "刘磊",
OwnerIDNum: "511324199308263974",
@@ -99,6 +99,7 @@ func TestCreateStore(t *testing.T) {
TabacooLicensePicHash: "",
})
fmt.Println(err)
fmt.Println(data)
}
func TestUpdataStore(t *testing.T) {
@@ -195,3 +196,7 @@ func TestDataUnmas(t *testing.T) {
fmt.Println("retsult", retsult.CallbackBusinessType)
fmt.Println("retsult", retsult.Param.PartnerOrderCode)
}
func TestErr2CallbackResponse(t *testing.T) {
fmt.Println(20 & 2)
}

View File

@@ -27,6 +27,14 @@ const (
ShopUpdateStatusAuditOnline = 30 // 审核驳回
)
type CreateStoreStruct struct {
Sign string `json:"sign"` //返回值签名,详见开放平台侧返回值签名算法
Code string `json:"code"` //错误码,详见开放平台侧错误码映射表
Msg string `json:"msg"` //错误信息
BusinessData string `json:"business_data"` // string
ApiCode string `json:"api_code"` // string
}
func (a *API) CreateStore(createStoreParam *CreateStoreBaseInfo) (result1 string, err error) {
requestHead := a.MakeFnRequestHead()
storeByte, err := json.Marshal(createStoreParam)
@@ -39,13 +47,19 @@ func (a *API) CreateStore(createStoreParam *CreateStoreBaseInfo) (result1 string
return "", err
}
createShop := struct {
ChainStoreId string `json:"chain_store_id"`
}{}
if err := json.Unmarshal([]byte(utils.Interface2String(result["business_data"])), &createShop); err != nil {
createData := &CreateStoreStruct{}
if err := utils.Map2StructByJson(result, createData, false); err != nil {
return "", err
}
return createShop.ChainStoreId, nil
defaultResult := struct {
ChainStoreId int64 `json:"chain_store_id"`
}{}
if err := json.Unmarshal([]byte(createData.BusinessData), &defaultResult); err != nil {
return "", err
}
return utils.Int64ToStr(defaultResult.ChainStoreId), err
}
func (a *API) UpdateStore(updateStore *UpdateStoreParam) (err error) {

View File

@@ -1,104 +0,0 @@
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 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 TestQueryOneStore(t *testing.T) {
api = New("6705486294797503379", "c1e6c280-e618-4103-9d0a-673bc54fb22e", "51658", "4W4hqacKND6NOct5gCyjbT")
token, err := api.GetAccessToken()
fmt.Println("err! ========", err)
api.accessToken = token.BusinessDataObj.AccessToken
fmt.Println("err! ========accessToken", api.accessToken)
data, err := api.GetStore("637910")
fmt.Println(data)
fmt.Println(err)
}

View File

@@ -1,452 +0,0 @@
package fnpsapi
import (
"git.rosy.net.cn/baseapi/platformapi"
"net/http"
"sync"
)
const (
TokenURL = "https://open-anubis.ele.me/anubis-webapi/openapi/token" // 正式环境
RefreshTokenUrl = "https://open-anubis.ele.me/anubis-webapi/openapi/refreshToken" // 正式环境刷新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"`
refreshToken string `json:"refresh_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"`
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 int `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"` // 服务商品明细
}
// 预下单商品服务明细
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 int `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运单生成成功120骑手接单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

View File

@@ -1,147 +0,0 @@
package fnpsapi
import (
"crypto/sha256"
"encoding/hex"
"encoding/json"
"fmt"
"git.rosy.net.cn/baseapi"
"git.rosy.net.cn/baseapi/platformapi"
"git.rosy.net.cn/baseapi/utils"
"net/http"
"sort"
"strings"
"sync"
"time"
)
func (a *API) SetToken(token string) {
a.locker.Lock()
defer a.locker.Unlock()
a.accessToken = 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(appID, appSecret, merchantId, code string, config ...*platformapi.APIConfig) *API {
curConfig := platformapi.DefAPIConfig
if len(config) > 0 {
curConfig = *config[0]
}
return &API{
grantType: "authorization_code", // 授权模式填固定值authorization_code
code: code,
appID: appID,
merchantId: merchantId,
signature: "",
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) {
var valueList []string
for k, v := range params {
if k != "signature" {
if str := fmt.Sprint(v); str != "" {
valueList = append(valueList, fmt.Sprintf("%s=%s", k, str))
}
}
}
sort.Sort(sort.StringSlice(valueList))
sig = strings.Join(valueList, "&")
sig = a.appSecret + sig
signature := sha256.Sum256([]byte(sig))
return hex.EncodeToString(signature[:])
}
// 获取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{}
if a.accessToken != "" && a.refreshToken != "" {
result, err = a.AccessAPI(RefreshTokenUrl, "", RequestPost, parameter)
} else {
parameter["grant_type"] = "authorization_code"
parameter["code"] = a.code
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
//a.r
return tokenInfo, err
}
func (a *API) AccessAPI(baseUrl, actionApi, method string, bizParams map[string]interface{}) (retVal map[string]interface{}, err error) {
bizParams["timestamp"] = utils.Int64ToStr(time.Now().Unix() * 1000)
bizParams["signature"] = a.signParam(bizParams)
// 序列化
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 RequestPost == method {
request, _ = http.NewRequest(http.MethodPost, fullURL, strings.NewReader(string(data)))
} else {
request, _ = http.NewRequest(http.MethodGet, utils.GenerateGetURL(baseUrl, actionApi, bizParams), nil)
}
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("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
}

View File

@@ -1,266 +0,0 @@
package fnpsapi
import (
"encoding/json"
"errors"
"git.rosy.net.cn/baseapi/utils"
"time"
)
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 //异常
)
// 蜂鸟预下单
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
}
// 蜂鸟正式下单
func (a *API) CreateOrder(createOrderParam *CreateOrderReqParam) (err error) {
orderHead := a.MakeFnRequestHead()
bytes, err := json.Marshal(createOrderParam)
if err != nil {
return err
}
orderHead["business_data"] = string(bytes)
_, err = a.AccessAPI(ApiURL, "createOrder", RequestPost, orderHead)
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
}
// 查询订单详情接口
func (a *API) QueryOrderDaile(req *GetOrderDetailReq) (result *GetOrderDetailRes, 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, "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
}
// 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
}

View File

@@ -1,68 +0,0 @@
package fnpsapi
import (
"fmt"
"testing"
"time"
)
// 预下单
func TestPreOrder(t *testing.T) {
api = New("6705486294797503379", "c1e6c280-e618-4103-9d0a-673bc54fb22e", "5375691", "51658")
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 TestAddTip(t *testing.T) {
api = New("6705486294797503379", "c1e6c280-e618-4103-9d0a-673bc54fb22e", "5375691", "51658")
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", "DDSdQhSc02m6l4oPVDELgx")
//token, err := api.GetAccessToken()
//fmt.Println(err)
api.accessToken = ""
data, err := api.GetCancelReasonList(&GetOrderDetailReq{
OrderId: "300000219758073736",
//PartnerOrderCode: "817102016000041",
})
fmt.Println(err)
fmt.Println(data)
}

View File

@@ -1,73 +0,0 @@
package fnpsapi
import (
"encoding/json"
"fmt"
"git.rosy.net.cn/baseapi/utils"
)
// 创建门店.
func (a *API) CreateStore(createStoreParam *CreateStoreBaseInfo) (err error) {
requestHead := a.MakeFnRequestHead()
storeByte, err := json.Marshal(createStoreParam)
if err != nil {
return err
}
requestHead["business_data"] = string(storeByte)
_, err = a.AccessAPI(ApiURL, "chainstoreCreate", RequestPost, requestHead)
return err
}
// 更新门店 209636747
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"] != "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
}

View File

@@ -1,4 +1,4 @@
package fnpsapi
package gome_live_show
import (
"net/url"

View File

@@ -0,0 +1,195 @@
package gome_live_show
import (
"encoding/json"
"errors"
"git.rosy.net.cn/baseapi/utils"
"net/http"
)
// 获取商品品类信息查询
func (a *API) GetGoodsCategoryList() (goodsCategory *GoodsCategoryListRes, err error) {
goodsCategoryMap, err := a.AccessAPI(gomeUrl, GoodsCategoryApi, http.MethodPost, utils.Struct2FlatMap(a.MakeRequestParam(nil)))
if err != nil {
return nil, err
}
result := &GoodsCategoryListRes{}
if err := utils.Map2StructByJson(goodsCategoryMap, result, false); err != nil {
return nil, err
}
if result.Code != 200 {
return nil, errors.New(result.Message)
}
return result, nil
}
//
//// 查询所有的商品规格
//func (a *API) QueryGoodsSizeListAll(param *QueryGoodsSpecSizeReq) {
// param.PageNumber = 1
// param.PageSize = 50
// result, err := a.QueryGoodsSizeList(param)
// if err != nil {
// return nil, err
// }
//
// for ; pageNo <= result.Data.Total/pageSize+1; pageNo++ {
// result2, err := getAPI(string(model.VendorGoMei)).QueryGoodsListById(&gomei.QueryGoodsListForStoreReq{
// Page: gomei.Page{
// PageNumber: pageNo,
// PageSize: pageSize,
// },
// })
// if err != nil {
// return nil, err
// }
//
// for _, v := range result2.Data.Records {
// if skuName := vendorSku2Jx2(v); skuName != nil {
// skuNameList = append(skuNameList, skuName)
// }
// }
// }
//
// return skuNameList, err
// reslut, err := a.QueryGoodsSizeList(param)
//
//}
//jsonMarshal,err := json.Marshal(gomeResult)
//if err != nil {
//return nil, err
//}
//if err := json.Unmarshal(jsonMarshal,data);err != nil {
//return nil, err
//}
// 查询商品规格
func (a *API) QueryGoodsSizeList(param *QueryGoodsSpecSizeReq) (result *QueryGoodsSpecSizeRes, err error) {
reqByte, err := json.Marshal(param)
if err != nil {
return
}
gomeResult, err := a.AccessAPI(gomeUrl, GoodsSpecListApi, http.MethodPost, utils.Struct2FlatMap(a.MakeRequestParam(reqByte)))
if err != nil {
return nil, err
}
data := &QueryGoodsSpecSizeRes{}
if err := utils.Map2StructByJson(gomeResult, data, false); err != nil {
return nil, err
}
jsonMarshal, err := json.Marshal(gomeResult)
if err != nil {
return nil, err
}
if err := json.Unmarshal(jsonMarshal, data); err != nil {
return nil, err
}
if data.Code != 200 {
return nil, errors.New(result.Message)
}
return data, err
}
// 查询商品规格详情
func (a *API) QueryGoodsDetails(specCode string) (result *QueryGoodsSpecDetailRes, err error) {
byteParam, err := json.Marshal(map[string]string{"specCode": specCode})
if err != nil {
return nil, err
}
gomeResult, err := a.AccessAPI(gomeUrl, GoodsSpecDetailApi, http.MethodPost, utils.Struct2FlatMap(a.MakeRequestParam(byteParam)))
if err != nil {
return nil, err
}
detail := &QueryGoodsSpecDetailRes{}
if err := utils.Map2StructByJson(gomeResult, detail, false); err != nil {
return nil, err
}
if result.Code != 200 {
return nil, errors.New(result.Message)
}
return detail, err
}
// 新增商品规格
func (a *API) CreateGoodsSpceList(param *CreateSpecDetailParam) (result *SystemParameterRes, err error) {
paramByte, err := json.Marshal(param)
if err != nil {
return nil, err
}
gomeResult, err := a.AccessAPI(gomeUrl, GoodsSpecCreateApi, http.MethodPost, utils.Struct2FlatMap(a.MakeRequestParam(paramByte)))
resultData := &SystemParameterRes{}
if err := utils.Map2StructByJson(gomeResult, resultData, true); err != nil {
return nil, err
}
if result.Code != 200 {
return nil, errors.New(result.Message)
}
return resultData, nil
}
// 修改商品规格
func (a *API) UpdateGoodsSize(param *UpdateGoodsSizeReq) (*SystemParameterRes, error) {
paramByte, err := json.Marshal(param)
if err != nil {
return nil, err
}
gomeResult, err := a.AccessAPI(gomeUrl, GoodsSpecUpdateApi, http.MethodPost, utils.Struct2FlatMap(a.MakeRequestParam(paramByte)))
resultData := &SystemParameterRes{}
if err := utils.Map2StructByJson(gomeResult, resultData, true); err != nil {
return nil, err
}
if resultData.Code != 200 {
return nil, errors.New(resultData.Message)
}
return resultData, nil
}
// 删除商品规格
func (a *API) DeleteGoodsSize(specCode string) (*SystemParameterRes, error) {
byteParam, err := json.Marshal(map[string]string{"specCode": specCode})
if err != nil {
return nil, err
}
gomeResult, err := a.AccessAPI(gomeUrl, GoodsSpecDeleteApi, http.MethodPost, utils.Struct2FlatMap(a.MakeRequestParam([]byte(byteParam))))
if err != nil {
return nil, err
}
resultData := &SystemParameterRes{}
if err := utils.Map2StructByJson(gomeResult, resultData, true); err != nil {
return nil, err
}
if resultData.Code != 200 {
return nil, errors.New(resultData.Message)
}
return resultData, nil
}
// 获取不同商品的类型
func (a *API) GetGoodsTypeList(cat3Code string) (*QueryGoodsTypeListRes, error) {
byteParam, err := json.Marshal(map[string]string{"cat3Code": cat3Code})
if err != nil {
return nil, err
}
gomeResult, err := a.AccessAPI(gomeUrl, GoodsSpecTypeApi, http.MethodPost, utils.Struct2FlatMap(a.MakeRequestParam([]byte(byteParam))))
if err != nil {
return nil, err
}
resultData := &QueryGoodsTypeListRes{}
if err := utils.Map2StructByJson(gomeResult, resultData, true); err != nil {
return nil, err
}
if resultData.Code != 200 {
return nil, errors.New(resultData.Message)
}
return resultData, nil
}

View File

@@ -0,0 +1,136 @@
package gome_live_show
//#region 获取商品品类信息
type GoodsCategoryListRes struct {
Code int64 `json:"code"` // 响应码
Timestamp int64 `json:"timestamp"` // 时间戳(秒)
Message string `json:"message"` // 响应描述
RequestId string `json:"requestId"` // 请求id
Data []*GoodsCategoryListRecordRes
}
// 商品品类查询 品类查询,创建商品规格和商品时需要维护品类信息。
type GoodsCategoryListRecordRes struct {
CatCode string `json:"catCode"` // 品类 id
CatLevel int `json:"catLevel"` // 品类级别 三级品类:1 一级品类2 二级品类3三级品类
CatName string `json:"catName"` // 品类名称
ChildCat []*GoodsCategoryListRecordRes `json:"childCat"` // 子类目信息
}
//#endregion
//#region 获取商铺尺寸列表
// 查询商品规格列表 创建商品时,可选择不同规格的组合商品进行售卖,,
//包含规格属性唯一标识(specCode)、规格属性名(specName) 、
//规格属性值唯一标识(specValueCode)、规格属性值(specValueName)等信息。
type QueryGoodsSpecSizeReq struct {
Cat3Code string `json:"cat3Code"` // 根据3级品类code查询,长度50
SpecName string `json:"specName"` // 规格属性名
Page
}
// 返回值
type QueryGoodsSpecSizeRes struct {
SystemParameterRes
Data *GoodsSpecSizeList
}
type GoodsSpecSizeList struct {
Records []*QueryGoodsSpecSizeRecords
SystemRecordDataDetailRes
}
type QueryGoodsSpecSizeRecords struct {
SpecCode string `json:"specCode"` // 规格属性名唯一标识
SpecName string `json:"specName"` // 规格属性名
FullCatName string `json:"fullCatName"` // 所属品类
Cat3Code string `json:"cat3Code"` // 三级品类Code
Remark string `json:"remark"` // 备注
}
//#endregion
//#region 查询商品规格详情
type QueryGoodsSpecDetailRes struct {
SystemParameterRes
Data *QueryGoodsSpecDetailRecordRes
}
type QueryGoodsSpecDetailRecordRes struct {
QueryGoodsSpecDetailDataRes
SystemRecordDataDetailRes
}
type QueryGoodsSpecDetailDataRes struct {
SpecCode string `json:"specCode"` // 规格属性名 id
SpecName string `json:"specName"` // 规格属性名
SpecValues []*SpecValuesList `json:"specValues"` // 规格属性值集合
FullCatName string `json:"fullCatName"` // 所属品类
Cat1Code string `json:"cat1Code"` // 一级品类code
Cat1Name string `json:"cat1Name"` // 一级品类名
Cat2Code string `json:"cat2Code"` // 二级品类code
Cat2Name string `json:"cat2Name"` // 二级品类名
Cat3Code string `json:"cat3Code"` // 三级品类 code
Cat3Name string `json:"cat3Name"` // 三级品类名
Remark string `json:"remark"` // 备注
}
type SpecValuesList struct {
SpecValueCode string `json:"specValueCode"` // 规格属性值唯一标示
SpecValueName string `json:"specValueName"` // 规格属性值名称
}
//#endregion
//#region 新增商品尺寸规格
type CreateSpecDetailParam struct {
SpecName string `json:"specName"` // 规格属性名[必填]
SpecValues []*SpecValueName `json:"specValues"` // 规格属性值[必填]
Cat3Code string `json:"cat3Code"` // 规格属性名[必填]
Remark string `json:"remark"` // 规格属性名
}
type SpecValueName struct {
SpecValueName string `json:"specValueName"` // 规格属性名必填
}
//#endregion
//#region 编辑商品规格
type UpdateGoodsSizeReq struct {
SpecCode string `json:"specCode"` // 规格属性名唯一标识[必填]
SpecName string `json:"specName"` // 规格属性名[必填]
SpecValues []*UpdateGoodsSpecValue `json:"specValues"` // 规格属性值[必填]
Cat3Code string `json:"cat3Code"` // 三级品类code[必填]
Remark string `json:"remark"` // 备注
}
type UpdateGoodsSpecValue struct {
SpecValueName string `json:"specValueName"` // 规格属性名
SpecValueCode string `json:"specValueCode"` // 规格属性名
}
//#endregion
//#region 删除商品规格
//#endregion
//#region 获取不同商品类型
type QueryGoodsTypeListRes struct {
SystemParameterRes
Data *QueryGoodsTypeListDataRes
}
type QueryGoodsTypeListDataRes struct {
SystemRecordDataDetailRes
Record []*struct {
GoodsType string `json:"goodsType"` // 商品类型
GoodsTypeName string `json:"goodsTypeName"` // 商品名称
}
}
//#endregion

View File

@@ -0,0 +1,42 @@
package gome_live_show
import (
"fmt"
"testing"
)
// 获取商品尺寸列表
func TestQueryGoodsList(t *testing.T) {
paramter := &QueryGoodsSpecSizeReq{
Cat3Code: "",
SpecName: "",
Page: Page{
PageNumber: PageNumber,
PageSize: PageSize,
},
}
data, err := api.QueryGoodsSizeList(paramter)
fmt.Println("err=", err)
fmt.Println("err=", data)
// fmt.Println("data", data.Records[0].Cat3Code)
}
// 获取尺寸详情
func TestQuerSpecListDetail(t *testing.T) {
api.QueryGoodsDetails("11111")
}
// 新增商品规格
func TestAddGoods(t *testing.T) {
data, err := api.CreateGoodsSpceList(&CreateSpecDetailParam{
SpecName: "测试分类",
SpecValues: []*SpecValueName{
{SpecValueName: "1111"},
{SpecValueName: "2222"},
},
Cat3Code: "100001",
Remark: "测试用力添加",
})
fmt.Println(data)
fmt.Println(err)
}

View File

@@ -0,0 +1,108 @@
package gome_live_show
// api/url
const (
gomeUrl = "http://openapi-uat-external.lohashow.com" // 基础url
GetTokenApi = "login/auth/getToken" // 获取token
// 门店
GetStoreListApi = "V2/store/list" // 获取门店列表
// 商户商品
GetMerchantGoodsList = "V2/goods/merchant/list" // 商户商品列表
GetMerchantGoodsDetailList = "V2/goods/merchant/detail" // 商户商品商品详情列表
CreateMerchantGoodsToStore = "V2/goods/merchant/create" // 商户商品新增
UpdateMerchantGoodsToStore = "V2/goods/merchant/update" // 商户商品修改
DeleteMerchantGoodsToStore = "V2/goods/merchant/delete" // 商户商品删除
// 门店分类
GetStoreCategoryListApi = "V2/category/storeGoods/list" // 获取店铺商品分类列表(素菜,水果,牛肉)
AddStoreCategoryApi = "V2/category/storeGoods/create" // 店铺商品分类新增
ModifyStoreCategoryApi = "V2/category/storeGoods/update" // 店铺商品分类修改
DeleteStoreCategoryApi = "V2/category/storeGoods/delete" // 店铺商品分类删除
// 门店商品规格
GoodsCategoryApi = "V2/goodsCategory/list" // 商品品类查询(超市/超市/(洋酒/鲜花/面包))
GoodsSpecListApi = "V2/spec/list" // 查询商品规格列表
GoodsSpecDetailApi = "V2/spec/detail" // 查询商品规格详情
GoodsSpecCreateApi = "V2/spec/create" // 创建商品规格
GoodsSpecUpdateApi = "V2/spec/update" // 修改商品规格
GoodsSpecDeleteApi = "V2/spec/delete" // 删除商品规格
GoodsSpecTypeApi = "V2/goodsType/list" // 获取不同商品类型
// 门店商品维护
QueryGoodsListByStoreId = "V2/goods/store/list" // 根据店铺编码查询店铺商品列表
QueryOneGoodsByStoreId = "V2/goods/store/detail" // 根据 storeCode+skuCode 查询店铺商品详情
GoodsOnOffLineByStore = "V2/goods/store/onOffline" // 门店商品上下架状态
UpdatePriceToOneGoodsByStore = "V2/goods/store/priceUpdate" // 单商品维护售价
UpdateGoodsStockForStore = "V2/goods/store/stockUpdate" // 商品库存更新接口
AddGoodsForStore = "V2/goods/store/create" // 新增店铺商品
// 订单
QueryOrderList = "V2/order/list" // 根据创建时间查询订单的列表信息
QueryOrderDetail = "V2/order/detail" // 查询订单详情接口
CancelOrder = "V2/order/cancel" // 取消订单
ConfirmOrder = "V2/order/confirm" // 此接口主要用于商户接单场景
DeliveryOrder = "V2/order/delivery" // 发货
CheckOutOrder = "V2/order/checkout" // 用户自提商家核销
CancelAgreeOrRefuseAfterApply = "V2/order/cancle/agreeOrRefuseAfterApply" // 用户自提商家核销
// 售后订单
QueryAfterSaleList = "V2/afterSale/list" // 批量查询售后单接口
CreateAfterSaleOrder = "V2/afterSale/create" // 创建售后单接口
QueryAfterSaleOrderDetail = "V2/afterSale/get" // 售后单详情接口
AgreeOrRefuseAfterApplyOrder = "V2/afterSale/agreeOrRefuseAfterApply" // 商家审核订单
MerchantAgreeOkAfterApplyOrder = "V2/afterSale/confirm/goods" // 售后单商户收货确认
UploadImg = "V2/material/upload" // 主要用于为合作方上传图片提供服务,将合作方素材转化为乐活秀平台所需素材链接。
)
// 国美枚举说明
const (
// 上下架枚举值
PutOnTheShelf = "SHELVE" // 上架
DownOnTheShelf = "READY" // 下架
// 订单状态枚举值
GoodsToBePrepared = "STOCKUP_PENDING" // 待备货
PayingAndCancel = "PAID_CANCEL" // 支付后取消
Consignment = "DELIVERY_PENDING" // 待发货
CancelAfterStock = "STOCKUP_CANCEL" // 备货后取消
GoodsToBeReceived = "RECEIVING" // 待收货
Completed = "COMPLETE" // 已完成
//售后单状态枚举值
SubmitAfterSalesApplication = iota // 提交售后申请 0
AfterSalesAuditPassed // 售后审核通过 1
MerchantFailedToPass // 上架审核未通过 2
CustomerShipped // 客户已发货 3
MerchantHasReceivedTheGoods // 商家已收货 4
AfterSalesCompletion // 售后完成 5
UserCancel // 用户取消(完成) 6
TimeoutShutdown // 超时关闭(完成) 7
PlatformInterventionConsent // 平台介入同意 9
PlatformInterventionNo // 平台介入拒绝 10
PlatformInterventionApply // 申请平台介入 11
PlatformInterventionAgainApply // 拒绝后再次申请 12
// 门店营业状态
GoMeiStoreStatusToBeOpen = 1 // 待开业
GoMeiStoreStatusOpen = 2 // 开业
GoMeiStoreStatusTemporaryClose = 3 // 临时关闭
GoMeiStoreStatusClose = 4 // 关闭
)
// 常量
const (
PageNumber = 1
PageSize = 50
ConstNumberOne = 0
GoMeiMaxStock = 99999999 // 最大库存量
)
func GoMeiStoreSkuStatus(status int) string {
if status == 1 {
return PutOnTheShelf
}
return DownOnTheShelf
}

View File

@@ -0,0 +1,158 @@
package gome_live_show
import (
"crypto/md5"
"encoding/json"
"fmt"
"git.rosy.net.cn/baseapi"
"git.rosy.net.cn/baseapi/platformapi"
"git.rosy.net.cn/baseapi/utils"
"net/http"
"sort"
"strings"
"sync"
"time"
)
var api *API
func init() {
appKey := "N0R033L2QQFR53"
secretKey := "686ffc3e31c24594838baed045563790"
api = New(appKey, secretKey, "")
api.GetAccessToken()
// api.GetAccessToken()
}
func (a *API) SetToken(token string) {
a.locker.Lock()
defer a.locker.Unlock()
a.sessionToken = token
}
func (a *API) GetAppKey() string {
a.locker.Lock()
defer a.locker.Unlock()
return a.appKey
}
func New(appKey, appSecret, code string, config ...*platformapi.APIConfig) *API {
curConfig := platformapi.DefAPIConfig
if len(config) > 0 {
curConfig = *config[0]
}
return &API{
code: code,
appKey: appKey,
sign: "",
appSecret: appSecret,
refreshToken: "",
sessionToken: "",
expiration: "",
version: "2",
locker: sync.RWMutex{},
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 != "sign" {
if str := fmt.Sprint(v); str != "" {
valueList = append(valueList, fmt.Sprintf("%s%s", k, str))
}
}
}
sort.Sort(sort.StringSlice(valueList))
sig = strings.Join(valueList, "")
sig = sig + "_" + a.appSecret
data := []byte(sig)
return strings.ToUpper(fmt.Sprintf("%x", md5.Sum(data)))
}
// 获取access_token
func (a *API) GetAccessToken() (tokenInfo *gomeToken, err error) {
parameter := make(map[string]interface{}, 3)
parameter["appKey"] = a.appKey
parameter["timestamp"] = utils.Int64ToStr(time.Now().Unix())
parameter["sign"] = a.signParam(parameter)
// 获取token
result, err := a.AccessAPI(gomeUrl, GetTokenApi, http.MethodPost, parameter)
if err != nil {
return nil, err
}
if err := utils.Map2StructByJson(result, &tokenInfo, false); err != nil {
return nil, err
}
a.refreshToken = tokenInfo.Data.RefreshToken
a.expiration = tokenInfo.Data.Expiration
a.sessionToken = tokenInfo.Data.SessionToken
return tokenInfo, err
}
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)
}
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["message"].(string), utils.Int64ToStr(utils.MustInterface2Int64(jsonResult1["code"])))
baseapi.SugarLogger.Debugf("gome 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
}
// 组装访问参数
func (a *API) MakeRequestParam(storeByte []byte) *SystemParameterReq {
param := &SystemParameterReq{
AuthToken: a.sessionToken,
Timestamp: time.Now().Unix(),
Version: a.version,
Sign: "",
}
param.Biz = "{}"
if storeByte != nil || len(storeByte) > 0 {
param.Biz = string(storeByte)
}
mapParametersReq := utils.Struct2FlatMap(param)
param.Sign = a.signParam(mapParametersReq)
return param
}

View File

@@ -0,0 +1,167 @@
package gome_live_show
import (
"encoding/json"
"errors"
"git.rosy.net.cn/baseapi/utils"
"net/http"
)
// 根据创建时间查询订单的列表信息
// 为了防止访问及返回的压力过大,可支持的时间区间查询范围,
// 不允许超过 30 分钟,每页显示 10 条正常频率查询增量查询建议1~3 分钟查询一次,
// 查询开始时间为上次查询结束时间,查询结束时间为当前 1~3 分钟之前;补充频率查询:为了防止数据遗漏,
// 建议10分钟查询一次。例如当前时间为 10:50查询区间为10:10~10:30具体细节有调用方把握减少数据遗漏的可能性
func (a *API) QueryOrderListByTime(req *QueryOrderListForTimeReq) (*QueryOrderListForTimeRes, error) {
byteReq, err := json.Marshal(req)
if err != nil {
return nil, err
}
gomeResult, err := a.AccessAPI(gomeUrl, QueryOrderList, http.MethodPost, utils.Struct2FlatMap(a.MakeRequestParam(byteReq)))
if err != nil {
return nil, err
}
result := &QueryOrderListForTimeRes{}
if err := utils.Map2StructByJson(gomeResult, result, false); err != nil {
return nil, err
}
if result.Code != 200 {
return nil, errors.New(result.Message)
}
return result, nil
}
// 查询订单详情接口
// 此接口主要用于订单下单后获取订单详细信息,包括订单基础信息、商品信息、配送信息、物流信息等
func (a *API) QueryOrderDetail(orderNo string) (*QueryOrderDetailRes, error) {
byteReq, err := json.Marshal(map[string]string{"orderNo": orderNo})
if err != nil {
return nil, err
}
gomeResult, err := a.AccessAPI(gomeUrl, QueryOrderDetail, http.MethodPost, utils.Struct2FlatMap(a.MakeRequestParam(byteReq)))
if err != nil {
return nil, err
}
result := &QueryOrderDetailRes{}
if err := utils.Map2StructByJson(gomeResult, result, false); err != nil {
return nil, err
}
if result.Code != 200 {
return nil, errors.New(result.Message)
}
return result, nil
}
// 商家取消订单 ,订单处于待备货或待发货的情况下,商家可主动操作取消订单,取消成功后订单变成支付后取消状态
func (a *API) CancelOrder(orderNo string) (*SystemParameterRes, error) {
byteReq, err := json.Marshal(map[string]string{"orderNo": orderNo})
if err != nil {
return nil, err
}
gomeResult, err := a.AccessAPI(gomeUrl, CancelOrder, http.MethodPost, utils.Struct2FlatMap(a.MakeRequestParam(byteReq)))
if err != nil {
return nil, err
}
result := &SystemParameterRes{}
if err := utils.Map2StructByJson(gomeResult, result, false); err != nil {
return nil, err
}
if result.Code != 200 {
return nil, errors.New(result.Message)
}
return result, nil
}
// 接单
func (a *API) ConfirmOrder(orderNo string) (*SystemParameterRes, error) {
byteReq, err := json.Marshal(map[string]string{"orderNo": orderNo})
if err != nil {
return nil, err
}
gomeResult, err := a.AccessAPI(gomeUrl, ConfirmOrder, http.MethodPost, utils.Struct2FlatMap(a.MakeRequestParam(byteReq)))
if err != nil {
return nil, err
}
result := &SystemParameterRes{}
if err := utils.Map2StructByJson(gomeResult, result, false); err != nil {
return nil, err
}
if result.Code != 200 {
return nil, errors.New(result.Message)
}
return result, nil
}
// 发货接口 此接口主要用于商户基于订单发货场景,第三方平台调用成功后,订单状态将变为待收货
func (a *API) DeliveryOrder(param *DeliveryOrderReq) (*SystemParameterRes, error) {
byteReq, err := json.Marshal(param)
if err != nil {
return nil, err
}
gomeResult, err := a.AccessAPI(gomeUrl, DeliveryOrder, http.MethodPost, utils.Struct2FlatMap(a.MakeRequestParam(byteReq)))
if err != nil {
return nil, err
}
result := &SystemParameterRes{}
if err := utils.Map2StructByJson(gomeResult, result, false); err != nil {
return nil, err
}
if result.Code != 200 {
return nil, errors.New(result.Message)
}
return result, nil
}
// 核销接口此接口主要用于 C 端用户下单自提,商家核销场景,核销成功订单状态变成已完成(订单号/核销码)
func (a *API) CheckOrder(orderNo, deliverCheckCode string) (*SystemParameterRes, error) {
byteReq, err := json.Marshal(map[string]string{"orderNo": orderNo, "deliverCheckCode": deliverCheckCode})
if err != nil {
return nil, err
}
gomeResult, err := a.AccessAPI(gomeUrl, CheckOutOrder, http.MethodPost, utils.Struct2FlatMap(a.MakeRequestParam(byteReq)))
if err != nil {
return nil, err
}
result := &SystemParameterRes{}
if err := utils.Map2StructByJson(gomeResult, result, false); err != nil {
return nil, err
}
if result.Code != 200 {
return nil, errors.New(result.Message)
}
return result, nil
}
// 此接口主要用于,售中(待发货状态)订单,用户发起全单取消,申请后进行商家审核场景,商家审核通过订单将变成备货后取消状态,商家拒绝订单则进行走正向流程
func (a *API) OrderAgreeOrRefuseAfterApply(req *AgreeOrRefuseCheck) (*SystemParameterRes, error) {
byteReq, err := json.Marshal(req)
if err != nil {
return nil, err
}
gomeResult, err := a.AccessAPI(gomeUrl, CancelAgreeOrRefuseAfterApply, http.MethodPost, utils.Struct2FlatMap(a.MakeRequestParam(byteReq)))
if err != nil {
return nil, err
}
result := &SystemParameterRes{}
if err := utils.Map2StructByJson(gomeResult, result, false); err != nil {
return nil, err
}
if result.Code != 200 {
return nil, errors.New(result.Message)
}
return result, nil
}

View File

@@ -0,0 +1,141 @@
package gome_live_show
import (
"encoding/json"
"errors"
"git.rosy.net.cn/baseapi/utils"
"net/http"
)
// 查询售后单
func (a *API) QueryAfterSaleList(req *QueryAfterSaleListReq) (*QueryAfterSaleListRes, error) {
byteReq, err := json.Marshal(req)
if err != nil {
return nil, err
}
gomeResult, err := a.AccessAPI(gomeUrl, QueryAfterSaleList, http.MethodPost, utils.Struct2FlatMap(a.MakeRequestParam(byteReq)))
if err != nil {
return nil, err
}
result := &QueryAfterSaleListRes{}
if err := utils.Map2StructByJson(gomeResult, result, false); err != nil {
return nil, err
}
if result.Code != 200 {
return nil, errors.New(result.Message)
}
return result, nil
}
// 创建售后单 此接口主要基于售后场景,订单处于待收货或已完成,商户在后台针对订单的单商品主动发起售后
func (a *API) CreateAfterSaleOrderApi(req *CreateOrderAfterSaleReq) (*SystemParameterRes, error) {
byteReq, err := json.Marshal(req)
if err != nil {
return nil, err
}
gomeResult, err := a.AccessAPI(gomeUrl, CreateAfterSaleOrder, http.MethodPost, utils.Struct2FlatMap(a.MakeRequestParam(byteReq)))
if err != nil {
return nil, err
}
result := &SystemParameterRes{}
if err := utils.Map2StructByJson(gomeResult, result, false); err != nil {
return nil, err
}
if result.Code != 200 {
return nil, errors.New(result.Message)
}
return result, nil
}
// 售后单详情接口
func (a *API) QueryAfterSaleOrderDetail(afterSaleNo string) (*QueryAfterSaleListRes, error) {
byteReq, err := json.Marshal(map[string]string{"afterSaleNo": afterSaleNo})
if err != nil {
return nil, err
}
gomeResult, err := a.AccessAPI(gomeUrl, QueryAfterSaleOrderDetail, http.MethodPost, utils.Struct2FlatMap(a.MakeRequestParam(byteReq)))
if err != nil {
return nil, err
}
result := &QueryAfterSaleListRes{}
if err := utils.Map2StructByJson(gomeResult, result, false); err != nil {
return nil, err
}
if result.Code != 200 {
return nil, errors.New(result.Message)
}
return result, nil
}
// 此接口主当售中待收货、已完成用户发起单sku的售后申请申请后进行商家审核场景
//商家审核通过售后单进退退款流程,商家拒绝售后单关闭,用户可进行重新申请或申请平台介入
func (a *API) AgreeOrRefuseAfterApplyOrder(req *CheckOutAfterOrderReq) (*SystemParameterRes, error) {
byteReq, err := json.Marshal(req)
if err != nil {
return nil, err
}
gomeResult, err := a.AccessAPI(gomeUrl, AgreeOrRefuseAfterApplyOrder, http.MethodPost, utils.Struct2FlatMap(a.MakeRequestParam(byteReq)))
if err != nil {
return nil, err
}
result := &SystemParameterRes{}
if err := utils.Map2StructByJson(gomeResult, result, false); err != nil {
return nil, err
}
if result.Code != 200 {
return nil, errors.New(result.Message)
}
return result, nil
}
// 售后单商户收货确认
func (a *API) MerchantConfirmOrder(afterSaleNo string) (*SystemParameterRes, error) {
byteReq, err := json.Marshal(map[string]string{"afterSaleNo": afterSaleNo})
if err != nil {
return nil, err
}
gomeResult, err := a.AccessAPI(gomeUrl, MerchantAgreeOkAfterApplyOrder, http.MethodPost, utils.Struct2FlatMap(a.MakeRequestParam(byteReq)))
if err != nil {
return nil, err
}
result := &SystemParameterRes{}
if err := utils.Map2StructByJson(gomeResult, result, false); err != nil {
return nil, err
}
if result.Code != 200 {
return nil, errors.New(result.Message)
}
return result, nil
}
// 合作方图片上传 materialType(枚举值1 图片2视频)
func (a *API) UploadPicture(data string, materialType int, materialName string) (*GomeiUploadImgRes, error) {
byteReq, err := json.Marshal(map[string]interface{}{"data": data, "materialType": materialType, "materialName": materialName})
if err != nil {
return nil, err
}
gomeResult, err := a.AccessAPI(gomeUrl, UploadImg, http.MethodPost, utils.Struct2FlatMap(a.MakeRequestParam(byteReq)))
if err != nil {
return nil, err
}
result := &GomeiUploadImgRes{}
if err := utils.Map2StructByJson(gomeResult, result, false); err != nil {
return nil, err
}
if result.Code != 200 {
return nil, errors.New(result.Message)
}
return result, nil
}

View File

@@ -0,0 +1,68 @@
package gome_live_show
//#region 查询平台售后单列表
// 查询平台售后单列表。
type QueryAfterSaleListReq struct {
Page
AfterSaleStatus int `json:"afterSaleStatus"` // 售后状态
OrderNo string `json:"orderNo"` // 按照订单号查询
AfterSaleNo string `json:"afterSaleNo"` // 按照售后单号查询
Mobile string `json:"mobile"` // 售后状态
StoreCode int `json:"storeCode"` // 平台店铺编码
}
type QueryAfterSaleListRes struct {
SystemParameterRes
Data *QueryAfterSaleListData
}
type QueryAfterSaleListData struct {
SystemRecordDataDetailRes
Record []*QueryAfterSaleListRecord
}
type QueryAfterSaleListRecord struct {
AfterSaleNo string `json:"afterSaleNo"` // 售后单单号
OrderNo string `json:"orderNo"` // 订单号
AfterSaleType int `json:"afterSaleType"` // 售后类型 0仅退款1退货退款
StoreName string `json:"storeName"` // 平台店铺名称
StoreCode string `json:"storeCode"` // 平台店铺编码
SkuCode string `json:"skuCode"` // 平台 sku 编码
GoodsName string `json:"goodsName"` // 商品名称
AfterSaleNumber int `json:"afterSaleNumber"` // 申请售后 sku 数
AfterSaleStatus int `json:"afterSaleStatus"` // 售后单状态 0 待商家确认1 待退货2退款中3 商家已拒绝4 平台介入中5已关闭6 已取消7 售后完成8退款失败
CreateTime string `json:"createTime"` // 创建时间
}
//#endregion
//#region 商户主动创建售后单,此接口主要基于售后场景,订单处于待收货或已完成,商户在后台针对订单的单商品主动发起售后
type CreateOrderAfterSaleReq struct {
// 必填
StoreCode string `json:"storeCode"` // 平台店铺编码
OrderNo string `json:"orderNo"` // 订单号
AfterSaleType int `json:"afterSaleType"` // 售后类型 0仅退款1退货退款
SkuCode string `json:"skuCode"` // 平台 sku 编码
AfterSaleNumber int `json:"afterSaleNumber"` // 申请售后 sku 数
// 非必填
CargoState int `json:"cargoState"` // 售后申请- 货物状态
IssueDesc int `json:"issueDesc"` // 售后申请- 补充描述
RefundReasonCode int `json:"refundReasonCode"` // 退款原因编码
RefundReasonStr int `json:"refundReasonStr"` // 退款原因
PicUrl int `json:"picUrl"` // 退款原因凭证图片
}
//#endregion
type CheckOutAfterOrderReq struct {
// 必填
AfterSaleNo string `json:"afterSaleNo"` // 售后单单号
AfterSaleApplyResult string `json:"afterSaleApplyResult"` // 商户审核结果1 同意2拒绝
// 非必填
afterSaleApplyRejectReason string `json:"afterSaleApplyRejectReason"` // 拒绝原因
}
//#region

View File

@@ -0,0 +1,203 @@
package gome_live_show
import "time"
//#region 根据创建时间查询订单的列表信息
// 查询半小时内的订单,
type QueryOrderListForTimeReq struct {
StartTime time.Time `json:"startTime"` // 订单创建起始时间,默认只查询当天订单
EndTime time.Time `json:"endTime"` // 订单创建时间截止,默认只查询当天订单
StoreCode string `json:"storeCode"` // 过滤店铺信息,不传递是所有
OrderNo string `json:"orderNo"` // 过滤订单号
Status string `json:"status"` // 订单状态枚举值,不传递是所有
Page
}
// 返回参数
type QueryOrderListForTimeRes struct {
SystemParameterRes
Data *QueryOrderListForTimeData
}
type QueryOrderListForTimeData struct {
Record []*QueryOrderListForTimeRecord
SystemRecordDataDetailRes
}
type QueryOrderListForTimeRecord struct {
StoreCode string `json:"storeCode"`
StoreName string `json:"storeName"`
OrderNo string `json:"orderNo"`
UserName string `json:"userName"` // 下单用户名
Mobile string `json:"mobile"` // 下单用户电话
Items []*Items `json:"items"` // 商品
TotalAmount float64 `json:"totalAmount"` // 订单总价
RealAmount float64 `json:"realAmount"` // 用户实付金额
CreateTime string `json:"createTime"` // 下单时间
Status string `json:"status"` // 订单状态
UserCancelState string `json:"userCancelState"` // 订单取消审核 NONE-未申请ON-申请中PASS-申请通过REJECT-申请被拒绝
}
type Items struct {
SpuCode string `json:"spuCode"` // 平台 spu 编码
SkuCode string `json:"skuCode"` // 平台 sku 编码
ThirdSkuCode string `json:"thirdSkuCode"` // 外部 sku 编码
GoodsName string `json:"goodsName"` // 商品名称
Quantity int `json:"quantity"` // 购买商品数量
Amount float64 `json:"amount"` // 商品总价
}
//#endregion
//#region 查询订单详情接口
type QueryOrderDetailRes struct {
SystemParameterRes
Data *QueryOrderListForTimeData
}
type QueryOrderDetailResData struct {
Record *QueryOrderDetailRecordReq
SystemRecordDataDetailRes
}
type QueryOrderDetailRecordReq struct {
StoreCode string `json:"storeCode"` // 店铺码
OrderNo string `json:"orderNo"` // 订单号
OrderType string `json:"orderType"` // 订单类型
OrderPayType string `json:"orderPayType"` // 订单付款方式
Mobile string `json:"mobile"` // 用户手机号码
UserName string `json:"userName"` // 用户名
Items []*GoodsItems `json:"items"` // 商品列表
TotalAmount float64 `json:"totalAmount"` // 商品订单总价
RealAmount float64 `json:"realAmount"` // 商品实付金额
Quantity int `json:"quantity"` // 订单下单数量
CreateTime string `json:"createTime"` // 下单时间
Status string `json:"status"` // 订单状态
Comment string `json:"comment"` // 用户下单备注
CancelInfo *CancelInfo `json:"cancelInfo"` // 订单取消信息集
DeliveryInfo *DeliveryInfo `json:"deliveryInfo"` // 配送信息集
ExpressInfo *ExpressInfo `json:"expressInfo"` // 物流信息集
}
type GoodsItems struct {
SkuCode string `json:"skuCode"` // 平台 sku 编码
SpuCode string `json:"spuCode"` // 平台 spu 编码
ThirdSkuCode string `json:"thirdSkuCode"` // 外部 sku 编码
MainPictureURL string `json:"mainPictureUrl"` // 商品主图
FullSpecName string `json:"fullSpecName"` // 商品规格名称
FullCatName string `json:"fullCatName"` // 商品所属品类
Quantity int `json:"quantity"` // 购买商品数量
SalePrice float64 `json:"salePrice"` // 商品售价
SkuRealAmount float64 `json:"skuRealAmount"` // 商品项实付金额
FinishAfterNumber int `json:"finishAfterNumber"` // 已申请售后数量
AftersaleEndTime string `json:"aftersaleEndTime"` // 售后截止时间
GoodsName string `json:"goodsName"` // 商品名称
Cat1Code string `json:"cat1Code"`
Cat2Code string `json:"cat2Code"`
Cat3Code string `json:"cat3Code"`
SpuName string `json:"spuName"`
OrderItemNo string `json:"orderItemNo"`
SkuName string `json:"skuName"`
}
type CancelInfo struct {
UserCancelApplyTime string `json:"userCancelApplyTime"` // 用户申请取消时间
UserCancelReasonStr string `json:"userCancelReasonStr"` // 用户申请取消原因
UserCancelState string `json:"userCancelState"` // 订单取消审核状态
MerchantCancelReason string `json:"merchantCancelReason"` // 商家取消原因Id
MerchantCancelReasonStr string `json:"merchantCancelReasonStr"` // 商家取消原因
}
type DeliveryInfo struct {
DeliveryOrderNo string `json:"deliveryOrderNo"` // 配送单号
ReceiverName string `json:"receiverName"` // 收货人姓名
ReceiverMobile string `json:"receiverMobile"` // 收货人手机号
ReceiverAddress string `json:"receiverAddress"` // 地址包含省市
ProvinceCode string `json:"provinceCode"` // 省编码
ProvinceName string `json:"provinceName"` // 省名称
CityCode string `json:"cityCode"` // 市编码
CityName string `json:"cityName"` // 市名称
DistrictCode string `json:"districtCode"` // 区编码
DistrictName string `json:"districtName"` // 区名称
DeliveryAdress string `json:"deliveryAdress"` // 详细地址
DeliveryAmount float64 `json:"deliveryAmount"` // 运费金额
}
type ExpressInfo struct {
ExpressName string `json:"expressName"` // 物流单号
ExpressNo string `json:"expressNo"` // 物流公司名称
ExpressCode string `json:"expressCode"` // 物流公司标准编码
}
//#endregion
//#region 此接口主要用于商户基于订单发货场景,第三方平台调用成功后,订单状态将变为待收货
type DeliveryOrderReq struct {
OrderNo string `json:"orderNo"` // 订单号[必填]
storeCode string `json:"storeCode"` // 平台店铺编码[必填]
ExpressList []*struct { // 订单发货物流集合[必填]
ExpressNo string `json:"expressNo"` // 物流单号[必填]
ExpressCode string `json:"expressCode"` // 物流公司编码[必填]
ExpressName string `json:"expressName"` // 物流公司物流公司[必填]
}
}
//#endregion
//#region 商户审核用户取消订单申请
type AgreeOrRefuseCheck struct {
OrderNo string `json:"orderNo"` // 订单号[必填]
StoreCode string `json:"storeCode"` // 店铺码[必填]
CancelApplyResult int `json:"cancelApplyResult"` // 审核结果 商户审核结果1 同意2拒绝[必填]
CancelApplyRejectReason string `json:"cancelApplyRejectReason"` // 商户审核用户取消拒绝原因
}
//#endregion
//#region 获取售后单详情
type QueryAfterSaleOrderDetailRes struct {
SystemParameterRes
Data *QueryAfterSaleOrderDetailDataRes
}
type QueryAfterSaleOrderDetailDataRes struct {
SystemRecordDataDetailRes
Records *QueryAfterSaleOrderDetailRecordsRes
}
type QueryAfterSaleOrderDetailRecordsRes struct {
AfterSaleNo string `json:"afterSaleNo"` // 售后单单号
StoreCode string `json:"storeCode"` // 平台店铺编码
StoreName string `json:"storeName"` // 平台店铺名称
OrderNo string `json:"orderNo"` // 订单号
AfterSaleType int `json:"afterSaleType"` // 售后类型
RefundReasonCode string `json:"refundReasonCode"` // 退款原因id
RefundReasonStr string `json:"refundReasonStr"` // 退款原因描述
CargoState int `json:"cargoState"` // 货物 状态
IssueDesc string `json:"issueDesc"` // 补充描述和凭证
SkuCode string `json:"skuCode"` // 平台 sku 编码
GoodsName string `json:"goodsName"` // 平台 sku 名称
AfterSaleNumber int `json:"afterSaleNumber"` // 申请售后 sku 数量
AfterSaleStatus int `json:"afterSaleStatus"` // 售后单状态
CreateTime time.Time `json:"createTime"` // 创建时间
ApproveDeadline time.Time `json:"approveDeadline"` // 商家审核截至时建间
AgreeApplyTime time.Time `json:"agreeApplyTime"` // 商家同意时间
AfterSaleRejectReason string `json:"afterSaleRejectReason"` // 商家拒绝理由
DeliverGoodsDeadline time.Time `json:"deliverGoodsDeadline"` // 用户发货截至时间
ConfirmGoodsDeadline time.Time `json:"confirmGoodsDeadline"` // 商家收货截至时 间
ExpectRefundAmount float64 `json:"expectRefundAmount"` // 预计退款金额
ReturnLogisticsNo string `json:"returnLogisticsNo"` // 用户退货快递单号
ReturnLogistics string `json:"returnLogistics"` // 用户退货快递公司
ReturnTime time.Time `json:"returnTime"` // 用户退货退货时间
}
//#endregion
//#region 上传图片
type GomeiUploadImgRes struct {
Code int64 `json:"code"` // 响应码
Timestamp int64 `json:"timestamp"` // 时间戳(秒)
Message string `json:"message"` // 响应描述
RequestId string `json:"requestId"` // 请求id
Data *struct {
Url string `json:"url"`
}
}
//#endregion

View File

@@ -0,0 +1 @@
package gome_live_show

View File

@@ -0,0 +1,121 @@
package gome_live_show
import (
"encoding/json"
"errors"
"git.rosy.net.cn/baseapi/utils"
"net/http"
)
// 查询店铺列表
func (a *API) QueryStoreList(storeList *GetStoreListReq) (result *GetStoreListRes, err error) {
if storeList.PageSize == ConstNumberOne {
storeList.PageSize = PageSize
}
if storeList.PageNumber == ConstNumberOne {
storeList.PageNumber = PageNumber
}
storeByte, err := json.Marshal(storeList)
if err != nil {
return nil, err
}
gomeStoreList, err := a.AccessAPI(gomeUrl, GetStoreListApi, http.MethodPost, utils.Struct2FlatMap(a.MakeRequestParam(storeByte)))
if err != nil {
return nil, err
}
resultData := &GetStoreListRes{}
if err := utils.Map2StructByJson(gomeStoreList, resultData, false); err != nil {
return nil, err
}
if resultData.Code != 200 {
return nil, errors.New(resultData.Message)
}
return resultData, nil
}
// 店铺商品分类列表查询
func (a *API) QueryStoreCategoryList(param *QueryStoreGoodsCategoryListReq) (*QueryStoreGoodsCategoryListRes, error) {
byteParam, err := json.Marshal(param)
if err != nil {
return nil, err
}
gomeResult, err := a.AccessAPI(gomeUrl, GetStoreCategoryListApi, http.MethodPost, utils.Struct2FlatMap(a.MakeRequestParam(byteParam)))
if err != nil {
return nil, err
}
result := &QueryStoreGoodsCategoryListRes{}
if err := utils.Map2StructByJson(gomeResult, result, false); err != nil {
return nil, err
}
return result, nil
}
// 店铺商品分类新增
func (a *API) AddStoreCategory(req *StoreAddGoodsCategory) (*SystemParameterRes, error) {
byteParam, err := json.Marshal(req)
if err != nil {
return nil, err
}
gomeResult, err := a.AccessAPI(gomeUrl, AddStoreCategoryApi, http.MethodPost, utils.Struct2FlatMap(a.MakeRequestParam(byteParam)))
if err != nil {
return nil, err
}
result := &SystemParameterRes{}
if err := utils.Map2StructByJson(gomeResult, result, false); err != nil {
return nil, err
}
if result.Code != 200 {
return nil, errors.New(result.Message)
}
return result, nil
}
// 店铺商品分类编辑
func (a *API) ModifyStoreGoodsCategory(req *StoreModifyGoodsCategory) (*SystemParameterRes, error) {
byteParam, err := json.Marshal(req)
if err != nil {
return nil, err
}
gomeResult, err := a.AccessAPI(gomeUrl, ModifyStoreCategoryApi, http.MethodPost, utils.Struct2FlatMap(a.MakeRequestParam(byteParam)))
if err != nil {
return nil, err
}
result := &SystemParameterRes{}
if err := utils.Map2StructByJson(gomeResult, result, false); err != nil {
return nil, err
}
if result.Code != 200 {
return nil, errors.New(result.Message)
}
return result, nil
}
// 店铺商品分类删除
func (a *API) DeleteStoreGoodsCategory(storeCode, categoryCode string) (*SystemParameterRes, error) {
byteParam, err := json.Marshal(map[string]string{"storeCode": storeCode, "categoryCode": categoryCode})
if err != nil {
return nil, err
}
gomeResult, err := a.AccessAPI(gomeUrl, DeleteStoreCategoryApi, http.MethodPost, utils.Struct2FlatMap(a.MakeRequestParam(byteParam)))
if err != nil {
return nil, err
}
result := &SystemParameterRes{}
if err := utils.Map2StructByJson(gomeResult, result, false); err != nil {
return nil, err
}
if result.Code != 200 {
return nil, errors.New(result.Message)
}
return result, nil
}

View File

@@ -0,0 +1,259 @@
package gome_live_show
import (
"encoding/json"
"errors"
"git.rosy.net.cn/baseapi/utils"
"net/http"
)
// 商户商品列表查询
func (a *API) GetMerchantStoreGoodsList(req *QueryStoreGoodsListReq) (*QueryStoreGoodsListRes, error) {
if req.PageNumber == 0 {
req.PageNumber = 1
}
if req.PageSize == 0 {
req.PageSize = 50
}
byteParam, err := json.Marshal(req)
if err != nil {
return nil, err
}
gomeResult, err := a.AccessAPI(gomeUrl, GetMerchantGoodsList, http.MethodPost, utils.Struct2FlatMap(a.MakeRequestParam(byteParam)))
if err != nil {
return nil, err
}
result := &QueryStoreGoodsListRes{}
if err := utils.Map2StructByJson(gomeResult, result, false); err != nil {
return nil, err
}
if result.Code != 200 {
return nil, errors.New(result.Message)
}
return result, nil
}
// 商品详情查询,包含商品基本信息名称、图片、品类,规格
func (a *API) QueryMerchantStoreGoodsDetail(spuCode string) (*QueryStoreGoodsDetailsRes, error) {
byteSpuCode, err := json.Marshal(map[string]string{"spuCode": spuCode})
if err != nil {
return nil, err
}
gomeResult, err := a.AccessAPI(gomeUrl, GetMerchantGoodsDetailList, http.MethodPost, utils.Struct2FlatMap(a.MakeRequestParam(byteSpuCode)))
if err != nil {
return nil, err
}
result := &QueryStoreGoodsDetailsRes{}
if err := utils.Map2StructByJson(gomeResult, result, false); err != nil {
return nil, err
}
if result.Code != 200 {
return nil, errors.New(result.Message)
}
return result, nil
}
// 商户创建新的商品
func (a *API) CreateMerchantGoodsOnStore(req *CreateGoodsListToStore) (*SystemParameterRes, error) {
byteReq, err := json.Marshal(req)
if err != nil {
return nil, err
}
gomeResult, err := a.AccessAPI(gomeUrl, CreateMerchantGoodsToStore, http.MethodPost, utils.Struct2FlatMap(a.MakeRequestParam(byteReq)))
if err != nil {
return nil, err
}
result := &SystemParameterRes{}
if err := utils.Map2StructByJson(gomeResult, result, false); err != nil {
return nil, err
}
if result.Code != 200 {
return nil, errors.New(result.Message)
}
return result, nil
}
// 修改商户商品商品一旦创建不可修改商品的品类和类型只能修改商品的基础信息如果规格信息有修改需要同时入参specProperty 和 skuSaleList
func (a *API) UpdateMerchantGoodsOnStore(req *CreateGoodsListToStore) (*SystemParameterRes, error) {
byteReq, err := json.Marshal(req)
if err != nil {
return nil, err
}
gomeResult, err := a.AccessAPI(gomeUrl, UpdateMerchantGoodsToStore, http.MethodPost, utils.Struct2FlatMap(a.MakeRequestParam(byteReq)))
if err != nil {
return nil, err
}
result := &SystemParameterRes{}
if err := utils.Map2StructByJson(gomeResult, result, false); err != nil {
return nil, err
}
if result.Code != 200 {
return nil, errors.New(result.Message)
}
return result, nil
}
// 不在使用的商户商品可删除
func (a *API) DeleteGoodsOnStore(spuCode string) (*SystemParameterRes, error) {
param, err := json.Marshal(map[string]string{"spuCode": spuCode})
if err != nil {
return nil, err
}
gomeResult, err := a.AccessAPI(gomeUrl, DeleteMerchantGoodsToStore, http.MethodPost, utils.Struct2FlatMap(a.MakeRequestParam(param)))
if err != nil {
return nil, err
}
result := &SystemParameterRes{}
if err := utils.Map2StructByJson(gomeResult, result, false); err != nil {
return nil, err
}
if result.Code != 200 {
return nil, errors.New(result.Message)
}
return result, nil
}
// 根据店铺编码查询店铺商品列表。
func (a *API) QueryGoodsListById(req *QueryGoodsListForStoreReq) (*QueryGoodsListForStoreRes, error) {
byteReq, err := json.Marshal(req)
if err != nil {
return nil, err
}
gomeResult, err := a.AccessAPI(gomeUrl, QueryGoodsListByStoreId, http.MethodPost, utils.Struct2FlatMap(a.MakeRequestParam(byteReq)))
if err != nil {
return nil, err
}
result := &QueryGoodsListForStoreRes{}
if err := utils.Map2StructByJson(gomeResult, result, false); err != nil {
return nil, err
}
if result.Code != 200 {
return nil, errors.New(result.Message)
}
return result, nil
}
// 查询单商品接口
func (a *API) QueryOneGoodsForStore(storeCode, skuCode string) (*QueryStoreOneGoodsRes, error) {
if storeCode == "" || skuCode == "" {
return nil, errors.New("参数不能为空")
}
byteReq, err := json.Marshal(map[string]string{"storeCode": storeCode, "skuCode": skuCode})
if err != nil {
return nil, err
}
gomeResult, err := a.AccessAPI(gomeUrl, QueryOneGoodsByStoreId, http.MethodPost, utils.Struct2FlatMap(a.MakeRequestParam(byteReq)))
if err != nil {
return nil, err
}
result := &QueryStoreOneGoodsRes{}
if err := utils.Map2StructByJson(gomeResult, result, false); err != nil {
return nil, err
}
if result.Code != 200 {
return nil, errors.New(result.Message)
}
return result, nil
}
// 商品上下架操作 功能描述: 商品上下架,支持单商品或多商品;如果商品在审核中或驳回情况下,
//将禁止商户的上架操作,最多支持10 个sku此接口不会立刻响应成功或失败需要调用查询接口确定
func (a *API) OnOffLineGoodsOnStore(req *ShelfGoodsForStoreReq) (*SystemParameterRes, error) {
byteReq, err := json.Marshal(req)
if err != nil {
return nil, err
}
gomeResult, err := a.AccessAPI(gomeUrl, GoodsOnOffLineByStore, http.MethodPost, utils.Struct2FlatMap(a.MakeRequestParam(byteReq)))
if err != nil {
return nil, err
}
result := &SystemParameterRes{}
if err := utils.Map2StructByJson(gomeResult, result, false); err != nil {
return nil, err
}
if result.Code != 200 {
return nil, errors.New(result.Message)
}
return result, nil
}
// 单商品维护售价
func (a *API) UpdateOnGoodsPriceForStore(req *StoreGoodsPriceUpdateReq) (*SystemParameterRes, error) {
byteReq, err := json.Marshal(req)
if err != nil {
return nil, err
}
gomeResult, err := a.AccessAPI(gomeUrl, UpdatePriceToOneGoodsByStore, http.MethodPost, utils.Struct2FlatMap(a.MakeRequestParam(byteReq)))
if err != nil {
return nil, err
}
result := &SystemParameterRes{}
if err := utils.Map2StructByJson(gomeResult, result, false); err != nil {
return nil, err
}
if result.Code != 200 {
return nil, errors.New(result.Message)
}
return result, nil
}
// 商品库存更新接口
func (a *API) UpdateStockForStore(req *StoreGoodsStockUpdateReq) (*SystemParameterRes, error) {
byteReq, err := json.Marshal(req)
if err != nil {
return nil, err
}
gomeResult, err := a.AccessAPI(gomeUrl, UpdateGoodsStockForStore, http.MethodPost, utils.Struct2FlatMap(a.MakeRequestParam(byteReq)))
if err != nil {
return nil, err
}
result := &SystemParameterRes{}
if err := utils.Map2StructByJson(gomeResult, result, false); err != nil {
return nil, err
}
if result.Code != 200 {
return nil, errors.New(result.Message)
}
return result, nil
}
// 新增店铺商品
func (a *API) CreateGoodsForStore(req *CreateGoodsForStoreReq) (*SystemParameterRes, error) {
byteReq, err := json.Marshal(req)
if err != nil {
return nil, err
}
gomeResult, err := a.AccessAPI(gomeUrl, AddGoodsForStore, http.MethodPost, utils.Struct2FlatMap(a.MakeRequestParam(byteReq)))
if err != nil {
return nil, err
}
result := &SystemParameterRes{}
if err := utils.Map2StructByJson(gomeResult, result, false); err != nil {
return nil, err
}
if result.Code != 200 {
return nil, errors.New(result.Message)
}
return result, nil
}

View File

@@ -0,0 +1,327 @@
package gome_live_show
import "time"
//#region 获取商铺详情
// 查询商铺列表
type GetStoreListReq struct {
Page
StoreName string `json:"storeName"`
}
// 查询商品列表返回值
type GetStoreListRes struct {
SystemParameterRes
Data *StoreListRecords
}
type StoreListRecords struct {
Records []*RecordsList `json:"records"`
SystemRecordDataDetailRes
}
type RecordsList struct {
StoreName string `json:"storeName"` // 店铺名称
StoreAlias string `json:"storeAlias"` // 店铺别名
StoreStatus int `json:"storeStatus"` // 店铺营业状态 1 待开店2 已开店3 临时闭店4已闭店
StoreCode string `json:"storeCode"` // 平台店铺编码
}
//#endregion
//#region 店铺商品分类列表查询
// 请求参数
type QueryStoreGoodsCategoryListReq struct {
Page
StoreCode string `json:"storeCode"` // 平台店铺编码
}
// 返回参数
type QueryStoreGoodsCategoryListRes struct {
SystemParameterRes
Data *QueryStoreGoodsCategoryListRecord
}
type QueryStoreGoodsCategoryListRecord struct {
SystemRecordDataDetailRes
Records []*StoreGoodsCategoryListRecord
}
type StoreGoodsCategoryListRecord struct {
CategoryCode string `json:"categoryCode"` // 店铺分类编码
CategoryName string `json:"categoryName"` // 店铺分类名称
Rank int `json:"rank"` // 排序
}
//#endregion
//#region 店铺分类新增
// 店铺商品分类新增
type StoreAddGoodsCategory struct {
StoreCode string `json:"storeCode"` // 平台店铺编码[必填]
CategoryName string `json:"categoryName"` // 分类名称[必填]
Rank int `json:"rank"` // 排序
}
// 店铺商品分类修改
type StoreModifyGoodsCategory struct {
StoreCode string `json:"storeCode"` // 平台店铺编码[必填]
CategoryCode string `json:"categoryCode"` // 店铺商品分类编码[必填]
CategoryName string `json:"categoryName"` // 分类名称[必填]
Rank int `json:"rank"` // 排序[必填]
}
//#endregion
//#region 商户商品列表
// 商户商品列表查询参数
type QueryStoreGoodsListReq struct {
GoodsName string `json:"goodsName"` // 商品名称[非必填]
Cat3Code string `json:"cat3Code"` // 三级品类[非必填]
Page
}
// 返回结构体
type QueryStoreGoodsListRes struct {
SystemParameterRes
Data *QueryStoreGoodsListRecord
}
type QueryStoreGoodsListRecord struct {
SystemRecordDataDetailRes
Records []*struct {
SpuCode string `json:"spuCode"` // 三级品类
GoodsName string `json:"goodsName"` // 商品名称
MainPictureUrl string `json:"mainPictureUrl"` // 商品主图
FullCatName string `json:"fullCatName"` // 商品所属品类 零售/美妆护肤/面部护肤
CreateTime string `json:"createTime"` // 创建时间
}
}
type QueryStoreGoodsListData struct {
SpuCode string `json:"spuCode"` // 三级品类
GoodsName string `json:"goodsName"` // 商品名称
MainPictureUrl string `json:"mainPictureUrl"` // 商品主图
FullCatName string `json:"fullCatName"` // 商品所属品类
CreateTime string `json:"createTime"` // 创建时间
}
//#endregion
//#region 商户商品详情
// 商品详情请求参数
type QueryStoreGoodsDetailsRes struct {
SystemParameterRes
Data *QueryStoreGoodsDetailsData
}
type QueryStoreGoodsDetailsData struct {
SystemRecordDataDetailRes
Records *QueryStoreGoodsDetailsRecords
}
type QueryStoreGoodsDetailsRecords struct {
GoodsName string `json:"goodsName"` // 商品名称
MainPictureUrl string `json:"mainPictureUrl"` // 商品主图
OtherPictureUrl string `json:"otherPictureUrl"` // 商品其他图
VideoUrl string `json:"videoUrl"` // 商品视频
Detail string `json:"detail"` // 商品详情
Cat1Code string `json:"cat1Code"` // 一级目录id
Cat2Code string `json:"cat2Code"` // 二级目录id
Cat3Code string `json:"cat3Code"` // 三级目录id
Cat1Name string `json:"cat1Name"` // 一级目录名称
Cat2Name string `json:"cat2Name"` // 二级目录名称
Cat3Name string `json:"cat3Name"` // 三级目录名称
SpecProperty []*SpecPropertyList `json:"specProperty"` // 商品支持的规格最多支持5个。
SkuSaleList []*SkuSaleList `json:"skuSaleList"` // 不同规格组合是一个sku示例颜色
}
// 商品规格
type SpecPropertyList struct {
SpecCode string `json:"specCode"` // 规格id
SpecName string `json:"specName"` // 规格名称(颜色)
SpecValues []*SpecValues
}
// sku
type SkuSaleList struct {
SkuCode string `json:"skuCode"` // 颜色名称(红色)
Specification string `json:"specification"` // 颜色名称(红色)
MarketPrice float64 `json:"marketPrice"` // 颜色名称(红色)
ThirdSkuCode string `json:"thirdSkuCode"` // 颜色名称(红色)
}
//#endregion
//#region 商户创建商品
type CreateGoodsListToStore struct {
GoodsName string `json:"goodsName"` // 商品名称[必填]
MainPictureURL string `json:"mainPictureUrl"` // 商品主图[必填] 格式pngjpeg大小3 兆以下宽高强制比例34 像素750px
Detail string `json:"detail"` // 详情[必填]
Cat3Code string `json:"cat3Code"` // 三级类目[必填]
SpecProperty []*SpecProperty `json:"specProperty"` // 规格集合[必填]
SkuSaleList []*SkuSaleListData `json:"skuSaleList"` // sku 售卖组[必填]
GoodsType string `json:"goodsType"` // 商品类型[必填]
OtherPictureURL []string `json:"otherPictureUrl"` // 商品其他图【最多四张】
VideoURL string `json:"videoUrl"` // 格式mp4, 大小20兆以下时长30秒以下。
SpecCode string `json:"specCode"` // 规格
SpecName string `json:"specName"` // 规格名称
SpecValues string `json:"specValues"` // 规格值集合
SpecValueCode string `json:"specValueCode"` // 规格值 ID
SpecValueName string `json:"specValueName"` // 规格值
Specification string `json:"specification"` // 规格id集合逗号间隔
MarketPrice float64 `json:"marketPrice"` // 参考价
ThirdSkuCode string `json:"thirdSkuCode"` // 第三方业务编码
}
type SpecValues struct {
SpecValueCode string `json:"specValueCode"` // 规格code
SpecValueName string `json:"specValueName"` // 规格值
}
type SpecProperty struct {
SpecCode string `json:"specCode"` // 规格
SpecName string `json:"specName"` // 规格名称
SpecValues []*SpecValues `json:"specValues"` // 规格值集合
}
type SkuSaleListData struct {
Specification string `json:"specification"` // 规格id集合, 逗号间隔
MarketPrice float64 `json:"marketPrice"` // 参考价
ThirdSkuCode string `json:"thirdSkuCode"` // 第三方业务
}
//#endregion
//#region 批量查询门店商品
// 批量查询门店商品请求参数
type QueryGoodsListForStoreReq struct {
storeCode string `json:"storeCode"` // 平台店铺编码 [必填]
Page
shelveStatus string `json:"shelveStatus"` // 可过滤商品上架状态枚举值;不传递返回全部
Cat1Code string `json:"cat1Code"` // 一级目录id
Cat2Code string `json:"cat2Code"` // 二级目录id
Cat3Code string `json:"cat3Code"` // 三级目录id
}
// 批量查询门店商品请求参数 返回参数
type QueryGoodsListForStoreRes struct {
SystemParameterRes
Data *QueryGoodsListForStoreDataRes
}
type QueryGoodsListForStoreDataRes struct {
SystemRecordDataDetailRes
Records []*QueryGoodsListForStoreRecordRes
}
type QueryGoodsListForStoreRecordRes struct {
SkuCode string `json:"skuCode"`
SpuCode string `json:"spuCode"`
ThirdSkuCode string `json:"thirdSkuCode"`
GoodsName string `json:"goodsName"`
Alias string `json:"alias"`
SalePrice float64 `json:"salePrice"`
MarketPrice float64 `json:"marketPrice"`
GoodsType string `json:"goodsType"`
ShelveStatus string `json:"shelveStatus"`
ShelveDate string `json:"shelveDate"`
UnshelveDate string `json:"unshelveDate"`
StockNum int `json:"stockNum"`
}
//#endregion
//#region 查询单个门店
type QueryStoreOneGoodsRes struct {
SystemParameterRes
Data *QueryStoreOneGoodsDataRes
}
type QueryStoreOneGoodsDataRes struct {
SystemRecordDataDetailRes
Records *QueryStoreOneGoodsRecordRes
}
type QueryStoreOneGoodsRecordRes struct {
SkuCode string `json:"skuCode"` // 平台 sku 编码
SpuCode string `json:"spuCode"` // 平台 spu 编码,乐活秀
ThirdSkuCode string `json:"thirdSkuCode"` // 第三方平台sku 编码
GoodsName string `json:"goodsName"` // 商品名称
Alias string `json:"alias"` // 商品别名或简称
SalePrice float64 `json:"salePrice"` // 商品售价
MarketPrice float64 `json:"marketPrice"` // 参考价
GoodsType string `json:"goodsType"` // 商品类型
FullCatName string `json:"fullCatName"` // 商品所属分类
ShelveDate time.Time `json:"shelveDate"` // 上架时间
UnshelveDate time.Time `json:"unshelveDate"` // 下架时间
StockNum int `json:"stockNum"` // 库存数量
ShelveStatus string `json:"shelveStatus"` // 商品上下架状态
Isshow int `json:"isshow"` // c端隐藏或显示
DeliverType string `json:"deliverType"` // 配送方式
DeliverTemplateCode string `json:"deliverTemplateCode"` // 运费模板
CategoryCodes string `json:"categoryCodes"` // 分类id
CategoryNames string `json:"categoryNames"` // 分类名称
MainPictureURL string `json:"mainPictureUrl"` // 商品主图
OtherPictureURL []string `json:"otherPictureUrl"` // 商品其他图
Specification []string `json:"specification"` // 商品规格属性
FullSpecName string `json:"fullSpecName"` // 商品规格名称
VideoUrls string `json:"videoUrls"` // 商品视频
Detail string `json:"detail"` // 商品详情
}
//#endregion
//#region 平台商品上下架
type ShelfGoodsForStoreReq struct {
StoreCode string `json:"storeCode"` // 平台店铺编码[必填]
SkuCode []string `json:"SkuCode"` // 平台 sku编码[必填]
ShelveStatus string `json:"SkuCode"` // 商品上架状态[必填]
}
//#endregion
//#region 平台商品价格修改
type StoreGoodsPriceUpdateReq struct {
StoreCode string `json:"storeCode"` // 平台店铺编码[必填]
SkuCode string `json:"SkuCode"` // 平台 sku编码[必填]
SalePrice float64 `json:"salePrice"` // 品商上品架售状价,枚两举位值小数,示例2.51元[必填]
}
//#endregion
//#region 平台商品库存修改
type StoreGoodsStockUpdateReq struct {
StoreCode string `json:"storeCode"` // 平台店铺编码[必填]
ItemStocks []*StoreSkuNum
}
type StoreSkuNum struct {
SkuCode string `json:"skuCode"` // 平台店铺编码
StockNum int64 `json:"stockNum"` // 库存数量
}
//#endregion
//#region 新增平台商品
type CreateGoodsForStoreReq struct {
StoreCode string `json:"storeCode"` // 平台店铺编码[必填]
SkuCode string `json:"SkuCode"` // 平台 sku编码[必填]
SalePrice float64 `json:"salePrice"` // 品商上品架售状价,枚两举位值小数,示例2.51元[必填]
DeliverType string `json:"deliverType"` // 配送方式[必填]
DeliverTemplateCode string `json:"deliverTemplateCode"` // 运费模板 运费模板信息id调用查询接口
}
//#endregion

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,32 @@
package gome_live_show
// 系统参数,所有接口都需要携带的参数
type SystemParameterReq struct {
AuthToken string `json:"authToken"` // 访问令牌,需要定时刷新获取
Timestamp int64 `json:"timestamp"` // 时间戳默认有效时间为10分钟
Version string `json:"version"` // 版本号
Sign string `json:"sign"` // 签名
Biz string `json:"biz"` // 业务参数json字符串为空时请传{}
}
// 系统参数返回值
type SystemParameterRes struct {
Code int64 `json:"code"` // 响应码
Timestamp int64 `json:"timestamp"` // 时间戳(秒)
Message string `json:"message"` // 响应描述
RequestId string `json:"requestId"` // 请求id
}
type Page struct {
PageNumber int `json:"pageNumber"` // 查询页码
PageSize int `json:"pageSize"` // 展示条数默认显示10条最高50条
}
// 系统参数,返回列表数据详情
type SystemRecordDataDetailRes struct {
Page
StartRow int `json:"startRow"` // 开始行
EndRow int `json:"endRow"` // 结束行
Total int `json:"total"` // 列表总数
PageTotal int `json:"pageTotal"` // 总页数
}

View File

@@ -0,0 +1,39 @@
package gome_live_show
import (
"git.rosy.net.cn/baseapi/platformapi"
"net/http"
"sync"
)
// 注册请求api
type API struct {
code string `json:"code"` // 商户码
appKey string `json:"appKey"` // appkey
sign string `json:"sign"` // 签名
timestamp string `json:"timestamp"` // 请求时间戳
appSecret string `json:"app_secret"` // 私钥
refreshToken string `json:"refresh_token"` // 刷新token
expiration string `json:"expiration"` // 刷新token过期时间
sessionToken string `json:"session_token"` // token
version string `json:"version"` // 版本
locker sync.RWMutex
client *http.Client
config *platformapi.APIConfig
}
// 国美token
type gomeToken struct {
Code int64 `json:"code"`
Timestamp int64 `json:"timestamp"`
Data *TokenInfo `json:"data"`
RequestId string `json:"request_id"`
}
// 获取token
type TokenInfo struct {
SessionToken string `json:"sessionToken"` // 商家令牌 sessionToken String
Expiration string `json:"expiration"` // 授权到期时间
RefreshToken string `json:"refreshToken"` // 刷新令牌
AppKey string `json:"appKey"` // 应用 code
}

View File

@@ -316,3 +316,9 @@ func TestQueryMemberTransListByCondition(t *testing.T) {
}
t.Log(utils.Format4Output(result, false))
}
type GuoMei struct {
appKey string
timestamp string
sign string
}

View File

@@ -22,10 +22,10 @@ func init() {
//api = New("589", "a81eb3df418d83d6a1a4b7c572156d2f", "", "")
// 果园
//api = New("4123", "df2c88338b85f830cebce2a9eab56628", "", "")
api = New("4123", "df2c88338b85f830cebce2a9eab56628", "", "")
//商超
api = New("5873", "41c479790a76f86326f89e8048964739", "", "token_vI4fNBaB5J1qvft0WmZG_g") //token_nH_IlcWQKAkZBqklwItNRw
//api = New("5873", "41c479790a76f86326f89e8048964739", "", "token_vI4fNBaB5J1qvft0WmZG_g") //token_nH_IlcWQKAkZBqklwItNRw
cookieStr := `
acctId=57396785; token=0bWbK5VbK50E2BmIhIH2zHB-am_y7mB37yXHm6RLZWx4*; wmPoiId=-1;
`

View File

@@ -7,7 +7,7 @@ import (
)
func TestRetailCatList(t *testing.T) {
result, err := api.RetailCatList("11655829")
result, err := api.RetailCatList("11105778")
if err != nil {
t.Fatal(err)
}

View File

@@ -4,7 +4,6 @@ import (
"encoding/json"
"fmt"
"git.rosy.net.cn/baseapi/platformapi"
"git.rosy.net.cn/baseapi/utils"
"net/http"
"strings"
)
@@ -30,44 +29,24 @@ func New(clientSecret, clientKey string, config ...*platformapi.APIConfig) *API
}
}
func (a *API) AccessAPI(baseUrl, actionApi, method string, bizParams map[string]interface{}) (retVal map[string]interface{}, err error) {
// 序列化
data, err := json.Marshal(bizParams)
func (a *API) AccessAPI2(url string, params map[string]interface{}) (retVal map[string]interface{}, err error) {
data, err := json.Marshal(params)
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)
err = platformapi.AccessPlatformAPIWithRetry(a.client,
func() *http.Request {
request, _ := http.NewRequest(http.MethodPost, url, strings.NewReader(string(data)))
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")
}
retVal = jsonResult1
return platformapi.ErrLevelSuccess, nil
})
return retVal, err
}

View File

@@ -7,9 +7,10 @@ import (
)
const (
BaseURL = "https://open.douyin.com"
TiktokTokenUrl = "/oauth/access_token/"
TiktokRefreshTokenUrl = "/oauth/renew_refresh_token/"
BaseURLTT = "https://open.douyin.com" // 抖音
BaseURL = "https://open.snssdk.com" // 头条
TiktokTokenUrl = "oauth/access_token/"
TiktokRefreshTokenUrl = "oauth/renew_refresh_token/"
)
type API struct {

View File

@@ -0,0 +1,33 @@
package tiktok
import (
"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)
}
func TestCode(t *testing.T) {
a := New("1e0d98ad7b2e9b1ba5d7529a7e17fa9b9d65380a ", "tta6a1d01c399f264201")
data, err := a.GetTiktokToken("7aK7VOuXnlU2OIiFDFi_ssRX9vQdXtDekgW-yV77Q20rVsw8-8DX4ASbXMTA3Z-gr8tstJcgMgL04OFc-BgXB92DC6otQV6GQUiy-TzhpH109xZfZwhCKjt-OiI")
fmt.Println(err)
fmt.Println(data)
}
func TestCode2(t *testing.T) {
a := New("1e0d98ad7b2e9b1ba5d7529a7e17fa9b9d65380a ", "tta6a1d01c399f264201")
data, err := a.GetTiktokToken2("CCRHRLfkl8kSHXuuZTDWQayoqHVXF2Vl4qrt173jxfWhg6Q1pZCbjRO0TzTGNPZd5vTW8UcjRupxfmEIdM06WSmAjwhvr-Ak_Pg9gJfHfrq2KvLH5eYL4C68BXM")
fmt.Println(err)
fmt.Println(data)
}

View File

@@ -1,19 +1,20 @@
package tiktok
import (
"errors"
"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
ErrorCode int64 `json:"error_code"` // 错误码
ExpiresIn uint64 `json:"expires_in"` // access_token接口调用凭证超时时间单位
OpenId string `json:"open_id"` // 授权用户唯一标识
RefreshExpiresIn int64 `json:"refresh_expires_in"` // refresh_token凭证超时时间单位)
RefreshToken string `json:"refresh_token"` // 用户刷新access_token
Scope string `json:"scope"` // 用户授权的作用域(Scope),使用逗号(,分隔开放平台几乎几乎每个接口都需要特定的Scope。
AccessToken string `json:"access_token"` // 接口调用凭证
Description string `json:"description"` // 错误码描述
}
// DYError 错误结构体
@@ -24,8 +25,21 @@ type DYError struct {
// OauthAccessTokenRes access_token
type OauthAccessTokenRes struct {
Data OauthAccessTokenResData `json:"data"`
Message string `json:"message"`
Data *OauthAccessTokenResData
Message string `json:"message"`
}
// 抖音登录返回值
type TiktokOauthResone struct {
ErrNo int64 `json:"err_no"`
ErrTips string `json:"err_tips"`
Data *struct {
SessionKey string `json:"session_key"`
OpenId string `json:"openid"` // 授权用户唯一标识
AnonymousOpenid string `json:"anonymous_openid"`
Unionid string `json:"unionid"`
Dopenid string `json:"dopenid"`
}
}
// 获取抖音token
@@ -35,7 +49,8 @@ func (a *API) GetTiktokToken(code string) (*OauthAccessTokenRes, error) {
tokenReq["code"] = code
tokenReq["grant_type"] = "authorization_code"
tokenReq["client_key"] = a.clientKey
result, err := a.AccessAPI(BaseURL, TiktokTokenUrl, http.MethodPost, tokenReq)
result, err := a.AccessAPI2(BaseURL, tokenReq)
if err != nil {
return nil, err
}
@@ -44,6 +59,28 @@ func (a *API) GetTiktokToken(code string) (*OauthAccessTokenRes, error) {
if err := utils.Map2StructByJson(result, oauthAccessToken, false); err != nil {
return nil, err
}
if oauthAccessToken.Data.ErrorCode != 0 {
return nil, errors.New(oauthAccessToken.Data.Description)
}
return oauthAccessToken, nil
}
// 获取抖音登录授权2
func (a *API) GetTiktokToken2(code string) (*TiktokOauthResone, error) {
tokenReq := make(map[string]interface{}, 3)
tokenReq["appid"] = a.GetAppID()
tokenReq["code"] = code
tokenReq["secret"] = a.GetSecret()
tokenReq["anonymous_code"] = ""
result, err := a.AccessAPI2("https://developer.toutiao.com"+"/"+"api/apps/v2/jscode2session", tokenReq)
if err != nil {
return nil, err
}
oauthAccessToken := &TiktokOauthResone{}
if err := utils.Map2StructByJson(result, oauthAccessToken, false); err != nil {
return nil, err
}
return oauthAccessToken, nil
}
@@ -69,7 +106,7 @@ func (a *API) RefreshToken(refreshToken string) (*OauthRefreshTokenRes, error) {
tokenReq["client_key"] = a.clientKey
tokenReq["refresh_token"] = refreshToken
// 通过旧的refresh_token获取新的refresh_token调用后旧refresh_token会失效新refresh_token有30天有效期。最多只能获取5次新的refresh_token5次过后需要用户重新授权。
result, err := a.AccessAPI(BaseURL, TiktokRefreshTokenUrl, http.MethodPost, tokenReq)
result, err := a.AccessAPI2(BaseURL, tokenReq)
if err != nil {
return nil, err
}

View File

@@ -8,12 +8,12 @@ import (
)
func TestQueryGoodsList(t *testing.T) {
result, totalCount, err := api.QueryGoodsList(1, 20, nil, nil)
if err != nil {
t.Fatal(err)
}
baseapi.SugarLogger.Debug(totalCount)
baseapi.SugarLogger.Debug(utils.Format4Output(result, false))
//result, totalCount, err := api.QueryGoodsList(1, 20, nil, nil)
//if err != nil {
// t.Fatal(err)
//}
//baseapi.SugarLogger.Debug(totalCount)
//baseapi.SugarLogger.Debug(utils.Format4Output(result, false))
}
func TestQueryGoodsDetail(t *testing.T) {

View File

@@ -49,7 +49,7 @@ func TestCBUpdateRemark(t *testing.T) {
}
func TestCBGetUserInfo(t *testing.T) {
userInfo, err := api.CBGetUserInfo("oUSjx58hW3ZeCcUfxW1HEHRnagiI")
userInfo, err := api.CBGetUserInfo("ox1y15LCS3ytipsTjEQ4_nXrRtkw")
if err != nil {
t.Fatal(err)
}