TWhatsApp
Source: source/classes/twhatsapp.prg
Hierarchy: TWhatsApp (standalone class, no inheritance)
TWhatsApp is a WhatsApp Cloud API client that communicates with Meta's Business Platform via HTTPS requests using the cURL library. It requires a Meta Business Account, a registered phone number ID, and a permanent system access token generated from the Meta App Dashboard. All message types are sent as JSON payloads through the Graph API.
New to the WhatsApp Cloud API? Follow the illustrated step-by-step setup guide to create the Meta app, get your access token and phone number ID, and send your first message in about 15 minutes.
Key DATA Members
| DATA | Type | Default | Description |
|---|---|---|---|
cToken | Character | Bearer access token for API authentication | |
cPhoneId | Character | Sender phone number ID (Meta numeric ID, not the phone number) | |
cVersion | Character | "v24.0" | Graph API version string |
cBaseUrl | Character | "https://graph.facebook.com" | Base URL for all API calls |
cResponse | Character | Raw JSON response from the last API call | |
nError | Numeric | 0 | cURL error code from the last operation |
nHttpCode | Numeric | 0 | HTTP status code from the last response |
Methods
| Method | Description |
|---|---|
New( cToken, cPhoneId, cVersion ) | Constructor. Initializes cURL handle and stores credentials. Optionally sets API version. |
End() | Clean up the cURL handle. Call when done with the object. |
SendText( cTo, cMsg, lPreviewUrl ) | Send a plain text message. lPreviewUrl enables link preview generation. |
SendTemplate( cTo, cName, cLang, aBodyParams, hHeader, aButtons ) | Send a pre-approved message template. All parameters are optional: aBodyParams is an array of body values, hHeader is { "type" => "text"|"image"|"document"|"video", ... } (text header takes "text"; media headers take "link" or "id", document also "filename") and aButtons is { { "sub_type" => "quick_reply", "payload" => c }, { "sub_type" => "url", "text" => cDynamicSuffix } }. Phone number buttons need no parameters. |
SendImage( cTo, cLinkOrId, cCaption ) | Send an image by URL or previously uploaded media ID. |
SendDocument( cTo, cLinkOrId, cFilename, cCaption ) | Send a document by URL or media ID with optional filename and caption. |
SendAudio( cTo, cLinkOrId ) | Send an audio file by URL or media ID. |
SendVideo( cTo, cLinkOrId, cCaption ) | Send a video by URL or media ID with optional caption. |
SendLocation( cTo, nLat, nLong, cName, cAddress ) | Send a location pin with latitude, longitude, and optional name/address. |
SendButtons( cTo, cBody, aButtons, cHeader, cFooter ) | Send an interactive message with up to 3 reply buttons: aButtons is { { "id" => cId, "title" => cLabel }, ... } (labels max 20 characters). cHeader and cFooter are optional text. |
SendList( cTo, cBody, cButton, aRows, cHeader, cFooter ) | Send an interactive list message: cButton is the label that opens the list and aRows is { { "id" => cId, "title" => cTitle, "description" => cDesc }, ... } (max 10 rows). cHeader and cFooter are optional text. |
SendReaction( cTo, cMsgId, cEmoji ) | React with an emoji to a received message. An empty cEmoji removes the reaction. |
SendContact( cTo, aContacts ) | Send one or more contact cards. Each contact is { "name" => cFullName, "first" => c, "last" => c, "phones" => { cPhone, ... }, "emails" => { cEmail, ... }, "company" => c, "title" => c }; only "name" is required. |
MarkAsRead( cMsgId, lTyping ) | Mark a received message as read (blue checks). With lTyping = .T. it also shows the typing indicator. cMsgId is the id of a message received via webhook. |
UploadMedia( cFileName, cMimeType ) | Upload a media file to WhatsApp servers. Returns the media ID string, or nil on failure. |
DownloadMedia( cMediaId, cTargetFile ) | Download a media file from WhatsApp servers and save to disk. Returns .T. on success. |
GetMessageId() | Extract the message ID from the last API response. Returns empty string on failure. |
GetError() | Extract the error message from the last API response. Returns empty string if no error. |
GetErrorCode() | Numeric Meta error code from the last API response, 0 if none. |
GetFbTraceId() | Meta fbtrace_id from the last error response, useful when reporting problems to Meta support. |
Example: Send Text Message
#include "FiveWin.ch"
function Main()
local oWA := TWhatsApp():New( "EAAx...token", "123456789", "v24.0" )
local cResp, cMsgId
// Send a simple text message
cResp := oWA:SendText( "5215512345678", "Hello from FiveWin!" )
cMsgId := oWA:GetMessageId()
if ! Empty( cMsgId )
MsgInfo( "Message sent. ID: " + cMsgId )
else
MsgInfo( "Error: " + oWA:GetError() )
endif
oWA:End()
return nil
Example: Template Message
#include "FiveWin.ch"
function SendTemplate()
local oWA := TWhatsApp():New( "EAAx...token", "123456789" )
local aParams := { "John", "FWH 26.05", "Monday" }
// "welcome_message" must be pre-approved by Meta
oWA:SendTemplate( "5215512345678", "welcome_message", "en_US", aParams )
oWA:End()
return nil
Example: Template with Header and Buttons
#include "FiveWin.ch"
function SendTemplateFull()
local oWA := TWhatsApp():New( "EAAx...token", "123456789" )
// "order_update" must exist and be approved in the Meta app:
// body with 2 parameters, image header, quick reply + dynamic URL buttons
oWA:SendTemplate( "5215512345678", "order_update", "es_ES", ;
{ "Ana", "1234" }, ;
{ "type" => "image", "link" => "https://www.fivetechsoft.com/images/fivewin_logo.png" }, ;
{ { "sub_type" => "quick_reply", "payload" => "track_1234" }, ;
{ "sub_type" => "url", "text" => "order/1234" } } )
oWA:End()
return nil
Example: Interactive Buttons
#include "FiveWin.ch"
function SendButtons()
local oWA := TWhatsApp():New( "EAAx...token", "123456789" )
oWA:SendButtons( "5215512345678", "Do you confirm the appointment tomorrow at 10:00?", ;
{ { "id" => "confirm_yes", "title" => "Confirm" }, ;
{ "id" => "confirm_no", "title" => "Cancel" } }, ;
"Appointment", "Reply with one tap" )
oWA:End()
return nil
Notes
- A Meta Business Account and a registered phone number are required. The phone number ID is a numeric identifier assigned by Meta, not the phone number itself.
- Use a permanent system access token from the Meta App Dashboard. Temporary user tokens expire.
SendImage,SendDocument,SendAudio, andSendVideoaccept either a public URL or a previously uploaded media ID. URLs must start withhttp(case-insensitive).- Template names must match pre-approved templates in the Meta Business account. Body parameters are inserted positionally.
- All send methods return the raw JSON response in
cResponse. CallGetMessageId()orGetError()to parse the result. - The class uses
hbcurl.chand requires the cURL library linked into the application.