七鱼开发文档中心
总览服务端 APIWebiOSAndroid鸿蒙Uniapp微信小程序插件三方接入

概述

七鱼客服SDK可以帮助第三方网站及应用快速构建一个完善的客服系统生态圈,SDK提供较为完善的客服应用功能,及简洁的API接口。

SDK提供如下扩展功能:

  • 自定义接入
  • CRM对接
  • 访客分流
  • 商品链接
  • 未读消息
  • VIP接入支持
  • 常见问题设置
  • 机器人欢迎语设置
  • 网站访问统计
  • 多机器人接入

以下所有接入代码的例子都可以在 这里下载。

对接七鱼WEB-SDK,只需要在页面上添加七鱼后台提供的接入代码即可,代码需要加在body中。访客访问页面时,页面会执行代码,加载七鱼的JS文件。

API列表

APIAPI说明
ysf('onready', callback)设置sdk初始化成功回调
ysf('product', info)设置商品链接
ysf('logoff')用户登出
ysf('open', options)打开客服聊天窗口
ysf('url')获取打开聊天窗口的URL地址
ysf('onunread', callback)设置未读消息通知回调
ysf('getUnreadMsg')获取当前未读消息
ysf('getConversation', callback)获取会话列表
ysf('onConversation', callback)设置会话列表新消息通知回调,返回会话列表
ysf('onSessionMessage', callback)设置会话列表新消息通知回调,返回当前收到的新的消息(单条消息)
ysf('config', options)配置企业及用户信息,嵌入七鱼客服SDK后可直接配置这些信息

其中 ysf('config', options) 的 options 参数说明如下:

参数类型描述
optionsObject企业配置信息
options.uidString企业当前登录用户标识,不传表示匿名用户
options.nameString企业当前登录用户名称
options.emailString企业当前登录用户邮箱
options.mobileString企业当前登录用户手机号
options.bidString当企业版本为平台版本的时候,用于指定咨询商户客服的商户id
options.dataString企业当前登录用户其他信息,JSON字符串,其中 avatar 字段用于设置访客头像;需包含 key,value,label 等信息;如果是头像,还需要 href;具体设置见下示例代码
options.staffidString指定客服id,非必填;如果同时存在 groupid,staffid 优先级更高
options.groupidString指定客服组id,非必填
options.shuntIdString访客选择多入口分流模版id,非必填
options.robotShuntSwitchNumber机器人优先开关(访客分配), 0 = 关闭,1 = 开启, 非必填
options.levelNumber企业当前登录用户vip等级,支持 1-10 级
options.qtypeNumber企业常见问题模板id,非必填
options.welcomeTemplateIdNumber机器人欢迎语模板id,非必填
options.successFunction配置成功回调
options.errorFunction配置失败回调
options.connectYunxinBoolean配置sdk连接云信服务,限平台企业(在七鱼开头的是平台主账号子账号的方式)使用
options.wxworkAppIdString配置企业微信id,用于语音功能,该字段需要进行加密,加密方式采用AES加密,加密代码参考如下实例,Aes Key为App Secret(系统管理-扩展与集成-开发者ID-AppSecret字段),使用老的授权方式绑定的企业微信应用,需要在应用中自行设置可信域名:qiyukf.com
options.spkfNumber主动发起视频邀请开关
options.isShowBackNumber导航头是否显示返回按钮(浮层模式设置无效)0:不显示 1:显示 ;默认是 0 不显示
options.languageString配置当前接入的语言,非必填,默认是 zh-cn 简体中文
options.shortcutTemplateIdNumber常见快捷入口模版id
options.layerSizeObjectPC端浮层模式窗口和输入框高度自定义设置,各项最小值:{ width: 360, height: 500, inputHeight: 150 } 只有配置大于最小值才生效,否则默认最小值;可以配置一项或者多项
options.emojiPopoverWidthstring指定pc端表情悬浮窗宽度
options.channelExtendInfostring渠道扩展信息,其中baiduQuery,baiduKeyword,baiduChannel是固定百度渠道相关的key
options.allowNewTabNumber值为 1 时,图片、文本、PDF 文件支持在新标签页中打开;值为 0 时在当前浮层内直接打开。默认值为 0,非必填。
options.alipayImagePermissionTextstring支付宝相册权限文案

语言参数说明:

语言字段
中文简体zh-cn
中文繁体zh-tw
英文en
阿拉伯语(沙特)ar
德语de
俄语ru
法语fr
菲律宾语tl
韩语ko
日语ja
泰语th
印尼语id
越南语vi
意大利语it
波兰语pl

使用范例

ysf('config', {
    uid:"1442286211167",
    name:'test',
    email:'test@163.com',
    mobile:'13888888888',
    data:JSON.stringify([
       {"key":"real_name", "value":"土豪"},
       {"key":"mobile_phone", "hidden":true, "value":"13800000000"},
       {"key":"email", "value":"13800000000@163.com"},
       {"key":"avatar", "label":"头像", "value": "https://ysf.qiyukf.net/operation/080659b993a45dd546fbd71efd5ef000"}, // 访客头像
       {"index":0, "key":"account", "label":"账号", "value":"zhangsan" , "href":"http://example.domain/user/zhangsan"},
       {"index":1, "key":"sex", "label":"性别", "value":"先生"},
       {"index":5, "key":"reg_date", "label":"注册日期", "value":"2015-11-16"},
       {"index":6, "key":"last_login", "label":"上次登录时间", "value":"2015-12-22 15:38:54"}
    ]),
    channelExtendInfo: JSON.stringify([
      {"key":"baiduQuery", "value":"百度搜索词"},
      {"key":"baiduKeyword", "value":"百度关键词"},
      {"key":"baiduChannel", "value":"百度来源"},
    ])
    staffid:'123',
    groupid: '123',
    shuntId: '123',
    level: 1,
    qtype: 1056,
    welcomeTemplateId: 1024,
    layerSize: { // 只对PC端的浮层模式有效
      width: 360,
      height: 500,
      inputHeight: 150
    },
    success: function(){
    	// todo
    },
    error: function(){
    	// handle error
    }
});

