Documentation
¶
Index ¶
- Constants
- Variables
- func CiphertextSize(rawSize int) int
- func DecodeAESKey(aesKeyB64 string) ([]byte, error)
- func DecodeConfig(raw map[string]any) (pkgchannel.WeixinConfig, error)
- func DecryptAESECB(ciphertext, key []byte) ([]byte, error)
- func DownloadFromCDN(cdnBaseURL, encryptedQueryParam string) ([]byte, error)
- func EncryptAESECB(plaintext, key []byte) ([]byte, error)
- func NewWeixinManagedRuntime(deps WeixinRuntimeDeps) pkgplugins.Runtime
- func RandomClientID(prefix string) string
- func RandomFileKey() string
- func RedactConfig(raw map[string]any) map[string]any
- func ResolveImageKey(imageItem *ImageItem) ([]byte, error)
- func UploadToCDN(cdnBaseURL, uploadParam, filekey string, encrypted []byte) (string, error)
- type BaseInfo
- type Bot
- type CDNMedia
- type Client
- func (c *Client) GetConfig(userID, contextToken, channelVersion string) (*GetConfigResponse, error)
- func (c *Client) GetQRCode(skRouteTag string) (*QRCodeResponse, error)
- func (c *Client) GetQRCodeStatus(qrcode, skRouteTag string) (*QRCodeStatusResponse, error)
- func (c *Client) GetUpdates(buf, channelVersion string, timeout time.Duration) (*GetUpdatesResponse, error)
- func (c *Client) GetUploadURL(params UploadParams, channelVersion string) (*GetUploadURLResponse, error)
- func (c *Client) SendMessage(msg WeixinMessage, channelVersion string) error
- func (c *Client) SendTyping(userID, typingTicket string, status int, channelVersion string) error
- type Config
- type FileItem
- type GetConfigRequest
- type GetConfigResponse
- type GetUpdatesRequest
- type GetUpdatesResponse
- type GetUploadURLRequest
- type GetUploadURLResponse
- type ImageItem
- type MessageItem
- type QRCodeResponse
- type QRCodeStatusResponse
- type RefMessage
- type SendMessageRequest
- type SendMessageResponse
- type SendTypingRequest
- type SendTypingResponse
- type TextItem
- type UploadParams
- type VideoItem
- type VoiceItem
- type WeixinMessage
- type WeixinRuntimeDeps
Constants ¶
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" )
const ( MessageTypeUser = 1 // USER — incoming message from a WeChat user. MessageTypeBot = 2 // BOT — outgoing message from the bot. )
Message type constants.
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.
const ( ItemTypeText = 1 ItemTypeImage = 2 ItemTypeVoice = 3 ItemTypeFile = 4 ItemTypeVideo = 5 )
Item type constants.
const ( MediaTypeImage = 1 MediaTypeVideo = 2 MediaTypeFile = 3 MediaTypeVoice = 4 )
Media type constants for getuploadurl.
const ( PluginID = "channel/weixin" RuntimeName = "bot" )
Variables ¶
var ErrSessionExpired = errors.New("weixin: session expired (ret=-14)")
ErrSessionExpired indicates the iLink session has expired (ret=-14 or errcode=-14).
Functions ¶
func CiphertextSize ¶
CiphertextSize returns the AES-128-ECB + PKCS7 ciphertext size for a given raw size. Formula: ceil((rawSize+1)/16) * 16
func DecodeAESKey ¶
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 ¶
DecryptAESECB decrypts ciphertext using AES-128-ECB and removes PKCS7 padding.
func DownloadFromCDN ¶
DownloadFromCDN downloads encrypted data from the WeChat CDN.
func EncryptAESECB ¶
EncryptAESECB encrypts plaintext using AES-128-ECB with PKCS7 padding.
func NewWeixinManagedRuntime ¶
func NewWeixinManagedRuntime(deps WeixinRuntimeDeps) pkgplugins.Runtime
func RandomClientID ¶
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 ResolveImageKey ¶
ResolveImageKey determines the AES key for an image item. Precedence: image_item.aeskey (hex) > media.aes_key (base64).
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 (*Bot) Notify ¶
Notify sends a notification message via sendmessage. 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 (*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.
type Config ¶
type Config struct {
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)
}