云端接口调用规范
- 无特殊说明时, 微信提供的接口超时为5s 
- 无特殊说明时, 不要对接口调用进行自动重试. 大量的自动重试可能导致对应appid被暂时屏蔽 
权限管理
获取access_token
通过微信开放平台调用微信内部接口时,需要使用appid与secret换取调用凭证access_token
具体参见: https://developers.weixin.qq.com/doc/offiaccount/Basic_Information/Get_access_token.html
设备SN注册
接口说明:
每一个设备绑定前,需要提前到微信硬件平台注册信息,需在设备上线前3个工作日内完成设备注册(如未提前完成设备注册,能力可能无法正常使用,请在上线前预留注册时间)。
注意:
- 单次接口调用,sn个数上限是100,超限将返回错误 
- 产品正式上线前, 只能注册20个sn供开发调试,产品正式上线后会打开注册个数限制 
- 批量离线注册前, 并发请求数不要超过5. 注册速度控制在1w台/min以内 
- 批量注册时间控制在工作日的10:00-20:00, 出问题时可以及时处理, 其他时间只能做少量注册 
- 批量多款产品时, 请一款接一款注册, 不要多款产品并行注册 
- 厂商需记录并维护sn及ilink_im_sdk_id的映射关系 
请求地址:
POST https://api.weixin.qq.com/ilink/api/cloud_register_device?access_token=xxx请求参数:
{
    "product_id": 123,
    "iot_device_list": [
        {
        	"sn": "xx1"
        },
        {
       	 	"sn": "xx2"
        }
    ]
}| 属性 | 类型 | 必填 | 说明 | 
|---|---|---|---|
| product_id | number | 是 | 设备产品唯一标识 | 
| sn | string | 是 | 厂商分配的设备唯一序列号. 长度限制120, 要求ascii字符 | 
返回值:
{
    "errcode":0,
    "errmsg":"xxx",
    "iot_device_list": [
        {
            "sn": "abcpatric",
            "ilink_im_sdk_id":"xxx@ilink.im.sdk"
        },
        {
            "sn": "abcpatric1",
            "ilink_im_sdk_id":"xxx@ilink.im.sdk"
        }
    ],
	"err_device_list":[
		{
			"sn":"abcpatric2",
			"errcode":-1,
			"errmsg":"xxxx"
		}
	]
}| 属性 | 类型 | 说明 | 
|---|---|---|
| errcode | number | 返回码,0为成功 | 
| errmsg | string | 错误信息 | 
| sn | string | 厂商分配的设备唯一序列号 | 
| ilink_im_sdk_id | string | 微信硬件平台分配的设备唯一标识 | 
| err_device_list | string | 注册失败的sn列表及详细错误信息, 只有在外层errcode为 -51003,sn注册部分失败时才存在 | 
绑定管理
拉取设备绑定凭证
接口说明:
设备绑定时,厂商后台到微信硬件平台拉取该台设备的绑定凭证,传递给小程序端或移动应用APP端
请求地址:
POST https://api.weixin.qq.com/ilink/api/get_device_ticket?access_token=xxx请求参数:
{
     "ilink_im_sdk_id": "xxx@ilink.im.sdk",
     "user_openid":"xxx",
 	"ticket_scene": 0
 }| 属性 | 类型 | 必填 | 说明 | 
|---|---|---|---|
| ilink_im_sdk_id | string | 是 | 微信硬件平台分配的设备唯一标识 | 
| user_openid | string | 否 | 绑定设备用户的openid,选填,填了后将在真正绑定时限制用户只能为所填openid对应用户 | 
| ticket_scene | number | 否 | 0:私人模式绑定场景. 4:公共模式绑定场景. 不填默认为0 | 
返回值:
{
     "errcode":0,
     "errmsg":"xxx",
     "ilink_device_ticket":""
 }| 属性 | 类型 | 说明 | 
|---|---|---|
| errcode | number | 返回码,0为成功 | 
| errmsg | string | 错误信息 | 
| ilink_device_ticket | string | 微信硬件平台设备绑定凭证,目前有效期为5分钟 | 
拉取设备绑定二维码
接口说明:
厂商后台到微信硬件平台拉取设备的绑定二维码,用户可使用微信扫描二维码绑定该设备
请求地址:
POST https://api.weixin.qq.com/ilink/api/mmiot/get_device_qrcode?access_token=xxx请求参数:
{
     "ilink_im_sdk_id": "xxx@ilink.im.sdk",
 	"payload":{
 		"ticket_scene": 0
 	}
 }| 属性 | 类型 | 必填 | 说明 | 
