mingyuanyun/yii2-imessage

消息发送组件,集成多渠道消息(邮件、企业微信、短信、APP)消息,内置重试机制、统一返回格式,支持下云(短信类支持公共组短信及阿里云短信)。

v1.0.211124 2021-11-24 09:25 UTC

This package is not auto-updated.

Last update: 2024-05-08 21:32:18 UTC


README

消息发送组件,集成多渠道消息(邮件、企业微信、短信、APP)消息,内置重试机制、统一返回格式,支持下云(短信类支持公共组短信及阿里云短信),短信支持主从服务商高可用。

安装方法

composer require mingyuanyun/yii2-imessage

配置

在配置文件中components中添加iMessage组件,以下是demo:

'iMessage' => [
    'class' => 'iMessage\Message',
    'config' => [
        'channels'=>[
            'mail' => [
                'username' => 'yunlianadxxxxxxx',
                'password' => 'uXXHLB7Zxxxxxx',
                'class' => 'Swift_SmtpTransport',// 选填
                'host' => 'smtp.exmail.qq.com',// 选填
                'port' => '465',// 选填
                'encryption' => 'ssl',// 选填
                'charset' => 'UTF-8',// 选填
                'from' => ['yunlianadmin@mingyuanyun.com' => '明源云链'],// 选填
            ],
            'qy-wx' => [
                'appId' => 'wxfe3aa6cxxxxxx',
                'appSecret' => '1X1z8GwVEy7TBxxxxxx',
                'agentId' => 1000050,
                'compatId' => '企业微信登录',// 选填
            ],
            'sms' => [// 公共组消息配置
                'merchantType'=>'publicSms',
                'host'=>'http://sms-test.myyscm.com',
                'account'=>'jgtest',
                'key'=>'xxxxxxx',
                'slave' => [
                    'merchantType' => 'aliyunSms',
                    'accessKeyId' => 'xxxx',
                    'accessSecret' => 'xxxx',
                ],
                'templateProvider' => '\services\SmsTemplateProvider' // 选填
            ],
            'app' => [// 根据实际用到的设备选择性填写
                'huawei' => [
                    'appPkgName' => '', // 包名
                    'clientId' => '', // 应用id
                    'clientSecret' => '' // 应用密钥
                ],
                'huawei-v2' => [
                    'appPkgName' => '', // 包名
                    'clientId' => '', // 应用id
                    'clientSecret' => '' // 应用密钥
                ],
                'meizu' => [
                    'appPkgName' => '', // 包名
                    'appId' => '', // 应用id
                    'appSecret' => '' // 应用密钥
                ],
                'xiaomi' => [
                    'appPkgName' => '', // 包名
                    'appSecret' => '' // 应用密钥
                ],
                'oppo' => [
                    'appPkgName' => '', // 包名
                    'appKey' => '', // 应用id
                    'masterSecret' => '' // 应用密钥
                ],
                'vivo' => [
                    'appPkgName' => '', // 包名
                    'appId' => '', // 应用id
                    'appKey' => '', // 应用key
                    'appSecret' => '' // 应用密钥
                ],
                'ios' => [
                    'isSandBox' => true, // 是否调试包
                    'certPath' => '', // pem格式推送证书本地绝对路径
                    'password' => '123', // 推送证书密码
                ],
                'ios-token' => [
                    'isSandBox' => true,
                    'teamId' => 'D4GSYVE6CN', // 开发者帐号teamId
                    'keyId' => '99BYW4U4SZ', // token认证keyId
                    'secretContent' => $iosCertContent, // 密钥内容,有值时忽略secretFile
                    'secretFile' => 'xxx.p8', // token认证密钥文件本地绝对路径
                    'bundleId' => 'com.mysoft.mdev' // 应用ID
                ]
            ]
        ],
        'eventHandler'=>'\services\MsgEventHandler', // 选填
    ]
]

以上sms配置部为公共组消息配置,下面是阿里云消息配置的demo:

