Browse Source

增加给联系人发送文本和发送图片功能

x 10 tháng trước cách đây
mục cha
commit
23ed5f4e83

+ 2 - 1
.gitignore

@@ -29,4 +29,5 @@
 
 # Build files
 *_api
-*_rpc
+*_rpc
+/wechat-api

+ 2 - 1
desc/all.api

@@ -2,4 +2,5 @@ import "base.api"
 import "./wechat/server.api"
 import "./wechat/wx.api"
 import "./wechat/wxhook.api"
-import "./wechat/contact.api"
+import "./wechat/contact.api"
+import "./wechat/message.api"

+ 68 - 0
desc/wechat/message.api

@@ -0,0 +1,68 @@
+import "../base.api"
+
+type (
+	// The response data of message information | Message信息
+	MessageInfo {
+		BaseIDInfo
+		// 属主微信id
+		WxWxid *string `json:"wxWxid"`
+		// 微信id 公众号微信ID
+		Wxid *string `json:"wxid"`
+		// 微信消息内容
+		Msg *string `json:"msg"`
+	}
+	// The response data of message list | Message列表数据
+	MessageListResp {
+		BaseDataInfo
+		// Message list data | Message列表数据
+		Data MessageListInfo `json:"data"`
+	}
+	// Message list data | Message列表数据
+	MessageListInfo {
+		BaseListInfo
+		// The API list data | Message列表数据
+		Data []MessageInfo `json:"data"`
+	}
+	// Get message list request params | Message列表请求参数
+	MessageListReq {
+		PageInfo
+		// 属主微信id
+		WxWxid *string `json:"wxWxid,optional"`
+		// 微信id 公众号微信ID
+		Wxid *string `json:"wxid,optional"`
+	}
+	// Message information response | Message信息返回体
+	MessageInfoResp {
+		BaseDataInfo
+		// Message information | Message数据
+		Data MessageInfo `json:"data"`
+	}
+)
+
+@server (
+	jwt:        Auth
+	group:      Message
+	middleware: Authority
+)
+service Wechat {
+	// Create message information | 创建Message
+	@handler createMessage
+	post /message/create (MessageInfo) returns (BaseMsgResp)
+
+	// Update message information | 更新Message
+	@handler updateMessage
+	post /message/update (MessageInfo) returns (BaseMsgResp)
+
+	// Delete message information | 删除Message信息
+	@handler deleteMessage
+	post /message/delete (IDsReq) returns (BaseMsgResp)
+
+	// Get message list | 获取Message列表
+	@handler getMessageList
+	post /message/list (MessageListReq) returns (MessageListResp)
+
+	// Get message by ID | 通过ID获取Message
+	@handler getMessageById
+	post /message (IDReq) returns (MessageInfoResp)
+}
+

+ 67 - 14
desc/wechat/wxhook.api

