Browse Source

feat:微信插件扩展微信小程序发送消息功能

Cheng Jian 2 years ago
parent
commit
707f4e9491

+ 79 - 0
opms_libary/database/oracle.go

@@ -0,0 +1,79 @@
+package database
+
+import (
+	"database/sql"
+	"github.com/gogf/gf/database/gdb"
+	"github.com/gogf/gf/errors/gcode"
+	"github.com/gogf/gf/errors/gerror"
+	"github.com/gogf/gf/text/gregex"
+	"github.com/gogf/gf/util/gconv"
+	gora "github.com/sijms/go-ora/v2"
+)
+
+type OracleDriver struct {
+	*gdb.DriverOracle
+}
+
+var (
+	// customDriverName is my driver name, which is used for registering.
+	customDriverName = "oracle"
+)
+
+func init() {
+	// It here registers my custom driver in package initialization function "init".
+	// You can later use this type in the database configuration.
+	if err := gdb.Register(customDriverName, &OracleDriver{}); err != nil {
+		panic(err)
+	}
+}
+
+// New creates and returns a database object for oracle.
+// It implements the interface of gdb.Driver for extra database driver installation.
+func (d *OracleDriver) New(core *gdb.Core, node *gdb.ConfigNode) (gdb.DB, error) {
+	return &OracleDriver{
+		&gdb.DriverOracle{
+			Core: core,
+		},
+	}, nil
+}
+
+// Open creates and returns an underlying sql.DB object for oracle.
+func (d *OracleDriver) Open(config *gdb.ConfigNode) (db *sql.DB, err error) {
+	var (
+		source               string
+		underlyingDriverName = "oracle"
+	)
+
+	options := map[string]string{
+		"CONNECTION TIMEOUT": "60",
+		"PREFETCH_ROWS":      "25",
+	}
+
+	if config.Debug {
+		options["TRACE FILE"] = "oracle_trace.log"
+	}
+	// [username:[password]@]host[:port][/service_name][?param1=value1&...&paramN=valueN]
+	if config.Link != "" {
+		// ============================================================================
+		// Deprecated from v2.2.0.
+		// ============================================================================
+		source = config.Link
+		// Custom changing the schema in runtime.
+		if config.Name != "" {
+			source, _ = gregex.ReplaceString(`@(.+?)/([\w\.\-]+)+`, "@$1/"+config.Name, source)
+		}
+	} else {
+		source = gora.BuildUrl(
+			config.Host, gconv.Int(config.Port), config.Name, config.User, config.Pass, options,
+		)
+	}
+
+	if db, err = sql.Open(underlyingDriverName, source); err != nil {
+		err = gerror.WrapCodef(
+			gcode.CodeDbOperationError, err,
+			`sql.Open failed for driver "%s" by source "%s"`, underlyingDriverName, source,
+		)
+		return nil, err
+	}
+	return
+}

+ 2 - 0
opms_libary/go.mod

@@ -5,10 +5,12 @@ go 1.16
 require (
 	dashoo.cn/common_definition v0.0.0
 	github.com/gogf/gf v1.16.9
+	github.com/lenaten/hl7 v0.0.0-20181009090854-63c5c49a56d9 // indirect
 	github.com/mojocn/base64Captcha v1.3.5
 	github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e // indirect
 	github.com/rcrowley/go-metrics v0.0.0-20201227073835-cf1acfcdf475
 	github.com/rpcxio/rpcx-consul v0.0.0-20220730062257-1ff0472e730f
+	github.com/sijms/go-ora/v2 v2.5.31 // indirect
 	github.com/smallnest/rpcx v1.8.0
 	gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f // indirect
 )

+ 4 - 4
opms_libary/plugin/wechat/mp/base/base.go → opms_libary/plugin/wechat/base/base.go

@@ -8,14 +8,14 @@ import (
 	"strings"
 )
 
