package xyz.kingsilk.qh.service.service
import grails.converters.JSON
import grails.transaction.Transactional
import org.springframework.http.*
import org.springframework.web.client.RestTemplate
import org.springframework.web.util.UriComponentsBuilder
@Transactional
class WeiXinDeviceService {
/** API URL : 设备的二维码 */
public static final String DEVICE_TICKETS = "https://api.weixin.qq.com/device/create_qrcode"
/** API URL : 第三方获取deviceid和设备二维码 */
public static final String DEVICE_GET_QRCODE = "https://api.weixin.qq.com/device/getqrcode"
/** API URL : 设备绑定 */
public static final String DEVICE_BIND = "https://api.weixin.qq.com/device/bind"
/** API URL : 设备强制绑定 */
public static final String DEVICE_COMPEL_BIND = "https://api.weixin.qq.com/device/compel_bind"
/** API URL : 设备解绑 */
public static final String DEVICE_UNBIND = "https://api.weixin.qq.com/device/unbind"
/** API URL : 设备强制解绑 */
public static final String DEVICE_COMPEL_UNBIND = "https://api.weixin.qq.com/device/compel_unbind"
/** API URL : 设备获取状态 */
public static final String DEVICE_GET_STATE = "https://api.weixin.qq.com/device/get_stat"
/** API URL : 设备验证二维码 */
public static final String DEVICE_VERIFY_QRCODE = "https://api.weixin.qq.com/device/verify_qrcode"
/** API URL : 获取设备绑定openID */
public static final String DEVICE_GET_QPENID = "https://api.weixin.qq.com/device/get_openid"
/** API URL : 通过openid获取用户绑定的deviceid */
public static final String DEVICE_GET_BIND = " https://api.weixin.qq.com/device/get_bind_device"
/** API URL : 设备授权*/
public static final String DEVICE_AUTHORIZE = "https://api.weixin.qq.com/device/authorize_device"
/** API URL : 主动发送消息给设备*/
public static final String DEVICE_TRANSMSG = "https://api.weixin.qq.com/device/transmsg"
/**
* 微信硬件应⽤端数据接口
* 微信硬件云端和应⽤端消息交互,分成三种消息类型:
1. 应⽤端查询设备状态:当应⽤端需要查询设备信息的时候,应⽤端可以调
⽤查询设备API,微信硬件云端收到请求后,⽴即返回成功收到请求。待
查询到设备状态成功,将查询结果POST到接⼊者的注册URL上。
2. 应⽤端设置设备状态:当应⽤端需要设置设备信息的时候,应⽤端可以调
⽤设置设备状态API,微信硬件云端收到请求后,⽴即返回成功收到请
求。待设备状态设置成功后,将查询结果POST到接⼊者的注册URL上。
3. 设备状态变化通知消息:当设备状态有变化或者有消息需要通知应⽤端的
时候,微信硬件云POST消息给接⼊者的注册URL上。微信硬件云端⽴即返
回成功收到请求。
*/
/** API URL : . 设备查询*/
public static
final String MY_DEVICE_GET_STATUS = "https://api.weixin.qq.com/hardware/mydevice/platform/get_device_status"
public static final String MY_DEVICE_CTRL = "https://api.weixin.qq.com/hardware/mydevice/platform/ctrl_device"
RestTemplate wxRestTemplate
/**
* 获取设备的二维码
* @param device_id_list
* @param accessToken
* @return
* 成功:json方式返回二维码的生成ticket
*{
* "errcode":0,
* "errmsg":"succ",
* "device_num":1,
* "code_list":[{"device_id":"id1","ticket":"t1"}]
*}* 错误的Json返回示例:
*{
* "errcode":-1,"errmsg":""
*}
*/
public String getDeviceTickets(List<String> device_id_list, String accessToken) {
URI uri = UriComponentsBuilder.fromHttpUrl(DEVICE_TICKETS)
.queryParam("access_token", accessToken)
.build()
.encode("UTF-8")
.toUri()
HttpHeaders headers = new HttpHeaders()
headers.setContentType(MediaType.APPLICATION_JSON)
def json = ([
device_num : device_id_list.size(),
device_id_list: device_id_list
] as JSON)
HttpEntity<String> reqEntity = new HttpEntity<String>(json.toString(), headers)
ResponseEntity respEntity = wxRestTemplate.exchange(uri, HttpMethod.POST, reqEntity, String.class)
return respEntity?.body
}
/**
* 主动发送消息给设备
* 第三方发送消息给设备主人的微信终端,并最终送达设备
* @param accessToken 调用接口凭证
* @param device_id 设备id
* @param device_type 设备类型,目前为“公众账号原始ID”
* @param content 消息内容,BASE64编码
* @param openid 用户对应的openid
* @return
* 成功的Json返回结果:
*{base_resp:{"errcode": 0,"errmsg":"ok"}}* 失败的Json返回示例:
*{base_resp:{"errcode": -1,"errmsg":"system error"}}
*/
public String transmsg(String accessToken, String device_id, String openid, String device_type, String content) {
URI uri = UriComponentsBuilder.fromHttpUrl(DEVICE_TRANSMSG)
.queryParam("access_token", accessToken)
.build()
.encode("UTF-8")
.toUri()
HttpHeaders headers = new HttpHeaders()
headers.setContentType(MediaType.APPLICATION_JSON)
def json = ([
"device_id" : device_id,
"openid" : openid,
"device_type": device_type,
"content" : content
] as JSON)
HttpEntity<String> reqEntity = new HttpEntity<String>(json.toString(), headers)
ResponseEntity respEntity = wxRestTemplate.exchange(uri, HttpMethod.POST, reqEntity, String.class)
return respEntity?.body
}
/**
* 设备强制绑定
* 第三方后台绑定操作处理成功,通知公众平台。
* @param accessToken 调用接口凭证
* @param device_id 设备id
* @param openid 用户对应的openid
* @return
* 成功的Json返回结果:
*{base_resp:{"errcode": 0,"errmsg":"ok"}}* 失败的Json返回示例:
*{base_resp:{"errcode": -1,"errmsg":"system error"}}
*/
public String compel_bind(String accessToken, String device_id, String openid) {
URI uri = UriComponentsBuilder.fromHttpUrl(DEVICE_COMPEL_BIND)
.queryParam("access_token", accessToken)
.build()
.encode("UTF-8")
.toUri()
HttpHeaders headers = new HttpHeaders()
headers.setContentType(MediaType.APPLICATION_JSON)
def json = ([
"device_id": device_id,
"openid" : openid
] as JSON)
HttpEntity<String> reqEntity = new HttpEntity<String>(json.toString(), headers)
ResponseEntity respEntity = wxRestTemplate.exchange(uri, HttpMethod.POST, reqEntity, String.class)
return respEntity?.body
}
/**
* 设备绑定
* 第三方后台绑定操作处理成功,通知公众平台。
* @param accessToken 调用接口凭证
* @param ticket 绑定操作合法性的凭证(由微信后台生成,第三方H5通过客户端jsapi获得)
* @param device_id 设备id
* @param openid 用户对应的openid
* @return
* 成功的Json返回结果:
*{base_resp:{"errcode": 0,"errmsg":"ok"}}* 失败的Json返回示例:
*{base_resp:{"errcode": -1,"errmsg":"system error"}}
*/
public String bind(String accessToken, String ticket, String device_id, String openid) {
URI uri = UriComponentsBuilder.fromHttpUrl(DEVICE_BIND)
.queryParam("access_token", accessToken)
.build()
.encode("UTF-8")
.toUri()
HttpHeaders headers = new HttpHeaders()
headers.setContentType(MediaType.APPLICATION_JSON)
def json = ([
"ticket" : ticket,
"device_id": device_id,
"openid" : openid
] as JSON)
HttpEntity<String> reqEntity = new HttpEntity<String>(json.toString(), headers)
ResponseEntity respEntity = wxRestTemplate.exchange(uri, HttpMethod.POST, reqEntity, String.class)
return respEntity?.body
}
/**
* 设备解绑
* 第三方后台绑定操作处理成功,通知公众平台。
* @param accessToken 调用接口凭证
* @param ticket 绑定操作合法性的凭证(由微信后台生成,第三方H5通过客户端jsapi获得)
* @param device_id 设备id
* @param openid 用户对应的openid
* @return
* 成功的Json返回结果:
*{base_resp:{"errcode": 0,"errmsg":"ok"}}* 失败的Json返回示例:
*{base_resp:{"errcode": -1,"errmsg":"system error"}}
*/
public String unbind(String accessToken, String ticket, String device_id, String openid) {
URI uri = UriComponentsBuilder.fromHttpUrl(DEVICE_UNBIND)
.queryParam("access_token", accessToken)
.build()
.encode("UTF-8")
.toUri()
HttpHeaders headers = new HttpHeaders()
headers.setContentType(MediaType.APPLICATION_JSON)
def json = ([
"ticket" : ticket,
"device_id": device_id,
"openid" : openid
] as JSON)
HttpEntity<String> reqEntity = new HttpEntity<String>(json.toString(), headers)
ResponseEntity respEntity = wxRestTemplate.exchange(uri, HttpMethod.POST, reqEntity, String.class)
return respEntity?.body
}
/**
* 设备强制解绑
* 第三方后台绑定操作处理成功,通知公众平台。
* @param accessToken 调用接口凭证
* @param device_id 设备id
* @param openid 用户对应的openid
* @return
* 成功的Json返回结果:
*{base_resp:{"errcode": 0,"errmsg":"ok"}}* 失败的Json返回示例:
*{base_resp:{"errcode": -1,"errmsg":"system error"}}
*/
public String compel_unbind(String accessToken, String device_id, String openid) {
URI uri = UriComponentsBuilder.fromHttpUrl(DEVICE_COMPEL_UNBIND)
.queryParam("access_token", accessToken)
.build()
.encode("UTF-8")
.toUri()
HttpHeaders headers = new HttpHeaders()
headers.setContentType(MediaType.APPLICATION_JSON)
def json = ([
"device_id": device_id,
"openid" : openid
] as JSON)
HttpEntity<String> reqEntity = new HttpEntity<String>(json.toString(), headers)
ResponseEntity respEntity = wxRestTemplate.exchange(uri, HttpMethod.POST, reqEntity, String.class)
return respEntity?.body
}
/**
* 利用deviceid更新设备属性
* 第三方公众账号将device id及其属性信息提交公众平台进行授权。
* http://iot.weixin.qq.com/wiki/new/index.html?page=3-4-6
* @param accessToken 调用接口凭证
* @param device_num 设备id的个数
* @param device_list 设备id的列表,json的array格式,其size必须等于device_num
* @param op_type 请求操作的类型,限定取值为: 1:设备更新(更新已授权设备的各属性值)
* @return
* 成功的Json返回结果:{"resp":[{
"base_info":{
"device_type":"your_devcie_type",
"device_id":"id"
},
"errcode":0,
"errmsg":"ok"
}]}* 失败的Json返回示例:
*{"errcode":42001,"errmsg":""}
*/
public String authorize(String accessToken, String device_num, String device_list, op_type) {
URI uri = UriComponentsBuilder.fromHttpUrl(DEVICE_AUTHORIZE)
.queryParam("access_token", accessToken)
.build()
.encode("UTF-8")
.toUri()
HttpHeaders headers = new HttpHeaders()
headers.setContentType(MediaType.APPLICATION_JSON)
def json = ([
"device_num" : device_num,
"device_list": device_list,
"op_type" : op_type
] as JSON)
HttpEntity<String> reqEntity = new HttpEntity<String>(json.toString(), headers)
ResponseEntity respEntity = wxRestTemplate.exchange(uri, HttpMethod.POST, reqEntity, String.class)
return respEntity?.body
}
/**
* 设备获取状态
* 第三方公众账号通过设备id查询该id的状态(三种状态:未授权、已授权、已绑定)。
* http://iot.weixin.qq.com/wiki/document-2_7.html
* @param accessToken 调用接口凭证
* @param product_id ;
* 设备的产品编号(由微信硬件平台分配)。可在公众号设备功能管理页面查询。
当product_id 为‘1’时,不要填写product_id 字段(会引起不必要错误);
当product_id 不为‘1’时,必须填写 product_id 字段;
* @return
* 成功的Json返回结果:{resp_msg:{"ret_code":0," error_info":"ok"},"deviceid":"XXX","qrticket":"XXX"}* 失败的Json返回示例:{resp_msg:{"ret_code":-1," error_info":"system error"}}
*/
public String get_qrcode(String accessToken, String product_id) {
URI uri = UriComponentsBuilder.fromHttpUrl(DEVICE_GET_QRCODE)
.queryParam("access_token", accessToken)
.queryParam("product_id", product_id)
.build()
.encode("UTF-8")
.toUri()
ResponseEntity respEntity = wxRestTemplate.getForEntity(uri, String)
return respEntity?.body
}
/**
* 设备获取状态
* 第三方公众账号通过设备id查询该id的状态(三种状态:未授权、已授权、已绑定)。
* http://iot.weixin.qq.com/wiki/document-2_7.html
* @param accessToken 调用接口凭证
* @param device_id 设备id
* @return
* 成功的Json返回结果:
*
* 设备状态,目前取值如下: 0:未授权
* 1:已经授权(尚未被用户绑定) 2:已经被用户绑定 3:属性未设置
*{
* "errcode":0,
* "errmsg":"ok",
* "status":2,
* "status_info":"bind"
*}* 失败的Json返回示例:
*{"errcode":42001,"errmsg":""}
*/
public String get_stat(String accessToken, String device_id) {
URI uri = UriComponentsBuilder.fromHttpUrl(DEVICE_GET_STATE)
.queryParam("access_token", accessToken)
.queryParam("device_id", device_id)
.build()
.encode("UTF-8")
.toUri()
ResponseEntity respEntity = wxRestTemplate.getForEntity(uri, String)
return respEntity?.body
}
/**
* 验证二维码
* 第三方后台绑定操作处理成功,通知公众平台。
* @param accessToken 调用接口凭证
* @param ticket 设备二维码的ticket
* @return
* 成功的Json返回结果:
*{
* "errcode":0,
* "errmsg":"ok",
* "device_type":"gh_xxxxxx",
* "device_id":"DEVICE_ID",
* "mac":"MAC"
*}* 失败的Json返回示例:
*{"errcode":42001,"errmsg":""}
*/
public String verify_qrcode(String accessToken, String ticket) {
URI uri = UriComponentsBuilder.fromHttpUrl(DEVICE_VERIFY_QRCODE)
.queryParam("access_token", accessToken)
.build()
.encode("UTF-8")
.toUri()
HttpHeaders headers = new HttpHeaders()
headers.setContentType(MediaType.APPLICATION_JSON)
def json = ([
"ticket": ticket,
] as JSON)
HttpEntity<String> reqEntity = new HttpEntity<String>(json.toString(), headers)
ResponseEntity respEntity = wxRestTemplate.exchange(uri, HttpMethod.POST, reqEntity, String.class)
return respEntity?.body
}
/**
* 获取设备绑定openID
* 通过device type和device id获取设备主人的openid。
* http://iot.weixin.qq.com/wiki/document-2_4.html
* @param device_type 设备类型,目前为“公众账号原始ID”
* @param accessToken 调用接口凭证
* @param device_id 设备id
* @return
* 成功的Json返回结果:
*{
* "open_id":["omN7ljrpaxQgK4NW4H5cRzFRtfa8","omN7ljtqrTZuvYLkjPEX_t_Pmmlg",],
* "resp_msg":{"ret_code":0,"error_info":"get open id list OK!"}*}* 失败的Json返回示例:
*{"errcode":42001,"errmsg":""}
*/
public String get_openid(String accessToken, String device_id, String device_type) {
URI uri = UriComponentsBuilder.fromHttpUrl(DEVICE_GET_QPENID)
.queryParam("access_token", accessToken)
.queryParam("device_id", device_id)
.queryParam("device_type", device_type)
.build()
.encode("UTF-8")
.toUri()
ResponseEntity respEntity = wxRestTemplate.getForEntity(uri, String)
return respEntity?.body
}
/**
* 获取设备绑定openID
* 通过device type和device id获取设备主人的openid。
* http://iot.weixin.qq.com/wiki/document-2_4.html
* @param device_type 设备类型,目前为“公众账号原始ID”
* @param accessToken 调用接口凭证
* @param device_id 设备id
* @return
* 成功的Json返回结果:
*{
* "resp_msg": {
* "ret_code": 0,
* "error_info": "ok"
*},
* "openid": "OPENID",
* "device_list": [
*{
* "device_type": "dt1",
* "device_id": "di1"
*}* ]
*}* 失败的Json返回示例:
*{
* "resp_msg": {
* "ret_code": -1,
* "error_info": "ERR_MSG"
*},
* "openid": "OPENID"
*}
*/
public String get_bind(String accessToken, String openid) {
URI uri = UriComponentsBuilder.fromHttpUrl(DEVICE_GET_BIND)
.queryParam("access_token", accessToken)
.queryParam("openid", openid)
.build()
.encode("UTF-8")
.toUri()
ResponseEntity respEntity = wxRestTemplate.getForEntity(uri, String)
return respEntity?.body
}
/**
* 获取设备的运⾏状态
* http://iot.weixin.qq.com/wiki/doc/hardwarecloud/openapi.pdf
* @param accessToken 公众号调⽤接⼜的凭证
* @param device_type 设备所属的公众号的原始ID
* @param device_id 设备ID
* @param services 欲查询的能⼒项及属性
* @param user ⽤户的openid
* @param data 可以⾃⾏填写任意内容,微信 平台将进⾏透传
* @return
回包格式:{
"error_code": 0, //0代表成功
"error_msg": "ok",
"msg_id" : "xxx"
}
*/
public String get_status(String accessToken, String device_type, String device_id, String services, String user, String data) {
URI uri = UriComponentsBuilder.fromHttpUrl(MY_DEVICE_GET_STATUS)
.queryParam("access_token", accessToken)
.build()
.encode("UTF-8")
.toUri()
HttpHeaders headers = new HttpHeaders()
headers.setContentType(MediaType.APPLICATION_JSON)
def json = ([
"device_type": device_type,
"services" : services,
"user" : user,
"data" : data,
"device_id" : device_id
] as JSON)
HttpEntity<String> reqEntity = new HttpEntity<String>(json.toString(), headers)
ResponseEntity respEntity = wxRestTemplate.exchange(uri, HttpMethod.POST, reqEntity, String.class)
return respEntity?.body
}
/**
* 设备控制
* 应⽤端POST设置消息到微信云,微信云⽴即回复收到。当设备设置成功后,微信云发送响应消息通知应⽤端成功处理。
* http://iot.weixin.qq.com/wiki/doc/hardwarecloud/openapi.pdf
* @param accessToken 公众号调⽤接⼜的凭证
* @param device_type 设备所属的公众号的原始ID
* @param device_id 设备ID
* @param services 欲查询的能⼒项及属性
* @param user ⽤户的openid
* @param data 可以⾃⾏填写任意内容,微信 平台将进⾏透传
* @return
*
回包格式:{
"error_code": 0,//0代表成功
"error_msg": "ok",
"msg_id" : "xxx"
}
*/
public String ctrl(String accessToken, String device_type, String device_id, String services, String user, String data) {
URI uri = UriComponentsBuilder.fromHttpUrl(MY_DEVICE_CTRL)
.queryParam("access_token", accessToken)
.build()
.encode("UTF-8")
.toUri()
HttpHeaders headers = new HttpHeaders()
headers.setContentType(MediaType.APPLICATION_JSON)
def json = ([
"device_type": device_type,
"services" : services,
"user" : user,
"data" : data,
"device_id" : device_id
] as JSON)
HttpEntity<String> reqEntity = new HttpEntity<String>(json.toString(), headers)
ResponseEntity respEntity = wxRestTemplate.exchange(uri, HttpMethod.POST, reqEntity, String.class)
return respEntity?.body
}
}