@@ -1,35 +1,76 @@
 import "../base.api"
 
 type (
-
-    LoginQRStatus  {
+    LoginQRStatus {
         // 登陆二维码
-        QRCode  string `json:"qRCode,optional"`
+        QRCode string `json:"qRCode,optional"`
 
         // 登陆二维码状态
-        Status  string `json:"status,optional"`
+        Status string `json:"status,optional"`
 
         // 登陆二维码状态描述
-        StatusDesc  string `json:"statusDesc,optional"`
+        StatusDesc string `json:"statusDesc,optional"`
     }
 
-    // 刷新登陆二维码请求参数
+        // 刷新登陆二维码请求参数
     RefreshLoginQRReq {
-        // 服务器id 
-        ServerId  *uint64 `json:"serverId,optional"`
+        // 服务器id
+        ServerId *uint64 `json:"serverId,optional"`
 
-        // 端口号 
-        Port  *string `json:"port,optional"`
+        // 端口号
+        Port *string `json:"port,optional"`
 
-        // 回调地址 
-        Callback  *string `json:"callback,optional"`
+        // 回调地址
+        Callback *string `json:"callback,optional"`
     }
 
-    // 刷新登陆二维码返回参数
+        // 刷新登陆二维码返回参数
     RefreshLoginQRResp {
         BaseDataInfo
         // 二维码Base64
-        Data  LoginQRStatus  `json:"data,optional"`
+        Data LoginQRStatus `json:"data,optional"`
+    }
+
+        // 发送微信文本消息请求参数
+    SendTextMsgReq {
+
+        // 属主微信id
+        WxWxid *string `json:"wxWxid"`
+
+        // 微信id 公众号微信ID
+        Wxid *string `json:"wxid"`
+
+        // 微信文本消息内容
+        Msg *string `json:"msg"`
+    }
+
+        // 发送微信图片消息请求参数
+    SendPicMsgReq {
+
+        // 属主微信id
+        WxWxid *string `json:"wxWxid"`
+
+        // 微信id 公众号微信ID
+        Wxid *string `json:"wxid"`
+
+        // 微信图片路径(本地或网络,本地需要上传操作,如:C:\\x.jpg)
+        Picpath *string `json:"picpath"`
+
+        // 微信图片自定义名称(此属性只有网络图片有)
+        Diyfilename *string `json:"diyfilename,optional"`
+    }
+
+        // 发送微信图片(本地)请求参数
+    SendPicMsgLocalReq {
+
+        // 属主微信id
+        WxWxid *string `json:"wxWxid"`
+
+        // 微信id 公众号微信ID
+        Wxid *string `json:"wxid"`
+
+        // 微信图片路径(本地或网络,本地需要上传操作,如:C:\\x.jpg)
+        Picpath *string `json:"picpath"`
     }
 )
 
@@ -51,4 +92,16 @@ service Wechat {
     // 获取好友和群信息
     @handler getFriendsAndGroups
     post /wxhook/getFriendsAndGroups (IDReq) returns (BaseMsgResp)
+
+    // 发送微信文本消息
+    @handler sendTextMsg
+    post /wxhook/sendTextMsg (SendTextMsgReq) returns (BaseMsgResp)
+
+    // 发送微信图片
+    @handler sendPicMsg
+    post /wxhook/sendPicMsg (SendPicMsgReq) returns (BaseMsgResp)
+
+    // 发送微信图片(本地)
+    @handler sendPicMsgLocal
+    post /wxhook/sendPicMsgLocal (SendPicMsgLocalReq) returns (BaseMsgResp)
 }

+ 36 - 0
ent/schema/message.go

@@ -0,0 +1,36 @@
+package schema
+
+import (
+	"entgo.io/ent"
+	"entgo.io/ent/dialect/entsql"
+	"entgo.io/ent/schema"
+	"entgo.io/ent/schema/field"
+)
+
+// Message holds the schema definition for the Message entity.
+type Message struct {
+	ent.Schema
+}
+
+// Fields of the Message.
+func (Message) Fields() []ent.Field {
+	return []ent.Field{
+		field.String("wx_wxid").Optional().Default("").
+			Annotations(entsql.WithComments(true)).
+			Comment("属主微信id"),
+		field.String("wxid").Default("").
+			Annotations(entsql.WithComments(true)).
+			Comment("微信id 公众号微信ID"),
+		field.String("content").Default("").
+			Annotations(entsql.WithComments(true)).
+			Comment("微信消息内容"),
+	}
+}
+
+// Edges of the Message.
+func (Message) Edges() []ent.Edge {
+	return nil
+}
+func (Message) Annotations() []schema.Annotation {
+	return []schema.Annotation{entsql.Annotation{Table: "message"}}
+}

+ 7 - 7
etc/wechat.yaml

@@ -21,11 +21,11 @@ Log:
 
 DatabaseConf:
   Type: mysql
-  Host: 127.0.0.1
+  Host: vm4
   Port: 3306
   DBName: wechat
   Username: root
-  Password: p@ssw0rd123456
+  Password: simple-admin.
   MaxOpenConn: 100
   SSLMode: disable
   CacheTime: 5
@@ -33,19 +33,19 @@ DatabaseConf:
 CoreRpc:
   # Target: k8s://default/core-rpc-svc:9101
   Endpoints:
-    - 127.0.0.1:9101
+    - vm4:9101
   Enabled: true
 
 RedisConf:
-  Host: 127.0.0.1:6379
+  Host: vm4:6379
 
 CasbinDatabaseConf:
   Type: mysql
-  Host: 127.0.0.1
+  Host: vm4
   Port: 3306
-  DBName: simple_admin
+  DBName: wechat-admin
   Username: root
-  Password: p@ssw0rd123456
+  Password: simple-admin.
   MaxOpenConn: 100
   SSLMode: disable
   CacheTime: 5

+ 1 - 1
go.mod

@@ -7,6 +7,7 @@ require (
 	github.com/casbin/casbin/v2 v2.85.0
 	github.com/imroc/req/v3 v3.43.1
 	github.com/redis/go-redis/v9 v9.5.1
+	github.com/spf13/cast v1.6.0
 	github.com/suyuan32/simple-admin-common v1.3.11
 	github.com/suyuan32/simple-admin-core v1.3.11
 	github.com/zeromicro/go-zero v1.6.3
@@ -91,7 +92,6 @@ require (
 	github.com/quic-go/quic-go v0.42.0 // indirect
 	github.com/refraction-networking/utls v1.6.3 // indirect
 	github.com/spaolacci/murmur3 v1.1.0 // indirect
-	github.com/spf13/cast v1.6.0 // indirect
 	github.com/zclconf/go-cty v1.14.3 // indirect
 	go.etcd.io/etcd/api/v3 v3.5.12 // indirect
 	go.etcd.io/etcd/client/pkg/v3 v3.5.12 // indirect

+ 2 - 4
go.sum

@@ -108,6 +108,8 @@ github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7
 github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4=
 github.com/fatih/color v1.16.0 h1:zmkK9Ngbjj+K0yRhTVONQh1p/HknKYSlNT+vZCzyokM=
 github.com/fatih/color v1.16.0/go.mod h1:fL2Sau1YI5c0pdGEVCbKQbLXB6edEj1ZgiY4NijnWvE=
+github.com/frankban/quicktest v1.14.6 h1:7Xjx+VpznH+oBnejlPUj8oUpdxnVs4f8XU8WnHkI4W8=
+github.com/frankban/quicktest v1.14.6/go.mod h1:4ptaffx2x8+WTWXmUCuVU6aPUX1/Mz7zb5vbUoiM6w0=
 github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
 github.com/gabriel-vasile/mimetype v1.4.3 h1:in2uUcidCuFcDKtdcBxlR0rJ1+fsokWf+uqxgUFjbI0=
 github.com/gabriel-vasile/mimetype v1.4.3/go.mod h1:d8uq/6HKRL6CGdk+aubisF/M5GcPfT7nKyLpA0lbSSk=
@@ -360,7 +362,6 @@ github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Ky
 github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM=
 github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY=
 github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
-github.com/mattn/go-runewidth v0.0.9 h1:Lm995f3rfxdpd6TSmuVCHVb/QhupuXlYr8sCI/QdE+0=
 github.com/mattn/go-runewidth v0.0.9/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI=
 github.com/mattn/go-sqlite3 v1.14.6/go.mod h1:NyWgC/yNuGj7Q9rpYnZvas74GogHl5/Z4A/KQRfk6bU=
 github.com/mattn/go-sqlite3 v1.14.22 h1:2gZY6PC6kBnID23Tichd1K+Z0oS6nE/XwU+Vz/5o4kU=
@@ -391,7 +392,6 @@ github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRW
 github.com/nicksnyder/go-i18n/v2 v2.4.0 h1:3IcvPOAvnCKwNm0TB0dLDTuawWEj+ax/RERNC+diLMM=
 github.com/nicksnyder/go-i18n/v2 v2.4.0/go.mod h1:nxYSZE9M0bf3Y70gPQjN9ha7XNHX7gMc814+6wVyEI4=
 github.com/oklog/ulid v1.3.1/go.mod h1:CirwcVhetQ6Lv90oh/F+FBtV6XMibvdAFo93nm5qn4U=
-github.com/olekukonko/tablewriter v0.0.5 h1:P2Ga83D34wi1o9J6Wh1mRuqd4mF/x/lgBS7N7AbDhec=
 github.com/olekukonko/tablewriter v0.0.5/go.mod h1:hPp6KlRPjbx+hW8ykQs1w3UBbZlj6HuIJcUGPhkA7kY=
 github.com/onsi/ginkgo/v2 v2.17.1 h1:V++EzdbhI4ZV4ev0UTIj0PzhzOcReJFyJaLjtSF55M8=
 github.com/onsi/ginkgo/v2 v2.17.1/go.mod h1:llBI3WDLL9Z6taip6f33H76YcWtJv+7R3HigUjbIBOs=
@@ -470,8 +470,6 @@ github.com/spf13/cast v1.3.0/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkU
 github.com/spf13/cast v1.6.0 h1:GEiTHELF+vaR5dhz3VqZfFSzZjYbgeKDpBxQVS4GYJ0=
 github.com/spf13/cast v1.6.0/go.mod h1:ancEpBxwJDODSW/UG4rDrAqiKolqNNh2DX3mk86cAdo=
 github.com/spf13/cobra v1.1.3/go.mod h1:pGADOWyqRD/YMrPZigI/zbliZ2wVD/23d+is3pSWzOo=
-github.com/spf13/cobra v1.7.0 h1:hyqWnYt1ZQShIddO5kBpj3vu05/++x6tJ6dg8EC572I=
-github.com/spf13/cobra v1.7.0/go.mod h1:uLxZILRyS/50WlhOIKD7W6V5bgeIt+4sICxh6uRMrb0=
 github.com/spf13/jwalterweatherman v1.0.0/go.mod h1:cQK4TGJAtQXfYWX+Ddv3mKDzgVb68N+wFjFa4jdeBTo=
 github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4=
 github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA=

+ 49 - 0
hook/message.go

@@ -17,3 +17,52 @@ func (h *Hook) ConfigureMsgRecive(isEnable string, url string) (err error) {
 	}
 	return
 }
+
+// 发送微信文本消息
+func (h *Hook) SendTextMsg(wxid, msg string) (err error) {
+	resp, err := h.Client.R().SetBody(&SendTextMsgReq{
+		Wxid: wxid,
+		Msg:  msg,
+	}).Post("http://" + h.ServerIp + ":" + h.WxPort + "/SendTextMsg")
+	if err != nil {
+		return
+	}
+	if !resp.IsSuccessState() {
+		err = fmt.Errorf("SendTextMsg failed with status code %d", resp.StatusCode)
+		return
+	}
+	return
+}
+
+// 发送微信图片
+func (h *Hook) SendPicMsg(wxid, picpath, diyfilename string) (err error) {
+	resp, err := h.Client.R().SetBody(&SendPicMsgReq{
+		Wxid:        wxid,
+		Picpath:     picpath,
+		Diyfilename: diyfilename,
+	}).Post("http://" + h.ServerIp + ":" + h.WxPort + "/SendPicMsg")
+	if err != nil {
+		return
+	}
+	if !resp.IsSuccessState() {
+		err = fmt.Errorf("SendPicMsg failed with status code %d", resp.StatusCode)
+		return
+	}
+	return
+}
+
+// 发送微信图片(本地测试)
+func (h *Hook) SendPicMsgLocal(wxid, picpath string) (err error) {
+	resp, err := h.Client.R().SetBody(&SendPicMsgLocalReq{
+		Wxid:    wxid,
+		Picpath: picpath,
+	}).Post("http://" + h.ServerIp + ":" + h.WxPort + "/SendPicMsg")
+	if err != nil {
+		return
+	}
+	if !resp.IsSuccessState() {
+		err = fmt.Errorf("SendPicMsgLocal failed with status code %d", resp.StatusCode)
+		return
+	}
+	return
+}

+ 16 - 0
hook/type.go

@@ -44,6 +44,22 @@ type ConfigureMsgReciveReq struct {
 	URL      string `json:"url"`
 }
 
+type SendTextMsgReq struct {
+	Wxid string `json:"wxid"`
+	Msg  string `json:"msg"`
+}
+
+type SendPicMsgReq struct {
+	Wxid        string `json:"wxid"`
+	Picpath     string `json:"picpath"`
+	Diyfilename string `json:"diyfilename"`
+}
+
+type SendPicMsgLocalReq struct {
+	Wxid    string `json:"wxid"`
+	Picpath string `json:"picpath"`
+}
+
 type GetSelfLoginInfoResp struct {
 	ProcessID string `json:"ProcessID"`
 	Wxid      string `json:"wxid"`

+ 44 - 0
internal/handler/Message/create_message_handler.go

@@ -0,0 +1,44 @@
+package Message
+
+import (
+	"net/http"
+
+	"github.com/zeromicro/go-zero/rest/httpx"
+
+	"wechat-api/internal/logic/Message"
+	"wechat-api/internal/svc"
+	"wechat-api/internal/types"
+)
+
+// swagger:route post /message/create Message CreateMessage
+//
+// Create message information | 创建Message
+//
+// Create message information | 创建Message
+//
+// Parameters:
+//  + name: body
+//    require: true
+//    in: body
+//    type: MessageInfo
+//
+// Responses:
+//  200: BaseMsgResp
+
+func CreateMessageHandler(svcCtx *svc.ServiceContext) http.HandlerFunc {
+	return func(w http.ResponseWriter, r *http.Request) {
+		var req types.MessageInfo
+		if err := httpx.Parse(r, &req, true); err != nil {
+			httpx.ErrorCtx(r.Context(), w, err)
+			return
+		}
+
+		l := Message.NewCreateMessageLogic(r.Context(), svcCtx)
+		resp, err := l.CreateMessage(&req)
+		if err != nil {
+			httpx.ErrorCtx(r.Context(), w, err)
+		} else {
+			httpx.OkJsonCtx(r.Context(), w, resp)
+		}
+	}
+}

+ 44 - 0
internal/handler/Message/delete_message_handler.go

@@ -0,0 +1,44 @@
+package Message
+
+import (
+	"net/http"
+
+	"github.com/zeromicro/go-zero/rest/httpx"
+
+	"wechat-api/internal/logic/Message"
+	"wechat-api/internal/svc"
+	"wechat-api/internal/types"
+)
+
+// swagger:route post /message/delete Message DeleteMessage
+//
+// Delete message information | 删除Message信息
+//
+// Delete message information | 删除Message信息
+//
+// Parameters:
+//  + name: body
+//    require: true
+//    in: body
+//    type: IDsReq
+//
+// Responses:
+//  200: BaseMsgResp
+
+func DeleteMessageHandler(svcCtx *svc.ServiceContext) http.HandlerFunc {
+	return func(w http.ResponseWriter, r *http.Request) {
+		var req types.IDsReq
+		if err := httpx.Parse(r, &req, true); err != nil {
+			httpx.ErrorCtx(r.Context(), w, err)
+			return
+		}
+
+		l := Message.NewDeleteMessageLogic(r.Context(), svcCtx)
+		resp, err := l.DeleteMessage(&req)
+		if err != nil {
+			httpx.ErrorCtx(r.Context(), w, err)
+		} else {
+			httpx.OkJsonCtx(r.Context(), w, resp)
+		}
+	}
+}

+ 44 - 0
internal/handler/Message/get_message_by_id_handler.go

@@ -0,0 +1,44 @@
+package Message
+
+import (
+	"net/http"
+
+	"github.com/zeromicro/go-zero/rest/httpx"
+
+	"wechat-api/internal/logic/Message"
+	"wechat-api/internal/svc"
+	"wechat-api/internal/types"
+)
+
+// swagger:route post /message Message GetMessageById
+//
+// Get message by ID | 通过ID获取Message
+//
+// Get message by ID | 通过ID获取Message
+//
+// Parameters:
+//  + name: body
+//    require: true
+//    in: body
+//    type: IDReq
+//
+// Responses:
+//  200: MessageInfoResp
+
+func GetMessageByIdHandler(svcCtx *svc.ServiceContext) http.HandlerFunc {
+	return func(w http.ResponseWriter, r *http.Request) {
+		var req types.IDReq
+		if err := httpx.Parse(r, &req, true); err != nil {
+			httpx.ErrorCtx(r.Context(), w, err)
+			return
+		}
+
+		l := Message.NewGetMessageByIdLogic(r.Context(), svcCtx)
+		resp, err := l.GetMessageById(&req)
+		if err != nil {
+			httpx.ErrorCtx(r.Context(), w, err)
+		} else {
+			httpx.OkJsonCtx(r.Context(), w, resp)
+		}
+	}
+}

+ 44 - 0
internal/handler/Message/get_message_list_handler.go

@@ -0,0 +1,44 @@
+package Message
+
+import (
+	"net/http"
+
+	"github.com/zeromicro/go-zero/rest/httpx"
+
+	"wechat-api/internal/logic/Message"
+	"wechat-api/internal/svc"
+	"wechat-api/internal/types"
+)
+
+// swagger:route post /message/list Message GetMessageList
+//
+// Get message list | 获取Message列表
+//
+// Get message list | 获取Message列表
+//
+// Parameters:
+//  + name: body
+//    require: true
+//    in: body
+//    type: MessageListReq
+//
+// Responses:
+//  200: MessageListResp
+
+func GetMessageListHandler(svcCtx *svc.ServiceContext) http.HandlerFunc {
+	return func(w http.ResponseWriter, r *http.Request) {
+		var req types.MessageListReq
+		if err := httpx.Parse(r, &req, true); err != nil {
+			httpx.ErrorCtx(r.Context(), w, err)
+			return
+		}
+
+		l := Message.NewGetMessageListLogic(r.Context(), svcCtx)
+		resp, err := l.GetMessageList(&req)
+		if err != nil {
+			httpx.ErrorCtx(r.Context(), w, err)
+		} else {
+			httpx.OkJsonCtx(r.Context(), w, resp)
+		}
+	}
+}

+ 44 - 0
internal/handler/Message/update_message_handler.go

@@ -0,0 +1,44 @@
+package Message
+
+import (
+	"net/http"
+
+	"github.com/zeromicro/go-zero/rest/httpx"
+
+	"wechat-api/internal/logic/Message"
+	"wechat-api/internal/svc"
+	"wechat-api/internal/types"
+)
+
+// swagger:route post /message/update Message UpdateMessage
+//
+// Update message information | 更新Message
+//
+// Update message information | 更新Message
+//
+// Parameters:
+//  + name: body
+//    require: true
+//    in: body
+//    type: MessageInfo
+//
+// Responses:
+//  200: BaseMsgResp
+
+func UpdateMessageHandler(svcCtx *svc.ServiceContext) http.HandlerFunc {
+	return func(w http.ResponseWriter, r *http.Request) {
+		var req types.MessageInfo
+		if err := httpx.Parse(r, &req, true); err != nil {
+			httpx.ErrorCtx(r.Context(), w, err)
+			return
+		}
+
+		l := Message.NewUpdateMessageLogic(r.Context(), svcCtx)
+		resp, err := l.UpdateMessage(&req)
+		if err != nil {
+			httpx.ErrorCtx(r.Context(), w, err)
+		} else {
+			httpx.OkJsonCtx(r.Context(), w, resp)
+		}
+	}
+}

+ 44 - 0
internal/handler/Wxhook/send_pic_msg_handler.go

@@ -0,0 +1,44 @@
+package Wxhook
+
+import (
+	"net/http"
+
+	"github.com/zeromicro/go-zero/rest/httpx"
+
+	"wechat-api/internal/logic/Wxhook"
+	"wechat-api/internal/svc"
+	"wechat-api/internal/types"
+)
+
+// swagger:route post /wxhook/sendPicMsg Wxhook SendPicMsg
+//
+// 发送微信图片
+//
+// 发送微信图片
+//
+// Parameters:
+//  + name: body
+//    require: true
+//    in: body
+//    type: SendPicMsgReq
+//
+// Responses:
+//  200: BaseMsgResp
+
+func SendPicMsgHandler(svcCtx *svc.ServiceContext) http.HandlerFunc {
+	return func(w http.ResponseWriter, r *http.Request) {
+		var req types.SendPicMsgReq
+		if err := httpx.Parse(r, &req, true); err != nil {
+			httpx.ErrorCtx(r.Context(), w, err)
+			return
+		}
+
+		l := Wxhook.NewSendPicMsgLogic(r.Context(), svcCtx)
+		resp, err := l.SendPicMsg(&req)
+		if err != nil {
+			httpx.ErrorCtx(r.Context(), w, err)
+		} else {
+			httpx.OkJsonCtx(r.Context(), w, resp)
+		}
+	}
+}

+ 44 - 0
internal/handler/Wxhook/send_pic_msg_local_handler.go

@@ -0,0 +1,44 @@
+package Wxhook
+
+import (
+	"net/http"
+
+	"github.com/zeromicro/go-zero/rest/httpx"
+
+	"wechat-api/internal/logic/Wxhook"
+	"wechat-api/internal/svc"
+	"wechat-api/internal/types"
+)
+
+// swagger:route post /wxhook/sendPicMsgLocal Wxhook SendPicMsgLocal
+//
+// 发送微信图片(本地)
+//
+// 发送微信图片(本地)
+//
+// Parameters:
+//  + name: body
+//    require: true
+//    in: body
+//    type: SendPicMsgLocalReq
+//
+// Responses:
+//  200: BaseMsgResp
+
+func SendPicMsgLocalHandler(svcCtx *svc.ServiceContext) http.HandlerFunc {
+	return func(w http.ResponseWriter, r *http.Request) {
+		var req types.SendPicMsgLocalReq
+		if err := httpx.Parse(r, &req, true); err != nil {
+			httpx.ErrorCtx(r.Context(), w, err)
+			return
+		}
+
+		l := Wxhook.NewSendPicMsgLocalLogic(r.Context(), svcCtx)
+		resp, err := l.SendPicMsgLocal(&req)
+		if err != nil {
+			httpx.ErrorCtx(r.Context(), w, err)
+		} else {
+			httpx.OkJsonCtx(r.Context(), w, resp)
+		}
+	}
+}

+ 44 - 0
internal/handler/Wxhook/send_text_msg_handler.go

@@ -0,0 +1,44 @@
+package Wxhook
+
+import (
+	"net/http"
+
+	"github.com/zeromicro/go-zero/rest/httpx"
+
+	"wechat-api/internal/logic/Wxhook"
+	"wechat-api/internal/svc"
+	"wechat-api/internal/types"
+)
+
+// swagger:route post /wxhook/sendTextMsg Wxhook SendTextMsg
+//
+// 发送微信文本消息
+//
+// 发送微信文本消息
+//
+// Parameters:
+//  + name: body
+//    require: true
+//    in: body
+//    type: SendTextMsgReq
+//
+// Responses:
+//  200: BaseMsgResp
+
+func SendTextMsgHandler(svcCtx *svc.ServiceContext) http.HandlerFunc {
+	return func(w http.ResponseWriter, r *http.Request) {
+		var req types.SendTextMsgReq
+		if err := httpx.Parse(r, &req, true); err != nil {
+			httpx.ErrorCtx(r.Context(), w, err)
+			return
+		}
+
+		l := Wxhook.NewSendTextMsgLogic(r.Context(), svcCtx)
+		resp, err := l.SendTextMsg(&req)
+		if err != nil {
+			httpx.ErrorCtx(r.Context(), w, err)
+		} else {
+			httpx.OkJsonCtx(r.Context(), w, resp)
+		}
+	}
+}

+ 50 - 0
internal/handler/routes.go

@@ -5,6 +5,7 @@ import (
 	"net/http"
 
 	Contact "wechat-api/internal/handler/Contact"
+	Message "wechat-api/internal/handler/Message"
 	WechatServer "wechat-api/internal/handler/WechatServer"
 	Wx "wechat-api/internal/handler/Wx"
 	Wxhook "wechat-api/internal/handler/Wxhook"
@@ -112,6 +113,21 @@ func RegisterHandlers(server *rest.Server, serverCtx *svc.ServiceContext) {
 					Path:    "/wxhook/getFriendsAndGroups",
 					Handler: Wxhook.GetFriendsAndGroupsHandler(serverCtx),
 				},
+				{
+					Method:  http.MethodPost,
+					Path:    "/wxhook/sendTextMsg",
+					Handler: Wxhook.SendTextMsgHandler(serverCtx),
+				},
+				{
+					Method:  http.MethodPost,
+					Path:    "/wxhook/sendPicMsg",
+					Handler: Wxhook.SendPicMsgHandler(serverCtx),
+				},
+				{
+					Method:  http.MethodPost,
+					Path:    "/wxhook/sendPicMsgLocal",
+					Handler: Wxhook.SendPicMsgLocalHandler(serverCtx),
+				},
 			}...,
 		),
 		rest.WithJwt(serverCtx.Config.Auth.AccessSecret),
@@ -150,4 +166,38 @@ func RegisterHandlers(server *rest.Server, serverCtx *svc.ServiceContext) {
 		),
 		rest.WithJwt(serverCtx.Config.Auth.AccessSecret),
 	)
+
+	server.AddRoutes(
+		rest.WithMiddlewares(
+			[]rest.Middleware{serverCtx.Authority},
+			[]rest.Route{
+				{
+					Method:  http.MethodPost,
+					Path:    "/message/create",
+					Handler: Message.CreateMessageHandler(serverCtx),
+				},
+				{
+					Method:  http.MethodPost,
+					Path:    "/message/update",
+					Handler: Message.UpdateMessageHandler(serverCtx),
+				},
+				{
+					Method:  http.MethodPost,
+					Path:    "/message/delete",
+					Handler: Message.DeleteMessageHandler(serverCtx),
+				},
+				{
+					Method:  http.MethodPost,
+					Path:    "/message/list",
+					Handler: Message.GetMessageListHandler(serverCtx),
+				},
+				{
+					Method:  http.MethodPost,
+					Path:    "/message",
+					Handler: Message.GetMessageByIdHandler(serverCtx),
+				},
+			}...,
+		),
+		rest.WithJwt(serverCtx.Config.Auth.AccessSecret),
+	)
 }

