Documentation
¶
Overview ¶
Package waga provides a Go client for interacting with the WhatsApp Gateway API.
The waga package enables Go applications to send WhatsApp messages, manage webhooks, and handle authentication with a WhatsApp Gateway service. It supports text and image messaging, message editing/deletion, webhook verification, and session management.
Quick Start ¶
To get started, create a new client and register your phone number:
client := waga.NewClient()
resp, err := client.Register(ctx, "6281234567890", "your-secret-key")
if err != nil {
log.Fatal(err)
}
Once registered, you can send messages:
msisdn := waga.FormatMSISDN("6281234567890")
msgResp, err := client.SendText(ctx, msisdn, "Hello, World!")
if err != nil {
log.Fatal(err)
}
Authentication ¶
The SDK supports two authentication methods:
1. Register a new phone number to obtain a JWT token 2. Use an existing JWT token with SetToken() or WithToken()
The client automatically stores the token returned by Register() for subsequent requests.
Message Formatting ¶
Phone numbers should be formatted as MSISDN (WhatsApp JID format). Use the helper functions FormatMSISDN() for individuals and FormatGroupID() for groups:
individual := waga.FormatMSISDN("6281234567890") // "6281234567890@s.whatsapp.net"
group := waga.FormatGroupID("1234567890") // "1234567890@g.us"
Webhooks ¶
Webhooks allow you to receive real-time notifications for incoming and outgoing messages. To handle webhooks securely, use the WebhookVerifier:
verifier := waga.NewWebhookVerifier("your-hmac-secret")
payload, err := verifier.ParseIncomingWebhook(body, signatureHeader)
if err != nil {
log.Fatal(err)
}
Configuration ¶
The client can be configured with options:
client := waga.NewClient(
waga.WithBaseURL("https://api.example.com"),
waga.WithTimeout(60*time.Second),
waga.WithToken("existing-jwt-token"),
)
Error Handling ¶
The SDK returns typed errors that can be checked using helper functions:
resp, err := client.SendText(ctx, msisdn, message)
if waga.IsUnauthorized(err) {
// Handle authentication error
} else if waga.IsRateLimited(err) {
// Handle rate limiting
}
For more examples and detailed usage, see the examples directory and README.md.
Index ¶
- Constants
- Variables
- func ComputeSignature(payload []byte, secret string) string
- func FormatGroupID(groupID string) string
- func FormatMSISDN(phoneNumber string) string
- func IsBadRequest(err error) bool
- func IsConflict(err error) bool
- func IsForbidden(err error) bool
- func IsInternalServer(err error) bool
- func IsNotFound(err error) bool
- func IsRateLimited(err error) bool
- func IsUnauthorized(err error) bool
- type Client
- func (c *Client) DeleteMessage(ctx context.Context, msisdn, messageID string) error
- func (c *Client) EditMessage(ctx context.Context, msisdn, messageID, newMessage string) error
- func (c *Client) GetLoginStatus(ctx context.Context) (*LoginStatus, error)
- func (c *Client) GetPairCode(ctx context.Context) (*LoginPairResponse, error)
- func (c *Client) GetQRCode(ctx context.Context, format string) (*LoginQrResponse, error)
- func (c *Client) GetToken() string
- func (c *Client) GetWebhook(ctx context.Context) (*WebhookResponse, error)
- func (c *Client) Health(ctx context.Context) (*HealthResponse, error)
- func (c *Client) Logout(ctx context.Context) error
- func (c *Client) React(ctx context.Context, msisdn, messageID, emoji string) error
- func (c *Client) Reconnect(ctx context.Context) error
- func (c *Client) Register(ctx context.Context, phoneNumber, secretKey string) (*RegisterResponse, error)
- func (c *Client) RegisterWebhook(ctx context.Context, url, hmacSecret string) error
- func (c *Client) SendImage(ctx context.Context, msisdn string, image io.Reader, caption string, ...) (*SendMessageResponse, error)
- func (c *Client) SendText(ctx context.Context, msisdn, message string) (*SendMessageResponse, error)
- func (c *Client) SetToken(token string)
- func (c *Client) UnregisterWebhook(ctx context.Context) error
- type ErrorResponse
- type HealthResponse
- type IncomingEventMessage
- type IncomingMessageMediaInfo
- type IncomingMessageType
- type IncomingWebhookPayload
- type LoginPairResponse
- type LoginQrResponse
- type LoginStatus
- type MessageDeleteRequest
- type MessageEditRequest
- type MessageReactRequest
- type Option
- type OutgoingEventMessage
- type OutgoingWebhookPayload
- type RegisterRequest
- type RegisterResponse
- type SDKError
- type SendMessageResponse
- type SendMessageTextRequest
- type SuccessResponse
- type WebhookRegisterRequest
- type WebhookResponse
- type WebhookVerifier
- func (v *WebhookVerifier) ParseIncomingWebhook(payload []byte, signature string) (*IncomingWebhookPayload, error)
- func (v *WebhookVerifier) ParseOutgoingWebhook(payload []byte, signature string) (*OutgoingWebhookPayload, error)
- func (v *WebhookVerifier) VerifySignature(payload []byte, signatureHeader string) bool
Constants ¶
const ( // EventMessageQueued is emitted when a message is added to the queue EventMessageQueued = OutgoingEventMessageMessageQueued // EventMessageSent is emitted when a message is successfully sent EventMessageSent = OutgoingEventMessageMessageSent // EventMessageFailed is emitted when a message fails to send EventMessageFailed = OutgoingEventMessageMessageFailed // EventMessageIncoming is emitted when a message is received EventMessageIncoming = IncomingEventMessageMessageIncoming )
Outgoing event type constants for convenience
const ( // MessageTypeText represents a text message MessageTypeText = IncomingMessageTypeText // MessageTypeImage represents an image message MessageTypeImage = IncomingMessageTypeImage // MessageTypeVideo represents a video message MessageTypeVideo = IncomingMessageTypeVideo // MessageTypeAudio represents an audio message MessageTypeAudio = IncomingMessageTypeAudio // MessageTypeDocument represents a document message MessageTypeDocument = IncomingMessageTypeDocument )
Incoming message type constants for convenience
const ( // DefaultBaseURL is the default API endpoint DefaultBaseURL = "http://localhost:3000/api/v1" // DefaultTimeout is the default HTTP request timeout DefaultTimeout = 30 * time.Second // DefaultUserAgent is the default User-Agent header DefaultUserAgent = "WhatsApp-Gateway-SDK-Go/1.0" )
Variables ¶
var ( ErrUnauthorized = &SDKError{Code: http.StatusUnauthorized, Message: "unauthorized"} // ErrBadRequest is returned for invalid requests (400) ErrBadRequest = &SDKError{Code: http.StatusBadRequest, Message: "bad request"} // ErrForbidden is returned when access is denied (403) ErrForbidden = &SDKError{Code: http.StatusForbidden, Message: "forbidden"} // ErrNotFound is returned when a resource is not found (404) ErrNotFound = &SDKError{Code: http.StatusNotFound, Message: "not found"} // ErrConflict is returned for conflicting requests (409) ErrConflict = &SDKError{Code: http.StatusConflict, Message: "conflict"} // ErrRateLimited is returned when rate limit is exceeded (429) ErrRateLimited = &SDKError{Code: http.StatusTooManyRequests, Message: "rate limited"} // ErrInternalServer is returned for server errors (500) ErrInternalServer = &SDKError{Code: http.StatusInternalServerError, Message: "internal server error"} // ErrInvalidSignature is returned when webhook signature verification fails ErrInvalidSignature = errors.New("invalid webhook signature") // ErrNotAuthenticated is returned when trying to use an authenticated method without setting a token ErrNotAuthenticated = errors.New("client not authenticated, call Register() or SetToken() first") )
Common API errors These predefined errors can be used for comparison with errors.Is().
Functions ¶
func ComputeSignature ¶
ComputeSignature computes the HMAC-SHA256 signature for a webhook payload. This is primarily useful for testing webhook implementations.
The returned signature is in the format "sha256=<hex_signature>", which matches the format used in the X-Webhook-Signature header.
Example:
payload := []byte(`{"event":"message.incoming"}`)
signature := waga.ComputeSignature(payload, "your-secret")
// Use signature to set X-Webhook-Signature header in test requests
func FormatGroupID ¶
FormatGroupID formats a group ID to WhatsApp group JID format. If the groupID already contains "@", it is returned as-is. Otherwise, "@g.us" is appended to create a valid group JID.
Example:
groupID := waga.FormatGroupID("1234567890") // "1234567890@g.us"
func FormatMSISDN ¶
FormatMSISDN formats a phone number to WhatsApp JID format for individual contacts. If the phoneNumber already contains "@", it is returned as-is. Otherwise, "@s.whatsapp.net" is appended to create a valid JID.
Example:
msisdn := waga.FormatMSISDN("6281234567890") // "6281234567890@s.whatsapp.net"
func IsBadRequest ¶
IsBadRequest checks if the error is a bad request error (HTTP 400). Returns true if err matches ErrBadRequest.
func IsConflict ¶
IsConflict checks if the error is a conflict error (HTTP 409). Returns true if err matches ErrConflict.
func IsForbidden ¶
IsForbidden checks if the error is a forbidden error (HTTP 403). Returns true if err matches ErrForbidden.
func IsInternalServer ¶
IsInternalServer checks if the error is an internal server error (HTTP 500). Returns true if err matches ErrInternalServer.
func IsNotFound ¶
IsNotFound checks if the error is a not found error (HTTP 404). Returns true if err matches ErrNotFound.
func IsRateLimited ¶
IsRateLimited checks if the error is a rate limit error (HTTP 429). Returns true if err matches ErrRateLimited.
func IsUnauthorized ¶
IsUnauthorized checks if the error is an unauthorized error (HTTP 401). Returns true if err matches ErrUnauthorized.
Types ¶
type Client ¶
type Client struct {
// contains filtered or unexported fields
}
Client is the main SDK client for interacting with the WhatsApp Gateway API. It provides methods for authentication, messaging, webhook management, and session control.
The client is safe for concurrent use.
func NewClient ¶
NewClient creates a new SDK client with the given options.
The client can be configured with functional options:
client := waga.NewClient(
waga.WithBaseURL("https://api.example.com"),
waga.WithTimeout(60*time.Second),
waga.WithToken("existing-jwt-token"),
)
By default, the client uses:
- Base URL: http://localhost:3000/api/v1
- Timeout: 30 seconds
- User-Agent: WhatsApp-Gateway-SDK-Go/1.0
func (*Client) DeleteMessage ¶
DeleteMessage deletes a previously sent message. The message will be removed from the chat for both sender and recipient.
The msisdn is the recipient's phone number, and messageID is the ID of the message to delete (returned by SendText or SendImage).
Requires authentication (call Register or SetToken first).
func (*Client) EditMessage ¶
EditMessage edits a previously sent message. It replaces the message content with newMessage.
The msisdn is the recipient's phone number, and messageID is the ID of the message to edit (returned by SendText or SendImage).
Requires authentication (call Register or SetToken first).
func (*Client) GetLoginStatus ¶
func (c *Client) GetLoginStatus(ctx context.Context) (*LoginStatus, error)
GetLoginStatus returns the current WhatsApp session status. It checks whether the WhatsApp session is authenticated and active.
Requires authentication (call Register or SetToken first).
func (*Client) GetPairCode ¶
func (c *Client) GetPairCode(ctx context.Context) (*LoginPairResponse, error)
GetPairCode generates a pair code for WhatsApp login. The pair code is an 8-character code that can be used to link the device without scanning a QR code. Users can enter the code in WhatsApp > Linked Devices.
The pair code expires after the duration specified in ExpiresIn.
Requires authentication (call Register or SetToken first).
func (*Client) GetQRCode ¶
GetQRCode generates a QR code for WhatsApp login. The format parameter specifies the response format:
- "json": returns a base64-encoded PNG image
- "html": returns an HTML img tag with the embedded QR code
The QR code can be displayed to users for scanning with the WhatsApp mobile app to link their account. The QR code expires after the duration specified in ExpiresIn.
Requires authentication (call Register or SetToken first).
func (*Client) GetToken ¶
GetToken returns the current JWT token stored in the client. Returns an empty string if no token has been set.
func (*Client) GetWebhook ¶
func (c *Client) GetWebhook(ctx context.Context) (*WebhookResponse, error)
GetWebhook returns the currently registered webhook URL. Use this to check if a webhook is configured and retrieve its URL.
Requires authentication (call Register or SetToken first).
func (*Client) Health ¶
func (c *Client) Health(ctx context.Context) (*HealthResponse, error)
Health checks the health status of the gateway service. This method does not require authentication and can be used to verify that the service is running and accessible.
func (*Client) Logout ¶
Logout logs out from the current WhatsApp session. This disconnects the WhatsApp account and invalidates the session. After logging out, you'll need to authenticate again using GetQRCode or GetPairCode.
Requires authentication (call Register or SetToken first).
func (*Client) React ¶
React adds a reaction emoji to a previously sent message. The emoji will appear on the message for all participants in the chat.
The msisdn is the recipient's phone number, messageID is the ID of the message to react to, and emoji is the emoji character(s) to use (e.g., "👍", "❤️").
Requires authentication (call Register or SetToken first).
func (*Client) Reconnect ¶
Reconnect attempts to reconnect to the existing WhatsApp session. Use this method if the connection to WhatsApp has been lost but the session is still valid. It attempts to restore the connection without requiring re-authentication.
Requires authentication (call Register or SetToken first).
func (*Client) Register ¶
func (c *Client) Register(ctx context.Context, phoneNumber, secretKey string) (*RegisterResponse, error)
Register registers a new phone number with the WhatsApp Gateway service. It retrieves and stores a JWT token for subsequent API requests.
The phoneNumber should be in international format without the "+" symbol (e.g., "6281234567890"). The secretKey is provided by the gateway service.
After successful registration, the token is automatically stored in the client and used for all authenticated requests.
func (*Client) RegisterWebhook ¶
RegisterWebhook registers a URL to receive webhook events. Webhooks allow you to receive real-time notifications for incoming and outgoing messages.
The url parameter is the endpoint where webhook events will be sent. The hmacSecret parameter is optional but highly recommended for verifying webhook signatures. If provided, all webhook payloads will include an X-Webhook-Signature header that can be verified using the WebhookVerifier.
Requires authentication (call Register or SetToken first).
func (*Client) SendImage ¶
func (c *Client) SendImage(ctx context.Context, msisdn string, image io.Reader, caption string, isViewOnce bool) (*SendMessageResponse, error)
SendImage sends an image message to the specified recipient.
The msisdn parameter should be the recipient's phone number in WhatsApp JID format. The image parameter is an io.Reader containing the image data (JPEG, PNG, etc.). The caption parameter is optional text to accompany the image. The isViewOnce parameter, if true, sends the image as a view-once media that disappears after being viewed.
Example:
file, _ := os.Open("image.jpg")
defer file.Close()
resp, err := client.SendImage(ctx, msisdn, file, "Check this out!", false)
Requires authentication (call Register or SetToken first).
func (*Client) SendText ¶
func (c *Client) SendText(ctx context.Context, msisdn, message string) (*SendMessageResponse, error)
SendText sends a text message to the specified recipient.
The msisdn parameter should be the recipient's phone number in WhatsApp JID format. Use the FormatMSISDN() helper function to convert a phone number to the correct format:
msisdn := waga.FormatMSISDN("6281234567890") // "6281234567890@s.whatsapp.net"
For group messages, use the group ID in the format "groupId@g.us".
Requires authentication (call Register or SetToken first).
func (*Client) SetToken ¶
SetToken sets the JWT token for authentication. Use this method if you already have a valid token from a previous registration. The token will be used for all subsequent API requests that require authentication.
func (*Client) UnregisterWebhook ¶
UnregisterWebhook removes the currently registered webhook URL. After calling this method, webhook events will no longer be sent to the previously configured endpoint.
Requires authentication (call Register or SetToken first).
type ErrorResponse ¶
type ErrorResponse struct {
// Error is a human-readable error message
Error string `json:"error"`
// Code is the HTTP status code or API error code
Code int `json:"code"`
}
ErrorResponse represents an error response from the API.
type HealthResponse ¶
type HealthResponse struct {
// Status is the health status of the service (e.g., "ok", "degraded")
Status string `json:"status"`
// Timestamp is the ISO 8601 timestamp of the health check
Timestamp string `json:"timestamp"`
}
HealthResponse represents the response from Health.
type IncomingEventMessage ¶
type IncomingEventMessage string
IncomingEventMessage represents the type of incoming message event.
const ( // IncomingEventMessageMessageIncoming is emitted when a new message is received IncomingEventMessageMessageIncoming IncomingEventMessage = "message.incoming" )
type IncomingMessageMediaInfo ¶
type IncomingMessageMediaInfo struct {
// Type is the media type (image, video, audio, or document)
Type IncomingMessageType `json:"type"`
// Url is the direct URL to download the media file
Url string `json:"url"`
// MimeType is the MIME type of the media file
MimeType string `json:"mime_type"`
// Filename is the original filename of the media file (if applicable)
Filename string `json:"filename,omitempty"`
// Caption is the text caption accompanying the media (if applicable)
Caption string `json:"caption,omitempty"`
// Size is the file size in bytes (if available)
Size int `json:"size,omitempty"`
}
IncomingMessageMediaInfo contains media information for incoming messages with attachments. This includes images, videos, audio, and documents.
type IncomingMessageType ¶
type IncomingMessageType string
IncomingMessageType represents the type of incoming message content.
const ( // IncomingMessageTypeText represents a text message IncomingMessageTypeText IncomingMessageType = "text" // IncomingMessageTypeImage represents an image message IncomingMessageTypeImage IncomingMessageType = "image" // IncomingMessageTypeVideo represents a video message IncomingMessageTypeVideo IncomingMessageType = "video" // IncomingMessageTypeAudio represents an audio message IncomingMessageTypeAudio IncomingMessageType = "audio" // IncomingMessageTypeDocument represents a document message IncomingMessageTypeDocument IncomingMessageType = "document" )
type IncomingWebhookPayload ¶
type IncomingWebhookPayload struct {
// Event is the type of event (always "message.incoming")
Event IncomingEventMessage `json:"event"`
// Chat is the chat ID where the message was received
Chat string `json:"chat"`
// From is the sender's phone number in WhatsApp JID format
From string `json:"from"`
// IsGroup indicates whether the message was received in a group chat
IsGroup bool `json:"is_group"`
// MessageId is the unique identifier for the message
MessageId string `json:"message_id"`
// PushName is the display name of the sender
PushName string `json:"push_name"`
// Timestamp is the Unix timestamp when the message was received
Timestamp int `json:"timestamp"`
// Text is the text content of the message (for text messages)
Text string `json:"text,omitempty"`
// Type is the message type (text, image, video, audio, or document)
Type IncomingMessageType `json:"type"`
// Media contains media information for non-text messages
Media *IncomingMessageMediaInfo `json:"media,omitempty"`
}
IncomingWebhookPayload represents the payload sent to webhooks for incoming message events. This contains all information about received messages.
type LoginPairResponse ¶
type LoginPairResponse struct {
// PairCode is the 8-character code for linking the device
PairCode string `json:"pair_code"`
// ExpiresIn is the number of seconds until the pair code expires
ExpiresIn int `json:"expires_in"`
}
LoginPairResponse represents the response when requesting a pair code for login. The pair code can be used to link the WhatsApp account without scanning a QR code.
type LoginQrResponse ¶
type LoginQrResponse struct {
// QrCode is the base64-encoded QR code image or HTML img tag
QrCode string `json:"qr_code"`
// ExpiresIn is the number of seconds until the QR code expires
ExpiresIn int `json:"expires_in"`
}
LoginQrResponse represents the response when requesting a QR code for login. The QR code can be displayed to users for scanning with the WhatsApp mobile app.
type LoginStatus ¶
type LoginStatus struct {
// Authenticated is true if the session is active and authenticated
Authenticated bool `json:"authenticated"`
}
LoginStatus represents the response from GetLoginStatus. It indicates whether the WhatsApp session is currently authenticated.
type MessageDeleteRequest ¶
type MessageDeleteRequest struct {
// MessageId is the ID of the message to delete
MessageId string `json:"message_id"`
// Msisdn is the recipient's phone number in WhatsApp JID format
Msisdn string `json:"msisdn"`
}
MessageDeleteRequest represents a request to delete a previously sent message.
type MessageEditRequest ¶
type MessageEditRequest struct {
// MessageId is the ID of the message to edit
MessageId string `json:"message_id"`
// Msisdn is the recipient's phone number in WhatsApp JID format
Msisdn string `json:"msisdn"`
// NewMessage is the updated message content
NewMessage string `json:"new_message"`
}
MessageEditRequest represents a request to edit a previously sent message.
type MessageReactRequest ¶
type MessageReactRequest struct {
// MessageId is the ID of the message to react to
MessageId string `json:"message_id"`
// Msisdn is the recipient's phone number in WhatsApp JID format
Msisdn string `json:"msisdn"`
// Emoji is the emoji reaction to add
Emoji string `json:"emoji"`
}
MessageReactRequest represents a request to add a reaction to a message.
type Option ¶
type Option func(*Client)
Option configures the SDK client. Options are applied when creating a new client with NewClient.
func WithBaseURL ¶
WithBaseURL sets the base URL for the API. Use this option to connect to a different WhatsApp Gateway server.
The default base URL is "http://localhost:3000/api/v1".
Example:
client := waga.NewClient(waga.WithBaseURL("https://api.example.com"))
func WithHTTPClient ¶
WithHTTPClient sets a custom HTTP client for making API requests. Use this option to customize HTTP behavior such as timeouts, redirects, transport settings, or proxy configuration.
Example:
httpClient := &http.Client{
Timeout: 60 * time.Second,
Transport: &http.Transport{...},
}
client := waga.NewClient(waga.WithHTTPClient(httpClient))
func WithTimeout ¶
WithTimeout sets the HTTP client timeout for API requests. The timeout applies to the entire HTTP request, including connection time, redirects, and reading the response body.
The default timeout is 30 seconds.
Example:
client := waga.NewClient(waga.WithTimeout(60 * time.Second))
func WithToken ¶
WithToken sets a pre-existing JWT token for authentication. Use this option if you already have a valid token from a previous registration and want to skip the registration step.
The token will be used for all authenticated API requests.
Example:
client := waga.NewClient(waga.WithToken("your-jwt-token"))
func WithUserAgent ¶
WithUserAgent sets a custom User-Agent header for API requests. Use this option to identify your application in API requests.
The default User-Agent is "WhatsApp-Gateway-SDK-Go/1.0".
Example:
client := waga.NewClient(waga.WithUserAgent("MyApp/1.0"))
type OutgoingEventMessage ¶
type OutgoingEventMessage string
OutgoingEventMessage represents the type of outgoing message event. These events are sent to webhooks to track message delivery status.
const ( // OutgoingEventMessageMessageQueued is emitted when a message is added to the queue OutgoingEventMessageMessageQueued OutgoingEventMessage = "message.queued" // OutgoingEventMessageMessageSent is emitted when a message is successfully sent OutgoingEventMessageMessageSent OutgoingEventMessage = "message.sent" // OutgoingEventMessageMessageFailed is emitted when a message fails to send OutgoingEventMessageMessageFailed OutgoingEventMessage = "message.failed" )
type OutgoingWebhookPayload ¶
type OutgoingWebhookPayload struct {
// Event is the type of event that occurred
Event OutgoingEventMessage `json:"event"`
// JobId is the unique identifier for the message job
JobId string `json:"job_id"`
// To is the recipient's phone number in WhatsApp JID format
To string `json:"to"`
// PhoneNumber is the sender's phone number
PhoneNumber string `json:"phone_number"`
// Timestamp is the Unix timestamp of the event
Timestamp int `json:"timestamp"`
// MessageId is the unique identifier for the message
MessageId string `json:"message_id"`
// Metadata contains additional optional information about the message
Metadata *map[string]interface{} `json:"metadata,omitempty"`
}
OutgoingWebhookPayload represents the payload sent to webhooks for outgoing message events. These events track the delivery status of messages sent through the API.
type RegisterRequest ¶
type RegisterRequest struct {
PhoneNumber string `json:"phone_number"`
SecretKey string `json:"secret_key"`
}
RegisterRequest represents a registration request for a new phone number. It contains the phone number and secret key required to authenticate with the WhatsApp Gateway service and obtain a JWT token.
type RegisterResponse ¶
type RegisterResponse struct {
// Token is the JWT authentication token for API requests
Token string `json:"token"`
}
RegisterResponse represents the response from a successful registration. It contains the JWT token that should be used for subsequent API requests.
type SDKError ¶
type SDKError struct {
// Code is the HTTP status code or API error code
Code int `json:"code"`
// Message is the error message describing what went wrong
Message string `json:"error"`
}
SDKError represents an error returned by the WhatsApp Gateway API. It contains both an HTTP status code and a human-readable error message.
func NewSDKError ¶
NewSDKError creates a new SDKError with the given code and message. Use this function to create custom SDK errors with specific codes and messages.
Example:
err := waga.NewSDKError(418, "I'm a teapot")
type SendMessageResponse ¶
type SendMessageResponse struct {
// Success indicates whether the message was successfully queued
Success bool `json:"success"`
// MessageId is the unique identifier for the sent message
MessageId string `json:"message_id"`
}
SendMessageResponse represents the response from sending a message.
type SendMessageTextRequest ¶
type SendMessageTextRequest struct {
// Msisdn is the recipient's phone number in WhatsApp JID format (e.g., "6281234567890@s.whatsapp.net")
Msisdn string `json:"msisdn"`
// Message is the text content to send
Message string `json:"message"`
}
SendMessageTextRequest represents a request to send a text message.
type SuccessResponse ¶
type SuccessResponse struct {
// Success indicates whether the operation completed successfully
Success bool `json:"success"`
}
SuccessResponse represents a generic success response from API operations.
type WebhookRegisterRequest ¶
type WebhookRegisterRequest struct {
// Url is the endpoint URL where webhook events will be sent
Url string `json:"url"`
// HmacSecret is the optional secret key used to sign webhook payloads for verification
HmacSecret *string `json:"hmac_secret,omitempty"`
}
WebhookRegisterRequest represents a request to register a webhook URL. Webhooks receive real-time notifications for message events.
type WebhookResponse ¶
type WebhookResponse struct {
// URL is the currently registered webhook endpoint
URL string `json:"url"`
}
WebhookResponse represents the response from GetWebhook.
type WebhookVerifier ¶
type WebhookVerifier struct {
// contains filtered or unexported fields
}
WebhookVerifier handles verification of incoming webhook signatures. It ensures that webhook payloads are genuine and haven't been tampered with by verifying HMAC-SHA256 signatures.
Security considerations:
- Always keep your HMAC secret secure and never expose it in client-side code
- Use constant-time comparison to prevent timing attacks
- Reject webhooks with invalid or missing signatures
func NewWebhookVerifier ¶
func NewWebhookVerifier(secret string) *WebhookVerifier
NewWebhookVerifier creates a new webhook verifier with the given HMAC secret. The secret must match the one configured when registering the webhook.
Example:
verifier := waga.NewWebhookVerifier("your-hmac-secret")
func (*WebhookVerifier) ParseIncomingWebhook ¶
func (v *WebhookVerifier) ParseIncomingWebhook(payload []byte, signature string) (*IncomingWebhookPayload, error)
ParseIncomingWebhook parses and verifies an incoming message webhook payload. It returns the parsed payload if the signature is valid, or an error otherwise.
This method verifies the signature first, then unmarshals the JSON payload. If either step fails, it returns an error.
Example:
body, _ := io.ReadAll(r.Body)
signature := r.Header.Get("X-Webhook-Signature")
webhook, err := verifier.ParseIncomingWebhook(body, signature)
if err != nil {
log.Fatal(err)
}
fmt.Printf("Message from %s: %s\n", webhook.From, webhook.Text)
func (*WebhookVerifier) ParseOutgoingWebhook ¶
func (v *WebhookVerifier) ParseOutgoingWebhook(payload []byte, signature string) (*OutgoingWebhookPayload, error)
ParseOutgoingWebhook parses and verifies an outgoing event webhook payload. It returns the parsed payload if the signature is valid, or an error otherwise.
Outgoing webhooks track the delivery status of messages sent through the API. This method verifies the signature first, then unmarshals the JSON payload.
Example:
body, _ := io.ReadAll(r.Body)
signature := r.Header.Get("X-Webhook-Signature")
webhook, err := verifier.ParseOutgoingWebhook(body, signature)
if err != nil {
log.Fatal(err)
}
fmt.Printf("Message %s: %s\n", webhook.Event, webhook.MessageId)
func (*WebhookVerifier) VerifySignature ¶
func (v *WebhookVerifier) VerifySignature(payload []byte, signatureHeader string) bool
VerifySignature validates the X-Webhook-Signature header from a webhook request. The signature header format is: "sha256=<hex_signature>".
This method uses constant-time comparison to prevent timing attacks. It returns false if the signature is missing, malformed, or doesn't match.
Example:
signature := r.Header.Get("X-Webhook-Signature")
if !verifier.VerifySignature(body, signature) {
return ErrInvalidSignature
}