func (s *Service) Send(ctx context.Context, subject, content string) error {
	for _, userID := range s.userIDs {
		select {
		case <-ctx.Done():
			return ctx.Err()
		default:
			text := fmt.Sprintf("%s\n%s", subject, content)
			err := s.messageManager.Send(message.NewCustomerTextMessage(userID, text))
			if err != nil {
				return errors.Wrapf(err, "failed to send message to WeChat user '%s'", userID)
			}
		}
	}
	return nil
}
Send takes a message subject and a message content and sends them to all previously set users.
package wechat
import (
	"context"
	"fmt"
	"net/http"
	"sync"
	"github.com/pkg/errors"
	"github.com/silenceper/wechat/v2"
	"github.com/silenceper/wechat/v2/cache"
	"github.com/silenceper/wechat/v2/officialaccount/config"
	"github.com/silenceper/wechat/v2/officialaccount/message"
	"github.com/silenceper/wechat/v2/util"
)
type verificationCallbackFunc func(r *http.Request, verified bool)
type Config struct {
	AppID          string
	AppSecret      string
	Token          string
	EncodingAESKey string
	Cache          cache.Cache
}
type wechatMessageManager interface {
	Send(msg *message.CustomerMessage) error
}
type Service struct {
	config         *Config
	messageManager wechatMessageManager
	userIDs        []string
}
func New(cfg *Config) *Service {
	wc := wechat.NewWechat()
	wcCfg := &config.Config{
		AppID:          cfg.AppID,
		AppSecret:      cfg.AppSecret,
		Token:          cfg.Token,
		EncodingAESKey: cfg.EncodingAESKey,
		Cache:          cfg.Cache,
	}
	oa := wc.GetOfficialAccount(wcCfg)
	return &Service{
		config:         cfg,
		messageManager: oa.GetCustomerMessageManager(),
	}
}
func (s *Service) WaitForOneOffVerification(serverURL string, devMode bool, callback verificationCallbackFunc) error {
	srv := &http.Server{Addr: serverURL}
	verificationDone := &sync.WaitGroup{}
	verificationDone.Add(1)
	http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
		query := r.URL.Query()
		echoStr := query.Get("echostr")
		if devMode {
			if callback != nil {
				callback(r, true)
			}
			_, _ = w.Write([]byte(echoStr))
			verificationDone.Done()
			return
		}
		timestamp := query.Get("timestamp")
		nonce := query.Get("nonce")
		suppliedSignature := query.Get("signature")
		computedSignature := util.Signature(s.config.Token, timestamp, nonce)
		if suppliedSignature == computedSignature {
			if callback != nil {
				callback(r, true)
			}
			_, _ = w.Write([]byte(echoStr))
			verificationDone.Done()
			return
		}
		if callback != nil {
			callback(r, false)
		}
	})
	var err error
	go func() {
		if innerErr := srv.ListenAndServe(); innerErr != http.ErrServerClosed {
			err = errors.Wrapf(innerErr, "failed to start verification listener '%s'", serverURL)
		}
	}()
	verificationDone.Wait()
	if innerErr := srv.Shutdown(context.TODO()); innerErr != nil {
		err = errors.Wrap(innerErr, "failed to shutdown verification listerer")
	}
	return err
}
func (s *Service) AddReceivers(userIDs ...string) {
	s.userIDs = append(s.userIDs, userIDs...)
}