diff --git a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php index bc1d623e75be9..bff1fcfda677b 100644 --- a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php +++ b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php @@ -3117,6 +3117,7 @@ private function registerNotifierConfiguration(array $config, ContainerBuilder $ $loader->load('notifier_webhook.php'); $webhookRequestParsers = [ + NotifierBridge\Smsbox\Webhook\SmsboxRequestParser::class => 'notifier.webhook.request_parser.smsbox', NotifierBridge\Sweego\Webhook\SweegoRequestParser::class => 'notifier.webhook.request_parser.sweego', NotifierBridge\Twilio\Webhook\TwilioRequestParser::class => 'notifier.webhook.request_parser.twilio', NotifierBridge\Vonage\Webhook\VonageRequestParser::class => 'notifier.webhook.request_parser.vonage', diff --git a/src/Symfony/Bundle/FrameworkBundle/Resources/config/notifier_webhook.php b/src/Symfony/Bundle/FrameworkBundle/Resources/config/notifier_webhook.php index 6447f41394679..0b30c33e25afa 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Resources/config/notifier_webhook.php +++ b/src/Symfony/Bundle/FrameworkBundle/Resources/config/notifier_webhook.php @@ -11,12 +11,16 @@ namespace Symfony\Component\DependencyInjection\Loader\Configurator; +use Symfony\Component\Notifier\Bridge\Smsbox\Webhook\SmsboxRequestParser; use Symfony\Component\Notifier\Bridge\Sweego\Webhook\SweegoRequestParser; use Symfony\Component\Notifier\Bridge\Twilio\Webhook\TwilioRequestParser; use Symfony\Component\Notifier\Bridge\Vonage\Webhook\VonageRequestParser; return static function (ContainerConfigurator $container) { $container->services() + ->set('notifier.webhook.request_parser.smsbox', SmsboxRequestParser::class) + ->alias(SmsboxRequestParser::class, 'notifier.webhook.request_parser.smsbox') + ->set('notifier.webhook.request_parser.sweego', SweegoRequestParser::class) ->alias(SweegoRequestParser::class, 'notifier.webhook.request_parser.sweego') diff --git a/src/Symfony/Component/Notifier/Bridge/Smsbox/README.md b/src/Symfony/Component/Notifier/Bridge/Smsbox/README.md index cb0dc35f46710..f9080836e1f68 100644 --- a/src/Symfony/Component/Notifier/Bridge/Smsbox/README.md +++ b/src/Symfony/Component/Notifier/Bridge/Smsbox/README.md @@ -54,3 +54,4 @@ $options = (new SmsboxOptions()) $sms->options($options); $texter->send($sms); ``` +## Smsbox notifier also provides Webhooks support. 🚀 diff --git a/src/Symfony/Component/Notifier/Bridge/Smsbox/Tests/Webhook/Fixtures/delivred.php b/src/Symfony/Component/Notifier/Bridge/Smsbox/Tests/Webhook/Fixtures/delivred.php new file mode 100644 index 0000000000000..0485c876d69f0 --- /dev/null +++ b/src/Symfony/Component/Notifier/Bridge/Smsbox/Tests/Webhook/Fixtures/delivred.php @@ -0,0 +1,9 @@ +setRecipientPhone('33612346578'); + +return $wh; diff --git a/src/Symfony/Component/Notifier/Bridge/Smsbox/Tests/Webhook/Fixtures/delivred.txt b/src/Symfony/Component/Notifier/Bridge/Smsbox/Tests/Webhook/Fixtures/delivred.txt new file mode 100644 index 0000000000000..d7aa8caa4f992 --- /dev/null +++ b/src/Symfony/Component/Notifier/Bridge/Smsbox/Tests/Webhook/Fixtures/delivred.txt @@ -0,0 +1 @@ +numero=33612346578&reference=250207960297&accuse=0&ts=1737368770 diff --git a/src/Symfony/Component/Notifier/Bridge/Smsbox/Tests/Webhook/SmsboxRequestParserTest.php b/src/Symfony/Component/Notifier/Bridge/Smsbox/Tests/Webhook/SmsboxRequestParserTest.php new file mode 100644 index 0000000000000..a2a7e6cf5de58 --- /dev/null +++ b/src/Symfony/Component/Notifier/Bridge/Smsbox/Tests/Webhook/SmsboxRequestParserTest.php @@ -0,0 +1,37 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Notifier\Bridge\Smsbox\Tests\Webhook; + +use Symfony\Component\HttpFoundation\Request; +use Symfony\Component\Notifier\Bridge\Smsbox\Webhook\SmsboxRequestParser; +use Symfony\Component\Webhook\Client\RequestParserInterface; +use Symfony\Component\Webhook\Test\AbstractRequestParserTestCase; + +class SmsboxRequestParserTest extends AbstractRequestParserTestCase +{ + protected function createRequestParser(): RequestParserInterface + { + return new SmsboxRequestParser(); + } + + protected function createRequest(string $payload): Request + { + parse_str(trim($payload), $parameters); + + return Request::create('/', 'GET', $parameters, [], [], ['REMOTE_ADDR' => '37.59.198.135']); + } + + protected static function getFixtureExtension(): string + { + return 'txt'; + } +} diff --git a/src/Symfony/Component/Notifier/Bridge/Smsbox/Webhook/SmsboxRequestParser.php b/src/Symfony/Component/Notifier/Bridge/Smsbox/Webhook/SmsboxRequestParser.php new file mode 100644 index 0000000000000..10ab612440f21 --- /dev/null +++ b/src/Symfony/Component/Notifier/Bridge/Smsbox/Webhook/SmsboxRequestParser.php @@ -0,0 +1,76 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Notifier\Bridge\Smsbox\Webhook; + +use Symfony\Component\HttpFoundation\ChainRequestMatcher; +use Symfony\Component\HttpFoundation\Request; +use Symfony\Component\HttpFoundation\RequestMatcher\IpsRequestMatcher; +use Symfony\Component\HttpFoundation\RequestMatcher\MethodRequestMatcher; +use Symfony\Component\HttpFoundation\RequestMatcherInterface; +use Symfony\Component\RemoteEvent\Event\Sms\SmsEvent; +use Symfony\Component\Webhook\Client\AbstractRequestParser; +use Symfony\Component\Webhook\Exception\RejectWebhookException; + +final class SmsboxRequestParser extends AbstractRequestParser +{ + protected function getRequestMatcher(): RequestMatcherInterface + { + return new ChainRequestMatcher([ + new MethodRequestMatcher(['GET']), + new IpsRequestMatcher([ + '37.59.198.135', + '178.33.185.51', + '54.36.93.79', + '54.36.93.80', + '62.4.31.47', + '62.4.31.48', + ]), + ]); + } + + protected function doParse(Request $request, #[\SensitiveParameter] string $secret): ?SmsEvent + { + $payload = $request->query->all(); + + if ( + !isset($payload['numero']) + || !isset($payload['reference']) + || !isset($payload['accuse']) + || !isset($payload['ts']) + ) { + throw new RejectWebhookException(406, 'Payload is malformed.'); + } + + $name = match ($payload['accuse']) { + // Documentation for SMSBOX dlr code https://www.smsbox.net/en/tools-development#doc-sms-accusees + '-3' => SmsEvent::FAILED, + '-1' => null, + '0' => SmsEvent::DELIVERED, + '1' => SmsEvent::FAILED, + '2' => SmsEvent::FAILED, + '3' => SmsEvent::FAILED, + '4' => SmsEvent::FAILED, + '5' => SmsEvent::FAILED, + '6' => SmsEvent::FAILED, + '7' => SmsEvent::FAILED, + '8' => SmsEvent::FAILED, + '9' => null, + '10' => null, + default => throw new RejectWebhookException(406, \sprintf('Unknown status: %s', $payload['accuse'])), + }; + + $event = new SmsEvent($name, $payload['reference'], $payload); + $event->setRecipientPhone($payload['numero']); + + return $event; + } +} diff --git a/src/Symfony/Component/Notifier/Bridge/Smsbox/composer.json b/src/Symfony/Component/Notifier/Bridge/Smsbox/composer.json index fc6fd5b6d3250..259fb81e9bcae 100644 --- a/src/Symfony/Component/Notifier/Bridge/Smsbox/composer.json +++ b/src/Symfony/Component/Notifier/Bridge/Smsbox/composer.json @@ -30,6 +30,9 @@ "symfony/notifier": "^7.2", "symfony/polyfill-php83": "^1.28" }, + "require-dev": { + "symfony/webhook": "^6.4|^7.0|^7.2" + }, "autoload": { "psr-4": { "Symfony\\Component\\Notifier\\Bridge\\Smsbox\\": ""