• API
  • 请求示例
  • 按键精灵
  • 按键精灵2014
  • 懒人精灵
  • EasyClick
  • Python
  • Java
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    
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
}    
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, 项目秘钥, 卡密, 机器码)
    

pom


    
    

java

package com.xxx.crm.controller.长情云验证;

import org.json.JSONException;
import org.json.JSONObject;

import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.URL;
import java.nio.charset.StandardCharsets;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.text.SimpleDateFormat;
import java.util.Base64;
import java.util.Date;

public class 卡密信息 {
	
	public static void main(String[] args) throws Exception {
		String xmid = "";
		String km = "";
		String xmmy = "";
		String jqm = String.valueOf(System.nanoTime());
		long timeStamp = System.currentTimeMillis() / 1000;
		String sign = getMD5(xmid + xmmy + timeStamp);
		String url = "https://api.yankami.cn/km?"
					 + "xmid=" + xmid
					 + "&km=" + km
					 + "&jqm=" + jqm
					 + "&timeStamp=" + timeStamp
					 + "&sign=" + sign
					 + "&updateJqm=1";
		JSONObject jsonEntity = getRequest(url);
		System.out.println("jsonEntity:" + jsonEntity);
		if (jsonEntity != null) {
			int code = jsonEntity.getInt("code");
			if (code == 201) {
				System.out.println("卡密不存在!");
			} else if (code == 202) {
				System.out.println("项目已经停用!");
			} else if (code == 203) {
				System.out.println("卡密已经到期!");
			} else if (code == 204) {
				System.out.println("卡密绑定了其他设备!");
			} else if (code != 200) {
				System.out.println("验证失败!");
			} else {
				String dataText = jsonEntity.getString("data");
				String serviceSign = jsonEntity.getString("sign");
				String localSign = getMD5(xmid + xmmy + Base64encodeToString(dataText) + timeStamp).substring(0, 4);
				System.out.println("serviceSign:" + serviceSign);
				System.out.println("localSign:" + localSign);
				boolean check = localSign.equalsIgnoreCase(serviceSign);
				if (!check) {
					System.out.println("非法的返回!");
				} else {
					System.out.println("成功的返回!");
					JSONObject data = new JSONObject(dataText);
					long dqsj = data.getLong("dqsj");
					String 到期时间 = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date(dqsj * 1000));
					System.out.println("到期时间:" + 到期时间);
				}
			}
		}
	}
	
	public static String Base64encodeToString(String text) {
		return Base64.getEncoder().encodeToString(text.getBytes(StandardCharsets.UTF_8));
	}
	
	public static String getMD5(String text) throws NoSuchAlgorithmException {
		byte[] bytes = MessageDigest.getInstance("MD5").digest(text.getBytes(StandardCharsets.UTF_8));
		StringBuilder builder = new StringBuilder(32);
		for (byte b : bytes) {
			builder.append(String.format("%02x", b));
		}
		return builder.toString();
	}
	
	public static JSONObject getRequest(String url) throws Exception {
		URL obj = new URL(url);
		HttpURLConnection con = (HttpURLConnection) obj.openConnection();
		con.setConnectTimeout(10000);
		con.setRequestMethod("GET");
		if (con.getResponseCode() == 200) {
			return getJSON(responseReader(con.getInputStream()));
		}
		return null;
	}
	
	private static String responseReader(InputStream inputStream) throws IOException {
		InputStreamReader inputStreamReader = new InputStreamReader(inputStream, StandardCharsets.UTF_8);
		StringBuilder stringBuilder = new StringBuilder();
		int len;
		char[] chars = new char[8192];
		while ((len = inputStreamReader.read(chars)) != -1) {
			stringBuilder.append(chars, 0, len);
		}
		inputStreamReader.close();
		return stringBuilder.toString();
	}
	
	private static JSONObject getJSON(String text) throws JSONException {
		if (text != null) {
			int indexOf = text.indexOf("{");
			int lastIndexOf = text.lastIndexOf("}");
			if (indexOf != -1 && lastIndexOf != -1) {
				return new JSONObject(text.substring(indexOf, lastIndexOf + 1));
			}
		}
		return null;
	}
}    
获取卡密信息(JSON)
请求支持GET和POST:https://api.yankami.cn/km
请求参数 是否必须 说明
xmid 是 项目ID
km 是 卡密
jqm 是 机器码 设备的唯一标识
updateJqm 否 更新机器码参数:1 code不会返回204直接更新机器码.
timeStamp 是 10位 时间戳
sign 是 签名 md5(项目ID + 项目秘钥 + 时间戳)
响应参数 响应状态 说明
code 200 成功
code 201 卡密不存在
code 202 项目已停用
code 203 卡密已到期
code 204 机器码不同
code 400 请求参数错误
code 500 获取卡密信息失败
响应信息 响应参数 说明
message ... 响应 code 不是 200 时返回
响应数据 响应参数 说明
data ... 响应 code 是 200 时返回
data["dqsj"] ... 到期时间 系统10位的秒数
响应校验 响应内容 说明
sign ... 响应 code 是 200 时返回 签名 md5(项目ID + 项目秘钥 + Base64(data) + 时间戳) 的前4位