本文目录导读:

我将为您详细介绍PHP集成API短信发送的完整流程,这里以常见的短信服务商为例(如阿里云短信、腾讯云短信等)。
基本集成步骤
1 准备工作
// 1. 注册短信服务商账号 // 2. 获取API密钥(AccessKey/SecretKey) // 3. 申请短信签名和模板
2 通用发送函数
<?php
/**
* 短信发送通用函数
*/
class SmsService {
private $apiKey;
private $apiSecret;
private $signName; // 短信签名
public function __construct($apiKey, $apiSecret, $signName) {
$this->apiKey = $apiKey;
$this->apiSecret = $apiSecret;
$this->signName = $signName;
}
/**
* 发送短信
* @param string $phone 手机号码
* @param string $templateCode 模板代码
* @param array $params 模板参数
* @return bool
*/
public function send($phone, $templateCode, $params = []) {
// 具体实现取决于短信服务商
return $this->callApi($phone, $templateCode, $params);
}
}
具体服务商集成示例
1 阿里云短信集成
<?php
// 需要安装阿里云SDK: composer require alibabacloud/dysmsapi
use AlibabaCloud\Client\AlibabaCloud;
use AlibabaCloud\Client\Exception\ClientException;
use AlibabaCloud\Client\Exception\ServerException;
class AliyunSmsService {
private $accessKeyId;
private $accessKeySecret;
private $signName;
public function __construct($accessKeyId, $accessKeySecret, $signName) {
$this->accessKeyId = $accessKeyId;
$this->accessKeySecret = $accessKeySecret;
$this->signName = $signName;
// 初始化客户端
AlibabaCloud::accessKeyClient($accessKeyId, $accessKeySecret)
->regionId('cn-hangzhou')
->asDefaultClient();
}
/**
* 发送短信
*/
public function sendSms($phone, $templateCode, $templateParam = []) {
try {
$result = AlibabaCloud::rpc()
->product('Dysmsapi')
->version('2017-05-25')
->action('SendSms')
->method('POST')
->host('dysmsapi.aliyuncs.com')
->options([
'query' => [
'RegionId' => 'cn-hangzhou',
'PhoneNumbers' => $phone,
'SignName' => $this->signName,
'TemplateCode' => $templateCode,
'TemplateParam' => json_encode($templateParam),
],
])
->request();
$response = $result->toArray();
if ($response['Code'] == 'OK') {
return [
'success' => true,
'message' => '发送成功',
'data' => $response
];
} else {
return [
'success' => false,
'message' => $response['Message'],
'code' => $response['Code']
];
}
} catch (ClientException $e) {
return [
'success' => false,
'message' => $e->getErrorMessage()
];
} catch (ServerException $e) {
return [
'success' => false,
'message' => $e->getErrorMessage()
];
}
}
}
// 使用示例
$sms = new AliyunSmsService('your_access_key_id', 'your_access_key_secret', '您的签名');
$result = $sms->sendSms('13800138000', 'SMS_123456789', ['code' => '123456']);
2 腾讯云短信集成
<?php
// 需要安装腾讯云SDK: composer require tencentcloud/tencentcloud-sdk-php
use TencentCloud\Common\Credential;
use TencentCloud\Common\Profile\ClientProfile;
use TencentCloud\Common\Profile\HttpProfile;
use TencentCloud\Sms\V20190711\SmsClient;
use TencentCloud\Sms\V20190711\Models\SendSmsRequest;
class TencentSmsService {
private $secretId;
private $secretKey;
private $appId;
private $signName;
public function __construct($secretId, $secretKey, $appId, $signName) {
$this->secretId = $secretId;
$this->secretKey = $secretKey;
$this->appId = $appId;
$this->signName = $signName;
}
/**
* 发送短信
*/
public function sendSms($phone, $templateId, $templateParams = []) {
try {
$cred = new Credential($this->secretId, $this->secretKey);
$httpProfile = new HttpProfile();
$httpProfile->setEndpoint('sms.tencentcloudapi.com');
$clientProfile = new ClientProfile();
$clientProfile->setHttpProfile($httpProfile);
$client = new SmsClient($cred, 'ap-guangzhou', $clientProfile);
$req = new SendSmsRequest();
$req->SmsSdkAppid = $this->appId;
$req->Sign = $this->signName;
$req->TemplateID = $templateId;
$req->PhoneNumberSet = ['+86' . $phone];
$req->TemplateParamSet = $templateParams;
$resp = $client->SendSms($req);
$result = json_decode($resp->toJsonString(), true);
if ($result['SendStatusSet'][0]['Code'] == 'Ok') {
return [
'success' => true,
'message' => '发送成功',
'data' => $result
];
} else {
return [
'success' => false,
'message' => $result['SendStatusSet'][0]['Message'],
'code' => $result['SendStatusSet'][0]['Code']
];
}
} catch (\Exception $e) {
return [
'success' => false,
'message' => $e->getMessage()
];
}
}
}
// 使用示例
$sms = new TencentSmsService('your_secret_id', 'your_secret_key', '1400xxxxxx', '您的签名');
$result = $sms->sendSms('13800138000', '123456', ['123456']);
3 简单HTTP请求方式(不依赖SDK)
<?php
class SimpleSmsService {
private $apiUrl;
private $apiKey;
public function sendSms($phone, $content) {
$postData = [
'api_key' => $this->apiKey,
'phone' => $phone,
'content' => $content
];
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $this->apiUrl);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query($postData));
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
curl_setopt($ch, CURLOPT_TIMEOUT, 30);
$response = curl_exec($ch);
$httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);
if ($httpCode == 200) {
return json_decode($response, true);
} else {
return false;
}
}
}
验证码发送示例
<?php
class VerificationCodeService {
private $smsService;
public function __construct($smsService) {
$this->smsService = $smsService;
}
/**
* 生成并发送验证码
*/
public function sendVerificationCode($phone) {
// 生成6位随机验证码
$code = str_pad(rand(0, 999999), 6, '0', STR_PAD_LEFT);
// 存储验证码到缓存(Redis/数据库)
$this->storeVerificationCode($phone, $code);
// 发送短信
$result = $this->smsService->sendSms(
$phone,
'SMS_VERIFICATION_TEMPLATE',
['code' => $code, 'minute' => 5]
);
return $result;
}
/**
* 验证验证码
*/
public function verifyCode($phone, $code) {
$storedCode = $this->getStoredVerificationCode($phone);
if ($storedCode && $storedCode == $code) {
// 验证成功后删除验证码
$this->deleteVerificationCode($phone);
return true;
}
return false;
}
private function storeVerificationCode($phone, $code) {
// 使用Redis存储,5分钟过期
// \Redis::setex('sms_code:' . $phone, 300, $code);
}
private function getStoredVerificationCode($phone) {
// return \Redis::get('sms_code:' . $phone);
}
private function deleteVerificationCode($phone) {
// \Redis::del('sms_code:' . $phone);
}
}
最佳实践建议
1 错误处理
class SmsException extends \Exception {
protected $errorCode;
public function __construct($message, $code = 0) {
parent::__construct($message, $code);
$this->errorCode = $code;
}
}
try {
$result = $smsService->sendSms($phone, $templateCode, $params);
if (!$result['success']) {
throw new SmsException($result['message'], $result['code']);
}
} catch (SmsException $e) {
// 记录日志
error_log("短信发送失败: " . $e->getMessage());
// 返回错误信息
return ['error' => $e->getMessage()];
}
2 频率限制
class SmsRateLimiter {
private $redis;
private $maxPerMinute = 1; // 每分钟最大发送次数
private $maxPerDay = 5; // 每天最大发送次数
public function canSend($phone) {
$minuteKey = "sms_limit:minute:{$phone}";
$dayKey = "sms_limit:day:" . date('Ymd') . ":{$phone}";
// 检查分钟限制
$minuteCount = $this->redis->get($minuteKey) ?: 0;
if ($minuteCount >= $this->maxPerMinute) {
return false;
}
// 检查天限制
$dayCount = $this->redis->get($dayKey) ?: 0;
if ($dayCount >= $this->maxPerDay) {
return false;
}
return true;
}
}
3 日志记录
// 使用Monolog记录日志
$log = new \Monolog\Logger('sms');
$log->pushHandler(new \Monolog\Handler\StreamHandler('path/to/sms.log', \Monolog\Logger::INFO));
$log->info('短信发送', [
'phone' => $phone,
'template' => $templateCode,
'result' => $result,
'time' => date('Y-m-d H:i:s')
]);
注意事项
- API密钥安全:不要在前端暴露API密钥,使用环境变量或配置文件管理
- 短信签名:需要提前在服务商处申请并通过审核
- 发送频率:合理控制发送频率,避免被认定为垃圾短信
- 错误处理:实现完善的错误处理和重试机制
- 日志记录:记录所有短信发送的详细日志,便于问题追踪
- 成本控制:注意短信发送的成本,避免被恶意利用
选择短信服务商时,建议对比各家服务的稳定性、价格和API易用性,选择最适合您项目需求的方案。