2.8 KiB
2.8 KiB
WuzAPI Native Channel Implementation Plan (V2 - Strict V1 Specs)
Goal
Implement WuzAPI as a native Channel::Whatsapp provider, adhering to strict V1 requirements: text-only, strong deduplication, and encrypted token storage.
User Review Required
[!IMPORTANT] > Schema Change: Adding
encrypted_wuzapi_user_tokenandencrypted_wuzapi_admin_token(plus IVs) tochannel_whatsappto replace insecure JSONB storage.
[!WARNING] > V1 Scope: Only
textmessages supported. Groups and self-messages are explicitly ignored.
Proposed Changes
Database
[NEW] Migration: Add Encrypted Tokens to Channel Whatsapp
- Add
encrypted_wuzapi_user_token(string) - Add
encrypted_wuzapi_user_token_iv(string) - Add
encrypted_wuzapi_admin_token(string) - Add
encrypted_wuzapi_admin_token_iv(string) - Rationale: Avoids storing sensitive tokens in
provider_config(JSONB).
Backend (Models)
[MODIFY] app/models/channel/whatsapp.rb
- Add
encrypts :wuzapi_user_token, :wuzapi_admin_token(Rails 7+ encryption). - Update
validate_provider_configto check these new fields instead of JSONB.
Backend (Services)
[NEW] app/services/whatsapp/providers/wuzapi/payload_parser.rb
- Implement class to strictly parse WuzAPI payload per contract:
external_id<-body.event.Info.IDfrom_me<-body.event.Info.IsFromMewa_id<-body.event.Info.Sender(parsed)text<-body.event.Message.conversationtimestamp<-body.event.Info.Timestamp
[MODIFY] app/services/whatsapp/incoming_message_wuzapi_service.rb
- Integrate
PayloadParser. - Implement Strong Dedupe:
- Return early if
Message.exists?(source_id: external_id, inbox_id: inbox.id).
- Return early if
- Implement Loop Protection:
- Return early if
from_meis true.
- Return early if
[MODIFY] app/services/whatsapp/providers/wuzapi_service.rb (Outbound)
- Update to use
channel.wuzapi_user_token(decrypted) instead ofprovider_config. - Ensure
send_messagehandles errors gracefully.
Security
- Token Migration: If any data exists (unlikely in prod yet), migrate from
provider_configto encrypted columns.
Verification Plan
Automated Tests
- Request Spec (
spec/requests/webhooks/whatsapp_controller_spec.rb)- Verify WuzAPI payload submission creates a message.
- Verify duplicate payload does NOT create a second message (Idempotency).
- Verify
is_from_me: trueis ignored.
Manual Verification
- Setup: Create Inbox with WuzAPI, providing Token.
- Persistence: Verify Token is stored in encrypted columns (checked via Rails Console).
- Inbound: Send "Hello" from WhatsApp. Verify it appears in Chatwoot.
- Dedupe: Replay the same webhook JSON. Verify no new message.
- Outbound: Reply "World" from Chatwoot. Verify delivery to WhatsApp.