首先需要选择可靠的短信服务提供商(如阿里云、腾讯云、Twilio等),注册账号并获取API密钥、访问密钥等必要信息。
确保PHP环境已安装cURL扩展,用于发送HTTP请求:
sudo apt-get install php-curl
<?php
class SmsSender {
private $apiKey;
private $apiSecret;
private $endpoint;
public function __construct($apiKey, $apiSecret, $endpoint) {
$this->apiKey = $apiKey;
$this->apiSecret = $apiSecret;
$this->endpoint = $endpoint;
}
public function sendSMS($phoneNumber, $message) {
$data = [
'phone' => $phoneNumber,
'message' => $message,
'timestamp' => time()
];
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $this->endpoint);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query($data));
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_HTTPHEADER, [
'Authorization: Bearer ' . $this->generateSignature($data)
]);
$response = curl_exec($ch);
curl_close($ch);
return json_decode($response, true);
}
private function generateSignature($data) {
ksort($data);
$signString = http_build_query($data) . $this->apiSecret;
return hash_hmac('sha256', $signString, $this->apiKey);
}
}
?>
public function sendSMS($phoneNumber, $message) {
try {
// 参数验证
if (!preg_match('/^\+?[1-9]\d{1,14}$/', $phoneNumber)) {
throw new InvalidArgumentException('Invalid phone number format');
}
if (empty(trim($message))) {
throw new InvalidArgumentException('Message cannot be empty');
}
// 发送逻辑...
} catch (Exception $e) {
error_log('SMS sending failed: ' . $e->getMessage());
return ['success' => false, 'error' => $e->getMessage()];
}
}
curl_setopt($ch, CURLOPT_TIMEOUT, 30); // 30秒超时
curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 10); // 10秒连接超时
public function sendWithRetry($phoneNumber, $message, $maxRetries = 3) {
$attempt = 0;
while ($attempt < $maxRetries) {
$result = $this->sendSMS($phoneNumber, $message);
if ($result['success']) {
return $result;
}
$attempt++;
sleep(2 * $attempt); // 指数退避
}
return ['success' => false, 'error' => 'Max retries exceeded'];
}
使用持久连接减少TCP握手开销:
curl_setopt($ch, CURLOPT_FORBID_REUSE, false);
curl_setopt($ch, CURLOPT_FRESH_CONNECT, false);
public function sendBatch($messages) {
$multiHandle = curl_multi_init();
$handles = [];
foreach ($messages as $index => $message) {
$handles[$index] = $this->prepareCurlHandle($message);
curl_multi_add_handle($multiHandle, $handles[$index]);
}
$running = null;
do {
curl_multi_exec($multiHandle, $running);
curl_multi_select($multiHandle);
} while ($running > 0);
$results = [];
foreach ($handles as $index => $handle) {
$results[$index] = curl_multi_getcontent($handle);
curl_multi_remove_handle($multiHandle, $handle);
curl_close($handle);
}
curl_multi_close($multiHandle);
return $results;
}
对于大量短信发送,建议使用消息队列:
// 使用Redis队列示例
$redis = new Redis();
$redis->connect('127.0.0.1', 6379);
// 将短信任务加入队列
$redis->lpush('sms_queue', json_encode([
'phone' => $phoneNumber,
'message' => $message,
'timestamp' => time()
]));
// 使用环境变量存储密钥
$apiKey = getenv('SMS_API_KEY');
$apiSecret = getenv('SMS_API_SECRET');
// 或在配置文件中设置访问权限
public function checkRateLimit($phoneNumber) {
$key = 'sms_limit:' . $phoneNumber;
$redis = new Redis();
$count = $redis->incr($key);
if ($count == 1) {
$redis->expire($key, 3600); // 1小时限制
}
return $count <= 10; // 每小时最多10条
}
class SmsLogger {
public static function log($phoneNumber, $message, $status, $response = null) {
$logData = [
'timestamp' => date('Y-m-d H:i:s'),
'phone' => substr($phoneNumber, 0, 3) . '****' . substr($phoneNumber, -4),
'message_length' => strlen($message),
'status' => $status,
'response' => $response
];
file_put_contents(
'/var/log/sms.log',
json_encode($logData) . PHP_EOL,
FILE_APPEND
);
}
}
$startTime = microtime(true);
// 发送短信操作
$endTime = microtime(true);
$duration = ($endTime - $startTime) * 1000; // 毫秒
// 记录性能数据
Metrics::record('sms_latency', $duration);
通过以上实现和优化措施,可以构建一个高效、稳定、安全的PHP短信发送系统。