PHP项目中如何实现短信推送?

wen PHP项目 2

本文目录导读:

PHP项目中如何实现短信推送?

  1. 核心步骤概览
  2. 方案一:使用阿里云短信(国内主流)
  3. 方案二:使用腾讯云短信
  4. 方案三:使用Twilio(国际短信/海外用户)
  5. 重要注意事项
  6. 简单封装为通用函数示例

在PHP项目中实现短信推送,通常是通过调用第三方短信服务提供商(SMS Provider)的API来完成的,你不需要自己搭建短信网关(成本高、不稳定),而是使用阿里云、腾讯云、七牛云、Twilio(国外)等成熟服务。

以下是实现短信推送的标准流程代码示例

核心步骤概览

  1. 选择服务商:阿里云短信、腾讯云短信、Twilio、Submail等。
  2. 注册并获取密钥:获取 AccessKeyIDAccessKeySecret(或 AppIDAppKey)。
  3. 申请短信模板需在服务商后台审核通过(如“您的验证码是:${code}”)。
  4. 安装SDK或使用HTTP请求:通过Composer安装官方SDK,或直接Curl调用API。
  5. 编写发送逻辑:调用SDK方法,传入手机号、模板参数等。
  6. 处理返回结果:记录日志、处理发送失败情况。

使用阿里云短信(国内主流)

阿里云是国内最常用的短信服务商之一,稳定性高。

安装SDK

在项目根目录运行Composer:

composer require alibabacloud/dysmsapi-20170525 2.0.24

PHP发送短信代码

<?php
require_once 'vendor/autoload.php';
use AlibabaCloud\SDK\Dysmsapi\V20170525\Dysmsapi;
use AlibabaCloud\OpenApiUtil\OpenApiUtilClient;
use AlibabaCloud\Tea\Exception\TeaException;
use AlibabaCloud\Tea\Utils\Utils;
class SmsService
{
    private $accessKeyId;
    private $accessKeySecret;
    private $signName;      // 短信签名,如 “某某科技”
    private $templateCode;  // 模板CODE,如 “SMS_123456789”
    public function __construct()
    {
        $this->accessKeyId = '你的AccessKeyId';
        $this->accessKeySecret = '你的AccessKeySecret';
        $this->signName = '你的签名';
        $this->templateCode = '你的模板CODE';
    }
    /**
     * 发送短信
     * @param string $phone 手机号
     * @param array $params 模板参数,如 ['code'=>'123456']
     * @return bool
     */
    public function sendSms(string $phone, array $params): bool
    {
        // 1. 创建客户端
        $client = self::createClient($this->accessKeyId, $this->accessKeySecret);
        // 2. 构造请求
        $sendSmsRequest = new \AlibabaCloud\SDK\Dysmsapi\V20170525\Models\SendSmsRequest([
            'phoneNumbers' => $phone,
            'signName' => $this->signName,
            'templateCode' => $this->templateCode,
            'templateParam' => json_encode($params) // 必须转为JSON字符串
        ]);
        try {
            // 3. 发送并获取响应
            $response = $client->sendSms($sendSmsRequest);
            // 4. 判断是否成功(阿里云返回Code为OK表示成功)
            if ($response->body->code === 'OK') {
                // 记录成功日志
                file_put_contents('sms.log', date('Y-m-d H:i:s') . " 发送成功: $phone | BizId: " . $response->body->bizId . PHP_EOL, FILE_APPEND);
                return true;
            } else {
                // 记录失败原因
                file_put_contents('sms.log', date('Y-m-d H:i:s') . " 发送失败: $phone | Code: " . $response->body->code . " | Message: " . $response->body->message . PHP_EOL, FILE_APPEND);
                return false;
            }
        } catch (TeaException $e) {
            // 打印错误信息(生产环境建议记录日志)
            echo $e->getMessage() . PHP_EOL;
            return false;
        } catch (\Exception $e) {
            echo $e->getMessage() . PHP_EOL;
            return false;
        }
    }
    /**
     * 创建客户端实例
     */
    private static function createClient($accessKeyId, $accessKeySecret)
    {
        $config = new \AlibabaCloud\Tea\Config([
            'accessKeyId' => $accessKeyId,
            'accessKeySecret' => $accessKeySecret
        ]);
        // 短信API默认接入点
        $config->endpoint = 'dysmsapi.aliyuncs.com';
        return new Dysmsapi($config);
    }
}
// 使用示例
$sms = new SmsService();
$result = $sms->sendSms('13800138000', ['code' => '9527']);
if ($result) {
    echo "短信发送成功";
} else {
    echo "短信发送失败,请查看日志";
}
?>

使用腾讯云短信

腾讯云也是常见选择,API调用方式类似。

安装SDK

composer require tencentcloud/sms-v20210111

发送代码(精简版)

