前言
目前微信使用人数特别多,假如你想通过微信给你的设备推送消息,可以对接一下微信硬件平台。
微信用户绑定设备后,可以通过微信给自己设备发送文件(充当文件助手)或者链接(充当分享好文快捷入口)等功能;
一、对接概览
对接效果:
本质: 微信和我们设备的sn进行绑定,然后下推一下类似IOT指令,三方服务商接收这个类似IOT指令,然后在设备上完成相应的功能。
核心的两个问题:
1、文件会发给谁?
1、微信用户绑定设备后将会有关系:微信用户唯一id(openid) -
三方厂商设备唯一id(sn)
2、厂商用户使用设备会有绑定关系:三方厂商设备唯一id(sn)- 用户唯一id
有了上面两个绑定关系,我们就能通过设备的sn进行转换,实现微信用户到我们厂商用户的映射
2、文件是怎么发的?
文件是微信先暂存了一次,然后通过HTTP回调的方式通知三方业务,三方业务做相应的消息存储和展示。
职责:
- 微信:提供
微信用户和三方设备绑定和推送文件消息的功能 - 厂商:完成用户设备绑定对接,并对接收到的消息进行处理
二、对接前准备
微信硬件平台上配置的参数:
名词解析:
- appId、secret:
小程序注册后能获取到这个的,用途:
- 需要通过这两个值来获取调用接口的凭证;
- 需要通过appid跟微信硬件平台绑定,
绑定后,才能通过**微信**扫码打开绑定页;- 回调地址:在微信硬件平台上面配置,通过微信给设备推消息的时候,微信会将信息通过回调调用这个回调地址(包括绑定、解绑、消息推送等);
- token:微信硬件平台自动生成的,通过他跟回调的参数进行拼接,对数据的完整性进行校验,判断这个调用是否来自于微信;
- procutID:需要在微信硬件平台上面添加,用于设备绑定。
三、微信硬件平台
名词解释:
- product_id: 微信硬件平台对具体某个厂商制造的某款设备产品的标识
- SN: 厂商后台为设备生成的可对外的全局唯一设备标识, product_id范围内唯一
- ilink_im_sdk_id: 设备在微信硬件平台的唯一标识,即微信硬件ID
- ilink_device_ticket: 设备绑定临时身份凭证,五分钟有效期
- ilink_iot_user_id: 设备绑定者在微信硬件平台的身份标识
限制:
- 一个设备只能跟一个用户绑定,即:一个用户可以拥有多个设备,但是一个设备不能属于多个用户
- 文档中有限制文件在30M之内,但是试了一下,超过30M也是可以上传。
四、对接方案
时序图如下:
原理就到这里,后面是一些接口的调用,不感兴趣可以不看
1、获取access_token
接口说明:
通过微信开放平台调用微信内部接口时,需要使用appid与secret换取调用凭证access_token
请求地址:
GET https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=xxx&secret=xxx
请求参数:
| 属性 | 类型 | 必填 | 说明 |
|---|---|---|---|
| grant_type | string | 是 | 填写 client_credential |
| appid | string | 是 | 小程序/APP唯一凭证,即 AppID,可在「微信公众平台 - 设置 - 开发 设置」页中获得。(需要已经成为开发者,且帐号没有异常状态) |
| secret | string | 是 | 小程序/APP唯一凭证密钥,即 AppSecret,获取方式同 appid |
返回值:
| 属性名 | 类型 | 说明 |
|---|---|---|
| access_token | string | 获取到的凭证 |
| expires_in | number | 凭证有效时间,单位:秒。目前是7200秒之内的值。 |
| errcode | number | 错误码, 0为成功 |
| errmsg | string | 错误信息 |
2、设备SN注册
接口说明:
每一个设备绑定前,需要到微信硬件平台注册信息
请求地址:
POST https://api.weixin.qq.com/ilink/api/cloud_register_device?access_token=xxx
url上请求参数:
| 属性 | 类型 | 必填 | 说明 |
|---|---|---|---|
| access_token | string | 是 | 获取到的凭证,来自上面接口获取access_token接口 |
请求参数:
{
"product_id": 上面申请的procut_id,
"iot_device_list": [
{
"sn": "48210927315672" //设备sn
},
{
"sn": "48210927315673" // 设备sn
}
]
}
| 属性 | 类型 | 必填 | 说明 |
|---|---|---|---|
| product_id | number | 是 | 设备产品唯一标识 |
| sn | string | 是 | 厂商分配的设备唯一序列号 |
- 单次接口调用,sn个数上线是100,超限将返回错误
- 产品上线前, 只能注册20个sn
返回值:
{
"iot_device_list": [{
"sn": "48210927315672",
"ilink_im_sdk_id": "AAYAABPamWLEhIPAAdkg-oTucvVKrSVfJAxxxB5Uw@ilink.im.sdk" // 这个就是在微信上注册后的硬件id
}, {
"sn": "48210927315673",
"ilink_im_sdk_id": "AAYAABPamWI1HBAQAdkg-pDbVJ0xLQXTuxxxyUAwk@ilink.im.sdk"
}],
"errcode": 0,
"errmsg": "",
"err_device_list": []
}
3、获取二维码接口
接口说明:
厂商后台到微信硬件平台拉取设备的绑定二维码,用户可使用微信扫描二维码绑定该设备。
请求地址:
POST https://api.weixin.qq.com/ilink/api/mmiot/get_device_qrcode?access_token=xxx
url上请求参数:
| 属性 | 类型 | 必填 | 说明 |
|---|---|---|---|
| access_token | string | 是 | 获取到的凭证,来自上面接口获取access_token接口 |
body请求参数:
{
"ilink_im_sdk_id": "xxx@ilink.im.sdk"
}
| 属性 | 类型 | 必填 | 说明 |
|---|---|---|---|
| ilink_im_sdk_id | string | 是 | 微信硬件平台分配的设备唯一标识,来自上面接口设备SN注册接口,传递这个值,扫完这个码,就是打开这个设备的绑定页(小程序) |
返回值:
{
"errcode": 0,
"errmsg": "xxx",
"payload": {
"device_qrcode_url": "https://mmae.qpic.cn/xxxxxxxx",
"expire_seconds": 300
}
}
| 属性 | 类型 | 说明 |
|---|---|---|
| errcode | number | 返回码,0为成功 |
| errmsg | string | 错误信息 |
| device_qrcode_url | string | 二维码图片链接 |
| expire_seconds | number | 二维码失效时间,以秒为单位 |
下载打开这个device_qrcode_url是一个二维码,打开这个二维码,会打开我们绑定上面绑定的二维码,界面如下:
可绑定,点击绑定即可完成绑定:
设备已经被绑定:
5、回调接口
回调的地址:
POST http://$callback_url?signature=xxx&timestamp=xxx&nonce=xxx
- callback_url为我们在微信硬件平台配置的接口
- 回调后我们需要对签名进行校验,判断来源的合法性,这里需要上面在硬件平台配置的签名材料token
签名规则:
- 将token、timestamp、nonce三个参数进行字典序排序
- 将三个参数字符串拼接成一个字符串进行sha1加密
- 开发者获得加密后的字符串可与signature对比,标识该请求来源于微信
例子:
token = 8GhcGcYyz70012
nonce=1410310936
timestamp=1636537701
signature = sha1(141031093616365377018GhcGcYyz70012) = 9d8ed9a3e985d2255807680ce8d450bd06fbde14
调用场景:
主要包括以下几个内容
- 设备绑定: topic : /ilink/sys/wechat_iot/ilink_im_sdk_id/bind
- 设备解绑:topic:/ilink/sys/wechat_iot/ilink_im_sdk_id/unbind
- (标准物联模型)设备发送消息: topic:/ilink/sys/wechat_iot/ ilink_im_sdk_id/invoke_device_service
主要通过topic字段去区分目前是哪种类型的接口调用,然后将接口中的product_id,和ilink_im_sdk_id截取出来,当成我们需要的参数,用于后续的匹配
- 设备绑定:通过product_id和ilink_im_sdk_id 去完成相应设备的绑定
- 设备解绑:通过product_id和ilink_im_sdk_id 去解除相应设备的绑定
- 设备发送消息:将设备的消息保存,下载响应文件,便于后续的查询
5.1 微信绑定回调
接口说明:
当小程序管理端绑定设备时,微信硬件平台回调厂商后台进行绑定. 厂商可以在绑定回调时进行自己的绑定管理和权限校验.
请注意该接口的可用性, 如果回调失败, 绑定流程也将失败
请求参数:
{
"topic": "/ilink/sys/wechat_iot/$product_id/$ilink_im_sdk_id/bind",
"payload": {
"binder_type": 1,
"binder_info":{
"ilink_iot_user_id": "xxx"
},
"device_info":{
"ilink_im_sdk_id": "xxx"
},
"ilink_device_ticket": "xxx"
}
}
| 属性 | 类型 | 必填 | 说明 |
|---|---|---|---|
| binder_type | int | 是 | 绑定者类型. 0=普通绑定者, 1=管理员 |
| ilink_iot_user_id | string | 是 | 微信硬件平台分配的绑定者身份标识,这里就是随机生成的一个用户id |
| ilink_im_sdk_id | string | 是 | 微信硬件平台分配的设备唯一标识 |
| ilink_device_ticket | string | 否 | 绑定ticket, 厂商在快速对接场景下可以通过该ticket关联微信用户与自有用户. 其他绑定场景不一定有该字段, 请勿使用 |
返回值:
{
"errcode":0,
"errmsg":"xxx",
}
5.2 解绑回调
接口说明:
当用户在微信硬件页解绑设备(见下图,无需开发)或小程序管理端解绑设备(这个是需要自己开发页面的)时,厂商可以在解绑回调时进行自己的绑定管理和权限校验.
请注意该接口的可用性, 如果回调失败, 解绑流程也将失败.
1、微信硬件也解绑设备(无需开发)
打开路径:我的 -> 设备 -> 设备 -> 在要解绑的设备右滑 -> 删除
2、小程序管理端解绑设备(需要开发)
如何跳转到解绑设备页
页面路径:/pages/delete-devices/delete-devices
传递参数:{"sdkIdList": ["xxx1", "xxx2", "xxx3"]}, 要解绑的设备sdkId列表(前面的ilink_im_sdk_id,微信硬件平台的设备唯一标示)
回跳参数也放在extraData里:{from: 'wx-iot', "successList": ["xxx1", "xxx2"], "failList": ["xxx3"]}, 里面放的是sdkid列表,表明哪些成功,哪些失败
5.3 消息推送回调
绑定完设备后即可获得长按微信消息->打开->发送到设备的能力
注意:目前仅支持30M以下文件的发送,虽然超过30M也成功了
下面是微信发送消息后,推送的对象
class WxStdSendMsg{
WxStdSendFileResp WxStdSendFile( WxStdSendFileReq req );
WxStdSendPoiResp WxStdSendPoi( WxStdSendPoiReq req );
WxStdSendMusicResp WxStdSendMusic (WxStdSendMusicReq req);
WxStdSendUrlResp WxStdSendUrl (WxStdSendUrlReq req);
}
class WxStdSendFileReq{
@Spec(name="文件类型")
String type; //如"pdf","docx"
@Spec(name="文件名")
String name; //如"文件.pdf"
@Spec(name="下载链接")
String download_url; //下载的内容经过加密, 需要厂商解密
@Spec(name="加密算法")
String encrypt_algo; //目前仅支持AEAD_AES_256_GCM
@Spec(name="秘钥base64")
String key_base64;
@Spec(name="iv base64")
String iv_base64; //解密的初始向量
@Spec(name="tag base64")
String tag_base64;
}
class WxStdSendFileResp{
}
class WxStdSendPoiReq{
@Spec(name="纬度")
double latitude ;
@Spec(name="经度")
double longitude ;
double scale;
@Spec(name="地点标签")
String label;// xx省xx市xx区xx路xx号
@Spec(name="地点名称")
String name;// xxx动物园
}
class WxStdSendPoiResp{
}
class WxStdSendMusicReq {
@Spec(name="标题")
String title; // 微信内的音乐卡片标题,一般是歌曲名
@Spec(name="描述")
String description; // 微信内的音乐卡片描述,一般是歌手名
@Spec(name="网页url")
String url; // 音频网页的URL地址
}
class WxStdSendMusicResp{
}
class WxStdSendUrlReq {
@Spec(name="标题")
String title; // 微信内的链接卡片标题
@Spec(name="描述")
String description; // 微信内的链接卡片描述
@Spec(name="链接")
String url;
}
class WxStdSendUrlResp {
}
卡片链接和音乐,将会是一个链接的提供,理论上不会过期;
如果是文件,如txt、pdf、xlxs 则会返回文件下载的链接,官网说是1天后过期。
出于安全性考虑,
download_url下载的内容经过了加密, 算法为AEAD_AES_256_GCM. 厂家需要通过请求中的key_base64,iv,tag_base64等作为参数, 将下载内容解密得到明文. 目前大部分编程语言都支持了AEAD_AES_256_GCM算法 ,解密见:解密文件,AEAD_AES_256_GCM
样例:
发送文件:
{
"payload": {
"ilink_im_sdk_id": "AAYAABxxxaAdkg-hgrHdnGvV_nnYrHpl3ux4s@ilink.im.sdk",
"service_identifier": "WxStdSendMsg.WxStdSendFile",
"params": {
"type": "xlsx",
"download_url": "https://mmae.qpic.cn/204/20303/stodownload?filekey=30340201010420301e020200cc040253480410183c43debb38c2199ce6404583673bac0202200c040d00000004627466730000000131&hy=SH&storeid=32303232303432313134343432343030306630303366353063663362343765653336623030623030303030306363&bizid=1023",
"iv_base64": "9Z0x8oIcjzOG2Z7w",
"encrypt_algo": "AEAD_AES_256_GCM",
"name": "2222222.xlsx",
"tag_base64": "mGuamsbaxv2ajkcMqFa4cw==",
"key_base64": "yt8b42s6rTknMWs1KmvSB4cgY//TnX3SX8Z8NdhGIRM="
},
"ilink_trace_id": "91675CB035B0B684B237B67423103B44"
},
"topic": "/ilink/sys/wechat_iot/3683/AAYAABxxxaAdkg-hgrHdnGvV_nnYrHpl3ux4s@ilink.im.sdk/invoke_device_service"
}
发送QQ音乐:
{
"payload": {
"ilink_im_sdk_id": "AAYAABPxxxxKRji8aAdkg-hgrHdnGvV_nnYrHpl3ux4s@ilink.im.sdk",
"service_identifier": "WxStdSendMsg.WxStdSendUrl",
"params": {
"url": "https://i.y.qq.com/v8/playsong.html?hosteuin=oKnz7ioqoKnzNn**&sharefrom=&from_id=0&from_idtype=0&from_name=&songid=9079096&songmid=&type=0&platform=(10rpl)&appsongtype=(11rpl)&_wv=1&source=qq&appshare=iphone&media_mid=003IIWWC1oJ239&ADTAG=wxfshare",
"description": "张卫健",
"title": "把酒狂歌"
},
"ilink_trace_id": "1C69F0475F0377FF01D1DF919A6049DE"
},
"topic": "/ilink/sys/wechat_iot/3683/AAYAABPxxxxKRji8aAdkg-hgrHdnGvV_nnYrHpl3ux4s@ilink.im.sdk/invoke_device_service"
}
标准物模型参数格式
一个标准物模型的属性,服务或事件名, 有可能和自定义物模型或其他标准物模型重复. 因此在物模管理中的设置设备属性, 调用设备服务, 上报设备属性 等接口传参时会带一个前缀, 具体格式如下:
| 参数名 | 参数格式 | 举例 | |
|---|---|---|---|
| 属性 | property_identifier | {标准物模型}.{属性名} | WxStdSwitch.switch_on |
| 服务 | service_identifier | {标准物模型}.{服务名} | WxStdSendFile.WxStdSendFile |
| 事件 | event_identifier | {标准物模型}.{事件名} | WxStdHealthDevice.SportsEvent |
到这里微信已经将消息推送给我们了,我们结合自己的业务需求,对消息进行保存&展示。
结语
感谢您的阅读,希望能有帮助~
附录:
微信官方对接文档: iot.weixin.qq.com/doc?page=5-…
小程序内完成绑定/解绑的流程 : juejin.cn/post/709192…