Sindbad~EG File Manager

Current Path : /home/copmadinaarea/thecopmadinaarea.org/portal/classes/
Upload File :
Current File : /home/copmadinaarea/thecopmadinaarea.org/portal/classes/SMSService.php

<?php
/**
 * SMS Service Class
 * Supports multiple African SMS gateways
 */

class SMSService {
    private $db;
    private $settings;
    
    public function __construct() {
        $this->db = Database::getInstance()->getConnection();
        $this->loadSettings();
    }
    
    /**
     * Load SMS settings from database
     */
    private function loadSettings() {
        $stmt = $this->db->query("SELECT * FROM sms_settings ORDER BY id DESC LIMIT 1");
        $this->settings = $stmt->fetch(PDO::FETCH_ASSOC);
        
        if (!$this->settings) {
            // Create default settings
            $this->db->exec("INSERT INTO sms_settings (gateway_provider, is_enabled, test_mode) VALUES ('africas_talking', 0, 1)");
            $this->loadSettings();
        }
    }
    
    /**
     * Check if SMS service is enabled
     */
    public function isEnabled() {
        return $this->settings && $this->settings['is_enabled'] == 1;
    }
    
    /**
     * Get current gateway provider
     */
    public function getGateway() {
        return $this->settings['gateway_provider'] ?? 'africas_talking';
    }
    
