Initial commit: CloudOps infrastructure platform
This commit is contained in:
@@ -0,0 +1,94 @@
|
||||
<?php
|
||||
|
||||
namespace Mautic\SmsBundle\Integration\Twilio;
|
||||
|
||||
use Mautic\PluginBundle\Helper\IntegrationHelper;
|
||||
use Twilio\Exceptions\ConfigurationException;
|
||||
|
||||
class Configuration
|
||||
{
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
private $messagingServiceSid;
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
private $accountSid;
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
private $authToken;
|
||||
|
||||
public function __construct(
|
||||
private IntegrationHelper $integrationHelper,
|
||||
) {
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*
|
||||
* @throws ConfigurationException
|
||||
*/
|
||||
public function getMessagingServiceSid()
|
||||
{
|
||||
$this->setConfiguration();
|
||||
|
||||
return $this->messagingServiceSid;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*
|
||||
* @throws ConfigurationException
|
||||
*/
|
||||
public function getAccountSid()
|
||||
{
|
||||
$this->setConfiguration();
|
||||
|
||||
return $this->accountSid;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*
|
||||
* @throws ConfigurationException
|
||||
*/
|
||||
public function getAuthToken()
|
||||
{
|
||||
$this->setConfiguration();
|
||||
|
||||
return $this->authToken;
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws ConfigurationException
|
||||
*/
|
||||
private function setConfiguration(): void
|
||||
{
|
||||
if ($this->accountSid) {
|
||||
return;
|
||||
}
|
||||
|
||||
$integration = $this->integrationHelper->getIntegrationObject('Twilio');
|
||||
|
||||
if (!$integration || !$integration->getIntegrationSettings()->getIsPublished()) {
|
||||
throw new ConfigurationException();
|
||||
}
|
||||
|
||||
$this->messagingServiceSid = $integration->getIntegrationSettings()->getFeatureSettings()['messaging_service_sid'];
|
||||
if (empty($this->messagingServiceSid)) {
|
||||
throw new ConfigurationException();
|
||||
}
|
||||
|
||||
$keys = $integration->getDecryptedApiKeys();
|
||||
if (empty($keys['username']) || empty($keys['password'])) {
|
||||
throw new ConfigurationException();
|
||||
}
|
||||
|
||||
$this->accountSid = $keys['username'];
|
||||
$this->authToken = $keys['password'];
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,75 @@
|
||||
<?php
|
||||
|
||||
namespace Mautic\SmsBundle\Integration\Twilio;
|
||||
|
||||
use Mautic\SmsBundle\Callback\CallbackInterface;
|
||||
use Mautic\SmsBundle\Exception\NumberNotFoundException;
|
||||
use Mautic\SmsBundle\Helper\ContactHelper;
|
||||
use Symfony\Component\HttpFoundation\InputBag;
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
use Symfony\Component\HttpKernel\Exception\BadRequestHttpException;
|
||||
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
|
||||
use Twilio\Exceptions\ConfigurationException;
|
||||
|
||||
class TwilioCallback implements CallbackInterface
|
||||
{
|
||||
public function __construct(
|
||||
private ContactHelper $contactHelper,
|
||||
private Configuration $configuration,
|
||||
) {
|
||||
}
|
||||
|
||||
public function getTransportName(): string
|
||||
{
|
||||
return 'twilio';
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws NumberNotFoundException
|
||||
*/
|
||||
public function getContacts(Request $request): \Doctrine\Common\Collections\ArrayCollection
|
||||
{
|
||||
$this->validateRequest($request->request);
|
||||
|
||||
$number = $request->get('From');
|
||||
|
||||
return $this->contactHelper->findContactsByNumber($number);
|
||||
}
|
||||
|
||||
public function getMessage(Request $request): string
|
||||
{
|
||||
$this->validateRequest($request->request);
|
||||
|
||||
return trim($request->get('Body'));
|
||||
}
|
||||
|
||||
/**
|
||||
* @param InputBag<bool|float|int|string> $request
|
||||
*/
|
||||
private function validateRequest(InputBag $request): void
|
||||
{
|
||||
try {
|
||||
$accountSid = $this->configuration->getAccountSid();
|
||||
} catch (ConfigurationException) {
|
||||
// Not published or not configured
|
||||
throw new NotFoundHttpException();
|
||||
}
|
||||
|
||||
// Validate this is a request from Twilio
|
||||
if ($accountSid !== $request->get('AccountSid')) {
|
||||
throw new BadRequestHttpException();
|
||||
}
|
||||
|
||||
// Who is the message from?
|
||||
$number = $request->get('From');
|
||||
if (empty($number)) {
|
||||
throw new BadRequestHttpException();
|
||||
}
|
||||
|
||||
// What did they say?
|
||||
$message = trim($request->get('Body'));
|
||||
if (empty($message)) {
|
||||
throw new BadRequestHttpException();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,114 @@
|
||||
<?php
|
||||
|
||||
namespace Mautic\SmsBundle\Integration\Twilio;
|
||||
|
||||
use libphonenumber\NumberParseException;
|
||||
use libphonenumber\PhoneNumberFormat;
|
||||
use libphonenumber\PhoneNumberUtil;
|
||||
use Mautic\LeadBundle\Entity\Lead;
|
||||
use Mautic\SmsBundle\Sms\TransportInterface;
|
||||
use Psr\Log\LoggerInterface;
|
||||
use Twilio\Exceptions\ConfigurationException;
|
||||
use Twilio\Exceptions\TwilioException;
|
||||
use Twilio\Rest\Client;
|
||||
|
||||
class TwilioTransport implements TransportInterface
|
||||
{
|
||||
private ?Client $client = null;
|
||||
|
||||
public function __construct(
|
||||
private Configuration $configuration,
|
||||
private LoggerInterface $logger,
|
||||
) {
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $content
|
||||
*
|
||||
* @return bool|string
|
||||
*/
|
||||
public function sendSms(Lead $lead, $content)
|
||||
{
|
||||
$number = $lead->getLeadPhoneNumber();
|
||||
|
||||
if (null === $number) {
|
||||
return false;
|
||||
}
|
||||
|
||||
try {
|
||||
$messagingServiceSid = $this->configuration->getMessagingServiceSid();
|
||||
$this->configureClient();
|
||||
|
||||
$this->client->messages->create(
|
||||
$this->sanitizeNumber($number),
|
||||
$this->createPayload($messagingServiceSid, $content)
|
||||
);
|
||||
|
||||
return true;
|
||||
} catch (NumberParseException $numberParseException) {
|
||||
$this->logger->warning(
|
||||
$numberParseException->getMessage(),
|
||||
['exception' => $numberParseException]
|
||||
);
|
||||
|
||||
return $numberParseException->getMessage();
|
||||
} catch (ConfigurationException $configurationException) {
|
||||
$message = $configurationException->getMessage() ?: 'mautic.sms.transport.twilio.not_configured';
|
||||
$this->logger->warning(
|
||||
$message,
|
||||
['exception' => $configurationException]
|
||||
);
|
||||
|
||||
return $message;
|
||||
} catch (TwilioException $twilioException) {
|
||||
$this->logger->warning(
|
||||
$twilioException->getMessage(),
|
||||
['exception' => $twilioException]
|
||||
);
|
||||
|
||||
return $twilioException->getMessage();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $number
|
||||
*
|
||||
* @return string
|
||||
*
|
||||
* @throws NumberParseException
|
||||
*/
|
||||
private function sanitizeNumber($number)
|
||||
{
|
||||
$util = PhoneNumberUtil::getInstance();
|
||||
$parsed = $util->parse($number, 'US');
|
||||
|
||||
return $util->format($parsed, PhoneNumberFormat::E164);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return mixed[]
|
||||
*/
|
||||
private function createPayload(string $messagingServiceSid, string $content): array
|
||||
{
|
||||
return [
|
||||
'messagingServiceSid' => $messagingServiceSid,
|
||||
'body' => $content,
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws ConfigurationException
|
||||
*/
|
||||
private function configureClient(): void
|
||||
{
|
||||
if ($this->client) {
|
||||
// Already configured
|
||||
return;
|
||||
}
|
||||
|
||||
$this->client = new Client(
|
||||
$this->configuration->getAccountSid(),
|
||||
$this->configuration->getAuthToken()
|
||||
);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user