金意芳台球馆 API 文档

* 欢迎来到莆田市秀屿区南日金意芳台球馆。
* 管理员【点此】可以获取台球桌二维码(请手工在网址中指定桌号)
BuyInfo: 价格信息
@form { }
第一次请求将初始化数据库
[检视源码]
function() {
	try { return db().query("select * from buyinfo"); }
	catch(err) { return initDb(), this.buyinfo(); }
}
Login: 管理员登录
@form { pass }
用于 API 页面的管理登录
[检视源码]
function() {
	if(form("pass") != sys.adminPass) return { err: "登录失败" };
	var user = db().fetch("select * from users where userid=1");
	if(!user) return { err: "暂时不存在管理账户" };
	me().bind(user); return user;
}
Recharge: 充入通电时长
@form { deskid, sec }
管理员给指定桌号充入通电时长(单位:秒)
[检视源码]
function() {
	if(!sys.isadmin) return { err: "没有权限" };
	var deskid = ~~form("deskid"), sec = ~~form("sec");
	// 获取桌号信息
	var rs = db().fetch("select * from deskball where deskid=?", [ deskid ]);
	if(!rs) return { err: "找不到此桌号" };
	var remain = sys.sTime - rs.etime;
	var isNew = remain >= 0, task = getTask();
	// 如果不是新开电操作,则先取消旧的关电任务
	if(!isNew) {
	task.delTask(rs.deskid);
	dbg().trace(rs.deskid + " 号桌续期 " + sec + " 秒。");
	}
	else dbg().trace(rs.deskid + " 号桌开始计时,本次时长 " + sec + " 秒");
	var data = { power: 1 };
	if(isNew) data.stime = sys.sTime.getVarDate();
	// 如果是续期,则在原来的基础上增加时长
	data.etime = new Date((isNew ? sys.sTime : rs.etime) - 0 + sec * 1000).getVarDate();
	dbg().trace("结束时间:" + tojson(data.etime).slice(1, -1));
	// 定时关灯
	task.addTask(data.etime - sys.sTime, rs.deskid);
	db().update("deskball", data, { deskid: rs.deskid });
	return rechargePower(deskid, sec, remain);
}
GetDeskPower: 查询台球桌供电状态
@form { deskid }
[检视源码]
function() {
	if(!sys.isadmin) return { err: "没有权限" };
	var desk = db().fetch("select * from deskball where deskid=?", [ ~~form("deskid") ]);
	if(!desk) return { err: "找不到桌号" };
	var url = "https://gateway.biandianxia.com/sharedevice/status?gateway=";
	url += sys.wifiGate.uuid + "&appkey=" + sys.wifiGate.key;
	url += "&deviceid=" + desk.deviceid + "&UUID=" + desk.uuid;
	var res = fromjson(ajax(url));
	if(!res.data) return res;
	var mode = toInt(40, 2) / 128 >= 1;
	return {
	flag: String.fromCharCode(toInt(18, 2) || 32),
	deviceid: toInt(24, 6),
	status: toInt(30, 2),
	chargeid: toInt(32, 8),
	mode: mode ? "电量" : "时长",
	remain: mode ? toInt(41, 5) : toInt(40, 6),
	quantity: toInt(46, 6),
	check: res.data.substr(52, 8),
	raw: res.data
	};
	function toInt(start, len) { len = parseInt(res.data.substr(start, len), 16); return isNaN(len) ? "" : len; }
}
Home: 首页数据
@form { deskid }
[检视源码]
function() {
	if(!me().isLogin) return { err: "需要登录" };
	var rs = { goods: this.buyinfo(), isadmin: sys.isadmin };
	// rs.goods[0].hour += "." + me().userid;
	var deskid = ~~form("deskid");
	if(!deskid) return rs;
	// 查询桌号信息及剩余时间
	var desk = db().fetch("select etime from deskball where deskid=?", [ deskid ]) || { etime: 0 };
	rs.expr = desk.etime - sys.sTime; if(rs.expr < 0) rs.expr = 0;
	return rs;
}
MakePay: 生成支付参数
@form { deskid, priceid }
[检视源码]
function() {
	if(!me().isLogin) return { err: "需要登录" };
	var deskid = ~~form("deskid"), priceid = ~~form("priceid");
	var pay = db().scalar("select price from buyinfo where id=?", [ priceid ]);
	if(!pay) return { err: "缺少价格信息" };
	return wxcashier(pay * 100, "WxBack/" + deskid + "/" + priceid + "/" + me().userid, env("URL"), sys.name);
}
WxCode: 微信 code 换取 openid
@form { code }
[检视源码]
function() {
	var rs = ajax("https://api.weixin.qq.com/sns/jscode2session?appid=" + sys.wx.id + "&secret=" + sys.wx.secret + "&js_code=" + form("code") + "&grant_type=authorization_code");
	rs = fromjson(rs) || new Object;
	if(!rs.openid) return { err: rs.errmsg || "登录未知错误" };
	function getUser() {
	var user = db().fetch("select * from users where openid=?", [ rs.openid ]);
	if(user) return user;
	db().insert("users", { openid: rs.openid });
	return getUser();
	}
	var user = getUser();
	return me().bind(user), { userid: user.userid };
}
WxBack: 微信支付回调
@form { json }
WxBack/桌号/购买ID/用户ID
[检视源码]
function() {
	if(!sys.answer) sys.answer = function(code, msg) { return { err: msg }; };
	var json = sys.form || fromjson(form("json"));
	if(!json) return sys.answer("FAIL", "非微信支付回调");
	if(!json.sign) return sys.answer("FAIL", "缺少支付签名");
	var sign = json.sign; delete json.sign;
	if(wxpaysign(json, sys.mch.key) != sign) return dbg().trace("签名验证失败", json), sys.answer("FAIL", "签名校验失败");
	json.sign = sign;
	// 判断是否重复支付
	if(db().fetch(
	"select * from orders where tradewx=?", [ json.transaction_id ]
	)) return dbg().trace("重复通知", json), sys.answer("SUCCESS", "OK");	// 重复通知
	var route = json.attach.split("/");
	// 获取桌号和购买信息
	var rs = db().table("(select cast(? as int) as deskid, cast(? as int) as buyid) a").
	join("deskball b on b.deskid=a.deskid").join("buyinfo c on c.id=a.buyid").
	select("b.*, c.hour").fetch([ ~~route[1], ~~route[2] ]);
	// 插入订单记录
	db().insert("orders", {
	tradeno: json.out_trade_no, tradewx: json.transaction_id, deskid: rs.deskid,
	userid: ~~route[3], ext: tojson(json), fee: json.total_fee, hour: rs.hour
	});
	var remain = sys.sTime - rs.etime;
	var isNew = remain > 0, task = getTask();
	// 如果不是新开电操作,则先取消旧的关电任务
	if(!isNew) {
	task.delTask(rs.deskid);
	dbg().trace(rs.deskid + " 号桌续期 " + rs.hour + " 小时。");
	}
	else dbg().trace(rs.deskid + " 号桌开始计时,本次时长 " + rs.hour + " 小时");
	var data = { userid: ~~route[3], power: 1 };
	if(isNew) data.stime = sys.sTime.getVarDate();
	// 如果是续期,则在原来的基础上增加时长
	data.etime = new Date((isNew ? sys.sTime : rs.etime) - 0 + rs.hour * 36e5).getVarDate();
	dbg().trace("结束时间:" + tojson(data.etime).slice(1, -1));
	// 定时关灯
	task.addTask(data.etime - sys.sTime, rs.deskid);
	db().update("deskball", data, { deskid: rs.deskid });
	// 调用开灯 API
	rechargePower(rs.deskid, rs.hour * 3600, remain);
	return sys.answer("SUCCESS", "OK");;
}
SetPower: 电源开关
@form { deskid, state }
deskid 为 桌子编号
0: 断电; 1: 通电
* 设备自带定时断电,此接口实际仅用于定时断电提示。
[检视源码]
function() {
	// dbg().trace(form(), "来自 " + origin + env("REMOTE_ADDR") + " 的请求");
	if(env("REMOTE_ADDR") != sys.whiteIP) return { err: "您没有权限调用此接口" };
	var deskid = ~~form("deskid"), state = form("state");
	db().update("deskball", { power: state }, { deskid: deskid });
	// 调用关灯 API
	return dbg().trace("桌号 " + deskid + " 已关闭电源。"), { msg: "OK" };
}
SavePrice: 保存价格
@form { [id], hour, price }
[检视源码]
function() {
	if(!me().isLogin) return { err: "需要登录" };
	if(!sys.isadmin) return { err: "没有权限" };
	var id = ~~form("id"), hour = ~~form("hour"), price = ~~form("price");
	var data = { hour: hour, price: price };
	if(!id) return db().insert("buyinfo", data), { msg: "添加成功" };
	return db().update("buyinfo", data, { id: id }), { msg: "修改成功" };
}
DropPrice: 删除价格信息
@form { id }
[检视源码]
function() {
	if(!me().isLogin) return { err: "需要登录" };
	if(!sys.isadmin) return { err: "没有权限" };
	db().query("delete from buyinfo where id=?", [ ~~form("id") ]);
	return { msg: "删除成功" };
}
SaveDesk: 保存台球桌信息
@form { deskid, deviceid, uuid }
deskid: 桌号
deviceid:电控设备编号
uuid: 控制器机器码
[检视源码]
function() {
	if(!sys.isadmin) return { err: "没有权限" };
	var deskid = ~~form("deskid");
	var data = { deviceid: form("deviceid"), uuid: form("uuid") };
	// 判断桌号原来是否存在
	var desk = db().fetch("select * from deskball where deskid=?", [ deskid ]);
	if(desk) return db().update("deskball", data, { deskid: deskid }), { msg: "修改成功" };
	data.deskid = deskid;
	return db().insert("deskball", data), { msg: "添加成功" };
}
PayStat: 统计当日收入情况
@form { }
[检视源码]
function() {
	if(!sys.isadmin) return { err: "没有权限" };
	var date = new Date; date.setHours(0, 0, 0, 0);
	return db().table("orders").groupby("deskid").where("paytime>=?").
	select("deskid, sum(fee) as income, sum(hour) as hours").
	astable("a").orderby("income desc, deskid").query([ date.getVarDate() ]);
}
PayList: 支付列表
@form { [page], [size] }
[检视源码]
function() {
	if(!sys.isadmin) return { err: "没有权限" };
	var pays = db().table("orders").page("ordid desc", form("size") || 5, form("page")).query();
	return { pays: pays, pager: db().pager };
}
DeskList: 台球桌列表
@form { [page], [size] }
[检视源码]
function() {
	if(!sys.isadmin) return { err: "没有权限" };
	var desks = db().table("deskball").page("deskid", form("size") || 5, form("page")).query();
	return { desks: desks, pager: db().pager };
}
UserList: 查看用户列表
@form { page, size }
[检视源码]
function() {
	if(!sys.isadmin) return { err: "没有权限" };
	var users = db().table("users").page("userid desc", form("size") || 5, form("page")).query();
	return { users: users, pager: db().pager };
}
参数录入
执行
取消