mirror of
https://github.com/silenceper/wechat.git
synced 2026-02-23 13:42:25 +08:00
群发消息接口 (#259)
* 添加TODO:待完善接口 * 【模板消息】将message.DataItem改为message.TemplateDataItem * 【群发消息】基本框架 * 群发消息-基本方法 * fix golint * fix:SendWxCard log
This commit is contained in:
16
cache/memcache_test.go
vendored
16
cache/memcache_test.go
vendored
@@ -3,6 +3,9 @@ package cache
|
|||||||
import (
|
import (
|
||||||
"testing"
|
"testing"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"github.com/bradfitz/gomemcache/memcache"
|
||||||
|
"github.com/stretchr/testify/assert"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestMemcache(t *testing.T) {
|
func TestMemcache(t *testing.T) {
|
||||||
@@ -16,13 +19,22 @@ func TestMemcache(t *testing.T) {
|
|||||||
if !mem.IsExist("username") {
|
if !mem.IsExist("username") {
|
||||||
t.Error("IsExist Error")
|
t.Error("IsExist Error")
|
||||||
}
|
}
|
||||||
|
exists := mem.IsExist("unknown-key")
|
||||||
|
assert.Equal(t, false, exists)
|
||||||
|
|
||||||
name := mem.Get("username").(string)
|
name := mem.Get("username").(string)
|
||||||
if name != "silenceper" {
|
if name != "" {
|
||||||
t.Error("get Error")
|
if name != "silenceper" {
|
||||||
|
t.Error("get Error")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
data := mem.Get("unknown-key")
|
||||||
|
assert.Nil(t, data)
|
||||||
|
|
||||||
if err = mem.Delete("username"); err != nil {
|
if err = mem.Delete("username"); err != nil {
|
||||||
t.Errorf("delete Error , err=%v", err)
|
t.Errorf("delete Error , err=%v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
err = mem.Delete("unknown-key")
|
||||||
|
assert.Equal(t, memcache.ErrCacheMiss, err)
|
||||||
}
|
}
|
||||||
|
|||||||
1
cache/redis_test.go
vendored
1
cache/redis_test.go
vendored
@@ -10,6 +10,7 @@ func TestRedis(t *testing.T) {
|
|||||||
Host: "127.0.0.1:6379",
|
Host: "127.0.0.1:6379",
|
||||||
}
|
}
|
||||||
redis := NewRedis(opts)
|
redis := NewRedis(opts)
|
||||||
|
redis.SetConn(redis.conn)
|
||||||
var err error
|
var err error
|
||||||
timeoutDuration := 1 * time.Second
|
timeoutDuration := 1 * time.Second
|
||||||
|
|
||||||
|
|||||||
3
go.sum
3
go.sum
@@ -4,6 +4,7 @@ github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8
|
|||||||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||||
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
||||||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||||
|
github.com/fatih/structs v1.1.0 h1:Q7juDM0QtcnhCpeyLGQKyg4TOIghuNXrkL32pHAUMxo=
|
||||||
github.com/fatih/structs v1.1.0/go.mod h1:9NiDSp5zOcgEDl+j00MP/WkGVPOlPRLejGD8Ga6PJ7M=
|
github.com/fatih/structs v1.1.0/go.mod h1:9NiDSp5zOcgEDl+j00MP/WkGVPOlPRLejGD8Ga6PJ7M=
|
||||||
github.com/gomodule/redigo v1.8.1 h1:Abmo0bI7Xf0IhdIPc7HZQzZcShdnmxeoVuDDtIQp8N8=
|
github.com/gomodule/redigo v1.8.1 h1:Abmo0bI7Xf0IhdIPc7HZQzZcShdnmxeoVuDDtIQp8N8=
|
||||||
github.com/gomodule/redigo v1.8.1/go.mod h1:P9dn9mFrCBvWhGE1wpxx6fgq7BAeLBk+UUUzlpkBYO0=
|
github.com/gomodule/redigo v1.8.1/go.mod h1:P9dn9mFrCBvWhGE1wpxx6fgq7BAeLBk+UUUzlpkBYO0=
|
||||||
@@ -11,10 +12,12 @@ github.com/h2non/parth v0.0.0-20190131123155-b4df798d6542 h1:2VTzZjLZBgl62/EtslC
|
|||||||
github.com/h2non/parth v0.0.0-20190131123155-b4df798d6542/go.mod h1:Ow0tF8D4Kplbc8s8sSb3V2oUCygFHVp8gC3Dn6U4MNI=
|
github.com/h2non/parth v0.0.0-20190131123155-b4df798d6542/go.mod h1:Ow0tF8D4Kplbc8s8sSb3V2oUCygFHVp8gC3Dn6U4MNI=
|
||||||
github.com/konsorten/go-windows-terminal-sequences v1.0.3 h1:CE8S1cTafDpPvMhIxNJKvHsGVBgn1xWYf1NbHQhywc8=
|
github.com/konsorten/go-windows-terminal-sequences v1.0.3 h1:CE8S1cTafDpPvMhIxNJKvHsGVBgn1xWYf1NbHQhywc8=
|
||||||
github.com/konsorten/go-windows-terminal-sequences v1.0.3/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
|
github.com/konsorten/go-windows-terminal-sequences v1.0.3/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
|
||||||
|
github.com/nbio/st v0.0.0-20140626010706-e9e8d9816f32 h1:W6apQkHrMkS0Muv8G/TipAy/FJl/rCYT0+EuS8+Z0z4=
|
||||||
github.com/nbio/st v0.0.0-20140626010706-e9e8d9816f32/go.mod h1:9wM+0iRr9ahx58uYLpLIr5fm8diHn0JbqRycJi6w0Ms=
|
github.com/nbio/st v0.0.0-20140626010706-e9e8d9816f32/go.mod h1:9wM+0iRr9ahx58uYLpLIr5fm8diHn0JbqRycJi6w0Ms=
|
||||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||||
github.com/sirupsen/logrus v1.6.0 h1:UBcNElsrwanuuMsnGSlYmtmgbb23qDR5dG+6X6Oo89I=
|
github.com/sirupsen/logrus v1.6.0 h1:UBcNElsrwanuuMsnGSlYmtmgbb23qDR5dG+6X6Oo89I=
|
||||||
github.com/sirupsen/logrus v1.6.0/go.mod h1:7uNnSEd1DgxDLC74fIahvMZmmYsHGZGEOFrfsX/uA88=
|
github.com/sirupsen/logrus v1.6.0/go.mod h1:7uNnSEd1DgxDLC74fIahvMZmmYsHGZGEOFrfsX/uA88=
|
||||||
|
github.com/spf13/cast v1.3.1 h1:nFm6S0SMdyzrzcmThSipiEubIDy8WEXKNZ0UOgiRpng=
|
||||||
github.com/spf13/cast v1.3.1/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE=
|
github.com/spf13/cast v1.3.1/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE=
|
||||||
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||||
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
|
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
|
||||||
|
|||||||
279
officialaccount/broadcast/broadcast.go
Normal file
279
officialaccount/broadcast/broadcast.go
Normal file
@@ -0,0 +1,279 @@
|
|||||||
|
package broadcast
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
|
||||||
|
"github.com/silenceper/wechat/v2/officialaccount/context"
|
||||||
|
"github.com/silenceper/wechat/v2/util"
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
sendURLByTag = "https://api.weixin.qq.com/cgi-bin/message/mass/sendall"
|
||||||
|
sendURLByOpenID = "https://api.weixin.qq.com/cgi-bin/message/mass/send"
|
||||||
|
deleteSendURL ="https://api.weixin.qq.com/cgi-bin/message/mass/delete"
|
||||||
|
)
|
||||||
|
|
||||||
|
//MsgType 发送消息类型
|
||||||
|
type MsgType string
|
||||||
|
|
||||||
|
const (
|
||||||
|
//MsgTypeNews 图文消息
|
||||||
|
MsgTypeNews MsgType = "mpnews"
|
||||||
|
//MsgTypeText 文本
|
||||||
|
MsgTypeText MsgType = "text"
|
||||||
|
//MsgTypeVoice 语音/音频
|
||||||
|
MsgTypeVoice MsgType = "voice"
|
||||||
|
//MsgTypeImage 图片
|
||||||
|
MsgTypeImage MsgType = "image"
|
||||||
|
//MsgTypeVideo 视频
|
||||||
|
MsgTypeVideo MsgType = "mpvideo"
|
||||||
|
//MsgTypeWxCard 卡券
|
||||||
|
MsgTypeWxCard MsgType = "wxcard"
|
||||||
|
)
|
||||||
|
|
||||||
|
//Broadcast 群发消息
|
||||||
|
type Broadcast struct {
|
||||||
|
*context.Context
|
||||||
|
}
|
||||||
|
|
||||||
|
//NewBroadcast new
|
||||||
|
func NewBroadcast(ctx *context.Context) *Broadcast {
|
||||||
|
return &Broadcast{ctx}
|
||||||
|
}
|
||||||
|
|
||||||
|
//User 发送的用户
|
||||||
|
type User struct {
|
||||||
|
TagID int64
|
||||||
|
OpenID []string
|
||||||
|
}
|
||||||
|
|
||||||
|
//Result 群发返回结果
|
||||||
|
type Result struct {
|
||||||
|
util.CommonError
|
||||||
|
MsgID int64 `json:"msg_id"`
|
||||||
|
MsgDataID int64 `json:"msg_data_id"`
|
||||||
|
}
|
||||||
|
|
||||||
|
//sendRequest 发送请求的数据
|
||||||
|
type sendRequest struct {
|
||||||
|
//根据tag获全部发送
|
||||||
|
Filter map[string]interface{} `json:"filter,omitempty"`
|
||||||
|
//根据OpenID发送
|
||||||
|
ToUser interface{} `json:"touser,omitempty"`
|
||||||
|
//发送文本
|
||||||
|
Text map[string]interface{} `json:"text,omitempty"`
|
||||||
|
//发送图文消息
|
||||||
|
Mpnews map[string]interface{} `json:"mpnews,omitempty"`
|
||||||
|
//发送语音
|
||||||
|
Voice map[string]interface{} `json:"voice,omitempty"`
|
||||||
|
//发送图片
|
||||||
|
Images *Image `json:"images,omitempty"`
|
||||||
|
//发送卡券
|
||||||
|
WxCard map[string]interface{} `json:"wxcard,omitempty"`
|
||||||
|
MsgType MsgType `json:"msgtype"`
|
||||||
|
SendIgnoreReprint int32 `json:"send_ignore_reprint,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
//Image 发送图片
|
||||||
|
type Image struct{
|
||||||
|
MediaIDs []string `json:"media_ids"`
|
||||||
|
Recommend string `json:"recommend"`
|
||||||
|
NeedOpenComment int32 `json:"need_open_comment"`
|
||||||
|
OnlyFansCanComment int32 `json:"only_fans_can_comment"`
|
||||||
|
}
|
||||||
|
|
||||||
|
//SendText 群发文本
|
||||||
|
//user 为nil,表示全员发送
|
||||||
|
//&User{TagID:2} 根据tag发送
|
||||||
|
//&User{OpenID:[]string("xxx","xxx")} 根据openid发送
|
||||||
|
func (broadcast *Broadcast) SendText(user *User, content string) (*Result, error) {
|
||||||
|
ak, err := broadcast.GetAccessToken()
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
req := &sendRequest{
|
||||||
|
ToUser: nil,
|
||||||
|
MsgType: MsgTypeText,
|
||||||
|
}
|
||||||
|
req.Text=map[string]interface{}{
|
||||||
|
"content":content,
|
||||||
|
}
|
||||||
|
req,sendURL:=broadcast.chooseTagOrOpenID(user,req)
|
||||||
|
url := fmt.Sprintf("%s?access_token=%s", sendURL, ak)
|
||||||
|
data, err := util.PostJSON(url, req)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
res := &Result{}
|
||||||
|
err = util.DecodeWithError(data, res, "SendText")
|
||||||
|
return res, err
|
||||||
|
}
|
||||||
|
|
||||||
|
//SendNews 发送图文
|
||||||
|
func (broadcast *Broadcast) SendNews(user *User, mediaID string,ignoreReprint bool) (*Result, error) {
|
||||||
|
ak, err := broadcast.GetAccessToken()
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
req := &sendRequest{
|
||||||
|
ToUser: nil,
|
||||||
|
MsgType: MsgTypeNews,
|
||||||
|
}
|
||||||
|
if ignoreReprint{
|
||||||
|
req.SendIgnoreReprint=1
|
||||||
|
}
|
||||||
|
req.Mpnews=map[string]interface{}{
|
||||||
|
"media_id":mediaID,
|
||||||
|
}
|
||||||
|
req,sendURL:=broadcast.chooseTagOrOpenID(user,req)
|
||||||
|
url := fmt.Sprintf("%s?access_token=%s", sendURL, ak)
|
||||||
|
data, err := util.PostJSON(url, req)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
res := &Result{}
|
||||||
|
err = util.DecodeWithError(data, res, "SendNews")
|
||||||
|
return res, err
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//SendVoice 发送语音
|
||||||
|
func (broadcast *Broadcast) SendVoice(user *User, mediaID string) (*Result, error) {
|
||||||
|
ak, err := broadcast.GetAccessToken()
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
req := &sendRequest{
|
||||||
|
ToUser: nil,
|
||||||
|
MsgType: MsgTypeVoice,
|
||||||
|
}
|
||||||
|
req.Voice=map[string]interface{}{
|
||||||
|
"media_id":mediaID,
|
||||||
|
}
|
||||||
|
req,sendURL:=broadcast.chooseTagOrOpenID(user,req)
|
||||||
|
url := fmt.Sprintf("%s?access_token=%s", sendURL, ak)
|
||||||
|
data, err := util.PostJSON(url, req)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
res := &Result{}
|
||||||
|
err = util.DecodeWithError(data, res, "SendVoice")
|
||||||
|
return res, err
|
||||||
|
}
|
||||||
|
|
||||||
|
//SendImage 发送图片
|
||||||
|
func (broadcast *Broadcast) SendImage(user *User, images *Image) (*Result, error) {
|
||||||
|
ak, err := broadcast.GetAccessToken()
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
req := &sendRequest{
|
||||||
|
ToUser: nil,
|
||||||
|
MsgType: MsgTypeImage,
|
||||||
|
}
|
||||||
|
req.Images=images
|
||||||
|
req,sendURL:=broadcast.chooseTagOrOpenID(user,req)
|
||||||
|
url := fmt.Sprintf("%s?access_token=%s", sendURL, ak)
|
||||||
|
data, err := util.PostJSON(url, req)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
res := &Result{}
|
||||||
|
err = util.DecodeWithError(data, res, "SendImage")
|
||||||
|
return res, err
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//SendVideo 发送视频
|
||||||
|
func (broadcast *Broadcast) SendVideo(user *User, mediaID string,title,description string) (*Result, error) {
|
||||||
|
ak, err := broadcast.GetAccessToken()
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
req := &sendRequest{
|
||||||
|
ToUser: nil,
|
||||||
|
MsgType: MsgTypeVideo,
|
||||||
|
}
|
||||||
|
req.Voice=map[string]interface{}{
|
||||||
|
"media_id":mediaID,
|
||||||
|
"title":title,
|
||||||
|
"description":description,
|
||||||
|
}
|
||||||
|
req,sendURL:=broadcast.chooseTagOrOpenID(user,req)
|
||||||
|
url := fmt.Sprintf("%s?access_token=%s", sendURL, ak)
|
||||||
|
data, err := util.PostJSON(url, req)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
res := &Result{}
|
||||||
|
err = util.DecodeWithError(data, res, "SendVideo")
|
||||||
|
return res, err
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//SendWxCard 发送卡券
|
||||||
|
func (broadcast *Broadcast) SendWxCard(user *User, cardID string) (*Result, error) {
|
||||||
|
ak, err := broadcast.GetAccessToken()
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
req := &sendRequest{
|
||||||
|
ToUser: nil,
|
||||||
|
MsgType: MsgTypeWxCard,
|
||||||
|
}
|
||||||
|
req.WxCard=map[string]interface{}{
|
||||||
|
"card_id":cardID,
|
||||||
|
}
|
||||||
|
req,sendURL:=broadcast.chooseTagOrOpenID(user,req)
|
||||||
|
url := fmt.Sprintf("%s?access_token=%s", sendURL, ak)
|
||||||
|
data, err := util.PostJSON(url, req)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
res := &Result{}
|
||||||
|
err = util.DecodeWithError(data, res, "SendWxCard")
|
||||||
|
return res, err
|
||||||
|
}
|
||||||
|
//Delete 删除群发消息
|
||||||
|
func (broadcast *Broadcast) Delete(msgID int64 ,articleIDx int64) error {
|
||||||
|
ak, err := broadcast.GetAccessToken()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
req := map[string]interface{}{
|
||||||
|
"msg_id": msgID,
|
||||||
|
"article_idx": articleIDx,
|
||||||
|
}
|
||||||
|
url := fmt.Sprintf("%s?access_token=%s", deleteSendURL, ak)
|
||||||
|
data, err := util.PostJSON(url, req)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return util.DecodeWithCommonError(data, "Delete")
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//TODO 发送预览,群发消息状态,发送速度
|
||||||
|
|
||||||
|
func (broadcast *Broadcast) chooseTagOrOpenID(user *User,req *sendRequest)(ret *sendRequest,url string){
|
||||||
|
sendURL:=""
|
||||||
|
if user == nil {
|
||||||
|
req.Filter=map[string]interface{}{
|
||||||
|
"is_to_all":true,
|
||||||
|
}
|
||||||
|
sendURL=sendURLByTag
|
||||||
|
} else {
|
||||||
|
if user.TagID != 0 {
|
||||||
|
req.Filter=map[string]interface{}{
|
||||||
|
"is_to_all":false,
|
||||||
|
"tag_id":user.TagID,
|
||||||
|
}
|
||||||
|
sendURL=sendURLByTag
|
||||||
|
}
|
||||||
|
if len(user.OpenID) != 0 {
|
||||||
|
req.ToUser = user.OpenID
|
||||||
|
sendURL=sendURLByOpenID
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return req,sendURL
|
||||||
|
}
|
||||||
@@ -24,13 +24,13 @@ func NewTemplate(context *context.Context) *Template {
|
|||||||
return tpl
|
return tpl
|
||||||
}
|
}
|
||||||
|
|
||||||
//Message 发送的模板消息内容
|
//TemplateMessage 发送的模板消息内容
|
||||||
type Message struct {
|
type TemplateMessage struct {
|
||||||
ToUser string `json:"touser"` // 必须, 接受者OpenID
|
ToUser string `json:"touser"` // 必须, 接受者OpenID
|
||||||
TemplateID string `json:"template_id"` // 必须, 模版ID
|
TemplateID string `json:"template_id"` // 必须, 模版ID
|
||||||
URL string `json:"url,omitempty"` // 可选, 用户点击后跳转的URL, 该URL必须处于开发者在公众平台网站中设置的域中
|
URL string `json:"url,omitempty"` // 可选, 用户点击后跳转的URL, 该URL必须处于开发者在公众平台网站中设置的域中
|
||||||
Color string `json:"color,omitempty"` // 可选, 整个消息的颜色, 可以不设置
|
Color string `json:"color,omitempty"` // 可选, 整个消息的颜色, 可以不设置
|
||||||
Data map[string]*DataItem `json:"data"` // 必须, 模板数据
|
Data map[string]*TemplateDataItem `json:"data"` // 必须, 模板数据
|
||||||
|
|
||||||
MiniProgram struct {
|
MiniProgram struct {
|
||||||
AppID string `json:"appid"` //所需跳转到的小程序appid(该小程序appid必须与发模板消息的公众号是绑定关联关系)
|
AppID string `json:"appid"` //所需跳转到的小程序appid(该小程序appid必须与发模板消息的公众号是绑定关联关系)
|
||||||
@@ -38,8 +38,8 @@ type Message struct {
|
|||||||
} `json:"miniprogram"` //可选,跳转至小程序地址
|
} `json:"miniprogram"` //可选,跳转至小程序地址
|
||||||
}
|
}
|
||||||
|
|
||||||
//DataItem 模版内某个 .DATA 的值
|
//TemplateDataItem 模版内某个 .DATA 的值
|
||||||
type DataItem struct {
|
type TemplateDataItem struct {
|
||||||
Value string `json:"value"`
|
Value string `json:"value"`
|
||||||
Color string `json:"color,omitempty"`
|
Color string `json:"color,omitempty"`
|
||||||
}
|
}
|
||||||
@@ -51,7 +51,7 @@ type resTemplateSend struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
//Send 发送模板消息
|
//Send 发送模板消息
|
||||||
func (tpl *Template) Send(msg *Message) (msgID int64, err error) {
|
func (tpl *Template) Send(msg *TemplateMessage) (msgID int64, err error) {
|
||||||
var accessToken string
|
var accessToken string
|
||||||
accessToken, err = tpl.GetAccessToken()
|
accessToken, err = tpl.GetAccessToken()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ import (
|
|||||||
|
|
||||||
"github.com/silenceper/wechat/v2/credential"
|
"github.com/silenceper/wechat/v2/credential"
|
||||||
"github.com/silenceper/wechat/v2/officialaccount/basic"
|
"github.com/silenceper/wechat/v2/officialaccount/basic"
|
||||||
|
"github.com/silenceper/wechat/v2/officialaccount/broadcast"
|
||||||
"github.com/silenceper/wechat/v2/officialaccount/config"
|
"github.com/silenceper/wechat/v2/officialaccount/config"
|
||||||
"github.com/silenceper/wechat/v2/officialaccount/context"
|
"github.com/silenceper/wechat/v2/officialaccount/context"
|
||||||
"github.com/silenceper/wechat/v2/officialaccount/device"
|
"github.com/silenceper/wechat/v2/officialaccount/device"
|
||||||
@@ -52,7 +53,7 @@ func (officialAccount *OfficialAccount) GetMenu() *menu.Menu {
|
|||||||
return menu.NewMenu(officialAccount.ctx)
|
return menu.NewMenu(officialAccount.ctx)
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetServer 消息管理
|
// GetServer 消息管理:接收事件,被动回复消息管理
|
||||||
func (officialAccount *OfficialAccount) GetServer(req *http.Request, writer http.ResponseWriter) *server.Server {
|
func (officialAccount *OfficialAccount) GetServer(req *http.Request, writer http.ResponseWriter) *server.Server {
|
||||||
srv := server.NewServer(officialAccount.ctx)
|
srv := server.NewServer(officialAccount.ctx)
|
||||||
srv.Request = req
|
srv.Request = req
|
||||||
@@ -94,3 +95,9 @@ func (officialAccount *OfficialAccount) GetTemplate() *message.Template {
|
|||||||
func (officialAccount *OfficialAccount) GetDevice() *device.Device {
|
func (officialAccount *OfficialAccount) GetDevice() *device.Device {
|
||||||
return device.NewDevice(officialAccount.ctx)
|
return device.NewDevice(officialAccount.ctx)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//GetBroadcast 群发消息
|
||||||
|
//TODO 待完善
|
||||||
|
func (officialAccount *OfficialAccount) GetBroadcast() *broadcast.Broadcast {
|
||||||
|
return broadcast.NewBroadcast(officialAccount.ctx)
|
||||||
|
}
|
||||||
|
|||||||
@@ -44,7 +44,7 @@ type Info struct {
|
|||||||
UnionID string `json:"unionid"`
|
UnionID string `json:"unionid"`
|
||||||
Remark string `json:"remark"`
|
Remark string `json:"remark"`
|
||||||
GroupID int32 `json:"groupid"`
|
GroupID int32 `json:"groupid"`
|
||||||
TagidList []int32 `json:"tagid_list"`
|
TagIDList []int32 `json:"tagid_list"`
|
||||||
SubscribeScene string `json:"subscribe_scene"`
|
SubscribeScene string `json:"subscribe_scene"`
|
||||||
QrScene int `json:"qr_scene"`
|
QrScene int `json:"qr_scene"`
|
||||||
QrSceneStr string `json:"qr_scene_str"`
|
QrSceneStr string `json:"qr_scene_str"`
|
||||||
|
|||||||
34
openplatform/account/account.go
Normal file
34
openplatform/account/account.go
Normal file
@@ -0,0 +1,34 @@
|
|||||||
|
package account
|
||||||
|
|
||||||
|
import "github.com/silenceper/wechat/v2/openplatform/context"
|
||||||
|
|
||||||
|
//Account 开放平台张哈管理
|
||||||
|
//TODO 实现方法
|
||||||
|
type Account struct {
|
||||||
|
*context.Context
|
||||||
|
}
|
||||||
|
|
||||||
|
//NewAccount new
|
||||||
|
func NewAccount(ctx *context.Context) *Account {
|
||||||
|
return &Account{ctx}
|
||||||
|
}
|
||||||
|
|
||||||
|
//Create 创建开放平台帐号并绑定公众号/小程序
|
||||||
|
func (account *Account) Create(appID string) (string, error) {
|
||||||
|
return "", nil
|
||||||
|
}
|
||||||
|
|
||||||
|
//Bind 将公众号/小程序绑定到开放平台帐号下
|
||||||
|
func (account *Account) Bind(appID string) error {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
//Unbind 将公众号/小程序从开放平台帐号下解绑
|
||||||
|
func (account *Account) Unbind(appID string, openAppID string) error {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
//Get 获取公众号/小程序所绑定的开放平台帐号
|
||||||
|
func (account *Account) Get(appID string) (string, error) {
|
||||||
|
return "", nil
|
||||||
|
}
|
||||||
@@ -14,7 +14,10 @@ const (
|
|||||||
queryAuthURL = "https://api.weixin.qq.com/cgi-bin/component/api_query_auth?component_access_token=%s"
|
queryAuthURL = "https://api.weixin.qq.com/cgi-bin/component/api_query_auth?component_access_token=%s"
|
||||||
refreshTokenURL = "https://api.weixin.qq.com/cgi-bin/component/api_authorizer_token?component_access_token=%s"
|
refreshTokenURL = "https://api.weixin.qq.com/cgi-bin/component/api_authorizer_token?component_access_token=%s"
|
||||||
getComponentInfoURL = "https://api.weixin.qq.com/cgi-bin/component/api_get_authorizer_info?component_access_token=%s"
|
getComponentInfoURL = "https://api.weixin.qq.com/cgi-bin/component/api_get_authorizer_info?component_access_token=%s"
|
||||||
getComponentConfigURL = "https://api.weixin.qq.com/cgi-bin/component/api_get_authorizer_option?component_access_token=%s"
|
//TODO 获取授权方选项信息
|
||||||
|
getComponentConfigURL = "https://api.weixin.qq.com/cgi-bin/component/api_get_authorizer_option?component_access_token=%s"
|
||||||
|
//TODO 获取已授权的账号信息
|
||||||
|
getuthorizerListURL = "POST https://api.weixin.qq.com/cgi-bin/component/api_get_authorizer_list?component_access_token=%s"
|
||||||
)
|
)
|
||||||
|
|
||||||
// ComponentAccessToken 第三方平台
|
// ComponentAccessToken 第三方平台
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
package openplatform
|
package openplatform
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"github.com/silenceper/wechat/v2/openplatform/account"
|
||||||
"github.com/silenceper/wechat/v2/openplatform/config"
|
"github.com/silenceper/wechat/v2/openplatform/config"
|
||||||
"github.com/silenceper/wechat/v2/openplatform/context"
|
"github.com/silenceper/wechat/v2/openplatform/context"
|
||||||
"github.com/silenceper/wechat/v2/openplatform/miniprogram"
|
"github.com/silenceper/wechat/v2/openplatform/miniprogram"
|
||||||
@@ -29,6 +30,12 @@ func (openPlatform *OpenPlatform) GetOfficialAccount(appID string) *officialacco
|
|||||||
}
|
}
|
||||||
|
|
||||||
//GetMiniProgram 小程序代理
|
//GetMiniProgram 小程序代理
|
||||||
func (openPlatform *OpenPlatform) GetMiniProgram(opCtx *context.Context, appID string) *miniprogram.MiniProgram {
|
func (openPlatform *OpenPlatform) GetMiniProgram(appID string) *miniprogram.MiniProgram {
|
||||||
return miniprogram.NewMiniProgram(opCtx, appID)
|
return miniprogram.NewMiniProgram(openPlatform.Context, appID)
|
||||||
|
}
|
||||||
|
|
||||||
|
//GetAccountManager 账号管理
|
||||||
|
//TODO
|
||||||
|
func (openPlatform *OpenPlatform) GetAccountManager() *account.Account {
|
||||||
|
return account.NewAccount(openPlatform.Context)
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user