+ 29 - 0
internal/logic/Message/create_message_logic.go

@@ -0,0 +1,29 @@
+package Message
+
+import (
+	"context"
+
+	"wechat-api/internal/svc"
+	"wechat-api/internal/types"
+
+	"github.com/zeromicro/go-zero/core/logx"
+)
+
+type CreateMessageLogic struct {
+	logx.Logger
+	ctx    context.Context
+	svcCtx *svc.ServiceContext
+}
+
+func NewCreateMessageLogic(ctx context.Context, svcCtx *svc.ServiceContext) *CreateMessageLogic {
+	return &CreateMessageLogic{
+		Logger: logx.WithContext(ctx),
+		ctx:    ctx,
+		svcCtx: svcCtx}
+}
+
+func (l *CreateMessageLogic) CreateMessage(req *types.MessageInfo) (resp *types.BaseMsgResp, err error) {
+	// todo: add your logic here and delete this line
+
+	return
+}

+ 29 - 0
internal/logic/Message/delete_message_logic.go

@@ -0,0 +1,29 @@
+package Message
+
+import (
+	"context"
+
+	"wechat-api/internal/svc"
+	"wechat-api/internal/types"
+
+	"github.com/zeromicro/go-zero/core/logx"
+)
+
+type DeleteMessageLogic struct {
+	logx.Logger
+	ctx    context.Context
+	svcCtx *svc.ServiceContext
+}
+
+func NewDeleteMessageLogic(ctx context.Context, svcCtx *svc.ServiceContext) *DeleteMessageLogic {
+	return &DeleteMessageLogic{
+		Logger: logx.WithContext(ctx),
+		ctx:    ctx,
+		svcCtx: svcCtx}
+}
+
+func (l *DeleteMessageLogic) DeleteMessage(req *types.IDsReq) (resp *types.BaseMsgResp, err error) {
+	// todo: add your logic here and delete this line
+
+	return
+}

