ВКонтакте - пример интеграции

Материал из BiTel WiKi

Перейти к: навигация, поиск

Функциональность:

  • Получение новых(не прочитанных сообщений из паблика 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>
>
Личные инструменты