    /**
     * Queue SMS for sending
     */
    public function queueSMS($phone, $message, $recipientName = null, $senderId = null, $scheduledAt = null) {
        if (!$this->isEnabled()) {
            error_log("SMS Service: Not enabled");
            return false;
        }
        
        // Validate phone number
        $phone = $this->formatPhoneNumber($phone);
        if (!$phone) {
            error_log("SMS Service: Invalid phone number");
            return false;
        }
        
        // Use default sender ID if not provided
        if (!$senderId) {
            $senderId = $this->settings['default_sender_name'] ?? $this->settings['at_sender_id'] ?? 'Church';
        }
        
        $stmt = $this->db->prepare("
            INSERT INTO sms_queue (recipient_phone, recipient_name, message, sender_id, scheduled_at)
            VALUES (?, ?, ?, ?, ?)
        ");
        
        return $stmt->execute([$phone, $recipientName, $message, $senderId, $scheduledAt]);
    }
    
    /**
     * Send SMS instantly
     */
    public function sendInstantSMS($phone, $message, $recipientName = null, $senderId = null) {
        if (!$this->isEnabled()) {
            return ['success' => false, 'error' => 'SMS service is not enabled'];
        }
        
        // Validate phone number
        $phone = $this->formatPhoneNumber($phone);
        if (!$phone) {
            return ['success' => false, 'error' => 'Invalid phone number'];
        }
        
        // Use default sender ID if not provided
        if (!$senderId) {
            $senderId = $this->settings['default_sender_name'] ?? $this->settings['at_sender_id'] ?? 'Church';
        }
        
        // Send based on gateway
        $gateway = $this->getGateway();
        
        switch ($gateway) {
            case 'africas_talking':
                return $this->sendViaAfricasTalking($phone, $message, $senderId);
                
            case 'twilio':
                return $this->sendViaTwilio($phone, $message);
                
            case 'bulksms_nigeria':
                return $this->sendViaBulkSMSNigeria($phone, $message, $senderId);
                
            case 'hubtel':
                return $this->sendViaHubtel($phone, $message, $senderId);
                
            case 'clickatell':
                return $this->sendViaClickatell($phone, $message);
                
            case 'smsportal':
                return $this->sendViaSMSPortal($phone, $message);
                
            case 'arkesel':
                return $this->sendViaArkesel($phone, $message, $senderId);
                
            case 'custom':
                return $this->sendViaCustomGateway($phone, $message, $senderId);
                
            default:
                return ['success' => false, 'error' => 'Unknown gateway: ' . $gateway];
        }
    }
    
    /**
     * Send via Africa's Talking (Kenya, Nigeria, Uganda, etc.)
     */
    private function sendViaAfricasTalking($phone, $message, $senderId) {
        $apiKey = $this->settings['at_api_key'];
        $username = $this->settings['at_username'];
        
        if (!$apiKey || !$username) {
            return ['success' => false, 'error' => 'Africa\'s Talking credentials not configured'];
        }
        
        if ($this->settings['test_mode']) {
            return $this->simulateSMS($phone, $message, 'africas_talking');
        }
        
        $url = 'https://api.africastalking.com/version1/messaging';
        
        $data = [
            'username' => $username,
            'to' => $phone,
            'message' => $message,
            'from' => $senderId
        ];
        
        $headers = [
            'apiKey: ' . $apiKey,
            'Content-Type: application/x-www-form-urlencoded',
            'Accept: application/json'
        ];
        
        $response = $this->sendHTTPRequest($url, 'POST', $data, $headers);
        
        if ($response['success']) {
            $result = json_decode($response['body'], true);
            if (isset($result['SMSMessageData']['Recipients'][0]['status']) && 
                $result['SMSMessageData']['Recipients'][0]['status'] === 'Success') {
                
                $this->logSMS($phone, $message, $senderId, 'africas_talking', 'sent', $response['body']);
                return ['success' => true, 'message_id' => $result['SMSMessageData']['Recipients'][0]['messageId'] ?? null];
            }
        }
        
        $this->logSMS($phone, $message, $senderId, 'africas_talking', 'failed', $response['body'] ?? 'Unknown error');
        return ['success' => false, 'error' => $response['error'] ?? 'Failed to send SMS'];
    }
    
    /**
     * Send via Twilio
     */
    private function sendViaTwilio($phone, $message) {
        $accountSid = $this->settings['twilio_account_sid'];
        $authToken = $this->settings['twilio_auth_token'];
        $fromNumber = $this->settings['twilio_from_number'];
        
        if (!$accountSid || !$authToken || !$fromNumber) {
            return ['success' => false, 'error' => 'Twilio credentials not configured'];
        }
        
        if ($this->settings['test_mode']) {
            return $this->simulateSMS($phone, $message, 'twilio');
        }
        
        $url = "https://api.twilio.com/2010-04-01/Accounts/{$accountSid}/Messages.json";
        
        $data = [
            'To' => $phone,
            'From' => $fromNumber,
            'Body' => $message
        ];
        
        $headers = [
            'Authorization: Basic ' . base64_encode($accountSid . ':' . $authToken)
        ];
        
        $response = $this->sendHTTPRequest($url, 'POST', $data, $headers);
        
        if ($response['success']) {
            $result = json_decode($response['body'], true);
            if (isset($result['sid'])) {
                $this->logSMS($phone, $message, $fromNumber, 'twilio', 'sent', $response['body']);
                return ['success' => true, 'message_id' => $result['sid']];
            }
        }
        
        $this->logSMS($phone, $message, $fromNumber, 'twilio', 'failed', $response['body'] ?? 'Unknown error');
        return ['success' => false, 'error' => $response['error'] ?? 'Failed to send SMS'];
    }
    
    /**
     * Send via BulkSMS Nigeria
     */
    private function sendViaBulkSMSNigeria($phone, $message, $senderId) {
        $apiToken = $this->settings['bulksms_api_token'];
        
        if (!$apiToken) {
            return ['success' => false, 'error' => 'BulkSMS Nigeria credentials not configured'];
        }
        
        if ($this->settings['test_mode']) {
            return $this->simulateSMS($phone, $message, 'bulksms_nigeria');
        }
        
        $url = 'https://www.bulksmsnigeria.com/api/v1/sms/create';
        
        $data = [
            'api_token' => $apiToken,
            'from' => $senderId,
            'to' => $phone,
            'body' => $message
        ];
        
        $response = $this->sendHTTPRequest($url, 'POST', $data);
        
        if ($response['success']) {
            $result = json_decode($response['body'], true);
            if (isset($result['data']['id'])) {
                $this->logSMS($phone, $message, $senderId, 'bulksms_nigeria', 'sent', $response['body']);
                return ['success' => true, 'message_id' => $result['data']['id']];
            }
        }
        
        $this->logSMS($phone, $message, $senderId, 'bulksms_nigeria', 'failed', $response['body'] ?? 'Unknown error');
        return ['success' => false, 'error' => $response['error'] ?? 'Failed to send SMS'];
    }
    
    /**
     * Send via Hubtel (Ghana)
     */
    private function sendViaHubtel($phone, $message, $senderId) {
        $clientId = $this->settings['hubtel_client_id'];
        $clientSecret = $this->settings['hubtel_client_secret'];
        
        if (!$clientId || !$clientSecret) {
            return ['success' => false, 'error' => 'Hubtel credentials not configured'];
        }
        
        if ($this->settings['test_mode']) {
            return $this->simulateSMS($phone, $message, 'hubtel');
        }
        
        $url = 'https://api.hubtel.com/v1/messages/send';
        
        $data = [
            'From' => $senderId,
            'To' => $phone,
            'Content' => $message
        ];
        
        $headers = [
            'Authorization: Basic ' . base64_encode($clientId . ':' . $clientSecret),
            'Content-Type: application/json'
        ];
        
        $response = $this->sendHTTPRequest($url, 'POST', json_encode($data), $headers);
        
        if ($response['success']) {
            $result = json_decode($response['body'], true);
            if (isset($result['MessageId'])) {
                $this->logSMS($phone, $message, $senderId, 'hubtel', 'sent', $response['body']);
                return ['success' => true, 'message_id' => $result['MessageId']];
            }
        }
        
        $this->logSMS($phone, $message, $senderId, 'hubtel', 'failed', $response['body'] ?? 'Unknown error');
        return ['success' => false, 'error' => $response['error'] ?? 'Failed to send SMS'];
    }
    
    /**
     * Send via Clickatell
     */
    private function sendViaClickatell($phone, $message) {
        $apiKey = $this->settings['clickatell_api_key'];
        
        if (!$apiKey) {
            return ['success' => false, 'error' => 'Clickatell credentials not configured'];
        }
        
        if ($this->settings['test_mode']) {
            return $this->simulateSMS($phone, $message, 'clickatell');
        }
        
        $url = 'https://platform.clickatell.com/messages';
        
        $data = [
            'messages' => [
                [
                    'to' => [$phone],
                    'text' => $message
                ]
            ]
        ];
        
        $headers = [
            'Authorization: ' . $apiKey,
            'Content-Type: application/json'
        ];
        
        $response = $this->sendHTTPRequest($url, 'POST', json_encode($data), $headers);
        
        if ($response['success']) {
            $result = json_decode($response['body'], true);
            if (isset($result['messages'][0]['apiMessageId'])) {
                $this->logSMS($phone, $message, null, 'clickatell', 'sent', $response['body']);
                return ['success' => true, 'message_id' => $result['messages'][0]['apiMessageId']];
            }
        }
        
        $this->logSMS($phone, $message, null, 'clickatell', 'failed', $response['body'] ?? 'Unknown error');
        return ['success' => false, 'error' => $response['error'] ?? 'Failed to send SMS'];
    }
    
    /**
     * Send via SMS Portal (South Africa)
     */
    private function sendViaSMSPortal($phone, $message) {
        $clientId = $this->settings['smsportal_client_id'];
        $clientSecret = $this->settings['smsportal_client_secret'];
        
        if (!$clientId || !$clientSecret) {
            return ['success' => false, 'error' => 'SMS Portal credentials not configured'];
        }
        
        if ($this->settings['test_mode']) {
            return $this->simulateSMS($phone, $message, 'smsportal');
        }
        
        $url = 'https://rest.smsportal.com/v1/bulkmessages';
        
        $data = [
            'messages' => [
                [
                    'content' => $message,
                    'destination' => $phone
                ]
            ]
        ];
        
        $headers = [
            'Authorization: Basic ' . base64_encode($clientId . ':' . $clientSecret),
            'Content-Type: application/json'
        ];
        
        $response = $this->sendHTTPRequest($url, 'POST', json_encode($data), $headers);
        
        if ($response['success']) {
            $this->logSMS($phone, $message, null, 'smsportal', 'sent', $response['body']);
            return ['success' => true];
        }
        
        $this->logSMS($phone, $message, null, 'smsportal', 'failed', $response['body'] ?? 'Unknown error');
        return ['success' => false, 'error' => $response['error'] ?? 'Failed to send SMS'];
    }
    
    /**
     * Send via Arkesel (Ghana)
     */
    private function sendViaArkesel($phone, $message, $senderId) {
        $apiKey = $this->settings['arkesel_api_key'];
        
        if (!$apiKey) {
            return ['success' => false, 'error' => 'Arkesel credentials not configured'];
        }
        
        if ($this->settings['test_mode']) {
            return $this->simulateSMS($phone, $message, 'arkesel');
        }
        
        // Use sender ID from settings if not provided
        if (!$senderId) {
            $senderId = $this->settings['arkesel_sender_id'] ?? 'Arkesel';
        }
        
        $url = 'https://sms.arkesel.com/api/v2/sms/send';
        
        $data = [
            'sender' => $senderId,
            'message' => $message,
            'recipients' => [$phone]
        ];
        
        $headers = [
            'api-key: ' . $apiKey,
            'Content-Type: application/json'
        ];
        
        $response = $this->sendHTTPRequest($url, 'POST', json_encode($data), $headers);
        
        if ($response['success']) {
            $result = json_decode($response['body'], true);
            if (isset($result['status']) && $result['status'] === 'success') {
                $this->logSMS($phone, $message, $senderId, 'arkesel', 'sent', $response['body']);
                return ['success' => true, 'message_id' => $result['data']['id'] ?? null];
            }
        }
        
        $this->logSMS($phone, $message, $senderId, 'arkesel', 'failed', $response['body'] ?? 'Unknown error');
        return ['success' => false, 'error' => $response['error'] ?? 'Failed to send SMS'];
    }
    
    /**
     * Send via custom gateway
     */
    private function sendViaCustomGateway($phone, $message, $senderId) {
        $url = $this->settings['custom_api_url'];
        $apiKey = $this->settings['custom_api_key'];
        $method = $this->settings['custom_method'] ?? 'POST';
        
        if (!$url) {
            return ['success' => false, 'error' => 'Custom gateway URL not configured'];
        }
        
        if ($this->settings['test_mode']) {
            return $this->simulateSMS($phone, $message, 'custom');
        }
        
        $data = [
            'phone' => $phone,
            'message' => $message,
            'sender_id' => $senderId,
            'api_key' => $apiKey
        ];
        
        $headers = [];
        if ($this->settings['custom_headers']) {
            $headers = json_decode($this->settings['custom_headers'], true) ?? [];
        }
        
        $response = $this->sendHTTPRequest($url, $method, $data, $headers);
        
        if ($response['success']) {
            $this->logSMS($phone, $message, $senderId, 'custom', 'sent', $response['body']);
            return ['success' => true];
        }
        
        $this->logSMS($phone, $message, $senderId, 'custom', 'failed', $response['body'] ?? 'Unknown error');
        return ['success' => false, 'error' => $response['error'] ?? 'Failed to send SMS'];
    }
    
    /**
     * Send HTTP request
     */
    private function sendHTTPRequest($url, $method = 'POST', $data = [], $headers = []) {
        $ch = curl_init();
        
        if ($method === 'POST') {
            curl_setopt($ch, CURLOPT_POST, true);
            curl_setopt($ch, CURLOPT_POSTFIELDS, is_array($data) ? http_build_query($data) : $data);
        } elseif ($method === 'GET' && $data) {
            $url .= '?' . http_build_query($data);
        }
        
        curl_setopt($ch, CURLOPT_URL, $url);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
        curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
        curl_setopt($ch, CURLOPT_TIMEOUT, 30);
        
        $response = curl_exec($ch);
        $httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
        $error = curl_error($ch);
        
        curl_close($ch);
        
        if ($error) {
            return ['success' => false, 'error' => $error];
        }
        
        if ($httpCode >= 200 && $httpCode < 300) {
            return ['success' => true, 'body' => $response, 'code' => $httpCode];
        }
        
        return ['success' => false, 'error' => 'HTTP ' . $httpCode, 'body' => $response];
    }
    
    /**
     * Simulate SMS sending (test mode)
     */
    private function simulateSMS($phone, $message, $gateway) {
        $messageId = 'TEST_' . time() . '_' . rand(1000, 9999);
        $this->logSMS($phone, $message, null, $gateway, 'sent', 'TEST MODE - SMS not actually sent');
        return ['success' => true, 'message_id' => $messageId, 'test_mode' => true];
    }
    
    /**
     * Log SMS to database
     */
    private function logSMS($phone, $message, $senderId, $gateway, $status, $response = null, $messageId = null) {
        $stmt = $this->db->prepare("
            INSERT INTO sms_logs (recipient_phone, message, sender_id, gateway_provider, status, gateway_response, gateway_message_id, sent_at)
            VALUES (?, ?, ?, ?, ?, ?, ?, NOW())
        ");
        
        $stmt->execute([$phone, $message, $senderId, $gateway, $status, $response, $messageId]);
    }
    
    /**
     * Format phone number to international format
     */
    private function formatPhoneNumber($phone) {
        // Remove spaces, dashes, and parentheses
        $phone = preg_replace('/[^0-9+]/', '', $phone);
        
        // If doesn't start with +, assume it needs country code
        if (!str_starts_with($phone, '+')) {
            // You can add logic here to add default country code
            // For now, we'll just prepend + if it starts with country code digits
            if (strlen($phone) > 10) {
                $phone = '+' . $phone;
            }
        }
        
        return $phone;
    }
    
    /**
     * Get SMS statistics
     */
    public function getStatistics($days = 30) {
        $stmt = $this->db->prepare("
            SELECT 
                COUNT(*) as total,
                SUM(CASE WHEN status = 'sent' THEN 1 ELSE 0 END) as sent,
                SUM(CASE WHEN status = 'failed' THEN 1 ELSE 0 END) as failed,
                gateway_provider
            FROM sms_logs
            WHERE sent_at >= DATE_SUB(NOW(), INTERVAL ? DAY)
            GROUP BY gateway_provider
        ");
        
        $stmt->execute([$days]);
        return $stmt->fetchAll(PDO::FETCH_ASSOC);
    }
}

Sindbad File Manager Version 1.0, Coded By Sindbad EG ~ The Terrorists