diff --git a/platformapi/mtpsapi/riderInfo.go b/platformapi/mtpsapi/riderInfo.go index 2ebaab96..e17129cb 100644 --- a/platformapi/mtpsapi/riderInfo.go +++ b/platformapi/mtpsapi/riderInfo.go @@ -9,11 +9,12 @@ const ( type RiderInfo struct { OrderId string `json:"order_id"` // 发单平台订单id(美团,京西,京,京东) - ThirdCarrierOrderId string `json:"third_carrier_order_id"` // 京西平台id + ThirdCarrierOrderId string `json:"third_carrier_order_id"` // 京西平台id(运单id) CourierName string `json:"courier_name"` // 骑手名称 CourierPhone string `json:"courier_phone"` // 骑手电话 LogisticsProviderCode string `json:"logistics_provider_code"` // 配送平台code 10001-顺丰, 10002-达达, 10003-闪送, 10004-蜂鸟, 10005 UU跑腿,10006 快跑者, 10007 极客快送,10008-点我达,10009 同达, 10010-生活半径,10011 邻趣,10012 趣送, 10013 快服务 10014 菜鸟新配盟 10015 商家自建配送 10016 风先生,10017-其他,10032-美团跑腿 LogisticsStatus int `json:"logistics_status"` // 配送状态 + LogisticsContext string `json:"logistics_context"` // 配送状态描述 Latitude string `json:"latitude"` // 骑手当前的纬度,美团使用的是高德坐标系。 Longitude string `json:"longitude"` // 骑手当前的经度,美团使用的是高德坐标系。 } diff --git a/platformapi/tiktok_shop/sdk-golang/api/logistics_indTrackPush/request/logistics_indTrackPush_reqeust.go b/platformapi/tiktok_shop/sdk-golang/api/logistics_indTrackPush/request/logistics_indTrackPush_reqeust.go new file mode 100644 index 00000000..2fd251ae --- /dev/null +++ b/platformapi/tiktok_shop/sdk-golang/api/logistics_indTrackPush/request/logistics_indTrackPush_reqeust.go @@ -0,0 +1,90 @@ +package logistics_indTrackPush_reqeust + +import ( + "encoding/json" + logistics_indTrackPush_response "git.rosy.net.cn/baseapi/platformapi/tiktok_shop/sdk-golang/api/logistics_indTrackPush/response" + doudian_sdk "git.rosy.net.cn/baseapi/platformapi/tiktok_shop/sdk-golang/core" +) + +type LogisticsIndTrackPushRequest struct { + doudian_sdk.BaseDoudianOpApiRequest + Param *LogisticsIndTrackPushParam +} + +// GetUrlPath 同步配送坐标,配送轨迹推送 +func (c *LogisticsIndTrackPushRequest) GetUrlPath() string { + return "/logistics/indTrackPush" +} + +func New() *LogisticsIndTrackPushRequest { + request := &LogisticsIndTrackPushRequest{ + Param: &LogisticsIndTrackPushParam{}, + } + request.SetConfig(doudian_sdk.GlobalConfig) + request.SetClient(doudian_sdk.DefaultDoudianOpApiClient) + return request + +} + +func (c *LogisticsIndTrackPushRequest) Execute(accessToken *doudian_sdk.AccessToken) (*logistics_indTrackPush_response.LogisticsIndTrackPushResponse, error) { + responseJson, err := c.GetClient().Request(c, accessToken) + if err != nil { + return nil, err + } + response := &logistics_indTrackPush_response.LogisticsIndTrackPushResponse{} + _ = json.Unmarshal([]byte(responseJson), response) + return response, nil + +} + +func (c *LogisticsIndTrackPushRequest) GetParamObject() interface{} { + return c.Param +} + +func (c *LogisticsIndTrackPushRequest) GetParams() *LogisticsIndTrackPushParam { + return c.Param +} + +type LogisticsIndTrackPushParam struct { + // 请求时间 + CurTime string `json:"cur_time"` + // 公司编码 + Company string `json:"company"` + // 轨迹信息 + TraceMsgs []TraceMsgList `json:"trace_msgs"` + // 未知 + AuthorityId string `json:"authority_id"` +} + +type TraceMsgList struct { + // 运单号 + TrackNo string `json:"track_no"` + // 轨迹列表 + Traces []TracesList `json:"traces"` +} + +type TracesList struct { + // 事件编码 + Opcode string `json:"opcode"` + // 时间操作时间 + OpTime string `json:"op_time"` + // 文案 + Content string `json:"content"` + // 骑手信息 + Rider ReiderInfo `json:"rider"` + // 三方运力公司,顺丰同城 sftc 闪送 shansong 达达 dada UU uupt 美团 meituan 蜂鸟 fengniao + ThirdPartyCompany string `json:"third_party_company"` + // 异常编码 + ExceptionCode string `json:"exception_code"` + // 异常原因 + ExceptionDesc string `json:"exception_desc"` + // 取消编码 + CancelCode string `json:"cancel_code"` + // 取消原因 + CancelDesc string `json:"cancel_desc"` +} + +type ReiderInfo struct { + Name string `json:"name"` // 骑手姓名 + Mobile string `json:"mobile"` // 骑手电话号码 +} diff --git a/platformapi/tiktok_shop/sdk-golang/api/logistics_indTrackPush/response/logistics_indTrackPush_response.go b/platformapi/tiktok_shop/sdk-golang/api/logistics_indTrackPush/response/logistics_indTrackPush_response.go new file mode 100644 index 00000000..4affc275 --- /dev/null +++ b/platformapi/tiktok_shop/sdk-golang/api/logistics_indTrackPush/response/logistics_indTrackPush_response.go @@ -0,0 +1,12 @@ +package logistics_indTrackPush_response + +import ( + doudian_sdk "git.rosy.net.cn/baseapi/platformapi/tiktok_shop/sdk-golang/core" +) + +type LogisticsIndTrackPushResponse struct { + doudian_sdk.BaseDoudianOpApiResponse + Data *LogisticsIndTrackPushData `json:"data"` +} +type LogisticsIndTrackPushData struct { +} diff --git a/platformapi/tiktok_shop/sdk-golang/api/logistics_indTrackRegister/request/logistics_indTrackRegister_reqeust.go b/platformapi/tiktok_shop/sdk-golang/api/logistics_indTrackRegister/request/logistics_indTrackRegister_reqeust.go new file mode 100644 index 00000000..543248ee --- /dev/null +++ b/platformapi/tiktok_shop/sdk-golang/api/logistics_indTrackRegister/request/logistics_indTrackRegister_reqeust.go @@ -0,0 +1,55 @@ +package logistics_indTrackRegister_reqeust + +import ( + "encoding/json" + logistics_indTrackRegister_response "git.rosy.net.cn/baseapi/platformapi/tiktok_shop/sdk-golang/api/logistics_indTrackRegister/response" + doudian_sdk "git.rosy.net.cn/baseapi/platformapi/tiktok_shop/sdk-golang/core" +) + +type LogisticsIndTrackRegisterRequest struct { + doudian_sdk.BaseDoudianOpApiRequest + Param *LogisticsIndTrackRegisterRequestParam +} + +// GetUrlPath 根据即时配单号和公司编码订阅轨迹,用于即时配服务商推送轨迹 +func (c *LogisticsIndTrackRegisterRequest) GetUrlPath() string { + return "/logistics/ind/track/register" +} + +func New() *LogisticsIndTrackRegisterRequest { + request := &LogisticsIndTrackRegisterRequest{ + Param: &LogisticsIndTrackRegisterRequestParam{}, + } + request.SetConfig(doudian_sdk.GlobalConfig) + request.SetClient(doudian_sdk.DefaultDoudianOpApiClient) + return request + +} + +func (c *LogisticsIndTrackRegisterRequest) Execute(accessToken *doudian_sdk.AccessToken) (*logistics_indTrackRegister_response.LogisticsIndTrackRegisterRequestResponse, error) { + responseJson, err := c.GetClient().Request(c, accessToken) + if err != nil { + return nil, err + } + response := &logistics_indTrackRegister_response.LogisticsIndTrackRegisterRequestResponse{} + _ = json.Unmarshal([]byte(responseJson), response) + return response, nil + +} + +func (c *LogisticsIndTrackRegisterRequest) GetParamObject() interface{} { + return c.Param +} + +func (c *LogisticsIndTrackRegisterRequest) GetParams() *LogisticsIndTrackRegisterRequestParam { + return c.Param +} + +type LogisticsIndTrackRegisterRequestParam struct { + // 运单号 + TrackNo string `json:"track_no"` + // 回调地址 + CallbackUrl string `json:"callback_url"` + // 物流商编码 + Company string `json:"company"` +} diff --git a/platformapi/tiktok_shop/sdk-golang/api/logistics_indTrackRegister/response/logistics_indTrackRegister_response.go b/platformapi/tiktok_shop/sdk-golang/api/logistics_indTrackRegister/response/logistics_indTrackRegister_response.go new file mode 100644 index 00000000..a7f87ce2 --- /dev/null +++ b/platformapi/tiktok_shop/sdk-golang/api/logistics_indTrackRegister/response/logistics_indTrackRegister_response.go @@ -0,0 +1,16 @@ +package logistics_indTrackRegister_response + +import ( + doudian_sdk "git.rosy.net.cn/baseapi/platformapi/tiktok_shop/sdk-golang/core" +) + +type LogisticsIndTrackRegisterRequestResponse struct { + doudian_sdk.BaseDoudianOpApiResponse + Data *LogisticsIndTrackRegisterRequestData `json:"data"` +} + +type LogisticsIndTrackRegisterRequestData struct { + Result bool `json:"result"` // 请求结果 + ReturnCode string `json:"return_code"` // 响应码 + Message string `json:"message"` // 错误消息 +} diff --git a/platformapi/tiktok_shop/sdk-golang/api/token_create/request/token_create_request.go b/platformapi/tiktok_shop/sdk-golang/api/token_create/request/token_create_request.go index e6e9fcb6..fb53dd73 100644 --- a/platformapi/tiktok_shop/sdk-golang/api/token_create/request/token_create_request.go +++ b/platformapi/tiktok_shop/sdk-golang/api/token_create/request/token_create_request.go @@ -2,6 +2,8 @@ package token_create_request import ( "encoding/json" + token_create_response "git.rosy.net.cn/baseapi/platformapi/tiktok_shop/sdk-golang/api/token_create/response" + doudian_sdk "git.rosy.net.cn/baseapi/platformapi/tiktok_shop/sdk-golang/core" ) type TokenCreateRequest struct { diff --git a/platformapi/tiktok_shop/sdk-golang/api/token_create/response/token_create_response.go b/platformapi/tiktok_shop/sdk-golang/api/token_create/response/token_create_response.go index 707ef8be..d7c5d377 100644 --- a/platformapi/tiktok_shop/sdk-golang/api/token_create/response/token_create_response.go +++ b/platformapi/tiktok_shop/sdk-golang/api/token_create/response/token_create_response.go @@ -1,5 +1,7 @@ package token_create_response +import doudian_sdk "git.rosy.net.cn/baseapi/platformapi/tiktok_shop/sdk-golang/core" + type TokenCreateResponse struct { doudian_sdk.BaseDoudianOpApiResponse Data *TokenCreateData `json:"data"` diff --git a/platformapi/tiktok_shop/sdk-golang/core/access_token_builder.go b/platformapi/tiktok_shop/sdk-golang/core/access_token_builder.go index 3efafbac..f68b8cd9 100644 --- a/platformapi/tiktok_shop/sdk-golang/core/access_token_builder.go +++ b/platformapi/tiktok_shop/sdk-golang/core/access_token_builder.go @@ -15,9 +15,12 @@ func (at *AccessToken) IsSuccess() bool { } type BuildAccessTokenParam struct { - Code string - ShopId int64 - Config *DoudianOpConfig + Code string + ShopId int64 + TestShop string `json:"test_shop"` + AuthId string `json:"auth_id"` + AuthSubjectType string `json:"auth_subject_type"` + Config *DoudianOpConfig } type RefreshAccessTokenParam struct { diff --git a/platformapi/tiktok_shop/tiktok_api/api_test.go b/platformapi/tiktok_shop/tiktok_api/api_test.go index 7d92939b..1f437bb3 100644 --- a/platformapi/tiktok_shop/tiktok_api/api_test.go +++ b/platformapi/tiktok_shop/tiktok_api/api_test.go @@ -2,6 +2,7 @@ package tiktok_api import ( "fmt" + order_logisticsAdd_request "git.rosy.net.cn/baseapi/platformapi/tiktok_shop/sdk-golang/api/order_logisticsAdd/request" "git.rosy.net.cn/baseapi/utils" "git.rosy.net.cn/jx-callback/globals" "testing" @@ -37,3 +38,26 @@ func TestTimeNow(t *testing.T) { h, m, s := time.Now().Clock() fmt.Println(h, m, s) } + +func TestSendGoods(t *testing.T) { + token := `{"access_token":"a1746210-a8a3-4497-a87b-09d1f10dbb95","expires_in":1665652230,"scope":"SCOPE","shop_id":"","shop_name":"小时达开放平台对接专用店","refresh_token":"c1cf8d88-0983-4f2a-b969-3746fae6b0cd","authority_id":""}` + a := New("7136048270014416392", "c397aa9f-3927-47c4-8cfe-4d84e02602e0", token) + param := &order_logisticsAdd_request.OrderLogisticsAddParam{ + OrderId: "7136048270014416392", + Company: "", + CompanyCode: "chengdouruoxi", + LogisticsCode: "7136048270014416392111", + IsRefundReject: false, + IsRejectRefund: false, + SerialNumberList: nil, + AddressId: 0, + StoreId: 63114504, + } + a.OrderDelivering(param) +} + +// 创建物流token +func TestCreateExpss(t *testing.T) { + a := NewExpress("7152420904331429407", "cc7ba367-2394-4cbb-81c6-26f0e929d1c6", "") + a.CreateToken() +} diff --git a/platformapi/tiktok_shop/tiktok_api/logistics_express.go b/platformapi/tiktok_shop/tiktok_api/logistics_express.go new file mode 100644 index 00000000..f019d119 --- /dev/null +++ b/platformapi/tiktok_shop/tiktok_api/logistics_express.go @@ -0,0 +1,160 @@ +package tiktok_api + +import ( + "encoding/json" + "errors" + logistics_indTrackPush_reqeust "git.rosy.net.cn/baseapi/platformapi/tiktok_shop/sdk-golang/api/logistics_indTrackPush/request" + token_create_request "git.rosy.net.cn/baseapi/platformapi/tiktok_shop/sdk-golang/api/token_create/request" + token_create_response "git.rosy.net.cn/baseapi/platformapi/tiktok_shop/sdk-golang/api/token_create/response" + doudian_sdk "git.rosy.net.cn/baseapi/platformapi/tiktok_shop/sdk-golang/core" + "git.rosy.net.cn/baseapi/utils" + "git.rosy.net.cn/jx-callback/globals" + "sync" + "time" +) + +type APIExpress struct { + appKey string + appSecret string + accessToken string + refreshToken string + expiresIn int64 // 当前时间的七天内为有效期 + locker sync.RWMutex + accessTokenObj *doudian_sdk.AccessToken // 存储数据库 +} + +func NewExpress(appKey, appSecret, accessToken string) *APIExpress { + var access *doudian_sdk.AccessToken + doudian_sdk.GlobalConfig.AppKey = appKey + doudian_sdk.GlobalConfig.AppSecret = appSecret + if accessToken != "" { + if err := json.Unmarshal([]byte(accessToken), &access); err != nil { + globals.SugarLogger.Debug("accessToken init err :", err) + return nil + } + + api := &APIExpress{ + appKey: appKey, + appSecret: appSecret, + accessToken: access.AccessToken, + refreshToken: access.RefreshToken, + expiresIn: access.ExpiresIn, + accessTokenObj: access, + } + if access.ExpiresIn < time.Now().Unix() { + api.RefreshToken() + } + return api + } + return &APIExpress{ + appKey: appKey, + appSecret: appSecret, + } +} + +// CreateToken 创建token只有第一次授权或者更新授权才需要,其他时候直接刷新就可以啦 +func (a *APIExpress) CreateToken() (*token_create_response.TokenCreateData, error) { + request := token_create_request.New() + param := request.GetParams() + param.Code = "" + param.GrantType = "authorization_self" + param.AuthId = "powertestexpress" + param.AuthSubjectType = "WuLiuShang" + response, err := request.Execute(nil) + if err != nil { + return nil, err + } + if response.Code != RequestSuccessCode { + return nil, errors.New(response.SubMsg) + } + + a.accessTokenObj.CreateTokenData = doudian_sdk.CreateTokenData{ + AccessToken: response.Data.AccessToken, + ExpiresIn: time.Now().Unix() + response.Data.ExpiresIn, + Scope: response.Data.Scope, + ShopId: utils.Int64ToStr(response.Data.ShopId), + ShopName: response.Data.ShopName, + RefreshToken: response.Data.RefreshToken, + AuthorityId: response.Data.AuthorityId, + } + + return response.Data, nil +} + +// RefreshToken 刷新token +func (a *APIExpress) RefreshToken() (*doudian_sdk.CreateTokenData, error) { + doudian_sdk.GlobalConfig.AppKey = a.appKey + doudian_sdk.GlobalConfig.AppSecret = a.appSecret + refresh := doudian_sdk.NewRefreshTokenRequest() + refresh.GetParam().RefreshToken = a.refreshToken + refresh.GetParam().GrantType = "refresh_token" + + createToken, err := refresh.Execute(a.accessTokenObj) + if err != nil { + return nil, err + } + if createToken.Code != RequestSuccessCode { + return nil, errors.New(createToken.SubMsg) + } + a.accessToken = createToken.Data.AccessToken + a.refreshToken = createToken.Data.RefreshToken + a.expiresIn = time.Now().Unix() + createToken.Data.ExpiresIn + globals.SugarLogger.Debug("===============data", createToken.Data) + + // 不要 + createToken.Data.ExpiresIn = a.expiresIn + strData, _ := json.Marshal(createToken.Data) + a.accessTokenObj.CreateTokenData = createToken.Data + globals.SugarLogger.Debug("=========", string(strData)) + return &createToken.Data, nil +} + +// OrderStatusAndPsInfo 三方配送同步骑手位置信息 +// 抖音物流信息和抖音小时达完全区分开(这边的appKey和APPSecret完全不同于小时达) +func (a *APIExpress) OrderStatusAndPsInfo(param map[string]interface{}) error { + // 组合参数 + request := logistics_indTrackPush_reqeust.New() + psInfo := &logistics_indTrackPush_reqeust.LogisticsIndTrackPushParam{ + CurTime: utils.Time2Str(time.Now()), + Company: TiktokExpressCode, + TraceMsgs: nil, + AuthorityId: "", + } + traceMsgs := make([]logistics_indTrackPush_reqeust.TraceMsgList, 0, 1) + traceMsg := logistics_indTrackPush_reqeust.TraceMsgList{ + TrackNo: param["third_carrier_order_id"].(string), + Traces: []logistics_indTrackPush_reqeust.TracesList{ + { + Opcode: "ORDER_RECEIVED", + OpTime: utils.Time2TimeStr(time.Now()), + Content: param["logistics_context"].(string), + Rider: logistics_indTrackPush_reqeust.ReiderInfo{ + Name: param["courier_name"].(string), + Mobile: param["courier_phone"].(string), + }, + ThirdPartyCompany: TiktokExpressCode, + ExceptionCode: "", + ExceptionDesc: "", + CancelCode: "", + CancelDesc: "", + }, + }, + } + traceMsgs = append(traceMsgs, traceMsg) + psInfo.TraceMsgs = traceMsgs + request.Param = psInfo + + if a.accessTokenObj == nil || a.accessTokenObj.CreateTokenData.AccessToken == "" { + a.CreateToken() + } else if a.accessTokenObj.CreateTokenData.ExpiresIn < time.Now().Unix() { + a.RefreshToken() + } + result, err := request.Execute(a.accessTokenObj) + if err != nil { + return err + } + if result.Code != RequestSuccessCode { + return errors.New(result.SubMsg) + } + return nil +} diff --git a/platformapi/tiktok_shop/tiktok_api/order.go b/platformapi/tiktok_shop/tiktok_api/order.go index 9182af61..0a4ae7af 100644 --- a/platformapi/tiktok_shop/tiktok_api/order.go +++ b/platformapi/tiktok_shop/tiktok_api/order.go @@ -595,7 +595,17 @@ func (a *API) GetCallbackOrderId(msgId string, data interface{}) (string, *Callb return "", &CallbackResponse{Code: CallbackSuccessCode, Msg: CallbackSuccess} } -// OrderStatusAndPsInfo 三方配送同步骑手位置信息 -func (a *API) OrderStatusAndPsInfo(param map[string]interface{}) error { +// OrderDelivering 订单发货 +func (a *API) OrderDelivering(param *order_logisticsAdd_request.OrderLogisticsAddParam) error { + request := order_logisticsAdd_request.New() + request.Param = param + + result, err := request.Execute(a.accessTokenObj) + if err != nil { + return err + } + if result.Code != RequestSuccessCode { + return errors.New(result.SubMsg) + } return nil } diff --git a/platformapi/tiktok_shop/tiktok_api/order_type_const.go b/platformapi/tiktok_shop/tiktok_api/order_type_const.go index ad527dc7..e07bc78c 100644 --- a/platformapi/tiktok_shop/tiktok_api/order_type_const.go +++ b/platformapi/tiktok_shop/tiktok_api/order_type_const.go @@ -1,6 +1,7 @@ package tiktok_api const RequestSuccessCode = 10000 +const TiktokExpressCode = "chengduruoxi" // 订单消息回调类型(正向订单) const (