weixin

package
v0.12.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Apr 16, 2026 License: MIT Imports: 21 Imported by: 0

Documentation

Index

Constants

View Source
const (
	// DefaultBaseURL is the default iLink API base URL.
	DefaultBaseURL = "https://ilinkai.weixin.qq.com"

	// DefaultCDNBaseURL is the CDN base URL for media upload/download.
	DefaultCDNBaseURL = "https://novac2c.cdn.weixin.qq.com"

	// DefaultChannelVersion is the SDK/client version string.
	DefaultChannelVersion = "1.0.0"
)
View Source
const (
	MessageTypeUser = 1 // USER — incoming message from a WeChat user.
	MessageTypeBot  = 2 // BOT — outgoing message from the bot.
)

Message type constants.

View Source
const (
	MessageStateNew        = 0 // NEW — initial state.
	MessageStateGenerating = 1 // GENERATING — content being generated (not used for sending).
	MessageStateFinish     = 2 // FINISH — final state; always use this for outbound messages.
)

Message state constants.

View Source
const (
	ItemTypeText  = 1
	ItemTypeImage = 2
	ItemTypeVoice = 3
	ItemTypeFile  = 4
	ItemTypeVideo = 5
)

Item type constants.

View Source
const (
	MediaTypeImage = 1
	MediaTypeVideo = 2
	MediaTypeFile  = 3
	MediaTypeVoice = 4
)

Media type constants for getuploadurl.

View Source
const (
	PluginID    = "channel/weixin"
	RuntimeName = "bot"
)

Variables

View Source
var ErrSessionExpired = errors.New("weixin: session expired (ret=-14)")

ErrSessionExpired indicates the iLink session has expired (ret=-14 or errcode=-14).

Functions

func CiphertextSize

func CiphertextSize(rawSize int) int

CiphertextSize returns the AES-128-ECB + PKCS7 ciphertext size for a given raw size. Formula: ceil((rawSize+1)/16) * 16

func DecodeAESKey

func DecodeAESKey(aesKeyB64 string) ([]byte, error)

DecodeAESKey decodes an AES key from the base64 value in CDNMedia.aes_key. It handles two formats:

  • Format A: base64(raw 16 bytes) → decode to 16 bytes, use directly
  • Format B: base64(hex string) → decode to 32 hex chars, hex-decode to 16 bytes

func DecodeConfig

func DecodeConfig(raw map[string]any) (pkgchannel.WeixinConfig, error)

func DecryptAESECB

func DecryptAESECB(ciphertext, key []byte) ([]byte, error)

DecryptAESECB decrypts ciphertext using AES-128-ECB and removes PKCS7 padding.

func DownloadFromCDN

func DownloadFromCDN(cdnBaseURL, encryptedQueryParam string) ([]byte, error)

DownloadFromCDN downloads encrypted data from the WeChat CDN.

func EncryptAESECB

func EncryptAESECB(plaintext, key []byte) ([]byte, error)

EncryptAESECB encrypts plaintext using AES-128-ECB with PKCS7 padding.

func NewWeixinManagedRuntime

func NewWeixinManagedRuntime(deps WeixinRuntimeDeps) pkgplugins.Runtime

func RandomClientID

func RandomClientID(prefix string) string

RandomClientID generates a unique client_id with the given prefix. Format: prefix:timestamp-random

func RandomFileKey

func RandomFileKey() string

RandomFileKey generates a random 16-byte hex string for CDN upload filekey.

func RedactConfig

func RedactConfig(raw map[string]any) map[string]any

func ResolveImageKey

func ResolveImageKey(imageItem *ImageItem) ([]byte, error)

ResolveImageKey determines the AES key for an image item. Precedence: image_item.aeskey (hex) > media.aes_key (base64).

func UploadToCDN

func UploadToCDN(cdnBaseURL, uploadParam, filekey string, encrypted []byte) (string, error)

UploadToCDN uploads encrypted data to the WeChat CDN. Returns the x-encrypted-param response header value.

Types

type BaseInfo

type BaseInfo struct {
	ChannelVersion string `json:"channel_version"`
}

BaseInfo is included in every business POST request body.

type Bot

type Bot struct {
	// contains filtered or unexported fields
}