'iMessage' => [
    'class' => 'iMessage\Message',
    'config' => [
        'channels'=>[
            .
            .
            .
            'sms' => [// 阿里云消息配置
                'merchantType'=>'aliyunSms',
                'accessKeyId'=>'xxxxxx',
                'accessSecret'=>'xxxxxx',
                'regionId'=>'xxxxxxx',
                'slave' => [
                    'merchantType' => 'publicSms',
                    'host'=>'http://sms-test.myyscm.com',
                    'account'=>'jgtest',
                    'key'=>'xxxxxxx',
                ],
                'templateProvider' => '\services\SmsTemplateProvider' // 选填
            ],
        ]
    ]
]

详细配置参数说明:

属性含义说明
channels.mail.class邮件类选填,默认为 Swift_SmtpTransport
channels.mail.host邮件host选填,默认为 'smtp.exmail.qq.com'
channels.mail.username邮件账号必填
channels.mail.password邮件密码必填
channels.mail.port邮件端口选填,默认为465
channels.mail.encryption邮件加密方式选填,默认为 ssl
channels.mail.charset邮件编码选填,默认为 UTF-8
channels.mail.from邮件来源选填
channels.qy-wx.appId企业微信appid必填
channels.qy-wx.appSecret企业微信密钥必须
channels.qy-wx.agentId企业微信应用id必须
channels.qy-wx.compatId企业微信应用名称兼容id选填
channels.sms.merchantType商户类型必须,publicSms 为公共组短信,aliyunSms 为阿里云短信
channels.sms.templateProvider短信模版数据,用于发送时根据code获取模版信息选填
channels.sms.slave短信备用服务商选填,主服务商发送失败会尝试从服务商(slave)进行发送
channels.sms.host公共组短信host商户类型为 publicSms 必填
channels.sms.account公共组短信账号商户类型为 publicSms 必填
channels.sms.key公共组短信密钥商户类型为 publicSms 必填
channels.sms.accessKeyId阿里云短信keyid商户类型 为aliyunSms 必填
channels.sms.accessSecret阿里云短信密钥商户类型为 aliyunSms 必填
channels.sms.regionId区域id商户类型为 aliyunSms 选填,默认为 cn-hangzhou
channels.appAPP消息配置根据用到的设备类型填写即可
eventHandler事件监听类选填

channels.qy-wx.compatId 配置说明:

如果项目之前已经应用了企业微信,并配置了应用名称参数,需要保证两边应用名称id(compatId)一致

channels.sms.templateProvider 配置说明:

由业务关联code为键,模版内容为内容体,可以直接以数组格式填入,也可以实现
\iMessage\interfaces\SmsTemplateProviderInterface 接口,以类的方式提供,推荐后种方式。

调用示例

1. 邮件消息

// 创建消息代理
$agent = \Yii::$app->iMessage->createClient();

// 注:详细参数说明请看README.md
// 视图模版消息
$mailMsg = new \iMessage\message\MailMessage();
$mailMsg->to = 'liuyx02@mingyuanyun.com'; // 发送对象邮件地址
$mailMsg->subject = '测试消息标题'; // 标题
$mailMsg->view = 'api-doc/create'; // 视图路径
$mailMsg->viewParams = ['account' => '张三', 'cn_name' => 'zhangs', 'code' => '123456']; // 视图参数
$mailMsg->cc = ['xx@qq.com', 'yy@qq.com']; // 复制接收者电子邮件地址
$mailMsg->attachments = ['./robots.txt','https://test-jgxl.oss-cn-shenzhen.aliyuncs.com/xxx/xxx.png']; // 附件(可选)
$agent->send($mailMsg);// 发送消息,直接返回true or false
$result = $agent->getLastResponse(); // 获取最后一次发送的结果

// 文本消息
$mailMsg = new \iMessage\message\MailMessage();
$mailMsg->to = 'liuyx02@mingyuanyun.com'; // 发送对象邮件地址
$mailMsg->subject = '测试消息标题'; // 标题
$mailMsg->textBody = '消息内容'; // 文本消息内容
$agent->send($mailMsg);// 发送消息,直接返回true or false
$result = $agent->getLastResponse(); // 获取最后一次发送的结果