+ 29 - 0
internal/logic/Message/get_message_by_id_logic.go

@@ -0,0 +1,29 @@
+package Message
+
+import (
+	"context"
+
+	"wechat-api/internal/svc"
+	"wechat-api/internal/types"
+
+	"github.com/zeromicro/go-zero/core/logx"
+)
+
+type GetMessageByIdLogic struct {
+	logx.Logger
+	ctx    context.Context
+	svcCtx *svc.ServiceContext
+}
+
+func NewGetMessageByIdLogic(ctx context.Context, svcCtx *svc.ServiceContext) *GetMessageByIdLogic {
+	return &GetMessageByIdLogic{
+		Logger: logx.WithContext(ctx),
+		ctx:    ctx,
+		svcCtx: svcCtx}
+}
+
+func (l *GetMessageByIdLogic) GetMessageById(req *types.IDReq) (resp *types.MessageInfoResp, err error) {
+	// todo: add your logic here and delete this line
+
+	return
+}

+ 29 - 0
internal/logic/Message/get_message_list_logic.go

@@ -0,0 +1,29 @@
+package Message
+
+import (
+	"context"
+
+	"wechat-api/internal/svc"
+	"wechat-api/internal/types"
+
+	"github.com/zeromicro/go-zero/core/logx"
+)
+
+type GetMessageListLogic struct {
+	logx.Logger
+	ctx    context.Context
+	svcCtx *svc.ServiceContext
+}
+
+func NewGetMessageListLogic(ctx context.Context, svcCtx *svc.ServiceContext) *GetMessageListLogic {
+	return &GetMessageListLogic{
+		Logger: logx.WithContext(ctx),
+		ctx:    ctx,
+		svcCtx: svcCtx}
+}
+
+func (l *GetMessageListLogic) GetMessageList(req *types.MessageListReq) (resp *types.MessageListResp, err error) {
+	// todo: add your logic here and delete this line
+
+	return
+}