|---|---|---|---|
| ilink_im_sdk_id | string | 是 | 微信硬件平台分配的设备唯一标识 | 
| ticket_scene | number | 否 | 0:私人模式绑定场景. 4:公共模式绑定场景. 不填默认为0 | 
返回值:
{
     "errcode": 0,
     "errmsg": "xxx",
     "payload": {
         "device_qrcode_url": "https://mmae.qpic.cn/xxxxxxxx",
         "expire_seconds": 300,
 		"ilink_device_ticket": "xxx"
     }
 }| 属性 | 类型 | 说明 | 
|---|---|---|
| errcode | number | 返回码,0为成功 | 
| errmsg | string | 错误信息 | 
| device_qrcode_url | string | 二维码图片链接 | 
| expire_seconds | number | 二维码失效时间,以秒为单位 | 
| ilink_device_ticket | number | 二维码所对应的微信硬件平台设备绑定凭证, 主要用作回调时厂商关联微信用户 | 
可以访问device_qrcode_url拿到二维码图片
GET https://mmae.qpic.cn/xxxxxxxxhttp status 200成功,非200失败。
成功时,body为图片buffer
(回调厂商)私人设备绑定回调
接口说明:
当管理端绑定私人设备时,微信硬件平台回调厂商后台进行绑定. 厂商可以在绑定回调时进行自己的绑定管理和权限校验.
- 请注意该接口的可用性, 如果回调失败, 绑定流程也将失败. 如果绑定时, 设备已经绑定过该用户, 则不会产生回调. 
- 请注意该接口的幂等性, 详见下文 
请求参数:
{
     "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 | 是 | 微信硬件平台分配的绑定者身份标识 | 
| ilink_im_sdk_id | string | 是 | 微信硬件平台分配的设备唯一标识 | 
| ilink_device_ticket | string | 否 | 绑定ticket, 厂商在快速对接场景下可以通过该ticket关联微信用户与自有用户. 其他绑定场景不一定有该字段, 请勿使用 | 
返回值:
{
     "errcode":0,
     "errmsg":"xxx"
 }(回调厂商)公共设备绑定回调
接口说明:
当管理端绑定公共设备时,微信硬件平台回调厂商后台进行绑定. 厂商可以在绑定回调时进行自己的绑定管理和权限校验.
- 请注意该接口的可用性, 如果回调失败, 绑定流程也将失败. 如果绑定时, 设备已经绑定过该用户, 则不会产生回调. 
- 请注意该接口的幂等性, 详见下文 
请求参数:
{
     "topic": "/ilink/sys/wechat_iot/$product_id/$ilink_im_sdk_id/bind_public_device",
     "payload": {
         "binder_info":{
             "ilink_iot_user_id": "xxx"
         },
         "device_info":{
             "ilink_im_sdk_id": "xxx"
         },
         "ilink_device_ticket": "xxx"
     }
 }
 | 属性 | 类型 | 必填 | 说明 | 
|---|---|---|---|
| ilink_iot_user_id | string | 是 | 微信硬件平台分配的绑定者身份标识 | 
| ilink_im_sdk_id | string | 是 | 微信硬件平台分配的设备唯一标识 | 
| ilink_device_ticket | string | 否 | 绑定ticket, 厂商可以通过该ticket关联微信用户与自有用户. | 
返回值:
{
     "errcode":0,
     "errmsg":"xxx"
 }解绑管理
(回调厂商)私人设备解绑回调
接口说明:
当管理端解绑设备时,厂商可以在解绑回调时进行自己的绑定管理和权限校验.
请注意:
- 请注意接口的可用性, 如果回调失败, 解绑流程也将失败 
- 请注意该接口的幂等性, 详见下文 
- 该接口在调用云接口 - reset_device时不会触发, 只在微信内删除时才触发
请求参数:
{
     "topic": "/ilink/sys/wechat_iot/$product_id/$ilink_im_sdk_id/unbind",
     "payload": {
         "binder_type": 1,
         "binder_info":{
             "ilink_iot_user_id": "xxx"
         },
         "device_info":{
             "ilink_im_sdk_id": "xxx"
         }
     }
 }| 属性 | 类型 | 必填 | 说明 | 
|---|---|---|---|
| binder_type | int | 是 | 绑定者类型. 0=普通绑定者, 1=管理员 | 
| ilink_iot_user_id | string | 是 | 微信硬件平台分配的绑定者身份标识 | 
| ilink_im_sdk_id | string | 是 | 微信硬件平台分配的设备唯一标识 | 
返回值:
{
     "errcode":0,
     "errmsg":"xxx"
 }(回调厂商)公共设备解绑回调
接口说明:
当管理端解绑设备时,厂商可以在解绑回调时进行自己的绑定管理和权限校验.
- 请注意接口的可用性, 如果回调失败, 解绑流程也将失败 
- 请注意该接口的幂等性, 详见下文 
请求参数:
{
     "topic": "/ilink/sys/wechat_iot/$product_id/$ilink_im_sdk_id/unbind_public_device",
     "payload": {
         "binder_info":{
             "ilink_iot_user_id": "xxx"
         },
         "device_info":{
             "ilink_im_sdk_id": "xxx"
         }
     }
 }| 属性 | 类型 | 必填 | 说明 | 
|---|---|---|---|
| ilink_iot_user_id | string | 是 | 微信硬件平台分配的绑定者身份标识 | 
| ilink_im_sdk_id | string | 是 | 微信硬件平台分配的设备唯一标识 | 
返回值:
{
     "errcode":0,
     "errmsg":"xxx"
 }绑定/解绑回调的幂等性
各类绑定/解绑回调接口应该设计为幂等的, 即连续重复绑定/解绑一对ilink_iot_user_id,ilink_im_sdk_id时, 应该总是有相同的返回. 通常是返回成功.
为什么要这样做?
由于网络问题, 微信系统错误等等原因, 有可能厂商侧会重复收到绑定/解绑请求. 此时如果接口幂等, 用户的绑定/解绑操作依然能成功. 少量的关系链不同步让用户通过重试自动修复.
如果接口不幂等, 则该接口只有第一次能调用成功, 之后会一直失败, 导致关系链不同步无法通过重试解决.
怎么做?
以绑定为例, 当厂商侧收到绑定回调.
- 判断该 - ilink_iot_user_id,- ilink_im_sdk_id是否已经绑定过, 若是, 则直接返回成功
- 执行正常的绑定逻辑 
解绑同理
传入绑定凭证进行绑定及解绑方式
使用小程序
说明
对于已经开发过小程序的厂商,厂商可使用小程序跳转接口拉起设备绑定和解绑页面,相关名词解释如下:
- sdkid:即微信硬件平台设备id, 获取方式见接口文档中的注册设备章节 
- ticket:设备绑定凭证,即ilink_device_ticket,获取方式见上问 
跳转appid
appid:wxd930c3b7cf7c92e6
跳转页面说明
跳转参数需放在extraData(json对象)里
- 跳转绑定页 
 页面路径:/pages/discover-new/discover-new
 传递参数:{"from": "xxx", "ticket": "xxxxx", "openid": "xxxx"}, from--添加设备标识符,ticket--从ilink后台获取的绑定凭证, openid--用户openid(可选)
- 跳转解绑设备页 
 页面路径:/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
             }使用移动应用APP