-//MpBase 微信公众平台,基本类
-type MpBase struct {
+//WechatBase 微信公众平台,基本类
+type WechatBase struct {
 	*context.Context
 }
 
 //HTTPGetWithAccessToken 微信公众平台中,自动加上access_token变量的GET调用,
 //如果失败,会清空AccessToken cache, 再试一次
-func (c *MpBase) HTTPGetWithAccessToken(url string) (resp []byte, err error) {
+func (c *WechatBase) HTTPGetWithAccessToken(url string) (resp []byte, err error) {
 	retry := 1
 Do:
 	var accessToken string
@@ -53,7 +53,7 @@ Do:
 }
 
 //HTTPPostJSONWithAccessToken post json 自动加上access token, 并retry
-func (c *MpBase) HTTPPostJSONWithAccessToken(url string, obj interface{}) (resp []byte, err error) {
+func (c *WechatBase) HTTPPostJSONWithAccessToken(url string, obj interface{}) (resp []byte, err error) {
 	retry := 1
 Do:
 	var accessToken string

+ 11 - 0
opms_libary/plugin/wechat/client.go

@@ -62,6 +62,17 @@ func (wc *ClientImpl) MpClient() (media *Media, err error) {
 	return
 }
 
+//MiniClient 公众平台
+func (wc *ClientImpl) MiniClient() (media *Mini, err error) {
+	err = wc.checkCfgBase()
+	if err != nil {
+		return
+	}
+	media = NewMini()
+	media.ClientImpl = wc
+	return
+}
+
 //checkCfgBase 检查配置基本信息
 func (wc *ClientImpl) checkCfgBase() (err error) {
 	if wc.Context.AppID == "" {

+ 18 - 0
opms_libary/plugin/wechat/mini.go

@@ -0,0 +1,18 @@
+package wechat
+
+import (
+	"dashoo.cn/opms_libary/plugin/wechat/mini/message"
+)
+
+type Mini struct {
+	*ClientImpl
+}
+
+func NewMini() *Mini {
+	return &Mini{}
+}
+
+// GetMessage 模板消息接口
+func (c *Media) GetMessage() *message.MiniMessage {
+	return message.NewMiniMessage(c.Context)
+}

+ 57 - 0
opms_libary/plugin/wechat/mini/message/consts.go

@@ -0,0 +1,57 @@
+package message
+
+import "encoding/xml"
+
+// MsgType 基本消息类型
+type MsgType string
+
+// EventType 事件类型
+type EventType string
+
+// InfoType 第三方平台授权事件类型
+type InfoType string
+
+const (
+	// MsgTypeText 文本消息
+	MsgTypeText MsgType = "text"
+	// MsgTypeImage 图片消息
+	MsgTypeImage = "image"
+	// MsgTypeLink 图文链接
+	MsgTypeLink = "link"
+	// MsgTypeMiniProgramPage 小程序卡片
+	MsgTypeMiniProgramPage = "miniprogrampage"
+)
+
+// CommonToken 消息中通用的结构
+type CommonToken struct {
+	XMLName      xml.Name `xml:"xml"`
+	ToUserName   string   `xml:"ToUserName"`
+	FromUserName string   `xml:"FromUserName"`
+	CreateTime   int64    `xml:"CreateTime"`
+	MsgType      MsgType  `xml:"MsgType"`
+}
+
+// MiniProgramMixMessage 小程序回调的消息结构
+type MiniProgramMixMessage struct {
+	CommonToken
+
+	MsgID int64 `xml:"MsgId"`
+
+	// 文本消息
+	Content string `xml:"Content"`
+
+	// 图片消息
+	PicURL  string `xml:"PicUrl"`
+	MediaID string `xml:"MediaId"`
+
+	// 小程序卡片消息
+	Title        string `xml:"Title"`
+	AppID        string `xml:"AppId"`
+	PagePath     string `xml:"PagePath"`
+	ThumbURL     string `xml:"ThumbUrl"`
+	ThumbMediaID string `xml:"ThumbMediaId"`
+
+	// 进入会话事件
+	Event       string `xml:"Event"`
+	SessionFrom string `xml:"SessionFrom"`
+}

+ 125 - 0
opms_libary/plugin/wechat/mini/message/message.go

@@ -0,0 +1,125 @@
+package message
+
+import (
+	"dashoo.cn/opms_libary/plugin/wechat/base"
+	"dashoo.cn/opms_libary/plugin/wechat/context"
+	"encoding/json"
+)
+
+const (
+	customerSendMessage = "https://api.weixin.qq.com/cgi-bin/message/custom/send"
+)
+
+// MiniMessage 消息管理者,可以发送消息
+type MiniMessage struct {
+	base.WechatBase
+}
+
+// NewMiniMessage 实例化消息管理者
+func NewMiniMessage(context *context.Context) *MiniMessage {
+	msg := new(MiniMessage)
+	msg.Context = context
+	return msg
+}
+
+// MediaText 文本消息的文字
+type MediaText struct {
+	Content string `json:"content"`
+}
+
+// MediaResource  消息使用的临时素材id
+type MediaResource struct {
+	MediaID string `json:"media_id"`
+}
+
+// MediaMiniprogrampage 小程序卡片
+type MediaMiniprogrampage struct {
+	Title        string `json:"title"`
+	Appid        string `json:"appid"`
+	Pagepath     string `json:"pagepath"`
+	ThumbMediaID string `json:"thumb_media_id"`
+}
+
+// MediaLink 发送图文链接
+type MediaLink struct {
+	Title       string `json:"title"`
+	Description string `json:"description"`
+	URL         string `json:"url"`
+	ThumbURL    string `json:"thumb_url"`
+}
+
+// CustomerMessage  客服消息
+type CustomerMessage struct {
+	ToUser          string                `json:"touser"`                    // 接受者OpenID
+	Msgtype         MsgType               `json:"msgtype"`                   // 客服消息类型
+	Text            *MediaText            `json:"text,omitempty"`            // 可选
+	Image           *MediaResource        `json:"image,omitempty"`           // 可选
+	Link            *MediaLink            `json:"link,omitempty"`            // 可选
+	Miniprogrampage *MediaMiniprogrampage `json:"miniprogrampage,omitempty"` // 可选
+}
+
+// NewTextMessage 文本消息结构体构造方法
+func NewTextMessage(toUser, text string) *CustomerMessage {
+	return &CustomerMessage{
+		ToUser:  toUser,
+		Msgtype: MsgTypeText,
+		Text: &MediaText{
+			Content: text,
+		},
+	}
+}
+
+// NewImgMessage 图片消息的构造方法
+func NewImgMessage(toUser, mediaID string) *CustomerMessage {
+	return &CustomerMessage{
+		ToUser:  toUser,
+		Msgtype: MsgTypeImage,
+		Image: &MediaResource{
+			MediaID: mediaID,
+		},
+	}
+}
+
+// NewLinkMessage 图文链接消息的构造方法
+func NewLinkMessage(toUser, title, description, url, thumbURL string) *CustomerMessage {
+	return &CustomerMessage{
+		ToUser:  toUser,
+		Msgtype: MsgTypeLink,
+		Link: &MediaLink{
+			Title:       title,
+			Description: description,
+			URL:         url,
+			ThumbURL:    thumbURL,
+		},
+	}
+}
+
+// NewMiniprogrampageMessage 小程序卡片消息的构造方法
+func NewMiniprogrampageMessage(toUser, title, pagepath, thumbMediaID string) *CustomerMessage {
+	return &CustomerMessage{
+		ToUser:  toUser,
+		Msgtype: MsgTypeMiniProgramPage,
+		Miniprogrampage: &MediaMiniprogrampage{
+			Title:        title,
+			Pagepath:     pagepath,
+			ThumbMediaID: thumbMediaID,
+		},
+	}
+}
+
+// Send 发送客服消息
+func (m *MiniMessage) Send(msg *CustomerMessage) (err error) {
+	response, err := m.HTTPPostJSONWithAccessToken(customerSendMessage, msg)
+	if err != nil {
+		return err
+	}
+	var result context.WxError
+	err = json.Unmarshal(response, &result)
+	if err != nil {
+		return
+	}
+	if result.Code != 0 {
+		return &result
+	}
+	return nil
+}

+ 2 - 3
opms_libary/plugin/wechat/mp/account/qrcode.go

@@ -1,9 +1,8 @@
 package account
 
 import (
+	"dashoo.cn/opms_libary/plugin/wechat/base"
 	"dashoo.cn/opms_libary/plugin/wechat/context"
-	"dashoo.cn/opms_libary/plugin/wechat/mp/base"
-
 	"encoding/json"
 	"errors"
 	"fmt"
@@ -17,7 +16,7 @@ const (
 
 //Qrcode 带参数的二维码
 type Qrcode struct {
-	base.MpBase
+	base.WechatBase
 }
 
 //NewQrcode 实例化

+ 2 - 2
opms_libary/plugin/wechat/mp/material/material.go

@@ -1,8 +1,8 @@
 package material
 
 import (
+	"dashoo.cn/opms_libary/plugin/wechat/base"
 	"dashoo.cn/opms_libary/plugin/wechat/context"
-	"dashoo.cn/opms_libary/plugin/wechat/mp/base"
 	"encoding/json"
 )
 
@@ -14,7 +14,7 @@ const (
 
 //Material 素材管理
 type Material struct {
-	base.MpBase
+	base.WechatBase
 }
 
 //NewMaterial init

+ 2 - 2
opms_libary/plugin/wechat/mp/menu/menu.go

@@ -1,8 +1,8 @@
 package menu
 
 import (
+	"dashoo.cn/opms_libary/plugin/wechat/base"
 	"dashoo.cn/opms_libary/plugin/wechat/context"
-	"dashoo.cn/opms_libary/plugin/wechat/mp/base"
 	"encoding/json"
 )
 
@@ -18,7 +18,7 @@ const (
 
 //Menu struct
 type Menu struct {
-	base.MpBase
+	base.WechatBase
 }
 
 //reqMenu 设置菜单请求数据

+ 2 - 2
opms_libary/plugin/wechat/mp/template/template.go

@@ -1,8 +1,8 @@
 package template
 
 import (
+	"dashoo.cn/opms_libary/plugin/wechat/base"
 	"dashoo.cn/opms_libary/plugin/wechat/context"
-	"dashoo.cn/opms_libary/plugin/wechat/mp/base"
 	"encoding/json"
 )
 
@@ -17,7 +17,7 @@ const (
 
 //Template 模板消息
 type Template struct {
-	base.MpBase
+	base.WechatBase
 }
 
 //NewTemplate 实例化

+ 2 - 2
opms_libary/plugin/wechat/mp/user/user.go

@@ -1,8 +1,8 @@
 package user
 
 import (
+	"dashoo.cn/opms_libary/plugin/wechat/base"
 	"dashoo.cn/opms_libary/plugin/wechat/context"
-	"dashoo.cn/opms_libary/plugin/wechat/mp/base"
 	"encoding/json"
 	"fmt"
 )
@@ -13,7 +13,7 @@ const (
 
 //User 用户管理
 type User struct {
-	base.MpBase
+	base.WechatBase
 }
 
 //NewUser 实例化