Overview
The WhatsApp RAG Bot uses a secure credential management system to store sensitive API keys and access tokens. All credentials are encrypted using AES-256-CBC encryption before being stored in the database.
Encryption System
The bot uses the EncryptionService class to encrypt and decrypt sensitive credentials.
Encryption Configuration
Set up your encryption key in the environment configuration:
APP_CIPHER_KEY = your-32-character-encryption-key-here
The APP_CIPHER_KEY must be set before using the application. Without it, the system will throw a RuntimeException.
How Encryption Works
The encryption service uses the following process:
Generate Initialization Vector
Creates a random IV using openssl_random_pseudo_bytes() for each encryption operation.
Encrypt Data
Encrypts the value using AES-256-CBC cipher with the generated IV and your APP_CIPHER_KEY.
Store Encrypted Value
Combines the IV and encrypted data, then encodes it in base64 format before storing in the database.
src/Services/EncryptionService.php
public function encrypt ( string $value ) : string
{
$ivLength = openssl_cipher_iv_length ( $this -> cipher );
$iv = openssl_random_pseudo_bytes ( $ivLength );
$encrypted = openssl_encrypt ( $value , $this -> cipher , $this -> cipherKey , OPENSSL_RAW_DATA , $iv );
if ( $encrypted === false ) {
throw new \RuntimeException ( 'Encryption failed' );
}
return base64_encode ( $iv . $encrypted );
}
Database Schema
Bot Credentials Table
Stores WhatsApp and OpenAI credentials:
CREATE TABLE IF NOT EXISTS bot_credentials (
id INT AUTO_INCREMENT PRIMARY KEY ,
whatsapp_phone_number_id VARCHAR ( 255 ) DEFAULT '' ,
whatsapp_access_token TEXT DEFAULT NULL ,
whatsapp_app_secret TEXT DEFAULT NULL ,
whatsapp_verify_token VARCHAR ( 255 ) DEFAULT '' ,
openai_api_key TEXT DEFAULT NULL ,
openai_model VARCHAR ( 100 ) DEFAULT 'gpt-3.5-turbo' ,
openai_embedding_model VARCHAR ( 100 ) DEFAULT 'text-embedding-ada-002' ,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 COLLATE = utf8mb4_unicode_ci;
Encrypted fields: whatsapp_access_token, whatsapp_app_secret, openai_api_key
Google OAuth Credentials Table
Stores Google Calendar OAuth credentials:
CREATE TABLE IF NOT EXISTS google_oauth_credentials (
id INT AUTO_INCREMENT PRIMARY KEY ,
client_id VARCHAR ( 255 ) DEFAULT '' ,
client_secret TEXT DEFAULT NULL ,
access_token TEXT DEFAULT NULL ,
refresh_token TEXT DEFAULT NULL ,
token_expires_at TIMESTAMP NULL ,
calendar_id VARCHAR ( 255 ) DEFAULT '' ,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 COLLATE = utf8mb4_unicode_ci;
Encrypted fields: client_secret, access_token, refresh_token
Settings Table
Stores general system settings:
CREATE TABLE IF NOT EXISTS settings (
id INT AUTO_INCREMENT PRIMARY KEY ,
setting_key VARCHAR ( 100 ) NOT NULL UNIQUE ,
setting_type ENUM( 'text' , 'boolean' , 'json' ) DEFAULT 'text' ,
setting_value TEXT NOT NULL ,
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 COLLATE = utf8mb4_unicode_ci;
Using the Credential Service
Retrieving WhatsApp Credentials
$credentialService = new CredentialService ( $db , $encryption );
$creds = $credentialService -> getWhatsAppCredentials ();
// Returns:
[
'phone_number_id' => 'YOUR_PHONE_NUMBER_ID' ,
'access_token' => 'decrypted_token' ,
'app_secret' => 'decrypted_secret' ,
'verify_token' => 'YOUR_VERIFY_TOKEN'
]
Retrieving OpenAI Credentials
$creds = $credentialService -> getOpenAICredentials ();
// Returns:
[
'api_key' => 'decrypted_api_key' ,
'model' => 'gpt-3.5-turbo' ,
'embedding_model' => 'text-embedding-ada-002'
]
Saving Credentials
Credentials are automatically encrypted when saved:
// Save WhatsApp credentials
$credentialService -> saveWhatsAppCredentials ([
'phone_number_id' => '123456789' ,
'access_token' => 'your_access_token' ,
'app_secret' => 'your_app_secret' ,
'verify_token' => 'your_verify_token'
]);
// Save OpenAI credentials
$credentialService -> saveOpenAICredentials ([
'api_key' => 'sk-...' ,
'model' => 'gpt-4' ,
'embedding_model' => 'text-embedding-3-small'
]);
Checking Credential Status
The CredentialService provides helper methods to check if credentials are configured:
src/Services/CredentialService.php
public function hasWhatsAppCredentials () : bool
{
$creds = $this -> getWhatsAppCredentials ();
return ! empty ( $creds [ 'access_token' ]) && ! empty ( $creds [ 'phone_number_id' ]);
}
public function hasOpenAICredentials () : bool
{
$creds = $this -> getOpenAICredentials ();
return ! empty ( $creds [ 'api_key' ]);
}
public function hasGoogleOAuthCredentials () : bool
{
$creds = $this -> getGoogleOAuthCredentials ();
return ! empty ( $creds [ 'access_token' ]) && ! empty ( $creds [ 'calendar_id' ]);
}
Security Best Practices
Never commit credentials to version control
Keep your APP_CIPHER_KEY secure and never share it
Use environment variables for all sensitive configuration
Regularly rotate API keys and access tokens
Ensure your database is properly secured with access controls
The encryption key should be at least 32 characters long for AES-256 encryption. Generate a secure random key using:
Configuration File vs Database
The system supports two configuration modes:
Database-stored credentials (Recommended): Managed through the admin dashboard with encryption
Config file credentials : Fallback option using config/config.php
if ( $credentialService && $credentialService -> hasWhatsAppCredentials ()) {
$waCreds = $credentialService -> getWhatsAppCredentials ();
$whatsapp = new WhatsAppService (
$waCreds [ 'access_token' ],
$waCreds [ 'phone_number_id' ],
Config :: get ( 'whatsapp.api_version' ),
$logger
);
} else {
// Fallback to config file
$whatsapp = new WhatsAppService (
Config :: get ( 'whatsapp.access_token' ),
Config :: get ( 'whatsapp.phone_number_id' ),
Config :: get ( 'whatsapp.api_version' ),
$logger
);
}
Next Steps
WhatsApp Setup Configure WhatsApp Business API credentials
OpenAI Setup Set up OpenAI API integration