说明
厂商使用APP接入硬件,需先至微信开放平台,申请移动应用,获得移动应用AppID后,进行后续开发。
其中,ticket为设备绑定凭证,获取方式见流程接口中的绑定小节;sdkid为微信硬件平台设备id, 获取方式见流程接口中的注册设备SN小节。
Android开发示例
开发前需下载Android开发工具包(SDK),可前往下载(https://developers.weixin.qq.com/doc/oplatform/Downloads/Android_Resource.html)
调用接口:WXLaunchMiniProgram
移动应用跳转到微信设备页示例:
String appId = "wxdxxxxxxxx";  // 厂商填移动应用(App)的 AppId
 IWXAPI api = WXAPIFactory.createWXAPI(context, appId);
 WXLaunchMiniProgram.Req req = new WXLaunchMiniProgram.Req();
 req.userName = "gh_471f5f7b25a9"// 注意这是微信硬件的username,不需要改动
 req.path = path 
  //以绑定为例,路径示例:"pages/discover-new/discover-new?ticket=234234",内部字符串不需要引号
  
  req.miniprogramType = WXLaunchMiniProgram.Req.MINIPTOGRAM_TYPE_RELEASE;//注意这里可选不同版本TEST(测试版)/PREVIEW(体验版)/RELEASE(线上版),正常测试时使用体验版,正式上线时需切换至线上正式版
  api.sendReq(req);
  
  //解绑设备需替换:
  req.path = path 
  //path路径示例:"pages/delete-devices/delete-devices?sdkIdList=[\"xxx@ilink.im.sdk\"]",内部字符串不需要引号,sdkid列表为json数组列表字符串回调说明:
WXEntryActivity中
  public void onResp(BaseResp resp) {
      if (resp.getType() == ConstantsAPI.COMMAND_LAUNCH_WX_MINIPROGRAM) {
          WXLaunchMiniProgram.Resp launchMiniProResp = (WXLaunchMiniProgram.Resp) resp;
          String extraData =launchMiniProResp.extMsg; //对应组件 <button open-type="launchApp"> 中的 app-parameter 属性
      }iOS开发示例
开发前需下载iOS开发工具包(SDK),前往下载(https://developers.weixin.qq.com/doc/oplatform/Downloads/iOS_Resource.html)
移动应用跳转到微信设备页示例:
WXLaunchMiniProgramReq *launchMiniProgramReq = [WXLaunchMiniProgramReq object];
  launchMiniProgramReq.userName = gh_471f5f7b25a9; // 注意这是微信硬件的username,不需要改动
  launchMiniProgramReq.path = path; 
  //以绑定为例,路径示例:"pages/discover-new/discover-new?ticket=234234",内部字符串不需要引号;
  
  launchMiniProgramReq.miniProgramType = miniProgramType; //注意这里不同版本TEST(测试版)/PREVIEW(体验版)/RELEASE(线上版),正常测试时使用体验版,正式上线时需切换至线上正式版
  return  [WXApi sendReq:launchMiniProgramReq];
  
  //解绑设备需替换:
  launchMiniProgramReq.path = path; 
   //路径示例:"pages/delete-devices/delete-devices?sdkIdList=sdkid列表",内部字符串不需要引号回调说明:
-(void)onResp:(BaseResp *)resp 
  {
       if ([resp isKindOfClass:[WXLaunchMiniProgramResp class]])
       {
            NSString *string = resp.extMsg;
            // 对应JsApi navigateBackApplication中的extraData字段数据
       }
  }私人设备重置
接口说明:
清空私人设备的绑定数据, 状态, 属性等各类数据。ilink_im_sdk_id不作废。本接口的使用场景是设备按钮触发或设备故障等非用户主动发起的重置。如果是用户主动发起的解绑,请通过前文拉起页面的方式解绑。
请求地址:
POST https://api.weixin.qq.com/ilink/api/reset_device?access_token=xxx请求参数:
{
                      "ilink_im_sdk_id": "xxxx@ilink.im.sdk",
                  }| 属性 | 类型 | 说明 | 
|---|---|---|
| ilink_im_sdk_id | string | 微信硬件平台分配的设备唯一标识 | 
返回值:
{
                  	"errcode": 0,
                  	"errmsg": "" 
                  }公共设备重置
接口说明:
清空公共设备的绑定数据。ilink_im_sdk_id不作废。本接口的使用场景是设备按钮触发或设备故障等非用户主动发起的重置。
请求地址:
POST https://api.weixin.qq.com/ilink/api/mmiot/reset_public_device?access_token=xxx请求参数:
{
                      "ilink_im_sdk_id": "xxxx@ilink.im.sdk",
                  }| 属性 | 类型 | 说明 | 
|---|---|---|
| ilink_im_sdk_id | string | 微信硬件平台分配的设备唯一标识 | 
返回值:
{
                  	"errcode": 0,
                  	"errmsg": "" 
                  }回调接口说明
回调是指用户在执行微信业务流程时, 微信后台对厂商后台的调用. 一般微信不会对失败的回调进行重试, 而是直接将业务流程视为失败.目前可认为回调接口的超时为3s.
厂商对请求的验证
流程1:厂商在微信硬件平台配置回调地址callback_url、签名材料token
流程2:当回调接收服务收到请求时,计算签名,并与请求签名比对
微信硬件平台请求的url为:
POST https://$callback_url?signature=xxx×tamp=xxx&nonce=xxx验签算法为
- 将token、timestamp、nonce三个参数进行字典序排序 
- 将三个参数字符串拼接成一个字符串进行sha1哈希 
- 开发者获得加密后的字符串可与signature对比,标识该请求来源于微信 
private function checkSignature()
{
    $signature = $_GET["signature"];	//示例: 9d8ed9a3e985d2255807680ce8d450bd06fbde14
    $timestamp = $_GET["timestamp"];	//示例: 1636537701
    $nonce = $_GET["nonce"];	//示例: 1410310936
    $token = TOKEN;	//示例: 8GhcGcYyz70012
    $tmpArr = array($token, $timestamp, $nonce);
    sort($tmpArr, SORT_STRING);
    $tmpStr = implode( $tmpArr );
    $tmpStr = sha1( $tmpStr );
    
    if( $tmpStr == $signature ){
        return true;
    }else{
        return false;
    }
}回调接口格式说明
回调接口请求包采用如下格式
{
	"topic": "/ilink/sys/...",
	"payload": {
		...
	}
}| 属性 | 类型 | 说明 | 
|---|---|---|
| topic | string | 请求topic | 
| payload | object | 请求体 | 
返回值
{
    "errcode": 0,
    "errmsg": ""
}回调中返回的错误码
| 错误码 | 含义 | 
|---|---|
| 0 | 调用成功 | 
| -50001 | 服务内部错误 | 
| -50002 | 参数错误 | 
| -50003 | 权限错误 | 
| -50004 | 签名校验错误 | 
| -50005 | 设备离线 | 
| -50010 | 属性值高于上限,限 设置设备属性接口使用 | 
| -50011 | 属性值低于下限,限 设置设备属性接口使用 | 
| -50100 | 其他错误 | 
建议在errmsg中附带错误原因, 请求的唯一id等信息, 方便追踪问题.
常见错误码
微信API常见错误码
| 错误码 | 含义 | 
|---|---|
| 0 | 调用成功 | 
| -1 | 服务内部错误 | 
| -2 | 参数错误 | 
| -20009 | 请求包反序列化错误, 通常是字段类型填错, 如数字填成了字符串 | 
| -40005 | 云接口appid无权限, 请检查access_token对应的appid是否和官网注册appid一致 | 
| -40050 | 回调厂商失败 | 
| -40060 | 测试sn数量达到上限 | 
| 40014 | 不合法的 access_token ,请开发者认真比对 access_token 的有效性(如是否过期),或查看是否正在为恰当的公众号调用接口 (https://developers.weixin.qq.com/doc/offiaccount/Getting_Started/Global_Return_Code.html) | 
| -51001 | sn并发注册错误 | 
| -51002 | 单台设备并发上报物模型错误 | 
| -51003 | sn注册部分失败 | 
物模型概述
物模型是一种描述产品功能的模型, 它描述了设备具有哪些功能, 具备哪些属性.
物模型将产品功能分为: 属性,服务
- 属性: 设备的运行状态. 如当前温度, 或者某个开关的开启关闭 
- 服务: 设备能对外提供的功能. 
- 事件: 设备产生的事件. 如摄像头有人经过, 运动产生步数等 
服务与属性的差别: 一个功能可能不适合描述成状态改变, 比如钟表启用时间校准功能, 或者对话机器人翻译一段话. 或者这个功能需要复杂的参数, 比如打印机打印文件时需要发送文件内容和复杂的打印配置. 此时这个功能适合描述为一个服务. 但类似"开门","开灯"这种状态的改变更适合设置为属性.
物模型定义
下文给出一个伪代码来描述一个物模型.
- 属性采用类的成员变量表示
- 服务采用类的成员函数, 以及相应的Request, Response表示
- 事件采用一个特定的的成员函数- ReportEvent(XxxEvent), 以及一个XxxEvent定义表示
//pid为1000的物模型定义
class ThingModel_Pid_1000{
    //属性定义
    @Spec(name="温度",//属性名称
    access_mode="rw",//属性读写类型:只读(r)或读写(rw)
        min=16,//最小值
        max=30,//最大值
        unit="℃",//单位
        step=1//步长
    )
    int temperature; 
    @Spec(name="状态列表", access_mode="rw",
    max_size=128//最大数组长度, array类特有
    )
    int[] status_list;
    @Spec(name="位置",access_mode="rw")
    Location location;
    //服务定义, 设置模式
    SetModelResp SetModel(SetModelReq req);
    //事件定义, 上报故障事件
    void ReportEvent(FaultEvent event);
}
//结构体定义
class Location{
    @Spec(name="经度",min=-180,max=180,unit="°",step=0.01)
    double longitude;
    @Spec(name="纬度",min=-180,max=180,unit="°",step=0.01)
    double latitude;
    @Spec(name="高度",min=0,max=9999,unit="m",step=0.01)
    double altitude;
}
//服务的reqeust和response定义
class SetModelReq{
    @Spec(name="模式") 
    String model;
}
class SetModelResp{
    @Spec(name="是否成功") 
    bool succ;
}
//事件定义
@Spec(event_type=error)//事件类型分为error,alert,info
class FaultEvent{
string fault_type;
long fault_time;
}调用格式
后台调用
是常规的调用方式, 指厂商通过微信的云接口, 云回调等进行物模型交互, 详见后文物模型管理 等接口
小程序调用
少数场景下, 厂商需要通过小程序处理物模型调用.
当前场景:
- 发送消息到设备时拉起厂商小程序 
厂商小程序获取微信传参示例
小程序里可通过wx.getEnterOptionsSync()获取微信传过来的参数(具体示例如下所示),一般在页面的onLoad方法中调用;其中可以验证场景值scene是1226,具体参数在iot字段
注意payload里的params字段是json字符串,需要再次parse成json对象来使用.
以发送文件WxStdSendMsg.WxStdSendFile为例
{
    "path":"pages/device-discovery/device-discovery",
    "query":{
    },
    "scene":1226,
    "referrerlnfo":{
    },
    "mode":"default",
    "apiCategory":"default",
    "iot":{
        "nonce":"3972126057",
        "timestamp":"1656590248",
        "signature":"e0fb1e92f5d44829379f466760ae407db683b937a54e2cadf6e69b5e1ed42195",
        "params":{
            "topic":"ilink/sys/wechatiot/3947/AAYAABPZmWJWW2aRAdkg-rwuVQYCzHpueK22r7DxclY@ilinkimsdk/invoke_device_service",
            "payload":{
                "ilink_im_sdk_id":"AAYAABPZmWJWW2aRAdkg-nwuVQYCzHpueK22r7DxclY@ilink.im.sdk",
                "params":"{\"tag_base64\":\"Jsk4UJcSy9zLFVBx2qXFaQ==\",\"keybase64\":\"2rZwgqsKWAMuRdXG8DXeSGCgCNIn76NQsiSfPbEgbe0=\",\"type\":\"pdf\",\"download_url\":\"http://wxapp.tc.qq.com/272/20303/stodownload?m=b1dedad05de9ffc85f205e44224c9f02&flekey=30350201010421301f020201100402535a0410b1dedad05de9ffc85f205e44224c9f0202030390f2040d00000004627466730000000131&hy=SZ&storeid=32303232303633303139353732373030306439313566626536333466653536623631383830393030303030313130&bizid=1023\",\"ivbase64\":\"R+lGduezQMPvr4ZU\",\"encrypt_algo\":\"AEAD_AES_256_GCM\",\"name\":\"微信硬件发送文件测试case(1).pdf\"}",
                "ilink_trace_id":"9952813327A8401E16B53FO18A1A5CCB",
                "service_identifer":"WxStdSendMsg WxStdSendFile"
            }
        },
        "signature_algo":"HMAC-SHA256"
    }
}其中的params即为物模型调用参数.
微信小程序参数的通用格式
即上文中的iot字段
{
"params": "...",
"timestamp": "12345",
"nonce": "12345",
"signature": "9d8ed9a3e985d2255807680ce8d450bd06fbde14",
"signature_algo": "HMAC-SHA256"
}对参数验签
为了防止不安全的客户端拉起小程序页面, 厂商可以在后台对参数进一步验签.
验签步骤为:
(1)params、timestamp、nonce三个参数进行字典序排序
(2)将三个参数字符串拼接成一个字符串input
(3) 计算签名, 签名=HMAC_SHA256( key=回调token, message=input )
(4) 验证该签名与微信参数中的signature是否一致. 若一致则说明该请求由微信服务端发起
概念介绍
本节介绍了微信标准的物模型. 如果厂商接入了标准的物模型, 可以获得微信的一些快捷能力.
标准物模型类似于编程语言中的"接口", 厂商物模型可以实现多个标准物模型
标准物模型: 健康设备
class WxStdHealthDevice{
	
	void ReportEvent(DailySummaryEvent event);
    void ReportEvent(SportsEvent event);
}
@Spec(event_type=info)
class DailySummaryEvent{
	@Spec(name="今日步数")
    int today_step; 
	
    @Spec(name="今日卡路里", unit="千卡")
    int today_calorie;
	
	@Spec(name="上报时间", unit="秒")
	int report_timestamp;
}
@Spec(event_type=info)
class SportsEvent{
    @Spec(name="运动类型")
    int sports_type;
	
    @Spec(name="运动距离", unit="米")
    int distance;
	
	@Spec(name="运动个数")
	int number;
	   
	@Spec(name="运动开始时间戳", unit="秒")
    int start_timestamp;
	
	@Spec(name="运动结束时间戳", unit="秒")
    int end_timestamp;
	
    @Spec(name="卡路里", unit="千卡")
    int calorie;
	
	@Spec(name="平均心率")
	int average_heart_rate;
	
	@Spec(name="持续时间", unit="秒")
	int duration;
}
标准物模型: 发送消息到设备
接入后可获得长按微信消息->打开->发送到设备的能力
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;	//下载的内容经过加密, 需要厂商解密. 有效期24h
	
    @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 {
}
出于安全性考虑,download_url下载的内容经过了加密, 算法为AEAD_AES_256_GCM. 厂家需要通过请求中的key_base64,iv,tag_base64等作为参数, 将下载内容解密得到明文. 目前大部分编程语言都支持了AEAD_AES_256_GCM算法
标准物模型identifier格式
一个标准物模型的属性,服务或事件名, 有可能和自定义物模型或其他标准物模型重复. 因此在设置设备属性, 调用设备服务, 上报设备属性 等接口传参时会带一个前缀, 具体格式如下:
| 参数名 | 参数格式 | 举例 | |
|---|---|---|---|
| 属性 | property_identifier | {标准物模型}.{属性名} | WxStdSwitch.switch_on | 
| 服务 | service_identifier | {标准物模型}.{服务名} | WxStdSendMsg.WxStdSendFile | 
| 事件 | event_identifier | {标准物模型}.{事件名} | WxStdHealthDevice.SportsEvent | 
上报设备状态
接口说明:
设备主动向后台上报状态, 状态是一些通用的设备信息, 没有在物模型中显式定义. 如上线,下线等
请求地址:
POST https://api.weixin.qq.com/ilink/api/report_device_status?access_token=xxx请求参数:
{
    "ilink_im_sdk_id": "xxxx@ilink.im.sdk",
    "status": "online"
}| 属性 | 类型 | 说明 | 
|---|---|---|
| ilink_im_sdk_id | string | 微信硬件平台分配的设备唯一标识 | 
| status | string | 设备状态, 有 online,offline | 
返回值:
{
"errcode": 0,
"errmsg": "" 
}上报设备属性(需接入物模型)
接口说明:
设备向后台上报属性
请求地址:
POST https://api.weixin.qq.com/ilink/api/report_device_property?access_token=xxx请求参数:
{
    "ilink_im_sdk_id": "xxxx@ilink.im.sdk",
    "properties": [
        {
                "property_identifier": "temperature",
                "value": 26
            },
            {
                "property_identifier": "mode",
                "value": "cooling"
            }
    ]
}| 属性 | 类型 | 说明 | 
|---|---|---|
| ilink_im_sdk_id | string | 微信硬件平台分配的设备唯一标识 | 
| properties | array | 要上报的属性列表。属性在物模型中定义过,或者是引用的标准物模型中的属性 | 
返回值:
{
    errcode: 0,
    errmsg: "", 
}(回调厂商)设置设备属性(需接入物模型)
接口说明:
设置设备属性. 厂商异步下发给设备即可.
请求参数:
{
    "topic": "/ilink/sys/wechat_iot/$product_id/$ilink_im_sdk_id/set_device_property",
    "payload":{
        "ilink_im_sdk_id": "xxxx@ilink.im.sdk",
        "properties": [
    {
                "property_identifier": "temperature",
                "value": 26
            },
            {
                // 引用的标准物模型WxStdSwitch中的属性switch_on
                "property_identifier": "WxStdSwitch.switch_on",
                "value": true
            },
            {
                "property_identifier": "location",
                "value": {
                    "longitude": 10.0,
                    "latitude": 10.0,
                    "altitude": 10.0
                }
            }
        ]
    }
}| 属性 | 类型 | 说明 | 
|---|---|---|
| ilink_im_sdk_id | string | 微信硬件平台分配的设备唯一标识 | 
| properties | array | 要设置的属性列表。属性在物模型中定义过,或者是引用的标准物模型中的属性 | 
返回值:
{
    "errcode":0,
    "errmsg":"xxx",
}| 属性 | 类型 | 说明 | 
|---|---|---|
| errcode | number | 返回码,0为成功 | 
| errmsg | string | 错误信息 | 
(回调厂商)调用设备服务 (需接入物模型)
接口说明:
调用设备服务. 厂商异步下发给设备即可.
调用物模型自定义的服务custom_service时,"service_identifier"的值为"custom_service"
调用物模型引用的标准物模型WxStdXXX的服务WxStdYYY时,"service_identifier"的值为"WxStdXXX.WxStdYYY"
请求参数:
{
    "topic": "/ilink/sys/wechat_iot/$product_id/$ilink_im_sdk_id/invoke_device_service",
    "payload":{
    "ilink_im_sdk_id": "xxxx@ilink.im.sdk",
        "service_identifier": "服务标识符",
        "params": {
            "temperature": 26,
            "mode": "cooling"
        },
        "ilink_trace_id": "XXXXXX",
    }
}| 属性 | 类型 | 说明 | 
|---|---|---|
| ilink_im_sdk_id | string | 微信硬件平台分配的设备唯一标识 | 
| service_identifier | string | 服务标识符, 在物模型中, 或被引用的标准物模型中定义过 | 
| params | object | 服务的参数. 在物模型中定义过 | 
| ilink_trace_id | string | 一个用来追踪请求调用的id, 设备完成服务后可以回传该id给微信,作为这次服务调用的响应 | 
返回值:
{
    "errcode":0,
    "errmsg":"xxx",
}| 属性 | 类型 | 说明 | 
|---|---|---|
| errcode | number | 返回码,0为成功 | 
| errmsg | string | 错误信息 | 
回调厂商返回的错误码说明:
在厂商收到微信回调的3s内,返回对应的errcode错误码,微信将根据不同状态,在发送结果页面中提醒用户对应的设备状态(在微信8.0.34及以上版本中支持).
| 错误码 | 含义 | 
|---|---|
| 0 | 回调成功 | 
| -62501 | 设备异常 | 
| -62502 | 不支持该种文件类型 | 
| -62503 | 不支持该种消息类型 | 
| -62504 | 文件过大,设备暂不支持 | 
| -62505 | 暂无法使用该设备 | 
响应服务调用(需接入物模型, 可选)
接口说明:
设备完成服务调用的操作后, 将响应发给微信. 当某些服务在控制端需要知道调用结果时, 可调用此接口上报设备调用结果.
请求地址:
POST https://api.weixin.qq.com/ilink/api/reply_device_service?access_token=xxx请求参数:
{
    "ilink_trace_id": "一段字符串",
    "ilink_im_sdk_id": "xxxx@ilink.im.sdk",
    "errcode": 0,
    "errmsg": "",
    "output": {
        "temperature": 26,
        "mode": "cooling"
    }
}| 属性 | 类型 | 说明 | 
|---|---|---|
| ilink_trace_id | string | 调用设备服务时的traceid | 
| ilink_im_sdk_id | string | 微信硬件平台分配的设备唯一标识 | 
| errcode | int | 调用设备服务的错误码 | 
| errmsg | string | 调用设备服务的错误信息 | 
| output | object | 设置设备属性的结果 | 
返回值:
{
    "errcode": 0,
    "errmsg": "", 
}上报设备事件(需接入物模型)
接口说明:
设备向后台上报事件,一天之内, 同个request_event_id只能上报一次, 重复上报则微信不再上报, 直接返回成功
请求地址:
POST https://api.weixin.qq.com/ilink/api/report_device_event?access_token=xxx请求参数:
{
    "ilink_im_sdk_id": "xxxx@ilink.im.sdk",
    "event_identifier": "事件标识符", //如WxStdHealthDevice.SportsEvent
    "params": {
        "temperature": 26,
        "mode": "cooling"
    },
"request_event_id": "request_event_id"
}| 属性 | 类型 | 说明 | 
|---|---|---|
| ilink_im_sdk_id | string | 微信硬件平台分配的设备唯一标识 | 
| event_identifier | string | 事件标识符, 在物模型中, 或被引用的标准物模型中定义过 | 
| params | object | 事件的参数. 在物模型中, 或被引用的标准物模型中定义过 | 
| request_event_id | string | 上报事件请求的标识串. 长度小于等于64,由ascii可见字符组成 | 
返回值:
{
    "errcode":0,
    "errmsg":"xxx",
}| 属性 | 类型 | 说明 | 
|---|---|---|
| errcode | number | 返回码,0为成功 | 
| errmsg | string | 错误信息 | 
1. 概述
微信硬件平台为硬件设备提供了连接微信用户的能力和身份。接入微信硬件平台的设备,可添加至用户的设备页中,微信用户可以在设备列表里查看和控制设备。

2. 微信运动
运动类设备,如运动手表、运动手环等,接入微信硬件平台后,用户可通过设备向微信传入运动数据,运动数据将在微信运动排行榜页、个人详情页及微信设备页进行展示,并显示数据来源。

3. 发送消息到设备
硬件设备接入微信硬件平台后,可接入发送消息到设备能力,用户在聊天界面中长按特殊类型的消息,可通过“打开”入口向设备发送此消息。目前已支持向硬件设备发送文件、图片类消息,详见开发文档。

1. 注册厂商信息
厂商首次接入时,需在首页中点击注册,填写厂商账号的信息并进行注册,此部分信息一经注册,不可修改。等待微信硬件平台审核通过,即可使用此账号登录,进行设备产品的注册。

2. 注册产品信息
填写产品基本信息
产品名称将在微信客户端设备页等页面内展示给用户,厂商需注意尽量使用简短的产品名称,不得包含与硬件无关的内容。注意,此部分产品信息一经注册,无法修改。

填写产品开发信息
首次注册产品时,需要填写回调地址与云端数据通讯APPID(此APPID用于访问微信硬件平台云接口,由微信公众平台或开放平台分配,可以使用厂商公众号、小程序、移动应用所分配的APPID其中之一;此APPID与回调地址在注册之后,可以在账号信息中进行修改)。

云快速接入方式支持厂商小程序或APP发起添加和解绑设备的流程。
若选择无自有小程序,则需要填写发起添加绑定的APP所对应的移动应用appid(微信开放平台注册并分配)。
若选择自有小程序接入,需填写对应的发起添加绑定的小程序所对应的appid(微信公众平台注册并分配)及跳转路径,绑定设备后,在微信客户端的设备页点击设备,可跳转至厂商小程序此路径的页面,进行设备相关的控制(跳转会携带设备参数,详见开发者文档)。
选择产品能力信息
根据设备类型及开发信息,选择接入的产品能力,功能介绍详见添加产品页面。

3. 申请设备上线
产品信息审核通过之后,厂商需先完成设备功能的开发和功能自测,之后可根据pid寄送测试样机至微信硬件平台,提交设备上线申请,微信测试验收通过后,厂商即可上线功能与设备。