<?php
require_once 'vendor/autoload.php';
use TencentCloud\Sms\V20210111\SmsClient;
use TencentCloud\Sms\V20210111\Models\SendSmsRequest;
use TencentCloud\Common\Exception\TencentCloudSDKException;
use TencentCloud\Common\Credential;
class TencentSms
{
    private $secretId;
    private $secretKey;
    private $appId;       // 短信应用ID: 1400开头
    private $signName;    // 短信签名
    private $templateId;  // 模板ID
    public function __construct()
    {
        $this->secretId = '你的SecretId';
        $this->secretKey = '你的SecretKey';
        $this->appId = '1400XXXXXX';
        $this->signName = '你的签名';
        $this->templateId = '1234567';
    }
    public function send($phone, $code)
    {
        try {
            $cred = new Credential($this->secretId, $this->secretKey);
            $client = new SmsClient($cred, "ap-guangzhou"); // 区域一般选广州
            $req = new SendSmsRequest();
            $req->PhoneNumberSet = ["+86" . $phone]; // 国际号需加前缀
            $req->SmsSdkAppId = $this->appId;
            $req->SignName = $this->signName;
            $req->TemplateId = $this->templateId;
            $req->TemplateParamSet = [$code]; // 模板参数,如 ['验证码']
            $resp = $client->SendSms($req);
            // 判断返回状态
            $sendStatus = $resp->SendStatusSet[0];
            if ($sendStatus->Code === 'Ok') {
                return true;
            } else {
                // 记录失败信息
                error_log("腾讯云短信发送失败: " . $sendStatus->Code . " - " . $sendStatus->Message);
                return false;
            }
        } catch (TencentCloudSDKException $e) {
            error_log("腾讯云SDK异常: " . $e->getMessage());
            return false;
        }
    }
}

使用Twilio(国际短信/海外用户)

如果你的项目面向海外用户,Twilio是首选。

安装SDK

composer require twilio/sdk

发送代码

<?php
require_once 'vendor/autoload.php';
use Twilio\Rest\Client;
class TwilioSms
{
    private $accountSid;  // Twilio Account SID
    private $authToken;   // Twilio Auth Token
    private $fromNumber;  // Twilio购买的号码
    public function __construct()
    {
        $this->accountSid = '你的ACCOUNT_SID';
        $this->authToken = '你的AUTH_TOKEN';
        $this->fromNumber = '+1234567890'; // 你拥有的Twilio号码
    }
    public function send($phone, $message)
    {
        $client = new Client($this->accountSid, $this->authToken);
        try {
            $message = $client->messages->create(
                $phone,    // 接收号码,如 '+8613800138000'
                [
                    'from' => $this->fromNumber,
                    'body' => $message
                ]
            );
            if ($message->sid) {
                return true; // 发送成功
            }
            return false;
        } catch (\Exception $e) {
            error_log("Twilio发送失败: " . $e->getMessage());
            return false;
        }
    }
}

重要注意事项

  1. 密钥安全accessKeySecret 等密钥绝不能写在代码中,应存入 .env 文件或配置中心,通过 $_ENV 或配置文件读取。
  2. 短信模板:所有服务商必须使用审核通过的模板,不能直接拼接任意内容发送(尤其是国内服务商,违反规定会被封禁)。
  3. 频率限制:避免对同一个手机号频繁发送(如1分钟内发5次以上),代码中应加入逻辑:
    • 记录上次发送时间。
    • 使用缓存(Redis/Memcached)设置发送间隔。
    • 限制每天发送次数。
  4. 异常处理:网络超时、API限流、余额不足等情况需捕获并记录日志。
  5. 发送验证码:通常是先发送,然后服务器存储验证码(加过期时间),用户提交表单时比对。
  6. 并发处理:如果你的项目需要大量并发发送(如营销),建议使用消息队列(RabbitMQ、Redis队列)异步处理,而不是直接在请求中同步调用。

简单封装为通用函数示例

/**
 * 发送验证码
 * @param string $phone
 * @param string $code
 * @return bool
 */
function sendVerificationCode(string $phone, string $code): bool
{
    // 1. 检查发送频率(伪代码)
    if (isTooFrequent($phone)) {
        return false; // 发送太频繁
    }
    // 2. 调用服务商
    $sms = new SmsService; // 以阿里云为例
    $result = $sms->sendSms($phone, ['code' => $code]);
    // 3. 记录发送状态
    if ($result) {
        // 将验证码存入Redis,5分钟过期
        // redis_set('sms_code:' . $phone, $code, 300);
        // 记录发送时间
        // redis_set('sms_last_send:' . $phone, time(), 60);
    }
    return $result;
}

选择一种你常用的服务商,按照上述代码进行修改,替换你的密钥和模板参数,即可在你的PHP项目中实现短信推送。

抱歉,评论功能暂时关闭!