群控系统服务端开发模式-应用开发-短信工厂华为云短信开发
一、华为云短信工厂开发
1、添加框架对应的SDK
composer require huaweicloud/huaweicloud-sdk-php
2、添加华为云工厂
在根目录下extend文件夹下Sms文件夹下channel文件夹下,创建华为云短信发送工厂并命名为HuaweiSmsSender。记住,一定要在华为云短信发送工厂类名后面去实现短信发送工厂。
<?php
/**
* 华为云短信发送
* User: 龙哥·三年风水
* Date: 2024/12/3
* Time: 15:07
*/
namespace Sms\channel;
use Error\BaseError;
use GuzzleHttp\Client;
use GuzzleHttp\Exception\RequestException;
use Sms\SmsSenderInterface;
class HuaweiSmsSender implements SmsSenderInterface
{
protected static $signName = ""; //签名
protected static $appkey = ""; //APPkey
protected static $appSecret = ""; //APPsecret
protected static $sender = ""; //短信发送方的号码
protected static $url = ""; //请求地址接口
protected static $statusCallback = ""; //选填,短信状态报告接收地址,推荐使用域名,为空或者不填表示不接收状态报告
protected static $smsClient = null; //客户端
public function __construct($param){
self::$signName = $param['sign_name'];
self::$appkey = $param['access_key_id'];
self::$appSecret = $param['access_key_secret'];
//self::$sender = $param['app_id'];
self::$smsClient = new Client();
}
/**
* 单条短信发送
* 内部json处理过
* User: 龙哥·三年风水
* Date: 2024/12/1/0001
* Time: 15:52
* @ param $mobile 要发送的对象
* @ param $templateCode 模板编号
* @ param $templateParam 模板对应参数
* @ param string $signName 签名(如果需要采用不同的签名才需要传参)
* @ return mixed
*/
public static function send($mobile, $templateCode, $templateParam, $signName = '')
{
try{
$response = self::$smsClient->request('POST', "https://smsapi.cn-north-4.myhuaweicloud.com/sms/batchSendSms/v1",[
'form_params' => [
'from' => self::$sender,
'to' => $mobile,
'templateId' => $templateCode,
'templateParas' => json_encode($templateParam),
'statusCallback' => self::$statusCallback,
'signature' => empty($signName) ? self::$signName : $signName //使用国内短信通用模板时,必须填写签名名称
],
'headers' => [
'Authorization' => 'WSSE realm="SDP",profile="UsernameToken",type="Appkey"',
'X-WSSE' => self::buildWsseHeader()
],
'verify' => false //为防止因HTTPS证书认证失败造成API调用失败,需要先忽略证书信任问题
]);
return true;
}catch (RequestException $e){
throw new BaseError('发送失败',50000,200);
}
}
/**
* 批量短信发送
* 内部json处理过,单个模板,单个签名
* User: 龙哥·三年风水
* Date: 2024/12/2
* Time: 13:42
* @ param $mobiles 要发送的对象,数组形式
* @ param $templateCode 要发送的模板
* @ param $templateParam 要发送的参数
* @ param string $signName 签名(如果需要采用不同的签名才需要传参)
* @ return mixed
*/
public static function batchSend($mobiles, $templateCode, $templateParam, $signName = '')
{
try{
$response = self::$smsClient->request('POST', "https://smsapi.cn-north-4.myhuaweicloud.com/sms/batchSendDiffSms/v1",[
'form_params' => [
'from' => self::$sender,
'smsContent' => [
'to' => $mobiles,
'templateId' => $templateCode,
'templateParas' => json_encode($templateParam),
'signature' => empty($signName) ? self::$signName : $signName //使用国内短信通用模板时,必须填写签名名称
],
'statusCallback' => self::$statusCallback
],
'headers' => [
'Authorization' => 'WSSE realm="SDP",profile="UsernameToken",type="Appkey"',
'X-WSSE' => self::buildWsseHeader()
],
'verify' => false //为防止因HTTPS证书认证失败造成API调用失败,需要先忽略证书信任问题
]);
return true;
}catch (RequestException $e){
throw new BaseError('发送失败',50000,200);
}
}
private static function buildWsseHeader(){
$now = date('Y-m-d\TH:i:s\Z'); //Created
$nonce = uniqid(); //Nonce
$base64 = base64_encode(hash('sha256', ($nonce . $now . self::$appSecret))); //PasswordDigest
return sprintf("UsernameToken Username=\"%s\",PasswordDigest=\"%s\",Nonce=\"%s\",Created=\"%s\"",self::$appkey, $base64, $nonce, $now);
}
}
二、修改短信发送类实例工厂
<?php
/**
* 创建短信发送类实例工厂
* User: 龙哥 三年风水
* Date: 2024/12/1/0001
* Time: 15:59
*/
namespace Sms;
use Sms\channel\AliyunSmsSender;
use Sms\channel\HuaweiSmsSender;
use Sms\channel\QiniuyunSmsSender;
use Sms\channel\TencentSmsSender;
use Error\BaseError;
use app\model\param\Emailsms;
use app\model\param\Sms;
class SmsSenderFactory
{
protected static $instance=null;//缓存实例
protected static $channel = [];//通道参数
/**
* 调用类实例
* User: 龙哥 三年风水
* Date: 2024/12/1/0001
* Time: 15:59
* @ return null|AliyunSmsSender|QiniuyunSmsSender|TencentSmsSender
*/
public static function create(){
$smsId = Emailsms::dataFind(['id' => 1],'sms_id');
if(empty($smsId) || empty($smsId['sms_id']))throw new BaseError("未设置任何短信发送通道",50000,200);
$resSms = Sms::dataFind(['id' => $smsId['sms_id']],'app_id,access_key_id,access_key_secret,sign_name,status',true);
if(empty($resSms) || empty($resSms['status']))throw new BaseError("短信发送通道已关闭",50000,200);
self::$channel = [
'app_id' => $resSms['app_id'],
'access_key_id' => $resSms['access_key_id'],
'access_key_secret' => $resSms['access_key_secret'],
'sign_name' => $resSms['sign_name']
];
switch ($smsId['sms_id']){
case 1:
self::$instance = new AliyunSmsSender(self::$channel);
break;
case 2:
self::$instance = new QiniuyunSmsSender(self::$channel);
break;
case 3:
self::$instance = new TencentSmsSender(self::$channel);
break;
case 4:
self::$instance = new HuaweiSmsSender(self::$channel);
break;
default:
self::$instance = null;
throw new BaseError("未设置任何短信发送通道",50000,200);
break;
}
return self::$instance;
}
}