diff --git a/api/admin.wechat.offiaccount.api b/api/admin.wechat.offiaccount.api index a27f05f8..7970b202 100644 --- a/api/admin.wechat.offiaccount.api +++ b/api/admin.wechat.offiaccount.api @@ -1,21 +1,2 @@ -import "admin/scrm/contactway.api" -//import "admin/scrm/customer.api" -//import "admin/scrm/contact.api" -// organzation -import "admin/scrm/organization/weworkemployee.api" -import "admin/scrm/organization/weworkdepartment.api" -// app -import "admin/scrm/app/weworkgroup.api" -import "admin/scrm/app/weworkapp.api" -import "admin/scrm/app/weworkappmessage.api" -// wechat.customer -import "admin/scrm/customer/weworkcustomer.api" -import "admin/scrm/customer/weworkcustomergroup.api" -// bot -import "admin/scrm/bot/weworkbot.api" -// resource -import "admin/scrm/resource/weworkresource.api" -// qrcode -import "admin/scrm/qrcode/weworkcustomergroupqrcode.api" -// tag -import "admin/scrm/tag/weworktag.api" +import "admin/wechat/officialaccount/menu.api" + diff --git a/api/admin/wechat/officialaccount/menu.api b/api/admin/wechat/officialaccount/menu.api index f3601840..426d1324 100644 --- a/api/admin/wechat/officialaccount/menu.api +++ b/api/admin/wechat/officialaccount/menu.api @@ -21,7 +21,7 @@ service PowerX { @doc "请求菜单上传链接" @handler SyncMenus - post /menus (SyncMenusRequest) returns (SyncMenusReply) + post /menus/sync (SyncMenusRequest) returns (SyncMenusReply) @doc "创建菜单" @@ -34,18 +34,25 @@ service PowerX { } type ( - SubButton struct { + OASubButton struct { Name string `json:"name,optional"` Id int `json:"id,optional"` Type string `json:"type,optional"` Key string `json:"key,omitempty,optional"` Url string `json:"url,omitempty,optional"` + AppID string `json:"appid,omitempty,optional"` + PagePath string `json:"pagepath,omitempty,optional"` } - Button struct { + OAButton struct { Name string `json:"name,optional"` - SubButton []*SubButton `json:"sub_button,optional"` + Type string `json:"type,optional"` + Key string `json:"key,omitempty,optional"` + Url string `json:"url,omitempty,optional"` + AppID string `json:"appid,omitempty,optional"` + PagePath string `json:"pagepath,omitempty,optional"` + OASubButton []*OASubButton `json:"sub_button,optional"` Id int `json:"id,optional"` } @@ -57,56 +64,46 @@ type ( City string `json:"city,optional"` Language string `json:"language,optional"` } - Menu struct { + OAMenu struct { Id int64 `json:"id,optional"` - Button []*Button `json:"button,optional"` + OAButton []*OAButton `json:"button,optional"` MatchRule *MatchRule `json:"matchrule,optional"` } ) type ( SyncMenusRequest struct { - Menu + OAMenu } SyncMenusReply struct { - success bool `json:"success,optional"` + Success bool `json:"success,optional"` + Data interface{} `json:"data"` } ) type ( CreateMenuRequest struct { - Menu + OAMenu } CreateMenuReply struct { - success bool `json:"success,optional"` + Success bool `json:"success,optional"` + Data interface{} `json:"data"` } ) type ( - QunerySubButton struct { - QueryList []SubButton `json:"list,optional"` - } - QueryButton struct { - Name string `json:"name,optional"` - SubButton []*QunerySubButton `json:"sub_button,optional"` - Id int `json:"id,optional"` - } - - SelfMenuInfo struct { - Button *QueryButton `json:"button,optional"` - } QueryMenusReply struct { - IsMenuOpen int64 `json:"is_menu_open,optional"` - SelfMenuInfo SelfMenuInfo `json:"selfmenu_info,optional"` + Menu *OAMenu `json:"menu,optional"` } ) type ( DeleteMenuReply struct { - success bool `json:"success"` + Success bool `json:"success"` + Data interface{} `json:"data"` } ) \ No newline at end of file diff --git a/go.mod b/go.mod index 6bab4646..38f01d3e 100644 --- a/go.mod +++ b/go.mod @@ -3,9 +3,9 @@ module PowerX go 1.21 require ( - github.com/ArtisanCloud/PowerLibs/v3 v3.0.13 - github.com/ArtisanCloud/PowerSocialite/v3 v3.0.6 - github.com/ArtisanCloud/PowerWeChat/v3 v3.0.63 + github.com/ArtisanCloud/PowerLibs/v3 v3.0.15 + github.com/ArtisanCloud/PowerSocialite/v3 v3.0.7 + github.com/ArtisanCloud/PowerWeChat/v3 v3.1.4 github.com/Blank-Xu/sql-adapter v0.0.0-20210714092925-0bdd0d548758 github.com/brianvoe/gofakeit/v6 v6.21.0 github.com/casbin/casbin/v2 v2.60.0 @@ -33,6 +33,7 @@ require ( github.com/beorn7/perks v1.0.1 // indirect github.com/cenkalti/backoff/v4 v4.1.3 // indirect github.com/cespare/xxhash/v2 v2.2.0 // indirect + github.com/clbanning/mxj/v2 v2.7.0 // indirect github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d // indirect github.com/davecgh/go-spew v1.1.1 // indirect github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f // indirect diff --git a/go.sum b/go.sum index 50bb2e17..1fab6224 100644 --- a/go.sum +++ b/go.sum @@ -360,12 +360,12 @@ cloud.google.com/go/workflows v1.7.0/go.mod h1:JhSrZuVZWuiDfKEFxU0/F1PQjmpnpcoIS cloud.google.com/go/workflows v1.8.0/go.mod h1:ysGhmEajwZxGn1OhGOGKsTXc5PyxOc0vfKf5Af+to4M= cloud.google.com/go/workflows v1.9.0/go.mod h1:ZGkj1aFIOd9c8Gerkjjq7OW7I5+l6cSvT3ujaO/WwSA= dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU= -github.com/ArtisanCloud/PowerLibs/v3 v3.0.13 h1:UmqOicYa+H0o36a92Dy/0fPfa9TH4z8V1nI4rDutzFw= -github.com/ArtisanCloud/PowerLibs/v3 v3.0.13/go.mod h1:51qXJs/QnkmUMfdAwq+TExLQVPwSJCQ95ewSiQ2dShU= -github.com/ArtisanCloud/PowerSocialite/v3 v3.0.6 h1:6Bd1B8XVezYo5ned7hhqESHLm8awsfVfyCsGMNscw7c= -github.com/ArtisanCloud/PowerSocialite/v3 v3.0.6/go.mod h1:VZQNCvcK/rldF3QaExiSl1gJEAkyc5/I8RLOd3WFZq4= -github.com/ArtisanCloud/PowerWeChat/v3 v3.0.63 h1:wjcGW3PXkPlrYTXFKrgtilZ7x6Jzu9Pc8Tx+afHR91o= -github.com/ArtisanCloud/PowerWeChat/v3 v3.0.63/go.mod h1:VDwos4k1onP+wPJvD0K5FVSuTEgI9n+Wi0096PFXJrs= +github.com/ArtisanCloud/PowerLibs/v3 v3.0.15 h1:EKWDvgu3y6S7OjT3ku7LEF6l5KpIKygBVVnbn2d+lns= +github.com/ArtisanCloud/PowerLibs/v3 v3.0.15/go.mod h1:KBO7ZQGTBjvYTveKY5M4QQpwxuoGBI0V2fZ4xP+TIuM= +github.com/ArtisanCloud/PowerSocialite/v3 v3.0.7 h1:P+erNlErr+X2v7Et+yTWaTfIRhw+HfpAPdvNIEwk9Gw= +github.com/ArtisanCloud/PowerSocialite/v3 v3.0.7/go.mod h1:VZQNCvcK/rldF3QaExiSl1gJEAkyc5/I8RLOd3WFZq4= +github.com/ArtisanCloud/PowerWeChat/v3 v3.1.4 h1:2xrbaBcNvnEUjq5IC0T5j+Q+9HFM8ub6KtBNeVbgVP0= +github.com/ArtisanCloud/PowerWeChat/v3 v3.1.4/go.mod h1:N6ATGWtdjvnts0dzbe9AYxQ1aRuA1yuTTabcUTQPFZo= github.com/Azure/go-autorest v14.2.0+incompatible/go.mod h1:r+4oMnoxhatjLLJ6zxSWATqVooLgysK6ZNox3g/xq24= github.com/Azure/go-autorest/autorest v0.11.18/go.mod h1:dSiJPy22c3u0OtOKDNttNgqpNFY/GeWa7GH/Pz56QRA= github.com/Azure/go-autorest/autorest/adal v0.9.13/go.mod h1:W/MM4U6nLxnIskrw4UwWzlHfGjwUS50aOsc/I3yuU8M= @@ -428,6 +428,8 @@ github.com/cespare/xxhash/v2 v2.2.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XL github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI= github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI= github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU= +github.com/clbanning/mxj/v2 v2.7.0 h1:WA/La7UGCanFe5NpHF0Q3DNtnCsVoxbPKuyBNHWRyME= +github.com/clbanning/mxj/v2 v2.7.0/go.mod h1:hNiWqW14h+kc+MdF9C6/YoRfjEJoR3ou6tn/Qo+ve2s= github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= github.com/cloudflare/golz4 v0.0.0-20150217214814-ef862a3cdc58/go.mod h1:EOBUe0h4xcZ5GoxqC5SDxFQ8gwyZPKQoEzownBlhI80= github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc= diff --git a/internal/handler/admin/wechat/officialaccount/menu/createmenuhandler.go b/internal/handler/admin/wechat/officialaccount/menu/createmenuhandler.go new file mode 100644 index 00000000..bfdc9e89 --- /dev/null +++ b/internal/handler/admin/wechat/officialaccount/menu/createmenuhandler.go @@ -0,0 +1,28 @@ +package menu + +import ( + "net/http" + + "PowerX/internal/logic/admin/wechat/officialaccount/menu" + "PowerX/internal/svc" + "PowerX/internal/types" + "github.com/zeromicro/go-zero/rest/httpx" +) + +func CreateMenuHandler(svcCtx *svc.ServiceContext) http.HandlerFunc { + return func(w http.ResponseWriter, r *http.Request) { + var req types.CreateMenuRequest + if err := httpx.Parse(r, &req); err != nil { + httpx.ErrorCtx(r.Context(), w, err) + return + } + + l := menu.NewCreateMenuLogic(r.Context(), svcCtx) + resp, err := l.CreateMenu(&req) + if err != nil { + httpx.ErrorCtx(r.Context(), w, err) + } else { + httpx.OkJsonCtx(r.Context(), w, resp) + } + } +} diff --git a/internal/handler/admin/wechat/officialaccount/menu/deletemenuhandler.go b/internal/handler/admin/wechat/officialaccount/menu/deletemenuhandler.go new file mode 100644 index 00000000..995ca940 --- /dev/null +++ b/internal/handler/admin/wechat/officialaccount/menu/deletemenuhandler.go @@ -0,0 +1,21 @@ +package menu + +import ( + "net/http" + + "PowerX/internal/logic/admin/wechat/officialaccount/menu" + "PowerX/internal/svc" + "github.com/zeromicro/go-zero/rest/httpx" +) + +func DeleteMenuHandler(svcCtx *svc.ServiceContext) http.HandlerFunc { + return func(w http.ResponseWriter, r *http.Request) { + l := menu.NewDeleteMenuLogic(r.Context(), svcCtx) + resp, err := l.DeleteMenu() + if err != nil { + httpx.ErrorCtx(r.Context(), w, err) + } else { + httpx.OkJsonCtx(r.Context(), w, resp) + } + } +} diff --git a/internal/handler/admin/wechat/officialaccount/menu/querymenushandler.go b/internal/handler/admin/wechat/officialaccount/menu/querymenushandler.go new file mode 100644 index 00000000..b001385e --- /dev/null +++ b/internal/handler/admin/wechat/officialaccount/menu/querymenushandler.go @@ -0,0 +1,21 @@ +package menu + +import ( + "net/http" + + "PowerX/internal/logic/admin/wechat/officialaccount/menu" + "PowerX/internal/svc" + "github.com/zeromicro/go-zero/rest/httpx" +) + +func QueryMenusHandler(svcCtx *svc.ServiceContext) http.HandlerFunc { + return func(w http.ResponseWriter, r *http.Request) { + l := menu.NewQueryMenusLogic(r.Context(), svcCtx) + resp, err := l.QueryMenus() + if err != nil { + httpx.ErrorCtx(r.Context(), w, err) + } else { + httpx.OkJsonCtx(r.Context(), w, resp) + } + } +} diff --git a/internal/handler/admin/wechat/officialaccount/menu/syncmenushandler.go b/internal/handler/admin/wechat/officialaccount/menu/syncmenushandler.go new file mode 100644 index 00000000..61016d95 --- /dev/null +++ b/internal/handler/admin/wechat/officialaccount/menu/syncmenushandler.go @@ -0,0 +1,28 @@ +package menu + +import ( + "net/http" + + "PowerX/internal/logic/admin/wechat/officialaccount/menu" + "PowerX/internal/svc" + "PowerX/internal/types" + "github.com/zeromicro/go-zero/rest/httpx" +) + +func SyncMenusHandler(svcCtx *svc.ServiceContext) http.HandlerFunc { + return func(w http.ResponseWriter, r *http.Request) { + var req types.SyncMenusRequest + if err := httpx.Parse(r, &req); err != nil { + httpx.ErrorCtx(r.Context(), w, err) + return + } + + l := menu.NewSyncMenusLogic(r.Context(), svcCtx) + resp, err := l.SyncMenus(&req) + if err != nil { + httpx.ErrorCtx(r.Context(), w, err) + } else { + httpx.OkJsonCtx(r.Context(), w, resp) + } + } +} diff --git a/internal/handler/routes.go b/internal/handler/routes.go index 29be045a..35b4b76e 100644 --- a/internal/handler/routes.go +++ b/internal/handler/routes.go @@ -42,6 +42,7 @@ import ( adminscrmtag "PowerX/internal/handler/admin/scrm/tag" admintag "PowerX/internal/handler/admin/tag" adminuserinfo "PowerX/internal/handler/admin/userinfo" + adminwechatofficialaccountmenu "PowerX/internal/handler/admin/wechat/officialaccount/menu" mpcustomerauth "PowerX/internal/handler/mp/customer/auth" mpdictionary "PowerX/internal/handler/mp/dictionary" mpmarketmedia "PowerX/internal/handler/mp/market/media" @@ -1451,6 +1452,35 @@ func RegisterHandlers(server *rest.Server, serverCtx *svc.ServiceContext) { rest.WithPrefix("/api/v1/admin/scrm/tag/wechat"), ) + server.AddRoutes( + rest.WithMiddlewares( + []rest.Middleware{serverCtx.EmployeeJWTAuth}, + []rest.Route{ + { + Method: http.MethodGet, + Path: "/menus-tree", + Handler: adminwechatofficialaccountmenu.QueryMenusHandler(serverCtx), + }, + { + Method: http.MethodPost, + Path: "/menus/sync", + Handler: adminwechatofficialaccountmenu.SyncMenusHandler(serverCtx), + }, + { + Method: http.MethodPost, + Path: "/menus", + Handler: adminwechatofficialaccountmenu.CreateMenuHandler(serverCtx), + }, + { + Method: http.MethodDelete, + Path: "/menus", + Handler: adminwechatofficialaccountmenu.DeleteMenuHandler(serverCtx), + }, + }..., + ), + rest.WithPrefix("/api/v1/admin/wechat/official-account"), + ) + server.AddRoutes( rest.WithMiddlewares( []rest.Middleware{serverCtx.MPCustomerJWTAuth}, diff --git a/internal/logic/admin/wechat/officialaccount/menu/createmenulogic.go b/internal/logic/admin/wechat/officialaccount/menu/createmenulogic.go new file mode 100644 index 00000000..0bf5e22a --- /dev/null +++ b/internal/logic/admin/wechat/officialaccount/menu/createmenulogic.go @@ -0,0 +1,30 @@ +package menu + +import ( + "context" + + "PowerX/internal/svc" + "PowerX/internal/types" + + "github.com/zeromicro/go-zero/core/logx" +) + +type CreateMenuLogic struct { + logx.Logger + ctx context.Context + svcCtx *svc.ServiceContext +} + +func NewCreateMenuLogic(ctx context.Context, svcCtx *svc.ServiceContext) *CreateMenuLogic { + return &CreateMenuLogic{ + Logger: logx.WithContext(ctx), + ctx: ctx, + svcCtx: svcCtx, + } +} + +func (l *CreateMenuLogic) CreateMenu(req *types.CreateMenuRequest) (resp *types.CreateMenuReply, err error) { + // todo: add your logic here and delete this line + + return +} diff --git a/internal/logic/admin/wechat/officialaccount/menu/deletemenulogic.go b/internal/logic/admin/wechat/officialaccount/menu/deletemenulogic.go new file mode 100644 index 00000000..4c437847 --- /dev/null +++ b/internal/logic/admin/wechat/officialaccount/menu/deletemenulogic.go @@ -0,0 +1,30 @@ +package menu + +import ( + "context" + + "PowerX/internal/svc" + "PowerX/internal/types" + + "github.com/zeromicro/go-zero/core/logx" +) + +type DeleteMenuLogic struct { + logx.Logger + ctx context.Context + svcCtx *svc.ServiceContext +} + +func NewDeleteMenuLogic(ctx context.Context, svcCtx *svc.ServiceContext) *DeleteMenuLogic { + return &DeleteMenuLogic{ + Logger: logx.WithContext(ctx), + ctx: ctx, + svcCtx: svcCtx, + } +} + +func (l *DeleteMenuLogic) DeleteMenu() (resp *types.DeleteMenuReply, err error) { + // todo: add your logic here and delete this line + + return +} diff --git a/internal/logic/admin/wechat/officialaccount/menu/querymenuslogic.go b/internal/logic/admin/wechat/officialaccount/menu/querymenuslogic.go new file mode 100644 index 00000000..eac016b4 --- /dev/null +++ b/internal/logic/admin/wechat/officialaccount/menu/querymenuslogic.go @@ -0,0 +1,30 @@ +package menu + +import ( + "context" + + "PowerX/internal/svc" + "PowerX/internal/types" + + "github.com/zeromicro/go-zero/core/logx" +) + +type QueryMenusLogic struct { + logx.Logger + ctx context.Context + svcCtx *svc.ServiceContext +} + +func NewQueryMenusLogic(ctx context.Context, svcCtx *svc.ServiceContext) *QueryMenusLogic { + return &QueryMenusLogic{ + Logger: logx.WithContext(ctx), + ctx: ctx, + svcCtx: svcCtx, + } +} + +func (l *QueryMenusLogic) QueryMenus() (resp *types.QueryMenusReply, err error) { + // todo: add your logic here and delete this line + + return +} diff --git a/internal/logic/admin/wechat/officialaccount/menu/syncmenuslogic.go b/internal/logic/admin/wechat/officialaccount/menu/syncmenuslogic.go new file mode 100644 index 00000000..5630a713 --- /dev/null +++ b/internal/logic/admin/wechat/officialaccount/menu/syncmenuslogic.go @@ -0,0 +1,92 @@ +package menu + +import ( + "context" + "github.com/ArtisanCloud/PowerWeChat/v3/src/officialAccount/menu/request" + + "PowerX/internal/svc" + "PowerX/internal/types" + + "github.com/zeromicro/go-zero/core/logx" +) + +type SyncMenusLogic struct { + logx.Logger + ctx context.Context + svcCtx *svc.ServiceContext +} + +func NewSyncMenusLogic(ctx context.Context, svcCtx *svc.ServiceContext) *SyncMenusLogic { + return &SyncMenusLogic{ + Logger: logx.WithContext(ctx), + ctx: ctx, + svcCtx: svcCtx, + } +} + +func (l *SyncMenusLogic) SyncMenus(req *types.SyncMenusRequest) (resp *types.SyncMenusReply, err error) { + + //resDelete, err := l.svcCtx.PowerX.WechatOA.App.Menu.Delete(l.ctx) + //if err != nil { + // return nil, err + //} + //if resDelete.ErrCode != 0 { + // return nil, errorx.WithCause(errorx.ErrDeleteObject, resDelete.ErrMsg) + //} + + buttons := TransformRequestToWechatOAMenu(&req.OAMenu) + //fmt.Dump(buttons) + _, err = l.svcCtx.PowerX.WechatOA.App.Menu.Create(l.ctx, buttons) + if err != nil { + return nil, err + } + + return &types.SyncMenusReply{ + Success: true, + Data: buttons, + }, nil +} + +func TransformRequestToWechatOAMenu(req *types.OAMenu) []*request.Button { + buttons := []*request.Button{} + for _, oaButton := range req.OAButton { + button := TransformRequestToWechatOAButton(oaButton) + buttons = append(buttons, button) + } + return buttons +} + +func TransformRequestToWechatOAButton(oaButton *types.OAButton) *request.Button { + subButtons := TransformRequestToWechatOASubButtons(oaButton.OASubButton) + return &request.Button{ + Type: oaButton.Type, + Name: oaButton.Name, + Key: oaButton.Key, + //MediaId: oaButton.MediaId, + URL: oaButton.Url, + AppID: oaButton.AppID, + PagePath: oaButton.PagePath, + SubButtons: subButtons, + } +} + +func TransformRequestToWechatOASubButtons(oaSubButtons []*types.OASubButton) []request.SubButton { + suyButtons := []request.SubButton{} + for _, oaSubButton := range oaSubButtons { + subButton := TransformRequestToWechatOASubButton(oaSubButton) + suyButtons = append(suyButtons, subButton) + } + return suyButtons +} + +func TransformRequestToWechatOASubButton(oaSuhButton *types.OASubButton) request.SubButton { + return request.SubButton{ + Type: oaSuhButton.Type, + Name: oaSuhButton.Name, + URL: oaSuhButton.Url, + AppID: oaSuhButton.AppID, + PagePath: oaSuhButton.PagePath, + Key: oaSuhButton.Key, + } + +} diff --git a/internal/types/types.go b/internal/types/types.go index 995757dd..86888c6f 100644 --- a/internal/types/types.go +++ b/internal/types/types.go @@ -2773,6 +2773,69 @@ type ActionCustomerTagRequest struct { RemoveTag []string `json:"removeTag,optional"` } +type OASubButton struct { + Name string `json:"name,optional"` + Id int `json:"id,optional"` + Type string `json:"type,optional"` + Key string `json:"key,omitempty,optional"` + Url string `json:"url,omitempty,optional"` + AppID string `json:"appid,omitempty,optional"` + PagePath string `json:"pagepath,omitempty,optional"` +} + +type OAButton struct { + Name string `json:"name,optional"` + Type string `json:"type,optional"` + Key string `json:"key,omitempty,optional"` + Url string `json:"url,omitempty,optional"` + AppID string `json:"appid,omitempty,optional"` + PagePath string `json:"pagepath,omitempty,optional"` + OASubButton []*OASubButton `json:"sub_button,optional"` + Id int `json:"id,optional"` +} + +type MatchRule struct { + TagId string `json:"tag_id,optional"` + Sex string `json:"sex,optional"` + Country string `json:"country,optional"` + Province string `json:"province,optional"` + City string `json:"city,optional"` + Language string `json:"language,optional"` +} + +type OAMenu struct { + Id int64 `json:"id,optional"` + OAButton []*OAButton `json:"button,optional"` + MatchRule *MatchRule `json:"matchrule,optional"` +} + +type SyncMenusRequest struct { + OAMenu +} + +type SyncMenusReply struct { + Success bool `json:"success,optional"` + Data interface{} `json:"data"` +} + +type CreateMenuRequest struct { + OAMenu +} + +type CreateMenuReply struct { + Success bool `json:"success,optional"` + Data interface{} `json:"data"` +} + +type QueryMenusReply struct { + Menu *OAMenu `json:"menu,optional"` +} + +type DeleteMenuReply struct { + Success bool `json:"success"` + Data interface{} `json:"data"` +} + type MPCustomerLoginRequest struct { Code string `json:"code"` }