// html消息
$mailMsg = new \iMessage\message\MailMessage();
$mailMsg->to = 'liuyx02@mingyuanyun.com'; // 发送对象邮件地址
$mailMsg->subject = '测试消息标题'; // 标题
$mailMsg->htmlBody = '<h1>消息内容</h1>'; // html消息内容
$agent->send($mailMsg);// 发送消息,直接返回true or false
$result = $agent->getLastResponse(); // 获取最后一次发送的结果

请求参数说明:

属性含义说明
to(邮件)发送对象邮件地址邮件消息必填,可传字符串或数组
subject(邮件)标题邮件消息必填
view(邮件)用于呈现消息正文的视图邮件消息选填
viewParams(邮件)消息参数邮件消息选填
cc(邮件)复制接收者电子邮件地址邮件消息选填
textBody(邮件)文本消息体邮件消息选填
htmlBody(邮件)html格式消息体邮件消息选填
attachments(邮件)附件附件地址选填
---

2. 企业微信消息

// 创建消息代理
$agent = \Yii::$app->iMessage->createClient();

// 注:详细参数说明请看README.md
// 简单文本消息
$qywxMsg = new \iMessage\message\QywxMessage();
$qywxMsg->type = 'text'; // 消息类型
$qywxMsg->to = 'liuyx02'; // 发送对象
$qywxMsg->content = '消息内容'; // 消息内容体
$agent->send($qywxMsg);// 发送消息,直接返回true or false
$result = $agent->getLastResponse(); // 获取最后一次发送的结果

// markdown文本消息
$qywxMsg = new \iMessage\message\QywxMessage();
$qywxMsg->type = 'markdown'; // 消息类型
$qywxMsg->to = 'liuyx02'; // 发送对象
$qywxMsg->content = '# 消息内容'; // 消息内容体
$agent->send($qywxMsg);// 发送消息,直接返回true or false
$result = $agent->getLastResponse(); // 获取最后一次发送的结果

// 卡片消息
$qywxMsg = new \iMessage\message\QywxMessage();
$qywxMsg->type = 'textcard'; // 消息类型
$qywxMsg->to = 'liuyx02'; // 发送对象
$qywxMsg->content = '消息内容'; // 消息内容体
$qywxMsg->subject = '消息标题'; // 消息标题
$qywxMsg->url = 'http://baidu.com'; // 详情链接
$qywxMsg->btntxt = '详情'; // 按钮文字
$agent->send($qywxMsg);// 发送消息,直接返回true or false
$result = $agent->getLastResponse(); // 获取最后一次发送的结果
return $result;

请求参数说明:

属性含义说明
to(企业微信)发送对象企业微信消息必填,可传字符串或数组
content(企业微信)内容体企业微信消息必填
type(企业微信)消息类型内容类型,默认text,可选text、markdown、textcard
subject(企业微信)标题内容类型为 textcard 时必填
url(企业微信)详情链接内容类型为 textcard 时必填
btntxt(企业微信)按钮文字内容类型为 textcard 时必填

3. 短信(公共组消息中心)消息

// 创建消息代理
$agent = \Yii::$app->iMessage->createClient();

// 注:详细参数说明请看README.md
// 当应用配置短信消息渠道商户类型( merchantType )设置为 `publicSms`时,走公共组消息中心通道

// 1.模版消息
$smsMsg = new \iMessage\message\SmsMessage();
$smsMsg->contentType = 'template'; // 内容类型
$smsMsg->to = '15521155161'; // 发送对象
$smsMsg->templateId = '39edc15f-7b16-1536-c7f7-a40dc7bb6c0a'; // 模版id
$smsMsg->templateParam = ['432532']; // 模版参数
$smsMsg->options = ['tenantCode' => '34343', 'appCode' => '3444']; // 可选参数,默认发送到消息中心
$agent->send($smsMsg);// 发送消息,直接返回true or false
$result = $agent->getLastResponse(); // 获取最后一次发送的结果

