客服聊天记录接口&resolveHttpparams rename to setDefaultParams

This commit is contained in:
jinyu 2016-08-03 11:22:03 +08:00
parent bbdd8980af
commit 5aaeec29e7
21 changed files with 319 additions and 145 deletions

View File

@ -102,7 +102,7 @@ public abstract class HttpClientFactory {
*/ */
public static HttpClient getInstance(HttpParams params) { public static HttpClient getInstance(HttpParams params) {
HttpClientFactory clientFactory = getDefaultFactory(); HttpClientFactory clientFactory = getDefaultFactory();
clientFactory.resolveHttpParams(params); clientFactory.setDefaultParams(params);
return clientFactory.newInstance(); return clientFactory.newInstance();
} }
@ -112,11 +112,11 @@ public abstract class HttpClientFactory {
* @param params * @param params
* 请求参数 * 请求参数
*/ */
public void resolveHttpParams(HttpParams params) { public void setDefaultParams(HttpParams params) {
if (params == null) { if (params == null) {
throw new IllegalArgumentException("'params' must not be empty"); throw new IllegalArgumentException("'params' must not be empty");
} }
resolveHttpParams0(params); resolveHttpParams(params);
} }
/** /**
@ -125,7 +125,7 @@ public abstract class HttpClientFactory {
* @param params * @param params
* 请求参数 * 请求参数
*/ */
protected abstract void resolveHttpParams0(HttpParams params); protected abstract void resolveHttpParams(HttpParams params);
/** /**
* 获取HttpClient实例 * 获取HttpClient实例

View File

@ -19,7 +19,7 @@ public class SimpleHttpClientFactory extends HttpClientFactory {
private HttpParams params; private HttpParams params;
@Override @Override
protected void resolveHttpParams0(HttpParams params) { protected void resolveHttpParams(HttpParams params) {
this.params = params; this.params = params;
} }

View File

@ -41,7 +41,7 @@ public class HttpComponent3Factory extends HttpClientFactory {
* Resolve Parameter * Resolve Parameter
*/ */
@Override @Override
protected void resolveHttpParams0(HttpParams params) { protected void resolveHttpParams(HttpParams params) {
if (params.getProxy() != null) { if (params.getProxy() != null) {
InetSocketAddress socketAddress = (InetSocketAddress) params InetSocketAddress socketAddress = (InetSocketAddress) params
.getProxy().address(); .getProxy().address();

View File

@ -41,7 +41,7 @@ public class HttpComponent4Factory extends HttpClientFactory {
} }
@Override @Override
protected void resolveHttpParams0(HttpParams params) { protected void resolveHttpParams(HttpParams params) {
httpComponentFactory.resolveHttpParams(params); httpComponentFactory.setDefaultParams(params);
} }
} }

View File

@ -39,7 +39,7 @@ public class HttpComponent4_1Factory extends HttpClientFactory {
} }
@Override @Override
protected void resolveHttpParams0(HttpParams params) { protected void resolveHttpParams(HttpParams params) {
if (params == null) { if (params == null) {
throw new IllegalArgumentException("'params' must not be empty"); throw new IllegalArgumentException("'params' must not be empty");
} }

View File

@ -42,7 +42,7 @@ public class HttpComponent4_2Factory extends HttpClientFactory {
} }
@Override @Override
public void resolveHttpParams0(HttpParams params) { public void resolveHttpParams(HttpParams params) {
clientBuilder.setDefaultRequestConfig(RequestConfig.custom() clientBuilder.setDefaultRequestConfig(RequestConfig.custom()
.setConnectTimeout(params.getConnectTimeout()) .setConnectTimeout(params.getConnectTimeout())
.setConnectionRequestTimeout(params.getReadTimeout()).build()); .setConnectionRequestTimeout(params.getReadTimeout()).build());

View File

@ -46,7 +46,7 @@ public class Netty4HttpClientFactory extends HttpClientFactory {
} }
@Override @Override
protected void resolveHttpParams0(HttpParams params) { protected void resolveHttpParams(HttpParams params) {
this.params = params; this.params = params;
} }

View File

@ -32,7 +32,7 @@ public class OkHttpClient2Factory extends HttpClientFactory {
} }
@Override @Override
protected void resolveHttpParams0(HttpParams params) { protected void resolveHttpParams(HttpParams params) {
okClient.setConnectTimeout(params.getConnectTimeout(), okClient.setConnectTimeout(params.getConnectTimeout(),
TimeUnit.MILLISECONDS); TimeUnit.MILLISECONDS);
okClient.setReadTimeout(params.getReadTimeout(), TimeUnit.MILLISECONDS); okClient.setReadTimeout(params.getReadTimeout(), TimeUnit.MILLISECONDS);

View File

@ -39,7 +39,7 @@ public class OkHttpClient3Factory extends HttpClientFactory {
* *
* */ * */
@Override @Override
protected void resolveHttpParams0(HttpParams params) { protected void resolveHttpParams(HttpParams params) {
clientBuilder.connectTimeout(params.getConnectTimeout(), clientBuilder.connectTimeout(params.getConnectTimeout(),
TimeUnit.MILLISECONDS); TimeUnit.MILLISECONDS);
clientBuilder.readTimeout(params.getReadTimeout(), clientBuilder.readTimeout(params.getReadTimeout(),

View File

@ -27,8 +27,8 @@ public class OkHttpClientFactory extends HttpClientFactory {
} }
@Override @Override
protected void resolveHttpParams0(HttpParams params) { protected void resolveHttpParams(HttpParams params) {
okHttpClientFactory.resolveHttpParams(params); okHttpClientFactory.setDefaultParams(params);
} }
@Override @Override

View File

@ -45,7 +45,7 @@ public class MediaRecord implements Serializable {
@JSONField(serialize = false, deserialize = false) @JSONField(serialize = false, deserialize = false)
private Pageable pageable; private Pageable pageable;
@JSONField(serialize = false, deserialize = false) @JSONField(serialize = false, deserialize = false)
private Pagedata<MediaItem> pagedata; private volatile Pagedata<MediaItem> pagedata;
public int getTotalCount() { public int getTotalCount() {
return totalCount; return totalCount;

View File

@ -94,7 +94,7 @@ public class Pageable implements Serializable {
} }
public Pageable first() { public Pageable first() {
return new Pageable(0, getPageSize(), getSort()); return new Pageable(1, getPageSize(), getSort());
} }
@Override @Override

View File

@ -79,7 +79,7 @@ public class DateUtil {
public static String formatFee2Fen(double fee) { public static String formatFee2Fen(double fee) {
BigDecimal _fee = new BigDecimal(Double.toString(fee)); BigDecimal _fee = new BigDecimal(Double.toString(fee));
fee = _fee.multiply(new BigDecimal("100")) fee = _fee.multiply(new BigDecimal("100"))
.setScale(2, BigDecimal.ROUND_HALF_UP).doubleValue(); .setScale(2, BigDecimal.ROUND_HALF_EVEN).doubleValue();
return new DecimalFormat("#").format(fee); return new DecimalFormat("#").format(fee);
} }

View File

@ -61,7 +61,7 @@ public abstract class HttpClientTest {
protected HttpClient createHttpClient(HttpParams params) { protected HttpClient createHttpClient(HttpParams params) {
HttpClientFactory httpClientFactory = createHttpFactory(); HttpClientFactory httpClientFactory = createHttpFactory();
httpClientFactory.resolveHttpParams(params); httpClientFactory.setDefaultParams(params);
return httpClientFactory.newInstance(); return httpClientFactory.newInstance();
} }

View File

@ -34,6 +34,7 @@ import com.foxinmy.weixin4j.mp.model.Following;
import com.foxinmy.weixin4j.mp.model.Group; import com.foxinmy.weixin4j.mp.model.Group;
import com.foxinmy.weixin4j.mp.model.KfAccount; import com.foxinmy.weixin4j.mp.model.KfAccount;
import com.foxinmy.weixin4j.mp.model.KfChatRecord; 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;
import com.foxinmy.weixin4j.mp.model.KfSession.KfSessionCounter; import com.foxinmy.weixin4j.mp.model.KfSession.KfSessionCounter;
import com.foxinmy.weixin4j.mp.model.Menu; import com.foxinmy.weixin4j.mp.model.Menu;
@ -387,8 +388,7 @@ public class WeixinProxy {
* "https://mp.weixin.qq.com/wiki?t=resource/res_main&id=mp1444738731&token=&lang=zh_CN"> * "https://mp.weixin.qq.com/wiki?t=resource/res_main&id=mp1444738731&token=&lang=zh_CN">
* 删除永久媒体素材</a> * 删除永久媒体素材</a>
*/ */
public ApiResult deleteMaterialMedia(String mediaId) public ApiResult deleteMaterialMedia(String mediaId) throws WeixinException {
throws WeixinException {
return mediaApi.deleteMaterialMedia(mediaId); return mediaApi.deleteMaterialMedia(mediaId);
} }
@ -514,8 +514,8 @@ public class WeixinProxy {
* 查询开始时间 * 查询开始时间
* @param endTime * @param endTime
* 查询结束时间 每次查询不能跨日查询 * 查询结束时间 每次查询不能跨日查询
* @param pageable * @param number
* 分页数据 * 最多10000条
* @see com.foxinmy.weixin4j.mp.model.CustomRecord * @see com.foxinmy.weixin4j.mp.model.CustomRecord
* @see com.foxinmy.weixin4j.mp.api.CustomApi * @see com.foxinmy.weixin4j.mp.api.CustomApi
* @see <a href="http://dkf.qq.com/document-1_1.html">查询客服聊天记录</a> * @see <a href="http://dkf.qq.com/document-1_1.html">查询客服聊天记录</a>
@ -525,30 +525,38 @@ public class WeixinProxy {
* @throws WeixinException * @throws WeixinException
*/ */
public List<KfChatRecord> getKfChatRecord(Date startTime, Date endTime, public List<KfChatRecord> getKfChatRecord(Date startTime, Date endTime,
Pageable pageable) throws WeixinException { int number) throws WeixinException {
return customApi.getKfChatRecord(startTime, endTime, pageable); return customApi.getKfChatRecord(startTime, endTime, number);
} }
/** /**
* 获取公众号中所设置的客服基本信息包括客服工号客服昵称客服登录账号 * 获取公众号中所设置的客服基本信息包括客服工号客服昵称客服登录账号
* *
* @param isOnline
* 是否在线 为ture时可以可以获取客服在线状态手机在线PC客户端在线手机和PC客户端全都在线客服自动接入最大值
* 客服当前接待客户数
* @return 多客服信息列表 * @return 多客服信息列表
* @see com.foxinmy.weixin4j.mp.model.KfAccount * @see com.foxinmy.weixin4j.mp.model.KfAccount
* @see com.foxinmy.weixin4j.mp.api.CustomApi * @see com.foxinmy.weixin4j.mp.api.CustomApi
* @see <a href="http://dkf.qq.com/document-3_1.html">获取客服基本信息</a>
* @see <a href= * @see <a href=
* "https://mp.weixin.qq.com/wiki?t=resource/res_main&id=mp1458044813&token=&lang=zh_CN"> * "https://mp.weixin.qq.com/wiki?t=resource/res_main&id=mp1458044813&token=&lang=zh_CN">
* 获取客服基本信息</a> * 获取客服基本信息</a>
* @see <a href="http://dkf.qq.com/document-3_2.html">获取在线客服接待信息</a>
* 获取在线客服接待信息</a>
* @throws WeixinException * @throws WeixinException
*/ */
public List<KfAccount> listKfAccount(boolean isOnline) public List<KfAccount> listKfAccount() throws WeixinException {
throws WeixinException { return customApi.listKfAccount();
return customApi.listKfAccount(isOnline); }
/**
* 获取在线客服在线状态手机在线PC客户端在线手机和PC客户端全都在线客服自动接入最大值 客服当前接待客户数
*
* @return 多客服在线信息列表
* @see com.foxinmy.weixin4j.mp.model.KfOnlineAccount
* @see com.foxinmy.weixin4j.mp.api.CustomApi
* @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 {
return customApi.listOnlineKfAccount();
} }
/** /**

View File

@ -14,10 +14,10 @@ import com.foxinmy.weixin4j.http.apache.FormBodyPart;
import com.foxinmy.weixin4j.http.apache.InputStreamBody; import com.foxinmy.weixin4j.http.apache.InputStreamBody;
import com.foxinmy.weixin4j.http.weixin.ApiResult; import com.foxinmy.weixin4j.http.weixin.ApiResult;
import com.foxinmy.weixin4j.http.weixin.WeixinResponse; import com.foxinmy.weixin4j.http.weixin.WeixinResponse;
import com.foxinmy.weixin4j.model.Pageable;
import com.foxinmy.weixin4j.model.Token; import com.foxinmy.weixin4j.model.Token;
import com.foxinmy.weixin4j.mp.model.KfAccount; import com.foxinmy.weixin4j.mp.model.KfAccount;
import com.foxinmy.weixin4j.mp.model.KfChatRecord; 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;
import com.foxinmy.weixin4j.mp.model.KfSession.KfSessionCounter; import com.foxinmy.weixin4j.mp.model.KfSession.KfSessionCounter;
import com.foxinmy.weixin4j.token.TokenManager; import com.foxinmy.weixin4j.token.TokenManager;
@ -50,8 +50,8 @@ public class CustomApi extends MpApi {
* 查询开始时间 * 查询开始时间
* @param endTime * @param endTime
* 查询结束时间 每次查询不能跨日查询 * 查询结束时间 每次查询不能跨日查询
* @param pageable * @param number
* 分页数据 * 最多10000条
* @throws WeixinException * @throws WeixinException
* @see com.foxinmy.weixin4j.mp.model.KfChatRecord * @see com.foxinmy.weixin4j.mp.model.KfChatRecord
* @see <a href="http://dkf.qq.com/document-1_1.html">查询客服聊天记录</a> * @see <a href="http://dkf.qq.com/document-1_1.html">查询客服聊天记录</a>
@ -59,61 +59,70 @@ public class CustomApi extends MpApi {
* "https://mp.weixin.qq.com/wiki?t=resource/res_main&id=mp1458044854&token=&lang=zh_CN"> * "https://mp.weixin.qq.com/wiki?t=resource/res_main&id=mp1458044854&token=&lang=zh_CN">
* 查询客服聊天记录</a> * 查询客服聊天记录</a>
*/ */
public List<KfChatRecord> getKfChatRecord(Date startTime, Date endTime, Pageable pageable) throws WeixinException { public List<KfChatRecord> getKfChatRecord(Date startTime, Date endTime,
int number) throws WeixinException {
List<KfChatRecord> records = new ArrayList<KfChatRecord>(); List<KfChatRecord> records = new ArrayList<KfChatRecord>();
String kf_chatrecord_uri = getRequestUri("kf_chatrecord_uri"); String kf_chatrecord_uri = getRequestUri("kf_chatrecord_uri");
Token token = tokenManager.getCache(); Token token = tokenManager.getCache();
JSONObject obj = new JSONObject(); JSONObject obj = new JSONObject();
obj.put("starttime", startTime.getTime() / 1000); obj.put("starttime", startTime.getTime() / 1000);
obj.put("endtime", endTime.getTime() / 1000); obj.put("endtime", endTime.getTime() / 1000);
for (int i = 0; i < (int) Math.ceil(pageable.getPageSize() / 50d); i++) { obj.put("msgid", "1");
obj.put("pagesize", Math.min(50, pageable.getPageSize())); obj.put("number", Math.min(10000, number));
obj.put("pageindex", pageable.getPageNumber()); JSONObject result = null;
WeixinResponse response = weixinExecutor.post(String.format(kf_chatrecord_uri, token.getAccessToken()), do {
WeixinResponse response = weixinExecutor.post(
String.format(kf_chatrecord_uri, token.getAccessToken()),
obj.toJSONString()); obj.toJSONString());
result = response.getAsJson();
String text = response.getAsJson().getString("recordlist"); String text = result.getString("recordlist");
if (StringUtil.isBlank(text) || "[]".equals(text)) { if (StringUtil.isBlank(text) || "[]".equals(text)) {
break; break;
} }
records.addAll(JSON.parseArray(text, KfChatRecord.class)); records.addAll(JSON.parseArray(text, KfChatRecord.class));
obj.put("msgid", result.getString("msgid"));
pageable = new Pageable(pageable.getPageNumber() + 1, } while (obj.getIntValue("number") == result.getIntValue("number"));
Math.min(50, Math.max(1, pageable.getPageSize() - ((i + 1) * 50))));
}
return records; return records;
} }
/** /**
* 获取公众号中所设置的客服基本信息包括客服工号客服昵称客服登录账号 * 获取公众号中所设置的客服基本信息包括客服工号客服昵称客服登录账号
* *
* @param isOnline
* 是否在线 为ture时可以可以获取客服在线状态手机在线PC客户端在线手机和PC客户端全都在线客服自动接入最大值
* 客服当前接待客户数
* @return 多客服信息列表 * @return 多客服信息列表
* @see com.foxinmy.weixin4j.mp.model.KfAccount * @see com.foxinmy.weixin4j.mp.model.KfAccount
* @see <a href="http://dkf.qq.com/document-3_1.html">获取客服基本信息</a>
* @see <a href= * @see <a href=
* "https://mp.weixin.qq.com/wiki?t=resource/res_main&id=mp1458044813&token=&lang=zh_CN"> * "https://mp.weixin.qq.com/wiki?t=resource/res_main&id=mp1458044813&token=&lang=zh_CN">
* 获取客服基本信息</a> * 获取客服基本信息</a>
* @see <a href="http://dkf.qq.com/document-3_2.html">获取在线客服接待信息</a>
* @throws WeixinException * @throws WeixinException
*/ */
public List<KfAccount> listKfAccount(boolean isOnline) throws WeixinException { public List<KfAccount> listKfAccount() throws WeixinException {
Token token = tokenManager.getCache(); Token token = tokenManager.getCache();
String text = ""; String kf_list_uri = getRequestUri("kf_list_uri");
if (isOnline) { WeixinResponse response = weixinExecutor.get(String.format(kf_list_uri,
String kf_onlinelist_uri = getRequestUri("kf_onlinelist_uri"); token.getAccessToken()));
WeixinResponse response = weixinExecutor.get(String.format(kf_onlinelist_uri, token.getAccessToken())); String text = response.getAsJson().getString("kf_list");
text = response.getAsJson().getString("kf_online_list");
} else {
String kf_list_uri = getRequestUri("kf_list_uri");
WeixinResponse response = weixinExecutor.get(String.format(kf_list_uri, token.getAccessToken()));
text = response.getAsJson().getString("kf_list");
}
return JSON.parseArray(text, KfAccount.class); 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);
}
/** /**
* 新增客服账号 * 新增客服账号
* *
@ -130,14 +139,16 @@ public class CustomApi extends MpApi {
* "https://mp.weixin.qq.com/wiki?t=resource/res_main&id=mp1458044813&token=&lang=zh_CN"> * "https://mp.weixin.qq.com/wiki?t=resource/res_main&id=mp1458044813&token=&lang=zh_CN">
* 新增客服账号</a> * 新增客服账号</a>
*/ */
public ApiResult createKfAccount(String id, String name, String pwd) throws WeixinException { public ApiResult createKfAccount(String id, String name, String pwd)
throws WeixinException {
JSONObject obj = new JSONObject(); JSONObject obj = new JSONObject();
obj.put("kf_account", id); obj.put("kf_account", id);
obj.put("nickname", name); obj.put("nickname", name);
obj.put("password", DigestUtil.MD5(pwd)); obj.put("password", DigestUtil.MD5(pwd));
String kf_create_uri = getRequestUri("kf_create_uri"); String kf_create_uri = getRequestUri("kf_create_uri");
Token token = tokenManager.getCache(); Token token = tokenManager.getCache();
WeixinResponse response = weixinExecutor.post(String.format(kf_create_uri, token.getAccessToken()), WeixinResponse response = weixinExecutor.post(
String.format(kf_create_uri, token.getAccessToken()),
obj.toJSONString()); obj.toJSONString());
return response.getAsResult(); return response.getAsResult();
} }
@ -158,14 +169,16 @@ public class CustomApi extends MpApi {
* "https://mp.weixin.qq.com/wiki?t=resource/res_main&id=mp1458044813&token=&lang=zh_CN"> * "https://mp.weixin.qq.com/wiki?t=resource/res_main&id=mp1458044813&token=&lang=zh_CN">
* 新增客服账号</a> * 新增客服账号</a>
*/ */
public ApiResult updateKfAccount(String id, String name, String pwd) throws WeixinException { public ApiResult updateKfAccount(String id, String name, String pwd)
throws WeixinException {
JSONObject obj = new JSONObject(); JSONObject obj = new JSONObject();
obj.put("kf_account", id); obj.put("kf_account", id);
obj.put("nickname", name); obj.put("nickname", name);
obj.put("password", DigestUtil.MD5(pwd)); obj.put("password", DigestUtil.MD5(pwd));
String kf_update_uri = getRequestUri("kf_update_uri"); String kf_update_uri = getRequestUri("kf_update_uri");
Token token = tokenManager.getCache(); Token token = tokenManager.getCache();
WeixinResponse response = weixinExecutor.post(String.format(kf_update_uri, token.getAccessToken()), WeixinResponse response = weixinExecutor.post(
String.format(kf_update_uri, token.getAccessToken()),
obj.toJSONString()); obj.toJSONString());
return response.getAsResult(); return response.getAsResult();
} }
@ -185,13 +198,15 @@ public class CustomApi extends MpApi {
* >邀请绑定客服帐号<a/> * >邀请绑定客服帐号<a/>
* @throws WeixinException * @throws WeixinException
*/ */
public ApiResult inviteKfAccount(String kfAccount, String inviteAccount) throws WeixinException { public ApiResult inviteKfAccount(String kfAccount, String inviteAccount)
throws WeixinException {
JSONObject obj = new JSONObject(); JSONObject obj = new JSONObject();
obj.put("kf_account", kfAccount); obj.put("kf_account", kfAccount);
obj.put("invite_wx", inviteAccount); obj.put("invite_wx", inviteAccount);
String kf_invite_uri = getRequestUri("kf_invite_uri"); String kf_invite_uri = getRequestUri("kf_invite_uri");
Token token = tokenManager.getCache(); Token token = tokenManager.getCache();
WeixinResponse response = weixinExecutor.post(String.format(kf_invite_uri, token.getAccessToken()), WeixinResponse response = weixinExecutor.post(
String.format(kf_invite_uri, token.getAccessToken()),
obj.toJSONString()); obj.toJSONString());
return response.getAsResult(); return response.getAsResult();
} }
@ -211,18 +226,22 @@ public class CustomApi extends MpApi {
* "https://mp.weixin.qq.com/wiki?t=resource/res_main&id=mp1458044813&token=&lang=zh_CN"> * "https://mp.weixin.qq.com/wiki?t=resource/res_main&id=mp1458044813&token=&lang=zh_CN">
* 上传客服头像</a> * 上传客服头像</a>
*/ */
public ApiResult uploadKfAvatar(String accountId, InputStream is, String fileName) throws WeixinException { public ApiResult uploadKfAvatar(String accountId, InputStream is,
String fileName) throws WeixinException {
if (StringUtil.isBlank(fileName)) { if (StringUtil.isBlank(fileName)) {
fileName = ObjectId.get().toHexString(); fileName = ObjectId.get().toHexString();
} }
if (StringUtil.isBlank(FileUtil.getFileExtension(fileName))) { if (StringUtil.isBlank(FileUtil.getFileExtension(fileName))) {
fileName = String.format("%s.jpg", fileName); fileName = String.format("%s.jpg", fileName);
} }
MimeType mimeType = new MimeType("image", FileUtil.getFileExtension(fileName)); MimeType mimeType = new MimeType("image",
FileUtil.getFileExtension(fileName));
Token token = tokenManager.getCache(); Token token = tokenManager.getCache();
String kf_avatar_uri = getRequestUri("kf_avatar_uri"); String kf_avatar_uri = getRequestUri("kf_avatar_uri");
WeixinResponse response = weixinExecutor.post(String.format(kf_avatar_uri, token.getAccessToken(), accountId), WeixinResponse response = weixinExecutor
new FormBodyPart("media", new InputStreamBody(is, mimeType.toString(), fileName))); .post(String.format(kf_avatar_uri, token.getAccessToken(),
accountId), new FormBodyPart("media",
new InputStreamBody(is, mimeType.toString(), fileName)));
return response.getAsResult(); return response.getAsResult();
} }
@ -241,7 +260,8 @@ public class CustomApi extends MpApi {
public ApiResult deleteKfAccount(String id) throws WeixinException { public ApiResult deleteKfAccount(String id) throws WeixinException {
Token token = tokenManager.getCache(); Token token = tokenManager.getCache();
String kf_delete_uri = getRequestUri("kf_delete_uri"); String kf_delete_uri = getRequestUri("kf_delete_uri");
WeixinResponse response = weixinExecutor.get(String.format(kf_delete_uri, token.getAccessToken(), id)); WeixinResponse response = weixinExecutor.get(String.format(
kf_delete_uri, token.getAccessToken(), id));
return response.getAsResult(); return response.getAsResult();
} }
@ -265,14 +285,16 @@ public class CustomApi extends MpApi {
* "https://mp.weixin.qq.com/wiki?t=resource/res_main&id=mp1458044820&token=&lang=zh_CN"> * "https://mp.weixin.qq.com/wiki?t=resource/res_main&id=mp1458044820&token=&lang=zh_CN">
* 创建会话</a> * 创建会话</a>
*/ */
public ApiResult createKfSession(String userOpenId, String kfAccount, String text) throws WeixinException { public ApiResult createKfSession(String userOpenId, String kfAccount,
String text) throws WeixinException {
Token token = tokenManager.getCache(); Token token = tokenManager.getCache();
String kfsession_create_uri = getRequestUri("kfsession_create_uri"); String kfsession_create_uri = getRequestUri("kfsession_create_uri");
JSONObject obj = new JSONObject(); JSONObject obj = new JSONObject();
obj.put("openid", userOpenId); obj.put("openid", userOpenId);
obj.put("kf_account", kfAccount); obj.put("kf_account", kfAccount);
obj.put("text", text); obj.put("text", text);
WeixinResponse response = weixinExecutor.post(String.format(kfsession_create_uri, token.getAccessToken()), WeixinResponse response = weixinExecutor.post(
String.format(kfsession_create_uri, token.getAccessToken()),
obj.toJSONString()); obj.toJSONString());
return response.getAsResult(); return response.getAsResult();
@ -293,14 +315,16 @@ public class CustomApi extends MpApi {
* "https://mp.weixin.qq.com/wiki?t=resource/res_main&id=mp1458044820&token=&lang=zh_CN"> * "https://mp.weixin.qq.com/wiki?t=resource/res_main&id=mp1458044820&token=&lang=zh_CN">
* 关闭会话</a> * 关闭会话</a>
*/ */
public ApiResult closeKfSession(String userOpenId, String kfAccount, String text) throws WeixinException { public ApiResult closeKfSession(String userOpenId, String kfAccount,
String text) throws WeixinException {
Token token = tokenManager.getCache(); Token token = tokenManager.getCache();
String kfsession_close_uri = getRequestUri("kfsession_close_uri"); String kfsession_close_uri = getRequestUri("kfsession_close_uri");
JSONObject obj = new JSONObject(); JSONObject obj = new JSONObject();
obj.put("openid", userOpenId); obj.put("openid", userOpenId);
obj.put("kf_account", kfAccount); obj.put("kf_account", kfAccount);
obj.put("text", text); obj.put("text", text);
WeixinResponse response = weixinExecutor.post(String.format(kfsession_close_uri, token.getAccessToken()), WeixinResponse response = weixinExecutor.post(
String.format(kfsession_close_uri, token.getAccessToken()),
obj.toJSONString()); obj.toJSONString());
return response.getAsResult(); return response.getAsResult();
@ -321,11 +345,12 @@ public class CustomApi extends MpApi {
public KfSession getKfSession(String userOpenId) throws WeixinException { public KfSession getKfSession(String userOpenId) throws WeixinException {
Token token = tokenManager.getCache(); Token token = tokenManager.getCache();
String kfsession_get_uri = getRequestUri("kfsession_get_uri"); String kfsession_get_uri = getRequestUri("kfsession_get_uri");
WeixinResponse response = weixinExecutor WeixinResponse response = weixinExecutor.get(String.format(
.get(String.format(kfsession_get_uri, token.getAccessToken(), userOpenId)); kfsession_get_uri, token.getAccessToken(), userOpenId));
KfSession session = response.getAsObject(new TypeReference<KfSession>() { KfSession session = response
}); .getAsObject(new TypeReference<KfSession>() {
});
session.setUserOpenId(userOpenId); session.setUserOpenId(userOpenId);
return session; return session;
} }
@ -342,19 +367,21 @@ public class CustomApi extends MpApi {
* "https://mp.weixin.qq.com/wiki?t=resource/res_main&id=mp1458044820&token=&lang=zh_CN"> * "https://mp.weixin.qq.com/wiki?t=resource/res_main&id=mp1458044820&token=&lang=zh_CN">
* 获取客服的会话列表</a> * 获取客服的会话列表</a>
*/ */
public List<KfSession> listKfSession(String kfAccount) throws WeixinException { public List<KfSession> listKfSession(String kfAccount)
throws WeixinException {
Token token = tokenManager.getCache(); Token token = tokenManager.getCache();
String kfsession_list_uri = getRequestUri("kfsession_list_uri"); String kfsession_list_uri = getRequestUri("kfsession_list_uri");
WeixinResponse response = weixinExecutor WeixinResponse response = weixinExecutor.get(String.format(
.get(String.format(kfsession_list_uri, token.getAccessToken(), kfAccount)); kfsession_list_uri, token.getAccessToken(), kfAccount));
List<KfSession> sessionList = JSON.parseArray(response.getAsJson().getString("sessionlist"), KfSession.class); List<KfSession> sessionList = JSON.parseArray(response.getAsJson()
.getString("sessionlist"), KfSession.class);
return sessionList; return sessionList;
} }
/** /**
* 获取未接入会话列表:获取当前正在等待队列中的会话列表此接口最多返回最早进入队列的100个未接入会话</br> * 获取未接入会话列表:获取当前正在等待队列中的会话列表此接口最多返回最早进入队列的100个未接入会话</br> <font
* <font color="red">缺陷没有count字段</font> * color="red">缺陷没有count字段</font>
* *
* @return 会话列表 * @return 会话列表
* @throws WeixinException * @throws WeixinException
@ -367,7 +394,8 @@ public class CustomApi extends MpApi {
public KfSessionCounter listKfWaitSession() throws WeixinException { public KfSessionCounter listKfWaitSession() throws WeixinException {
Token token = tokenManager.getCache(); Token token = tokenManager.getCache();
String kfsession_wait_uri = getRequestUri("kfsession_wait_uri"); String kfsession_wait_uri = getRequestUri("kfsession_wait_uri");
WeixinResponse response = weixinExecutor.get(String.format(kfsession_wait_uri, token.getAccessToken())); WeixinResponse response = weixinExecutor.get(String.format(
kfsession_wait_uri, token.getAccessToken()));
return response.getAsObject(new TypeReference<KfSessionCounter>() { return response.getAsObject(new TypeReference<KfSessionCounter>() {
}); });

View File

@ -79,7 +79,7 @@ mass_preview_uri={api_cgi_url}/message/mass/preview?access_token=%s
# \u67e5\u8be2\u7fa4\u53d1\u72b6\u6001 # \u67e5\u8be2\u7fa4\u53d1\u72b6\u6001
mass_get_uri={api_cgi_url}/message/mass/get?access_token=%s mass_get_uri={api_cgi_url}/message/mass/get?access_token=%s
# \u5ba2\u670d\u804a\u5929\u8bb0\u5f55 # \u5ba2\u670d\u804a\u5929\u8bb0\u5f55
kf_chatrecord_uri={api_cgi_url}/customservice/getrecord?access_token=%s kf_chatrecord_uri={api_base_url}/customservice/msgrecord/getmsglist?access_token=%s
# \u5ba2\u670d\u57fa\u672c\u4fe1\u606f # \u5ba2\u670d\u57fa\u672c\u4fe1\u606f
kf_list_uri={api_cgi_url}/customservice/getkflist?access_token=%s kf_list_uri={api_cgi_url}/customservice/getkflist?access_token=%s
# \u5728\u7ebf\u5ba2\u670d\u57fa\u672c\u4fe1\u606f # \u5728\u7ebf\u5ba2\u670d\u57fa\u672c\u4fe1\u606f

View File

@ -1,9 +1,10 @@
package com.foxinmy.weixin4j.mp.model; package com.foxinmy.weixin4j.mp.model;
import java.io.Serializable; import java.io.Serializable;
import java.util.Date;
import com.alibaba.fastjson.annotation.JSONField; import com.alibaba.fastjson.annotation.JSONField;
import com.foxinmy.weixin4j.mp.type.KfOnlineStatus; import com.foxinmy.weixin4j.mp.type.KfInviteStatus;
/** /**
* 多客服账号信息 * 多客服账号信息
@ -17,7 +18,11 @@ import com.foxinmy.weixin4j.mp.type.KfOnlineStatus;
public class KfAccount implements Serializable { public class KfAccount implements Serializable {
private static final long serialVersionUID = -4565570894727129245L; private static final long serialVersionUID = -4565570894727129245L;
/**
* 客服工号
*/
@JSONField(name = "kf_id")
private String id;
/** /**
* 客服账号@微信别名 微信别名如有修改旧账号返回旧的微信别名新增的账号返回新的微信别名 * 客服账号@微信别名 微信别名如有修改旧账号返回旧的微信别名新增的账号返回新的微信别名
*/ */
@ -28,32 +33,31 @@ public class KfAccount implements Serializable {
*/ */
@JSONField(name = "kf_nick") @JSONField(name = "kf_nick")
private String nickName; private String nickName;
/**
* 客服工号
*/
@JSONField(name = "kf_id")
private String id;
/** /**
* 客服头像 * 客服头像
*/ */
@JSONField(name = "kf_headimg") @JSONField(name = "kf_headimgurl")
private String headImg; private String headimgurl;
// 以下字段是调用在线客服状态返回的字段
/** /**
* 客服在线状态 1pc在线2手机在线 若pc和手机同时在线则为 1+2=3 * 客服微信
*/ */
private int status; @JSONField(name = "kf_wx")
private String wx;
/** /**
* 客服设置的最大自动接入数 * 客服绑定邀请的微信号
*/ */
@JSONField(name = "auto_accept") @JSONField(name = "invite_wx")
private int autoAccept; private String inviteWx;
/** /**
* 客服当前正在接待的会话数 * 客服邀请的过期时间
*/ */
@JSONField(name = "accepted_case") @JSONField(name = "invite_expire_time")
private int acceptedCase; private long inviteExpireTime;
/**
* 客服邀请的状态
*/
@JSONField(name = "invite_status")
private String inviteStatus;
public String getAccount() { public String getAccount() {
return account; return account;
@ -79,53 +83,62 @@ public class KfAccount implements Serializable {
this.id = id; this.id = id;
} }
public String getHeadImg() { public String getHeadimgurl() {
return headImg; return headimgurl;
} }
public void setHeadImg(String headImg) { public void setHeadimgurl(String headimgurl) {
this.headImg = headImg; this.headimgurl = headimgurl;
} }
public int getStatus() { public String getWx() {
return status; return wx;
}
public void setWx(String wx) {
this.wx = wx;
}
public String getInviteWx() {
return inviteWx;
}
public void setInviteWx(String inviteWx) {
this.inviteWx = inviteWx;
}
public long getInviteExpireTime() {
return inviteExpireTime;
} }
@JSONField(serialize = false) @JSONField(serialize = false)
public KfOnlineStatus getFormatStatus() { public Date getFormatInviteExpireTime() {
if (status == 1) { return new Date(inviteExpireTime * 1000l);
return KfOnlineStatus.PC;
} else if (status == 2) {
return KfOnlineStatus.MOBILE;
} else {
return KfOnlineStatus.BOTH;
}
} }
public void setStatus(int status) { public void setInviteExpireTime(long inviteExpireTime) {
this.status = status; this.inviteExpireTime = inviteExpireTime;
} }
public int getAutoAccept() { public String getInviteStatus() {
return autoAccept; return inviteStatus;
} }
public void setAutoAccept(int autoAccept) { @JSONField(serialize = false)
this.autoAccept = autoAccept; public KfInviteStatus getFormatInviteStatus() {
return inviteStatus != null ? KfInviteStatus.valueOf(inviteStatus
.toUpperCase()) : null;
} }
public int getAcceptedCase() { public void setInviteStatus(String inviteStatus) {
return acceptedCase; this.inviteStatus = inviteStatus;
}
public void setAcceptedCase(int acceptedCase) {
this.acceptedCase = acceptedCase;
} }
@Override @Override
public String toString() { public String toString() {
return "KfAccount [account=" + account + ", nickName=" + nickName return "KfAccount [id=" + id + ", account=" + account + ", nickName="
+ ", id=" + id + ", status=" + status + ", autoAccept=" + nickName + ", headimgurl=" + headimgurl + ", wx=" + wx
+ autoAccept + ", acceptedCase=" + acceptedCase + "]"; + ", inviteWx=" + inviteWx + ", inviteExpireTime="
+ inviteExpireTime + ", inviteStatus=" + inviteStatus + "]";
} }
} }

View File

@ -0,0 +1,102 @@
package com.foxinmy.weixin4j.mp.model;
import java.io.Serializable;
import com.alibaba.fastjson.annotation.JSONField;
import com.foxinmy.weixin4j.mp.type.KfOnlineStatus;
/**
* 多客服在线信息
*
* @className KfOnlineAccount
* @author jinyu(foxinmy@gmail.com)
* @date 2014年11月16日
* @since JDK 1.6
* @see <a href="http://dkf.qq.com/document-3_1.html">多客服账号信息</a>
*/
public class KfOnlineAccount implements Serializable {
private static final long serialVersionUID = -4565570894727129245L;
/**
* 客服工号
*/
@JSONField(name = "kf_id")
private String id;
/**
* 客服账号@微信别名 微信别名如有修改旧账号返回旧的微信别名新增的账号返回新的微信别名
*/
@JSONField(name = "kf_account")
private String account;
/**
* 客服在线状态 1pc在线2手机在线 若pc和手机同时在线则为 1+2=3
*/
private int status;
/**
* 客服设置的最大自动接入数
*/
@JSONField(name = "auto_accept")
private int autoAccept;
/**
* 客服当前正在接待的会话数
*/
@JSONField(name = "accepted_case")
private int acceptedCase;
public String getAccount() {
return account;
}
public void setAccount(String account) {
this.account = account;
}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public int getStatus() {
return status;
}
@JSONField(serialize = false)
public KfOnlineStatus getFormatStatus() {
if (status == 1) {
return KfOnlineStatus.PC;
} else if (status == 2) {
return KfOnlineStatus.MOBILE;
} else {
return KfOnlineStatus.BOTH;
}
}
public void setStatus(int status) {
this.status = status;
}
public int getAutoAccept() {
return autoAccept;
}
public void setAutoAccept(int autoAccept) {
this.autoAccept = autoAccept;
}
public int getAcceptedCase() {
return acceptedCase;
}
public void setAcceptedCase(int acceptedCase) {
this.acceptedCase = acceptedCase;
}
@Override
public String toString() {
return "KfAccount [account=" + account + ", id=" + id + ", status="
+ status + ", autoAccept=" + autoAccept + ", acceptedCase="
+ acceptedCase + "]";
}
}

View File

@ -0,0 +1,23 @@
package com.foxinmy.weixin4j.mp.type;
/**
* 多客服邀请状态
*
* @className KfInviteStatus
* @author jinyu(foxinmy@gmail.com)
* @date 2014年11月16日
* @since JDK 1.6
* @see
*/
public enum KfInviteStatus {
WAITING("等待确认"), REJECTED("被拒绝"), EXPIRED("已过期");
private String desc;
KfInviteStatus(String desc) {
this.desc = desc;
}
public String getDesc() {
return desc;
}
}

View File

@ -13,10 +13,10 @@ import org.junit.Test;
import com.foxinmy.weixin4j.exception.WeixinException; import com.foxinmy.weixin4j.exception.WeixinException;
import com.foxinmy.weixin4j.http.weixin.ApiResult; import com.foxinmy.weixin4j.http.weixin.ApiResult;
import com.foxinmy.weixin4j.model.Pageable;
import com.foxinmy.weixin4j.mp.api.CustomApi; import com.foxinmy.weixin4j.mp.api.CustomApi;
import com.foxinmy.weixin4j.mp.model.KfAccount; import com.foxinmy.weixin4j.mp.model.KfAccount;
import com.foxinmy.weixin4j.mp.model.KfChatRecord; 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;
import com.foxinmy.weixin4j.mp.model.KfSession.KfSessionCounter; import com.foxinmy.weixin4j.mp.model.KfSession.KfSessionCounter;
@ -47,19 +47,19 @@ public class CustomTest extends TokenTest {
calendar.set(Calendar.HOUR_OF_DAY, 21); calendar.set(Calendar.HOUR_OF_DAY, 21);
Date endtime = calendar.getTime(); Date endtime = calendar.getTime();
List<KfChatRecord> recordList = customApi.getKfChatRecord(starttime, List<KfChatRecord> recordList = customApi.getKfChatRecord(starttime,
endtime, new Pageable(1, 70)); endtime, 10);
Assert.assertFalse(recordList.isEmpty()); Assert.assertFalse(recordList.isEmpty());
System.out.println(recordList); System.out.println(recordList);
} }
@Test @Test
public void kfList() throws WeixinException { public void kfList() throws WeixinException {
List<KfAccount> kfList = customApi.listKfAccount(false); List<KfAccount> kfList = customApi.listKfAccount();
Assert.assertFalse(kfList.isEmpty());
System.out.println(kfList);
kfList = customApi.listKfAccount(true);
Assert.assertFalse(kfList.isEmpty()); Assert.assertFalse(kfList.isEmpty());
System.out.println(kfList); System.out.println(kfList);
List<KfOnlineAccount> kfOnlineList = customApi.listOnlineKfAccount();
Assert.assertFalse(kfOnlineList.isEmpty());
System.out.println(kfOnlineList);
} }
@Test @Test