Init Git Prod Mars 2026
This commit is contained in:
commit
d81efe93b1
362 files changed
+86627
No files matched your search
@@ -0,0 +1,115 @@
|
||||
<?php
|
||||
// /sms/wa_client.php
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Sms;
|
||||
|
||||
final class WaClient
|
||||
{
|
||||
private string $phoneId;
|
||||
private string $token;
|
||||
private int $timeout;
|
||||
|
||||
public function __construct(array $cfg)
|
||||
{
|
||||
$this->phoneId = $cfg['phone_number_id'] ?? '';
|
||||
$this->token = $cfg['access_token'] ?? '';
|
||||
$this->timeout = (int)($cfg['timeout'] ?? 20);
|
||||
|
||||
if ($this->phoneId === '' || $this->token === '') {
|
||||
throw new \RuntimeException('Config WhatsApp incomplète: phone_number_id / access_token manquants.');
|
||||
}
|
||||
}
|
||||
|
||||
/** Normalise en format international chiffres-only (WhatsApp: pas de "+") */
|
||||
public static function normalizePhone(string $raw): string
|
||||
{
|
||||
$n = preg_replace('/\D+/', '', $raw ?? '');
|
||||
// Ex: numéro FR commençant par 0 -> remplace 0 initial par 33
|
||||
if (preg_match('/^0\d{9}$/', $n)) {
|
||||
$n = '33' . substr($n, 1);
|
||||
}
|
||||
return $n;
|
||||
}
|
||||
|
||||
/**
|
||||
* Envoi d’un template Utility.
|
||||
* $templateName: ex. 'notification_rdv'
|
||||
* $lang: 'ru' (ou celui déclaré/validé chez Meta)
|
||||
* $to: numéro destinataire (06..., +33..., 336..., etc.)
|
||||
* $bodyParams: tableau des valeurs pour {{1}}, {{2}}, ...
|
||||
*/
|
||||
public function sendTemplate(string $templateName, string $lang, string $to, array $bodyParams, ?array $buttonUrlParams = null): array
|
||||
{
|
||||
$toNorm = self::normalizePhone($to);
|
||||
if ($toNorm === '' || strlen($toNorm) < 8) {
|
||||
throw new \InvalidArgumentException('Numéro destinataire invalide.');
|
||||
}
|
||||
|
||||
// BODY params
|
||||
$components = [[
|
||||
'type' => 'body',
|
||||
'parameters' => array_map(fn($t) => ['type'=>'text','text'=>(string)$t], $bodyParams)
|
||||
]];
|
||||
|
||||
// BUTTON URL params (facultatif)
|
||||
// $buttonUrlParams attendu sous la forme: ['0' => ['123']] // index "0" => [ valeurs pour {{1}}, {{2}} si existait ]
|
||||
if ($buttonUrlParams) {
|
||||
foreach ($buttonUrlParams as $index => $values) {
|
||||
$params = array_map(fn($t) => ['type'=>'text','text'=>(string)$t], (array)$values);
|
||||
$components[] = [
|
||||
'type' => 'button',
|
||||
'sub_type' => 'url',
|
||||
'index' => (string)$index,
|
||||
'parameters' => $params,
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
$payload = [
|
||||
'messaging_product' => 'whatsapp',
|
||||
'to' => $toNorm,
|
||||
'type' => 'template',
|
||||
'template' => [
|
||||
'name' => $templateName,
|
||||
'language' => ['code' => $lang],
|
||||
'components' => $components,
|
||||
]
|
||||
];
|
||||
|
||||
$json = json_encode($payload, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES);
|
||||
|
||||
$ch = curl_init("https://graph.facebook.com/v23.0/{$this->phoneId}/messages");
|
||||
curl_setopt_array($ch, [
|
||||
CURLOPT_HTTPHEADER => [
|
||||
"Authorization: Bearer {$this->token}",
|
||||
"Content-Type: application/json",
|
||||
"Accept: application/json",
|
||||
"Expect:",
|
||||
"Connection: close",
|
||||
],
|
||||
CURLOPT_POST => true,
|
||||
CURLOPT_POSTFIELDS => $json,
|
||||
CURLOPT_RETURNTRANSFER => true,
|
||||
CURLOPT_TIMEOUT => $this->timeout,
|
||||
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
|
||||
CURLOPT_SSL_VERIFYPEER => true,
|
||||
CURLOPT_SSL_VERIFYHOST => 2,
|
||||
]);
|
||||
|
||||
$resp = curl_exec($ch);
|
||||
$code = curl_getinfo($ch, CURLINFO_HTTP_CODE);
|
||||
$err = curl_error($ch);
|
||||
curl_close($ch);
|
||||
|
||||
$data = json_decode($resp ?? '', true);
|
||||
|
||||
return [
|
||||
'http_code' => $code,
|
||||
'error' => $err ?: null,
|
||||
'response' => $data ?? $resp,
|
||||
'payload' => $payload,
|
||||
];
|
||||
}
|
||||
|
||||
}
|
||||
Reference in new issue
Block a user