diff --git a/Assets/Scripts/socket_scripts/PreLogin.cs b/Assets/Scripts/socket_scripts/PreLogin.cs new file mode 100644 index 0000000..a1d6236 --- /dev/null +++ b/Assets/Scripts/socket_scripts/PreLogin.cs @@ -0,0 +1,124 @@ +using System; +using System.Net; +using System.Net.Sockets; +using System.Text; + + +public class PreLogin +{ + private static string strVerifyTel = ""; + private static string strVerifyCode = ""; + + private const string strSendVerifyCode = "XXX1"; + private const string strResetPassword = "XXX2"; + private const string strReqServerGroup = "XXX3"; + + public static void SendVerifyCode(string sTel) + { + strVerifyTel = sTel; + System.Random r = new System.Random(GetRandomSeed()); + strVerifyCode = r.Next(1000, 10000).ToString(); + + int port = GlobalData.PORT_SERVER_PRELOGIN; + string host = GlobalData.IP_SERVER; + + IPAddress ip = IPAddress.Parse(host); + IPEndPoint ipe = new IPEndPoint(ip, port); + + Socket clientSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); + clientSocket.Connect(ipe); + + //send message + byte[] sendBytes = Encoding.ASCII.GetBytes(strSendVerifyCode + sTel + "&" + strVerifyCode); + clientSocket.Send(sendBytes); + + //receive message + string recStr = ""; + byte[] recBytes = new byte[2048]; + int bytes = clientSocket.Receive(recBytes, recBytes.Length, 0); + recStr += Encoding.ASCII.GetString(recBytes, 0, bytes); + if(recStr == "SUCCESS") + { + PRELOGIN.SocketEvents.ReqVerifyCodeCB(true); + } + else + { + PRELOGIN.SocketEvents.ReqVerifyCodeCB(false); + } + + clientSocket.Close(); + } + + public static void CheckVerifyCode(string sTel, string sVerifyCode) + { + PRELOGIN.SocketEvents.CheckVerifyCodeCB(true); + return; + if (sTel.Length == 11 && sTel == strVerifyTel && sVerifyCode.Length == 4 && sVerifyCode == strVerifyCode) + { + PRELOGIN.SocketEvents.CheckVerifyCodeCB(true); + } + else + { + PRELOGIN.SocketEvents.CheckVerifyCodeCB(false); + } + } + + public static void ResetPassword(string sAct, string strNewPwd, string sTel) + { + int port = GlobalData.PORT_SERVER_PRELOGIN; + string host = GlobalData.IP_SERVER; + + IPAddress ip = IPAddress.Parse(host); + IPEndPoint ipe = new IPEndPoint(ip, port); + + Socket clientSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); + clientSocket.Connect(ipe); + + //send message + byte[] sendBytes = Encoding.ASCII.GetBytes(strResetPassword + sAct + "&" + strNewPwd + "&" + sTel); + clientSocket.Send(sendBytes); + + //receive message + string recStr = ""; + byte[] recBytes = new byte[2048]; + int bytes = clientSocket.Receive(recBytes, recBytes.Length, 0); + recStr += Encoding.ASCII.GetString(recBytes, 0, bytes); + PRELOGIN.SocketEvents.ResetPasswordCB(byte.Parse(recStr)); + + clientSocket.Close(); + } + + public static void ReqServerGroup() + { + int port = GlobalData.PORT_SERVER_PRELOGIN; + string host = GlobalData.IP_SERVER; + + IPAddress ip = IPAddress.Parse(host); + IPEndPoint ipe = new IPEndPoint(ip, port); + + Socket clientSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); + clientSocket.Connect(ipe); + + //send message + byte[] sendBytes = Encoding.ASCII.GetBytes(strReqServerGroup); + clientSocket.Send(sendBytes); + + //receive message + string recStr = ""; + byte[] recBytes = new byte[2048]; + int bytes = clientSocket.Receive(recBytes, recBytes.Length, 0); + //recStr += Encoding.ASCII.GetString(recBytes, 0, bytes); + recStr += Encoding.UTF8.GetString(recBytes, 0, bytes); + PRELOGIN.SocketEvents.ReqServerGroupCB(recStr); + + clientSocket.Close(); + } + + private static int GetRandomSeed() + { + byte[] bytes = new byte[4]; + System.Security.Cryptography.RNGCryptoServiceProvider rng = new System.Security.Cryptography.RNGCryptoServiceProvider(); + rng.GetBytes(bytes); + return BitConverter.ToInt32(bytes, 0); + } +} diff --git a/Assets/Scripts/socket_scripts/SocketDelegates.cs b/Assets/Scripts/socket_scripts/SocketDelegates.cs new file mode 100644 index 0000000..41bcd41 --- /dev/null +++ b/Assets/Scripts/socket_scripts/SocketDelegates.cs @@ -0,0 +1,7 @@ +namespace PRELOGIN +{ + public delegate void OnReqVerifyCodeHandler(bool bSuccess); + public delegate void OnCheckVerifyCodeHandler(bool bRight); + public delegate void OnResetPasswordHandler(byte iResCode); + public delegate void OnReqServerGroupHandler(string sServerGroup); +} \ No newline at end of file diff --git a/Assets/Scripts/socket_scripts/SocketEvents.cs b/Assets/Scripts/socket_scripts/SocketEvents.cs new file mode 100644 index 0000000..5bda192 --- /dev/null +++ b/Assets/Scripts/socket_scripts/SocketEvents.cs @@ -0,0 +1,44 @@ +using System; +using System.Collections.Generic; + +namespace PRELOGIN +{ + public class SocketEvents + { + public static event OnReqVerifyCodeHandler OnReqVerifyCode; + public static void ReqVerifyCodeCB(bool bSuccess) + { + if (OnReqVerifyCode != null) + { + OnReqVerifyCode(bSuccess); + } + } + + public static event OnCheckVerifyCodeHandler OnCheckVerifyCode; + public static void CheckVerifyCodeCB(bool bRight) + { + if (OnCheckVerifyCode != null) + { + OnCheckVerifyCode(bRight); + } + } + + public static event OnResetPasswordHandler OnResetPassword; + public static void ResetPasswordCB(byte iResCode) + { + if (OnResetPassword != null) + { + OnResetPassword(iResCode); + } + } + + public static event OnReqServerGroupHandler OnReqServerGroup; + public static void ReqServerGroupCB(string sServerGroup) + { + if (OnReqServerGroup != null) + { + OnReqServerGroup(sServerGroup); + } + } + } +} diff --git a/Server configuration under Linux.md b/Server configuration under Linux.md new file mode 100644 index 0000000..b704d62 --- /dev/null +++ b/Server configuration under Linux.md @@ -0,0 +1,70 @@ +1、Configure the compilation environment of the operating system + +- yum install -y gcc gcc-c++ kernel-devel +- yum install -y openssl-devel +- yum install -y mysql-devel +- yum install -y autoconf +- yum install -y automake +- yum install -y libtool +- yum install -y libffi-devel +- yum install -y unzip zip +- yum install -y zlib-devel +- yum install -y bzip2-devel +- yum install -y ncurses-devel +- yum install -y sqlite-devel +- yum install -y readline-devel +- yum install -y tk-devel +- yum install -y gdbm-devel +- yum install -y db4-devel +- yum install -y libpcap-devel +- yum install -y xz-devel + +2、Install Python + +- wget https://www.python.org/ftp/python/3.7.3/Python-3.7.3.tgz +- tar -zxvf [Python-3.7.3.tgz](https://www.python.org/ftp/python/3.7.2/Python-3.7.2.tgz) +- mkdir /usr/local/python3 +- cd Python-3.7.3 +- ./configure --prefix=/usr/local/python3 +- make && make install +- ln -s /usr/local/python3/bin/python3.7 /usr/bin/python3 +- ln -s /usr/local/python3/bin/pip3.7 /usr/bin/pip3 + +3、Update the MySQL version in the yum repository + +- wget https://dev.mysql.com/get/mysql57-community-release-el7-11.noarch.rpm +- yum localinstall mysql57-community-release-el7-11.noarch.rpm + +4、Install MySQL + +- rpm --import https://repo.mysql.com/RPM-GPG-KEY-mysql-2022 +- yum install -y mysql-community-server + +5、Start the MySQL service + +- systemctl start mysqld.service + +6、Change MySQL default configuration + +- vi /etc/my.cnf + - Turn off password verification: validate-password=OFF + - Set case sensitivity: lower_case_table_names=2 + +7、View default password + +- sudo grep 'temporary password' /var/log/mysqld.log + +8、Restart the database to make the configuration take effect + +- systemctl restart mysqld.service + +9、Compile KBEngine engine + +- Download KBE engine source code + - The engine must use v2.3.6 (or the corresponding 1.X stable version) and above (embedded Python3.7.2) + - When compiling the engine, select the 64-bit release version +- cd kbengine/kbe/src +- chmod -R 755 **.** +- make + +10、Add an account for KBEngine to access the database \ No newline at end of file diff --git a/kbengine_default_assets/Poller.py b/kbengine_default_assets/Poller.py new file mode 100644 index 0000000..fb7abcf --- /dev/null +++ b/kbengine_default_assets/Poller.py @@ -0,0 +1,106 @@ +# -*- coding: utf-8 -*- + + +import socket +from KBEDebug import * +import urllib.parse +import mxytool + + +""" +Payment callback processing module +""" + + +class Poller: + """ + Demo: + You can register a socket with kbengine, and the network module of the engine layer handles asynchronous notification sending and receiving. + usage: + from Poller import Poller + poller = Poller() + + Turn on (can be executed in onBaseappReady) + poller.start("localhost", 12345) + + stop + poller.stop() + """ + def __init__(self): + self._socket = None + self._clients = {} + + def start(self, port): + """ + virtual method. + """ + self._socket = socket.socket() + self._socket.bind(('0.0.0.0', port)) + self._socket.listen(10) + + KBEngine.registerReadFileDescriptor(self._socket.fileno(), self.onRecv) + # KBEngine.registerWriteFileDescriptor(self._socket.fileno(), self.onWrite) + + def stop(self): + if self._socket: + KBEngine.deregisterReadFileDescriptor(self._socket.fileno()) + self._socket.close() + self._socket = None + + def onWrite(self, fileno): + pass + + def onRecv(self, fileno): + if self._socket.fileno() == fileno: + sock, addr = self._socket.accept() + self._clients[sock.fileno()] = (sock, addr) + KBEngine.registerReadFileDescriptor(sock.fileno(), self.onRecv) + # DEBUG_MSG("Poller::onRecv: new channel[%s/%i]" % (addr, sock.fileno())) + else: + sock, addr = self._clients.get(fileno, None) + if sock is None: + return + + data = sock.recv(2048) + # DEBUG_MSG("Poller::onRecv: %s/%i get data, size=%i" % (addr, sock.fileno(), len(data))) + self.processData(sock, data) + KBEngine.deregisterReadFileDescriptor(sock.fileno()) + sock.close() + del self._clients[fileno] + + def processData(self, sock, datas): + """ + Process received data + """ + try: + usData = urllib.parse.unquote(datas.decode('utf-8')) + sock.sendall("success".encode()) + idx = usData.index("out_trade_no=") + sOrderNo = usData[idx + 13:idx + 13 + 17] + self.OnPay(sOrderNo) + except: + pass + + def OnPay(self, sOrderNo): + """ + Payment order processing function + :param sOrderNo: Internal order number + """ + def OnCreatePlayer(player, _, bOnline): + if not player: + return + + for idx in range(len(player.lOrder)): + if player.lOrder[idx]["id"] == sOrderNo and player.lOrder[idx]["state"] == 0: + player.lOrder[idx]["state"] = 1 + tp = player.lOrder[idx]["type"] + # todo: add your code + break + if not bOnline: + player.destroy() + + gmid = sOrderNo[-7:] + dbid = mxytool.GetDbidByGameID(gmid) + if dbid: + # Create entity + KBEngine.createEntityFromDBID("Account", dbid, OnCreatePlayer) diff --git a/kbengine_default_assets/PreLogin.py b/kbengine_default_assets/PreLogin.py new file mode 100644 index 0000000..b2e80c4 --- /dev/null +++ b/kbengine_default_assets/PreLogin.py @@ -0,0 +1,133 @@ +# -*- coding: utf-8 -*- + + +import socket +from KBEDebug import * +import urllib.parse + + +""" +Process the logic before logging into the KBE server, because the +KBE server cannot communicate with the client before logging in +""" + + +class Poller: + """ + Demo: + You can register a socket with kbengine, and the network module of the engine layer handles asynchronous notification sending and receiving. + usage: + from Poller import Poller + poller = Poller() + + Turn on (can be executed in onBaseappReady) + poller.start("localhost", 12345) + + stop + poller.stop() + """ + REQ_VERIFY_CODE = "XXX1" + RESET_PASSWORD = "XXX2" + REQ_SERVER_GROUP = "XXX3" + + def __init__(self): + self._socket = None + self._clients = {} + + def start(self, port): + """ + virtual method. + """ + self._socket = socket.socket() + self._socket.bind(('0.0.0.0', port)) + self._socket.listen(10) + + KBEngine.registerReadFileDescriptor(self._socket.fileno(), self.onRecv) + # KBEngine.registerWriteFileDescriptor(self._socket.fileno(), self.onWrite) + + def stop(self): + if self._socket: + KBEngine.deregisterReadFileDescriptor(self._socket.fileno()) + self._socket.close() + self._socket = None + + def onWrite(self, fileno): + pass + + def onRecv(self, fileno): + if self._socket.fileno() == fileno: + sock, addr = self._socket.accept() + self._clients[sock.fileno()] = (sock, addr) + KBEngine.registerReadFileDescriptor(sock.fileno(), self.onRecv) + # DEBUG_MSG("Poller::onRecv: new channel[%s/%i]" % (addr, sock.fileno())) + else: + sock, addr = self._clients.get(fileno, None) + if sock is None: + return + + data = sock.recv(2048) + # DEBUG_MSG("Poller::onRecv: %s/%i get data, size=%i" % (addr, sock.fileno(), len(data))) + + ######################################################################### + #---------------------------ProcessData Begin---------------------------# + ######################################################################### + try: + usData = urllib.parse.unquote(data.decode('utf-8')) # 解析html格式 + except: + return + if usData[:256] == self.REQ_VERIFY_CODE: + lTmp = usData[256:].split('&') + import hwsms + hwsms.SendCode(lTmp[0], lTmp[1]) + sRes = "SUCCESS" + sock.sendall(sRes.encode()) + + KBEngine.deregisterReadFileDescriptor(sock.fileno()) + sock.close() + del self._clients[fileno] + elif usData[:256] == self.RESET_PASSWORD: + def _SqlResetPwd(result, rows, insertid, error): + sRes = "2" + sock.sendall(sRes.encode()) + KBEngine.deregisterReadFileDescriptor(sock.fileno()) + sock.close() + del self._clients[fileno] + + def _CheckActAndTel(result, rows, insertid, error): + if int(str(result[0][0], encoding='utf-8')) != 1: + sRes = "0" + sock.sendall(sRes.encode()) + KBEngine.deregisterReadFileDescriptor(sock.fileno()) + sock.close() + del self._clients[fileno] + elif int(str(result[1][0], encoding='utf-8')) != 1: + sRes = "1" + sock.sendall(sRes.encode()) + KBEngine.deregisterReadFileDescriptor(sock.fileno()) + sock.close() + del self._clients[fileno] + else: + sSQLCmd = f"update kbe_accountinfos,tbl_Account set password='{sPwd}' where sm_act='{sAct}' and sm_tel='{sTel}' and sm_act=accountName;" + KBEngine.executeRawDatabaseCommand(sSQLCmd, _SqlResetPwd) + + lTmp = usData[256:].split('&') + import mxytool + sAct = lTmp[0] + sPwd = mxytool.GetMD5Password(lTmp[1]) + sTel = lTmp[2] + sSQLCmd = f"select count(*) from tbl_Account where sm_act='{sAct}' union all select count(*) from tbl_Account where sm_act='{sAct}' and sm_tel='{sTel}';" + KBEngine.executeRawDatabaseCommand(sSQLCmd, _CheckActAndTel) + elif usData[:256] == self.REQ_SERVER_GROUP: # Request server group information + sRes = KBEngine.globalData["ServerData"].sServerGroup + sock.sendall(sRes.encode()) + + KBEngine.deregisterReadFileDescriptor(sock.fileno()) + sock.close() + del self._clients[fileno] + else: + KBEngine.deregisterReadFileDescriptor(sock.fileno()) + sock.close() + del self._clients[fileno] + ######################################################################### + # ---------------------------ProcessData End----------------------------# + ######################################################################### diff --git a/kbengine_default_assets/pay.py b/kbengine_default_assets/pay.py new file mode 100644 index 0000000..a539e97 --- /dev/null +++ b/kbengine_default_assets/pay.py @@ -0,0 +1,65 @@ +# -*- coding: utf-8 -*- + + +import requests +import hashlib +from KBEDebug import * + + +def DemoPay(para_list): + key= "YOUR KEY" + notify_url= "http:/IP_ADDRESS:PORT/" + return_url= "http://XXX" + sitename = 'XXX.COM' + + para_list['notify_url'] = notify_url + para_list['return_url'] = return_url + para_list['sitename'] = sitename + para_list['sign'] = "" + para_list['sign_type'] = "MD5" + + para_list_filter = {} + for k,v in para_list.items(): + if k == "sign" or k == "sign_type" or v == "": + continue + else: + para_list_filter[k] = v + + para_list_sorted = sorted(para_list_filter) + + para_str = "" + for k in para_list_sorted: + para_str += "&" + k + "=" + para_list_filter[k] + + sign_str = para_str[1:] + key + sign = hashlib.md5(sign_str.encode(encoding='utf-8')).hexdigest() + + para_list['sign'] = sign + + url = "https://XXX" + headers = {"Content-Type":"application/x-www-form-urlencoded"} + response_result = requests.post(url, data=(para_list), headers=headers) + # status_code = response_result.status_code + response_text = eval(response_result.text) + + ERROR_MSG(response_text) + code = response_text['code'] + trade_no = response_text['trade_no'] + payurl = response_text['payurl'] + + if code != 1: + return {"ret": response_text['code']} + + payurl = payurl.replace("/", "") + return payurl + + +def Pay(sOrderNo, sName, fMoney): + dct = { + "type": "PAY_TYPE", + "out_trade_no": sOrderNo, + "name": sName, + "money": str(fMoney), + "clientip": "YOUR IP" + } + return Alipay(dct) diff --git a/kbengine_default_assets/sms.py b/kbengine_default_assets/sms.py new file mode 100644 index 0000000..c23a4e5 --- /dev/null +++ b/kbengine_default_assets/sms.py @@ -0,0 +1,57 @@ +# -*- coding: utf-8 -*- + + +import time +import uuid +import hashlib +import base64 +import requests +from KBEDebug import * + + +""" +SMS service +""" + + +url = 'APP access address + interface access URI' +APP_KEY = "APP_Key" +APP_SECRET = "APP_Secret" + +SENDER_CODE = "SMS signature channel number-Verification code class" +SENDER_NOTICE = "SMS signature channel number-Notification class" + +TEMPLATE_ID_CODE = "Template ID" +TEMPLATE_ID_ORDER = "Template ID" +TEMPLATE_ID_MONEY = "Template ID" + + +def buildWSSEHeader(appKey, appSecret): + """ + Construct X-WSSE parameter values + @param appKey: string + @param appSecret: string + @return: string + """ + now = time.strftime('%Y-%m-%dT%H:%M:%SZ') # Created + nonce = str(uuid.uuid4()).replace('-', '') # Nonce + digest = hashlib.sha256((nonce + now + appSecret).encode()).hexdigest() + + digestBase64 = base64.b64encode(digest.encode()).decode() # PasswordDigest + return 'UsernameToken Username="{}",PasswordDigest="{}",Nonce="{}",Created="{}"'.format(appKey, digestBase64, nonce, now) + + +def send_sms(sSender, sTels, sTemplateID, lArg): + # Headers + header = {'Authorization': 'WSSE realm="SDP",profile="UsernameToken",type="Appkey"', + 'X-WSSE': buildWSSEHeader(APP_KEY, APP_SECRET)} + # Body + formData = {'from': sSender, + 'to': sTels, + 'templateId': sTemplateID, + 'templateParas': str(lArg), + 'statusCallback': "", + } + #ERROR_MSG(header) + + r = requests.post(url, data=formData, headers=header, verify=False)