+ 29 - 0
internal/logic/Message/update_message_logic.go

@@ -0,0 +1,29 @@
+package Message
+
+import (
+	"context"
+
+	"wechat-api/internal/svc"
+	"wechat-api/internal/types"
+
+	"github.com/zeromicro/go-zero/core/logx"
+)
+
+type UpdateMessageLogic struct {
+	logx.Logger
+	ctx    context.Context
+	svcCtx *svc.ServiceContext
+}
+
+func NewUpdateMessageLogic(ctx context.Context, svcCtx *svc.ServiceContext) *UpdateMessageLogic {
+	return &UpdateMessageLogic{
+		Logger: logx.WithContext(ctx),
+		ctx:    ctx,
+		svcCtx: svcCtx}
+}
+
+func (l *UpdateMessageLogic) UpdateMessage(req *types.MessageInfo) (resp *types.BaseMsgResp, err error) {
+	// todo: add your logic here and delete this line
+
+	return
+}

+ 71 - 0
internal/logic/Wxhook/send_pic_msg_local_logic.go

@@ -0,0 +1,71 @@
+package Wxhook
+
+import (
+	"context"
+	"github.com/suyuan32/simple-admin-common/enum/errorcode"
+	"github.com/suyuan32/simple-admin-common/msg/errormsg"
+	"wechat-api/ent/predicate"
+	"wechat-api/ent/wx"
+	"wechat-api/hook"
+
+	"wechat-api/internal/svc"
+	"wechat-api/internal/types"
+
+	"github.com/zeromicro/go-zero/core/logx"
+)
+
+type SendPicMsgLocalLogic struct {
+	logx.Logger
+	ctx    context.Context
+	svcCtx *svc.ServiceContext
+}
+
+func NewSendPicMsgLocalLogic(ctx context.Context, svcCtx *svc.ServiceContext) *SendPicMsgLocalLogic {
+	return &SendPicMsgLocalLogic{
+		Logger: logx.WithContext(ctx),
+		ctx:    ctx,
+		svcCtx: svcCtx}
+}
+
+func (l *SendPicMsgLocalLogic) SendPicMsgLocal(req *types.SendPicMsgLocalReq) (resp *types.BaseMsgResp, err error) {
+
+	//根据wx实体的wxid查询
+	var predicates []predicate.Wx
+	if req.WxWxid != nil {
+		predicates = append(predicates, wx.WxidContains(*req.WxWxid))
+	}
+
+	wxInfo, err := l.svcCtx.DB.Wx.Query().Where(predicates...).Only(l.ctx)
+
+	//根据wx实体的主键ID查询
+	//wxInfo, err := l.svcCtx.DB.Wx.Get(l.ctx, *req.AgentWxId)
+
+	l.Infof("wxInfo = %v", wxInfo)
+
+	if err != nil {
+		l.Error("查询微信信息失败", err)
+		return
+	}
+
+	serverInfo, err := l.svcCtx.DB.Server.Get(l.ctx, wxInfo.ServerID)
+	if err != nil {
+		l.Error("查询服务器信息失败", err)
+		return
+	}
+
+	hookClient := hook.NewHook(serverInfo.PrivateIP, serverInfo.AdminPort, wxInfo.Port)
+
+	err = hookClient.SendPicMsgLocal(*req.Wxid, *req.Picpath)
+
+	if err != nil {
+		l.Error("发送微信图片(本地)失败", err)
+		return
+	}
+
+	resp = &types.BaseMsgResp{
+		Msg:  errormsg.Success,
+		Code: errorcode.OK,
+	}
+
+	return
+}