Bot wraps a WeChat iLink bot with agent pool integration. It implements channel.Channel.

func New

func New(cfg Config, handler channel.Handler) (*Bot, error)

New creates a WeChat iLink bot. Call Start to begin polling.

func (*Bot) Name

func (b *Bot) Name() string

Name returns the channel name. Implements channel.Channel.

func (*Bot) Notify

func (b *Bot) Notify(_ context.Context, n channel.Notification) error

Notify sends a notification message via sendmessage. Implements channel.Channel.

func (*Bot) Platform added in v0.10.0

func (b *Bot) Platform() string

func (*Bot) Start

func (b *Bot) Start(ctx context.Context) error

Start begins long-polling for messages. It blocks until ctx is cancelled.

func (*Bot) Stop

func (b *Bot) Stop()

Stop gracefully shuts down the WeChat bot. Implements channel.Channel.

type CDNMedia

type CDNMedia struct {
	EncryptQueryParam string `json:"encrypt_query_param,omitempty"`
	AESKey            string `json:"aes_key,omitempty"` // base64 encoded
	EncryptType       int    `json:"encrypt_type,omitempty"`
}

CDNMedia is the shared CDN reference for images, voice, files, and videos.

type Client

type Client struct {
	// contains filtered or unexported fields
}

Client is an HTTP client for the iLink Bot API.

func NewClient

func NewClient(baseURL, cdnBaseURL, token string) *Client

NewClient creates a new iLink API client.

func (*Client) GetConfig

func (c *Client) GetConfig(userID, contextToken, channelVersion string) (*GetConfigResponse, error)

GetConfig retrieves the typing_ticket for a user.

func (*Client) GetQRCode

func (c *Client) GetQRCode(skRouteTag string) (*QRCodeResponse, error)

GetQRCode requests a new QR code for login.

func (*Client) GetQRCodeStatus

func (c *Client) GetQRCodeStatus(qrcode, skRouteTag string) (*QRCodeStatusResponse, error)

GetQRCodeStatus polls the QR code scan status.

func (*Client) GetUpdates

func (c *Client) GetUpdates(buf, channelVersion string, timeout time.Duration) (*GetUpdatesResponse, error)

GetUpdates performs a long-poll for new messages. Returns the response including messages, new cursor, and timeout hint.

func (*Client) GetUploadURL

func (c *Client) GetUploadURL(params UploadParams, channelVersion string) (*GetUploadURLResponse, error)

GetUploadURL requests CDN upload parameters for a file.

func (*Client) SendMessage

func (c *Client) SendMessage(msg WeixinMessage, channelVersion string) error

SendMessage sends a message to a user.

func (*Client) SendTyping

func (c *Client) SendTyping(userID, typingTicket string, status int, channelVersion string) error

SendTyping sends or cancels a typing indicator. status=1 starts typing, status=2 cancels.

type Config

type Config struct {
	InstanceID string `json:"-"`
	BotToken   string `json:"bot_token"` // iLink bot_token
	BaseURL    string `json:"base_url"`  // iLink base URL (default: https://ilinkai.weixin.qq.com)
	BotID      string `json:"bot_id"`    // ilink_bot_id
	UserID     string `json:"user_id"`   // ilink_user_id
}

Config holds WeChat iLink bot settings.

type FileItem

type FileItem struct {
	Media    *CDNMedia `json:"media,omitempty"`
	FileName string    `json:"file_name,omitempty"`
	MD5      string    `json:"md5,omitempty"`
	Len      string    `json:"len,omitempty"` // plaintext file size as string
}

FileItem holds file content.

type GetConfigRequest

type GetConfigRequest struct {
	ILinkUserID  string   `json:"ilink_user_id"`
	ContextToken string   `json:"context_token,omitempty"`
	BaseInfo     BaseInfo `json:"base_info"`
}

GetConfigRequest is the request body for getconfig.

type GetConfigResponse

type GetConfigResponse struct {
	Ret          int    `json:"ret"`
	ErrCode      int    `json:"errcode,omitempty"`
	ErrMsg       string `json:"errmsg,omitempty"`
	TypingTicket string `json:"typing_ticket,omitempty"`
}

GetConfigResponse is the response body for getconfig.

