闲聊几句
大概是一年前,我就已经了解过这款产品。当时也有过建站,但是没有坚持下来。现在是第二次尝试。在原先的基础上,增加了更多的自定义。在这里记录一下网站接入闲聊么的过程。
简单接入
xianliao.me是支持最简洁的方式接入到你的网站的,只需要在他们的官网注册一个账号。你就能得到一个web_id和SSO_key。

根据上面的图片,只需要使用很简单的代码,就可以接入到你的网站。
但是,有一个非常现实的问题,如果访问者想要加入,必须使用微信扫一扫才能登录并且开始聊天。
相信不是流量特别大的网站,这一步应该可以劝退一大波的访问者了。所以就有了下文。我是如何通过他的API搭建起一个只需要输入一个随机用户名就能开始聊天的系统的。
分析API
在xianliaome的官网,我们发现他们提供了 定制代码接入 的功能,我们可以通过手机端接入API,模拟出一个“已登录用户”,提供给游客进行聊天。
在手机端接入闲聊么的方法:
https://xianliao.me/s/你的web_id?mobile=1&uid={登录用户的ID}&username={登录用户的用户名,需要做URI encode}&avatar={登录用户的头像URL,需要做URI encode}&ts={当前的Linux timestamp}&token={即xlm_hash,见下附的xlm_hash的生成方法}
通过上面的接口信息我们可以看出来,其中登录用户id,用户名,用户头像我们都可以通过一个特定规则进行模拟。然后得到一个完整的模拟用户,提供给闲聊么,然后他会返回一个完整的聊天窗口给我们。
模拟用户
用户id
首先要声明的是,经过我的测试,同一个web_id下,用户ID是不能够重复的,重复就会当做同一个用户,所以,我们需要采用一套不会重复或者重复几率较小的生成规则生成用户ID。
我们生成随机数的时候,使用9301, 49297, 233280三个数字作为基数(原理看这儿:https://www.zhihu.com/question/22818104), 生成一个理论上不会重复的用户ID。
用户名
用户名,我们可以通过弹框让访问的游客自己输入一个名称,也可以使用随机生成一个姓名。此处无太多技术点,不做详解。
用户头像
如果不传头像,“闲聊么”会用一个空白作为默认头像,但是不够美观,所以在这里,我们使用 http://www.gravatar.com 。
使用gravatar后,我们只需要一个简单的http请求,就能够获得一个有趣的头像。
http://www.gravatar.com/avatar/{hash}?s=256&d=identicon
- hash: 生成一个随机数填充
- s:尺寸
- d:风格,目前可选 identicon、monsterid、wavatar、retro、robohash 等。具体可见官方文档
hash的话,我们前面生成了一个可能不会重复的user_id,在这里,就可以将user_id当做hash传入到请求中。
s,尺寸,可以不用传,默认尺寸即可。
d,风格,我使用了数组保存了五种风格,然后每次创建用户的时候使用一个[0-4]的随机数,使用随机数当做styleArray的下标获得一个随机的风格。
生成chat_url
有了上面的几步,我们获得了web_id,sso_key,user_id,username,avatar。timestamp可以获取。现在,我们已经能够生成一个token了。
create token
按照官方文档,token的生成是由以下几个字段经过SHA512加密之后的字符串。
webid_userid_当前时间戳_ssokey
由于SSO_KEY属于隐私信息,所以我们不能够在前端生成token,这一步,应该交给后台。
后端编写一个**createXianLiaoToken()**接口,前台传入当前时间戳和用户ID即可,web_id和SSO_KEY保存在服务端。
此处,我使用Java演示。
Controller.java
/** * 用于生成闲聊么 所需要的token信息 */ @GetMapping("createXianLiaoToken") public @ResponseBody String createXianLiaoToken(HttpServletRequest request) { String uid = request.getParameter("uid"); String timestamp = request.getParameter("timestamp"); String str = WebConst.WEB_ID + "_" + uid + "_" + timestamp + "_" + WebConst.SSO_KEY; try { return Commons.SHA(str, "SHA-512"); } catch (Exception e) { throw new TipException("系统异常, SHA-512加密失败."); } }
Commons#SHA(网上很多,我在CSDN复制的)
public static String SHA(final String strText, final String strType) { // 返回值 String strResult = null; // 是否是有效字符串 if (strText != null && strText.length() > 0) { try { // SHA 加密开始 // 创建加密对象 并傳入加密類型 MessageDigest messageDigest = MessageDigest .getInstance(strType); // 传入要加密的字符串 messageDigest.update(strText.getBytes()); // 得到 byte 類型结果 byte byteBuffer[] = messageDigest.digest(); // 將 byte 轉換爲 string StringBuffer strHexString = new StringBuffer(); 大专栏 闲聊么 // 遍歷 byte buffer for (int i = 0; i < byteBuffer.length; i++) { String hex = Integer.toHexString(0xff & byteBuffer[i]); if (hex.length() == 1) { strHexString.append('0'); } strHexString.append(hex); } // 得到返回結果 strResult = strHexString.toString(); } catch (NoSuchAlgorithmException e) { e.printStackTrace(); } } return strResult; }
AJAX
// 从后台获取到与闲聊么通信的token function getToken(xlm_uid, timestamp) { var result = null; $.ajax({ url: [[@{/createXianLiaoToken}]], type: 'GET', dataType: 'text', contentType: 'application/json', data: {'uid': xlm_uid, 'timestamp': timestamp}, async: false, success: function(data){ result = data; } }); return result; }
通过上述操作,我们拿到了token,然后我们可以开始组装整个chat_url信息。
根据官网的文档,chat_url的格式为:
https://xianliao.me/s/web_id?mobile=1&uid={登录用户的ID}&username={登录用户的用户名,需要做URI encode}&avatar={登录用户的头像URL,需要做URI encode}&ts={当前的Linux timestamp}&token={即xlm_hash,见下附的xlm_hash的生成方法}
我们将上面步骤获得信息,一一填入到链接中,然后通过window.location.href = chat_url,将当前页面重定向到闲聊么的页面。就得到了一个闲聊么的聊天界面了。下面看一下我的完整前端代码。
xianliaome.html
<!DOCTYPE html> <html xmlns:th="http://www.thymeleaf.org"> <head> <title>闲聊么</title> <script th:src="@{//cdn.bootcss.com/jquery/2.2.3/jquery.min.js}"></script> </head> <body> <script th:inline="javascript"> // thymeleaf 不能输入地址符,但是闲聊么api又不能识别转移后了的&,所以用CDATA包起来. /*<![CDATA[*/ var ds = ['identicon', 'monsterid', 'wavatar', 'retro', 'robohash']; // 初始化闲聊么需要的数据 function init() { var web_id = 'xxxxxx'; var xlm_uid; var xlm_name; var xlm_avatar; if (easyLocalStorage('xlm_uid') != null) { xlm_uid = easyLocalStorage('xlm_uid'); xlm_name = easyLocalStorage('xlm_name'); xlm_avatar = easyLocalStorage('xlm_avatar'); }else { xlm_uid = decodeURI(Math.seededRandom(Date.parse(new Date()), 1)); var name = prompt('请输入用户名').trim(); xlm_name = decodeURI(name === '' ? '匿名' : name); xlm_avatar = decodeURI(avatarRandom(xlm_uid)); easyLocalStorage('xlm_uid', xlm_uid); easyLocalStorage('xlm_name', xlm_name); easyLocalStorage('xlm_avatar', xlm_avatar); } var timestamp = Date.parse(new Date()); var token = getToken(xlm_uid, timestamp); window.location.href = "https://www.xianliao.me/s/" + web_id + "" + "?mobile=1" + "&uid=" + xlm_uid + "" + "&username=" + xlm_name + "" + "&avatar=" + xlm_avatar + "" + "&ts=" + timestamp + "" + "&token=" + token; } $(function () { init() }) // 从后台获取到与闲聊么通信的token function getToken(xlm_uid, timestamp) { var result = null; $.ajax({ url: [[@{/createXianLiaoToken}]], type: 'GET', dataType: 'text', contentType: 'application/json', data: {'uid': xlm_uid, 'timestamp': timestamp}, async: false, success: function(data){ result = data; } }); return result; } // 通过gravatar.com.随机获取一个有趣的用户头像 function avatarRandom(xlm_uid) { var num = Math.floor(Math.random() * 4 + 1); return 'http://www.gravatar.com/avatar/' + xlm_uid + '?d=' + ds[num]; } // 对本地存储的建议封装 function easyLocalStorage(key, value) { if (value == null || value.trim() === '') { return localStorage.getItem(key); }else { localStorage.setItem(key, value); } return true; } // 获取一个随机数 Math.seed = 5; Math.seededRandom = function(max, min) { max = max || 1; min = min || 0; Math.seed = (Math.seed * 9301 + 49297) % 233280; var rnd = Math.seed / 233280.0; return Math.ceil( min + rnd * (max - min) ); // Math.ceil实现取整功能,可以根据需要取消取整 }; /*]]>*/ </script> </body> </html>
如何使用
上面的教程,我们已经有了一个xianliaome.html的页面,在我们需要使用的地方,我们可以通过iframe将其嵌入到当前页面中。
至此,就完成了我们闲聊么的匿名聊天功能了。
缺陷
- 闲聊么的页面还有一点问题,会挡住我们自己的页面。
- 如果需要访客输入用户名的话,那么尽管没有点击聊天,打开页面就会弹出输入用户名的弹框,非常不友好
正对上面的不足,我将会继续优化。直至完美。
感谢阅读,第一次写长篇博客,排版和描述不是特别友好。
来源:https://www.cnblogs.com/lijianming180/p/12389438.html