From ff5b116ce524c18178903da3fc31030ba31e70e4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=82=B9=E5=AE=97=E6=A5=A0?= Date: Fri, 13 May 2022 16:03:37 +0800 Subject: [PATCH] =?UTF-8?q?=E6=B7=BB=E5=8A=A0=E5=9B=BD=E7=BE=8Eapi,?= =?UTF-8?q?=E5=88=A0=E9=99=A4=E8=80=81=E7=89=88=E6=9C=AC=E8=9C=82=E9=B8=9F?= =?UTF-8?q?API=EF=BC=8C=E6=B7=BB=E5=8A=A0=E6=8A=96=E9=9F=B3=E6=8E=88?= =?UTF-8?q?=E6=9D=83api=E3=80=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- platformapi/dadaapi/order.go | 21 +- platformapi/fnpsapi/fn_test.go | 11 +- platformapi/fnpsapi/store.go | 24 +- platformapi/fnpsapi_v3/fnClient_test.go | 104 ---- platformapi/fnpsapi_v3/fnps_v3.go | 452 ------------------ platformapi/fnpsapi_v3/fnpsapi.go | 147 ------ platformapi/fnpsapi_v3/order.go | 266 ----------- platformapi/fnpsapi_v3/order_test.go | 68 --- platformapi/fnpsapi_v3/store.go | 73 --- .../callback.go | 2 +- platformapi/gome_live_show/goods.go | 195 ++++++++ platformapi/gome_live_show/goods_model.go | 136 ++++++ platformapi/gome_live_show/goods_test.go | 42 ++ .../gome_live_show/guomei_const_emu.go | 108 +++++ platformapi/gome_live_show/guomei_token.go | 158 ++++++ platformapi/gome_live_show/order.go | 167 +++++++ .../gome_live_show/order_after_sale.go | 141 ++++++ .../gome_live_show/order_after_sale_model.go | 68 +++ platformapi/gome_live_show/order_model.go | 203 ++++++++ platformapi/gome_live_show/order_test.go | 1 + platformapi/gome_live_show/store_category.go | 121 +++++ platformapi/gome_live_show/store_goods.go | 259 ++++++++++ platformapi/gome_live_show/store_model.go | 327 +++++++++++++ platformapi/gome_live_show/store_test.go | 192 ++++++++ platformapi/gome_live_show/system_model.go | 32 ++ platformapi/gome_live_show/token_model.go | 39 ++ platformapi/jdapi/store_page_test.go | 6 + platformapi/mtwmapi/mtwmapi_test.go | 4 +- platformapi/mtwmapi/retail_test.go | 2 +- platformapi/tiktok/tiktok.go | 53 +- platformapi/tiktok/tiktok_const.go | 7 +- platformapi/tiktok/tiktok_test.go | 33 ++ platformapi/tiktok/tiktok_token.go | 61 ++- platformapi/weimobapi/goods_test.go | 12 +- platformapi/weixinapi/cgibin_test.go | 2 +- 35 files changed, 2346 insertions(+), 1191 deletions(-) delete mode 100644 platformapi/fnpsapi_v3/fnClient_test.go delete mode 100644 platformapi/fnpsapi_v3/fnps_v3.go delete mode 100644 platformapi/fnpsapi_v3/fnpsapi.go delete mode 100644 platformapi/fnpsapi_v3/order.go delete mode 100644 platformapi/fnpsapi_v3/order_test.go delete mode 100644 platformapi/fnpsapi_v3/store.go rename platformapi/{fnpsapi_v3 => gome_live_show}/callback.go (98%) create mode 100644 platformapi/gome_live_show/goods.go create mode 100644 platformapi/gome_live_show/goods_model.go create mode 100644 platformapi/gome_live_show/goods_test.go create mode 100644 platformapi/gome_live_show/guomei_const_emu.go create mode 100644 platformapi/gome_live_show/guomei_token.go create mode 100644 platformapi/gome_live_show/order.go create mode 100644 platformapi/gome_live_show/order_after_sale.go create mode 100644 platformapi/gome_live_show/order_after_sale_model.go create mode 100644 platformapi/gome_live_show/order_model.go create mode 100644 platformapi/gome_live_show/order_test.go create mode 100644 platformapi/gome_live_show/store_category.go create mode 100644 platformapi/gome_live_show/store_goods.go create mode 100644 platformapi/gome_live_show/store_model.go create mode 100644 platformapi/gome_live_show/store_test.go create mode 100644 platformapi/gome_live_show/system_model.go create mode 100644 platformapi/gome_live_show/token_model.go create mode 100644 platformapi/tiktok/tiktok_test.go diff --git a/platformapi/dadaapi/order.go b/platformapi/dadaapi/order.go index b9a5c982..4ef53294 100644 --- a/platformapi/dadaapi/order.go +++ b/platformapi/dadaapi/order.go @@ -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 ( diff --git a/platformapi/fnpsapi/fn_test.go b/platformapi/fnpsapi/fn_test.go index fc772efb..5a87f050 100644 --- a/platformapi/fnpsapi/fn_test.go +++ b/platformapi/fnpsapi/fn_test.go @@ -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) +} diff --git a/platformapi/fnpsapi/store.go b/platformapi/fnpsapi/store.go index efa29d72..5710568f 100644 --- a/platformapi/fnpsapi/store.go +++ b/platformapi/fnpsapi/store.go @@ -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) { diff --git a/platformapi/fnpsapi_v3/fnClient_test.go b/platformapi/fnpsapi_v3/fnClient_test.go deleted file mode 100644 index dbee403e..00000000 --- a/platformapi/fnpsapi_v3/fnClient_test.go +++ /dev/null @@ -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) -} diff --git a/platformapi/fnpsapi_v3/fnps_v3.go b/platformapi/fnpsapi_v3/fnps_v3.go deleted file mode 100644 index c749e682..00000000 --- a/platformapi/fnpsapi_v3/fnps_v3.go +++ /dev/null @@ -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,运单生成成功1,20:骑手接单,80:骑手到店,2:配送中,3:已完成,4:已取消,5:配送异常 - CarrierDriverId string `json:"carrier_driver_id"` // 配送员id - CarrierDriverName string `json:"carrier_driver_name"` // 配送员姓名 - CarrierDriverPhone string `json:"carrier_driver_phone"` // 配送员电话 - EstimateArriveTime int64 `json:"estimate_arrive_time"` // 预计送达时间(毫秒) - OvertimeCompensationCostCent int64 `json:"overtime_compensation_cost_cent"` // 时效赔付 - IfCanAddTip int `json:"if_can_add_tip"` // 是否支持添加调度费 1可以,0不可以 - OrderTipAmountCent int64 `json:"order_tip_amount_cent"` // 订单当前小费总金额 分 - DeliveryFetchPhotos []interface{} `json:"delivery_fetch_photos"` // 骑手取货照片地址 - OrderTotalAmountCent int64 `json:"order_total_amount_cent"` // 原始配送费金额(分) - OrderActualAmountCent int64 `json:"order_actual_amount_cent"` // 订单实际配送支付总金额关注这个字段即可(分) - PriceDetail []*PriceOpenapiDetail `json:"price_detail"` // 配送费价格明细 - AbnormalCode string `json:"abnormal_code"` // 运单异常原因code - AbnormalDesc string `json:"abnormal_desc"` // 运单异常原因描述 - EventLogDetails []*OrderNodeInfo `json:"event_log_details"` // 运单事件节点信息 - ComplaintId int64 `json:"complaint_id"` // 投诉编号 - ComplaintReasonDesc string `json:"complaint_reason_desc"` // 投诉原因描述 - ComplaintStatus int `json:"complaint_status"` // 投诉状态 1待处理, 2成功,3失败 - ClaimId int64 `json:"claim_id"` // 索赔id - ClaimReasonDesc string `json:"claim_reason_desc"` // 索赔原因描述 - ClaimStatus int `json:"claim_status"` // 索赔状态 1待处理, 2成功,3失败 - Temperature string `json:"temperature"` // 骑手体温 - OrderDistance float64 `json:"order_distance"` // 配送距离(米) -} - -// 点单详情信息,订单结点信息 -type OrderNodeInfo struct { - OrderStatus int `json:"order_status"` // 订单状态 - OccurTime int64 `json:"occur_time"` // 时间结点 - CarrierDriverName string `json:"carrier_driver_name"` // 配送员姓名 - CarrierDriverPhone string `json:"carrier_driver_phone"` // 配送电话 -} - -// getKnightInfo 查询骑手信息接口,参数 GetOrderDetailReq -type GetKnightInfoRes struct { - CarrierDriverId string `json:"carrier_driver_id"` // 配送员id - CarrierDriverName string `json:"carrier_driver_name"` // 配送员姓名 - CarrierDriverPhone string `json:"carrier_driver_phone"` // 配送员电话 - CarrierDriverLongitude string `json:"carrier_driver_longitude"` // 骑手坐标 - CarrierDriverLatitude string `json:"carrier_driver_latitude"` // 骑手坐标 -} - -//#endregion - -//#region 加小费接口 - -//追加小费,订单小费总金额为每次累加 -//注:不是所有订单都支持加小费,受合同服务 & 接单运力 & 当时订单状态等多个因素影响。 订单详情接口有返回是否可加小费字段。 -//另:联调环境使用加小费接口 需先使用联调工具->订单状态回调:把订单状态改为1,否则订单状态会不支持加小费 -// 添加小费 -type AddTipRes struct { - OrderId string `json:"order_id"` // 订单号 订单号和外部订单号必填1个 - PartnerOrderCode string `json:"partner_order_code"` // 外部订单号 - AddTipAmountCent int64 `json:"add_tip_amount_cent"` // 小费金额分(必填) - ThirdIndexId int64 `json:"third_index_id"` // 本次加小费唯一标识 每个订单内 不可重复, 会用来做幂等,相同third_index_id的后续请求会被忽略 -} - -// 业务出参 "business_data": "{\"result\":true}" -//#endregion - -//#region 取消接口 - -// getCancelReasonList 获取可用取消原因列表接口 参数:GetOrderDetailReq - -// getCancelReasonListRes 取消接口返回值 -type GetCancelReasonListRes struct { - CancelReasonList []*struct { - OrderCancelCode int `json:"order_cancel_code"` // 取消原因code - OrderCancelDesc int `json:"order_cancel_desc"` // 取消原因描述 - } -} - -// preCancelOrder 预取消订单接口 -type PreCancelOrderReq struct { - GetOrderDetailReq - OrderCancelCode int64 `json:"order_cancel_code"` // 从可用取消原因列表接口返回结果选择(必填) -} - -// cancelOrder 正式取消订单接口 -type CancelOrderReq struct { - GetOrderDetailReq - OrderCancelCode int64 `json:"order_cancel_code"` // 从可用取消原因列表接口返回结果选择(必填) - ActualCancelCostCent int64 `json:"actual_cancel_cost_cent"` // 单位分 取消实际需扣金额,从预取消接口拿(非必填) - OrderCancelOtherReason string `json:"order_cancel_other_reason"` // 取消原因补充 20字以内(非必填) - OrderCancelRole int `json:"order_cancel_role"` // 1商户取消, 2 用户取消(必填) -} - -//#endregion - -//#region 投诉订单 - -// complaintOrder投诉订单 -type ComplaintOrderReq struct { - GetOrderDetailReq - OrderComplaintCode int `json:"order_complaint_code"` // 投诉编码 230:其他, 150:未保持餐品完整, 160:服务态度恶劣, 190:额外索取费用,170:诱导收货人或商户退单, 140:提前点击送达,210:虚假标记异常, 220:少餐错餐,200:虚假配送, 130:未进行配送(必填) - OrderComplaintDesc string `json:"order_complaint_desc"` // 投诉原因描述(否) -} - -// claimOrder 索赔订单 -type ClaimOrderRes struct { - GetOrderDetailReq - OrderClaimCode int `json:"order_claim_code"` // 索赔编码150: 未保持餐品完整,160: 服务态度恶劣, 170: 诱导收货人或商户退单,210:虚假标记异常, 130: 骑手接单后未完成配送,320:少餐错餐, 190:额外索取费用,140:提前点击送达, 200:骑手点击配送成功,实际未配送 - OrderClaimDesc string `json:"order_claim_desc"` // 投诉原因描述 - OrderClaimPriceCent int64 `json:"order_claim_price_cent"` // 索赔金额 分 - OrderClaimSku []*OrderClaimSkuDto `json:"order_claim_sku"` // 索赔明细 -} - -// 索赔明细 -type OrderClaimSkuDto struct { - ClaimSkuName string `json:"claim_sku_name"` // 索赔商品名称 - ClaimSkuGoodsCount string `json:"claim_sku_goods_count"` // 索赔商品数量 - ClaimSkuPriceCent string `json:"claim_sku_price_cent"` // 索赔商品实际单价 分 - ClaimSkuTotalPriceCent string `json:"claim_sku_total_price_cent"` // 索赔商品实际总价 分 -} - -//#endregion - -//#endregion diff --git a/platformapi/fnpsapi_v3/fnpsapi.go b/platformapi/fnpsapi_v3/fnpsapi.go deleted file mode 100644 index bf845aec..00000000 --- a/platformapi/fnpsapi_v3/fnpsapi.go +++ /dev/null @@ -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 -} diff --git a/platformapi/fnpsapi_v3/order.go b/platformapi/fnpsapi_v3/order.go deleted file mode 100644 index bdbf4595..00000000 --- a/platformapi/fnpsapi_v3/order.go +++ /dev/null @@ -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 -} diff --git a/platformapi/fnpsapi_v3/order_test.go b/platformapi/fnpsapi_v3/order_test.go deleted file mode 100644 index 2ab7f7ca..00000000 --- a/platformapi/fnpsapi_v3/order_test.go +++ /dev/null @@ -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) -} diff --git a/platformapi/fnpsapi_v3/store.go b/platformapi/fnpsapi_v3/store.go deleted file mode 100644 index 9055f952..00000000 --- a/platformapi/fnpsapi_v3/store.go +++ /dev/null @@ -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 -} diff --git a/platformapi/fnpsapi_v3/callback.go b/platformapi/gome_live_show/callback.go similarity index 98% rename from platformapi/fnpsapi_v3/callback.go rename to platformapi/gome_live_show/callback.go index 173887f4..84999431 100644 --- a/platformapi/fnpsapi_v3/callback.go +++ b/platformapi/gome_live_show/callback.go @@ -1,4 +1,4 @@ -package fnpsapi +package gome_live_show import ( "net/url" diff --git a/platformapi/gome_live_show/goods.go b/platformapi/gome_live_show/goods.go new file mode 100644 index 00000000..df2c8870 --- /dev/null +++ b/platformapi/gome_live_show/goods.go @@ -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 +} diff --git a/platformapi/gome_live_show/goods_model.go b/platformapi/gome_live_show/goods_model.go new file mode 100644 index 00000000..e9a07b64 --- /dev/null +++ b/platformapi/gome_live_show/goods_model.go @@ -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 diff --git a/platformapi/gome_live_show/goods_test.go b/platformapi/gome_live_show/goods_test.go new file mode 100644 index 00000000..afc46435 --- /dev/null +++ b/platformapi/gome_live_show/goods_test.go @@ -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) +} diff --git a/platformapi/gome_live_show/guomei_const_emu.go b/platformapi/gome_live_show/guomei_const_emu.go new file mode 100644 index 00000000..825eca2f --- /dev/null +++ b/platformapi/gome_live_show/guomei_const_emu.go @@ -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 +} diff --git a/platformapi/gome_live_show/guomei_token.go b/platformapi/gome_live_show/guomei_token.go new file mode 100644 index 00000000..20a587a0 --- /dev/null +++ b/platformapi/gome_live_show/guomei_token.go @@ -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 +} diff --git a/platformapi/gome_live_show/order.go b/platformapi/gome_live_show/order.go new file mode 100644 index 00000000..5c825e5b --- /dev/null +++ b/platformapi/gome_live_show/order.go @@ -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 +} diff --git a/platformapi/gome_live_show/order_after_sale.go b/platformapi/gome_live_show/order_after_sale.go new file mode 100644 index 00000000..0f9b58fd --- /dev/null +++ b/platformapi/gome_live_show/order_after_sale.go @@ -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 +} diff --git a/platformapi/gome_live_show/order_after_sale_model.go b/platformapi/gome_live_show/order_after_sale_model.go new file mode 100644 index 00000000..00e98fa7 --- /dev/null +++ b/platformapi/gome_live_show/order_after_sale_model.go @@ -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 diff --git a/platformapi/gome_live_show/order_model.go b/platformapi/gome_live_show/order_model.go new file mode 100644 index 00000000..86bc3d69 --- /dev/null +++ b/platformapi/gome_live_show/order_model.go @@ -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 diff --git a/platformapi/gome_live_show/order_test.go b/platformapi/gome_live_show/order_test.go new file mode 100644 index 00000000..e17dcaf8 --- /dev/null +++ b/platformapi/gome_live_show/order_test.go @@ -0,0 +1 @@ +package gome_live_show diff --git a/platformapi/gome_live_show/store_category.go b/platformapi/gome_live_show/store_category.go new file mode 100644 index 00000000..54110874 --- /dev/null +++ b/platformapi/gome_live_show/store_category.go @@ -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 +} diff --git a/platformapi/gome_live_show/store_goods.go b/platformapi/gome_live_show/store_goods.go new file mode 100644 index 00000000..d90c54e4 --- /dev/null +++ b/platformapi/gome_live_show/store_goods.go @@ -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 +} diff --git a/platformapi/gome_live_show/store_model.go b/platformapi/gome_live_show/store_model.go new file mode 100644 index 00000000..7cf6a931 --- /dev/null +++ b/platformapi/gome_live_show/store_model.go @@ -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"` // 商品主图[必填] 格式:png,jpeg大小:3 兆以下,宽高强制比例3:4 像素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 diff --git a/platformapi/gome_live_show/store_test.go b/platformapi/gome_live_show/store_test.go new file mode 100644 index 00000000..97bdf00e --- /dev/null +++ b/platformapi/gome_live_show/store_test.go @@ -0,0 +1,192 @@ +package gome_live_show + +import ( + "fmt" + "git.rosy.net.cn/baseapi" + "git.rosy.net.cn/baseapi/utils" + "go.uber.org/zap" + "testing" +) + +var ( + sugarLogger *zap.SugaredLogger +) + +func init() { + logger, _ := zap.NewDevelopment() + sugarLogger = logger.Sugar() + baseapi.Init(sugarLogger) +} + +func TestGuoMei(t *testing.T) { + appKey := "N0R033L2QQFR53" + secretKey := "686ffc3e31c24594838baed045563790" + + api := New(appKey, secretKey, "") + data, err := api.GetAccessToken() + fmt.Println(err) + fmt.Println(data) + +} + +// 查询门店列表 +func TestStoreList(t *testing.T) { + data, _ := api.QueryStoreList(&GetStoreListReq{ + StoreName: "京西", + }) + + for _, v := range data.Data.Records { + fmt.Println(v.StoreName) + fmt.Println(v.StoreCode) + } +} + +// 查询门店分类 +func TestQueryCategory(t *testing.T) { + data, _ := api.QueryStoreCategoryList(&QueryStoreGoodsCategoryListReq{ + Page: Page{ + PageSize: 50, + PageNumber: 1, + }, + StoreCode: "GMJ-MS-XOMRF-1J1", + }) + + for _, v := range data.Data.Records { + fmt.Println(v.CategoryCode) + fmt.Println(v.CategoryName) + fmt.Println(v.Rank) + } +} + +// 图片上传 +func TestUploadImg(t *testing.T) { + data := `data:image/png;base64,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` + //dataByte := []byte(data) + data1, err := api.UploadPicture(data, 1, "aaaa.png") + fmt.Println(data1) + fmt.Println(err) +} + +// 添加门店分类 +func TestNew(t *testing.T) { + data, err := api.AddStoreCategory(&StoreAddGoodsCategory{ + StoreCode: "GMJ-MS-XOMRF-1J1", + CategoryName: "新鲜海鲜", + Rank: 3, + }) + fmt.Println("err===", err) + fmt.Println("err===", data.Code) +} + +// 新增商户商品 +func TestAddGoods1(t *testing.T) { + api.CreateMerchantGoodsOnStore(&CreateGoodsListToStore{ + GoodsName: "小包菜", + MainPictureURL: "xxxxx.jpg", + Detail: "多汁的小包菜", + Cat3Code: "", + SpecProperty: nil, + SkuSaleList: nil, + GoodsType: "", + //OtherPictureURL: nil, + //VideoURL: "", + //SpecCode: "", + //SpecName: "", + //SpecValues: "", + //SpecValueCode: "", + //SpecValueName: "", + //Specification: "", + //MarketPrice: 0, + //ThirdSkuCode: "", + }) +} + +// 查询商户商品列表 +func TestQueryMerchGoodsList(t *testing.T) { + data, err := api.GetMerchantStoreGoodsList(&QueryStoreGoodsListReq{ + GoodsName: "", + Cat3Code: "", + Page: Page{}, + }) + fmt.Println("err===", err) + fmt.Println("err===", data) +} + +// 查询所有的品类 +func TestGetAllCategoryList(t *testing.T) { + data, _ := api.GetGoodsCategoryList() + t.Log(data.Data) + for _, v := range data.Data { + fmt.Println(v.CatCode) + fmt.Println(v.CatLevel) + fmt.Println(v.CatName) + if len(v.ChildCat) > 0 { + for _, d := range v.ChildCat { + fmt.Println(d.CatCode) + fmt.Println(d.CatLevel) + fmt.Println(d.CatName) + } + } + } +} + +// 商户商品创建1e0d98ad7b2e9b1ba5d7529a7e17fa9b9d65380a +func TestGoMeiMerStoreAddGoods(t *testing.T) { + // 获取商品三级目录 + data, _ := api.QueryGoodsSizeList(&QueryGoodsSpecSizeReq{ + Cat3Code: "", + SpecName: "", + Page: Page{ + PageNumber: PageNumber, + PageSize: PageSize, + }, + }) + t.Log(utils.Format4Output(data, false)) + + //api.CreateMerchantGoodsOnStore(&CreateGoodsListToStore{ + // GoodsName: "大白菜", + // MainPictureURL: "https://img", + // OtherPictureURL: nil, + // VideoURL: "", + // Detail: "这是一颗大白菜", + // Cat3Code: "", + // SpecProperty: nil, + // SkuSaleList: nil, + // GoodsType: "", + // SpecCode: "", + // SpecName: "", + // SpecValues: "", + // SpecValueCode: "", + // SpecValueName: "", + // Specification: "", + // MarketPrice: 0, + // ThirdSkuCode: "", + //}) +} + +// 门店商品创建 +func TestGoMeiStoreAddGoods(t *testing.T) { + api.CreateGoodsForStore(&CreateGoodsForStoreReq{ + StoreCode: "GMJ-MS-XOMRF-1J1", + SkuCode: "", + SalePrice: 2.5, + DeliverType: "", + DeliverTemplateCode: "", + }) +} + +// 获取门店商品列表 +func TestGetSkuList(t *testing.T) { + data, _ := api.GetMerchantStoreGoodsList(&QueryStoreGoodsListReq{ + GoodsName: "", + Cat3Code: "002023002", + Page: Page{}, + }) + t.Log(data.Data.Records) + +} + +// 获取商品详情 +func TestGetSkuDetail(t *testing.T) { + api.QueryMerchantStoreGoodsDetail("11") +} diff --git a/platformapi/gome_live_show/system_model.go b/platformapi/gome_live_show/system_model.go new file mode 100644 index 00000000..412881cd --- /dev/null +++ b/platformapi/gome_live_show/system_model.go @@ -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"` // 总页数 +} diff --git a/platformapi/gome_live_show/token_model.go b/platformapi/gome_live_show/token_model.go new file mode 100644 index 00000000..bd0ace55 --- /dev/null +++ b/platformapi/gome_live_show/token_model.go @@ -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 +} diff --git a/platformapi/jdapi/store_page_test.go b/platformapi/jdapi/store_page_test.go index e797e10d..42cfbb31 100644 --- a/platformapi/jdapi/store_page_test.go +++ b/platformapi/jdapi/store_page_test.go @@ -316,3 +316,9 @@ func TestQueryMemberTransListByCondition(t *testing.T) { } t.Log(utils.Format4Output(result, false)) } + +type GuoMei struct { + appKey string + timestamp string + sign string +} diff --git a/platformapi/mtwmapi/mtwmapi_test.go b/platformapi/mtwmapi/mtwmapi_test.go index 368a9b05..d1a4edf0 100644 --- a/platformapi/mtwmapi/mtwmapi_test.go +++ b/platformapi/mtwmapi/mtwmapi_test.go @@ -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; ` diff --git a/platformapi/mtwmapi/retail_test.go b/platformapi/mtwmapi/retail_test.go index 8e189de0..0d96d9e8 100644 --- a/platformapi/mtwmapi/retail_test.go +++ b/platformapi/mtwmapi/retail_test.go @@ -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) } diff --git a/platformapi/tiktok/tiktok.go b/platformapi/tiktok/tiktok.go index f0d10e75..13bf25b5 100644 --- a/platformapi/tiktok/tiktok.go +++ b/platformapi/tiktok/tiktok.go @@ -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 } diff --git a/platformapi/tiktok/tiktok_const.go b/platformapi/tiktok/tiktok_const.go index 1f1085e8..0970fd10 100644 --- a/platformapi/tiktok/tiktok_const.go +++ b/platformapi/tiktok/tiktok_const.go @@ -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 { diff --git a/platformapi/tiktok/tiktok_test.go b/platformapi/tiktok/tiktok_test.go new file mode 100644 index 00000000..1b2c368c --- /dev/null +++ b/platformapi/tiktok/tiktok_test.go @@ -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) +} diff --git a/platformapi/tiktok/tiktok_token.go b/platformapi/tiktok/tiktok_token.go index a576f2d1..cb2d9aed 100644 --- a/platformapi/tiktok/tiktok_token.go +++ b/platformapi/tiktok/tiktok_token.go @@ -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_token,5次过后需要用户重新授权。 - result, err := a.AccessAPI(BaseURL, TiktokRefreshTokenUrl, http.MethodPost, tokenReq) + result, err := a.AccessAPI2(BaseURL, tokenReq) if err != nil { return nil, err } diff --git a/platformapi/weimobapi/goods_test.go b/platformapi/weimobapi/goods_test.go index 440d1bd4..06b4d404 100644 --- a/platformapi/weimobapi/goods_test.go +++ b/platformapi/weimobapi/goods_test.go @@ -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) { diff --git a/platformapi/weixinapi/cgibin_test.go b/platformapi/weixinapi/cgibin_test.go index bc3df17e..2cb422a6 100644 --- a/platformapi/weixinapi/cgibin_test.go +++ b/platformapi/weixinapi/cgibin_test.go @@ -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) }