type GetUpdatesRequest

type GetUpdatesRequest struct {
	GetUpdatesBuf string   `json:"get_updates_buf"`
	BaseInfo      BaseInfo `json:"base_info"`
}

GetUpdatesRequest is the request body for getupdates.

type GetUpdatesResponse

type GetUpdatesResponse struct {
	Ret                  int             `json:"ret"`
	ErrCode              int             `json:"errcode,omitempty"`
	ErrMsg               string          `json:"errmsg,omitempty"`
	Msgs                 []WeixinMessage `json:"msgs,omitempty"`
	GetUpdatesBuf        string          `json:"get_updates_buf,omitempty"`
	LongPollingTimeoutMS int             `json:"longpolling_timeout_ms,omitempty"`
}

GetUpdatesResponse is the response body for getupdates.

type GetUploadURLRequest

type GetUploadURLRequest struct {
	UploadParams
	BaseInfo BaseInfo `json:"base_info"`
}

GetUploadURLRequest is the request body for getuploadurl.

type GetUploadURLResponse

type GetUploadURLResponse struct {
	Ret              int    `json:"ret,omitempty"`
	ErrCode          int    `json:"errcode,omitempty"`
	ErrMsg           string `json:"errmsg,omitempty"`
	UploadParam      string `json:"upload_param,omitempty"`
	ThumbUploadParam string `json:"thumb_upload_param,omitempty"`
}

GetUploadURLResponse is the response body for getuploadurl.

type ImageItem

type ImageItem struct {
	Media       *CDNMedia `json:"media,omitempty"`
	ThumbMedia  *CDNMedia `json:"thumb_media,omitempty"`
	AESKey      string    `json:"aeskey,omitempty"` // hex string, 32 chars
	URL         string    `json:"url,omitempty"`
	MidSize     int64     `json:"mid_size,omitempty"`
	ThumbSize   int64     `json:"thumb_size,omitempty"`
	ThumbHeight int       `json:"thumb_height,omitempty"`
	ThumbWidth  int       `json:"thumb_width,omitempty"`
	HDSize      int64     `json:"hd_size,omitempty"`
}

ImageItem holds image content and CDN references.

type MessageItem

type MessageItem struct {
	Type         int         `json:"type,omitempty"`
	CreateTimeMS int64       `json:"create_time_ms,omitempty"`
	UpdateTimeMS int64       `json:"update_time_ms,omitempty"`
	IsCompleted  *bool       `json:"is_completed,omitempty"`
	MsgID        string      `json:"msg_id,omitempty"`
	RefMsg       *RefMessage `json:"ref_msg,omitempty"`
	TextItem     *TextItem   `json:"text_item,omitempty"`
	ImageItem    *ImageItem  `json:"image_item,omitempty"`
	VoiceItem    *VoiceItem  `json:"voice_item,omitempty"`
	FileItem     *FileItem   `json:"file_item,omitempty"`
	VideoItem    *VideoItem  `json:"video_item,omitempty"`
}

MessageItem represents a single content item within a message.

type QRCodeResponse

type QRCodeResponse struct {
	QRCode           string `json:"qrcode,omitempty"`
	QRCodeImgContent string `json:"qrcode_img_content,omitempty"`
}

QRCodeResponse is the response from get_bot_qrcode.

type QRCodeStatusResponse

type QRCodeStatusResponse struct {
	Status      string `json:"status,omitempty"`
	BotToken    string `json:"bot_token,omitempty"`
	ILinkBotID  string `json:"ilink_bot_id,omitempty"`
	ILinkUserID string `json:"ilink_user_id,omitempty"`
	BaseURL     string `json:"baseurl,omitempty"`
}

QRCodeStatusResponse is the response from get_qrcode_status.

type RefMessage

type RefMessage struct {
	Title       string       `json:"title,omitempty"`
	MessageItem *MessageItem `json:"message_item,omitempty"`
}

RefMessage represents a quoted/referenced message.

type SendMessageRequest

type SendMessageRequest struct {
	Msg      WeixinMessage `json:"msg"`
	BaseInfo BaseInfo      `json:"base_info"`
}

SendMessageRequest is the request body for sendmessage.

type SendMessageResponse