+ 71 - 0
internal/logic/Wxhook/send_pic_msg_logic.go

@@ -0,0 +1,71 @@
+package Wxhook
+
+import (
+	"context"
+	"github.com/suyuan32/simple-admin-common/enum/errorcode"
+	"github.com/suyuan32/simple-admin-common/msg/errormsg"
+	"wechat-api/ent/predicate"
+	"wechat-api/ent/wx"
+	"wechat-api/hook"
+
+	"wechat-api/internal/svc"
+	"wechat-api/internal/types"
+
+	"github.com/zeromicro/go-zero/core/logx"
+)
+
+type SendPicMsgLogic struct {
+	logx.Logger
+	ctx    context.Context
+	svcCtx *svc.ServiceContext
+}
+
+func NewSendPicMsgLogic(ctx context.Context, svcCtx *svc.ServiceContext) *SendPicMsgLogic {
+	return &SendPicMsgLogic{
+		Logger: logx.WithContext(ctx),
+		ctx:    ctx,
+		svcCtx: svcCtx}
+}
+
+func (l *SendPicMsgLogic) SendPicMsg(req *types.SendPicMsgReq) (resp *types.BaseMsgResp, err error) {
+
+	//根据wx实体的wxid查询
+	var predicates []predicate.Wx
+	if req.WxWxid != nil {
+		predicates = append(predicates, wx.WxidContains(*req.WxWxid))
+	}
+
+	wxInfo, err := l.svcCtx.DB.Wx.Query().Where(predicates...).Only(l.ctx)
+
+	//根据wx实体的主键ID查询
+	//wxInfo, err := l.svcCtx.DB.Wx.Get(l.ctx, *req.AgentWxId)
+
+	l.Infof("wxInfo = %v", wxInfo)
+
+	if err != nil {
+		l.Error("查询微信信息失败", err)
+		return
+	}
+
+	serverInfo, err := l.svcCtx.DB.Server.Get(l.ctx, wxInfo.ServerID)
+	if err != nil {
+		l.Error("查询服务器信息失败", err)
+		return
+	}
+
+	hookClient := hook.NewHook(serverInfo.PrivateIP, serverInfo.AdminPort, wxInfo.Port)
+
+	err = hookClient.SendPicMsg(*req.Wxid, *req.Picpath, *req.Diyfilename)
+
+	if err != nil {
+		l.Error("发送微信图片失败", err)
+		return
+	}
+
+	resp = &types.BaseMsgResp{
+		Msg:  errormsg.Success,
+		Code: errorcode.OK,
+	}
+
+	return
+}

+ 70 - 0
internal/logic/Wxhook/send_text_msg_logic.go

@@ -0,0 +1,70 @@
+package Wxhook
+
+import (
+	"context"
+	"github.com/suyuan32/simple-admin-common/enum/errorcode"
+	"github.com/suyuan32/simple-admin-common/msg/errormsg"
+	"wechat-api/ent/predicate"
+	"wechat-api/ent/wx"
+	"wechat-api/hook"
+	"wechat-api/internal/svc"
+	"wechat-api/internal/types"
+
+	"github.com/zeromicro/go-zero/core/logx"
+)
+
+type SendTextMsgLogic struct {
+	logx.Logger
+	ctx    context.Context
+	svcCtx *svc.ServiceContext
+}
+
+func NewSendTextMsgLogic(ctx context.Context, svcCtx *svc.ServiceContext) *SendTextMsgLogic {
+	return &SendTextMsgLogic{
+		Logger: logx.WithContext(ctx),
+		ctx:    ctx,
+		svcCtx: svcCtx}
+}
+
+func (l *SendTextMsgLogic) SendTextMsg(req *types.SendTextMsgReq) (resp *types.BaseMsgResp, err error) {
+
+	//根据wx实体的wxid查询
+	var predicates []predicate.Wx
+	if req.WxWxid != nil {
+		predicates = append(predicates, wx.WxidContains(*req.WxWxid))
+	}
+
+	wxInfo, err := l.svcCtx.DB.Wx.Query().Where(predicates...).Only(l.ctx)
+
+	//根据wx实体的主键ID查询
+	//wxInfo, err := l.svcCtx.DB.Wx.Get(l.ctx, *req.AgentWxId)
+
+	l.Infof("wxInfo = %v", wxInfo)
+
+	if err != nil {
+		l.Error("查询微信信息失败", err)
+		return
+	}
+
+	serverInfo, err := l.svcCtx.DB.Server.Get(l.ctx, wxInfo.ServerID)
+	if err != nil {
+		l.Error("查询服务器信息失败", err)
+		return
+	}
+
+	hookClient := hook.NewHook(serverInfo.PrivateIP, serverInfo.AdminPort, wxInfo.Port)
+
+	err = hookClient.SendTextMsg(*req.Wxid, *req.Msg)
+
+	if err != nil {
+		l.Error("发送微信文本消息失败", err)
+		return
+	}
+
+	resp = &types.BaseMsgResp{
+		Msg:  errormsg.Success,
+		Code: errorcode.OK,
+	}
+
+	return
+}

+ 81 - 0
internal/types/types.go

@@ -362,6 +362,41 @@ type RefreshLoginQRResp struct {
 	Data LoginQRStatus `json:"data,optional"`
 }
 
+// 发送微信文本消息请求参数
+// swagger:model SendTextMsgReq
+type SendTextMsgReq struct {
+	// 属主微信id
+	WxWxid *string `json:"wxWxid"`
+	// 微信id 公众号微信ID
+	Wxid *string `json:"wxid"`
+	// 微信文本消息内容
+	Msg *string `json:"msg"`
+}
+
+// 发送微信图片消息请求参数
+// swagger:model SendPicMsgReq
+type SendPicMsgReq struct {
+	// 属主微信id
+	WxWxid *string `json:"wxWxid"`
+	// 微信id 公众号微信ID
+	Wxid *string `json:"wxid"`
+	// 微信图片路径(本地或网络,本地需要上传操作,如:C:\\x.jpg)
+	Picpath *string `json:"picpath"`
+	// 微信图片自定义名称(此属性只有网络图片有)
+	Diyfilename *string `json:"diyfilename,optional"`
+}
+
+// 发送微信图片(本地)请求参数
+// swagger:model SendPicMsgLocalReq
+type SendPicMsgLocalReq struct {
+	// 属主微信id
+	WxWxid *string `json:"wxWxid"`
+	// 微信id 公众号微信ID
+	Wxid *string `json:"wxid"`
+	// 微信图片路径(本地或网络,本地需要上传操作,如:C:\\x.jpg)
+	Picpath *string `json:"picpath"`
+}
+
 // The response data of contact information | Contact信息
 // swagger:model ContactInfo
 type ContactInfo struct {
@@ -435,3 +470,49 @@ type ContactInfoResp struct {
 	// Contact information | Contact数据
 	Data ContactInfo `json:"data"`
 }
+
+// The response data of message information | Message信息
+// swagger:model MessageInfo
+type MessageInfo struct {
+	BaseIDInfo
+	// 属主微信id
+	WxWxid *string `json:"wxWxid"`
+	// 微信id 公众号微信ID
+	Wxid *string `json:"wxid"`
+	// 微信消息内容
+	Msg *string `json:"msg"`
+}
+
+// The response data of message list | Message列表数据
+// swagger:model MessageListResp
+type MessageListResp struct {
+	BaseDataInfo
+	// Message list data | Message列表数据
+	Data MessageListInfo `json:"data"`
+}
+
+// Message list data | Message列表数据
+// swagger:model MessageListInfo
+type MessageListInfo struct {
+	BaseListInfo
+	// The API list data | Message列表数据
+	Data []MessageInfo `json:"data"`
+}
+
+// Get message list request params | Message列表请求参数
+// swagger:model MessageListReq
+type MessageListReq struct {
+	PageInfo
+	// 属主微信id
+	WxWxid *string `json:"wxWxid,optional"`
+	// 微信id 公众号微信ID
+	Wxid *string `json:"wxid,optional"`
+}
+
+// Message information response | Message信息返回体
+// swagger:model MessageInfoResp
+type MessageInfoResp struct {
+	BaseDataInfo
+	// Message information | Message数据
+	Data MessageInfo `json:"data"`
+}