1. Что необходимо для взаимодействия с ГИС ГМП?
- Электронный ключ eToken с хранилищем ключей и сертификатов для электронно-цифровой подписи сообщений, отправляемых в ГИС ГМП
- Участник взаимодействия должен быть подключен к СМЭВ
- Участник взаимодействия должен быть зарегистрирован в ГИС ГМП и иметь уникальный регистрационный номер
2. Установка КриптоПро JCP
Для успешного взаимодействия, сообщения, отправляемые в ГИС ГМП, должны быть подписаны электронно-цифровой подписью, для чего используется средство криптографической защиты КриптоПро JCP. Для корректной работы JCP необходимо:
- скачать дистрибутив с официального сайта и установить в директорию с используемой JRE
- установить eToken PKI client для нужной версии ОС и выгрузить с eToken ключа хранилище ключей на жесткий диск
- cкачать и подключить библиотеки WSS4J к проекту
- скачать и подключить библиотеки JCP.jar, JCPxml.jar, xmlsec-1.5.0.jar, xalan-2.7.0.jar, XMLDSigRI.jar к проекту (большинство из них можно найти в папке с установленным JCP)
3. WSDL to Java
Для формирования сообщений, отправляемых веб-сервису, предоставляемому СМЭВ для взаимодействия с ГИС ГМП, необходимо конвертировать wsdl веб-сервиса в java классы, объекты которых в дальнейшем будут использованы для построения этих сообщений. Сделать это можно с помощью команды wsdl2java Apache CXF. В результате должны получиться полностью аннотированные java классы такого типа:
@javax.xml.bind.annotation.XmlAccessorType(javax.xml.bind.annotation.XmlAccessType.FIELD) @javax.xml.bind.annotation.XmlType(name = "", propOrder = {"message", "messageData"}) @javax.xml.bind.annotation.XmlRootElement(name = "UnifoTransferMsg") public class UnifoTransferMsg { @javax.xml.bind.annotation.XmlElement(name = "Message", namespace = "http://smev.gosuslugi.ru/rev111111", required = true) protected ru.gosuslugi.smev.rev111111.MessageType message; @javax.xml.bind.annotation.XmlElement(name = "MessageData", namespace = "http://smev.gosuslugi.ru/rev111111", required = true) protected ru.gosuslugi.smev.rev111111.MessageDataType messageData; public UnifoTransferMsg() { /* compiled code */ } public ru.gosuslugi.smev.rev111111.MessageType getMessage() { /* compiled code */ } public void setMessage(ru.gosuslugi.smev.rev111111.MessageType value) { /* compiled code */ } public ru.gosuslugi.smev.rev111111.MessageDataType getMessageData() { /* compiled code */ } public void setMessageData(ru.gosuslugi.smev.rev111111.MessageDataType value) { /* compiled code */ } }После этого нужно добавить полученные классы в jar архив и подключить его к проекту.
4. Разработка клиента к веб-сервису
4.1 WebServiceTemplate
WebServiceTemplate это центральный класс в Spring-WS API, который отвечает за отправку и получение сообщений от веб-сервиса. Для использования WebServiceTemplate объявим его как bean в конфигурационном файле Spring'а:<bean id="smevGISGMPWebServiceTemplate" class="org.springframework.ws.client.core.WebServiceTemplate"> <property name="messageFactory"> <bean class="org.springframework.ws.pox.dom.DomPoxMessageFactory"/> </property> <property name="defaultUri" value="http://smev-mvf.test.gosuslugi.ru:7777/gateway/services/SID0003218?WSDL"/> <property name="messageSender" ref="smevGISGMPMessageSender"/> </bean> <bean id="smevGISGMPMessageSender" class="org.springframework.ws.transport.http.HttpUrlConnectionMessageSender"/>Рассмотрим подробнее каждое из свойств smevGISGMPWebServiceTemplate:
- messageFactory отвечает за формирование сообщений, отправляемых веб-сервису
- messageSender отвечает за отправку сообщений веб-сервису
- defaultUri определяет адрес веб-сервиса, с которым мы будем взаимодействовать
Свойство messageFactory должно быть связано с одной из реализаций интерфейса WebServiceMessageFactory. Spring предоставляет на выбор три реализации данного интерфейса:
![](/images/messageFactory.png)
В нашем случае используем DomPoxMessageFactory, т.к. остальные реализации messageFactory добавляют в сообщение лишние SOAP заголовки, которые уже будут добавлены нами в ручную перед подписыванием нашего сообщения электронно-цифровой подписью.
Свойство messageSender должно быть связано с одной из реализаций интерфейса WebServiceMessageSender. Spring предлагает две реализации данного интерфейса:
![](/images/1.jpg)
Мы будем использовать HttpUrlConnectionMessageSender реализацию, т.к. нам не требуется никакой расширенной функциональности для нашего messageSender'a.
4.2 Формирование сообщения
После того как мы сконфигурировали smevGISGMPWebServiceTemplate можно перейти к формированию, подписи и отправке сообщения ГИС ГМП. Допустим нам необходимо отправить сообщение для импорта начисления в ГИС ГМП, пример такого сообщения:<?xml version="1.0" encoding="UTF-8"?> <SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd" xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd"> <SOAP-ENV:Body wsu:Id="body"> <n1:UnifoTransferMsg xsi:schemaLocation="http://roskazna.ru/SmevUnifoService/ MethodMsg.xsd" xmlns:ds="http://www.w3.org/2000/09/xmldsig#" xmlns:n1="http://roskazna.ru/SmevUnifoService/" xmlns:n3="http://www.altova.com/samplexml/other-namespace" xmlns:pirq="http://roskazna.ru/xsd/PGU_ImportRequest" xmlns:smev="http://smev.gosuslugi.ru/rev111111" xmlns:unifo="http://rosrazna.ru/xsd/SmevUnifoService" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> <smev:Message> <smev:Sender> <smev:Code>RKZN35001</smev:Code> <smev:Name>Казначейство России</smev:Name> </smev:Sender> <smev:Recipient> <smev:Code>RKZN35001</smev:Code> <smev:Name>Казначейство России</smev:Name> </smev:Recipient> <smev:TypeCode>GFNC</smev:TypeCode> <smev:Status>REQUEST</smev:Status> <smev:Date>2012-07-25T09:40:48.0Z</smev:Date> <smev:ExchangeType>6</smev:ExchangeType> </smev:Message> <smev:MessageData> <smev:AppData> <unifo:ImportData> <pirq:ImportRequest> <PostBlock> <ID>13454</ID> <TimeStamp>2012-07-25T09:40:47.0Z</TimeStamp> <SenderIdentifier>00022</SenderIdentifier> </PostBlock> <Charge SupplierBillID="19255500000000000079"> <BillDate>2011-03-10</BillDate> <SupplierOrgInfo> <Name>Управление Федеральной миграционной службы по Республике Татарстан</Name> <INN>1655102196</INN> <KPP>165501001</KPP> <Account> <Account>40101810800000010001</Account> <Bank> <Name>ГРКЦ НБ РТ г. Казани</Name> <BIK>049205001</BIK> </Bank> </Account> </SupplierOrgInfo> <BillFor>Госпошлина за выдачу загранпаспорта</BillFor> <TotalAmount>100000</TotalAmount> <ChangeStatus>1</ChangeStatus> <TreasureBranch>УФК по Республике Татарстан</TreasureBranch> <KBK>19210806000011000110</KBK> <OKATO>92401000000</OKATO> <BudgetIndex> <Status>0</Status> <PaymentType>0</PaymentType> <Purpose>0</Purpose> <TaxPeriod>0</TaxPeriod> <TaxDocNumber>0</TaxDocNumber> <TaxDocDate>0</TaxDocDate> </BudgetIndex> <ApplicationID>455555</ApplicationID> <UnifiedPayerIdentifier>0100000000006667775555643</UnifiedPayerIdentifier> </Charge> </pirq:ImportRequest> </unifo:ImportData> </smev:AppData> </smev:MessageData> </n1:UnifoTransferMsg> </SOAP-ENV:Body> </SOAP-ENV:Envelope>То есть все что необходимо для отправки сообщения это:
- сформировать его используя объекты java классов, которые мы получили из wsdl веб-сервиса
- добавить в сообщение SOAP заголовки, т.к. с помощью SOAP протокола происходит обмен сообщениями с сервисом ГИС ГМП
- добавить в него электронно-цифровую подпись с помощью КриптоПро JCP
public UnifoTransferMsg createImportChargeRequestMsg(ChargeType charge) throws DatatypeConfigurationException { UnifoTransferMsg msg = new UnifoTransferMsg(); GregorianCalendar c = new GregorianCalendar(); c.setTime(new Date()); XMLGregorianCalendar date = DatatypeFactory.newInstance().newXMLGregorianCalendar(c); MessageType messageType = initServiceData(date); MessageDataType messageDataType = new MessageDataType(); AppDataType appData = new AppDataType(); ImportData importData = new ImportData(); ImportRequest importRequest = new ImportRequest(); PostBlock postBlock = getPostBlockInfo(date); importRequest.setPostBlock(postBlock); importRequest.setCharge(charge); importData.setImportRequest(importRequest); appData.setImportData(importData); messageDataType.setAppData(appData); msg.setMessage(messageType); msg.setMessageData(messageDataType); return msg; } private MessageType initServiceData(XMLGregorianCalendar date) { MessageType messageType = new MessageType(); OrgExternalType senderType = gisGMPDAO.getSenderType().get(0); OrgExternalType recipietnType = gisGMPDAO.getRecipientType().get(0); messageType.setSender(senderType); messageType.setRecipient(recipietnType); messageType.setTypeCode(TypeCodeType.GFNC); messageType.setStatus(StatusType.REQUEST); messageType.setDate(date); messageType.setExchangeType(EXCHANGE_TYPE); return messageType; } private PostBlock getPostBlockInfo(XMLGregorianCalendar date) { UUID requestId = UUID.randomUUID(); PostBlock postBlock = new PostBlock(); postBlock.setID(requestId.toString()); postBlock.setSenderIdentifier(gisGMPDAO.getSenderIdentifier()); postBlock.setTimeStamp(date); return postBlock; }Где на вход методу createImportChargeRequestMsg поступает объект начисления, содержащий все необходимые данные начисления в контексте нашей системы и возвращает необходимый нам объект UnifoTransferMsg веб-сервиса. Сам процесс формирования объекта UnifoTransferMsg не является ключевым и для разных информационных систем может быть индивидуальным.
Далее необходимо преобразовать наш объект UnifoTransferMsg в объект SOAPMessage, для последующего добавления электронно-цифровой подписи в наше сообщение:
public SOAPMessage unifoTransferToSOAPMessage(UnifoTransferMsg msg) throws ParserConfigurationException, JAXBException, SOAPException { SOAPMessage soapMessage = MessageFactory.newInstance().createMessage(); Document document = DocumentBuilderFactory.newInstance().newDocumentBuilder().newDocument(); JAXBContext jaxbCtx = JAXBContext.newInstance(UnifoTransferMsg.class, Include.class); jaxbCtx.createMarshaller().marshal(msg, document); soapMessage.getSOAPBody().addDocument(document); return soapMessage; }
4.3 Подпись сообщения с помощью КриптоПро JCP
Процесс подписи SOAP сообщения с помощью JCP подробно изложен на официальном сайте, но лично у меня с данным примером возникали некоторые проблемы, поэтому вот рабочий вариант класса, используемого для подписи SOAP сообщения, отдельного тега SOAP сообщения и проверки корректности подписи:public class SOAPXMLSignatureManager { private static final String WSSECURITY_SECEXT_URI = "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd"; private static final String WSSECURITY_UTILITY_URI = "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd"; private Provider xmlDSigProvider; private KeyStore keyStore; private PrivateKey privateKey; private X509Certificate cert; private static SOAPXMLSignatureManager instance; public static synchronized SOAPXMLSignatureManager getInstance(){ if (instance == null){ instance = new SOAPXMLSignatureManager(); } return instance; } private SOAPXMLSignatureManager() { org.apache.xml.security.Init.init(); xmlDSigProvider = new ru.CryptoPro.JCPxml.dsig.internal.dom.XMLDSigRI(); //путь до хранилища ключей, которое мы выгрузили предварительно с eToken HDImageStore.setDir(ResourceBundle.getBundle("application").getString("config.cryptoPro.keyStore.path")); try { //тип хранилища ключей, в нашем случае - HDImageStore keyStore = KeyStore.getInstance(ResourceBundle.getBundle("application").getString("config.cryptoPro.keyStore.type")); keyStore.load(null, null); //имя хранилища и пароль к нему privateKey = (PrivateKey) keyStore.getKey( ResourceBundle.getBundle("application").getString("config.cryptoPro.keyStore.alias"), ResourceBundle.getBundle("application").getString("config.cryptoPro.keyStore.password").toCharArray() ); cert = (X509Certificate) keyStore.getCertificate(ResourceBundle.getBundle("application").getString("config.cryptoPro.keyStore.alias")); } catch (KeyStoreException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } catch (NoSuchAlgorithmException e) { e.printStackTrace(); } catch (CertificateException e) { e.printStackTrace(); } catch (UnrecoverableKeyException e) { e.printStackTrace(); } } public void signSOAPMessage(SOAPMessage soapMessage) throws SOAPException, WSSecurityException, KeyStoreException, CertificateException, NoSuchAlgorithmException, IOException, TransformationException, InvalidAlgorithmParameterException, MarshalException, XMLSignatureException, TransformerException, UnrecoverableKeyException { prepareMessageForSigning(soapMessage); Document doc = soapMessage.getSOAPPart().getEnvelope().getOwnerDocument(); final Transforms transforms = new Transforms(doc); transforms.addTransform(Transforms.TRANSFORM_C14N_EXCL_OMIT_COMMENTS); XMLSignatureFactory fac = XMLSignatureFactory.getInstance("DOM", xmlDSigProvider); ListМетод signElementByTag используется в том случае, когда мы импортируем какую-либо сущность в ГИС ГМП, например начисление, тогда этот метод позволяет подписать определенную часть SOAP сообщения, которая соответствует данным импортируемой сущности.transformList = new ArrayList (); Transform transformC14N = fac.newTransform(Transforms.TRANSFORM_C14N_EXCL_OMIT_COMMENTS, (XMLStructure) null); transformList.add(transformC14N); Reference ref = fac.newReference( "#body", fac.newDigestMethod("http://www.w3.org/2001/04/xmldsig-more#gostr3411", null), transformList, null, null ); SignedInfo si = fac.newSignedInfo( fac.newCanonicalizationMethod(CanonicalizationMethod.EXCLUSIVE, (C14NMethodParameterSpec) null), fac.newSignatureMethod("http://www.w3.org/2001/04/xmldsig-more#gostr34102001-gostr3411", null), Collections.singletonList(ref) ); KeyInfoFactory kif = fac.getKeyInfoFactory(); X509Data x509d = kif.newX509Data(Collections.singletonList(cert)); KeyInfo ki = kif.newKeyInfo(Collections.singletonList(x509d)); Element token = (Element) soapMessage.getSOAPHeader().getChildElements().next(); javax.xml.crypto.dsig.XMLSignature sig = fac.newXMLSignature(si, ki); DOMSignContext signContext = new DOMSignContext(privateKey, token); sig.sign(signContext); Element sigE = (Element) XPathAPI.selectSingleNode(signContext.getParent(), "//ds:Signature"); Node keyE = XPathAPI.selectSingleNode(sigE, "//ds:KeyInfo", sigE); token.getFirstChild().setTextContent(XPathAPI.selectSingleNode(keyE, "//ds:X509Certificate", keyE).getFirstChild().getNodeValue()); keyE.removeChild(XPathAPI.selectSingleNode(keyE, "//ds:X509Data", keyE)); NodeList chl = keyE.getChildNodes(); for (int i = 0; i < chl.getLength(); i++) { keyE.removeChild(chl.item(i)); } Node str = keyE.appendChild(doc.createElementNS( "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd", "wsse:SecurityTokenReference" )); Element strRef = (Element) str.appendChild(doc.createElementNS( "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd", "wsse:Reference" )); strRef.setAttribute( "ValueType", "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-x509-token-profile-1.0#X509v3" ); strRef.setAttribute("URI", "#CertId"); token.appendChild(sigE); } public void signElementByTag(SOAPMessage soapMessage, String tag) throws Exception{ NodeList tagNodeList = soapMessage.getSOAPPart().getElementsByTagName(tag); Document newXMLDocument = DocumentBuilderFactory.newInstance().newDocumentBuilder().newDocument(); Node copyNode = newXMLDocument.importNode(tagNodeList.item(0), true); newXMLDocument.appendChild(copyNode); NodeList newNodeList = newXMLDocument.getElementsByTagName(tag); Element signedNode = (Element)newNodeList.item(0); XMLSignatureFactory fac = XMLSignatureFactory.getInstance("DOM", xmlDSigProvider); List transformList = new ArrayList (); Transform transform = fac.newTransform(Transform.ENVELOPED, (XMLStructure) null); Transform transformC14N = fac.newTransform(Transforms.TRANSFORM_C14N_EXCL_OMIT_COMMENTS, (XMLStructure) null); transformList.add(transform); transformList.add(transformC14N); Reference ref = fac.newReference("", fac.newDigestMethod("http://www.w3.org/2001/04/xmldsig-more#gostr3411", null), transformList, null, null); SignedInfo si = fac.newSignedInfo(fac.newCanonicalizationMethod(CanonicalizationMethod.EXCLUSIVE, (C14NMethodParameterSpec) null), fac.newSignatureMethod("http://www.w3.org/2001/04/xmldsig-more#gostr34102001-gostr3411", null), Collections.singletonList(ref)); KeyInfoFactory kif = fac.getKeyInfoFactory(); X509Data x509d = kif.newX509Data(Collections.singletonList(cert)); KeyInfo ki = kif.newKeyInfo(Collections.singletonList(x509d)); javax.xml.crypto.dsig.XMLSignature sig = fac.newXMLSignature(si, ki); DOMSignContext signContext = new DOMSignContext(privateKey, signedNode); signContext.putNamespacePrefix(javax.xml.crypto.dsig.XMLSignature.XMLNS, "ds"); sig.sign(signContext); Document doc = soapMessage.getSOAPPart().getEnvelope().getOwnerDocument(); Node signedTag = newXMLDocument.getFirstChild(); Node oldNode = tagNodeList.item(0); Node parentNode = oldNode.getParentNode(); parentNode.removeChild(oldNode); Node newNode = doc.importNode(signedTag, true); parentNode.appendChild(newNode); } private void prepareMessageForSigning(SOAPMessage soapMessage) throws SOAPException, WSSecurityException { soapMessage.getSOAPPart().getEnvelope().addNamespaceDeclaration( "wsse", WSSECURITY_SECEXT_URI ); soapMessage.getSOAPPart().getEnvelope().addNamespaceDeclaration( "wsu", WSSECURITY_UTILITY_URI ); soapMessage.getSOAPPart().getEnvelope().addNamespaceDeclaration("ds", "http://www.w3.org/2000/09/xmldsig#"); soapMessage.getSOAPBody().setAttributeNS(WSSECURITY_UTILITY_URI, "wsu:Id", "body"); WSSecHeader header = new WSSecHeader(); header.setActor("http://smev.gosuslugi.ru/actors/smev"); header.setMustUnderstand(false); Element sec = header.insertSecurityHeader(soapMessage.getSOAPPart()); Document doc = soapMessage.getSOAPPart().getEnvelope().getOwnerDocument(); Element token = (Element) sec.appendChild(doc.createElementNS(WSSECURITY_SECEXT_URI, "wsse:BinarySecurityToken")); token.setAttribute("EncodingType", "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-soap-message-security-1.0#Base64Binary"); token.setAttribute("ValueType", "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-x509-token-profile-1.0#X509v3"); token.setAttribute("wsu:Id", "CertId"); header.getSecurityHeader().appendChild(token); } public boolean verifySecuredMessage(SOAPMessage message) throws Exception { Document doc = message.getSOAPPart().getEnvelope().getOwnerDocument(); final Element wssecontext = doc.createElementNS(null, "namespaceContext"); wssecontext.setAttributeNS( "http://www.w3.org/2000/xmlns/", "xmlns:"+"wsse".trim(), "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd" ); NodeList secnodeList = XPathAPI.selectNodeList(doc.getDocumentElement(), "//wsse:Security"); Element r = null; Element el; if( secnodeList != null&&secnodeList.getLength() > 0 ) { String actorAttr; for( int i = 0; i<secnodeList.getLength(); i++ ) { el = (Element) secnodeList.item(i); actorAttr = el.getAttributeNS("http://schemas.xmlsoap.org/soap/envelope/", "actor"); if(actorAttr != null&&actorAttr.equals("http://smev.gosuslugi.ru/actors/smev")) { r = (Element)XPathAPI.selectSingleNode(el, "//wsse:BinarySecurityToken[1]", wssecontext); break; } } } if(r == null) return false; final X509Security x509 = new X509Security(r); if(x509 == null) return false; final X509Certificate cert = (X509Certificate) CertificateFactory.getInstance("X.509").generateCertificate(new ByteArrayInputStream(x509.getToken())); if (cert == null) { throw new Exception("Cannot find certificate to verify signature"); } NodeList nl = doc.getElementsByTagNameNS("http://www.w3.org/2000/09/xmldsig#", "Signature"); if (nl.getLength() == 0) { throw new Exception("Cannot find Signature element"); } XMLSignatureFactory fac = XMLSignatureFactory.getInstance("DOM", xmlDSigProvider); DOMValidateContext valContext = new DOMValidateContext(KeySelector.singletonKeySelector(cert.getPublicKey()), nl.item(0)); javax.xml.crypto.dsig.XMLSignature signature = fac.unmarshalXMLSignature(valContext); return signature.validate(valContext); } }
4.4 Отправка и получение сообщения
Последний этап это непосредственно сама отправка сообщения веб-сервису ГИС ГМП и получение ответа от него. Ниже представлен метод, сожержащий в себе все этапы сообщения после формирования его данных - подпись части сообщения, подпись сообщения целиком, проверка корректности подписи сообщения, отправка и прием сообщения:private synchronized UnifoTransferMsg sendAndRecieveMessage(UnifoTransferMsg requestMessage, String signingElementTagName) throws Exception { SOAPMessage importRequestSoapMsg = smevGISGMPMessagesService.unifoTransferToSOAPMessage(requestMessage); SOAPXMLSignatureManager signatureManager = SOAPXMLSignatureManager.getInstance(); if (signingElementTagName != null){ signatureManager.signElementByTag(importRequestSoapMsg, CHARGE_ELEMENT_TAG_NAME); } signatureManager.signSOAPMessage(importRequestSoapMsg); if (signatureManager.verifySecuredMessage(importRequestSoapMsg)){ JAXBContext jaxbCtx = JAXBContext.newInstance(UnifoTransferMsg.class, Include.class); JDOMResult result = new JDOMResult(); ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); importRequestSoapMsg.writeTo(outputStream); smevGISGMPWebServiceTemplate.sendSourceAndReceiveToResult(new StringSource(outputStream.toString()), result); Document resultDocument = result.getDocument(); Element responseElement = resultDocument.getRootElement(); Element unifoTransferMsg = responseElement.getChildren().get(1).getChildren().get(0); StringSource resultStringSource = new StringSource(new XMLOutputter().outputString(unifoTransferMsg)); UnifoTransferMsg responseMsg = (UnifoTransferMsg)jaxbCtx.createUnmarshaller().unmarshal(resultStringSource); return responseMsg; } else { throw new Exception(gisgmpMessages.getSignatureVerificationError()); } }Метод принимает как входные параметры объект UnifoTransferMsg , содержащий в себе отправляемые данные в ГИС ГМП и название сущности импортируемой в ГИС ГМП (например Charge), если отправляется запрос на импорт, иначе signingElementTagName == null. И возвращает объект UnifoTransferMsg, содержащий данные ответа сервиса ГИС ГМП на наше сообщение.