这是一个node.js版本的demo,用于对接开关的API接口,可以控制开关的开和关,还有获取开关的状态 数据传输过程使用discuz加解密方法,个人密匙可以自己配置
//POST URL 接口地址
var urlstr = 'https://wx663ca7ac2632b137.vip.aoyacms.com/plugin/aoya/iot/api.php';
var key = 'd0d3d5b5466cc1ee89eb808de9f5672d';//个人密匙
var mid = '5b53a2d341d78427feafeb4520bf41eb';//设备密匙
//数据发送方法
function post(urlstr,data){
var querystring = require('querystring');
var url = require('url');
var http = require('http');
var https = require('https');
var util = require('util');
var bodyQueryStr = data;
var contentStr = querystring.stringify(bodyQueryStr);
var contentLen = Buffer.byteLength(contentStr, 'utf8');
//console.log(util.format('post data: %s, with length: %d', contentStr, contentLen));
var httpModule = urlstr.indexOf('https') === 0 ? https : http;
var urlData = url.parse(urlstr);
//HTTP请求选项
var opt = {
hostname: urlData.hostname,
path: urlData.path,
method: 'POST',
headers: {'Content-Type': 'application/x-www-form-urlencoded','Content-Length': contentLen}
};
//处理事件回调
var req = httpModule.request(opt, function(httpRes) {
var buffers = [];
httpRes.on('data', function(chunk) {
buffers.push(chunk);
});
httpRes.on('end', function(chunk) {
var wholeData = Buffer.concat(buffers);
var dataStr = wholeData.toString('utf8');
//console.log('content ' + wholeData);
});
}).on('error', function(err) {
//console.log('error ' + err);
});
//写入数据,完成发送
req.write(contentStr);
req.end();
}
//加解密方法
function authcode(str, operation, key, expiry) {
var operation = operation ? operation : 'DECODE';
var key = key ? key : '';
var expiry = expiry ? expiry : 0;
var ckey_length = 4;
key = md5(key);
// 密匙a会参与加解密
var keya = md5(key.substr(0, 16));
// 密匙b会用来做数据完整性验证
var keyb = md5(key.substr(16, 16));
// 密匙c用于变化生成的密文
var keyc = ckey_length ? (operation == 'DECODE' ? str.substr(0, ckey_length): md5(microtime()).substr(-ckey_length)) : '';
// 参与运算的密匙
var cryptkey = keya+md5(keya+keyc);
var strbuf;
if(operation == 'DECODE') {
str = str.substr(ckey_length);
strbuf = new Buffer(str,'base64');
//string = b.toString();
}
else {
expiry = expiry ? expiry + time() : 0;
tmpstr = expiry.toString();
if(tmpstr.length>=10)
str = tmpstr.substr(0,10)+md5(str+keyb).substr(0, 16)+str;
else {
var count = 10 - tmpstr.length;
for(var i=0;i<count;i++) {
tmpstr = '0'+tmpstr;
}
str = tmpstr+md5(str+keyb).substr(0, 16)+str;
}
strbuf = new Buffer(str);
}
var box = new Array(256);
for(var i=0; i < 256; i++) {
box[i] = i;
}
var rndkey = new Array();
// 产生密匙簿
for(var i=0; i < 256; i++) {
rndkey[i] = cryptkey.charCodeAt(i % cryptkey.length);
}
// 用固定的算法,打乱密匙簿,增加随机性,好像很复杂,实际上对并不会增加密文的强度
for(var j = i = 0; i < 256; i++) {
j = (j + box[i] + rndkey[i]) % 256;
tmp = box[i];
box[i] = box[j];
box[j] = tmp;
}
// 核心加解密部分
var s = '';
for(var a = j = i = 0; i < strbuf.length; i++) {
a = (a + 1) % 256;
j = (j + box[a]) % 256;
tmp = box[a];
box[a] = box[j];
box[j] = tmp;
// 从密匙簿得出密匙进行异或,再转成字符
//s += String.fromCharCode(string[i] ^ (box[(box[a] + box[j]) % 256]));
strbuf[i] = strbuf[i] ^ (box[(box[a] + box[j]) % 256])
}
if(operation == 'DECODE') {
var s = strbuf.toString();
if((s.substr(0, 10) == 0 || s.substr( 0, 10) - time() > 0) && s.substr(10, 16) == md5(s.substr(26)+keyb).substr(0, 16)) {
s = s.substr(26);
} else {
s = '';
}
}
else {
var s = strbuf.toString('base64');
var regex = new RegExp('=', "g");
s = s.replace(regex, '');
s = keyc+s;
}
return s;
}
function md5(str){
var hash = require('crypto').createHash('md5');
return hash.update(str+"").digest('hex');
//return hex_md5(str);
}
function time() {
var unixtime_ms = new Date().getTime();
return parseInt(unixtime_ms / 1000);
}
function microtime(get_as_float) {
var unixtime_ms = new Date().getTime();
var sec = parseInt(unixtime_ms / 1000);
return get_as_float ? (unixtime_ms/1000) : (unixtime_ms - (sec * 1000))/1000 + ' ' + sec;
}
var t = time();//时间秒数
var info = {
"act" : "switch"// switch 控制设备开关 getState获取开关状态
};
var json = JSON.stringify(info);
var ciphertext = authcode(json,'ENCODE',key);
var check = md5(t + mid + ciphertext);
var data = {
"t" : t,
"mid" : mid,
"ciphertext" : ciphertext,
"check" : check
};
post(urlstr,data);
|