让微信能给你设备发送文件消息-微信硬件平台(1)

背景

此篇文章你能获得:了解如何通过微信给自己设备发送文件(充当文件助手)或者链接(充当分享好文快捷入口)等功能;

业务情况

随着用户对 学习机(自研的设备) 不断使用,我们在埋点数据各核心功能使用统计中发现微信的使用率稳居第一,据调研用户主要使用微信上网课、接收文件等。

目标 手机给我们自己的设备传输文件

这里有很多的实现方案
方案1:
自己开发一个文件传输助手,用户可以实现互传,但是手机和设备都装一下文件助手 —— 但是这种方案有些蠢,开发这个文件传输助手还不如我直接在设备上装一个微信呢. 这种方案就不讲了
方案2:
从上面看到用户目前还是比较喜欢通过微信传输文件的习惯的,那可以使用微信开放的接口,通过微信账号跟我们你的设备绑定,然后就可以通过微信给我们的设备推送消息了。
下面我们看看通过微信推送的文件的方案。

一、对接概览

微信硬件平台:https://iot.weixin.qq.com/
对接效果:

本质: 微信和我们设备的sn进行绑定,然后下推一下类似IOT指令,三方服务商接受这个类似IOT指令,然后在设备上完成相应的功能。

二、对接前准备

image.png
微信硬件平台上配置的参数:
image.png 参数解析:

  • appId、secret:小程序注册后给的,需要通过这两个值来获取调用接口的凭证; 还需要通过appid跟微信硬件平台绑定;
  • 回调地址:在微信硬件平台上面配置,通过微信给设备推消息的时候,微信会将信息通过回调调用这个回调地址(包括绑定、解绑、消息推送等);
  • token:微信硬件平台自动生成的,通过他跟回调的参数进行拼接,对数据的完整性进行校验,判断这个调用是否来自于微信;
  • procutID:需要在微信硬件平台上面添加,用于设备绑定。

注意:

要正式投入使用需要在微信硬件平台上面申请上线

三、接入方案

整体流程:
image.png
解析:
1、微信推送消息
可以推动文件(pdf、word、txt等)、图片、链接(微信公众号文章,三方分享到微信的文章)、音乐(QQ音乐、网易云音乐等,实际上也是个链接)
2、存储文件
会先将消息存储和文件先存到云上(文件、图片url的下载有效期是1天,链接和音乐理论上是永久有效)
3、消息通知
通过消息回调的方式,回调到你在微信硬件平台,会将消息推送给你,无论是图片、文件、音乐、链接都是统一成链接给你
4、转存文件(可选)
假如是文件的话,文件是有失效时间的,假如文件转存下来,防止丢失
ps:文件都是加过密的,需要解密,加密算法为AEAD_AES_256_GC,解密见:解密文件,AEAD_AES_256_GCM
5、消息下发 可以以你需要的形式将消息发送给用户

  • 可以存到库中,用户通过http主动拉去数据,下载用户自主选择下载
  • 可以通过iot通知客户端,客户端主动下载

四、微信硬件平台

名词解释:

  • product_id: 微信硬件平台对具体某个厂商制造的某款设备产品的标识
  • SN: 厂商后台为设备生成的可对外的全局唯一设备标识, product_id范围内唯一
  • ilink_im_sdk_id: 设备在微信硬件平台的唯一标识,即微信硬件ID
  • ilink_device_ticket: 设备绑定临时身份凭证,五分钟有效期
  • ilink_iot_user_id: 设备绑定者在微信硬件平台的身份标识

限制:

  • 一个设备只能跟一个用户绑定,即:一个用户可以拥有多个设备,但是一个设备不能属于多个用户
  • 文档中有限制文件在30M之内,但是试了一下,超过30M也是可以上传。

五、接口概览

源文件(可用starUML打开):发送消息.mdj

image.png


下面部分主要是一些接口概览,如不是实际对接可以不看

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

请求参数:

{
    "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-oTucvVKrSVfJAZsDEPB5Uw@ilink.im.sdk"  // 这个就是在微信上注册后的硬件id
    }, {
        "sn": "48210927315673",
        "ilink_im_sdk_id": "AAYAABPamWI1HBAQAdkg-pDbVJ0xLQXTuee784yUAwk@ilink.im.sdk"
    }],
    "errcode": 0,
    "errmsg": "",
    "err_device_list": []
}

3、获取绑定设备凭证

接口说明:

设备绑定时,厂商后台到微信硬件平台拉取该台设备的绑定凭证,传递给小程序端

请求地址:

POST  https://api.weixin.qq.com/ilink/api/get_device_ticket?access_token=xxx

请求参数:

