WindChat/windchat-business/src/main/java/com/windchat/im/business/impl/tai/ApiPluginService.java

332 lines
13 KiB
Java
Raw Normal View History

2019-07-29 23:42:16 +08:00
/**
* Copyright 2018-2028 Akaxin Group
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
2019-11-27 23:33:33 +08:00
package com.windchat.im.business.impl.tai;
2019-07-29 23:42:16 +08:00
import java.util.Base64;
import java.util.List;
import java.util.Map;
//import org.apache.commons.codec.binary.Base64;
2019-11-27 23:33:33 +08:00
import com.windchat.im.business.dao.SitePluginDao;
import com.windchat.im.business.impl.AbstractRequest;
import com.windchat.im.business.impl.site.SiteConfig;
2019-07-29 23:42:16 +08:00
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.akaxin.common.command.Command;
import com.akaxin.common.command.CommandResponse;
import com.akaxin.common.constant.CharsetCoding;
import com.akaxin.common.constant.CommandConst;
import com.akaxin.common.constant.ErrorCode2;
import com.akaxin.common.constant.IErrorCode;
import com.akaxin.common.crypto.AESCrypto;
import com.akaxin.common.exceptions.ZalyException2;
import com.akaxin.common.http.ZalyHttpClient;
import com.akaxin.common.logs.LogUtils;
import com.akaxin.proto.core.CoreProto;
import com.akaxin.proto.core.PluginProto;
import com.akaxin.proto.site.ApiPluginListProto;
import com.akaxin.proto.site.ApiPluginPageProto;
import com.akaxin.proto.site.ApiPluginProxyProto;
import com.akaxin.site.business.dao.SitePluginDao;
import com.akaxin.site.business.impl.AbstractRequest;
import com.akaxin.site.business.impl.site.SiteConfig;
2019-07-31 23:12:30 +08:00
import com.windchat.im.storage.bean.PluginBean;
2019-07-29 23:42:16 +08:00
import com.google.protobuf.ByteString;
/**
* 处理客户端与服务点扩展之间功能
*
* @author Sam{@link an.guoyue254@gmail.com}
* @since 2017-12-11 14:46:28
*/
public class ApiPluginService extends AbstractRequest {
private static Logger logger = LoggerFactory.getLogger(ApiPluginService.class);
private static final String HTTP_PREFFIX = "http://";
private static final String HTTPS_PREFFIX = "https://";
/**
* 分页获取扩展列表
*
* @param command
* @return
*/
public CommandResponse list(Command command) {
CommandResponse commandResponse = new CommandResponse().setAction(CommandConst.ACTION_RES);
IErrorCode errCode = ErrorCode2.ERROR;
try {
ApiPluginListProto.ApiPluginListRequest request = ApiPluginListProto.ApiPluginListRequest
.parseFrom(command.getParams());
String siteUserId = command.getSiteUserId();
String sessionId = command.getHeader().get(CoreProto.HeaderKey.CLIENT_SOCKET_SITE_SESSION_ID_VALUE);
int pageNumber = request.getPageNumber();
int pageSize = request.getPageSize();
PluginProto.PluginPosition position = request.getPosition();
LogUtils.requestDebugLog(logger, command, request.toString());
pageNumber = Math.max(pageNumber, 1);// 从第一页开始
// 支持首页以及消息聊天界面扩展
if (PluginProto.PluginPosition.HOME_PAGE != position && PluginProto.PluginPosition.MSG_PAGE != position) {
throw new ZalyException2(ErrorCode2.ERROR2_PLUGIN_STATUS);
}
List<PluginBean> pluginList = null;
if (StringUtils.isNotBlank(siteUserId) && SiteConfig.isSiteManager(siteUserId)) {
pluginList = SitePluginDao.getInstance().getAdminPluginPageList(pageNumber, pageSize,
position.getNumber());
} else {
pluginList = SitePluginDao.getInstance().getOrdinaryPluginPageList(pageNumber, pageSize,
position.getNumber());
}
if (pluginList != null) {
ApiPluginListProto.ApiPluginListResponse.Builder responseBuilder = ApiPluginListProto.ApiPluginListResponse
.newBuilder();
for (PluginBean bean : pluginList) {
PluginProto.Plugin.Builder pluginBuilder = getPluginProtoBuilder(bean);
String authKey = bean.getAuthKey();
if (StringUtils.isNotEmpty(authKey)) {
byte[] tsk = bean.getAuthKey().getBytes(CharsetCoding.ISO_8859_1);
byte[] encryptedSessionId = AESCrypto.encrypt(tsk,
sessionId.getBytes(CharsetCoding.ISO_8859_1));
String base64UrlSafeSessionId = Base64.getUrlEncoder().encodeToString(encryptedSessionId);
pluginBuilder.setEncryptedSessionIdBase64(base64UrlSafeSessionId);
}
responseBuilder.addPlugin(pluginBuilder.build());
}
commandResponse.setParams(responseBuilder.build().toByteArray());
errCode = ErrorCode2.SUCCESS;
}
} catch (Exception e) {
errCode = ErrorCode2.ERROR_SYSTEMERROR;
LogUtils.requestErrorLog(logger, command, e);
} catch (ZalyException2 e) {
errCode = e.getErrCode();
LogUtils.requestErrorLog(logger, command, e);
}
return commandResponse.setErrCode(errCode);
}
/**
* <pre>
* 获取插件扩展的展示页面,支持两种方式
* 1.非加密方式此时扩展authkey不存在
* 2.加密方式此时扩展authkey存在
* </pre>
*
* @param command
* @return
*/
public CommandResponse page(Command command) {
CommandResponse commandResponse = new CommandResponse().setAction(CommandConst.ACTION_RES);
ErrorCode2 errCode = ErrorCode2.ERROR;
try {
ApiPluginPageProto.ApiPluginPageRequest request = ApiPluginPageProto.ApiPluginPageRequest
.parseFrom(command.getParams());
String siteUserId = command.getSiteUserId();
String pluginId = request.getPluginId();
String requestPage = request.getPage();// /index || index.php || index.html
String requestParams = request.getParams();
LogUtils.requestDebugLog(logger, command, request.toString());
Map<Integer, String> header = command.getHeader();
String siteSessionId = header.get(CoreProto.HeaderKey.CLIENT_SOCKET_SITE_SESSION_ID_VALUE);
String pluginRefere = header.get(CoreProto.HeaderKey.PLUGIN_CLIENT_REFERER_VALUE);
if (StringUtils.isNoneEmpty(siteUserId, pluginId)) {
PluginBean bean = SitePluginDao.getInstance().getPluginProfile(Integer.valueOf(pluginId));
if (bean != null && bean.getApiUrl() != null) {
String pageUrl = buildUrl(bean.getApiUrl(), requestPage, bean.getUrlPage());
logger.debug("http request uri={}", pageUrl);
PluginProto.ProxyPluginPackage.Builder packageBuilder = PluginProto.ProxyPluginPackage.newBuilder();
packageBuilder.putPluginHeader(PluginProto.PluginHeaderKey.CLIENT_SITE_USER_ID_VALUE, siteUserId);
packageBuilder.putPluginHeader(PluginProto.PluginHeaderKey.CLIENT_SITE_SESSION_ID_VALUE,
siteSessionId);
packageBuilder.putPluginHeader(PluginProto.PluginHeaderKey.PLUGIN_ID_VALUE, pluginId);
packageBuilder.putPluginHeader(PluginProto.PluginHeaderKey.PLUGIN_TIMESTAMP_VALUE,
String.valueOf(System.currentTimeMillis()));
if (StringUtils.isNotEmpty(pluginRefere)) {
packageBuilder.putPluginHeader(PluginProto.PluginHeaderKey.PLUGIN_REFERER_VALUE, pluginRefere);
}
if (StringUtils.isNotEmpty(requestParams)) {
packageBuilder.setData(requestParams);
}
byte[] httpContent = packageBuilder.build().toByteArray();
String authKey = bean.getAuthKey();
if (StringUtils.isNotEmpty(authKey)) {
// AES 加密整个proto通过http传输给plugin
byte[] tsk = bean.getAuthKey().getBytes(CharsetCoding.ISO_8859_1);
byte[] enPostContent = AESCrypto.encrypt(tsk, httpContent);
httpContent = enPostContent;
}
byte[] httpResponse = ZalyHttpClient.getInstance().postBytes(pageUrl, httpContent);
if (httpResponse != null) {
ApiPluginProxyProto.ApiPluginProxyResponse response = ApiPluginProxyProto.ApiPluginProxyResponse
.newBuilder().setData(ByteString.copyFrom(httpResponse)).build();
commandResponse.setParams(response.toByteArray());
errCode = ErrorCode2.SUCCESS;
} else {
logger.error("http request uri={} response={}", pageUrl, httpResponse);
}
}
} else {
errCode = ErrorCode2.ERROR_PARAMETER;
}
} catch (Exception e) {
errCode = ErrorCode2.ERROR_SYSTEMERROR;
LogUtils.requestErrorLog(logger, command, e);
}
return commandResponse.setErrCode2(errCode);
}
/**
* <pre>
* 代理前台客户端中扩展的请求
* 1.界面请求后台一般使用http请求
* 2.使用tcp代理代替http请求
* </pre>
*
* @param command
* @return
*/
public CommandResponse proxy(Command command) {
CommandResponse commandResponse = new CommandResponse().setAction(CommandConst.ACTION_RES);
ErrorCode2 errCode = ErrorCode2.ERROR;
try {
ApiPluginProxyProto.ApiPluginProxyRequest request = ApiPluginProxyProto.ApiPluginProxyRequest
.parseFrom(command.getParams());
String siteUserId = command.getSiteUserId();
String pluginId = request.getPluginId();
String requestApi = request.getApi();
String requestParams = request.getParams();
LogUtils.requestDebugLog(logger, command, request.toString());
Map<Integer, String> header = command.getHeader();
String siteSessionId = header.get(CoreProto.HeaderKey.CLIENT_SOCKET_SITE_SESSION_ID_VALUE);
String pluginRefere = header.get(CoreProto.HeaderKey.PLUGIN_CLIENT_REFERER_VALUE);
if (!StringUtils.isAnyBlank(siteUserId, pluginId, requestApi)) {
PluginBean bean = SitePluginDao.getInstance().getPluginProfile(Integer.valueOf(pluginId));
if (bean != null && bean.getApiUrl() != null) {
String pluginUrl = this.buildUrl(bean.getApiUrl(), requestApi, null);
logger.debug("action={} pluginId={} api={} url={} params={}", command.getAction(), pluginId,
requestApi, pluginUrl, requestParams);
PluginProto.ProxyPluginPackage.Builder packageBuilder = PluginProto.ProxyPluginPackage.newBuilder();
packageBuilder.putPluginHeader(PluginProto.PluginHeaderKey.CLIENT_SITE_USER_ID_VALUE, siteUserId);
packageBuilder.putPluginHeader(PluginProto.PluginHeaderKey.CLIENT_SITE_SESSION_ID_VALUE,
siteSessionId);
packageBuilder.putPluginHeader(PluginProto.PluginHeaderKey.PLUGIN_ID_VALUE, pluginId);
packageBuilder.putPluginHeader(PluginProto.PluginHeaderKey.PLUGIN_TIMESTAMP_VALUE,
String.valueOf(System.currentTimeMillis()));
if (StringUtils.isNotEmpty(pluginRefere)) {
packageBuilder.putPluginHeader(PluginProto.PluginHeaderKey.PLUGIN_REFERER_VALUE, pluginRefere);
}
if (StringUtils.isNotEmpty(requestParams)) {
packageBuilder.setData(requestParams);
}
byte[] httpContent = packageBuilder.build().toByteArray();
String authKey = bean.getAuthKey();
if (StringUtils.isNotEmpty(authKey)) {
// AES 加密整个proto通过http传输给plugin
// byte[] tsk = AESCrypto.generateTSKey(bean.getAuthKey());
byte[] tsk = bean.getAuthKey().getBytes(CharsetCoding.ISO_8859_1);
byte[] enPostContent = AESCrypto.encrypt(tsk, httpContent);
httpContent = enPostContent;
}
byte[] httpResponse = ZalyHttpClient.getInstance().postBytes(pluginUrl, httpContent);
if (httpResponse != null) {
ApiPluginProxyProto.ApiPluginProxyResponse response = ApiPluginProxyProto.ApiPluginProxyResponse
.newBuilder().setData(ByteString.copyFrom(httpResponse)).build();
commandResponse.setParams(response.toByteArray());// httpResposne,callback方法的回调方法参数
}
errCode = ErrorCode2.SUCCESS;
}
} else {
errCode = ErrorCode2.ERROR_PARAMETER;
}
} catch (Exception e) {
errCode = ErrorCode2.ERROR_SYSTEMERROR;
LogUtils.requestErrorLog(logger, command, e);
}
return commandResponse.setErrCode2(errCode);
}
private PluginProto.Plugin.Builder getPluginProtoBuilder(PluginBean bean) {
PluginProto.Plugin.Builder pluginBuilder = PluginProto.Plugin.newBuilder();
pluginBuilder.setId(String.valueOf(bean.getId()));
if (StringUtils.isNotBlank(bean.getName())) {
pluginBuilder.setName(bean.getName());
}
if (StringUtils.isNotBlank(bean.getIcon())) {
pluginBuilder.setIcon(bean.getIcon());
}
if (StringUtils.isNotBlank(bean.getUrlPage())) {
pluginBuilder.setUrlPage(bean.getUrlPage());
}
if (StringUtils.isNotBlank(bean.getApiUrl())) {
pluginBuilder.setApiUrl(bean.getApiUrl());
}
if (StringUtils.isNotBlank(bean.getAuthKey())) {
pluginBuilder.setAuthKey(bean.getAuthKey());
}
if (StringUtils.isNotBlank(bean.getAllowedIp())) {
pluginBuilder.setAllowedIp(bean.getAllowedIp());
}
pluginBuilder.setOrder(bean.getSort());
pluginBuilder.setPositionValue(bean.getPosition());
pluginBuilder.setPermissionStatusValue(bean.getPermissionStatus());
pluginBuilder.setDisplayModeValue(bean.getDisplayMode());
// pluginBuilder.setEncryptedSessionIdBase64(value)
return pluginBuilder;
}
private String buildUrl(String apiUrl, String apiName, String defaultPage) {
String pageUrl = HTTP_PREFFIX;
if (apiUrl.startsWith(HTTP_PREFFIX) || apiUrl.startsWith(HTTPS_PREFFIX)) {
pageUrl = apiUrl;
} else {
pageUrl += apiUrl;
}
if (StringUtils.isNotEmpty(apiName)) {
if (apiName.startsWith("/")) {
pageUrl += apiName;
} else {
pageUrl += "/" + apiName;
}
} else {
if (StringUtils.isNotEmpty(defaultPage)) {
if (defaultPage.startsWith("/")) {
pageUrl += defaultPage;
} else {
pageUrl += "/" + defaultPage;
}
}
}
return pageUrl;
}
}