本文目录导读:

我将为您详细介绍如何在Symfony项目中集成Twilio实现短信发送功能。
安装依赖
composer require twilio/sdk
配置Twilio参数
在 .env 文件中添加配置:
TWILIO_ACCOUNT_SID=your_account_sid TWILIO_AUTH_TOKEN=your_auth_token TWILIO_FROM_NUMBER=+1234567890
创建Twilio配置服务
// config/services.yaml
services:
App\Service\TwilioService:
arguments:
$accountSid: '%env(TWILIO_ACCOUNT_SID)%'
$authToken: '%env(TWILIO_AUTH_TOKEN)%'
$fromNumber: '%env(TWILIO_FROM_NUMBER)%'
创建SMS服务类
// src/Service/TwilioService.php
namespace App\Service;
use Twilio\Rest\Client;
use Psr\Log\LoggerInterface;
class TwilioService
{
private Client $client;
private string $fromNumber;
private LoggerInterface $logger;
public function __construct(
string $accountSid,
string $authToken,
string $fromNumber,
LoggerInterface $logger
) {
$this->client = new Client($accountSid, $authToken);
$this->fromNumber = $fromNumber;
$this->logger = $logger;
}
/**
* 发送短信
*/
public function sendSms(string $to, string $message, array $options = []): array
{
try {
$sms = $this->client->messages->create(
$to,
array_merge([
'from' => $this->fromNumber,
'body' => $message,
], $options)
);
$this->logger->info('SMS sent successfully', [
'to' => $to,
'sid' => $sms->sid,
'status' => $sms->status
]);
return [
'success' => true,
'sid' => $sms->sid,
'status' => $sms->status,
'message' => 'SMS sent successfully'
];
} catch (\Exception $e) {
$this->logger->error('Failed to send SMS', [
'to' => $to,
'error' => $e->getMessage()
]);
return [
'success' => false,
'error' => $e->getMessage()
];
}
}
/**
* 发送验证码
*/
public function sendVerificationCode(string $to, string $code): array
{
$message = sprintf(
'您的验证码是: %s,有效期为5分钟。',
$code
);
return $this->sendSms($to, $message);
}
/**
* 批量发送短信
*/
public function sendBulkSms(array $recipients, string $message): array
{
$results = [];
foreach ($recipients as $recipient) {
$results[] = $this->sendSms($recipient, $message);
}
return $results;
}
/**
* 获取短信状态
*/
public function getMessageStatus(string $sid): ?string
{
try {
$message = $this->client->messages($sid)->fetch();
return $message->status;
} catch (\Exception $e) {
$this->logger->error('Failed to get message status', [
'sid' => $sid,
'error' => $e->getMessage()
]);
return null;
}
}
}
创建Form类型
// src/Form/SmsType.php
namespace App\Form;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\Form\Extension\Core\Type\TextType;
use Symfony\Component\Form\Extension\Core\Type\TextareaType;
use Symfony\Component\Form\Extension\Core\Type\TelType;
use Symfony\Component\Validator\Constraints as Assert;
class SmsType extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array $options): void
{
$builder
->add('phoneNumber', TelType::class, [
'label' => '手机号码',
'constraints' => [
new Assert\NotBlank(['message' => '请填写手机号码']),
new Assert\Regex([
'pattern' => '/^\+?[1-9]\d{1,14}$/',
'message' => '请输入有效的手机号码(包含国家代码)'
])
]
])
->add('message', TextareaType::class, [
'label' => '短信内容',
'constraints' => [
new Assert\NotBlank(['message' => '请填写短信内容']),
new Assert\Length([
'max' => 160,
'maxMessage' => '短信内容不能超过{{ limit }}个字符'
])
]
])
->add('verificationCode', TextType::class, [
'label' => '验证码(可选)',
'required' => false,
'constraints' => [
new Assert\Length([
'min' => 6,
'max' => 6,
'exactMessage' => '验证码必须为6位数字'
])
]
]);
}
}
创建Controller
// src/Controller/SmsController.php
namespace App\Controller;
use App\Service\TwilioService;
use App\Form\SmsType;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Routing\Annotation\Route;
use Symfony\Component\Security\Http\Attribute\IsGranted;
#[Route('/sms')]
#[IsGranted('ROLE_USER')]
class SmsController extends AbstractController
{
public function __construct(
private TwilioService $twilioService
) {}
#[Route('/send', name: 'sms_send')]
public function send(Request $request): Response
{
$result = null;
$form = $this->createForm(SmsType::class);
$form->handleRequest($request);
if ($form->isSubmitted() && $form->isValid()) {
$data = $form->getData();
if ($data['verificationCode']) {
$result = $this->twilioService->sendVerificationCode(
$data['phoneNumber'],
$data['verificationCode']
);
} else {
$result = $this->twilioService->sendSms(
$data['phoneNumber'],
$data['message']
);
}
if ($result['success']) {
$this->addFlash('success', '短信发送成功!SID: ' . $result['sid']);
} else {
$this->addFlash('error', '短信发送失败:' . $result['error']);
}
return $this->redirectToRoute('sms_send');
}
return $this->render('sms/send.html.twig', [
'form' => $form->createView(),
'result' => $result
]);
}
#[Route('/status/{sid}', name: 'sms_status')]
public function status(string $sid): Response
{
$status = $this->twilioService->getMessageStatus($sid);
return $this->json([
'sid' => $sid,
'status' => $status
]);
}
#[Route('/send-bulk', name: 'sms_send_bulk')]
public function sendBulk(Request $request): Response
{
if ($request->isMethod('POST')) {
$recipients = $request->request->all('recipients');
$message = $request->request->get('message');
$results = $this->twilioService->sendBulkSms($recipients, $message);
$successCount = count(array_filter($results, fn($r) => $r['success']));
$this->addFlash('success', "成功发送 {$successCount}/" . count($results) . " 条短信");
return $this->redirectToRoute('sms_send_bulk');
}
return $this->render('sms/send_bulk.html.twig');
}
}
创建模板
{# templates/sms/send.html.twig #}
{% extends 'base.html.twig' %}
{% block title %}发送短信{% endblock %}
{% block body %}
<div class="container mt-4">
<h1>发送短信</h1>
{% for message in app.flashes('success') %}
<div class="alert alert-success">{{ message }}</div>
{% endfor %}
{% for message in app.flashes('error') %}
<div class="alert alert-danger">{{ message }}</div>
{% endfor %}
{{ form_start(form, {'attr': {'class': 'needs-validation'}}) }}
<div class="mb-3">
{{ form_label(form.phoneNumber, null, {'label_attr': {'class': 'form-label'}}) }}
{{ form_widget(form.phoneNumber, {'attr': {'class': 'form-control'}}) }}
{{ form_errors(form.phoneNumber) }}
</div>
<div class="mb-3">
{{ form_label(form.message, null, {'label_attr': {'class': 'form-label'}}) }}
{{ form_widget(form.message, {'attr': {'class': 'form-control', 'rows': 3}}) }}
{{ form_errors(form.message) }}
</div>
<div class="mb-3">
{{ form_label(form.verificationCode, null, {'label_attr': {'class': 'form-label'}}) }}
{{ form_widget(form.verificationCode, {'attr': {'class': 'form-control'}}) }}
<small class="form-text text-muted">如果需要发送验证码,请填写6位数字</small>
{{ form_errors(form.verificationCode) }}
</div>
<button type="submit" class="btn btn-primary">发送短信</button>
{{ form_end(form) }}
</div>
{% endblock %}
创建验证码生成器
// src/Service/VerificationCodeGenerator.php
namespace App\Service;
class VerificationCodeGenerator
{
public function generate(int $length = 6): string
{
$code = '';
for ($i = 0; $i < $length; $i++) {
$code .= random_int(0, 9);
}
return $code;
}
public function store(string $phoneNumber, string $code): void
{
// 存储验证码到缓存或数据库
// 例如使用Redis或Symfony Cache组件
// 示例:使用文件缓存(生产环境应使用Redis等)
$cacheFile = sprintf('/tmp/sms_verification_%s.json', md5($phoneNumber));
file_put_contents($cacheFile, json_encode([
'code' => $code,
'expires_at' => time() + 300 // 5分钟有效期
]));
}
public function verify(string $phoneNumber, string $code): bool
{
$cacheFile = sprintf('/tmp/sms_verification_%s.json', md5($phoneNumber));
if (!file_exists($cacheFile)) {
return false;
}
$data = json_decode(file_get_contents($cacheFile), true);
if ($data['expires_at'] < time()) {
unlink($cacheFile);
return false;
}
return $data['code'] === $code;
}
}
创建异步发送(可选)
// src/Message/SmsNotification.php
namespace App\Message;
class SmsNotification
{
public function __construct(
private string $phoneNumber,
private string $message
) {}
public function getPhoneNumber(): string
{
return $this->phoneNumber;
}
public function getMessage(): string
{
return $this->message;
}
}
// src/MessageHandler/SmsNotificationHandler.php
namespace App\MessageHandler;
use App\Message\SmsNotification;
use App\Service\TwilioService;
use Symfony\Component\Messenger\Attribute\AsMessageHandler;
#[AsMessageHandler]
class SmsNotificationHandler
{
public function __construct(
private TwilioService $twilioService
) {}
public function __invoke(SmsNotification $message): void
{
$this->twilioService->sendSms(
$message->getPhoneNumber(),
$message->getMessage()
);
}
}
使用示例
// 在Controller中使用
class SomeController extends AbstractController
{
public function __construct(
private TwilioService $twilioService,
private VerificationCodeGenerator $codeGenerator
) {}
public function sendVerification(Request $request): Response
{
$phoneNumber = $request->get('phone');
$code = $this->codeGenerator->generate();
// 存储验证码
$this->codeGenerator->store($phoneNumber, $code);
// 发送短信
$result = $this->twilioService->sendVerificationCode($phoneNumber, $code);
if ($result['success']) {
return $this->json(['message' => '验证码已发送']);
}
return $this->json(['error' => '发送失败'], 500);
}
}
注意事项
- 安全: 妥善保管Twilio凭证,不要提交到版本控制
- 验证: 始终验证电话号码格式
- 限制: 设置发送频率限制,防止滥用
- 日志: 记录所有短信发送操作
- 错误处理: 妥善处理所有异常情况
- 测试: 在开发环境使用Twilio测试凭证
这样就完成了Symfony项目中的Twilio SMS集成,记得根据实际需求调整配置和功能。
版权声明:NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播