311 lines
9.6 KiB
Markdown
311 lines
9.6 KiB
Markdown
# WhatsApp Automation
|
||
|
||
WhatsApp Automation is a Spring Boot backend for WhatsApp Business messaging workflows. It receives webhook events from Meta, runs bot-driven conversation logic, and persists booking/state data in PostgreSQL.
|
||
|
||
## About The Project
|
||
|
||
This project provides automation features around WhatsApp messaging:
|
||
|
||
- Webhook verification and message handling (`/webhook`)
|
||
- Chatbot conversation flow
|
||
- PostgreSQL persistence for appointments, service bookings, test bookings, and user state
|
||
|
||
The application is a **Java 21** Maven service built with Spring Boot.
|
||
|
||
## Tech Stack
|
||
|
||
- Spring Boot 3.3.2
|
||
- Java 21
|
||
- Spring Web
|
||
- Spring Data JPA
|
||
- PostgreSQL
|
||
- ngrok (for local webhook tunneling to Meta)
|
||
|
||
## Requirements
|
||
|
||
| Tool | Purpose |
|
||
|------|---------|
|
||
| **Java 21** | Runtime for the Spring Boot app |
|
||
| **Maven 3.9+** | Build and run the project |
|
||
| **PostgreSQL** | Application database |
|
||
| **ngrok** | Expose local backend to the public internet so Meta can call your webhook |
|
||
| **Meta / WhatsApp Business API access** | Access token, webhook configuration, and test messaging |
|
||
|
||
---
|
||
|
||
## How to Run the Backend (Full Setup)
|
||
|
||
Follow these steps in order.
|
||
|
||
### 1. Clone the repository
|
||
|
||
```bash
|
||
git clone <repository-url>
|
||
cd "WhatsApp Automation"
|
||
```
|
||
|
||
Replace `<repository-url>` with the actual Git remote URL for this project.
|
||
|
||
---
|
||
|
||
### 2. Install ngrok
|
||
|
||
ngrok creates a public HTTPS URL that tunnels to your local Spring Boot server so Meta can deliver WhatsApp webhooks.
|
||
|
||
1. Go to [https://ngrok.com](https://ngrok.com)
|
||
2. Sign up or sign in
|
||
3. Install ngrok for your OS (macOS example with Homebrew):
|
||
|
||
```bash
|
||
brew install ngrok
|
||
```
|
||
|
||
Or download the binary from the ngrok dashboard and follow their install instructions.
|
||
|
||
---
|
||
|
||
### 3. Authenticate ngrok with your access token
|
||
|
||
After signing in to ngrok, copy your **authtoken** from the ngrok dashboard, then run:
|
||
|
||
```bash
|
||
ngrok config add-authtoken <YOUR_NGROK_AUTHTOKEN>
|
||
```
|
||
|
||
Without this step, ngrok will not start a usable tunnel.
|
||
|
||
---
|
||
|
||
### 4. Log in to the WhatsApp Business / Meta developer dashboard
|
||
|
||
1. Open the [WhatsApp Business API / Meta for Developers](https://developers.facebook.com/) dashboard
|
||
2. Log in with the account that has access to this app
|
||
3. Use the project’s WhatsApp / Meta credentials (app ID, business ID, phone number ID, etc.) as configured for your team
|
||
|
||
Relevant app links used by this project:
|
||
|
||
- **API testing / access token:**
|
||
[Generate WhatsApp access token](https://developers.facebook.com/apps/1054675710401577/use_cases/customize/api-testing-v2/?product_route=whatsapp-business&business_id=1051413880774512&use_case_enum=WHATSAPP_BUSINESS_MESSAGING&selected_tab=api-testing-v2)
|
||
|
||
- **Webhooks configuration:**
|
||
[Configure webhooks](https://developers.facebook.com/apps/1054675710401577/use_cases/customize/webhooks/?product_route=webhooks&business_id=1051413880774512&use_case_enum=WHATSAPP_BUSINESS_MESSAGING&selected_tab=webhooks)
|
||
|
||
---
|
||
|
||
### 5. Generate a WhatsApp access token and configure the app
|
||
|
||
1. Open the API testing page:
|
||
[https://developers.facebook.com/apps/1054675710401577/use_cases/customize/api-testing-v2/?product_route=whatsapp-business&business_id=1051413880774512&use_case_enum=WHATSAPP_BUSINESS_MESSAGING&selected_tab=api-testing-v2](https://developers.facebook.com/apps/1054675710401577/use_cases/customize/api-testing-v2/?product_route=whatsapp-business&business_id=1051413880774512&use_case_enum=WHATSAPP_BUSINESS_MESSAGING&selected_tab=api-testing-v2)
|
||
2. Generate a **new Access Token**
|
||
3. Open the project config file:
|
||
|
||
```text
|
||
src/main/resources/application.properties
|
||
```
|
||
|
||
4. Paste the token into the access-token property:
|
||
|
||
```properties
|
||
whatsapp.access-token=<YOUR_WHATSAPP_ACCESS_TOKEN>
|
||
```
|
||
|
||
> **Note:** Temporary tokens from Meta expire. If outbound WhatsApp API calls start failing with auth errors, generate a new token and update this property.
|
||
|
||
---
|
||
|
||
### 6. Create the PostgreSQL database and set credentials
|
||
|
||
1. Ensure PostgreSQL is installed and running locally
|
||
2. Create the database used by this project (default name: `rmc_bot`):
|
||
|
||
```bash
|
||
createdb rmc_bot
|
||
```
|
||
|
||
Or via `psql`:
|
||
|
||
```sql
|
||
CREATE DATABASE rmc_bot;
|
||
```
|
||
|
||
3. Update database settings in `src/main/resources/application.properties`:
|
||
|
||
```properties
|
||
spring.datasource.url=jdbc:postgresql://localhost:5432/rmc_bot
|
||
spring.datasource.username=<YOUR_POSTGRES_USERNAME>
|
||
spring.datasource.password=<YOUR_POSTGRES_PASSWORD>
|
||
```
|
||
|
||
Default values currently in the file (change these for your machine):
|
||
|
||
| Property | Default / example |
|
||
|----------|-------------------|
|
||
| `spring.datasource.url` | `jdbc:postgresql://localhost:5432/rmc_bot` |
|
||
| `spring.datasource.username` | `postgres` |
|
||
| `spring.datasource.password` | *(your local password)* |
|
||
|
||
The app uses:
|
||
|
||
```properties
|
||
spring.jpa.hibernate.ddl-auto=update
|
||
```
|
||
|
||
so tables are created/updated automatically on startup.
|
||
|
||
---
|
||
|
||
### 7. Start the Spring Boot backend
|
||
|
||
The server listens on **port 8085** (`server.port=8085`).
|
||
|
||
From the project root:
|
||
|
||
```bash
|
||
mvn spring-boot:run
|
||
```
|
||
|
||
Confirm the app started successfully (no datasource or port-binding errors). Leave this process running.
|
||
|
||
You can also run tests with:
|
||
|
||
```bash
|
||
mvn test
|
||
```
|
||
|
||
---
|
||
|
||
### 8. Start ngrok and point it at the backend
|
||
|
||
**Important:** Start the Spring Boot backend *before* configuring Meta webhooks, and keep both the backend and ngrok running while testing.
|
||
|
||
In a **new terminal**:
|
||
|
||
```bash
|
||
ngrok http 8085
|
||
```
|
||
|
||
ngrok will print a public HTTPS URL, for example:
|
||
|
||
```text
|
||
https://abcd-1234.ngrok-free.app
|
||
```
|
||
|
||
Copy that base URL (the `https://...` forwarding address).
|
||
|
||
> Free ngrok URLs change every time you restart ngrok. When the URL changes, you must update the Callback URL in Meta again.
|
||
|
||
---
|
||
|
||
### 9. Configure the Meta webhook
|
||
|
||
1. Open the webhooks page:
|
||
[https://developers.facebook.com/apps/1054675710401577/use_cases/customize/webhooks/?product_route=webhooks&business_id=1051413880774512&use_case_enum=WHATSAPP_BUSINESS_MESSAGING&selected_tab=webhooks](https://developers.facebook.com/apps/1054675710401577/use_cases/customize/webhooks/?product_route=webhooks&business_id=1051413880774512&use_case_enum=WHATSAPP_BUSINESS_MESSAGING&selected_tab=webhooks)
|
||
|
||
2. Set **Callback URL** to:
|
||
|
||
```text
|
||
https://<YOUR_NGROK_HOST>/webhook
|
||
```
|
||
|
||
Example:
|
||
|
||
```text
|
||
https://abcd-1234.ngrok-free.app/webhook
|
||
```
|
||
|
||
3. Set **Verify Token** to exactly:
|
||
|
||
```text
|
||
my_whatsapp_verify_token_123
|
||
```
|
||
|
||
This must match `whatsapp.verify-token` in `application.properties`:
|
||
|
||
```properties
|
||
whatsapp.verify-token=my_whatsapp_verify_token_123
|
||
```
|
||
|
||
4. Click **Verify and Save** (or equivalent). Meta will send a `GET` request to `/webhook` with `hub.mode`, `hub.verify_token`, and `hub.challenge`. The backend validates the token and returns the challenge.
|
||
|
||
5. Subscribe to the webhook fields you need (typically **messages** for inbound WhatsApp traffic).
|
||
|
||
---
|
||
|
||
## Configuration reference
|
||
|
||
All runtime secrets and connection settings live in:
|
||
|
||
```text
|
||
src/main/resources/application.properties
|
||
```
|
||
|
||
| Property | Description |
|
||
|----------|-------------|
|
||
| `server.port` | Backend HTTP port (default `8085`) |
|
||
| `whatsapp.access-token` | Meta WhatsApp Cloud API access token |
|
||
| `whatsapp.verify-token` | Token Meta uses to verify your webhook (`my_whatsapp_verify_token_123`) |
|
||
| `spring.datasource.url` | JDBC URL for PostgreSQL |
|
||
| `spring.datasource.username` | PostgreSQL username |
|
||
| `spring.datasource.password` | PostgreSQL password |
|
||
| `spring.jpa.hibernate.ddl-auto` | Schema mode (`update`) |
|
||
| `spring.jpa.properties.hibernate.dialect` | PostgreSQL dialect |
|
||
| `spring.jpa.show-sql` | Log SQL statements |
|
||
|
||
Webhook endpoint exposed by the app:
|
||
|
||
| Method | Path | Purpose |
|
||
|--------|------|---------|
|
||
| `GET` | `/webhook` | Meta webhook verification |
|
||
| `POST` | `/webhook` | Inbound WhatsApp events / messages |
|
||
|
||
---
|
||
|
||
## Quick checklist
|
||
|
||
Use this when bringing the stack up on a new machine:
|
||
|
||
1. [ ] Clone the repo
|
||
2. [ ] Install and authenticate ngrok
|
||
3. [ ] Log in to Meta / WhatsApp Business dashboard
|
||
4. [ ] Generate access token → set `whatsapp.access-token`
|
||
5. [ ] Create PostgreSQL DB → set datasource username/password
|
||
6. [ ] `mvn spring-boot:run` (port **8085**)
|
||
7. [ ] `ngrok http 8085`
|
||
8. [ ] Meta Callback URL = `https://<ngrok-host>/webhook`
|
||
9. [ ] Verify token = `my_whatsapp_verify_token_123`
|
||
10. [ ] Verify webhook + subscribe to message events
|
||
|
||
---
|
||
|
||
## Troubleshooting
|
||
|
||
| Problem | What to check |
|
||
|---------|----------------|
|
||
| Webhook verification fails | Verify token must be exactly `my_whatsapp_verify_token_123`. Backend must be running. Callback URL must end with `/webhook`. |
|
||
| Meta cannot reach the server | ngrok must be running (`ngrok http 8085`). Use the current ngrok HTTPS URL, not an old one. |
|
||
| Database connection errors | PostgreSQL is running; database `rmc_bot` exists; username/password in `application.properties` are correct. |
|
||
| Cannot send WhatsApp messages | Access token may have expired — generate a new one and update `whatsapp.access-token`. |
|
||
| Port already in use | Something else is bound to `8085`, or change `server.port` and point ngrok at the new port. |
|
||
| Not receiving messages on webhook | Your WhatsApp Business Account (WABA) might not be subscribed to your developer App. Link them via API: `curl -X POST "https://graph.facebook.com/v20.0/<WABA_ID>/subscribed_apps" -H "Authorization: Bearer <your_access_token>"` |
|
||
|
||
---
|
||
|
||
## Project structure (high level)
|
||
|
||
```text
|
||
src/main/java/com/example/whatsappautomation/
|
||
WhatsAppAutomationApplication.java
|
||
controller/WhatsAppWebhookController.java
|
||
service/ChatbotService.java
|
||
entity/ # Appointment, ServiceBooking, TestBooking, UserState
|
||
repository/ # Spring Data JPA repositories
|
||
src/main/resources/
|
||
application.properties
|
||
```
|
||
|
||
---
|
||
|
||
## License
|
||
|
||
Internal / project use unless otherwise specified.
|