// 2.自定义消息
$smsMsg = new \iMessage\message\SmsMessage();
$smsMsg->contentType = 'custom'; // 内容类型
$smsMsg->to = '15521155161'; // 发送对象
$smsMsg->templateId = '39ee5289-caf2-4b38-1c70-d59b3135f382'; // 模版id
$smsMsg->content = '首易自定义内容'; // 自定义消息内容
$agent->send($smsMsg);// 发送消息,直接返回true or false
$result = $agent->getLastResponse(); // 获取最后一次发送的结果

// 3.语音消息
$smsMsg = new \iMessage\message\SmsMessage();
$smsMsg->contentType = 'voice'; // 内容类型
$smsMsg->to = '15521155161'; // 发送对象
$smsMsg->templateId = '39edc27b-87d4-50aa-0936-be587038e9a4'; // 模版id
$smsMsg->voiceTemplateCode = '432532'; // 语音验证码
$agent->send($smsMsg);// 发送消息,直接返回true or false
$result = $agent->getLastResponse(); // 获取最后一次发送的结果

// 4.可通过在应用配置下配置 channels.sms.templateProvider 参数的方式,从配置文件获取配置,详情请看 \demo\DemoSmsTemplateProvider.php 文件,以下时调用demo
$smsMsg = new \iMessage\message\SmsMessage();
$smsMsg->code = 'yf-AppCheckRoom-ForgetPassword'; // 传入code后可以不写 templateId 及 signName 字段
$smsMsg->contentType = 'template'; // 内容类型
$smsMsg->to = '15521155161'; // 发送对象
$smsMsg->templateParam = ['432532']; // 模版参数
$smsMsg->options = ['code' => '432532', 'product' => 'liuyx02']; // 可选参数,默认发送到消息中心
$agent->send($smsMsg);// 发送消息,直接返回true or false
$result = $agent->getLastResponse(); // 获取最后一次发送的结果


// 5.应用配置加了slave的配置后如果主 master 短信服务发送失败,会尝试从 slave 短信服务发送。
// 短信消息还支持强制选定某个短信服务商进行发送
$agent = \Yii::$app->iMessage->createClient();
$smsMsg = new \iMessage\message\SmsMessage();

// 填master只发主短信服务商;填slave只发从短信服务商;默认为auto,主服务商发送失败尝试从服务商发送
$smsMsg->selected = 'slave';

$smsMsg->code = 'yf-AppCheckRoom-ForgetPassword'; // 传入code后可以不写 templateId 及 signName 字段
$smsMsg->contentType = 'template'; // 内容类型
$smsMsg->to = '15521155161'; // 发送对象
$smsMsg->options = ['tenantCode' => '34343', 'appCode' => '3444']; // 可选参数,默认发送到消息中心
$agent->send($smsMsg);// 发送消息,直接返回true or false
$result = $agent->getLastResponse(); // 获取最后一次发送的结果

请求参数说明:

属性含义说明
to(短信)发送对象手机号码短信消息必填,可传字符串或数组
contentType(短信)内容类型可选 custom(自定义消息)、template(模版消息)、voice(语音消息);默认为 template(模版消息)
templateId(短信)消息模版id必填
templateParam(短信)消息模版参数内容类型为 template 时必填
code(短信)模版数据 templateProvider 的键名选填
voiceTemplateCode(短信)语音验证码内容类型为 voice 时必填
content(短信)短信内容体内容类型为 custom 时必填
options(短信)默认发送到消息中心选填

4. 短信(阿里云消息服务)消息

// 创建消息代理
$agent = \Yii::$app->iMessage->createClient();

// 注:详细参数说明请看README.md
// 当应用配置短信消息渠道商户类型( merchantType )设置为 `aliyunSms`时,走阿里云消息服务通道

// 一次请求中向多个不同的手机号码发送 同样内容 的短信
$smsMsg = new \iMessage\message\SmsMessage();
$smsMsg->to = '155211551xx'; // 发送对象
$smsMsg->templateId = 'SMS_66835xxxx'; // 模版id
$smsMsg->templateParam = ['code' => '432532', 'product' => '云链erp']; // 模版参数
$smsMsg->signName = '测试签名'; // 短信签名名称,当商户类型为aliyunSms是必填
$agent->send($smsMsg);// 发送消息,直接返回true or false
$result = $agent->getLastResponse(); // 获取最后一次发送的结果

