CustomApi.java
package com.foxinmy.weixin4j.mp.api;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.TypeReference;
import com.foxinmy.weixin4j.exception.WeixinException;
import com.foxinmy.weixin4j.http.MimeType;
import com.foxinmy.weixin4j.http.apache.content.InputStreamBody;
import com.foxinmy.weixin4j.http.apache.mime.FormBodyPart;
import com.foxinmy.weixin4j.http.weixin.ApiResult;
import com.foxinmy.weixin4j.http.weixin.WeixinResponse;
import com.foxinmy.weixin4j.model.Token;
import com.foxinmy.weixin4j.mp.model.KfAccount;
import com.foxinmy.weixin4j.mp.model.KfChatRecord;
import com.foxinmy.weixin4j.mp.model.KfOnlineAccount;
import com.foxinmy.weixin4j.mp.model.KfSession;
import com.foxinmy.weixin4j.mp.model.KfSession.KfSessionCounter;
import com.foxinmy.weixin4j.token.TokenManager;
import com.foxinmy.weixin4j.util.FileUtil;
import com.foxinmy.weixin4j.util.ObjectId;
import com.foxinmy.weixin4j.util.StringUtil;
/**
* 多客服API
*
* @className CustomApi
* @author jinyu(foxinmy@gmail.com)
* @date 2014年11月16日
* @since JDK 1.6
* @see <a href="http://dkf.qq.com">多客服说明</a>
*/
public class CustomApi extends MpApi {
private final TokenManager tokenManager;
public CustomApi(TokenManager tokenManager) {
this.tokenManager = tokenManager;
}
/**
* 客服聊天记录
*
* @param startTime
* 查询开始时间
* @param endTime
* 查询结束时间 每次查询不能跨日查询
* @param number
* 最多10000条
* @throws WeixinException
* @see com.foxinmy.weixin4j.mp.model.KfChatRecord
* @see <a href="http://dkf.qq.com/document-1_1.html">查询客服聊天记录</a>
* @see <a href=
* "https://mp.weixin.qq.com/wiki?t=resource/res_main&id=mp1458044854&token=&lang=zh_CN">
* 查询客服聊天记录</a>
*/
public List<KfChatRecord> getKfChatRecord(Date startTime, Date endTime,
int number) throws WeixinException {
List<KfChatRecord> records = new ArrayList<KfChatRecord>();
String kf_chatrecord_uri = getRequestUri("kf_chatrecord_uri");
Token token = tokenManager.getCache();
JSONObject obj = new JSONObject();
obj.put("starttime", startTime.getTime() / 1000);
obj.put("endtime", endTime.getTime() / 1000);
obj.put("msgid", "1");
obj.put("number", Math.min(10000, number));
JSONObject result = null;
do {
WeixinResponse response = weixinExecutor.post(
String.format(kf_chatrecord_uri, token.getAccessToken()),
obj.toJSONString());
result = response.getAsJson();
String text = result.getString("recordlist");
if (StringUtil.isBlank(text) || "[]".equals(text)) {
break;
}
records.addAll(JSON.parseArray(text, KfChatRecord.class));
obj.put("msgid", result.getString("msgid"));
} while (obj.getIntValue("number") == result.getIntValue("number"));
return records;
}
/**
* 获取公众号中所设置的客服基本信息,包括客服工号、客服昵称、客服登录账号
*
* @return 多客服信息列表
* @see com.foxinmy.weixin4j.mp.model.KfAccount
* @see <a href=
* "https://mp.weixin.qq.com/wiki?t=resource/res_main&id=mp1458044813&token=&lang=zh_CN">
* 获取客服基本信息</a>
* @throws WeixinException
*/
public List<KfAccount> listKfAccount() throws WeixinException {
Token token = tokenManager.getCache();
String kf_list_uri = getRequestUri("kf_list_uri");
WeixinResponse response = weixinExecutor.get(String.format(kf_list_uri,
token.getAccessToken()));
String text = response.getAsJson().getString("kf_list");
return JSON.parseArray(text, KfAccount.class);
}
/**
* 获取在线客服在线状态(手机在线、PC客户端在线、手机和PC客户端全都在线)、客服自动接入最大值、 客服当前接待客户数
*
* @return 多客服在线信息列表
* @see com.foxinmy.weixin4j.mp.model.KfOnlineAccount
* @see <a href=
* "https://mp.weixin.qq.com/wiki?t=resource/res_main&id=mp1458044813&token=&lang=zh_CN">
* 获取客服在线信息</a>
* @throws WeixinException
*/
public List<KfOnlineAccount> listOnlineKfAccount() throws WeixinException {
Token token = tokenManager.getCache();
String kf_onlinelist_uri = getRequestUri("kf_onlinelist_uri");
WeixinResponse response = weixinExecutor.get(String.format(
kf_onlinelist_uri, token.getAccessToken()));
String text = response.getAsJson().getString("kf_online_list");
return JSON.parseArray(text, KfOnlineAccount.class);
}
/**
* 新增客服账号
*
* @param id
* 完整客服账号,格式为:账号前缀@公众号微信号,账号前缀最多10个字符,必须是英文或者数字字符。如果没有公众号微信号,
* 请前往微信公众平台设置。
* @param name
* 客服昵称,最长6个汉字或12个英文字符
* @return 处理结果
* @throws WeixinException
* @see <a href=
* "https://mp.weixin.qq.com/wiki?t=resource/res_main&id=mp1458044813&token=&lang=zh_CN">
* 新增客服账号</a>
*/
public ApiResult createKfAccount(String id, String name)
throws WeixinException {
JSONObject obj = new JSONObject();
obj.put("kf_account", id);
obj.put("nickname", name);
String kf_create_uri = getRequestUri("kf_create_uri");
Token token = tokenManager.getCache();
WeixinResponse response = weixinExecutor.post(
String.format(kf_create_uri, token.getAccessToken()),
obj.toJSONString());
return response.getAsResult();
}
/**
* 更新客服账号
*
* @param id
* 完整客服账号,格式为:账号前缀@公众号微信号,账号前缀最多10个字符,必须是英文或者数字字符。如果没有公众号微信号,
* 请前往微信公众平台设置。
* @param name
* 客服昵称,最长6个汉字或12个英文字符
* @return 处理结果
* @throws WeixinException
* @see <a href=
* "https://mp.weixin.qq.com/wiki?t=resource/res_main&id=mp1458044813&token=&lang=zh_CN">
* 新增客服账号</a>
*/
public ApiResult updateKfAccount(String id, String name)
throws WeixinException {
JSONObject obj = new JSONObject();
obj.put("kf_account", id);
obj.put("nickname", name);
String kf_update_uri = getRequestUri("kf_update_uri");
Token token = tokenManager.getCache();
WeixinResponse response = weixinExecutor.post(
String.format(kf_update_uri, token.getAccessToken()),
obj.toJSONString());
return response.getAsResult();
}
/**
* 邀请绑定客服帐号
* 新添加的客服帐号是不能直接使用的,只有客服人员用微信号绑定了客服账号后,方可登录Web客服进行操作。此接口发起一个绑定邀请到客服人员微信号
* ,客服人员需要在微信客户端上用该微信号确认后帐号才可用。尚未绑定微信号的帐号可以进行绑定邀请操作,邀请未失效时不能对该帐号进行再次绑定微信号邀请。
*
* @param kfAccount
* 完整客服帐号,格式为:帐号前缀@公众号微信号
* @param inviteAccount
* 接收绑定邀请的客服微信号
* @return 处理结果
* @see <a href=
* "https://mp.weixin.qq.com/wiki?t=resource/res_main&id=mp1458044813&token=&lang=zh_CN"
* >邀请绑定客服帐号<a/>
* @throws WeixinException
*/
public ApiResult inviteKfAccount(String kfAccount, String inviteAccount)
throws WeixinException {
JSONObject obj = new JSONObject();
obj.put("kf_account", kfAccount);
obj.put("invite_wx", inviteAccount);
String kf_invite_uri = getRequestUri("kf_invite_uri");
Token token = tokenManager.getCache();
WeixinResponse response = weixinExecutor.post(
String.format(kf_invite_uri, token.getAccessToken()),
obj.toJSONString());
return response.getAsResult();
}
/**
* 上传客服头像
*
* @param accountId
* 完整客服账号,格式为:账号前缀@公众号微信号
* @param is
* 头像图片文件必须是jpg格式,推荐使用640*640大小的图片以达到最佳效果
* @param fileName
* 文件名 为空时将自动生成
* @return 处理结果
* @throws WeixinException
* @see <a href=
* "https://mp.weixin.qq.com/wiki?t=resource/res_main&id=mp1458044813&token=&lang=zh_CN">
* 上传客服头像</a>
*/
public ApiResult uploadKfAvatar(String accountId, InputStream is,
String fileName) throws WeixinException {
if (StringUtil.isBlank(fileName)) {
fileName = ObjectId.get().toHexString();
}
if (StringUtil.isBlank(FileUtil.getFileExtension(fileName))) {
fileName = String.format("%s.jpg", fileName);
}
MimeType mimeType = new MimeType("image",
FileUtil.getFileExtension(fileName));
Token token = tokenManager.getCache();
String kf_avatar_uri = getRequestUri("kf_avatar_uri");
WeixinResponse response = weixinExecutor
.post(String.format(kf_avatar_uri, token.getAccessToken(),
accountId), new FormBodyPart("media",
new InputStreamBody(is, mimeType.toString(), fileName)));
return response.getAsResult();
}
/**
* 删除客服账号
*
* @param id
* 完整客服账号,格式为:账号前缀@公众号微信号
* @return 处理结果
* @throws WeixinException
* @see <a href=
* "https://mp.weixin.qq.com/wiki?t=resource/res_main&id=mp1458044813&token=&lang=zh_CN">
* 删除客服账号</a>
*/
public ApiResult deleteKfAccount(String id) throws WeixinException {
Token token = tokenManager.getCache();
String kf_delete_uri = getRequestUri("kf_delete_uri");
WeixinResponse response = weixinExecutor.get(String.format(
kf_delete_uri, token.getAccessToken(), id));
return response.getAsResult();
}
/**
* 创建会话
* <p>
* 开发者可以使用本接口,为多客服的客服工号创建会话,将某个客户直接指定给客服工号接待,需要注意此接口不会受客服自动接入数以及自动接入开关限制。
* 只能为在线的客服(PC客户端在线,或者已绑定多客服助手)创建会话。
* </p>
*
* @param userOpenId
* 用户的userOpenId
* @param kfAccount
* 完整客服账号,格式为:账号前缀@公众号微信号
* @param text
* 附加信息,文本会展示在客服人员的多客服客户端
* @return 处理结果
* @throws WeixinException
* @see <a href=
* "https://mp.weixin.qq.com/wiki?t=resource/res_main&id=mp1458044820&token=&lang=zh_CN">
* 创建会话</a>
*/
public ApiResult createKfSession(String userOpenId, String kfAccount,
String text) throws WeixinException {
Token token = tokenManager.getCache();
String kfsession_create_uri = getRequestUri("kfsession_create_uri");
JSONObject obj = new JSONObject();
obj.put("openid", userOpenId);
obj.put("kf_account", kfAccount);
obj.put("text", text);
WeixinResponse response = weixinExecutor.post(
String.format(kfsession_create_uri, token.getAccessToken()),
obj.toJSONString());
return response.getAsResult();
}
/**
* 关闭会话
*
* @param userOpenId
* 用户的userOpenId
* @param kfAccount
* 完整客服账号,格式为:账号前缀@公众号微信号
* @param text
* 附加信息,文本会展示在客服人员的多客服客户端
* @return 处理结果
* @throws WeixinException
* @see <a href=
* "https://mp.weixin.qq.com/wiki?t=resource/res_main&id=mp1458044820&token=&lang=zh_CN">
* 关闭会话</a>
*/
public ApiResult closeKfSession(String userOpenId, String kfAccount,
String text) throws WeixinException {
Token token = tokenManager.getCache();
String kfsession_close_uri = getRequestUri("kfsession_close_uri");
JSONObject obj = new JSONObject();
obj.put("openid", userOpenId);
obj.put("kf_account", kfAccount);
obj.put("text", text);
WeixinResponse response = weixinExecutor.post(
String.format(kfsession_close_uri, token.getAccessToken()),
obj.toJSONString());
return response.getAsResult();
}
/**
* 获取客户的会话状态:获取客户当前的会话状态。
*
* @param userOpenId
* 用户的openid
* @return 会话对象
* @throws WeixinException
* @see com.foxinmy.weixin4j.mp.model.KfSession
* @see <a href=
* "https://mp.weixin.qq.com/wiki?t=resource/res_main&id=mp1458044820&token=&lang=zh_CN">
* 获取会话状态</a>
*/
public KfSession getKfSession(String userOpenId) throws WeixinException {
Token token = tokenManager.getCache();
String kfsession_get_uri = getRequestUri("kfsession_get_uri");
WeixinResponse response = weixinExecutor.get(String.format(
kfsession_get_uri, token.getAccessToken(), userOpenId));
KfSession session = response
.getAsObject(new TypeReference<KfSession>() {
});
session.setUserOpenId(userOpenId);
return session;
}
/**
* 获取客服的会话列表:获取某个客服正在接待的会话列表。
*
* @param kfAccount
* 完整客服账号,格式为:账号前缀@公众号微信号,账号前缀最多10个字符,必须是英文或者数字字符。
* @return 会话列表
* @throws WeixinException
* @see com.foxinmy.weixin4j.mp.model.KfSession
* @see <a href=
* "https://mp.weixin.qq.com/wiki?t=resource/res_main&id=mp1458044820&token=&lang=zh_CN">
* 获取客服的会话列表</a>
*/
public List<KfSession> listKfSession(String kfAccount)
throws WeixinException {
Token token = tokenManager.getCache();
String kfsession_list_uri = getRequestUri("kfsession_list_uri");
WeixinResponse response = weixinExecutor.get(String.format(
kfsession_list_uri, token.getAccessToken(), kfAccount));
List<KfSession> sessionList = JSON.parseArray(response.getAsJson()
.getString("sessionlist"), KfSession.class);
return sessionList;
}
/**
* 获取未接入会话列表:获取当前正在等待队列中的会话列表,此接口最多返回最早进入队列的100个未接入会话。</br> <font
* color="red">缺陷:没有count字段</font>
*
* @return 会话列表
* @throws WeixinException
* @see com.foxinmy.weixin4j.mp.model.KfSession
* @see com.foxinmy.weixin4j.mp.model.KfSession.KfSessionCounter
* @see <a href=
* "https://mp.weixin.qq.com/wiki?t=resource/res_main&id=mp1458044820&token=&lang=zh_CN">
* 获取客服的会话列表</a>
*/
public KfSessionCounter listKfWaitSession() throws WeixinException {
Token token = tokenManager.getCache();
String kfsession_wait_uri = getRequestUri("kfsession_wait_uri");
WeixinResponse response = weixinExecutor.get(String.format(
kfsession_wait_uri, token.getAccessToken()));
return response.getAsObject(new TypeReference<KfSessionCounter>() {
});
}
}