458f206ce9
Канал «SMS-Таргет» (target.t2.ru, HTTP API v2, Basic Auth) обеими половинами:
- отправка через POST /send_message (msisdn числом, shortcode, text);
- опрос судьбы GET /send_message/message-id-{id} — по одному сообщению,
пакетного запроса у t2 нет;
- приёмник обратных звонков GET|POST /api/webhook/t2-delivery/{secret}
со строками ?id=&status=&parts= — форма другая, чем у МТС.
Ловушки, закрытые тестами:
- слово status в ответе встречается дважды: снаружи «запрос удался»,
внутри судьба сообщения. Спутать = объявить доставленным всё подряд;
- отказ приезжает с HTTP 200 — судим по телу, не по коду;
- незнакомое слово статуса судьбу НЕ меняет, сохраняется в delivery_raw.
За «не доставлено» клиенту возвращаются деньги (В-198) — выдумка двигала
бы рубли;
- t2 наш ответ не проверяет и повторов не делает: пропущенный звонок потерян,
поэтому опрос client-sms:poll-delivery остаётся обязательным.
Деньги приёмник не двигает — возврат живёт в команде опроса (В-146).
Защита приёмника как у МТС: секрет не короче 32 знаков (пустой = закрыт
наглухо), список адресов отправителя, счётчик обращений; чужому 404, не 403.
Канал ВЫКЛЮЧЕН и живьём не пробован: имя отправителя Liderra.ru (заявка
№ 31121) на согласовании, без него t2 не выдаёт логин с паролём.
Порядок включения — docs/superpowers/runbooks/2026-08-04-vklyuchenie-kanala-t2.md
Миграций нет: графы судьбы появились ещё при МТС. Теле2 уже был в списке
разрешённых операторов и в тарифах админки — новых экранов не нужно.
Проверено: 78 тестов зелёные, Pint чист, статанализ по ВСЕМУ проекту 0 ошибок,
маршрут зарегистрирован. Против main — только вставки, удалений нет.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
61 lines
2.8 KiB
PHP
61 lines
2.8 KiB
PHP
<?php
|
|
|
|
declare(strict_types=1);
|
|
|
|
use App\Services\Sms\Providers\FakeSmsProvider;
|
|
use App\Services\Sms\SmsRouter;
|
|
|
|
it('в песочнице роутер несёт только заглушку', function () {
|
|
config()->set('services.sms.sandbox', true);
|
|
app()->forgetInstance(SmsRouter::class);
|
|
|
|
$router = app(SmsRouter::class);
|
|
|
|
expect($router->pick('mts'))->toBeInstanceOf(FakeSmsProvider::class);
|
|
});
|
|
|
|
it('в бою поднимаются только включённые каналы с ключами', function () {
|
|
config()->set('services.sms.sandbox', false);
|
|
config()->set('services.smsc.login', 'l');
|
|
config()->set('services.smsc.password', 'p');
|
|
config()->set('services.sms.mts.token', ''); // ключа нет → канал не встаёт
|
|
config()->set('services.sms.providers.mts.enabled', true);
|
|
config()->set('services.sms.providers.smsc.enabled', true);
|
|
app()->forgetInstance(SmsRouter::class);
|
|
|
|
$router = app(SmsRouter::class);
|
|
|
|
// МТС-ключа нет → МТС-номер уходит универсалу (СМС-центр).
|
|
expect($router->pick('mts')?->key())->toBe('smsc')
|
|
->and($router->pick('')?->key())->toBe('smsc');
|
|
});
|
|
|
|
it('канал Теле2 встаёт, когда включён и есть логин с паролем', function () {
|
|
config()->set('services.sms.sandbox', false);
|
|
config()->set('services.smsc.login', 'l');
|
|
config()->set('services.smsc.password', 'p');
|
|
config()->set('services.sms.providers.smsc.enabled', true);
|
|
config()->set('services.sms.tele2.login', 'liderra_api');
|
|
config()->set('services.sms.tele2.password', 'secret');
|
|
config()->set('services.sms.providers.tele2.enabled', true);
|
|
config()->set('services.sms.providers.tele2.serves', ['tele2']);
|
|
app()->forgetInstance(SmsRouter::class);
|
|
|
|
// Номер Теле2 уходит своему оператору, чужой — по-прежнему универсалу.
|
|
expect(app(SmsRouter::class)->pick('tele2')?->key())->toBe('tele2')
|
|
->and(app(SmsRouter::class)->pick('beeline')?->key())->toBe('smsc');
|
|
});
|
|
|
|
it('без логина Теле2 канал не встаёт и номер уходит универсалу', function () {
|
|
config()->set('services.sms.sandbox', false);
|
|
config()->set('services.smsc.login', 'l');
|
|
config()->set('services.smsc.password', 'p');
|
|
config()->set('services.sms.providers.smsc.enabled', true);
|
|
config()->set('services.sms.tele2.login', ''); // ключа нет → канал не встаёт
|
|
config()->set('services.sms.providers.tele2.enabled', true);
|
|
config()->set('services.sms.providers.tele2.serves', ['tele2']);
|
|
app()->forgetInstance(SmsRouter::class);
|
|
|
|
expect(app(SmsRouter::class)->pick('tele2')?->key())->toBe('smsc');
|
|
});
|