// 一次请求中分别向多个不同的手机号码发送不同签名的短信。
$smsMsg = new \iMessage\message\SmsMessage();
$smsMsg->to = ['15521155xx', '135328650xx']; // 发送对象
$smsMsg->templateId = 'SMS_66835xxxx'; // 模版id
$smsMsg->templateParam = [['code' => '432532', 'product' => '云链erp'], ['code' => '432322', 'product' => '云链erp']]; // 模版参数
$smsMsg->signName = ['测试签名', '测试签名2']; // 短信签名名称,当商户类型为aliyunSms是必填
$agent->send($smsMsg);// 发送消息,直接返回true or false
$result = $agent->getLastResponse(); // 获取最后一次发送的结果

请求参数说明:

属性含义说明
to(短信)发送对象手机号码短信消息必填,可传字符串或数组
templateId(短信)消息模版id必填
templateParam(短信)消息模版参数必填,数组格式
signName(短信)短信签名名称当商户类型为aliyunSms是必填,可填字符串或数组

5. APP 消息

app消息调用了 yunchuang/push 扩展来发送app消息。

// 创建消息代理
$agent = \Yii::$app->iMessage->createClient();

$appMsg = new \iMessage\message\AppMessage();
$appMsg->gateway = 'xiaomi'; // 通道类型
$appMsg->to = 'lqMU8xjpFwgeDQzgFOeEhq/DXiDaHCKxqvDyZKYHUtUmOS9VR1SOJ6c42s190GyZ'; // 发送对象
$appMsg->businessId = 12345678; // 业务ID
$appMsg->title = 'test title'; // 标题
$appMsg->subTitle = 'subTitle'; // 内容
$appMsg->content = 'test content'; // 内容
$appMsg->extra = ['key1' => 'v1', 'key2' => 2]; // 自定义数据
$appMsg->options = ['token' => 'CFx88jTVr6adjsh6eVOLvhtqnDlhLxb7CljykbXxu7vLsnexatUJZM1lqXHPzfnurD0gknQnIu7SRvWhAPx/zQ=='];
$agent->send($appMsg);// 发送消息,直接返回true or false
$result = $agent->getLastResponse(); // 获取最后一次发送的结果

请求参数说明:

属性含义说明
to目标设备id必填,可传可传字符串或数组
gateway网关渠道必填,可填huawei(华为),huawei-v2(华为新版),xiaomi(小米),meizu(魅族),oppo(Oppo),vivo(Vivo),ios(苹果-基于推送证书认证),ios-token(苹果-基于token认证)及自定义网关名
businessId业务ID,相同业务ID只推送一次必填
title标题必填
subTitle副标题选填
content内容必填
badge角标选填
extra服务端传给APP的自定义数据,数组格式选填,建议转换为json字符串后长度不超过1024字节
callback送达回执地址选填, 供推送厂商调用,最大128个字节,具体请查阅各厂商文档。华为仅支持在应用管理中心配置;魅族需在管理后台注册回执地址,每次推送时也需指定回执地址;苹果ios-token通道由SDK调用回执
callbackParam自定义回执参数选填
notifyId聚合标签选填,同标签消息在通知栏只显示一条。小米通道支持,字母、数字组合不超过8位
gatewayOptions厂商扩展参数选填
options附加信息选填

gatewayOptions 厂商扩展参数说明:

考虑到各厂商均有自己特有的参数,故提供此扩展参数来提供支持。如果扩展参数与通用参数有冲突,则取扩展参数中值。 参数类型为以厂商通道为键名的数组,格式如下:

[
    "huawei": 与华为消息格式一致,下同,
    "xiaomi": xxx,
    "vivo": xxx,
    "oppo": xxx,
    "meizu": xxx,
    "ios-token": xxx
]

示例:

$appMsg->gatewayOptions = [
    'xiaomi' => [
        'extra.notify_foreground' => '1',
    ],
    'huawei' => [
        'hps' => [
            'ext' => [
                'badgeAddNum' => '1',
                'badgeClass' => 'com.mysoft.core.activity.LauncherActivity',
            ]
        ]
    ]
];

options 附加信息说明:

参数类型说明
tokenstring认证token
pushMingYuanYun\Push\Support\ApnsPushiOS证书推送实例,考虑到文件I/O问题,故此设计

5. 更多功能

// 1.支持绑定事件
// 在应用配置直接注入到 `eventHandler` 字段即可,然后继承 \iMessage\base\MsgEventHandlerBase 类进行
//个性化操作,可参考 demo 目录下 MsgEventHandler.php 文件。

// 2. 短信可通过在应用配置下配置 channels.sms.templateProvider 参数的方式,从配置文件获取配置,详情请看 \demo\DemoSmsTemplateProvider.php 文件,以下时调用demo
$agent = \Yii::$app->iMessage->createClient();
$smsMsg = new \iMessage\message\SmsMessage();
$smsMsg->contentType = 'template'; // 内容类型
$smsMsg->to = '15521155161'; // 发送对象
$smsMsg->code = 'yf-AppCheckRoom-ForgetPassword'; // 传入code后可以不写 templateId 及 signName 字段
$smsMsg->options = ['tenantCode' => '34343', 'appCode' => '3444']; // 可选参数,默认发送到消息中心
$agent->send($smsMsg); // 发送消息,直接返回true or false
$result = $agent->getLastResponse(); // 获取最后一次发送的结果

//  3. 短信高可用(支持master-slave),也支持强制选定某个短信服务商进行发送
//  可通过在应用配置下配置 channels.sms.slave 配置备用短信服务商
$agent = \Yii::$app->iMessage->createClient();
$smsMsg = new \iMessage\message\SmsMessage();

// 填master只发主短信服务商;填slave只发从短信服务商;默认为auto,主服务商发送失败尝试从服务商发送
$smsMsg->selected = 'slave';

$smsMsg->code = 'yf-AppCheckRoom-ForgetPassword'; // 传入code后可以不写 templateId 及 signName 字段
$smsMsg->contentType = 'template'; // 内容类型
$smsMsg->to = '15521155161'; // 发送对象
$smsMsg->options = ['tenantCode' => '34343', 'appCode' => '3444']; // 可选参数,默认发送到消息中心
$agent->send($smsMsg);// 发送消息,直接返回true or false
$result = $agent->getLastResponse(); // 获取最后一次发送的结果

返回结果

获取返回结果:

// 发送消息后,通过 getLastResponse 方法获取最后一次发送返回结果
$agent = \Yii::$app->iMessage->createClient();
$agent->send($smsMsg);
$result = $agent->getLastResponse(); // 获取返回结果

默认返回结果示例:

{
    "msg_type": "sms",
    "errcode": 0,
    "errmsg": "ok",
    "original": {
        "code": 0,
        "data": "39f634f1-cc46-baa3-f334-1203a2f1e4cd"
    }
}

短信除了以上配置还会有商户类型字段返回,且如果配置了slave配置且调用了slave发送短信slave的结果会覆盖master的结果(除了original字段的数据不覆盖,而是增加slave的结果到original的slave字段),以下为结果示例:

{
    "msg_type": "sms",
    "errcode": -1,
    "errmsg": "商户无响应",
    "original": {
        "code": -1,
        "data": "39f65e46-c447-69af-13ab-87f26b221c8a",
        "slave": {
            "Message": "error",
            "RequestId": "F007FD52-9AD7-4195-BC9D-E6609E86E9BE",
            "BizId": "860507994709634306^0",
            "Code": "error"
        },
    },
    "merchantType": "publicsms"
}

返回结果参数说明:

属性参数类型含义
msg_typestring消息类型
errcodeint错误码,0表示发送成功
errmsgstring错误信息
originalarray消息原始返回结果
original.slavearray备选商户消息原始返回结果
merchantTypestring短信商户类型

更多请查看 Demo 。