
# PHP
|    样例    |                                                                                       [发送短信（示例1）]、[发送分批短信（示例1）] [发送短信（示例2）]、[发送分批短信（示例2）] [接收状态报告]、[接收上行短信]                                                                                        |
|---|---|
| **环境要求** | 基于PHP 7.2.9版本，要求PHP 7.0及以上版本。                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                           |
| **依赖配置** | Composer、Guzzle（仅示例1依赖） 1. 请参考：<https://getcomposer.org/download/>，安装配置Composer。  2. 在项目文件夹下，创建文件composer.json，内容如下： ``` { "require": { "guzzlehttp/guzzle": "~6.0@dev" } } ```   3. 打开命令行窗口，进入项目文件夹，执行*composer install* ，安装guzzle。 注：安装完成，会在项目文件夹下自动生成"vendor/autoload.php"文件。    |
   
![](https://support.huaweicloud.com/devg-msgsms/public_sys-resources/notice_3.0-zh-cn.png)
- 发送短信为单模板群发短信示例，发送分批短信为多模板群发短信示例。

- 本文档所述Demo在提供服务的过程中，可能会涉及个人数据的使用，建议您遵从国家的相关法律采取足够的措施，以确保用户的个人数据受到充分的保护。
- 本文档所述Demo仅用于功能演示，不允许客户直接进行商业使用。
- 本文档信息仅供参考，不构成任何要约或承诺。
 
 #### 发送短信（示例1）
```
<?php
require 'vendor/autoload.php'; //执行composer install时自动生成
use GuzzleHttp\Psr7;
use GuzzleHttp\Client;
use GuzzleHttp\Exception\RequestException;
//必填,请参考"开发准备"获取如下数据,替换为实际值
$url = 'https://smsapi.cn-north-4.myhuaweicloud.com:443/sms/batchSendSms/v1'; //APP接入地址(在控制台"应用管理"页面获取)+接口访问URI
// 认证用的appKey和appSecret硬编码到代码中或者明文存储都有很大的安全风险，建议在配置文件或者环境变量中密文存放，使用时解密，确保安全；
$APP_KEY = 'c8RWg3ggEcyd4D3p94bf3Y7x1Ile'; //APP_Key
$APP_SECRET = 'q4Ii87Bh************80SfD7Al'; //APP_Secret
$sender = 'csms12345678'; //国内短信签名通道号
$TEMPLATE_ID = '8ff55eac1d0b478ab3c06c3c6a492300'; //模板ID
//条件必填,国内短信关注,当templateId指定的模板类型为通用模板时生效且必填,必须是已审核通过的,与模板类型一致的签名名称
$signature = "华为云短信测试"; //签名名称
//必填,全局号码格式(包含国家码),示例:+86151****6789,多个号码之间用英文逗号分隔
$receiver = '+86151****6789,+86152****7890'; //短信接收人号码
//选填,短信状态报告接收地址,推荐使用域名,为空或者不填表示不接收状态报告
$statusCallback = '';
/**
 * 选填,使用无变量模板时请赋空值 $TEMPLATE_PARAS = '';
 * 单变量模板示例:模板内容为"您的验证码是${1}"时,$TEMPLATE_PARAS可填写为 '["369751"]'
 * 双变量模板示例:模板内容为"您有${1}件快递请到${2}领取"时,$TEMPLATE_PARAS可填写为'["3","人民公园正门"]'
 * 模板中的每个变量都必须赋值，且取值不能为空
 * 查看更多模板规范和变量规范:产品介绍>短信模板须知和短信变量须知
 * @var string $TEMPLATE_PARAS
 */
$TEMPLATE_PARAS = '["369751"]'; //模板变量，此处以单变量验证码短信为例，请客户自行生成6位验证码，并定义为字符串类型，以杜绝首位0丢失的问题（例如：002569变成了2569）。
$client = new Client();
try {
    $response = $client->request('POST', $url, [
        'form_params' => [
            'from' => $sender,
            'to' => $receiver,
            'templateId' => $TEMPLATE_ID,
            'templateParas' => $TEMPLATE_PARAS,
            'statusCallback' => $statusCallback,
//            'signature' => $signature //使用国内短信通用模板时,必须填写签名名称
        ],
        'headers' => [
            'Authorization' => 'WSSE realm="SDP",profile="UsernameToken",type="Appkey"',
            'X-WSSE' => buildWsseHeader($APP_KEY, $APP_SECRET)
        ],
        'verify' => false //为防止因HTTPS证书认证失败造成API调用失败，需要先忽略证书信任问题
    ]);
    echo Psr7\str($response); //打印响应信息
} catch (RequestException $e) {
    echo $e;
    echo Psr7\str($e->getRequest()), "\n";
    if ($e->hasResponse()) {
        echo Psr7\str($e->getResponse());
    }
}
/**
 * 构造X-WSSE参数值
 * @param string $appKey
 * @param string $appSecret
 * @return string
 */
function buildWsseHeader(string $appKey, string $appSecret){
    $now = date('Y-m-d\TH:i:s\Z'); //Created
    $nonce = uniqid(); //Nonce
    $base64 = base64_encode(hash('sha256', ($nonce . $now . $appSecret))); //PasswordDigest
    return sprintf("UsernameToken Username=\"%s\",PasswordDigest=\"%s\",Nonce=\"%s\",Created=\"%s\"",
        $appKey, $base64, $nonce, $now);
}
?>
```
 #### 发送短信（示例2）
```
<?php
//必填,请参考"开发准备"获取如下数据,替换为实际值
$url = 'https://smsapi.cn-north-4.myhuaweicloud.com:443/sms/batchSendSms/v1'; //APP接入地址(在控制台"应用管理"页面获取)+接口访问URI
// 认证用的appKey和appSecret硬编码到代码中或者明文存储都有很大的安全风险，建议在配置文件或者环境变量中密文存放，使用时解密，确保安全；
$APP_KEY = 'c8RWg3ggEcyd4D3p94bf3Y7x1Ile'; //APP_Key
$APP_SECRET = 'q4Ii87Bh************80SfD7Al'; //APP_Secret
$sender = 'csms12345678'; //国内短信签名通道号
$TEMPLATE_ID = '8ff55eac1d0b478ab3c06c3c6a492300'; //模板ID
//条件必填,国内短信关注,当templateId指定的模板类型为通用模板时生效且必填,必须是已审核通过的,与模板类型一致的签名名称
$signature = '华为云短信测试'; //签名名称
//必填,全局号码格式(包含国家码),示例:+86151****6789,多个号码之间用英文逗号分隔
$receiver = '+8615123456789,+86152****7890'; //短信接收人号码
//选填,短信状态报告接收地址,推荐使用域名,为空或者不填表示不接收状态报告
$statusCallback = '';
/**
 * 选填,使用无变量模板时请赋空值 $TEMPLATE_PARAS = '';
 * 单变量模板示例:模板内容为"您的验证码是${1}"时,$TEMPLATE_PARAS可填写为'["369751"]'
 * 双变量模板示例:模板内容为"您有${1}件快递请到${2}领取"时,$TEMPLATE_PARAS可填写为'["3","人民公园正门"]'
 * 模板中的每个变量都必须赋值，且取值不能为空
 * 查看更多模板规范和变量规范:产品介绍>短信模板须知和短信变量须知
 * @var string $TEMPLATE_PARAS
 */
$TEMPLATE_PARAS = '["369751"]'; //模板变量，此处以单变量验证码短信为例，请客户自行生成6位验证码，并定义为字符串类型，以杜绝首位0丢失的问题（例如：002569变成了2569）。
//请求Headers
$headers = [
    'Content-Type: application/x-www-form-urlencoded',
    'Authorization: WSSE realm="SDP",profile="UsernameToken",type="Appkey"',
    'X-WSSE: ' . buildWsseHeader($APP_KEY, $APP_SECRET)
];
//请求Body
$data = http_build_query([
    'from' => $sender,
    'to' => $receiver,
    'templateId' => $TEMPLATE_ID,
    'templateParas' => $TEMPLATE_PARAS,
    'statusCallback' => $statusCallback,
//    'signature' => $signature //使用国内短信通用模板时,必须填写签名名称
]);
$context_options = [
    'http' => ['method' => 'POST', 'header'=> $headers, 'content' => $data, 'ignore_errors' => true],
    'ssl' => ['verify_peer' => false, 'verify_peer_name' => false] //为防止因HTTPS证书认证失败造成API调用失败，需要先忽略证书信任问题
];
print_r($context_options) . PHP_EOL; //打印请求信息
$response = file_get_contents($url, false, stream_context_create($context_options));
print_r($response) . PHP_EOL; //打印响应信息
/**
 * 构造X-WSSE参数值
 * @param string $appKey
 * @param string $appSecret
 * @return string
 */
function buildWsseHeader(string $appKey, string $appSecret){
    date_default_timezone_set('Asia/Shanghai');
    $now = date('Y-m-d\TH:i:s\Z'); //Created
    $nonce = uniqid(); //Nonce
    $base64 = base64_encode(hash('sha256', ($nonce . $now . $appSecret))); //PasswordDigest
    return sprintf("UsernameToken Username=\"%s\",PasswordDigest=\"%s\",Nonce=\"%s\",Created=\"%s\"",
        $appKey, $base64, $nonce, $now);
}
?>
```
 #### 发送分批短信（示例1）
```
<?php
require 'vendor/autoload.php'; //执行composer install时自动生成
use GuzzleHttp\Psr7;
use GuzzleHttp\Client;
use GuzzleHttp\Exception\RequestException;
//必填,请参考"开发准备"获取如下数据,替换为实际值
$url = 'https://smsapi.cn-north-4.myhuaweicloud.com:443/sms/batchSendDiffSms/v1'; //APP接入地址(在控制台"应用管理"页面获取)+接口访问URI
// 认证用的appKey和appSecret硬编码到代码中或者明文存储都有很大的安全风险，建议在配置文件或者环境变量中密文存放，使用时解密，确保安全；
$APP_KEY = 'c8RWg3ggEcyd4D3p94bf3Y7x1Ile'; //APP_Key
$APP_SECRET = 'q4Ii87Bh************80SfD7Al'; //APP_Secret
$sender = 'csms12345678'; //国内短信签名通道号
$TEMPLATE_ID_1 = '8ff55eac1d0b478ab3c06c3c6a492300'; //模板ID1
$TEMPLATE_ID_2 = '8ff55eac1d0b478ab3c06c3c6a492300'; //模板ID2
//条件必填,国内短信关注,当templateId指定的模板类型为通用模板时生效且必填,必须是已审核通过的,与模板类型一致的签名名称
$signature_1 = "华为云短信测试"; //签名名称1
$signature_2 = "华为云短信测试"; //签名名称2
//必填,全局号码格式(包含国家码),示例:+86151****6789,多个号码之间用英文逗号分隔
$receiver_1 = ['+86151****6789', '+86152****7890']; //模板1的接收号码
$receiver_2 = ['+86151****6789', '+86152****7890']; //模板2的接收号码
//选填,短信状态报告接收地址,推荐使用域名,为空或者不填表示不接收状态报告
$statusCallback = '';
/**
 * 选填,使用无变量模板时请赋空值 $TEMPLATE_PARAS = [];
 * 单变量模板示例:模板内容为"您的验证码是${1}"时,$TEMPLATE_PARAS可填写为['369751']
 * 双变量模板示例:模板内容为"您有${1}件快递请到${2}领取"时,$TEMPLATE_PARAS可填写为['3','人民公园正门']
 * 模板中的每个变量都必须赋值，且取值不能为空
 * 查看更多模板规范和变量规范:产品介绍>短信模板须知和短信变量须知
 */
$TEMPLATE_PARAS_1 = ['123456']; //模板1变量，此处以单变量验证码短信为例，请客户自行生成6位验证码，并定义为字符串类型，以杜绝首位0丢失的问题（例如：002569变成了2569）。
$TEMPLATE_PARAS_2 = ['234567']; //模板2变量，此处以单变量验证码短信为例，请客户自行生成6位验证码，并定义为字符串类型，以杜绝首位0丢失的问题（例如：002569变成了2569）。
//必填,请根据模板ID数量灵活增减
$smsContent = [
    //smsContent,不携带签名名称时,signature请填null
    initDiffSms($receiver_1, $TEMPLATE_ID_1, $TEMPLATE_PARAS_1, $signature_1),
    initDiffSms($receiver_2, $TEMPLATE_ID_2, $TEMPLATE_PARAS_2, $signature_2)
];
$client = new Client();
try {
    $response = $client->request('POST', $url, [
        'body' => json_encode([
            'from' => $sender,
            'statusCallback' => $statusCallback,
            'smsContent' => $smsContent
        ]),
        'headers' => [
            'Authorization' => 'WSSE realm="SDP",profile="UsernameToken",type="Appkey"',
            'X-WSSE' => buildWsseHeader($APP_KEY, $APP_SECRET),
            'Content-Type' => 'application/json'
        ],
        'verify' => false //为防止因HTTPS证书认证失败造成API调用失败，需要先忽略证书信任问题
    ]);
    echo Psr7\str($response); //打印响应信息
} catch (RequestException $e) {
    echo $e;
    echo Psr7\str($e->getRequest()), "\n";
    if ($e->hasResponse()) {
        echo Psr7\str($e->getResponse());
    }
}
/**
 * 构造smsContent参数值
 * @param array $receiver
 * @param string $templateId
 * @param array $templateParas
 * @param string $signature | 签名名称,使用国内短信通用模板时填写
 * @return string[]
 */
function initDiffSms(array $receiver, string $templateId, array $templateParas, string $signature) {
    if (null != $signature && strlen($signature) > 0) {
        return ['to' => $receiver, 'templateId' => $templateId, 'templateParas' => $templateParas, 'signature' => $signature];
    }
    return ['to' => $receiver, 'templateId' => $templateId, 'templateParas' => $templateParas];
}
/**
 * 构造X-WSSE参数值
 * @param string $appKey
 * @param string $appSecret
 * @return string
 */
function buildWsseHeader(string $appKey, string $appSecret){
    $now = date('Y-m-d\TH:i:s\Z'); //Created
    $nonce = uniqid();  //Nonce
    $base64 = base64_encode(hash('sha256', ($nonce . $now . $appSecret))); //PasswordDigest
    return sprintf("UsernameToken Username=\"%s\",PasswordDigest=\"%s\",Nonce=\"%s\",Created=\"%s\"",
        $appKey, $base64, $nonce, $now);
}
?>
```
 #### 发送分批短信（示例2）
```
<?php
//必填,请参考"开发准备"获取如下数据,替换为实际值
$url = 'https://smsapi.cn-north-4.myhuaweicloud.com:443/sms/batchSendDiffSms/v1'; //APP接入地址(在控制台"应用管理"页面获取)+接口访问URI
$APP_KEY = 'c8RWg3ggEcyd4D3p94bf3Y7x1Ile'; //APP_Key
// 认证用的appKey和appSecret硬编码到代码中或者明文存储都有很大的安全风险，建议在配置文件或者环境变量中密文存放，使用时解密，确保安全；
$APP_SECRET = 'q4Ii87Bh************80SfD7Al'; //APP_Secret
$sender = 'csms12345678'; //国内短信签名通道号
$TEMPLATE_ID_1 = '8ff55eac1d0b478ab3c06c3c6a492300'; //模板ID1
$TEMPLATE_ID_2 = '8ff55eac1d0b478ab3c06c3c6a492300'; //模板ID2
//条件必填,国内短信关注,当templateId指定的模板类型为通用模板时生效且必填,必须是已审核通过的,与模板类型一致的签名名称
$signature_1 = "华为云短信测试"; //签名名称1
$signature_2 = "华为云短信测试"; //签名名称2
//必填,全局号码格式(包含国家码),示例:+86151****6789,多个号码之间用英文逗号分隔
$receiver_1 = ['+86151****6789', '+86152****7890']; //模板1的接收号码
$receiver_2 = ['+86151****6789', '+86152****7890']; //模板2的接收号码
//选填,短信状态报告接收地址,推荐使用域名,为空或者不填表示不接收状态报告
$statusCallback = '';
/**
 * 选填,使用无变量模板时请赋空值 $TEMPLATE_PARAS = [];
 * 单变量模板示例:模板内容为"您的验证码是${1}"时,$TEMPLATE_PARAS可填写为['369751']
 * 双变量模板示例:模板内容为"您有${1}件快递请到${2}领取"时,$TEMPLATE_PARAS可填写为['3','人民公园正门']
 * 模板中的每个变量都必须赋值，且取值不能为空
 * 查看更多模板规范和变量规范:产品介绍>短信模板须知和短信变量须知
 */
$TEMPLATE_PARAS_1 = ['123456']; //模板1变量，此处以单变量验证码短信为例，请客户自行生成6位验证码，并定义为字符串类型，以杜绝首位0丢失的问题（例如：002569变成了2569）。
$TEMPLATE_PARAS_2 = ['234567']; //模板2变量，此处以单变量验证码短信为例，请客户自行生成6位验证码，并定义为字符串类型，以杜绝首位0丢失的问题（例如：002569变成了2569）。
//请求Headers
$headers = [
    'Content-Type: application/json',
    'Authorization: WSSE realm="SDP",profile="UsernameToken",type="Appkey"',
    'X-WSSE: ' . buildWsseHeader($APP_KEY, $APP_SECRET)
];
//请求Body
$data = json_encode([
    'from' => $sender,
    'statusCallback' => $statusCallback,
    'smsContent' => [ //必填,请根据模板ID数量灵活增减
        //smsContent,不携带签名名称时,signature请填''
        initDiffSms($receiver_1, $TEMPLATE_ID_1, $TEMPLATE_PARAS_1, $signature_1),
        initDiffSms($receiver_2, $TEMPLATE_ID_2, $TEMPLATE_PARAS_2, $signature_2)
    ]
]);
$context_options = [
    'http' => ['method' => 'POST', 'header'=> $headers, 'content' => $data, 'ignore_errors' => true],
    'ssl' => ['verify_peer' => false, 'verify_peer_name' => false] //为防止因HTTPS证书认证失败造成API调用失败，需要先忽略证书信任问题
];
print_r($context_options) . PHP_EOL; //打印请求信息
$response = file_get_contents($url, false, stream_context_create($context_options));
print_r($response) . PHP_EOL; //打印响应信息
/**
 * 构造smsContent参数值
 * @param array $receiver
 * @param string $templateId
 * @param array $templateParas
 * @param string $signature | 签名名称,使用国内短信通用模板时填写
 * @return string[]
 */
function initDiffSms(array $receiver, string $templateId, array $templateParas, string $signature) {
    if (null != $signature && strlen($signature) > 0) {
        return ['to' => $receiver, 'templateId' => $templateId, 'templateParas' => $templateParas, 'signature' => $signature];
    }
    return ['to' => $receiver, 'templateId' => $templateId, 'templateParas' => $templateParas];
}
/**
 * 构造X-WSSE参数值
 * @param string $appKey
 * @param string $appSecret
 * @return string
 */
function buildWsseHeader(string $appKey, string $appSecret){
    date_default_timezone_set('Asia/Shanghai');
    $now = date('Y-m-d\TH:i:s\Z'); //Created
    $nonce = uniqid(); //Nonce
    $base64 = base64_encode(hash('sha256', ($nonce . $now . $appSecret))); //PasswordDigest
    return sprintf("UsernameToken Username=\"%s\",PasswordDigest=\"%s\",Nonce=\"%s\",Created=\"%s\"",
        $appKey, $base64, $nonce, $now);
}
?>
```
 #### 接收状态报告
```
<?php
// 短信平台上报状态报告数据样例(urlencode)
// $success_body = 'sequence=1&total=1&updateTime=2018-10-31T08%3A43%3A41Z&source=2&smsMsgId=2ea20735-f856-4376-afbf-570bd70a46ee_11840135&status=DELIVRD';
$failed_body = 'sequence=1&total=1&updateTime=2018-10-31T08%3A43%3A41Z&source=2&smsMsgId=2ea20735-f856-4376-afbf-570bd70a46ee_11840135&status=E200027';
// onSmsStatusReport($success_body);
onSmsStatusReport($failed_body);
/**
 * 解析状态报告数据
 *
 * @param string $data 短信平台上报的状态报告数据
 */
function onSmsStatusReport(string $data)
{
    $keyValues = [];
    parse_str($data, $keyValues); //解析状态报告数据
    /**
     * Example: 此处已解析status为例,请按需解析所需参数并自行实现相关处理
     *
     * 'smsMsgId': 短信唯一标识
     * 'total': 长短信拆分条数
     * 'sequence': 拆分后短信序号
     * 'source': 状态报告来源
     * 'updateTime': 资源更新时间
     * 'status': 状态码
     */
    $status = $keyValues['status']; // 状态报告枚举值
    // 通过status判断短信是否发送成功
    if ('DELIVRD' === strtoupper($status)) {
        print 'Send sms success. smsMsgId: ' . $keyValues['smsMsgId'] . PHP_EOL;
    } else {
        // 发送失败,打印status和orgCode
        print 'Send sms failed. smsMsgId: ' . $keyValues['smsMsgId'] . PHP_EOL;
        print 'Failed status: ' . $status . PHP_EOL;
    }
}
?>
```
 #### 接收上行短信
```
<?php
// 上行短信通知样例(urlencode)
$upData = 'from=%2B86151****6789&to=1069****019&body=********&smsMsgId=9692b5be-c427-4525-8e73-cf4a6ac5b3f7';
onSmsUpData($upData);
/**
 * 解析上行短信通知数据
 *
 * @param string $data 短信平台推送的上行短信通知数据
 */
function onSmsUpData(string $data)
{
    $keyValues = [];
    parse_str($data, $keyValues); //解析上行短信通知数据
    /**
     * Example: 此处已解析body为例,请按需解析所需参数并自行实现相关处理
     *
     * 'smsMsgId': 上行短信唯一标识
     * 'from': 上行短信发送方的号码
     * 'to': 上行短信接收方的号码
     * 'body': 上行短信发送的内容
     */
    $body = $keyValues['body']; // 上行短信发送的内容
    print 'Sms up data. Body: ' . $body . PHP_EOL;
}
?>
```
#### 相关推荐
| 相关文档                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                               | 相关产品                                                                                                                                                                  |
|:---|:---|
| - 代码样例：[Java](https://support.huaweicloud.com/devg-msgsms/sms_04_0002.html)/[Python](https://support.huaweicloud.com/devg-msgsms/sms_04_0004.html)/[C#](https://support.huaweicloud.com/devg-msgsms/sms_04_0005.html)/[Node.js](https://support.huaweicloud.com/devg-msgsms/sms_04_0008.html)/[Go](https://support.huaweicloud.com/devg-msgsms/sms_04_0012.html)  - [发送短信API](https://support.huaweicloud.com/api-msgsms/sms_05_0001.html)  - [发送分批短信API](https://support.huaweicloud.com/api-msgsms/sms_05_0002.html)  - [接收状态报告API](https://support.huaweicloud.com/api-msgsms/sms_05_0003.html)  - [接收上行短信API](https://support.huaweicloud.com/api-msgsms/sms_05_0004.html)  - [调测问题处理](https://support.huaweicloud.com/api-msgsms/sms_05_0050.html)   | [语音通话](https://www.huaweicloud.com/product/voice.html) [隐私保护通话](https://www.huaweicloud.com/product/privatenumber.html) |
   
