Import "Cjson.lua"
Import "ShanHai.lua"
Thread.SetShareVar "请求地址", "https://api.yankami.cn/"
Thread.SetShareVar "项目ID", ""
Thread.SetShareVar "项目秘钥", ""
Thread.SetShareVar "卡密", ""
//首次验证会保存到期时间,首次验证失败会停止!
Thread.SetShareVar "验证超时分钟", 1440//可调整
Thread.SetShareVar "验证心跳频秒", 10//可调整
Thread.SetShareVar "验证时间", False//变量需要 不要调整
Thread.SetShareVar "获取卡密到期时间", False//变量需要 不要调整
Thread.SetShareVar "设备编号", GetDeviceID()
//【主线程方式一】发送验证 等待返回 需要在主方法中循环调用来验证到期时间
Function 验证卡密()
获取卡密信息()
End Function
//【主线程方式二】在休眠时验证 参数:休眠毫秒 减去等待时间 需要在主方法中循环调用来验证到期时间
Function 休眠验证(s)
Dim 开始时间 = TickCount()
获取卡密信息()
Delay s + (开始时间 - TickCount())
End Function
//主线程
Do
验证卡密()
Delay 1000
Loop
Function 获取卡密信息()
Dim timeStamp = Time()
Dim sign = Encode.Md5(Thread.GetShareVar("项目ID")&Thread.GetShareVar("项目秘钥")&timeStamp)
If not Thread.GetShareVar("获取卡密到期时间") or TickCount() - Thread.GetShareVar("验证时间") >= (Thread.GetShareVar("验证心跳频秒") * 1000) or Thread.GetShareVar("获取卡密到期时间") and timeStamp > Thread.GetShareVar("获取卡密到期时间") Then
If not Thread.GetShareVar("获取卡密到期时间") Then
For 1
If Len(Thread.GetShareVar("卡密")&"") = 0 Then
Dialog.MsgBox("\t\t\t\t\t\t\t 提示:请输入卡密!",0)
ElseIf Len(Thread.GetShareVar("卡密")&"") < 8 or Len(Thread.GetShareVar("卡密")&"") > 40 Then
Dialog.MsgBox("\t\t\t\t\t 提示:请输正确的卡密!",0)
ElseIf Len(Thread.GetShareVar("设备编号")&"") < 5 or Len(Thread.GetShareVar("设备编号")&"") > 50 Then
Dialog.MsgBox("\t\t\t\t\t\t\t\t\t 设备编号错误:"&Len(Thread.GetShareVar("设备编号")&""),0)
Else
Exit For
End If
EndScript//停止辅助
Next
End If
//获取卡密信息
Dim 请求返回 = ""&URL.Get(Thread.GetShareVar("请求地址")&"km?xmid="&Thread.GetShareVar("项目ID")&"&km="&Thread.GetShareVar("卡密")&"&jqm="&Thread.GetShareVar("设备编号")&"&updateJqm=1"&"&timeStamp="&timeStamp&"&sign="&sign,5)
TracePrint "获取卡密信息:"&请求返回
If InStr(1, 请求返回, "{") <> 1 or InStr(1, 请求返回, "code") = 0 Then
//如果是首次验证失败停止 或者 验证超时提示验证失败停止
If not Thread.GetShareVar("获取卡密到期时间") or TickCount() - Thread.GetShareVar("验证时间") >= Thread.GetShareVar("验证超时分钟") * (1000 * 60) Then
Dialog.MsgBox("\t\t\t\t\t\t\t验证失败,请重新运行!",0)
EndScript//停止辅助
End If
If timeStamp > Thread.GetShareVar("获取卡密到期时间") Then
TracePrint "卡密已经到期"
Dialog.MsgBox("\t\t\t\t\t\t\t 提示:卡密已经到期!",0)
EndScript//停止辅助
End If
Else
//JSON字符串转换为Table
Dim json = Cjson.Decode(请求返回)
If json["code"] = 201 Then
TracePrint "卡密不存在"
Dialog.MsgBox("\t\t\t\t\t\t\t\t提示:卡密不存在!",0)
EndScript//停止辅助
ElseIf json["code"] = 202 Then
TracePrint "项目已经停用"
Dialog.MsgBox("\t\t\t\t\t\t\t 提示:项目已经停用!",0)
EndScript//停止辅助
ElseIf json["code"] = 203 Then
TracePrint "卡密已经到期"
Dialog.MsgBox("\t\t\t\t\t\t\t 提示:卡密已经到期!",0)
EndScript//停止辅助
ElseIf json["code"] = 204 Then
TracePrint "卡密绑定了其他设备!"
Dialog.MsgBox("\t\t\t\t提示:卡密绑定了其他设备!", 0)
EndScript//停止辅助
ElseIf json["code"] <> 200 Then
Dialog.MsgBox("\t\t\t\t\t\t\t验证失败,请重新运行!",0)
EndScript//停止辅助
Else
Dim dataText = json["data"]
TracePrint "数据:"&dataText
//服务器返回校验
Dim serviceSign = json["sign"]
Dim localSign = Mid(Encode.Md5(Thread.GetShareVar("项目ID")&Thread.GetShareVar("项目秘钥")&ShanHai.Base64En(dataText)&timeStamp),1,4)
TracePrint "serviceSign:"&serviceSign
TracePrint "localSign:"&localSign
If not localSign = serviceSign Then
TracePrint "非法的返回!"
Dialog.MsgBox("\t\t\t\t\t\t\t\t提示:非法的返回!",0)
EndScript//停止辅助
Else
TracePrint "成功的返回!"
End If
//JSON字符串转换为Table
Dim data = Cjson.Decode(dataText)
If not Thread.GetShareVar("获取卡密到期时间") Then
//首次验证提示
Dialog.MsgBox("\t\t\t卡密到期日期:"&DateTime.Format("%Y-%m-%d %H:%M:%S",data["dqsj"]),0)
End If
Thread.SetShareVar "验证时间", TickCount()
Thread.SetShareVar "获取卡密到期时间", data["dqsj"]
End If
End If
Else
TracePrint "下次获取卡密信息:"&(Thread.GetShareVar("验证心跳频秒") * 1000) - (TickCount() - Thread.GetShareVar("验证时间"))
End If
End Function
Dim 项目ID,项目秘钥,卡密,设备编号,验证超时分钟,验证心跳频秒,验证时间,获取卡密到期时间
项目ID = ""
项目秘钥 = ""
卡密 = ""
//首次验证会保存到期时间,首次验证失败会停止!
验证超时分钟 = 1440//可调整
验证心跳频秒 = 10//可调整
验证时间 = False//变量需要 不要调整
获取卡密到期时间 = False//变量需要 不要调整
设备编号 = CStr(Plugin.Sys.GetHDDSN())
//主线程
Do
Call 获取卡密信息()
Delay 1000
loop
Function 获取卡密信息()
Dim timeStamp,sign,请求地址,请求URL,响应内容,状态,数据,到期时间,本地校验,服务器校验
timeStamp = getTime()
sign = Plugin.Encrypt.Md5String(项目ID&项目秘钥&timeStamp)
If 获取卡密到期时间 = False or getTime() - 验证时间 >= 验证心跳频秒 or (获取卡密到期时间 and timeStamp > 获取卡密到期时间) Then
TracePrint "时间戳:"&timeStamp
If 获取卡密到期时间 = False Then
For 1
If Len(卡密&"") = 0 Then
MessageBox "提示:请输入卡密!"
ElseIf Len(卡密&"") < 8 or Len(卡密&"") > 40 Then
MessageBox "提示:请输正确的卡密!"
ElseIf Len(设备编号&"") < 5 or Len(设备编号&"") > 50 Then
MessageBox "设备编号错误:"&Len(设备编号&"")
Else
Exit For
End If
ExitScript//停止辅助
Next
End If
请求地址 = "http://api.yankami.cn/km"
请求URL = 请求地址&"?xmid="&项目ID&"&km="&卡密&"&jqm="&设备编号&"&updateJqm=1"&"&timeStamp="&timeStamp&"&sign="&sign
TracePrint "请求卡密 URL:"&请求URL
响应内容 = Lib.网络.获得网页源文件_增强版(请求URL,"utf-8")
TracePrint "响应内容:"&响应内容
If InStr(1, 响应内容, "{") <> 1 or InStr(1, 响应内容, "code") = 0 Then
//如果是首次验证失败停止 或者 验证超时提示验证失败停止
If 获取卡密到期时间 = False or getTime() - 验证时间 >= 验证超时分钟 * (1000 * 60) Then
MessageBox "验证失败,请重新运行!"
ExitScript//停止辅助
End If
If timeStamp > 获取卡密到期时间 Then
TracePrint "提示:卡密已经到期!"
MessageBox "提示:卡密已经到期!"
ExitScript//停止辅助
End If
Else
状态 = json解析(响应内容, "code")
TracePrint "状态:"&状态
If 状态 = 201 Then
TracePrint "提示:卡密不存在!"
MessageBox "提示:卡密不存在!"
ExitScript//停止辅助
ElseIf 状态 = 202 Then
TracePrint "提示:项目已经停用!"
MessageBox "提示:项目已经停用!"
ExitScript//停止辅助
ElseIf 状态 = 203 Then
TracePrint "提示:卡密已经到期!"
MessageBox "提示:卡密已经到期!"
ExitScript//停止辅助
ElseIf 状态 = 204 Then
TracePrint "提示:卡密绑定了其他设备!"
MessageBox "提示:卡密绑定了其他设备!"
ExitScript//停止辅助
ElseIf 状态 <> 200 Then
TracePrint "提示:验证失败,请重新运行!"
MessageBox "提示:验证失败,请重新运行!"
ExitScript//停止辅助
Else
数据 = json解析(响应内容, "data")
TracePrint "数据:"&数据
//服务器返回校验
服务器校验 = json解析(响应内容, "sign")
本地校验 = Mid(LCase(Plugin.Encrypt.Md5String(项目ID&项目秘钥&Base64Encode(数据)&timeStamp)),1,4)
TracePrint "本地校验:"&本地校验
TracePrint "服务器校验:"&服务器校验
If not 本地校验 = 服务器校验 Then
MessageBox "非法的返回!"
ExitScript//停止辅助
End If
到期时间 = json解析(数据, "dqsj")
TracePrint "到期时间:"&到期时间
If 获取卡密到期时间 = False Then
Dim 首次验证提示卡密到期时间
首次验证提示卡密到期时间 = dateTimeToFormat(到期时间)
//首次验证提示
TracePrint "到期时间:"&首次验证提示卡密到期时间
MessageBox "到期时间:"&首次验证提示卡密到期时间
End If
验证时间 = getTime()
获取卡密到期时间 = 到期时间
End If
End If
Else
TracePrint "下次获取卡密信息:"&验证心跳频秒 - (getTime() - 验证时间)
End If
End Function
Function Base64Encode(Str)
Dim BASE64_CHARS
BASE64_CHARS = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"
Dim length, modValue, result, i, a, b, c, d
Str = StringToByteArray(Str)
length = UBound(Str) + 1
modValue = length Mod 3
result = ""
For i = 0 To length - modValue - 1 Step 3
a = (Str(i) And &HFC) \ &H4
b = ((Str(i) And &H3) * &H10) Or ((Str(i + 1) And &HF0) \ &H10)
c = ((Str(i + 1) And &HF) * &H4) Or ((Str(i + 2) And &HC0) \ &H40)
d = Str(i + 2) And &H3F
result = result & Mid(BASE64_CHARS, a + 1, 1)
result = result & Mid(BASE64_CHARS, b + 1, 1)
result = result & Mid(BASE64_CHARS, c + 1, 1)
result = result & Mid(BASE64_CHARS, d + 1, 1)
Next
If modValue = 1 Then
a = (Str(length - 1) And &HFC) \ &H4
b = (Str(length - 1) And &H3) * &H10
result = result & Mid(BASE64_CHARS, a + 1, 1)
result = result & Mid(BASE64_CHARS, b + 1, 1)
result = result & "=="
ElseIf modValue = 2 Then
a = (Str(length - 2) And &HFC) \ &H4
b = ((Str(length - 2) And &H3) * &H10) Or ((Str(length - 1) And &HF0) \ &H10)
c = (Str(length - 1) And &HF) * &H4
result = result & Mid(BASE64_CHARS, a + 1, 1)
result = result & Mid(BASE64_CHARS, b + 1, 1)
result = result & Mid(BASE64_CHARS, c + 1, 1)
result = result & "="
End If
Base64Encode = result
End Function
//字符串转数组
Function StringToByteArray(szInput)
Dim i, byteArray, wch, nAsc
byteArray = ""
For i=1 To Len(szInput)
wch = Mid(szInput, i, 1)
nAsc = AscW(wch)
If nAsc < 0 Then
nAsc = nAsc + 65536
End If
If (nAsc And &HFF80) = 0 Then
byteArray = byteArray & "," & AscW(wch)
Else
If (nAsc And &HF000) = 0 Then
byteArray = byteArray & "," & Cint("&H" & Hex(((nAsc \ 2 ^ 6)) Or &HC0)) - 256 & "," & Cint("&H" & Hex(nAsc And &H3F Or &H80))-256
Else
byteArray = byteArray & "," & Cint("&H" & Hex((nAsc \ 2 ^ 12) Or &HE0)) - 256 & "," & Cint("&H" & Hex((nAsc \ 2 ^ 6) And &H3F Or &H80)) - 256 & "," & Cint("&H" & Hex(nAsc And &H3F Or &H80)) - 256
End If
End If
Next
If Left(byteArray, 1) = "," Then
byteArray = Right(byteArray, Len(byteArray) - 1)
End If
StringToByteArray = Split(byteArray, ",")
End Function
Function json解析(resp,json路径)
Set sc = CreateObject("MSScriptControl.ScriptControl")
sc.Language = "JScript"
sc.AddCode "var tmp = " & resp & ";"
json解析 = sc.Eval("tmp." & json路径)
End Function
Function getTime()
Dim sc
Set sc = CreateObject("MSScriptControl.ScriptControl")
sc.Language = "JScript"
getCurrentTimestamp = sc.Eval("Math.floor(new Date().getTime() / 1000)")
End Function
Function dateTimeToFormat(time)
If Len(time) = 10 Then
time = time * 1000
End If
Dim sc, jsCode
Set sc = CreateObject("MSScriptControl.ScriptControl")
sc.Language = "JScript"
jsCode = "var d = new Date(" & time & ");"
jsCode = jsCode & "var y = d.getFullYear();"
jsCode = jsCode & "var m = ('0' + (d.getMonth()+1)).slice(-2);"
jsCode = jsCode & "var dd = ('0' + d.getDate()).slice(-2);"
jsCode = jsCode & "var h = ('0' + d.getHours()).slice(-2);"
jsCode = jsCode & "var min = ('0' + d.getMinutes()).slice(-2);"
jsCode = jsCode & "var s = ('0' + d.getSeconds()).slice(-2);"
jsCode = jsCode & "y + '-' + m + '-' + dd + ' ' + h + ':' + min + ':' + s;"
jsCode = jsCode & "var y = d.getFullYear();"
timestampToDateTime = sc.Eval(jsCode)
End Function
local 请求地址 = "https://api.yankami.cn/"
local 项目ID = ""
local 项目秘钥 = ""
local 卡密 = ""
local 验证超时分钟 = 1440--可调整
local 验证心跳频秒 = 10--可调整
local 验证时间 = false--变量需要 不要调整
local 获取卡密到期时间 = false--变量需要 不要调整
local 设备编号 = "LanRen" .. os.time()
function 获取卡密信息()
local timeStamp = os.time()
if not 获取卡密到期时间 or tickCount() - 验证时间 >= (验证心跳频秒 * 1000) or 获取卡密到期时间 and timeStamp > 获取卡密到期时间 then
if not 卡密 then
print("请输入卡密!")
toast("请输入卡密!")
restartScript()
end
local sign = MD5(项目ID .. 项目秘钥 .. timeStamp);
local ret, code = httpPost(请求地址 .. "km", "xmid=" .. 项目ID .. "&km=" .. 卡密 .. "&jqm=" .. 设备编号 .. "&updateJqm=1" .. "&timeStamp=" .. timeStamp .. "&sign=" .. sign)
print("获取卡密信息:" .. ret)
if code ~= 200 or not (utf8.mid(ret, 1, 1) == "{" and utf8.mid(ret, utf8.length(ret), 1) == "}") then
if not 获取卡密到期时间 or tickCount() - 验证时间 >= (验证超时分钟 * 1000 * 60) then
print("验证失败,请重新运行!")
toast("验证失败,请重新运行!")
restartScript()
end
if timeStamp > 获取卡密到期时间 then
print("卡密已经到期!")
toast("卡密已经到期!")
restartScript()
end
else
ret = jsonLib.decode(ret)
if ret.code == 201 then
print("卡密不存在!")
toast("卡密不存在!")
restartScript()
elseif ret.code == 202 then
print("项目已经停用!")
toast("项目已经停用!")
restartScript()
elseif ret.code == 203 then
print("卡密已经到期!")
toast("卡密已经到期!")
restartScript()
elseif ret.code == 204 then
while true do
print("卡密绑定了其他设备!")
toast("卡密绑定了其他设备!")
sleep(1000)
end
elseif ret.code ~= 200 then
print("验证失败,请重新运行!")
toast("验证失败,请重新运行!")
restartScript()
else
local serviceSign = ret.sign
local localSign = string.sub(MD5(项目ID .. 项目秘钥 .. encodeBase64(ret.data) .. timeStamp), 1, 4)
print("serviceSign:" .. serviceSign)
print("localSign:" .. localSign)
if not (string.lower(serviceSign) == string.lower(localSign)) then
print("非法的返回!")
toast("非法的返回!")
restartScript()
end
local data = jsonLib.decode(ret.data)
if not 获取卡密到期时间 then
local dqsj = os.date("%Y-%m-%d %H:%M:%S", data.dqsj)
print("卡密到期日期:" .. dqsj)
toast("卡密到期日期:" .. dqsj)
sleep(1000)
end
验证时间 = tickCount()
获取卡密到期时间 = data.dqsj
end
end
else
print("下次获取卡密信息:" .. ((验证心跳频秒 * 1000) - (tickCount() - 验证时间)))
end
end
--验证并休眠
function 验证卡密(ms)
local 开始时间 = tickCount()
获取卡密信息()
local 结束时间 = tickCount()
local delay = ms + (开始时间 - 结束时间)
if delay > 0 then
sleep(delay)
end
end
--主代码
while true do
--循环调用验证
验证卡密(1000)
end
var 请求地址 = "https://api.yankami.cn/"
var 项目ID = ""
var 项目秘钥 = ""
var 卡密 = ""
//首次验证会保存到期时间,首次验证失败会停止!
var 验证超时分钟 = 60//可调整
var 验证心跳频秒 = 10//可调整
var 验证时间 = false//变量需要 不要调整
var 获取卡密到期时间 = false//变量需要 不要调整
var 设备编号 = DeviceWrapper.prototype.getAndroidId()
while (true) {
获取卡密信息()
sleep(1000)
}
function 获取卡密信息() {
var timeStamp = parseInt(new Date().getTime() / 1000)
console.log("timeStamp:" + timeStamp)
var sign = UtilsWrapper.prototype.dataMd5(项目ID + 项目秘钥 + timeStamp)
验证心跳频秒 = 验证心跳频秒 < 1 ? 1 : 验证心跳频秒
if (!验证时间 || new Date().getTime() - 验证时间 >= 验证心跳频秒 * 1000 || timeStamp && timeStamp > 获取卡密到期时间 * 1000) {
var 请求返回 = sendGet(请求地址 + "km?xmid=" + 项目ID + "&km=" + 卡密 + "&jqm=" + 设备编号 + "&updateJqm=1" + "&timeStamp=" + timeStamp + "&sign=" + sign)
console.log("获取卡密信息:" + 请求返回)
if (!请求返回.startsWith("{") || !请求返回.endsWith("}")) {
if (!获取卡密到期时间 || parseInt((new Date().getTime() - 验证时间) / 1000) >= 验证超时分钟 * (1000 * 60)) {
console.log("验证失败,请重新运行!")
toast("验证失败,请重新运行!")
sleep(1000)
exit()//停止辅助
}
if (new Date().getTime() > 获取卡密到期时间 * 1000) {
console.log("卡密已经到期!")
toast("卡密已经到期!")
sleep(1000)
exit()//停止辅助
}
} else {
//解析JSON
var json = JSON.parse(请求返回)
if (json["code"] == 201) {
console.log("卡密不存在!")
toast("卡密不存在!")
sleep(1000)
exit()//停止辅助
} else if (json["code"] == 202) {
console.log("项目已停用!")
toast("项目已停用!")
sleep(1000)
exit()//停止辅助
} else if (json["code"] == 203) {
console.log("卡密已经到期!")
toast("卡密已经到期!")
sleep(1000)
exit()//停止辅助
} else if (json["code"] == 204) {
console.log("卡密绑定了其他设备!")
while (true)
toast("卡密绑定了其他设备!")
sleep(1000)
end
} else if (json["code"] == 200) {
var sign = json["sign"]
var localSign = UtilsWrapper.prototype.dataMd5(项目ID + 项目秘钥 + base64(json["data"]) + timeStamp).substring(0, 4)
console.log("serviceSign:" + sign)
console.log("localSign:" + localSign)
if (localSign != sign) {
console.log("非法的返回!")
toast("非法的返回!")
sleep(1000)
exit()//停止辅助
}
//解析JSON
var data = JSON.parse(json["data"])
//首次验证提示
if (!获取卡密到期时间) {
console.log("卡密到期日期:" + dateFormat("YYYY-mm-dd HH:MM", new Date(data["dqsj"] * 1000)))
toast("卡密到期日期:" + dateFormat("YYYY-mm-dd HH:MM", new Date(data["dqsj"] * 1000)))
sleep(1000)
}
验证时间 = new Date().getTime()
获取卡密到期时间 = data["dqsj"]
} else {
console.log("获取卡密信息失败!")
toast("获取卡密信息失败!")
sleep(1000)
exit()//停止辅助
}
}
} else {
console.log("下次获取卡密信息:" + ((验证心跳频秒 * 1000) - (new Date().getTime() - 验证时间)))
}
}
//编码
function base64(str) {
return java.lang.String(android.util.Base64.encode(java.lang.String(str).getBytes(), 2));
}
//发送Get请求
function sendGet(target) {
return "" + HttpWrapper.prototype.httpGet(target, null, 30000, null)
}
//解析时间格式
function dateFormat(fmt, date) {
let ret
const opt = {
"Y+": date.getFullYear().toString(), // 年
"m+": (date.getMonth() + 1).toString(), // 月
"d+": date.getDate().toString(), // 日
"H+": date.getHours().toString(), // 时
"M+": date.getMinutes().toString(), // 分
"S+": date.getSeconds().toString() // 秒
// 有其他格式化字符需求可以继续添加,必须转化成字符串
}
for (let k in opt) {
ret = new RegExp("(" + k + ")").exec(fmt)
if (ret) {
fmt = fmt.replace(ret[1], (ret[1].length == 1) ? (opt[k]) : (opt[k].padStart(ret[1].length, "0")))
}
}
return fmt
}