AES加密代码参考

public final class AESEncryptUtil {
    private static final ThreadLocal<Map<String, Cipher>> CIPHER_THREAD_LOCAL_EN_URS_COOKIE = new ThreadLocal<>();

    private static final ThreadLocal<Map<String, Cipher>> CIPHER_THREAD_LOCAL_DE_URS_COOKIE = new ThreadLocal<>();

    private AESEncryptUtil() {
    }

    public static String encrypt(String sSrc, String aesKey) {
        validate(aesKey);
        try {
            return encrypt_(sSrc, aesKey);
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    public static String decrypt(String sSrc, String aesKey) {
        validate(aesKey);
        try {
            return decrypt_(sSrc, aesKey);
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

	private static void validate(String aesKey) {
		if (strIsBlank(aesKey) || (16 != aesKey.length() && 24 != aesKey.length() && 32 != aesKey.length())) {
			throw new RuntimeException("AES密钥长度只能是 16 24 32 字节");
		}
	}

    /**
     * 加密
     *
     * @param sSrc
     * @return
     * @throws Exception
     */
    public static String encrypt_(String sSrc, String aesKey) throws Exception {
        if (strIsBlank(sSrc) || strIsBlank(aesKey)) {
            return null;
        }
        Map<String, Cipher> cipherMap = CIPHER_THREAD_LOCAL_EN_URS_COOKIE.get();

        if (cipherMap == null) {
            cipherMap = new HashMap<>(10);
            CIPHER_THREAD_LOCAL_EN_URS_COOKIE.set(cipherMap);
        }
        Cipher aesCipher = cipherMap.get(aesKey);
        if (aesCipher == null) {
            byte[] raw = aesKey.getBytes("utf-8");
            SecretKeySpec skeySpec = new SecretKeySpec(raw, "AES");
            aesCipher = Cipher.getInstance("AES");
            aesCipher.init(Cipher.ENCRYPT_MODE, skeySpec);
            cipherMap.put(aesKey, aesCipher);
        }
        return bytesToHexStr(aesCipher.doFinal(sSrc.getBytes("UTF-8")));
    }

    /**
     * 解密
     *
     * @param sSrc
     * @return
     * @throws Exception
     */
    public static String decrypt_(String sSrc, String aesKey) throws Exception {
        if (strIsBlank(sSrc) || strIsBlank(aesKey)) {
            return "";
        }

        Map<String, Cipher> cipherMap = CIPHER_THREAD_LOCAL_DE_URS_COOKIE.get();
        if (cipherMap == null) {
            cipherMap = new HashMap<>(10);
            CIPHER_THREAD_LOCAL_DE_URS_COOKIE.set(cipherMap);
        }
        Cipher aesCipher = cipherMap.get(aesKey);
        if (aesCipher == null) {
            byte[] raw = aesKey.getBytes("utf-8");
            SecretKeySpec skeySpec = new SecretKeySpec(raw, "AES");
            aesCipher = Cipher.getInstance("AES");
            aesCipher.init(Cipher.DECRYPT_MODE, skeySpec);
            cipherMap.put(aesKey, aesCipher);
        }
        return new String(aesCipher.doFinal(hexStrToBytes(sSrc)), "UTF-8");
    }

    /**
     * 将16进制字符串还原为字节数组.
     */
    private static byte[] hexStrToBytes(String s) {
        byte[] bytes;

        bytes = new byte[s.length() / 2];

        for (int i = 0; i < bytes.length; i++) {
            bytes[i] = (byte) Integer.parseInt(s.substring(2 * i, 2 * i + 2), 16);
        }

        return bytes;
    }

    /**
     * 将字节数组转换为16进制字符串的形式.
     */
    private static String bytesToHexStr(byte[] bcd) {
        StringBuffer s = new StringBuffer(bcd.length * 2);

        for (byte aBcd : bcd) {
            s.append(HEX_LOOKUP_STRING[(aBcd >>> 4) & 0x0f]);
            s.append(HEX_LOOKUP_STRING[aBcd & 0x0f]);
        }

        return s.toString();
    }


	private static boolean strIsBlank(CharSequence cs) {
		int strLen;
		if (cs != null && (strLen = cs.length()) != 0) {
			for (int i = 0; i < strLen; ++i) {
				if (!Character.isWhitespace(cs.charAt(i))) {
					return false;
				}
			}
			return true;
		} else {
			return true;
		}
	}

    private static final char[] HEX_LOOKUP_STRING = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c',
            'd', 'e', 'f' };

    public static void main(String[] args) {
        String appId = "XXXXX"; // 企业微信appId
        String aeskey = "XXXX"; //app secret key
        System.out.println(AESEncryptUtil.encrypt(appId, aeskey));
    }
}

这篇文档有帮助吗?

目录