解决腾讯云SMS短信接口报错

浏览数(1065)

解决腾讯云SMS短信接口报错

0

因为腾讯云的短信接口最近搞活动,注册的时候会送100条免费短信,所以我注册了腾讯云的短信接口来用于我的个人网站和公众号注册的验证码。

image.png

但是在下载他们官方的SDK对接的时候,出现了一个问题,就是返回的数据一直都是空白的,一开始以为是本地调用的时候,或者接口参数配置错了,后面在他们官方SDK的代码里面发现了这一段:

    /**
     * Returns the default cacert bundle for the current system.
     *
     * First, the openssl.cafile and curl.cainfo php.ini settings are checked.
     * If those settings are not configured, then the common locations for
     * bundles found on Red Hat, CentOS, Fedora, Ubuntu, Debian, FreeBSD, OS X
     * and Windows are checked. If any of these file locations are found on
     * disk, they will be utilized.
     *
     * Note: the result of this function is cached for subsequent calls.
     *
     * @throws \RuntimeException if no bundle can be found.
     *
     * @deprecated Utils::defaultCaBundle will be removed in guzzlehttp/guzzle:8.0. This method is not needed in PHP 5.6+.
     */
    public static function defaultCaBundle(): string
    {
        static $cached = null;
        static $cafiles = [
            // Red Hat, CentOS, Fedora (provided by the ca-certificates package)
            '/etc/pki/tls/certs/ca-bundle.crt',
            // Ubuntu, Debian (provided by the ca-certificates package)
            '/etc/ssl/certs/ca-certificates.crt',
            // FreeBSD (provided by the ca_root_nss package)
            '/usr/local/share/certs/ca-root-nss.crt',
            // SLES 12 (provided by the ca-certificates package)
            '/var/lib/ca-certificates/ca-bundle.pem',
            // OS X provided by homebrew (using the default path)
            '/usr/local/etc/openssl/cert.pem',
            // Google app engine
            '/etc/ca-certificates.crt',
            // Windows?
            'C:\\windows\\system32\\curl-ca-bundle.crt',
            'C:\\windows\\curl-ca-bundle.crt',
        ];

我本地环境是IIS+PHP8,应该是V3的接口需要通过CA证书来进行接口交互,然后我的解决思路是这样的:

一、先在 https://curl.haxx.se/ca/cacert.pem 下载 cacert.pem 文件
二、把下载下来的 cacert.pem 文件放到所在版本的php目录里面
三、使用记事本编辑所在版本目录里面的 php.ini 文件
四、使用快捷键 ctrl+f 搜索 curl.cainfo(如果没有搜索到就手动加入)
五、删除 curl.cainfo 配置前分号注释符 ( ; ) 
六、配置 curl.cainfo 绝对路径
(如:我的当前php版本目录为 C:\Program Files\PHP\v8.1.13\,那么就修改成 curl.cainfo =C:\Program Files\PHP\v8.1.13\cacert.pem)


接下来就问题解决了,发送 成功 / 失败 过后,返回的数据为json格式,php可以通过 json_decode 将其转换成数组来处理:

image.png

以下是验证码短信发送成功过后,手机收到的信息:

8d4e3a6ffd738e6f991f13e370fa940.jpg


如果觉得使用腾讯官方SDK来实现短信验证码太麻烦,也可以直接使用我后面手写的php代码(使用的是V2接口,不需要额外配置 CA证书 进行联调,直接复制,按照注释改一下参数就可以使用了):

<?php
/**
 * LCSAY TENCENT SMS
 * WECHAT AND QQ : 516519782
*/
date_default_timezone_set("PRC");

$uid = ''; // 云API密钥上申请的标识身份 SecretId,入口 https://console.cloud.tencent.com/capi
$pwd = ''; // 云API密钥上申请的标识身份 SecretKey
$Sign = 'LCSAY公众号'; // 短信签名内容,使用 UTF-8 编码,必须填写已审核通过的签名

$TemplateParamSet = '065432'; // 模板参数,比如验证码的数字
$mobile = ''; // 例如:+8615812345678,其中前面有一个+号,86为国家码
$TemplateID = ''; // 模板 ID,必须填写已审核通过的模板 ID
$SmsSdkAppid = ''; // 短信SdkAppid在 [短信控制台](https://console.cloud.tencent.com/smsv2) 添加应用后生成的实际SdkAppid,示例如1400006666

$Timestamp = time();
$Nonce = mt_rand(111111, 999999);

$data = array(
    'Action' => 'SendSms',
    'PhoneNumberSet.0' => $mobile,
    'TemplateID' => $TemplateID,
    'Sign' => $Sign,
    'TemplateParamSet.0' => $TemplateParamSet,
    'SmsSdkAppid' => $SmsSdkAppid,
    'Nonce' => $Nonce,
    'Region' => 'ap-shanghai',
    'SecretId' => $uid,
    'Timestamp' => $Timestamp,
    'Version' => '2019-07-11',
);

$qsign = tosign('POST', $data, $pwd);
$data['Signature'] = $qsign;

$target = "https://sms.tencentcloudapi.com/";

$result = _sendRequest($target, $data, 'POST');

//$result = json_decode($result, true);

var_dump($result);

$req = $result['Response']['SendStatusSet'][0]['Code'];

if ($req == 'Ok') {
    // 发送成功
    return true;
}

function _sendRequest($url, $paramArray, $method = 'POST')
{

    $ch = curl_init();

    if ($method == 'POST') {
        $paramArray = is_array($paramArray) ? http_build_query($paramArray, '', '&', PHP_QUERY_RFC3986) : $paramArray;

        curl_setopt($ch, CURLOPT_POST, 1);
        curl_setopt($ch, CURLOPT_POSTFIELDS, $paramArray);
    } else {
        $url .= '?' . http_build_query($paramArray, '', '&', PHP_QUERY_RFC3986);
    }

    curl_setopt($ch, CURLOPT_URL, $url);
    curl_setopt($ch, CURLOPT_TIMEOUT, 30);

    curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);

    if (false !== strpos($url, "https")) {
        // 证书
        curl_setopt($ch, CURLOPT_SSL_VERIFYPEER,  false);
        curl_setopt($ch, CURLOPT_SSL_VERIFYHOST,  false);
    }
    $resultStr = curl_exec($ch);

    // 在解码之前检查 $resultStr 是否是一个字符串
    if (is_string($resultStr)) {
        $result = json_decode($resultStr, true);

        if (!$result) {
            return $resultStr;
        }
        return $result;
    } else {
        // 处理 $resultStr 不是字符串的情况(已经是数组的情况)
        return $resultStr;
    }
}

function tosign($pa, $param, $pwd)
{
    ksort($param);
    $signStr = $pa . "sms.tencentcloudapi.com/?";
    foreach ($param as $key => $value) {
        $signStr = $signStr . $key . "=" . $value . "&";
    }
    $signStr = substr($signStr, 0, -1);

    $signature = base64_encode(hash_hmac("sha1", $signStr, $pwd, true));

    return $signature;
}
?>

注:本文由www.lcsay.com发表,如需转载或已侵权,请联系我。

✎﹏𝓁𝒸𝓈𝒶𝓎﹍﹍·

评论0