You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

400 lines
14 KiB
Lua

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

local skynet = require 'skynet'
local cjson = require 'cjson'
local cluster = require 'skynet.cluster'
local login_logic = require "login_logic"
local mongohelper = require "mongohelper"
local redishelper = require "redishelper"
local keysutils = require "keysutils"
local settings = require 'settings'
local bson = require "bson"
local dateutils = require "dateutils"
require "functions"
local max_client = settings.login_conf.max_client
local M = {}
function M.init()
DEBUG("myself = ", skynet.self())
end
local pattern = "(%d+)-(%d+)-(%d+) (%d+):(%d+):(%d+)"
function M.gen_secret()
math.randomseed(tostring(os.time()):reverse():sub(1, 6))
return tostring(math.random(1, 10000000))
end
function M.wx_auth(parms)
local openid = parms.openid
local access_token = parms.access_token
local serverid = parms.serverid
local ok, user = skynet.call(".mysqld", "lua", "loaduser", {openid=openid})
if ok then
return user.id, serverid
else
local resp = login_logic.wx_auth(openid, access_token)
resp.openid = openid
resp.serverid = serverid
local ok, uid = skynet.call(".mysqld", "lua", "register", resp)
if not access_token then
error("wx_auth register failed")
end
return uid, serverid
end
end
--APP微信登录
function M.wxlogin(parms)
local count = login_logic.get_online_count()
if count >= max_client then
error(string.format("online count=%d more than max_client=%d", count, max_client))
end
local uid, serverid = M.wx_auth(parms)
local secret = M.gen_secret()
local server, gate, port = login_logic.get_server_cfg(serverid, parms.protocol)
-- INFO(string.format("%s@%s is login, secret is %s", uid, server, secret))
-- only one can login, because disallow multilogin
-- TODO:把 此数据 单独 个 服务
local last = login_logic.get_user_online(uid)
-- 如果该用户已经在某个服务器上登录了,先踢下线
if last then
-- DEBUG(string.format("call last server %s to kick uid=%d subid=%d ...", last.server, uid, last.subid))
local ok = pcall(cluster.call, last.server, ".watchdog", "kick", uid, last.subid)
skynet.error(" watchdog kick ok = ", ok)
if ok then
login_logic.del_user_online(uid)
end
end
-- login_handler会被并发可能同一用户在另一处中又登录了所以再次确认是否登录
if login_logic.get_user_online(uid) then
ERROR("user %d is already online", uid)
error(string.format("user %d is already online", uid))
end
-- 登录游戏服务器
-- INFO(string.format("uid=%s is login to gameserver %s ...", uid, server))
local ok, subid = pcall(cluster.call, server, ".watchdog", "login",uid, secret)
if not ok then
error("login call gameserver error")
end
login_logic.add_user_online(uid, { subid = subid, server = server })
return 0, "登录成功", {uid = uid, subid = subid, gate = gate, port = port, secret = secret}
end
function M.mini_auth(parms)
DEBUG("mini_auth parms = ", DUMP(parms))
DEBUG("mini_auth settings = ", DUMP(settings))
local openid = parms.openid
if not openid or openid == "" then
return 101, nil, nil
end
local unionid = parms.unionid
if not unionid or unionid == "" then
return 101, nil, nil
end
local parent_id = parms.parent_id or ""
local friend_id = parms.friend_id or ""
local user = mongohelper.findOne(settings.agent_mongodb_key.tname, settings.agent_mongodb_key.cname, {_id=parent_id})
if not user then
parent_id = ""
end
local serverid = skynet.call(".redisd", "lua", "getserverid", unionid)
serverid = checkint(serverid)
local regionid = 0
if serverid == 0 then
local servers = mongohelper.find(settings.server_item_mongodb_key.tname, settings.server_item_mongodb_key.cname, {status=1})
local r = math.random(1, #servers)
local s = servers[r]
serverid = checkint(s._id)
regionid = checkint(s.server_id)
end
if serverid == 0 then
return 102, nil, nil
end
if settings.debug then
local user = mongohelper.findOne(settings.user_mongodb_key.tname, settings.user_mongodb_key.cname, {unionid=unionid, serverid=serverid})
if not user then
if regionid == 0 then
return 102, nil, nil
end
local uid = math.floor(skynet.call(".redisd", "lua", "genid"))
local userinfo = {
uid=uid,
parent_id=parent_id,
openid=openid,
unionid=unionid,
regionid=regionid,
serverid=serverid,
nickname = "SG:"..uid,
lv = 1,
stage = 0,
max_level = 1,
recharge_total = 0,
vip_lv = 0,
avatar = "",
last_login_time = "",
last_logout_time = "",
account_status = 0,
updated_at = os.date("%Y-%m-%d %H:%M:%S"),
created_at = os.date("%Y-%m-%d %H:%M:%S")
}
local ok1 = mongohelper.upsert(settings.user_mongodb_key.tname, settings.user_mongodb_key.cname, {["$set"]=userinfo}, {uid=uid})
local bag = {
uid=uid,
serverid=serverid,
box_lv1 = 0,
coin = 10,
gold = 0,
xiaoyugan= 10,
updated_at = os.date("%Y-%m-%d %H:%M:%S"),
created_at = os.date("%Y-%m-%d %H:%M:%S")
}
local ok2 = mongohelper.upsert(settings.bag_mongodb_key.tname, settings.bag_mongodb_key.cname, {["$set"]=bag}, {uid=uid})
local ok = skynet.call(".redisd", "lua", "setserverid", openid, serverid)
-- DEBUG('setserverid ok = ', ok)
if friend_id ~= "" then
skynet.call(".redisd", "lua", "addinvitenum", friend_id)
end
return 200, uid, serverid
end
if user.account_status and user.account_status == 1 then
if user.freeze_date and user.freeze_date ~= "" then
if os.time() < dateutils.get_timestamp_by_datetime(user.freeze_date, pattern) then
return 302, user.freeze_season, nil
end
end
end
return 200, user.uid, serverid
else
local resp = {}
local user = mongohelper.findOne(settings.user_mongodb_key.tname, settings.user_mongodb_key.cname, {unionid=unionid, serverid=serverid})
if not user then
if regionid == 0 then
return 102, nil, nil
end
local uid = math.floor(skynet.call(".redisd", "lua", "genid"))
local userinfo = {
uid=uid,
parent_id=parent_id,
openid=openid,
unionid=unionid,
regionid=regionid,
serverid=serverid,
nickname = resp.nickname or "SG:"..uid,
avatar = resp.headimgurl or "",
lv = 1,
stage = 0,
max_level = 1,
recharge_total = 0,
vip_lv = 0,
last_login_time = "",
last_logout_time = "",
account_status = 0,
updated_at = os.date("%Y-%m-%d %H:%M:%S"),
created_at = os.date("%Y-%m-%d %H:%M:%S")
}
local ok1 = mongohelper.upsert(settings.user_mongodb_key.tname, settings.user_mongodb_key.cname, {["$set"]=userinfo}, {uid=uid})
local bag = {
uid=uid,
serverid=serverid,
box_lv1 = 0,
coin = 10,
gold = 0,
xiaoyugan= 10,
updated_at = os.date("%Y-%m-%d %H:%M:%S"),
created_at = os.date("%Y-%m-%d %H:%M:%S")
}
local ok2 = mongohelper.upsert(settings.bag_mongodb_key.tname, settings.bag_mongodb_key.cname, {["$set"]=bag}, {uid=uid})
local ok = skynet.call(".redisd", "lua", "setserverid", unionid, serverid)
if friend_id ~= "" then
skynet.call(".redisd", "lua", "addinvitenum", friend_id)
end
return 200, uid, serverid
end
if user.account_status and user.account_status == 1 then
if user.freeze_date and user.freeze_date ~= "" then
if os.time() < dateutils.get_timestamp_by_datetime(user.freeze_date, pattern) then
return 302, user.freeze_season, nil
end
end
end
return 200, user.uid, serverid
end
end
function M.add_login_log(uid, serverid)
local log = {
uid=uid,
serverid=serverid,
logind_at = os.date("%Y-%m-%d %H:%M:%S")
}
local ok2 = mongohelper.insert(settings.user_login_mongodb_key.tname, settings.user_login_mongodb_key.cname, log)
end
--小程序
function M.minilogin(parms)
local count = login_logic.get_online_count()
if count >= max_client then
error(string.format("online count=%d more than max_client=%d", count, max_client))
end
local uid, serverid = M.mini_auth(parms)
local secret = M.gen_secret()
local server, gate, port = login_logic.get_server_cfg(serverid, parms.protocol)
-- INFO(string.format("%s@%s is login, gate is %s secret is %s", uid, server, gate, secret))
-- only one can login, because disallow multilogin
-- TODO:把 此数据 单独 个 服务
local last = login_logic.get_user_online(uid)
-- 如果该用户已经在某个服务器上登录了,先踢下线
if last then
-- DEBUG(string.format("call last server %s to kick uid=%d subid=%d ...", last.server, uid, last.subid))
local ok = pcall(cluster.call, last.server, ".watchdog", "kick", uid, last.subid)
skynet.error(" watchdog kick ok = ", ok)
if ok then
login_logic.del_user_online(uid)
end
end
-- login_handler会被并发可能同一用户在另一处中又登录了所以再次确认是否登录
if login_logic.get_user_online(uid) then
error(string.format("user %d is already online", uid))
end
-- 登录游戏服务器
-- INFO(string.format("uid=%s is login to gameserver %s ...", uid, server))
local ok, subid = pcall(cluster.call, server, ".watchdog", "login", uid, secret)
if not ok then
error("login call gameserver error")
end
login_logic.add_user_online(uid, { subid = subid, server = server })
return 0, "登录成功", {uid = uid, subid = subid, gate = gate, port = port, secret = secret}
end
--小程序code2Session
-- function M.code2Session(parms)
-- local code = parms.code
-- local resp = login_logic.code2Session(code)
-- if resp.errcode ~= 0 then
-- return 401, "请求失败", resp
-- end
-- --TODO:通过openid 去找serverid
-- resp.serverid = 1
-- return 0, "请求成功", resp
-- end
function M.code2Session(parms)
local count = login_logic.get_online_count()
if count >= max_client then
-- error(string.format("online count=%d more than max_client=%d", count, max_client))
return 400, "当前人数过多,请等待", {}
end
local code = parms.code
local parent_id = parms.parent_id or ""
local friend_id = parms.friend_id or ""
local app = parms.app or "sg"
DEBUG("parms = ", DUMP(parms))
if settings.debug then
parms.openid = code
parms.unionid = code
else
if parms.platform and parms.platform == "h5" then
parms.openid = code
parms.unionid = code
else
local resp = login_logic.code2Session(app, code)
-- DEBUG("code2Session resp = ", DUMP(resp))
if resp.errcode and resp.errcode ~= 0 then
return 401, "请求失败", resp
end
parms.openid = resp.openid
parms.unionid = resp.unionid
end
end
local code, uid, serverid = M.mini_auth(parms)
if code == 101 then
return 101, "参数错误,openid获取", {}
end
if code == 102 then
return 102, "服务器选择失败", {}
end
if code == 302 then
return 302, "该账号已冻结, ".. uid, {}
end
local secret = M.gen_secret()
local server, gate, port = login_logic.get_server_cfg(serverid, parms.protocol or "ws")
-- only one can login, because disallow multilogin
-- TODO:把 此数据 单独 个 服务
local last = login_logic.get_user_online(uid)
-- 如果该用户已经在某个服务器上登录了,先踢下线
if last then
-- DEBUG(string.format("call last server %s to kick uid=%d subid=%d ...", last.server, uid, last.subid))
local ok = pcall(cluster.call, last.server, ".watchdog", "kick", uid, last.subid)
-- skynet.error(" watchdog kick ok = ", ok)
if ok then
login_logic.del_user_online(uid)
end
end
-- login_handler会被并发可能同一用户在另一处中又登录了所以再次确认是否登录
if login_logic.get_user_online(uid) then
return 402, "关闭之前登录用户得链接", {}
end
-- 登录游戏服务器
-- INFO(string.format("uid=%s is login to gameserver %s ...", uid, server))
local ok, subid = pcall(cluster.call, server, ".watchdog", "login", uid, secret)
if not ok then
return 403, "系统繁忙", {}
end
login_logic.add_user_online(uid, { subid = subid, server = server })
M.add_login_log(uid, serverid)
return 0, "登录成功", {uid = uid, subid = subid, gate = gate, port = port, secret = secret}
end
--停服
function M.stop(parms)
end
--开服
function M.start(parms)
end
--踢掉所有用户
function M.kickall(parms)
end
--管理后台踢掉用户
function M.adminkick(parms)
end
return M