ВКонтакте - пример интеграции
Материал из BiTel WiKi
(Различия между версиями)
Dog (Обсуждение | вклад) |
Dog (Обсуждение | вклад) |
||
(5 промежуточных версий не показаны.) | |||
Строка 1: | Строка 1: | ||
+ | Функциональность: | ||
+ | * Получение новых(не прочитанных сообщений из паблика VK). | ||
+ | * Отображение полученных сообщений в BGCRM -> Сообщения. | ||
+ | * Оповещение о новых сообщениях в счётчике новых не прочитанных сообщений BGCRM. | ||
+ | |||
+ | дальнейшая обработка сообщений в BGCRM не реализована и заблокирована. Общение происходит в паблике ВК | ||
+ | |||
+ | |||
реализация API. Для того чтобы работало в конфигурацию надо добавить: | реализация API. Для того чтобы работало в конфигурацию надо добавить: | ||
* vk.access.token - токен авторизации для приложения. брать в настройках паблика. | * vk.access.token - токен авторизации для приложения. брать в настройках паблика. | ||
* vk.v - версия API. на момент реализации была 5.60 | * vk.v - версия API. на момент реализации была 5.60 | ||
* vk.pname - отображаемое имя паблика. | * vk.pname - отображаемое имя паблика. | ||
+ | * vk.mtip - ID типа сообщения из конфигурации BGCRM | ||
<source lang="java"> | <source lang="java"> | ||
Строка 46: | Строка 55: | ||
*/ | */ | ||
private String VK_PUBLIC_NAME; | private String VK_PUBLIC_NAME; | ||
+ | /** | ||
+ | * Тип сообщений в BGCRM | ||
+ | */ | ||
+ | private String VK_MESSAGE_TID; | ||
+ | |||
public VkAPI(){ | public VkAPI(){ | ||
Строка 51: | Строка 65: | ||
VK_V = Setup.getSetup().get("vk.v", "5.60"); | VK_V = Setup.getSetup().get("vk.v", "5.60"); | ||
VK_PUBLIC_NAME = Setup.getSetup().get("vk.pname", "ООО \"Рога и копыта\""); | VK_PUBLIC_NAME = Setup.getSetup().get("vk.pname", "ООО \"Рога и копыта\""); | ||
+ | VK_MESSAGE_TID = Setup.getSetup().get("vk.mtip", "200"); | ||
} | } | ||
Строка 101: | Строка 116: | ||
message.setSubject(vkMessage.body); | message.setSubject(vkMessage.body); | ||
message.setTo(VK_PUBLIC_NAME); | message.setTo(VK_PUBLIC_NAME); | ||
- | message.setTypeId( | + | message.setTypeId(Integer.valueOf(VK_MESSAGE_TID)); |
message.setProcessed(false); | message.setProcessed(false); | ||
message.setSystemId(String.valueOf(vkMessage.fromId)); | message.setSystemId(String.valueOf(vkMessage.fromId)); | ||
Строка 132: | Строка 147: | ||
return jsonString; | return jsonString; | ||
+ | } | ||
+ | |||
+ | } | ||
+ | </source> | ||
+ | |||
+ | класс диалога VK | ||
+ | |||
+ | <source lang="java"> | ||
+ | package ru.bgcrm.dyn.vk; | ||
+ | |||
+ | import java.util.List; | ||
+ | |||
+ | import org.json.JSONObject; | ||
+ | |||
+ | public class VkDialog { | ||
+ | |||
+ | /** | ||
+ | * | ||
+ | */ | ||
+ | Integer userId; | ||
+ | /** | ||
+ | * | ||
+ | */ | ||
+ | List<VkMessage> messageList; | ||
+ | /** | ||
+ | * | ||
+ | */ | ||
+ | Integer inRead; | ||
+ | /** | ||
+ | * | ||
+ | */ | ||
+ | Integer outRead; | ||
+ | /** | ||
+ | * | ||
+ | */ | ||
+ | VkMessage lastMessage; | ||
+ | |||
+ | |||
+ | public VkDialog (){ | ||
+ | |||
+ | } | ||
+ | |||
+ | public VkDialog(int user_id, int in_read, int out_read, JSONObject jmessage) { | ||
+ | userId = user_id; | ||
+ | inRead = in_read; | ||
+ | outRead = out_read; | ||
+ | VkMessage vkMessage = new VkMessage(jmessage.getInt("id"), | ||
+ | jmessage.getInt("user_id"), | ||
+ | jmessage.getInt("user_id"), | ||
+ | jmessage.getInt("date"), | ||
+ | jmessage.getInt("read_state"), | ||
+ | jmessage.getInt("out"), | ||
+ | jmessage.getString("body")); | ||
+ | lastMessage = vkMessage; | ||
} | } | ||
Строка 165: | Строка 234: | ||
</source> | </source> | ||
- | |||
класс MessageTypeVK: | класс MessageTypeVK: | ||
+ | <source lang="java"> | ||
package ru.bgcrm.dyn.vk; | package ru.bgcrm.dyn.vk; | ||
Строка 312: | Строка 381: | ||
} | } | ||
+ | </source> | ||
+ | |||
+ | в конфигурации BGCRM создаем новый тип сообщений: | ||
+ | |||
+ | <source lang="bash"> | ||
+ | ### Сообщения от группы ВК | ||
+ | messageType.200.title=ВК "Рога и копыта" | ||
+ | messageType.200.class=ru.bgcrm.dyn.vk.MessageTypeVK | ||
+ | </source> | ||
+ | |||
+ | добавляем этот тип сообщений в планировщике, для периодического приёма: | ||
+ | |||
+ | <source lang="bash"> | ||
+ | ##Планировщик получения сообщений | ||
+ | scheduler.task.4.class=ru.bgcrm.worker.MessageExchange | ||
+ | scheduler.task.4.messageTypeIds=200 | ||
+ | #scheduler.task.4.hours= | ||
+ | scheduler.task.4.minutes=10,20,30,40,50,60 | ||
+ | </source> | ||
+ | |||
+ | для того чтобы заблокировать открытие сообщения для дальнейшей обработке в Сообщениях: | ||
+ | |||
+ | <source lang="bash"> | ||
+ | # diff /srv/BGCRM/webapps/WEB-INF/jspf/user/message/list.jsp /srv/BGCRM/webapps/WEB-INF/jspf/user/message/list.jsp.orig | ||
+ | 190d189 | ||
+ | < | ||
+ | 193,205c192,197 | ||
+ | < <c:set var="typeId" value="${item.typeId}"/> | ||
+ | < <c:choose> | ||
+ | < <c:when test="${typeId eq 200}"> | ||
+ | < | ||
+ | < </c:when> | ||
+ | < <c:otherwise> | ||
+ | < <c:url var="url" value="message.do"> | ||
+ | < <c:param name="typeId" value="${item.typeId}"/> | ||
+ | < <c:param name="messageId" value="${item.systemId}"/> | ||
+ | < <c:param name="returnUrl" value="${form.requestUrl}"/> | ||
+ | < </c:url> | ||
+ | < </c:otherwise> | ||
+ | < </c:choose> | ||
+ | --- | ||
+ | > <c:url var="url" value="message.do"> | ||
+ | > <c:param name="typeId" value="${item.typeId}"/> | ||
+ | > <c:param name="messageId" value="${item.systemId}"/> | ||
+ | > <c:param name="returnUrl" value="${form.requestUrl}"/> | ||
+ | > </c:url> | ||
+ | > | ||
</source> | </source> |
Текущая версия на 11:29, 10 февраля 2017
Функциональность:
- Получение новых(не прочитанных сообщений из паблика VK).
- Отображение полученных сообщений в BGCRM -> Сообщения.
- Оповещение о новых сообщениях в счётчике новых не прочитанных сообщений BGCRM.
дальнейшая обработка сообщений в BGCRM не реализована и заблокирована. Общение происходит в паблике ВК
реализация API. Для того чтобы работало в конфигурацию надо добавить:
- vk.access.token - токен авторизации для приложения. брать в настройках паблика.
- vk.v - версия API. на момент реализации была 5.60
- vk.pname - отображаемое имя паблика.
- vk.mtip - ID типа сообщения из конфигурации BGCRM
package ru.bgcrm.dyn.vk; import java.io.IOException; import java.util.ArrayList; import java.util.Date; import java.util.List; import org.apache.http.HttpResponse; import org.apache.http.ParseException; import org.apache.http.client.methods.HttpPost; import org.apache.http.impl.client.CloseableHttpClient; import org.apache.http.impl.client.HttpClientBuilder; import org.apache.http.util.EntityUtils; import org.json.JSONArray; import org.json.JSONObject; import ru.bgcrm.model.message.Message; import ru.bgcrm.util.Setup; /** * @author Сергей * */ public class VkAPI { /** * Ключ к API */ private String VK_ACCESS_TOKEN; /** * */ private String VK_API_BASE_URI = "https://api.vk.com/method/"; /** * Версия VK API с которой работаем */ private String VK_V; /** * Отображаемое имя паблика */ private String VK_PUBLIC_NAME; /** * Тип сообщений в BGCRM */ private String VK_MESSAGE_TID; public VkAPI(){ VK_ACCESS_TOKEN = Setup.getSetup().get("vk.access.token", ""); VK_V = Setup.getSetup().get("vk.v", "5.60"); VK_PUBLIC_NAME = Setup.getSetup().get("vk.pname", "ООО \"Рога и копыта\""); VK_MESSAGE_TID = Setup.getSetup().get("vk.mtip", "200"); } /** * Получение диалогов * * @param unanswered 0 - все; 1 - только не отвеченные сообщения; * @param important 0 - все; 1 - только важные; * @param unread 0 - все; 1 - только не прочитанные; * @return */ public List<VkDialog> getDialogs(Integer unanswered, Integer important, Integer unread){ List<VkDialog> result = new ArrayList<VkDialog>(); String method = "messages.getDialogs"; String body = ""; body = "unanswered=" + unanswered + "&important" + important + "&unread=" + unread; try { String response = sendRequest(method, body); JSONObject jsonResponse = new JSONObject(response); JSONArray jsonArrayDialogs = jsonResponse.getJSONObject("response").getJSONArray("items"); if (jsonArrayDialogs.length() > 0){ for(int i=0; i<jsonArrayDialogs.length(); i++){ VkDialog vkDialog = new VkDialog(jsonArrayDialogs.getJSONObject(i).getJSONObject("message").getInt("user_id"), jsonArrayDialogs.getJSONObject(i).getInt("in_read"), jsonArrayDialogs.getJSONObject(i).getInt("out_read"), jsonArrayDialogs.getJSONObject(i).getJSONObject("message")); result.add(vkDialog); } } } catch (ParseException | IOException e) { e.printStackTrace(); } return result; } /** * Конвертируем лист сообщений VK в лист сообщений CRM * * @param vkMessageList * @return */ public List<Message> toMessageList(List<VkMessage> vkMessageList){ List<Message> result = new ArrayList<Message>(); for (VkMessage vkMessage : vkMessageList){ Message message = new Message(); message.setDirection(Message.DIRECTION_INCOMING); message.setFrom(String.valueOf(vkMessage.fromId)); message.setFromTime(new Date((long)vkMessage.date*1000)); message.setText(vkMessage.body); message.setSubject(vkMessage.body); message.setTo(VK_PUBLIC_NAME); message.setTypeId(Integer.valueOf(VK_MESSAGE_TID)); message.setProcessed(false); message.setSystemId(String.valueOf(vkMessage.fromId)); result.add(message); } return result; } /** * Отсылаем запрос. Возвращаем JSON * * @param method * @param body * @return * @throws ParseException * @throws IOException */ private String sendRequest(String method, String body) throws ParseException, IOException{ CloseableHttpClient httpClient = HttpClientBuilder.create().build(); body = body + "&access_token=" + VK_ACCESS_TOKEN + "&v=" + VK_V; HttpPost request = new HttpPost(VK_API_BASE_URI + method + "?" + body); request.addHeader("content-type", "application/json"); HttpResponse result = httpClient.execute(request); String jsonString = EntityUtils.toString(result.getEntity(), "UTF-8"); System.out.println(jsonString); httpClient.close(); return jsonString; } }
класс диалога VK
package ru.bgcrm.dyn.vk; import java.util.List; import org.json.JSONObject; public class VkDialog { /** * */ Integer userId; /** * */ List<VkMessage> messageList; /** * */ Integer inRead; /** * */ Integer outRead; /** * */ VkMessage lastMessage; public VkDialog (){ } public VkDialog(int user_id, int in_read, int out_read, JSONObject jmessage) { userId = user_id; inRead = in_read; outRead = out_read; VkMessage vkMessage = new VkMessage(jmessage.getInt("id"), jmessage.getInt("user_id"), jmessage.getInt("user_id"), jmessage.getInt("date"), jmessage.getInt("read_state"), jmessage.getInt("out"), jmessage.getString("body")); lastMessage = vkMessage; } }
класс сообщения VK
package ru.bgcrm.dyn.vk; public class VkMessage { public int id; public int userId; public int fromId; public int date; public int readState; public int out; public String body; public VkMessage(int id, int user_id, int from_id, int date, int read_state, int out, String body) { this.id = id; this.userId = user_id; this.fromId = from_id; this.date = date; this.readState = read_state; this.out = out; this.body = body; } }
класс MessageTypeVK:
package ru.bgcrm.dyn.vk; import java.sql.Connection; import java.util.ArrayList; import java.util.List; import org.apache.log4j.Logger; import ru.bgcrm.dao.message.MessageType; import ru.bgcrm.model.BGException; import ru.bgcrm.model.message.Message; import ru.bgcrm.struts.form.DynActionForm; import ru.bgcrm.util.ParameterMap; import ru.bgcrm.util.sql.ConnectionSet; public class MessageTypeVK extends MessageType { private static final Logger log = Logger.getLogger(MessageTypeVK.class); public MessageTypeVK(int id, ParameterMap config) throws BGException { super(id, config.get("title"), config); } protected MessageTypeVK(int id, String title, ParameterMap config) throws BGException { super(id, config.get("title"), config); } @Override public void updateMessage(Connection con, DynActionForm form, Message message) throws BGException { } /* (non-Javadoc) * @see ru.bgcrm.dao.message.MessageType#newMessageList(ru.bgcrm.util.sql.ConnectionSet) * * Получаем последние сообщения из неотвеченных диалогов в ВК */ public List<ru.bgcrm.model.message.Message> newMessageList(ConnectionSet conSet) throws BGException { log.info((new StringBuilder("Fetching new message list."))); VkAPI VkApi = new VkAPI(); List<VkMessage> vkMessageList = getNewMessageList(VkApi); return VkApi.toMessageList(vkMessageList); } /* (non-Javadoc) * @see ru.bgcrm.dao.message.MessageType#getProcessMessageHeaderColor(ru.bgcrm.model.message.Message) * * настройка цвета сообщения */ public String getProcessMessageHeaderColor(Message message) { return "#e6fb9d"; } /** * получаем список неотвеченных сообщений * @param VkAPI * @return */ private List<VkMessage> getNewMessageList(VkAPI VkApi) { List<VkMessage> vkMessageList = new ArrayList<VkMessage>(); List<VkDialog> vkDialogList = VkApi.getDialogs(1, 0, 0); log.info(vkDialogList.size() + " unanswered dialogs found."); for (VkDialog vkDialog : vkDialogList){ log.info("vkUserId : " + vkDialog.userId); vkMessageList.add(vkDialog.lastMessage); } this.unprocessedMessagesCount = Integer.valueOf(vkMessageList.size()); return vkMessageList; } /* (non-Javadoc) * @see ru.bgcrm.dao.message.MessageType#process() * * Метод обработки сообщений по шедулеру */ public void process(){ log.info((new StringBuilder("Starting VK daemon, public name: "))); readPublicMessages(); sendPublicMessages(); } /** * Метод чтения сообщений из паблика */ private void readPublicMessages() { log.info((new StringBuilder("Fetching new message list."))); VkAPI VkApi = new VkAPI(); getNewMessageList(VkApi); } /** * Метод отправки сообщений в паблик */ private void sendPublicMessages() { log.info((new StringBuilder("Public messages sended."))); } /* (non-Javadoc) * @see ru.bgcrm.dao.message.MessageType#isEditable(ru.bgcrm.model.message.Message) * * Поддерживает ли изменение */ public boolean isEditable(Message message) { return false; } /* (non-Javadoc) * @see ru.bgcrm.dao.message.MessageType#isRemovable(ru.bgcrm.model.message.Message) * * Поддерживает ли удаление */ public boolean isRemovable(Message message) { return false; } /* (non-Javadoc) * @see ru.bgcrm.dao.message.MessageType#isProcessChangeSupport() * * Можно ли сменить процесс */ public boolean isProcessChangeSupport() { return false; } /* (non-Javadoc) * @see ru.bgcrm.dao.message.MessageType#isAnswerSupport() * * ??? Можно ли отвечать ??? */ public boolean isAnswerSupport(){ return false; } }
в конфигурации BGCRM создаем новый тип сообщений:
### Сообщения от группы ВК messageType.200.title=ВК "Рога и копыта" messageType.200.class=ru.bgcrm.dyn.vk.MessageTypeVK
добавляем этот тип сообщений в планировщике, для периодического приёма:
##Планировщик получения сообщений scheduler.task.4.class=ru.bgcrm.worker.MessageExchange scheduler.task.4.messageTypeIds=200 #scheduler.task.4.hours= scheduler.task.4.minutes=10,20,30,40,50,60
для того чтобы заблокировать открытие сообщения для дальнейшей обработке в Сообщениях:
# diff /srv/BGCRM/webapps/WEB-INF/jspf/user/message/list.jsp /srv/BGCRM/webapps/WEB-INF/jspf/user/message/list.jsp.orig 190d189 < 193,205c192,197 < <c:set var="typeId" value="${item.typeId}"/> < <c:choose> < <c:when test="${typeId eq 200}"> < < </c:when> < <c:otherwise> < <c:url var="url" value="message.do"> < <c:param name="typeId" value="${item.typeId}"/> < <c:param name="messageId" value="${item.systemId}"/> < <c:param name="returnUrl" value="${form.requestUrl}"/> < </c:url> < </c:otherwise> < </c:choose> --- > <c:url var="url" value="message.do"> > <c:param name="typeId" value="${item.typeId}"/> > <c:param name="messageId" value="${item.systemId}"/> > <c:param name="returnUrl" value="${form.requestUrl}"/> > </c:url> >