type SendMessageResponse struct {
	Ret     int    `json:"ret,omitempty"`
	ErrCode int    `json:"errcode,omitempty"`
	ErrMsg  string `json:"errmsg,omitempty"`
}

SendMessageResponse is the response body for sendmessage.

type SendTypingRequest

type SendTypingRequest struct {
	ILinkUserID  string   `json:"ilink_user_id"`
	TypingTicket string   `json:"typing_ticket"`
	Status       int      `json:"status"`
	BaseInfo     BaseInfo `json:"base_info"`
}

SendTypingRequest is the request body for sendtyping.

type SendTypingResponse

type SendTypingResponse struct {
	Ret     int    `json:"ret"`
	ErrCode int    `json:"errcode,omitempty"`
	ErrMsg  string `json:"errmsg,omitempty"`
}

SendTypingResponse is the response body for sendtyping.

type TextItem

type TextItem struct {
	Text string `json:"text,omitempty"`
}

TextItem holds text content.

type UploadParams

type UploadParams struct {
	FileKey       string `json:"filekey"`
	MediaType     int    `json:"media_type"`
	ToUserID      string `json:"to_user_id"`
	RawSize       int    `json:"rawsize"`
	RawFileMD5    string `json:"rawfilemd5"`
	FileSize      int    `json:"filesize"`
	NoNeedThumb   bool   `json:"no_need_thumb,omitempty"`
	AESKey        string `json:"aeskey,omitempty"` // hex string
	ThumbRawSize  int    `json:"thumb_rawsize,omitempty"`
	ThumbRawMD5   string `json:"thumb_rawfilemd5,omitempty"`
	ThumbFileSize int    `json:"thumb_filesize,omitempty"`
}

UploadParams holds the parameters for getuploadurl.

type VideoItem

type VideoItem struct {
	Media       *CDNMedia `json:"media,omitempty"`
	VideoSize   int64     `json:"video_size,omitempty"`
	PlayLength  int       `json:"play_length,omitempty"`
	VideoMD5    string    `json:"video_md5,omitempty"`
	ThumbMedia  *CDNMedia `json:"thumb_media,omitempty"`
	ThumbSize   int64     `json:"thumb_size,omitempty"`
	ThumbHeight int       `json:"thumb_height,omitempty"`
	ThumbWidth  int       `json:"thumb_width,omitempty"`
}

VideoItem holds video content.

type VoiceItem

type VoiceItem struct {
	Media         *CDNMedia `json:"media,omitempty"`
	EncodeType    int       `json:"encode_type,omitempty"`
	BitsPerSample int       `json:"bits_per_sample,omitempty"`
	SampleRate    int       `json:"sample_rate,omitempty"`
	Playtime      int       `json:"playtime,omitempty"`
	Text          string    `json:"text,omitempty"`
}

VoiceItem holds voice content.

type WeixinMessage

type WeixinMessage struct {
	Seq          int64         `json:"seq,omitempty"`
	MessageID    int64         `json:"message_id,omitempty"`
	FromUserID   string        `json:"from_user_id,omitempty"`
	ToUserID     string        `json:"to_user_id,omitempty"`
	ClientID     string        `json:"client_id,omitempty"`
	CreateTimeMS int64         `json:"create_time_ms,omitempty"`
	UpdateTimeMS int64         `json:"update_time_ms,omitempty"`
	DeleteTimeMS int64         `json:"delete_time_ms,omitempty"`
	SessionID    string        `json:"session_id,omitempty"`
	GroupID      string        `json:"group_id,omitempty"`
	MessageType  int           `json:"message_type,omitempty"`
	MessageState int           `json:"message_state,omitempty"`
	ItemList     []MessageItem `json:"item_list,omitempty"`
	ContextToken string        `json:"context_token,omitempty"`
}

WeixinMessage represents a single message in the iLink Bot protocol.

type WeixinRuntimeDeps

type WeixinRuntimeDeps struct {
	Parent        context.Context
	Handler       pkgchannel.Handler
	Notifications pkgplugins.ChannelRegistry
	Log           *slog.Logger
	Now           func() time.Time
	NewChannel    func(pkgchannel.WeixinConfig, pkgchannel.Handler) (pkgchannel.Channel, error)
}

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL