阿里大于在最近(其实我也不知道确定的时候)并入阿里云,并且成为阿里云·通信

2-1.jpg

新的短信发送接口文档(包括SDK下载):

一、遇到的问题

很尴尬的一点是,我的一个项目本来使用的是自己的测试账户(阿里大于),然后上线的时候,使用的是甲方的账户。

而甲方是在阿里大于成为阿里云·通信之后注册的账户。

区别:

之前的阿里大于的用户能够继续在原阿里大于的控制面板进行操作,新注册的用户已经无法进入原阿里大于的控制面板,进入的时候阿里云的控制面板

旧的阿里大于的SDK已经不适用于新的阿里云通信的SDK

所以我之前的sdk已经无法使用了,短信业务这部分我需要接入新的阿里云的SDK进行操作。

二、接入过程中遇到的麻烦

在接入的时候就看到有人说(忘记在哪里看到的了)新的云通信的SDK存在一定的问题,尤其是在接入的时候

我的项目是ThinkPHP5的,集成肯定使用的是composer。

但是SDK开发者本身没有上传到packgist,不过有别人已经上传了,我是用别人的require的

推荐的接入方式:

  1. 直接复制到vendor文件夹中,不管其他的(粗暴型)
  2. 使用composer require,一个可用的包:zeonwang/aliyun-dysms-php-sdk(变相粗暴型)

PS : 其实最终都一样,也就是直接放在了vendor中(我看了,只是去掉了tests等),好处框架能够自动加载vendor中的autoload

接入之后遇到的问题:

帮助文档中(文章开头给了地址),给了一个demo的(PHP的demo),代码如下:

//此处需要替换成自己的AK信息
    $accessKeyId = "yourAccessKeyId";//参考本文档步骤2
    $accessKeySecret = "yourAccessKeySecret";//参考本文档步骤2
    //短信API产品名(短信产品名固定,无需修改)
    $product = "Dysmsapi";
    //短信API产品域名(接口地址固定,无需修改)
    $domain = "dysmsapi.aliyuncs.com";
    //暂时不支持多Region(目前仅支持cn-hangzhou请勿修改)
    $region = "cn-hangzhou";
    //初始化访问的acsCleint
    $profile = DefaultProfile::getProfile($region, $accessKeyId, $accessKeySecret);
    DefaultProfile::addEndpoint("cn-hangzhou", "cn-hangzhou", $product, $domain);
    $acsClient= new DefaultAcsClient($profile);
    $request = new Dysmsapi\Request\V20170525\SendSmsRequest;
    //必填-短信接收号码。支持以逗号分隔的形式进行批量调用,批量上限为1000个手机号码,批量调用相对于单条调用及时性稍有延迟,验证码类型的短信推荐使用单条调用的方式
    $request->setPhoneNumbers("15067126468");
    //必填-短信签名
    $request->setSignName("云通信");
    //必填-短信模板Code
    $request->setTemplateCode("SMS_0001");
    //选填-假如模板中存在变量需要替换则为必填(JSON格式),友情提示:如果JSON中需要带换行符,请参照标准的JSON协议对换行符的要求,比如短信内容中包含\r\n的情况在JSON中需要表示成\\r\\n,否则会导致JSON在服务端解析失败
    $request->setTemplateParam("{\"code\":\"12345\",\"product\":\"云通信服务\"}");
    //选填-发送短信流水号
    $request->setOutId("1234");
    //发起访问请求
    $acsResponse = $acsClient->getAcsResponse($request);

我是创建了一个函数,然后原封不动的复制进去,然后做了一些基本的更改和配置,但是当我调用函数的时候一直是失败的,提示我类没找到

错误我就不贴出来了,反正就是各种类找不到错误,但是如果使用PHPstorm,类是提示加载可用的!!

三、类无法找到的原因

这个错误是所有的SDK的类都找不到

我其实找了很久的原因,因为在我的印象中,SDK的所有都会自动加载的,他说类无法找到,很明显是在加载过程中出了问题,但是我又不知道这个问题是什么。

为此我还在segmentfault上问了问题。

不过我在自己看了SDK中的demo后发现了问题的关键:

2-2.jpg

关键在于它的demoSms中其实是加载了 Config.php 中的 Config

use Aliyun\Core\Config;
use Aliyun\Core\Profile\DefaultProfile;
use Aliyun\Core\DefaultAcsClient;
use Aliyun\Api\Sms\Request\V20170525\SendSmsRequest;
use Aliyun\Api\Sms\Request\V20170525\QuerySendDetailsRequest;

// 加载区域结点配置
Config::load();

而在官方的帮助手册中是没有给这个 Config::load()

因此我在我的函数中直接写入了 Config::load() 来加载,其他和帮助手册中的代码一样即可

我的函数如下:

  public function sms($data=[])
    {
        // 这里 Config::load() 加载配置
        // 注意命名空间
        \Aliyun\Core\Config::load();
        //此处需要替换成自己的AK信息
        $accessKeyId = Config::get('alidayu.appkey');// 从配置加载appkey
        $accessKeySecret = Config::get('alidayu.secretKey');// 从配置加载appkey
        //短信API产品名(短信产品名固定,无需修改)
        $product = "Dysmsapi";
        //短信API产品域名(接口地址固定,无需修改)
        $domain = "dysmsapi.aliyuncs.com";
        //暂时不支持多Region(目前仅支持cn-hangzhou请勿修改)
        $region = "cn-hangzhou";
        //初始化访问的acsCleint
        $profile = DefaultProfile::getProfile($region, $accessKeyId, $accessKeySecret);
        DefaultProfile::addEndpoint("cn-hangzhou","cn-hangzhou", $product, $domain);
        $acsClient= new DefaultAcsClient($profile);
        $request = new SendSmsRequest();
        //必填-短信接收号码。支持以逗号分隔的形式进行批量调用,批量上限为1000个手机号码,批量调用相对于单条调用及时性稍有延迟,验证码类型的短信推荐使用单条调用的方式
        $request->setPhoneNumbers($data['mobile']);
        //必填-短信签名
        $request->setSignName(Config::get('alidayu.FreeSignName'));
        //必填-短信模板Code
        $request->setTemplateCode($data['template']);
        //选填-假如模板中存在变量需要替换则为必填(JSON格式)
        $request->setTemplateParam(json_encode($data['param']));
        //选填-发送短信流水号
        // $request->setOutId("1234");
        //发起访问请求
        $acsResponse = $acsClient->getAcsResponse($request);
        if(!$acsResponse || $acsResponse->Code !="OK"){
            // 发送失败
            $codeList=Cache::get("code_list");
            $codeList=$codeList?$codeList:[];
            // 写入缓存表明原因
            Cache::set("code_list",array_push($codeList,['time'=>time(),'code'=>$acsResponse->Code]));
            return false;
        }else{
            return true;
        }
    }

我的函数调用的方式:

$result = $Send->sms([
    'param'  => ['code'=>$code],  // param 是在创建模板的时候的key=>value,我的模板只有code一个参数
    'mobile'  => strval($phone),  // 手机号
    'template'  => Config::get('alidayu.template_1'), // 选择短信模板
]);

四、比较好的解决方式

出现上面的问题,可以使用粗暴的解决,我就是粗暴的解决,不过我在segmenfault上的问题,有人给了更好的解决方法。

其实在集成sdk的时候,修改autoload是比较好的方式,让其加载Config。

不过可能会引起冲突。

还是值得参考的解决方法: