• 闲聊么


    闲聊几句

    大概是一年前,我就已经了解过这款产品。当时也有过建站,但是没有坚持下来。现在是第二次尝试。在原先的基础上,增加了更多的自定义。在这里记录一下网站接入闲聊么的过程。

    简单接入

    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又不能识别转移后了的&amp;,所以用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将其嵌入到当前页面中。
    至此,就完成了我们闲聊么的匿名聊天功能了。

    缺陷

    • 闲聊么的页面还有一点问题,会挡住我们自己的页面。
    • 如果需要访客输入用户名的话,那么尽管没有点击聊天,打开页面就会弹出输入用户名的弹框,非常不友好

    正对上面的不足,我将会继续优化。直至完美。

    感谢阅读,第一次写长篇博客,排版和描述不是特别友好。

  • 相关阅读:
    log4net 简单使用教程(配置)
    C#WinForm 国际化的简单实现,多语言实现
    EF Power Tool 参数错误 HRESULT:0x80070057 (E_INVALIDARG)) 解决办法
    如何用委托与事件实现winfrom窗体之间值传递
    VS2010自带的Dotfuscator 5注册
    WinForm 实现主程序(exe)与其关联类库(*.dll)分开存放
    POJ_3211 Washing Clothes (01背包)
    POJ_3624 Charm Bracelet ( 01背包 )
    集训队内部测试赛(2012.01.02)
    HDU_1011 Starship Troopers && HDU_1561 The more, The Better (树型dp)
  • 原文地址:https://www.cnblogs.com/lijianming180/p/12389438.html
Copyright © 2020-2023  润新知