Add WhatsApp Business API integration with Twilio documentation
- Add comprehensive guide for integrating WhatsApp Business API using Twilio phone numbers - Include complete workflow: from number purchase to Meta configuration - Add 5 detailed guides: quick-start, webhooks, examples, troubleshooting, quick-reference - Cover phone number verification via voice call (Twilio requirement) - Document all Meta credentials: Access Token, Phone Number ID, WABA ID, Verify Token, Application ID - Provide code examples in BASIC, Node.js, and Python - Integrate into Appendix B: External Services (no new chapter) - All example values randomized for security
This commit is contained in:
parent
c8d39c0e62
commit
6df9f7dce5
7 changed files with 4343 additions and 0 deletions
|
|
@ -1 +1,275 @@
|
|||
# Channel Integrations
|
||||
|
||||
This guide covers integrating messaging channels with General Bots, focusing on WhatsApp Business API integration using Twilio-purchased phone numbers.
|
||||
|
||||
## Overview
|
||||
|
||||
General Bots supports multiple messaging channels through a unified API. This section focuses on WhatsApp Business API, the most widely used business messaging platform globally.
|
||||
|
||||
## Supported Channels
|
||||
|
||||
| Channel | Status | Config Keys |
|
||||
|---------|--------|-------------|
|
||||
| WhatsApp | ✅ Production Ready | `whatsapp-api-key`, `whatsapp-phone-number-id` |
|
||||
| Twilio SMS | ✅ Production Ready | `twilio-account-sid`, `twilio-auth-token` |
|
||||
| Instagram | ✅ Production Ready | `instagram-access-token`, `instagram-page-id` |
|
||||
| Microsoft Teams | ✅ Production Ready | `teams-app-id`, `teams-app-password` |
|
||||
|
||||
## WhatsApp Business Integration
|
||||
|
||||
The most popular channel for business messaging. Complete integration guide: [WhatsApp Quick Start](./whatsapp-quick-start.md)
|
||||
|
||||
### Quick Setup (5 minutes)
|
||||
|
||||
1. **Purchase a phone number from Twilio**
|
||||
```bash
|
||||
# Twilio Console > Phone Numbers > Buy a Number
|
||||
# Select: Voice capability (required for verification)
|
||||
# Example: +553322980098
|
||||
```
|
||||
|
||||
2. **Create Meta App with WhatsApp**
|
||||
```bash
|
||||
# https://developers.facebook.com/apps/
|
||||
# Create App > Business > Add WhatsApp product
|
||||
```
|
||||
|
||||
3. **Configure credentials in `config.csv`**
|
||||
```csv
|
||||
whatsapp-enabled,true
|
||||
whatsapp-api-key,EAAQdlso6aM8BOwlhc3yM6bbJkGyibQPGJd87zFDHtfaFoJDJPohMl2c5nXs4yYuuHwoXJWx0rQKo0VXgTwThPYzqLEZArOZBhCWPBUpq7YlkEJXFAgB6ZAb3eoUzZAMgNZCZA1sg11rT2G8e1ZAgzpRVRffU4jmMChc7ybcyIwbtGOPKZAXKcNoMRfUwssoLhDWr
|
||||
whatsapp-phone-number-id,1158433381968079
|
||||
whatsapp-business-account-id,390727550789228
|
||||
whatsapp-webhook-verify-token,4qIogZadggQ.BEoMeciXIdl_MlkV_1DTx8Z_i0bYPxtSJwKSbH0FKlY
|
||||
whatsapp-application-id,323250907549153
|
||||
```
|
||||
|
||||
### BASIC Keywords for WhatsApp
|
||||
|
||||
```basic
|
||||
REM Send a message
|
||||
SEND WHATSAPP TO "+5511999999999" WITH "Hello from General Bots!"
|
||||
|
||||
REM Handle incoming messages
|
||||
ON WHATSAPP MESSAGE RECEIVED
|
||||
LET SENDER$ = GET WHATSAPP SENDER NUMBER
|
||||
LET MESSAGE$ = GET WHATSAPP MESSAGE BODY
|
||||
|
||||
REM Echo message back
|
||||
SEND WHATSAPP TO SENDER$ WITH "You said: " + MESSAGE$
|
||||
END ON
|
||||
```
|
||||
|
||||
### Credential Reference
|
||||
|
||||
| Credential | Format | Example | Purpose |
|
||||
|------------|--------|---------|---------|
|
||||
| Access Token | `EAAQ...` | `EAAQdlso6aM8BOwl...` | API authentication |
|
||||
| Phone Number ID | 16 digits | `1158433381968079` | Message sending endpoint |
|
||||
| WABA ID | 15 digits | `390727550789228` | Business account identifier |
|
||||
| Verify Token | Custom string | `4qIogZadggQ.BEoMeci...` | Webhook security |
|
||||
| Application ID | 15 digits | `323250907549153` | App identifier |
|
||||
|
||||
### Phone Number Verification
|
||||
|
||||
Twilio numbers require **voice call verification** (not SMS):
|
||||
|
||||
1. **Configure Twilio webhook** to capture verification calls
|
||||
```xml
|
||||
<!-- TwiML for voice handling -->
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<Response>
|
||||
<Gather action="https://twimlets.com/voicemail?Email=your@email.com">
|
||||
<Say voice="alice">Please enter your verification code.</Say>
|
||||
</Gather>
|
||||
</Response>
|
||||
```
|
||||
|
||||
2. **In Meta Business Suite**: Select "Phone Call" verification method
|
||||
3. **Enter the 6-digit code** received via email
|
||||
4. **Verification complete** - number ready for WhatsApp
|
||||
|
||||
See: [Webhook Configuration Guide](./whatsapp-webhooks.md)
|
||||
|
||||
## Advanced Configuration
|
||||
|
||||
### Message Templates
|
||||
|
||||
For business-initiated messages outside the 24-hour window:
|
||||
|
||||
```javascript
|
||||
// Send template message
|
||||
POST https://graph.facebook.com/v18.0/1158433381968079/messages
|
||||
{
|
||||
"messaging_product": "whatsapp",
|
||||
"to": "5511999999999",
|
||||
"type": "template",
|
||||
"template": {
|
||||
"name": "hello_world",
|
||||
"language": { "code": "pt_BR" }
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Rate Limiting
|
||||
|
||||
WhatsApp enforces rate limits per tier:
|
||||
|
||||
| Tier | Messages/Day | Messages/Second |
|
||||
|------|--------------|-----------------|
|
||||
| Tier 1 | 1,000 | 1 |
|
||||
| Tier 2 | 10,000 | 5 |
|
||||
| Tier 3 | 100,000 | 50 |
|
||||
| Tier 4 | Unlimited | 1,000 |
|
||||
|
||||
Implement rate limiting in your bot:
|
||||
|
||||
```basic
|
||||
REM Simple rate limiting
|
||||
LET LAST_SENT = 0
|
||||
SUB SEND WHATSAPP WITH LIMIT TO NUMBER$, MESSAGE$
|
||||
LET NOW = TIMER
|
||||
IF NOW - LAST_SENT < 1 THEN
|
||||
WAIT 1 - (NOW - LAST_SENT)
|
||||
END IF
|
||||
SEND WHATSAPP TO NUMBER$ WITH MESSAGE$
|
||||
LAST_SENT = TIMER
|
||||
END SUB
|
||||
```
|
||||
|
||||
### Webhook Security
|
||||
|
||||
Always verify webhook signatures:
|
||||
|
||||
```javascript
|
||||
// Node.js signature verification
|
||||
const crypto = require('crypto');
|
||||
|
||||
function verifySignature(payload, signature, appSecret) {
|
||||
const expected = 'sha256=' +
|
||||
crypto.createHmac('sha256', appSecret)
|
||||
.update(payload)
|
||||
.digest('hex');
|
||||
return crypto.timingSafeEqual(
|
||||
Buffer.from(signature),
|
||||
Buffer.from(expected)
|
||||
);
|
||||
}
|
||||
```
|
||||
|
||||
## Complete Documentation
|
||||
|
||||
For detailed guides and examples:
|
||||
|
||||
- **[WhatsApp Quick Start Guide](./whatsapp-quick-start.md)** - 30-minute setup walkthrough
|
||||
- **[Webhook Configuration](./whatsapp-webhooks.md)** - Detailed webhook setup for Twilio and Meta
|
||||
- **[Code Examples](./whatsapp-examples.md)** - Examples in BASIC, Node.js, and Python
|
||||
- **[Troubleshooting Guide](./whatsapp-troubleshooting.md)** - Common issues and solutions
|
||||
- **[Quick Reference](./whatsapp-quick-reference.md)** - Commands, configs, and snippets
|
||||
|
||||
## Other Channels
|
||||
|
||||
### Twilio SMS
|
||||
|
||||
Simple SMS integration using Twilio:
|
||||
|
||||
```csv
|
||||
# config.csv
|
||||
twilio-account-sid,ACxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
|
||||
twilio-auth-token,your_auth_token_here
|
||||
twilio-from-number,+15551234567
|
||||
```
|
||||
|
||||
```basic
|
||||
REM Send SMS
|
||||
SEND SMS TO "+5511999999999" WITH "Hello via SMS!"
|
||||
```
|
||||
|
||||
### Instagram Direct Messages
|
||||
|
||||
Connect Instagram messaging:
|
||||
|
||||
```csv
|
||||
# config.csv
|
||||
instagram-access-token,EAAxxxx...
|
||||
instagram-page-id,123456789012345
|
||||
```
|
||||
|
||||
```basic
|
||||
REM Send Instagram DM
|
||||
SEND INSTAGRAM TO "1234567890" WITH "Hello via Instagram!"
|
||||
```
|
||||
|
||||
## Configuration Template
|
||||
|
||||
Complete channel configuration example:
|
||||
|
||||
```csv
|
||||
# config.csv
|
||||
|
||||
# WhatsApp Business (Primary channel)
|
||||
whatsapp-enabled,true
|
||||
whatsapp-api-key,EAAQdlso6aM8BOwlhc3yM6bbJkGyibQPGJd87zFDHtfaFoJDJPohMl2c5nXs4yYuuHwoXJWx0rQKo0VXgTwThPYzqLEZArOZBhCWPBUpq7YlkEJXFAgB6ZAb3eoUzZAMgNZCZA1sg11rT2G8e1ZAgzpRVRffU4jmMChc7ybcyIwbtGOPKZAXKcNoMRfUwssoLhDWr
|
||||
whatsapp-phone-number-id,1158433381968079
|
||||
whatsapp-business-account-id,390727550789228
|
||||
whatsapp-webhook-verify-token,4qIogZadggQ.BEoMeciXIdl_MlkV_1DTx8Z_i0bYPxtSJwKSbH0FKlY
|
||||
|
||||
# Twilio SMS (Backup channel)
|
||||
twilio-enabled,false
|
||||
twilio-account-sid,ACxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
|
||||
twilio-auth-token,your_auth_token_here
|
||||
twilio-from-number,+15551234567
|
||||
|
||||
# Instagram (Social channel)
|
||||
instagram-enabled,false
|
||||
instagram-access-token,EAAxxxx...
|
||||
instagram-page-id,123456789012345
|
||||
```
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
### Common Issues
|
||||
|
||||
**Issue: Phone number verification fails**
|
||||
- **Solution**: Ensure "Phone Call" verification is selected (not SMS)
|
||||
- **Solution**: Verify Twilio webhook is configured correctly
|
||||
- See: [Troubleshooting Guide](./whatsapp-troubleshooting.md)
|
||||
|
||||
**Issue: Messages not sending**
|
||||
- **Solution**: Check access token validity
|
||||
- **Solution**: Verify phone number format: `5511999999999` (no +, no spaces)
|
||||
- **Solution**: Ensure webhook is subscribed to "messages" field
|
||||
|
||||
**Issue: Rate limit errors**
|
||||
- **Solution**: Implement rate limiting in your bot
|
||||
- **Solution**: Use message queues for bulk sending
|
||||
- See: [Code Examples](./whatsapp-examples.md)
|
||||
|
||||
## Best Practices
|
||||
|
||||
1. **Never hardcode credentials** - Always use `config.csv`
|
||||
2. **Implement retry logic** - Handle API failures gracefully
|
||||
3. **Monitor rate limits** - Respect platform limits
|
||||
4. **Secure webhooks** - Verify all incoming requests
|
||||
5. **Test thoroughly** - Use ngrok for local testing
|
||||
6. **Log everything** - Track message delivery and errors
|
||||
7. **Use templates** - Pre-approved templates for business-initiated messages
|
||||
8. **Handle errors** - Provide user-friendly error messages
|
||||
|
||||
## Support
|
||||
|
||||
- **Documentation**: [Full guide](./whatsapp-quick-start.md)
|
||||
- **Examples**: [Code samples](./whatsapp-examples.md)
|
||||
- **Community**: [General Bots Discord](https://discord.gg/general-bots)
|
||||
- **Meta Docs**: [WhatsApp Business API](https://developers.facebook.com/docs/whatsapp/)
|
||||
- **Twilio Docs**: [Twilio WhatsApp](https://www.twilio.com/docs/whatsapp)
|
||||
|
||||
## Next Steps
|
||||
|
||||
1. Complete the [Quick Start Guide](./whatsapp-quick-start.md)
|
||||
2. Set up webhooks using [Webhook Configuration](./whatsapp-webhooks.md)
|
||||
3. Explore [Code Examples](./whatsapp-examples.md) for your use case
|
||||
4. Configure monitoring and error handling
|
||||
5. Test with your team before launching to users
|
||||
|
||||
For configuration of other services (LLM providers, databases, etc.), see [Appendix B: External Services](./README.md).
|
||||
1410
src/18-appendix-external-services/whatsapp-examples.md
Normal file
1410
src/18-appendix-external-services/whatsapp-examples.md
Normal file
File diff suppressed because it is too large
Load diff
678
src/18-appendix-external-services/whatsapp-quick-reference.md
Normal file
678
src/18-appendix-external-services/whatsapp-quick-reference.md
Normal file
|
|
@ -0,0 +1,678 @@
|
|||
# Quick Reference Guide
|
||||
|
||||
Essential commands, configurations, and code snippets for WhatsApp Business API integration with Twilio.
|
||||
|
||||
## Configuration Keys
|
||||
|
||||
### Required config.csv Entries
|
||||
|
||||
```csv
|
||||
# Core Configuration
|
||||
whatsapp-enabled,true
|
||||
whatsapp-api-key,EAAQdlso6aM8BOwlhc3yM6bbJkGyibQPGJd87zFDHtfaFoJDJPohMl2c5nXs4yYuuHwoXJWx0rQKo0VXgTwThPYzqLEZArOZBhCWPBUpq7YlkEJXFAgB6ZAb3eoUzZAMgNZCZA1sg11rT2G8e1ZAgzpRVRffU4jmMChc7ybcyIwbtGOPKZAXKcNoMRfUwssoLhDWr
|
||||
whatsapp-phone-number-id,1158433381968079
|
||||
whatsapp-business-account-id,390727550789228
|
||||
whatsapp-webhook-verify-token,4qIogZadggQ.BEoMeciXIdl_MlkV_1DTx8Z_i0bYPxtSJwKSbH0FKlY
|
||||
whatsapp-application-id,323250907549153
|
||||
|
||||
# Optional: Advanced Settings
|
||||
whatsapp-webhook-url,https://your-domain.com/webhooks/whatsapp
|
||||
whatsapp-timeout,30000
|
||||
whatsapp-retry-attempts,3
|
||||
whatsapp-rate-limit,50
|
||||
whatsapp-from-number,+553322980098
|
||||
```
|
||||
|
||||
### Environment Variables
|
||||
|
||||
```bash
|
||||
# Meta WhatsApp Configuration
|
||||
export WHATSAPP_API_KEY="EAAQdlso6aM8BOwl..."
|
||||
export WHATSAPP_PHONE_NUMBER_ID="1158433381968079"
|
||||
export WHATSAPP_WABA_ID="390727550789228"
|
||||
export WHATSAPP_VERIFY_TOKEN="4qIogZadggQ.BEoMeci..."
|
||||
export WHATSAPP_APPLICATION_ID="323250907549153"
|
||||
export WHATSAPP_APP_SECRET="your_app_secret_here"
|
||||
|
||||
# Twilio Configuration
|
||||
export TWILIO_ACCOUNT_SID="ACxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
|
||||
export TWILIO_AUTH_TOKEN="your_auth_token_here"
|
||||
export TWILIO_PHONE_NUMBER="+553322980098"
|
||||
|
||||
# Webhook Configuration
|
||||
export WEBHOOK_URL="https://your-domain.com/webhooks/whatsapp"
|
||||
export WEBHOOK_PORT="3000"
|
||||
```
|
||||
|
||||
## API Endpoints
|
||||
|
||||
### Meta WhatsApp API
|
||||
|
||||
```bash
|
||||
# Base URL
|
||||
https://graph.facebook.com/v18.0
|
||||
|
||||
# Send Message
|
||||
POST /{phone-number-id}/messages
|
||||
|
||||
# Get Phone Number Info
|
||||
GET /{phone-number-id}
|
||||
|
||||
# Mark as Read
|
||||
POST /{message-id}
|
||||
|
||||
# Upload Media
|
||||
POST /{phone-number-id}/media
|
||||
|
||||
# Get Message Templates
|
||||
GET /{waba-id}/message_templates
|
||||
```
|
||||
|
||||
### Twilio API
|
||||
|
||||
```bash
|
||||
# Base URL
|
||||
https://api.twilio.com/2010-04-01
|
||||
|
||||
# Incoming Call Webhook
|
||||
POST /twilio/voice
|
||||
|
||||
# Gather Handler
|
||||
POST /twilio/gather
|
||||
|
||||
# Get Call Logs
|
||||
GET /Accounts/{AccountSid}/Calls.json
|
||||
```
|
||||
|
||||
## Common API Requests
|
||||
|
||||
### Send Text Message
|
||||
|
||||
```bash
|
||||
curl -X POST \
|
||||
'https://graph.facebook.com/v18.0/1158433381968079/messages' \
|
||||
-H 'Authorization: Bearer EAAQdlso6aM8BOwl...' \
|
||||
-H 'Content-Type: application/json' \
|
||||
-d '{
|
||||
"messaging_product": "whatsapp",
|
||||
"to": "5511999999999",
|
||||
"type": "text",
|
||||
"text": {
|
||||
"body": "Hello from General Bots!"
|
||||
}
|
||||
}'
|
||||
```
|
||||
|
||||
### Send Image
|
||||
|
||||
```bash
|
||||
curl -X POST \
|
||||
'https://graph.facebook.com/v18.0/1158433381968079/messages' \
|
||||
-H 'Authorization: Bearer EAAQdlso6aM8BOwl...' \
|
||||
-H 'Content-Type: application/json' \
|
||||
-d '{
|
||||
"messaging_product": "whatsapp",
|
||||
"to": "5511999999999",
|
||||
"type": "image",
|
||||
"image": {
|
||||
"link": "https://example.com/image.jpg",
|
||||
"caption": "Check this out!"
|
||||
}
|
||||
}'
|
||||
```
|
||||
|
||||
### Send Template
|
||||
|
||||
```bash
|
||||
curl -X POST \
|
||||
'https://graph.facebook.com/v18.0/1158433381968079/messages' \
|
||||
-H 'Authorization: Bearer EAAQdlso6aM8BOwl...' \
|
||||
-H 'Content-Type: application/json' \
|
||||
-d '{
|
||||
"messaging_product": "whatsapp",
|
||||
"to": "5511999999999",
|
||||
"type": "template",
|
||||
"template": {
|
||||
"name": "hello_world",
|
||||
"language": {
|
||||
"code": "en_US"
|
||||
}
|
||||
}
|
||||
}'
|
||||
```
|
||||
|
||||
### Mark as Read
|
||||
|
||||
```bash
|
||||
curl -X POST \
|
||||
'https://graph.facebook.com/v18.0/wamid.HBgLNTE1OTk5OTk5OTk5FQIAERgSMzg1QTlCNkE2RTlFRTdFNDdF' \
|
||||
-H 'Authorization: Bearer EAAQdlso6aM8BOwl...' \
|
||||
-H 'Content-Type: application/json' \
|
||||
-d '{
|
||||
"messaging_product": "whatsapp",
|
||||
"status": "read"
|
||||
}'
|
||||
```
|
||||
|
||||
## BASIC Keywords
|
||||
|
||||
### Sending Messages
|
||||
|
||||
```basic
|
||||
REM Send simple text
|
||||
SEND WHATSAPP TO "+5511999999999" WITH "Hello!"
|
||||
|
||||
REM Send with formatting
|
||||
SEND WHATSAPP TO "+5511999999999" WITH "*Bold* and _italics_"
|
||||
|
||||
REM Send location
|
||||
SEND WHATSAPP TO "+5511999999999" WITH LOCATION AT "-23.5505,-46.6333"
|
||||
|
||||
REM Send image
|
||||
SEND WHATSAPP TO "+5511999999999" WITH IMAGE FROM "https://example.com/img.jpg"
|
||||
|
||||
REM Send document
|
||||
SEND WHATSAPP TO "+5511999999999" WITH DOCUMENT FROM "https://example.com/doc.pdf"
|
||||
```
|
||||
|
||||
### Receiving Messages
|
||||
|
||||
```basic
|
||||
REM Handle incoming messages
|
||||
ON WHATSAPP MESSAGE RECEIVED
|
||||
LET SENDER$ = GET WHATSAPP SENDER NUMBER
|
||||
LET MESSAGE$ = GET WHATSAPP MESSAGE BODY
|
||||
LET ID$ = GET WHATSAPP MESSAGE ID
|
||||
LET TIMESTAMP$ = GET WHATSAPP MESSAGE TIMESTAMP
|
||||
|
||||
LOG "From: " + SENDER$ + " Msg: " + MESSAGE$
|
||||
|
||||
REM Process message
|
||||
PROCESS MESSAGE SENDER$, MESSAGE$
|
||||
END ON
|
||||
```
|
||||
|
||||
## Error Codes
|
||||
|
||||
### Common HTTP Status Codes
|
||||
|
||||
| Code | Meaning | Solution |
|
||||
|------|---------|----------|
|
||||
| 200 | Success | Request completed |
|
||||
| 400 | Bad Request | Check request body |
|
||||
| 401 | Unauthorized | Verify access token |
|
||||
| 403 | Forbidden | Check permissions |
|
||||
| 404 | Not Found | Verify phone number ID |
|
||||
| 429 | Rate Limited | Implement backoff |
|
||||
| 500 | Server Error | Retry later |
|
||||
|
||||
### WhatsApp-Specific Errors
|
||||
|
||||
```json
|
||||
{
|
||||
"error": {
|
||||
"message": "Invalid parameter",
|
||||
"type": "WhatsAppApiError",
|
||||
"code": 130426,
|
||||
"error_data": {
|
||||
"details": "Phone number ID is required"
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
| Error Code | Description | Solution |
|
||||
|------------|-------------|----------|
|
||||
| 130426 | Invalid parameter | Check phone number format |
|
||||
| 130472 | Rate limit hit | Reduce message frequency |
|
||||
| 131056 | 24-hour window | Use message templates |
|
||||
| 131047 | Media upload failed | Check media URL |
|
||||
| 131053 | Template not approved | Submit template for review |
|
||||
|
||||
## Phone Number Formatting
|
||||
|
||||
### Correct Formats
|
||||
|
||||
```javascript
|
||||
// Remove all non-digits
|
||||
function formatPhone(phone) {
|
||||
return phone.replace(/\D/g, '');
|
||||
}
|
||||
|
||||
// Examples
|
||||
Input: +55 (11) 99999-9999
|
||||
Output: 5511999999999
|
||||
|
||||
Input: +1-555-123-4567
|
||||
Output: 15551234567
|
||||
|
||||
Input: 55 11 99999 9999
|
||||
Output: 5511999999999
|
||||
```
|
||||
|
||||
### Country Codes
|
||||
|
||||
| Country | Code | Example |
|
||||
|---------|------|---------|
|
||||
| Brazil | 55 | 5511999999999 |
|
||||
| USA | 1 | 15551234567 |
|
||||
| Mexico | 52 | 5215512345678 |
|
||||
| Argentina | 54 | 5491112345678 |
|
||||
| Portugal | 351 | 351912345678 |
|
||||
|
||||
## Webhook Payloads
|
||||
|
||||
### Incoming Message
|
||||
|
||||
```json
|
||||
{
|
||||
"object": "whatsapp_business_account",
|
||||
"entry": [{
|
||||
"id": "390727550789228",
|
||||
"changes": [{
|
||||
"value": {
|
||||
"messaging_product": "whatsapp",
|
||||
"metadata": {
|
||||
"display_phone_number": "+553322980098",
|
||||
"phone_number_id": "1158433381968079"
|
||||
},
|
||||
"contacts": [{
|
||||
"profile": {
|
||||
"name": "John Doe"
|
||||
},
|
||||
"wa_id": "5511999999999"
|
||||
}],
|
||||
"messages": [{
|
||||
"from": "5511999999999",
|
||||
"id": "wamid.HBgLNTE1OTk5OTk5OTk5FQIAERgSMzg1QTlCNkE2RTlFRTdFNDdF",
|
||||
"timestamp": "1704067200",
|
||||
"text": {
|
||||
"body": "Hello bot!"
|
||||
},
|
||||
"type": "text"
|
||||
}]
|
||||
},
|
||||
"field": "messages"
|
||||
}]
|
||||
}]
|
||||
}
|
||||
```
|
||||
|
||||
### Message Status
|
||||
|
||||
```json
|
||||
{
|
||||
"object": "whatsapp_business_account",
|
||||
"entry": [{
|
||||
"id": "390727550789228",
|
||||
"changes": [{
|
||||
"value": {
|
||||
"status": "sent",
|
||||
"id": "wamid.HBgLNTE1OTk5OTk5OTk5FQIAERgSMzg1QTlCNkE2RTlFRTdFNDdF",
|
||||
"timestamp": "1704067201"
|
||||
},
|
||||
"field": "message_template_status_update"
|
||||
}]
|
||||
}]
|
||||
}
|
||||
```
|
||||
|
||||
## TwiML Examples
|
||||
|
||||
### Gather Verification Code
|
||||
|
||||
```xml
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<Response>
|
||||
<Gather action="https://your-domain.com/twilio/gather"
|
||||
method="POST"
|
||||
numDigits="6"
|
||||
timeout="10">
|
||||
<Say voice="alice" language="pt-BR">
|
||||
Please enter your verification code followed by the pound sign.
|
||||
</Say>
|
||||
</Gather>
|
||||
<Redirect>
|
||||
https://twimlets.com/voicemail?Email=your-email@example.com
|
||||
</Redirect>
|
||||
</Response>
|
||||
```
|
||||
|
||||
### Simple Voicemail
|
||||
|
||||
```xml
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<Response>
|
||||
<Say>Please leave your message after the tone.</Say>
|
||||
<Record action="https://your-domain.com/twilio/recording"
|
||||
method="POST"
|
||||
maxLength="30" />
|
||||
<Say>Thank you for your message.</Say>
|
||||
</Response>
|
||||
```
|
||||
|
||||
## Diagnostic Commands
|
||||
|
||||
### Test Connectivity
|
||||
|
||||
```bash
|
||||
# Test webhook endpoint
|
||||
curl -X POST https://your-domain.com/webhooks/whatsapp \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{"test": true}'
|
||||
|
||||
# Test Meta API
|
||||
curl -X GET "https://graph.facebook.com/v18.0/1158433381968079" \
|
||||
-H "Authorization: Bearer EAAQdlso6aM8BOwl..."
|
||||
|
||||
# Test Twilio webhook
|
||||
curl -X POST https://your-domain.com/twilio/voice \
|
||||
-d "CallSid=CA123&From=+1234567890&To=+553322980098"
|
||||
|
||||
# Check SSL certificate
|
||||
openssl s_client -connect your-domain.com:443
|
||||
```
|
||||
|
||||
### Monitor Logs
|
||||
|
||||
```bash
|
||||
# General Bots logs
|
||||
tail -f .gbot/logs/bot.log
|
||||
|
||||
# Webhook server logs (PM2)
|
||||
pm2 logs whatsapp-webhook
|
||||
|
||||
# System logs
|
||||
journalctl -u whatsapp-webhook -f
|
||||
|
||||
# Twilio debugger
|
||||
# https://console.twilio.com/us1/develop/monitor/debugger
|
||||
|
||||
# Meta webhook status
|
||||
# https://developers.facebook.com/apps/YOUR_APP_ID/webhooks/
|
||||
```
|
||||
|
||||
## Rate Limits
|
||||
|
||||
### WhatsApp Business API
|
||||
|
||||
| Tier | Messages/Day | Messages/Second |
|
||||
|------|--------------|-----------------|
|
||||
| Tier 1 | 1,000 | 1 |
|
||||
| Tier 2 | 10,000 | 5 |
|
||||
| Tier 3 | 100,000 | 50 |
|
||||
| Tier 4 | Unlimited | 1,000 |
|
||||
|
||||
### Rate Limiting Implementation
|
||||
|
||||
```javascript
|
||||
const rateLimiter = {
|
||||
requests: [],
|
||||
maxRequests: 50,
|
||||
timeWindow: 60000, // 1 minute
|
||||
|
||||
canMakeRequest() {
|
||||
const now = Date.now();
|
||||
this.requests = this.requests.filter(t => now - t < this.timeWindow);
|
||||
return this.requests.length < this.maxRequests;
|
||||
},
|
||||
|
||||
recordRequest() {
|
||||
this.requests.push(Date.now());
|
||||
}
|
||||
};
|
||||
```
|
||||
|
||||
## Formatting Syntax
|
||||
|
||||
### Text Formatting
|
||||
|
||||
```basic
|
||||
REM Bold text
|
||||
*bold text*
|
||||
|
||||
REM Italics
|
||||
_italics_
|
||||
|
||||
REM Strikethrough
|
||||
~strikethrough~
|
||||
|
||||
REM Monospace
|
||||
```monospace```
|
||||
|
||||
REM Combined
|
||||
*_bold and italic_*
|
||||
|
||||
REM Line breaks
|
||||
Line 1
|
||||
Line 2
|
||||
```
|
||||
|
||||
### Message Examples
|
||||
|
||||
```basic
|
||||
REM Formatted menu
|
||||
SEND WHATSAPP TO "+5511999999999" WITH "🤖 *Bot Menu*" + CHR$(10) + CHR$(10) + "1. 📊 Status" + CHR$(10) + "2. 🌐 Weather" + CHR$(10) + "3. 📧 Contact"
|
||||
|
||||
REM Address
|
||||
SEND WHATSAPP TO "+5511999999999" WITH "📍 *Address:*" + CHR$(10) + "123 Main St" + CHR$(10) + "São Paulo, SP" + CHR$(10) + "Brazil"
|
||||
|
||||
REM Code snippet
|
||||
SEND WHATSAPP TO "+5511999999999" WITH "```bash" + CHR$(10) + "npm install" + CHR$(10) + "```"
|
||||
```
|
||||
|
||||
## URLs
|
||||
|
||||
### Meta Platforms
|
||||
|
||||
```
|
||||
Meta for Developers:
|
||||
https://developers.facebook.com/
|
||||
|
||||
Meta Business Suite:
|
||||
https://business.facebook.com/
|
||||
|
||||
WhatsApp Business API:
|
||||
https://developers.facebook.com/docs/whatsapp/
|
||||
|
||||
Webhook Configuration:
|
||||
https://developers.facebook.com/apps/YOUR_APP_ID/webhooks/
|
||||
|
||||
Message Templates:
|
||||
https://business.facebook.com/latest/wa/manage/message-templates/
|
||||
```
|
||||
|
||||
### Twilio Platforms
|
||||
|
||||
```
|
||||
Twilio Console:
|
||||
https://console.twilio.com/
|
||||
|
||||
Twilio Debugger:
|
||||
https://console.twilio.com/us1/develop/monitor/debugger
|
||||
|
||||
TwiML Bins:
|
||||
https://console.twilio.com/us1/develop/twiml/bins
|
||||
|
||||
Phone Numbers:
|
||||
https://console.twilio.com/us1/develop/phone-numbers/manage/active
|
||||
```
|
||||
|
||||
### General Bots
|
||||
|
||||
```
|
||||
Documentation:
|
||||
https://botbook.general-bots.com/
|
||||
|
||||
Community Discord:
|
||||
https://discord.gg/general-bots
|
||||
|
||||
GitHub Repository:
|
||||
https://github.com/general-bots/general-bots
|
||||
```
|
||||
|
||||
## Quick Troubleshooting
|
||||
|
||||
### Issue: Verification Code Not Received
|
||||
|
||||
```bash
|
||||
# Check Twilio webhook is configured
|
||||
twilio phone-numerals:info +553322980098
|
||||
|
||||
# Test webhook manually
|
||||
curl -X POST https://your-domain.com/twilio/voice \
|
||||
-d "CallSid=CA123&From=+1234567890"
|
||||
|
||||
# Verify voice capability is enabled
|
||||
# In Twilio Console: Phone Numbers > Active Numbers > Your Number
|
||||
# Check "Voice" is enabled
|
||||
```
|
||||
|
||||
### Issue: Messages Not Sending
|
||||
|
||||
```bash
|
||||
# Verify access token
|
||||
curl -X GET "https://graph.facebook.com/v18.0/me" \
|
||||
-H "Authorization: Bearer YOUR_TOKEN"
|
||||
|
||||
# Check phone number ID
|
||||
curl -X GET "https://graph.facebook.com/v18.0/1158433381968079" \
|
||||
-H "Authorization: Bearer YOUR_TOKEN"
|
||||
|
||||
# Test message format
|
||||
# Ensure phone number: 5511999999999 (no +, no spaces)
|
||||
```
|
||||
|
||||
### Issue: Webhook Not Receiving Messages
|
||||
|
||||
```bash
|
||||
# Verify webhook subscription
|
||||
curl -X GET "https://graph.facebook.com/v18.0/YOUR_APP_ID/subscriptions" \
|
||||
-H "Authorization: Bearer YOUR_TOKEN"
|
||||
|
||||
# Test webhook endpoint
|
||||
curl -X POST https://your-domain.com/webhooks/whatsapp \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{"object":"whatsapp_business_account","entry":[]}'
|
||||
|
||||
# Check webhook is subscribed to "messages" field
|
||||
# In Meta Dashboard: WhatsApp > API Setup > Webhook > Manage
|
||||
```
|
||||
|
||||
## Code Snippets
|
||||
|
||||
### Validate Phone Number
|
||||
|
||||
```javascript
|
||||
function validatePhoneNumber(phone) {
|
||||
// Remove non-digits
|
||||
const cleaned = phone.replace(/\D/g, '');
|
||||
|
||||
// Check length (10-15 digits)
|
||||
if (cleaned.length < 10 || cleaned.length > 15) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Check if all digits
|
||||
if (!/^\d+$/.test(cleaned)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return cleaned;
|
||||
}
|
||||
```
|
||||
|
||||
### Format WhatsApp Message
|
||||
|
||||
```javascript
|
||||
function formatMessage(template, variables) {
|
||||
let message = template;
|
||||
|
||||
for (const [key, value] of Object.entries(variables)) {
|
||||
message = message.replace(new RegExp(`{{${key}}}`, 'g'), value);
|
||||
}
|
||||
|
||||
return message;
|
||||
}
|
||||
|
||||
// Usage
|
||||
const template = 'Hello {{name}}, your order {{orderId}} is confirmed!';
|
||||
const variables = { name: 'John', orderId: '12345' };
|
||||
const message = formatMessage(template, variables);
|
||||
// Result: "Hello John, your order 12345 is confirmed!"
|
||||
```
|
||||
|
||||
### Retry Logic
|
||||
|
||||
```javascript
|
||||
async function sendWithRetry(whatsapp, to, message, maxRetries = 3) {
|
||||
for (let attempt = 1; attempt <= maxRetries; attempt++) {
|
||||
try {
|
||||
return await whatsapp.sendText(to, message);
|
||||
} catch (error) {
|
||||
if (attempt === maxRetries) {
|
||||
throw error;
|
||||
}
|
||||
|
||||
// Exponential backoff
|
||||
const delay = Math.pow(2, attempt) * 1000;
|
||||
await new Promise(resolve => setTimeout(resolve, delay));
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## Environment Checklist
|
||||
|
||||
### Development
|
||||
|
||||
```bash
|
||||
# Node.js
|
||||
npm install express twilio body-parser axios
|
||||
|
||||
# Python
|
||||
pip install flask requests twilio
|
||||
|
||||
# BASIC
|
||||
REM No installation required
|
||||
```
|
||||
|
||||
### Production
|
||||
|
||||
```bash
|
||||
# Reverse proxy (nginx)
|
||||
apt install nginx
|
||||
|
||||
# Process manager (PM2)
|
||||
npm install -g pm2
|
||||
|
||||
# SSL certificate (Let's Encrypt)
|
||||
apt install certbot python3-certbot-nginx
|
||||
```
|
||||
|
||||
## Meta Console URLs
|
||||
|
||||
### Direct Access
|
||||
|
||||
Replace with your IDs:
|
||||
|
||||
```
|
||||
WhatsApp Settings:
|
||||
https://business.facebook.com/latest/settings/whatsapp_account/?business_id=312254061496740&selected_asset_id=303621682831134&selected_asset_type=whatsapp-business-account
|
||||
|
||||
Webhook Configuration:
|
||||
https://developers.facebook.com/apps/323250907549153/webhooks/
|
||||
|
||||
Message Templates:
|
||||
https://business.facebook.com/latest/wa/manage/message-templates/?waba_id=390727550789228
|
||||
|
||||
API Usage:
|
||||
https://developers.facebook.com/apps/323250907549153/usage/
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
**For detailed documentation:** See [README.md](./README.md)
|
||||
**For troubleshooting:** See [troubleshooting.md](./troubleshooting.md)
|
||||
**For code examples:** See [examples.md](./examples.md)
|
||||
**For webhook setup:** See [webhooks.md](./webhooks.md)
|
||||
298
src/18-appendix-external-services/whatsapp-quick-start.md
Normal file
298
src/18-appendix-external-services/whatsapp-quick-start.md
Normal file
|
|
@ -0,0 +1,298 @@
|
|||
# Quick Start Guide
|
||||
|
||||
Get your WhatsApp Business bot up and running in 30 minutes with this streamlined setup guide.
|
||||
|
||||
## Prerequisites Checklist
|
||||
|
||||
- [ ] Twilio account with $10+ credit
|
||||
- [ ] Meta for Developers account
|
||||
- [ ] Meta Business Suite account
|
||||
- [ ] Publicly accessible webhook URL (use ngrok for testing)
|
||||
- [ ] Basic command line knowledge
|
||||
|
||||
## 30-Minute Setup
|
||||
|
||||
### Step 1: Buy Twilio Number (5 minutes)
|
||||
|
||||
```bash
|
||||
# Log into Twilio Console
|
||||
# https://console.twilio.com/
|
||||
|
||||
# Navigate to: Phone Numbers > Buy a Number
|
||||
# Select: Voice capability (required!)
|
||||
# Purchase number
|
||||
# Example: +553322980098
|
||||
```
|
||||
|
||||
**Tip:** Choose a number from your target country for easier verification.
|
||||
|
||||
### Step 2: Create Meta App (5 minutes)
|
||||
|
||||
```bash
|
||||
# Go to Meta for Developers
|
||||
# https://developers.facebook.com/apps/
|
||||
|
||||
# Click: Create App > Business type
|
||||
# App name: "My WhatsApp Bot"
|
||||
# Add product: WhatsApp
|
||||
# Create WhatsApp Business Account (WABA)
|
||||
```
|
||||
|
||||
**Save these values:**
|
||||
```
|
||||
WABA ID: 390727550789228
|
||||
Application ID: 323250907549153
|
||||
Phone Number ID: (after verification)
|
||||
```
|
||||
|
||||
### Step 3: Configure Twilio Webhook (5 minutes)
|
||||
|
||||
**Option A: TwiML Bin (Fastest)**
|
||||
|
||||
```xml
|
||||
<!-- Create TwiML Bin in Twilio Console -->
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<Response>
|
||||
<Gather action="https://twimlets.com/voicemail?Email=your-email@example.com" method="POST">
|
||||
<Say voice="alice">Please enter your verification code.</Say>
|
||||
</Gather>
|
||||
</Response>
|
||||
```
|
||||
|
||||
**Option B: ngrok + Node.js (Recommended)**
|
||||
|
||||
```bash
|
||||
# Install dependencies
|
||||
npm install express twilio body-parser
|
||||
|
||||
# Create server.js
|
||||
```
|
||||
|
||||
```javascript
|
||||
const express = require('express');
|
||||
const twilio = require('twilio');
|
||||
const app = express();
|
||||
|
||||
app.use(require('body-parser').urlencoded({ extended: false }));
|
||||
|
||||
app.post('/twilio/voice', (req, res) => {
|
||||
const twiml = new twilio.twiml.VoiceResponse();
|
||||
twiml.redirect('https://twimlets.com/voicemail?Email=your-email@example.com');
|
||||
res.type('text/xml');
|
||||
res.send(twiml.toString());
|
||||
});
|
||||
|
||||
app.listen(3000);
|
||||
```
|
||||
|
||||
```bash
|
||||
# Start ngrok
|
||||
ngrok http 3000
|
||||
|
||||
# Update Twilio number webhook to:
|
||||
# https://abc123.ngrok.io/twilio/voice
|
||||
```
|
||||
|
||||
### Step 4: Verify Phone Number (5 minutes)
|
||||
|
||||
```bash
|
||||
# In Meta Business Suite:
|
||||
# 1. WhatsApp Accounts > Add Phone Number
|
||||
# 2. Enter: +553322980098
|
||||
# 3. Select: "Phone Call" (NOT SMS!)
|
||||
# 4. Click: Verify
|
||||
|
||||
# Meta will call your Twilio number
|
||||
# Check your email for the verification code
|
||||
# Enter code in Meta dashboard
|
||||
```
|
||||
|
||||
**Critical:** Select "Phone Call" verification - Twilio numbers don't support SMS!
|
||||
|
||||
### Step 5: Get API Credentials (3 minutes)
|
||||
|
||||
```bash
|
||||
# In Meta for Developers:
|
||||
# 1. Your App > WhatsApp > API Setup
|
||||
# 2. Click: "Temporary Access Token"
|
||||
# 3. Copy token (starts with EAAQ...)
|
||||
# 4. Note Phone Number ID from URL
|
||||
```
|
||||
|
||||
**Required credentials:**
|
||||
```csv
|
||||
whatsapp-api-key,EAAQdlso6aM8BOwlhc3yM6bbJkGyibQPGJd87zFDHtfaFoJDJPohMl2c5nXs4yYuuHwoXJWx0rQKo0VXgTwThPYzqLEZArOZBhCWPBUpq7YlkEJXFAgB6ZAb3eoUzZAMgNZCZA1sg11rT2G8e1ZAgzpRVRffU4jmMChc7ybcyIwbtGOPKZAXKcNoMRfUwssoLhDWr
|
||||
whatsapp-phone-number-id,1158433381968079
|
||||
whatsapp-business-account-id,390727550789228
|
||||
whatsapp-webhook-verify-token,4qIogZadggQ.BEoMeciXIdl_MlkV_1DTx8Z_i0bYPxtSJwKSbH0FKlY
|
||||
whatsapp-application-id,323250907549153
|
||||
whatsapp-enabled,true
|
||||
```
|
||||
|
||||
### Step 6: Configure Webhook (5 minutes)
|
||||
|
||||
```bash
|
||||
# Start your webhook server
|
||||
node server.js
|
||||
|
||||
# In Meta Developers:
|
||||
# 1. WhatsApp > API Setup > Webhook > Edit
|
||||
# 2. Webhook URL: https://your-domain.com/webhooks/whatsapp
|
||||
# 3. Verify Token: 4qIogZadggQ.BEoMeciXIdl_MlkV_1DTx8Z_i0bYPxtSJwKSbH0FKlY
|
||||
# 4. Click: Verify and Save
|
||||
# 5. Subscribe to: messages
|
||||
```
|
||||
|
||||
### Step 7: Configure General Bots (2 minutes)
|
||||
|
||||
```bash
|
||||
# Edit .gbot/config.csv
|
||||
```
|
||||
|
||||
```csv
|
||||
key,value
|
||||
whatsapp-enabled,true
|
||||
whatsapp-api-key,EAAQdlso6aM8BOwlhc3yM6bbJkGyibQPGJd87zFDHtfaFoJDJPohMl2c5nXs4yYuuHwoXJWx0rQKo0VXgTwThPYzqLEZArOZBhCWPBUpq7YlkEJXFAgB6ZAb3eoUzZAMgNZCZA1sg11rT2G8e1ZAgzpRVRffU4jmMChc7ybcyIwbtGOPKZAXKcNoMRfUwssoLhDWr
|
||||
whatsapp-phone-number-id,1158433381968079
|
||||
whatsapp-business-account-id,390727550789228
|
||||
whatsapp-webhook-verify-token,4qIogZadggQ.BEoMeciXIdl_MlkV_1DTx8Z_i0bYPxtSJwKSbH0FKlY
|
||||
whatsapp-application-id,323250907549153
|
||||
```
|
||||
|
||||
### Step 8: Test Your Bot (5 minutes)
|
||||
|
||||
```bash
|
||||
# Send test message via API
|
||||
curl -X POST \
|
||||
'https://graph.facebook.com/v18.0/1158433381968079/messages' \
|
||||
-H 'Authorization: Bearer EAAQdlso6aM8BOwl...' \
|
||||
-H 'Content-Type: application/json' \
|
||||
-d '{
|
||||
"messaging_product": "whatsapp",
|
||||
"to": "5511999999999",
|
||||
"type": "text",
|
||||
"text": {"body": "Hello from General Bots!"}
|
||||
}'
|
||||
|
||||
# Or use BASIC
|
||||
```
|
||||
|
||||
```basic
|
||||
REM Test your WhatsApp integration
|
||||
SEND WHATSAPP TO "+5511999999999" WITH "Hello from General Bots!"
|
||||
```
|
||||
|
||||
## Your First WhatsApp Bot
|
||||
|
||||
Create a simple echo bot:
|
||||
|
||||
```basic
|
||||
REM Simple WhatsApp Echo Bot
|
||||
ON WHATSAPP MESSAGE RECEIVED
|
||||
LET SENDER$ = GET WHATSAPP SENDER NUMBER
|
||||
LET MESSAGE$ = GET WHATSAPP MESSAGE BODY
|
||||
|
||||
LOG "Message from " + SENDER$ + ": " + MESSAGE$
|
||||
|
||||
REM Echo back with acknowledgment
|
||||
SEND WHATSAPP TO SENDER$ WITH "You said: " + MESSAGE$
|
||||
END ON
|
||||
```
|
||||
|
||||
## Common First-Time Mistakes
|
||||
|
||||
❌ **Don't select SMS verification** - Use "Phone Call"
|
||||
❌ **Don't hardcode tokens** - Use config.csv
|
||||
❌ **Don't forget webhook subscriptions** - Subscribe to "messages"
|
||||
❌ **Don't use + in phone numbers** - Format: 5511999999999
|
||||
❌ **Don't ignore rate limits** - Max 1000 messages/second
|
||||
|
||||
## Next Steps
|
||||
|
||||
1. **Create message templates** for business-initiated conversations
|
||||
2. **Set up persistent storage** for conversation history
|
||||
3. **Implement retry logic** for failed messages
|
||||
4. **Add monitoring** for webhook health
|
||||
5. **Review security best practices**
|
||||
|
||||
## Need Help?
|
||||
|
||||
- 📖 [Full Documentation](./README.md)
|
||||
- 🔧 [Troubleshooting Guide](./troubleshooting.md)
|
||||
- 💻 [Code Examples](./examples.md)
|
||||
- 🌐 [Webhook Configuration](./webhooks.md)
|
||||
- 💬 [Community Discord](https://discord.gg/general-bots)
|
||||
|
||||
## Verification Checklist
|
||||
|
||||
- [ ] Twilio number purchased with Voice capability
|
||||
- [ ] Meta app created with WhatsApp product
|
||||
- [ ] Phone number verified via phone call
|
||||
- [ ] Access token generated and saved
|
||||
- [ ] Webhook configured and verified
|
||||
- [ ] Webhook subscribed to "messages"
|
||||
- [ ] config.csv updated with all credentials
|
||||
- [ ] Test message sent successfully
|
||||
- [ ] Incoming webhook received
|
||||
- [ ] Bot replied to test message
|
||||
|
||||
✅ **All checked? Your WhatsApp bot is live!**
|
||||
|
||||
## Quick Reference: Essential Commands
|
||||
|
||||
```bash
|
||||
# Test webhook connectivity
|
||||
curl -X POST https://your-webhook.com/webhooks/whatsapp \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{"test":true}'
|
||||
|
||||
# Check Meta API status
|
||||
curl https://developers.facebook.com/status/
|
||||
|
||||
# View Twilio call logs
|
||||
# https://console.twilio.com/us1/develop/monitor/logs/calls
|
||||
|
||||
# Test access token
|
||||
curl -X GET "https://graph.facebook.com/v18.0/me" \
|
||||
-H "Authorization: Bearer YOUR_TOKEN"
|
||||
|
||||
# Monitor bot logs
|
||||
tail -f .gbot/logs/bot.log
|
||||
```
|
||||
|
||||
## Configuration Template
|
||||
|
||||
Copy this template and replace with your values:
|
||||
|
||||
```csv
|
||||
# WhatsApp Business Configuration
|
||||
whatsapp-enabled,true
|
||||
whatsapp-api-key,YOUR_ACCESS_TOKEN_HERE
|
||||
whatsapp-phone-number-id,YOUR_PHONE_NUMBER_ID_HERE
|
||||
whatsapp-business-account-id,YOUR_WABA_ID_HERE
|
||||
whatsapp-webhook-verify-token,YOUR_VERIFY_TOKEN_HERE
|
||||
whatsapp-application-id,YOUR_APP_ID_HERE
|
||||
whatsapp-from-number,+553322980098
|
||||
|
||||
# Optional: Advanced Settings
|
||||
whatsapp-webhook-url,https://your-domain.com/webhooks/whatsapp
|
||||
whatsapp-timeout,30000
|
||||
whatsapp-retry-attempts,3
|
||||
whatsapp-rate-limit,50
|
||||
```
|
||||
|
||||
## Time-Saving Tips
|
||||
|
||||
💡 **Use ngrok for testing** - No need to deploy to test webhooks
|
||||
💡 **Save all credentials immediately** - Tokens won't be shown again
|
||||
💡 **Test with your own number first** - Verify everything works
|
||||
💡 **Enable debug logging** - Troubleshoot issues faster
|
||||
💡 **Set up monitoring early** - Catch problems before users do
|
||||
|
||||
---
|
||||
|
||||
**Estimated total time:** 30 minutes
|
||||
**Difficulty:** Intermediate
|
||||
**Cost:** ~$10/month (Twilio number + usage)
|
||||
|
||||
For detailed explanations, advanced configurations, and production deployment, see the [complete documentation](./README.md).
|
||||
1044
src/18-appendix-external-services/whatsapp-troubleshooting.md
Normal file
1044
src/18-appendix-external-services/whatsapp-troubleshooting.md
Normal file
File diff suppressed because it is too large
Load diff
632
src/18-appendix-external-services/whatsapp-webhooks.md
Normal file
632
src/18-appendix-external-services/whatsapp-webhooks.md
Normal file
|
|
@ -0,0 +1,632 @@
|
|||
# Webhook Configuration Guide
|
||||
|
||||
This guide provides detailed instructions for configuring webhooks for both Twilio (voice call handling) and Meta (WhatsApp message handling) in your General Bots integration.
|
||||
|
||||
## Overview
|
||||
|
||||
The integration requires two separate webhook configurations:
|
||||
|
||||
1. **Twilio Voice Webhook** - Handles incoming verification calls and captures verification codes
|
||||
2. **Meta WhatsApp Webhook** - Receives incoming WhatsApp messages and status updates
|
||||
|
||||
## Twilio Webhook Configuration
|
||||
|
||||
### Purpose
|
||||
|
||||
The Twilio webhook is critical during the initial phone number verification phase. Since Twilio numbers don't support SMS verification, Meta must call your number and read a 6-digit code. Your webhook must:
|
||||
|
||||
1. Answer the incoming call from Meta
|
||||
2. Capture the audio or DTMF tones (key presses)
|
||||
3. Forward the verification code to your email or logging system
|
||||
|
||||
### Webhook URL Structure
|
||||
|
||||
```
|
||||
POST https://your-domain.com/twilio/voice
|
||||
```
|
||||
|
||||
### Required HTTP Headers
|
||||
|
||||
Twilio sends these headers with every webhook request:
|
||||
|
||||
| Header | Description | Example |
|
||||
|--------|-------------|---------|
|
||||
| `X-Twilio-Signature` | Request signature for security | `RCYmLs...` |
|
||||
| `Content-Type` | Always `application/x-www-form-urlencoded` | - |
|
||||
|
||||
### Request Body Parameters
|
||||
|
||||
When a call comes in, Twilio POSTs these parameters:
|
||||
|
||||
| Parameter | Description | Example |
|
||||
|-----------|-------------|---------|
|
||||
| `CallSid` | Unique call identifier | `CA1234567890ABCDEF1234567890ABCDEF` |
|
||||
| `From` | Caller's phone number | `+1234567890` (Meta's verification number) |
|
||||
| `To` | Your Twilio number | `+553322980098` |
|
||||
| `CallStatus` | Current call status | `ringing` |
|
||||
| `Direction` | Call direction | `inbound` |
|
||||
|
||||
### TwiML Response Format
|
||||
|
||||
Your webhook must respond with TwiML (Twilio Markup Language) XML:
|
||||
|
||||
```xml
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<Response>
|
||||
<Gather action="https://your-domain.com/twilio/gather" method="POST" numDigits="6">
|
||||
<Say voice="alice" language="pt-BR">
|
||||
Please enter your verification code followed by the pound sign.
|
||||
</Say>
|
||||
</Gather>
|
||||
<Redirect>https://twimlets.com/voicemail?Email=your-email@example.com</Redirect>
|
||||
</Response>
|
||||
```
|
||||
|
||||
### Implementation Examples
|
||||
|
||||
#### Node.js/Express
|
||||
|
||||
```javascript
|
||||
const express = require('express');
|
||||
const twilio = require('twilio');
|
||||
const app = express();
|
||||
|
||||
app.post('/twilio/voice', (req, res) => {
|
||||
const twiml = new twilio.twiml.VoiceResponse();
|
||||
|
||||
const gather = twiml.gather({
|
||||
action: '/twilio/gather',
|
||||
method: 'POST',
|
||||
numDigits: 6,
|
||||
timeout: 10
|
||||
});
|
||||
|
||||
gather.say({
|
||||
voice: 'alice',
|
||||
language: 'pt-BR'
|
||||
}, 'Please enter your verification code followed by the pound key.');
|
||||
|
||||
// Fallback to voicemail if no input
|
||||
twiml.redirect('https://twimlets.com/voicemail?Email=your-email@example.com');
|
||||
|
||||
res.type('text/xml');
|
||||
res.send(twiml.toString());
|
||||
});
|
||||
|
||||
app.post('/twilio/gather', (req, res) => {
|
||||
const verificationCode = req.body.Digits;
|
||||
|
||||
console.log('WhatsApp Verification Code:', verificationCode);
|
||||
|
||||
// Send email notification
|
||||
sendEmail({
|
||||
to: 'your-email@example.com',
|
||||
subject: 'WhatsApp Verification Code',
|
||||
body: `Your verification code is: ${verificationCode}`
|
||||
});
|
||||
|
||||
const twiml = new twilio.twiml.VoiceResponse();
|
||||
twiml.say('Thank you. Your code has been received.');
|
||||
|
||||
res.type('text/xml');
|
||||
res.send(twiml.toString());
|
||||
});
|
||||
|
||||
app.listen(3000, () => {
|
||||
console.log('Twilio webhook server running on port 3000');
|
||||
});
|
||||
```
|
||||
|
||||
#### Python/Flask
|
||||
|
||||
```python
|
||||
from flask import Flask, request, Response
|
||||
from twilio.twiml.voice_response import VoiceResponse, Gather
|
||||
import smtplib
|
||||
|
||||
app = Flask(__name__)
|
||||
|
||||
@app.route('/twilio/voice', methods=['POST'])
|
||||
def voice_webhook():
|
||||
response = VoiceResponse()
|
||||
|
||||
gather = Gather(
|
||||
action='/twilio/gather',
|
||||
method='POST',
|
||||
num_digits=6,
|
||||
timeout=10
|
||||
)
|
||||
gather.say(
|
||||
'Please enter your verification code followed by the pound key.',
|
||||
voice='alice',
|
||||
language='pt-BR'
|
||||
)
|
||||
response.append(gather)
|
||||
|
||||
# Fallback to voicemail
|
||||
response.redirect('https://twimlets.com/voicemail?Email=your-email@example.com')
|
||||
|
||||
return Response(str(response), mimetype='text/xml')
|
||||
|
||||
@app.route('/twilio/gather', methods=['POST'])
|
||||
def gather_webhook():
|
||||
verification_code = request.form.get('Digits')
|
||||
|
||||
print(f'WhatsApp Verification Code: {verification_code}')
|
||||
|
||||
# Send email notification
|
||||
send_email(
|
||||
to='your-email@example.com',
|
||||
subject='WhatsApp Verification Code',
|
||||
body=f'Your verification code is: {verification_code}'
|
||||
)
|
||||
|
||||
response = VoiceResponse()
|
||||
response.say('Thank you. Your code has been received.')
|
||||
|
||||
return Response(str(response), mimetype='text/xml')
|
||||
|
||||
def send_email(to, subject, body):
|
||||
# Implement email sending logic
|
||||
pass
|
||||
|
||||
if __name__ == '__main__':
|
||||
app.run(port=3000)
|
||||
```
|
||||
|
||||
#### BASIC (General Bots)
|
||||
|
||||
```basic
|
||||
REM Twilio Voice Webhook Handler
|
||||
ON WEBHOOK POST TO "/twilio/voice" DO
|
||||
REM Create TwiML response
|
||||
LET TWIML$ = "<?xml version=""1.0"" encoding=""UTF-8""?>"
|
||||
TWIML$ = TWIML$ + "<Response>"
|
||||
TWIML$ = TWIML$ + "<Gather action=""https://your-domain.com/twilio/gather"" method=""POST"" numDigits=""6"">"
|
||||
TWIML$ = TWIML$ + "<Say voice=""alice"" language=""pt-BR"">"
|
||||
TWIML$ = TWIML$ + "Please enter your verification code followed by the pound sign."
|
||||
TWIML$ = TWIML$ + "</Say>"
|
||||
TWIML$ = TWIML$ + "</Gather>"
|
||||
TWIML$ = TWIML$ + "<Redirect>https://twimlets.com/voicemail?Email=your-email@example.com</Redirect>"
|
||||
TWIML$ = TWIML$ + "</Response>"
|
||||
|
||||
REM Set response content type
|
||||
SET RESPONSE HEADER "Content-Type" TO "text/xml"
|
||||
PRINT TWIML$
|
||||
END ON
|
||||
|
||||
REM Gather Handler (receives the DTMF input)
|
||||
ON WEBHOOK POST TO "/twilio/gather" DO
|
||||
REM Get the digits entered
|
||||
LET CODE$ = GET FORM VALUE "Digits"
|
||||
|
||||
REM Log the verification code
|
||||
LOG "WhatsApp Verification Code: " + CODE$
|
||||
|
||||
REM Send email notification
|
||||
SEND MAIL TO "your-email@example.com" WITH SUBJECT "WhatsApp Verification Code" AND BODY "Your verification code is: " + CODE$
|
||||
|
||||
REM Create confirmation TwiML
|
||||
LET TWIML$ = "<?xml version=""1.0"" encoding=""UTF-8""?>"
|
||||
TWIML$ = TWIML$ + "<Response>"
|
||||
TWIML$ = TWIML$ + "<Say>Thank you. Your code has been received.</Say>"
|
||||
TWIML$ = TWIML$ + "</Response>"
|
||||
|
||||
SET RESPONSE HEADER "Content-Type" TO "text/xml"
|
||||
PRINT TWIML$
|
||||
END ON
|
||||
```
|
||||
|
||||
### Configuring Twilio
|
||||
|
||||
1. **Navigate to your phone number**
|
||||
- Go to Twilio Console > Phone Numbers > Active Numbers
|
||||
- Click on your purchased number
|
||||
|
||||
2. **Configure Voice Webhook**
|
||||
- Find "Voice & Fax" section
|
||||
- Set "A Call Comes In" to your webhook URL
|
||||
- Select HTTP POST method
|
||||
- Example: `https://your-domain.com/twilio/voice`
|
||||
|
||||
3. **Save changes**
|
||||
- Click "Save" to apply the configuration
|
||||
|
||||
### Webhook Security
|
||||
|
||||
Verify that requests come from Twilio:
|
||||
|
||||
```javascript
|
||||
const twilio = require('twilio');
|
||||
const client = twilio(process.env.TWILIO_ACCOUNT_SID, process.env.TWILIO_AUTH_TOKEN);
|
||||
|
||||
app.post('/twilio/voice', (req, res) => {
|
||||
const url = `https://${req.headers.host}${req.path}`;
|
||||
const signature = req.headers['x-twilio-signature'];
|
||||
|
||||
if (client.validateRequest(url, req.body, signature)) {
|
||||
// Request is from Twilio, process it
|
||||
handleVoiceWebhook(req, res);
|
||||
} else {
|
||||
// Invalid signature
|
||||
res.status(403).send('Invalid signature');
|
||||
}
|
||||
});
|
||||
```
|
||||
|
||||
## Meta WhatsApp Webhook Configuration
|
||||
|
||||
### Purpose
|
||||
|
||||
The Meta webhook receives:
|
||||
- Incoming WhatsApp messages from users
|
||||
- Message delivery status updates
|
||||
- Message read receipts
|
||||
- Webhook verification requests
|
||||
|
||||
### Webhook URL Structure
|
||||
|
||||
```
|
||||
POST https://your-domain.com/webhooks/whatsapp
|
||||
```
|
||||
|
||||
### Required HTTP Headers
|
||||
|
||||
| Header | Description | Example |
|
||||
|--------|-------------|---------|
|
||||
| `X-Hub-Signature-256` | HMAC SHA-256 signature | `sha256=...` |
|
||||
|
||||
### Webhook Verification
|
||||
|
||||
When you first configure the webhook, Meta sends a GET request to verify your URL:
|
||||
|
||||
```
|
||||
GET https://your-domain.com/webhooks/whatsapp?hub.verify_token=YOUR_TOKEN&hub.challenge=CHALLENGE_STRING
|
||||
```
|
||||
|
||||
Your webhook must respond with the challenge:
|
||||
|
||||
```javascript
|
||||
app.get('/webhooks/whatsapp', (req, res) => {
|
||||
const mode = req.query['hub.mode'];
|
||||
const token = req.query['hub.verify_token'];
|
||||
const challenge = req.query['hub.challenge'];
|
||||
|
||||
const VERIFY_TOKEN = '4qIogZadggQ.BEoMeciXIdl_MlkV_1DTx8Z_i0bYPxtSJwKSbH0FKlY';
|
||||
|
||||
if (mode === 'subscribe' && token === VERIFY_TOKEN) {
|
||||
console.log('Webhook verified');
|
||||
res.status(200).send(challenge);
|
||||
} else {
|
||||
res.sendStatus(403);
|
||||
}
|
||||
});
|
||||
```
|
||||
|
||||
### Message Payload Structure
|
||||
|
||||
Meta sends JSON payloads with message data:
|
||||
|
||||
```json
|
||||
{
|
||||
"object": "whatsapp_business_account",
|
||||
"entry": [{
|
||||
"id": "390727550789228",
|
||||
"changes": [{
|
||||
"value": {
|
||||
"messaging_product": "whatsapp",
|
||||
"metadata": {
|
||||
"display_phone_number": "+553322980098",
|
||||
"phone_number_id": "1158433381968079"
|
||||
},
|
||||
"contacts": [{
|
||||
"profile": {
|
||||
"name": "John Doe"
|
||||
},
|
||||
"wa_id": "5511999999999"
|
||||
}],
|
||||
"messages": [{
|
||||
"from": "5511999999999",
|
||||
"id": "wamid.HBgLNTE1OTk5OTk5OTk5FQIAERgSMzg1QTlCNkE2RTlFRTdFNDdF",
|
||||
"timestamp": "1704067200",
|
||||
"text": {
|
||||
"body": "Hello, how can I help you?"
|
||||
},
|
||||
"type": "text"
|
||||
}]
|
||||
},
|
||||
"field": "messages"
|
||||
}]
|
||||
}]
|
||||
}
|
||||
```
|
||||
|
||||
### Implementation Examples
|
||||
|
||||
#### Node.js/Express
|
||||
|
||||
```javascript
|
||||
app.post('/webhooks/whatsapp', (req, res) => {
|
||||
try {
|
||||
const data = req.body;
|
||||
|
||||
// Check if this is a WhatsApp message
|
||||
if (data.object === 'whatsapp_business_account') {
|
||||
data.entry.forEach(entry => {
|
||||
entry.changes.forEach(change => {
|
||||
if (change.field === 'messages') {
|
||||
const message = change.value.messages[0];
|
||||
const from = message.from;
|
||||
const body = message.text.body;
|
||||
const messageId = message.id;
|
||||
|
||||
console.log(`Received message from ${from}: ${body}`);
|
||||
|
||||
// Process the message
|
||||
processWhatsAppMessage(from, body, messageId);
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
res.status(200).send('OK');
|
||||
} catch (error) {
|
||||
console.error('Webhook error:', error);
|
||||
res.status(500).send('Error');
|
||||
}
|
||||
});
|
||||
|
||||
async function processWhatsAppMessage(from, body, messageId) {
|
||||
// Implement your bot logic here
|
||||
const response = await generateResponse(body);
|
||||
|
||||
// Send reply
|
||||
await sendWhatsAppMessage(from, response);
|
||||
}
|
||||
```
|
||||
|
||||
#### Python/Flask
|
||||
|
||||
```python
|
||||
@app.route('/webhooks/whatsapp', methods=['POST'])
|
||||
def whatsapp_webhook():
|
||||
try:
|
||||
data = request.get_json()
|
||||
|
||||
if data.get('object') == 'whatsapp_business_account':
|
||||
for entry in data.get('entry', []):
|
||||
for change in entry.get('changes', []):
|
||||
if change.get('field') == 'messages':
|
||||
message = change['value']['messages'][0]
|
||||
from_number = message['from']
|
||||
body = message['text']['body']
|
||||
message_id = message['id']
|
||||
|
||||
print(f"Received message from {from_number}: {body}")
|
||||
|
||||
# Process the message
|
||||
process_whatsapp_message(from_number, body, message_id)
|
||||
|
||||
return 'OK', 200
|
||||
except Exception as e:
|
||||
print(f'Webhook error: {e}')
|
||||
return 'Error', 500
|
||||
|
||||
def process_whatsapp_message(from_number, body, message_id):
|
||||
# Implement your bot logic here
|
||||
response = generate_response(body)
|
||||
|
||||
# Send reply
|
||||
send_whatsapp_message(from_number, response)
|
||||
```
|
||||
|
||||
#### BASIC (General Bots)
|
||||
|
||||
```basic
|
||||
REM Meta WhatsApp Webhook Handler
|
||||
ON WEBHOOK POST TO "/webhooks/whatsapp" DO
|
||||
REM Get the JSON payload
|
||||
LET PAYLOAD$ = GET REQUEST BODY
|
||||
|
||||
REM Parse the JSON (requires JSON parser library)
|
||||
LET OBJ = PARSE JSON PAYLOAD$
|
||||
|
||||
REM Check if this is a WhatsApp message
|
||||
IF GET JSON PATH OBJ, "object" = "whatsapp_business_account" THEN
|
||||
REM Get the message
|
||||
LET MESSAGE = GET JSON PATH OBJ, "entry[0].changes[0].value.messages[0]"
|
||||
|
||||
REM Extract message details
|
||||
LET FROM$ = GET JSON PATH MESSAGE, "from"
|
||||
LET BODY$ = GET JSON PATH MESSAGE, "text.body"
|
||||
LET ID$ = GET JSON PATH MESSAGE, "id"
|
||||
|
||||
REM Log the message
|
||||
LOG "WhatsApp message from " + FROM$ + ": " + BODY$
|
||||
|
||||
REM Process the message asynchronously
|
||||
SPAWN PROCESS WHATSAPP MESSAGE FROM$, BODY$, ID$
|
||||
END IF
|
||||
|
||||
REM Respond with 200 OK
|
||||
PRINT "OK"
|
||||
SET RESPONSE STATUS TO 200
|
||||
END ON
|
||||
|
||||
REM Message processor
|
||||
SUB PROCESS WHATSAPP MESSAGE FROM$, BODY$, ID$
|
||||
REM Generate a response
|
||||
LET RESPONSE$ = GENERATE RESPONSE BODY$
|
||||
|
||||
REM Send the reply
|
||||
SEND WHATSAPP TO FROM$ WITH RESPONSE$
|
||||
END SUB
|
||||
```
|
||||
|
||||
### Configuring Meta
|
||||
|
||||
1. **Navigate to WhatsApp API Setup**
|
||||
- Go to Meta for Developers > Your App > WhatsApp > API Setup
|
||||
|
||||
2. **Edit Webhook**
|
||||
- Click "Edit" next to Webhook
|
||||
- Enter your webhook URL: `https://your-domain.com/webhooks/whatsapp`
|
||||
- Enter your Verify Token: `4qIogZadggQ.BEoMeciXIdl_MlkV_1DTx8Z_i0bYPxtSJwKSbH0FKlY`
|
||||
- Click "Verify and Save"
|
||||
|
||||
3. **Subscribe to Webhook Fields**
|
||||
- Subscribe to: `messages`
|
||||
- This ensures you receive all incoming messages
|
||||
|
||||
### Webhook Security
|
||||
|
||||
Implement signature verification:
|
||||
|
||||
```javascript
|
||||
const crypto = require('crypto');
|
||||
|
||||
app.post('/webhooks/whatsapp', (req, res) => {
|
||||
const signature = req.headers['x-hub-signature-256'];
|
||||
const payload = JSON.stringify(req.body);
|
||||
const appSecret = 'YOUR_APP_SECRET'; // From Meta dashboard
|
||||
|
||||
const expectedSignature = 'sha256=' + crypto
|
||||
.createHmac('sha256', appSecret)
|
||||
.update(payload)
|
||||
.digest('hex');
|
||||
|
||||
if (signature !== expectedSignature) {
|
||||
console.error('Invalid webhook signature');
|
||||
return res.status(403).send('Invalid signature');
|
||||
}
|
||||
|
||||
// Process the webhook
|
||||
processWebhook(req.body);
|
||||
res.status(200).send('OK');
|
||||
});
|
||||
```
|
||||
|
||||
## Testing Webhooks
|
||||
|
||||
### Using Ngrok for Local Development
|
||||
|
||||
1. **Install ngrok**
|
||||
```bash
|
||||
npm install -g ngrok
|
||||
```
|
||||
|
||||
2. **Start your local server**
|
||||
```bash
|
||||
node server.js
|
||||
```
|
||||
|
||||
3. **Start ngrok**
|
||||
```bash
|
||||
ngrok http 3000
|
||||
```
|
||||
|
||||
4. **Use the ngrok URL**
|
||||
- Your webhook URL: `https://abc123.ngrok.io/webhooks/whatsapp`
|
||||
|
||||
### Testing Twilio Webhook
|
||||
|
||||
Use Twilio's webhook debugger:
|
||||
|
||||
```bash
|
||||
curl -X POST \
|
||||
'https://your-domain.com/twilio/voice' \
|
||||
-H 'Content-Type: application/x-www-form-urlencoded' \
|
||||
-d 'CallSid=CA123&From=+1234567890&To=+553322980098&CallStatus=ringing&Direction=inbound'
|
||||
```
|
||||
|
||||
### Testing Meta Webhook
|
||||
|
||||
Use Meta's webhook testing tool:
|
||||
|
||||
```bash
|
||||
curl -X POST \
|
||||
'https://your-domain.com/webhooks/whatsapp' \
|
||||
-H 'Content-Type: application/json' \
|
||||
-H 'X-Hub-Signature-256: sha256=...' \
|
||||
-d '{
|
||||
"object": "whatsapp_business_account",
|
||||
"entry": [{
|
||||
"id": "390727550789228",
|
||||
"changes": [{
|
||||
"value": {
|
||||
"messaging_product": "whatsapp",
|
||||
"messages": [{
|
||||
"from": "5511999999999",
|
||||
"text": {"body": "Test message"}
|
||||
}]
|
||||
},
|
||||
"field": "messages"
|
||||
}]
|
||||
}]
|
||||
}'
|
||||
```
|
||||
|
||||
## Production Considerations
|
||||
|
||||
### High Availability
|
||||
|
||||
- Deploy webhooks behind a load balancer
|
||||
- Implement retry logic for failed deliveries
|
||||
- Use a message queue (RabbitMQ, Redis) for async processing
|
||||
- Monitor webhook health and set up alerts
|
||||
|
||||
### Performance
|
||||
|
||||
- Respond to webhooks quickly (< 3 seconds)
|
||||
- Process heavy operations asynchronously
|
||||
- Use worker queues for message processing
|
||||
- Implement rate limiting to prevent abuse
|
||||
|
||||
### Monitoring
|
||||
|
||||
- Log all webhook requests and responses
|
||||
- Track delivery success rates
|
||||
- Monitor response times
|
||||
- Set up alerts for failures
|
||||
- Use tools like Sentry, Datadog, or New Relic
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
### Common Issues
|
||||
|
||||
**Problem: Webhook verification fails**
|
||||
- Ensure verify token matches exactly
|
||||
- Check that your endpoint returns the challenge
|
||||
- Verify your URL is publicly accessible
|
||||
|
||||
**Problem: Messages not received**
|
||||
- Check webhook logs for errors
|
||||
- Verify subscription to `messages` field
|
||||
- Ensure your server is online and responding
|
||||
|
||||
**Problem: Invalid signature errors**
|
||||
- Verify your app secret is correct
|
||||
- Check that you're computing the hash correctly
|
||||
- Ensure you're using the raw request body
|
||||
|
||||
**Problem: Timeout errors**
|
||||
- Optimize your webhook handler
|
||||
- Move heavy processing to background jobs
|
||||
- Increase server capacity if needed
|
||||
|
||||
### Debugging Tools
|
||||
|
||||
- **Twilio Debugger**: View all Twilio webhook attempts
|
||||
- **Meta Webhook Debugging**: Enable in app settings
|
||||
- **Ngrok Inspector**: Inspect requests in real-time
|
||||
- **Webhook.site**: Test webhooks without a server
|
||||
|
||||
## Next Steps
|
||||
|
||||
- Set up persistent storage for message history
|
||||
- Implement message queue for reliability
|
||||
- Add webhook retry logic
|
||||
- Configure monitoring and alerting
|
||||
- Set up automated testing
|
||||
|
||||
For more information on webhook security, see [Security Considerations](./README.md#security-considerations).
|
||||
|
|
@ -433,6 +433,11 @@
|
|||
- [LLM Providers](./18-appendix-external-services/llm-providers.md)
|
||||
- [Weather API](./18-appendix-external-services/weather.md)
|
||||
- [Channel Integrations](./18-appendix-external-services/channels.md)
|
||||
- [Quick Start Guide](./18-appendix-external-services/whatsapp-quick-start.md)
|
||||
- [Webhook Configuration](./18-appendix-external-services/whatsapp-webhooks.md)
|
||||
- [Code Examples](./18-appendix-external-services/whatsapp-examples.md)
|
||||
- [Troubleshooting](./18-appendix-external-services/whatsapp-troubleshooting.md)
|
||||
- [Quick Reference](./18-appendix-external-services/whatsapp-quick-reference.md)
|
||||
- [Storage Services](./18-appendix-external-services/storage.md)
|
||||
- [Directory Services](./18-appendix-external-services/directory.md)
|
||||
- [Attendance Queue](./18-appendix-external-services/attendance-queue.md)
|
||||
|
|
@ -452,5 +457,7 @@
|
|||
- [LXC Migration](./19-maintenance/lxc-migration.md)
|
||||
|
||||
|
||||
|
||||
|
||||
[Glossary](./glossary.md)
|
||||
[Contact](./contact/README.md)
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue