ManualService996Proxy.lua 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438
  1. local DebugProxy = requireProxy("DebugProxy")
  2. local ManualService996Proxy = class("ManualService996Proxy", DebugProxy)
  3. ManualService996Proxy.NAME = global.ProxyTable.ManualService996Proxy
  4. local cjson = require("cjson")
  5. local socket = require("socket")
  6. local signkey = "385755076a9b81c9ea85b7570679d6ca"
  7. local function calcSuffix(originData)
  8. -- 计算sign
  9. local origin = ""
  10. local realOrigin = ""
  11. for i, v in ipairs(originData) do
  12. local send_value = v.value
  13. if send_value then
  14. if string.find(send_value, "%%") then
  15. local strList = string.split(send_value, "%")
  16. local t = urlencodeT("%")
  17. send_value = table.concat(strList, t)
  18. end
  19. if string.find(send_value, "%+") then
  20. local strList = string.split(send_value, "+")
  21. local t = urlencodeT("+")
  22. send_value = table.concat(strList, t)
  23. end
  24. if string.find(send_value, "%&") then
  25. local strList = string.split(send_value, "&")
  26. local t = urlencodeT("&")
  27. send_value = table.concat(strList, t)
  28. end
  29. end
  30. origin = origin .. string.format("%s=%s", v.key, v.value)
  31. origin = origin .. (i < #originData and "&" or "")
  32. realOrigin = realOrigin .. string.format("%s=%s", v.key, send_value)
  33. realOrigin = realOrigin .. (i < #originData and "&" or "")
  34. end
  35. -- 拼接sign
  36. local suffix = get_str_MD5(realOrigin)
  37. return suffix
  38. end
  39. local function HTTPRequestPost1(url, callback, data, header)
  40. local httpRequest = cc.XMLHttpRequest:new()
  41. httpRequest.responseType = cc.XMLHTTPREQUEST_RESPONSE_JSON
  42. httpRequest.timeout = 100000 -- 10 s
  43. httpRequest:open("POST", url)
  44. if header then
  45. for k, v in pairs(header) do
  46. httpRequest:setRequestHeader(k, v)
  47. end
  48. end
  49. if callback then
  50. local function HttpResponseCB()
  51. local code = httpRequest.status
  52. local success = code >= 200 and code < 300
  53. local response = httpRequest.response
  54. releasePrint("Http Request Code:" .. tostring(code))
  55. callback(success, response, code)
  56. end
  57. httpRequest:registerScriptHandler(HttpResponseCB)
  58. end
  59. httpRequest:send(data)
  60. end
  61. function ManualService996Proxy:ctor()
  62. ManualService996Proxy.super.ctor(self)
  63. -- 请求地址
  64. --[[
  65. test: https://api-test.kf.996sdk.net/api/third/syncUserInfo
  66. pre: https://api-pre.kf.996sdk.net/api/third/syncUserInfo
  67. prod: https://api.kf.996sdk.net/api/third/syncUserInfo
  68. ]]
  69. self._is_sdk_ui = false
  70. self._show = false
  71. self._url = nil
  72. local envProxy = global.Facade:retrieveProxy(global.ProxyTable.GameEnvironment)
  73. local visitorLinkUrl = envProxy:GetCustomDataByKey("visitorLinkUrl")
  74. if visitorLinkUrl and string.len(visitorLinkUrl) > 0 then
  75. self._url = visitorLinkUrl
  76. self._show = true
  77. end
  78. local queryUrl = envProxy:GetCustomDataByKey("queryVisitorMsgUrl")
  79. if queryUrl and string.len(queryUrl) > 0 then
  80. self._query_url = queryUrl
  81. end
  82. self._un_read_nums = 0
  83. self._is_show_maual_service = false
  84. self._is_load_finish = false
  85. self._schedule_id = nil -- 兜底检测
  86. self._is_query_visitor_ing = false
  87. self._is_web_open = false
  88. self._guide_widget_config = requireConfig("GuideWidgetConfig.lua")
  89. end
  90. function ManualService996Proxy:onSUIComponentUpdate(data)
  91. if not self:IsShow() or self._is_load_finish then
  92. return
  93. end
  94. local mainID = data.index
  95. if mainID == 101 and self:FindManualService996Button() then
  96. self._is_load_finish = true
  97. local NativeBridgeProxy = global.Facade:retrieveProxy(global.ProxyTable.NativeBridgeProxy)
  98. local unReadNums = NativeBridgeProxy:Get996KeFuUnReadNums()
  99. self:SetUnReadNums(unReadNums or 0)
  100. end
  101. end
  102. function ManualService996Proxy:SetShowMaulServiceState(state)
  103. self._is_show_maual_service = state == true
  104. end
  105. function ManualService996Proxy:IsShow()
  106. return self._show
  107. end
  108. function ManualService996Proxy:SetSDKUI(value)
  109. self._is_sdk_ui = value == true
  110. end
  111. function ManualService996Proxy:IsSDKUIShow()
  112. if cc.PLATFORM_OS_WINDOWS ~= global.Platform then
  113. return self._is_sdk_ui
  114. end
  115. return false
  116. end
  117. function ManualService996Proxy:SetUnReadNums(nums)
  118. self:UpdateService996ButtonRed(self._un_read_nums, self._is_show_maual_service and 0 or nums)
  119. self._un_read_nums = nums
  120. end
  121. function ManualService996Proxy:GetUnReadNums()
  122. return self._un_read_nums
  123. end
  124. function ManualService996Proxy:UpdateService996ButtonRed(oldNums, curNums)
  125. if oldNums <= 0 and curNums > 0 then
  126. -- 加红点
  127. local btn = self:FindManualService996Button()
  128. if not btn then
  129. return
  130. end
  131. local offset = "0#0#0#0|0#0#0#0"
  132. local RedPointProxy = global.Facade:retrieveProxy(global.ProxyTable.RedPointProxy)
  133. RedPointProxy:addRedDot(btn, offset)
  134. elseif oldNums > 0 and curNums <= 0 then
  135. -- 移除红点
  136. local btn = self:FindManualService996Button()
  137. if not btn then
  138. return
  139. end
  140. local RedPointProxy = global.Facade:retrieveProxy(global.ProxyTable.RedPointProxy)
  141. RedPointProxy:rmvRedDot(btn)
  142. end
  143. end
  144. function ManualService996Proxy:FindManualService996Button()
  145. local mainId = 101
  146. local buttonId = "996kf_red"
  147. local getNodesFunc = self._guide_widget_config[mainId]
  148. if not getNodesFunc then
  149. return {}
  150. end
  151. local widget, parent = getNodesFunc({ typeassist = buttonId })
  152. if widget then
  153. return widget
  154. end
  155. return nil
  156. end
  157. function ManualService996Proxy:SetWebOpenState( state )
  158. self._is_web_open = state == true
  159. end
  160. function ManualService996Proxy:OnCheckRedPoint()
  161. if self._schedule_id then
  162. return
  163. end
  164. local totalTimes = 5 * 60 --5分钟之后自行停止
  165. local delayTime = 10
  166. local checkTimes = 0
  167. self._schedule_id = Schedule(function()
  168. checkTimes = checkTimes + delayTime
  169. self:RequestQueryVisitorMsg()
  170. if checkTimes >= totalTimes then
  171. self:RemoveCheck()
  172. end
  173. end, delayTime)
  174. end
  175. function ManualService996Proxy:RemoveCheck(isUnRed)
  176. if self._schedule_id then
  177. UnSchedule(self._schedule_id)
  178. self._schedule_id = nil
  179. end
  180. if isUnRed then
  181. self:SetUnReadNums(0)
  182. end
  183. end
  184. function ManualService996Proxy:RequestManualService()
  185. -- 盒子打开的PC端 启用PC端盒子
  186. if global.isBoxLogin and SL:GetMetaValue("PLATFORM_WINDOWS") then
  187. local currModule = global.L_ModuleManager:GetCurrentModule()
  188. local gameid = currModule:GetOperID()
  189. local url = "box996://callCustomService/id=" .. gameid
  190. -- 点击npc打开导致touch为invalid
  191. PerformWithDelayGlobal(function()
  192. cc.Application:getInstance():openURL(url)
  193. end,0.1)
  194. return
  195. end
  196. if not self._url then
  197. return
  198. end
  199. if self._is_web_open then
  200. self:SetUnReadNums(0)
  201. SLBridge:onLUAEvent(LUA_EVENT_MANUAL_SERVICE_MESSAGE_UN_READ, {unReadNums = 0})
  202. global.Facade:sendNotification(global.NoticeTable.Layer_Manual_Service_996_Open)
  203. return
  204. end
  205. -- body
  206. --[[
  207. box996://callCustomService/id=游戏id --盒子唤醒
  208. ]]
  209. local AuthProxy = global.Facade:retrieveProxy( global.ProxyTable.AuthProxy )
  210. local loginProxy= global.Facade:retrieveProxy( global.ProxyTable.Login )
  211. local propertyProxy = global.Facade:retrieveProxy( global.ProxyTable.PlayerProperty )
  212. local currModule = global.L_ModuleManager:GetCurrentModule()
  213. local userId = tostring( AuthProxy:GetUID() )
  214. local name = loginProxy:GetSelectedRoleName()
  215. local account= tostring( AuthProxy:GetUID() )
  216. local phone = ""
  217. local nonce = randDataID("996Box")
  218. local timestamp = math.floor(socket.gettime() * 1000) -- 时间戳 毫秒13位
  219. local customField = {
  220. {
  221. attributeKey = "gameName",
  222. attributeName= "游戏名称",
  223. attributeValue = currModule:GetName(),
  224. },
  225. {
  226. attributeKey = "gameId",
  227. attributeName= "游戏id",
  228. attributeValue = currModule:GetOperID(),
  229. },
  230. {
  231. attributeKey = "account",
  232. attributeName= "账号UID",
  233. attributeValue = account,
  234. },
  235. {
  236. attributeKey = "serverRoleName",
  237. attributeName= "区服角色",
  238. attributeValue = loginProxy:GetSelectedRoleName(),
  239. },
  240. {
  241. attributeKey = "serverName",
  242. attributeName= "区服名称",
  243. attributeValue = loginProxy:GetSelectedServerName(),
  244. },
  245. {
  246. attributeKey = "roleId",
  247. attributeName= "角色id",
  248. attributeValue = loginProxy:GetSelectedRoleID(),
  249. },
  250. {
  251. attributeKey = "roleLevel",
  252. attributeName= "角色等级",
  253. attributeValue = propertyProxy:GetRoleLevel(),
  254. },
  255. {
  256. attributeKey = "serverId",
  257. attributeName= "区服id",
  258. attributeValue = loginProxy:GetSelectedServerId(),
  259. }
  260. }
  261. --[[
  262. "userId": 21, //用户id
  263. "name": "我是名称拉", //用户名称
  264. "account": "yy", //游戏账号
  265. "visitorSource": 1, // 1, "app端/h5端", 2, "pc端 3, "游戏" 4. 交易行
  266. "headImg": "xx", //访客头像
  267. "phone":"18896856652", //手机号
  268. "lastGameInfo":"传奇2", //最近在玩游戏(3款)
  269. "customField": "xx" //自定义字段 json格式
  270. "nonce": "1221", //随机字符串
  271. "timestamp": 1704778924000, //时间戳
  272. "signature": "xx", //加密后的参数
  273. "gameId": 2519
  274. ]]
  275. local data = {
  276. userId = userId,
  277. name = name,
  278. account = account,
  279. visitorSource = 3,
  280. source = 3,
  281. headImg = "",
  282. phone = "",
  283. lastGameInfo = currModule:GetName() or "",
  284. customField = cjson.encode(customField),
  285. nonce = nonce,
  286. timestamp = timestamp,
  287. gameId = tostring(currModule:GetOperID()),
  288. }
  289. local originData = {
  290. { key="userId", value=data.userId or ""},
  291. { key="name", value=data.name or ""},
  292. { key="account", value=data.account or ""},
  293. { key="phone", value=data.phone or ""},
  294. { key="nonce", value=data.nonce or ""},
  295. { key="timestamp", value=data.timestamp},
  296. { key="sign", value=signkey or ""},
  297. }
  298. data.signature = calcSuffix(originData)
  299. local jsonStr = cjson.encode(data)
  300. local header = {}
  301. header["Content-Type"] = "application/json"
  302. HTTPRequestPost1(self._url, function( success, response )
  303. if not success then
  304. ShowSystemTips("请求失败")
  305. return false
  306. end
  307. releasePrint("========kefu:", response)
  308. local jsonData = cjson.decode(response)
  309. if not jsonData then
  310. ShowSystemTips("解析失败")
  311. return false
  312. end
  313. if not (jsonData.code == 200) then
  314. ShowSystemTips("获取验证码失败, 状态异常 " .. jsonData.msg)
  315. return false
  316. end
  317. local linkURL = jsonData.data and jsonData.data.visitorLinkUrl
  318. if not linkURL or linkURL == "" or string.len(linkURL) == 0 then
  319. ShowSystemTips("获取客服地址失败")
  320. return false
  321. end
  322. local uid = ""
  323. if jsonData.chatting then
  324. linkURL = linkURL .. "&uid=" .. jsonData.customerId
  325. end
  326. -- self:SetShowMaulServiceState(false)
  327. self:SetUnReadNums(0)
  328. SLBridge:onLUAEvent(LUA_EVENT_MANUAL_SERVICE_MESSAGE_UN_READ, {unReadNums = 0})
  329. if cc.PLATFORM_OS_WINDOWS ~= global.Platform and not self:IsSDKUIShow() then
  330. linkURL = linkURL .. "&sourceType=game"
  331. global.Facade:sendNotification(global.NoticeTable.Layer_Manual_Service_996_Open, {url = linkURL})
  332. return
  333. end
  334. local NativeBridgeProxy = global.Facade:retrieveProxy( global.ProxyTable.NativeBridgeProxy )
  335. NativeBridgeProxy:GN_ShowCustomerService({
  336. url = linkURL
  337. })
  338. end, jsonStr, header)
  339. releasePrint("RequestAuthCode url: " .. self._url .. " postData: " .. jsonStr)
  340. end
  341. -- 检测访客信息
  342. function ManualService996Proxy:RequestQueryVisitorMsg()
  343. if not self._query_url then
  344. return
  345. end
  346. if self._is_query_visitor_ing then
  347. return
  348. end
  349. self._is_query_visitor_ing = true
  350. local AuthProxy = global.Facade:retrieveProxy( global.ProxyTable.AuthProxy )
  351. local userId = tostring( AuthProxy:GetUID() )
  352. local url = string.format("%s?visitorId=%s&visitorSource=%s", self._query_url, userId, 3)
  353. releasePrint("===self._query_url111: ", url )
  354. HTTPRequest(url, function( success, response )
  355. self._is_query_visitor_ing = false
  356. if not success then
  357. releasePrint("查询请求失败")
  358. return false
  359. end
  360. releasePrint("========查询kefu:", response)
  361. local jsonData = cjson.decode(response)
  362. if not jsonData then
  363. releasePrint("查询解析失败")
  364. return false
  365. end
  366. local unReadMsg = jsonData and jsonData.data and jsonData.data.unReadMsg
  367. if unReadMsg then
  368. local unReadNums = self._un_read_nums or 0
  369. unReadNums = unReadNums + 1
  370. self:SetUnReadNums(unReadNums)
  371. self:RemoveCheck()
  372. SLBridge:onLUAEvent(LUA_EVENT_MANUAL_SERVICE_MESSAGE_UN_READ, {unReadNums = unReadNums})
  373. end
  374. end)
  375. end
  376. return ManualService996Proxy