{
    "ilink_im_sdk_id": "123@ilink.im.sdk",
    "user_openid":"xxx"
}
属性类型必填说明
ilink_im_sdk_id string 微信硬件平台分配的设备唯一标识
user_openid string 绑定设备用户的openid,**选填,填了后将在真正绑定时限制用户只能为所填openid对应用户,假如想限制谁可以绑定设备防止错绑可以加上这个**

返回值:

{
    "errcode":0,
    "errmsg":"xxx",
    "ilink_device_ticket":"xxx" //ticket
}
属性类型说明
errcode number 返回码,0为成功
errmsg string 错误信息
ilink_device_ticket string 微信硬件平台设备绑定凭证

4、绑定流程

小程序拉起绑定/解绑页

跳转参数都放在 extraData(json 对象)里

  • 跳转绑定页

  • 页面路径:/pages/discover-new/discover-new

* 传递参数:{"from": "wxprint", "ticket": "xxxxx", "openid": "xxxx"}, from--添加设备标识符, ticket--从ilink后台获取的绑定凭证, openid--用户openid(可选)

绑定成功之后,在微信 -> 设置 -> 设备中出现如下的内容 image.png 上面是我自己添加的三个设备,右滑即可对设备进行改名或者直接解绑设备

在微信 -> 设置 -> 设备 中能看到设备即可在聊天框中长按给设备发消息了

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/productid/ilink_im_sdk_id/bind
  • 设备解绑:topic:/ilink/sys/wechat_iot/productid/ilink_im_sdk_id/unbind
  • (标准物联模型)设备发送消息: topic:/ilink/sys/wechat_iot/ productid/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 微信硬件平台分配的绑定者身份标识, 上一步生成ticket有传用户openid,就是用户openid;上一步生成ticket无传用户openid,这里就是随机生成的一个用户id
ilink_im_sdk_id string 微信硬件平台分配的设备唯一标识
ilink_device_ticket string 绑定ticket, 厂商在快速对接场景下可以通过该ticket关联微信用户与自有用户. 其他绑定场景不一定有该字段, 请勿使用

返回值:


{
    "errcode":0,
    "errmsg":"xxx",
}

5.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以下文件的发送

下面是发送消息后,推动的对象

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": "AAYAABPamWKRji8aAdkg-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/AAYAABPamWKRji8aAdkg-hgrHdnGvV_nnYrHpl3ux4s@ilink.im.sdk/invoke_device_service"
}

发送QQ音乐:

{
    "payload": {
        "ilink_im_sdk_id": "AAYAABPamWKRji8aAdkg-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/AAYAABPamWKRji8aAdkg-hgrHdnGvV_nnYrHpl3ux4s@ilink.im.sdk/invoke_device_service"
}

标准物模型参数格式

一个标准物模型的属性,服务或事件名, 有可能和自定义物模型或其他标准物模型重复. 因此在物模管理中的设置设备属性调用设备服务上报设备属性 等接口传参时会带一个前缀, 具体格式如下:

 参数名参数格式举例
属性 property_identifier {标准物模型}.{属性名} WxStdSwitch.switch_on
服务 service_identifier {标准物模型}.{服务名} WxStdSendFile.WxStdSendFile
事件 event_identifier {标准物模型}.{事件名} WxStdHealthDevice.SportsEvent

6.解绑

image.png

跳转页面说明

页面路径:/pages/delete-devices/delete-devices

传递参数:{"sdkIdList": ["xxx1", "xxx2", "xxx3"]}, 要解绑的设备sdkId列表

回跳参数也放在extraData里:{from: 'wx-iot', "successList": ["xxx1", "xxx2"], "failList": ["xxx3"]}, 里面放的是sdkid列表,表明哪些成功,哪些失败

设备管理页跳转厂商小程序控制面板

微信设备页中,点击设备可支持跳转至厂商小程序中的设备控制页面,厂商需要在产品注册时选择小程序控制面板,并提供:appid 与 page_path,跳转过去所带参数放在extraData里,目前为sdkid参数:{from: 'wx-iot', sdkid: xxxx}

此外需要注意的是如果操作流程是厂商小程序——管理小程序——厂商小程序,则管理小程序会使用wx.navigateBackMiniProgram来跳转,相关参数会放在extraData里,如:

extraData: {     
  from: 'wx-iot',
  sdkid: device.deviceInfo.sdkILinkId,
  path: minfo.path

}

结语

感谢您的阅读,希望能有帮助~

附录:

微信官方对接文档: https://iot.weixin.qq.com/doc?page=5-1

新开了掘金号:希望围观 https://juejin.cn/user/255513359550446

posted on 2022-04-29 16:31  WhyWin  阅读(106)  评论(0编辑  收藏  举报

导航