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 年, 月, 天, 小时, 分钟, 秒, dataTime
dataTime = Plugin.GetSysInfo.GetDateTime()
年 = Year(dataTime)
月 = Month(dataTime) - 2
天 = Day(dataTime) - 1
小时 = Hour(dataTime)
分钟 = Minute(dataTime)
秒 = Second(dataTime)
If 月 < 0 Then
月 = 月 + 12
年 = 年 - 1
End If
getTime = (((((Round((年 - 1) * 365 + 年 / 4 - 年 / 100 + 年 / 400) + Int((((367 * 月) / 12) - 30) + 59) + 天 - 719162) * 24 + (小时 - 8)) * 60) + 分钟) * 60 + 秒)
End Function
Function dateTimeToFormat(time)
Dim 闰年, 非闰年, 年, 月, 天, 日, 小时, 分钟, 秒, i, q, temp
闰年 = Array(31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31)
非闰年 = Array(31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31)
年 = 1970
天 = Int(time / (24 * 3600))
time = time Mod ( 24 * 3600 )
小时 = Int((time / 3600) + 8)
time = time Mod 3600
分钟 = Int(time / 60)
秒 = Int(time Mod 60)
For i = 天 To 365 Step - 1
年 = 年 + 1
If 年 Mod 4 = 0 and 年 Mod 100 <> 0 or 年 Mod 400 = 0 Then
//闰年
i = i - 366 + 1
Else
//非闰年
i = i - 365 + 1
End If
Next
if(年 Mod 4 = 0 and 年 Mod 100 <> 0) or 年 Mod 400 = 0 Then
//闰年
i = i + 1
if i < 31 Then
月 = 1
日 = i + 1
Else
For q = 0 To 11 Step 1
temp = 闰年(q)
if temp < i + 1 Then
月= q + 1
i = i - 闰年(q)
Else
Exit For
End If
Next
日 = i + 1
月 = 月 + 1
End If
Else
//非闰年
if i < 31 then
月 = 1
日 = i + 1
Else
For q = 0 To 11 Step 1
temp = 非闰年(q)
if temp < i + 1 then
月 = q + 1
i = i - 非闰年(q)
Else
Exit For
End If
Next
日 = i + 1
月 = 月 + 1
End If
End If
If 月 < 10 Then
月 = "0"&月
End If
dateTimeToFormat = 年&"-"&月&"-"&日&" "&小时&":"&分钟&":"&秒
End Function
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
}
import base64
import json
import requests
import hashlib
import time
import datetime
def 获取卡密信息(项目ID, 项目秘钥, 卡密, 机器码):
timeStamp = int(time.time())
print(f"时间戳: {timeStamp}")
sign = hashlib.md5((str(项目ID) + 项目秘钥 + str(timeStamp)).encode('utf-8')).hexdigest()
params = {"xmid": 项目ID, "km": 卡密, "jqm": 机器码, "updateJqm": 1, "timeStamp": timeStamp, "sign": sign}
try:
if False:
result = requests.get('https://api.yankami.cn/xm', params=params).json()
else:
result = requests.post('https://api.yankami.cn/km', data=params).json()
print("result:", result)
code = result["code"]
if code == 201:
print("卡密不存在!")
elif code == 202:
print("项目已经停用!")
elif code == 203:
print("卡密已经到期!")
elif code == 204:
print("卡密绑定了其他设备!")
elif code != 200:
print("获取卡密信息失败!")
else:
data = result["data"]
print("data:", data)
serviceSign = result["sign"]
localSign = hashlib.md5((str(项目ID) + 项目秘钥 + base64.b64encode(str(data).encode('utf-8')).decode('utf-8') + str(timeStamp)).encode('utf-8')).hexdigest()[0:4]
print("serviceSign:", serviceSign)
print("localSign:", localSign)
if serviceSign != localSign:
print("非法的返回!")
else:
print("成功的返回!")
data = json.loads(data)
dqsj = datetime.datetime.fromtimestamp(data["dqsj"]).strftime("%Y-%m-%d %H:%M:%S")
print("到期时间:", dqsj)
except Exception as e:
print(f"获取卡密信息失败:{e}")
if __name__ == "__main__":
项目ID = ""
项目秘钥 = ""
卡密 = ""
机器码 = str(int(time.time()))
获取卡密信息(项目ID, 项目秘钥, 卡密, 机器码)