Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
0.00% covered (danger)
0.00%
0 / 59
0.00% covered (danger)
0.00%
0 / 2
CRAP
0.00% covered (danger)
0.00%
0 / 1
AfricasTalkingSmsProvider
0.00% covered (danger)
0.00%
0 / 59
0.00% covered (danger)
0.00%
0 / 2
72
0.00% covered (danger)
0.00%
0 / 1
 __construct
0.00% covered (danger)
0.00%
0 / 8
0.00% covered (danger)
0.00%
0 / 1
12
 send
0.00% covered (danger)
0.00%
0 / 51
0.00% covered (danger)
0.00%
0 / 1
30
1<?php
2
3namespace App\Services\Communication\Providers\Sms\Global;
4
5use App\Services\Communication\Contracts\SmsProviderInterface;
6
7class AfricasTalkingSmsProvider implements SmsProviderInterface
8{
9    private string $apiUrl;
10    private string $apiKey;
11    private string $username;
12    private string $senderId;
13
14    public function __construct(array $credentials)
15    {
16        $this->apiUrl    = rtrim($credentials['api_url'] ?? 'https://api.africastalking.com/version1/messaging', '/');
17        $this->apiKey    = trim($credentials['api_key']   ?? '');
18        $this->username  = trim($credentials['username']  ?? '');
19        $this->senderId  = trim($credentials['sender_id'] ?? '');
20
21        if (empty($this->apiKey) || empty($this->username)) {
22            throw new \RuntimeException(
23                'AfricasTalkingSmsProvider: api_key et username sont obligatoires'
24            );
25        }
26    }
27
28    // ================================================================
29    // SEND
30    // ================================================================
31
32    public function send(string $to, string $message): bool
33    {
34        // ── 1. Formatage du destinataire ─────────────────────────
35        $toClean = preg_replace('/[^0-9+]/', '', $to);
36        if (!str_starts_with($toClean, '+')) {
37            $toClean = '+' . $toClean;
38        }
39
40        // ── 2. Construction du body ───────────────────────────────
41        $formParams = [
42            'username' => $this->username,
43            'to'       => $toClean,
44            'message'  => $message,
45        ];
46
47        // senderId uniquement si défini
48        if (!empty($this->senderId)) {
49            $formParams['from'] = $this->senderId;
50        }
51
52        log_message('debug', '[AfricasTalkingSmsProvider::send] url='    . $this->apiUrl);
53        log_message('debug', '[AfricasTalkingSmsProvider::send] params=' . json_encode($formParams));
54
55        // ── 3. Envoi ──────────────────────────────────────────────
56        $client   = \Config\Services::curlrequest();
57        $response = $client->post($this->apiUrl, [
58            'headers' => [
59                'apiKey'       => $this->apiKey,
60                'Content-Type' => 'application/x-www-form-urlencoded',
61                'Accept'       => 'application/json',
62            ],
63            'form_params' => $formParams,
64            'http_errors' => false,
65            'timeout'     => 30,
66        ]);
67
68        $status       = $response->getStatusCode();
69        $responseBody = $response->getBody();
70
71        // ── 4. Succès ─────────────────────────────────────────────
72        if ($status === 201) {
73            $parsed    = json_decode($responseBody, true);
74            $msgStatus = $parsed['SMSMessageData']['Recipients'][0]['status'] ?? 'unknown';
75            $messageId = $parsed['SMSMessageData']['Recipients'][0]['messageId'] ?? 'N/A';
76
77            if ($msgStatus !== 'Success') {
78                log_message('error', '[AfricasTalkingSmsProvider::send] FAIL'
79                    . ' | status='    . $msgStatus
80                    . ' | to='        . $toClean
81                    . ' | body='      . $responseBody
82                );
83
84                throw new \RuntimeException(
85                    "[AfricasTalkingSmsProvider::send] Statut inattendu={$msgStatus} — to={$toClean} — {$responseBody}"
86                );
87            }
88
89            log_message('info', '[AfricasTalkingSmsProvider::send] SUCCESS'
90                . ' | to='        . $toClean
91                . ' | messageId=' . $messageId
92            );
93
94            return true;
95        }
96
97        // ── 5. Échec HTTP ─────────────────────────────────────────
98        log_message('error', '[AfricasTalkingSmsProvider::send] FAIL'
99            . ' | status=' . $status
100            . ' | to='     . $toClean
101            . ' | body='   . $responseBody
102        );
103
104        throw new \RuntimeException(
105            "[AfricasTalkingSmsProvider::send] HTTP {$status} — to={$toClean} — {$responseBody}"
106        );
107    }
108}