The ability to automatically generate a REST OData interface for everything was implemented application solution. Thus, we have the opportunity to provide full access third party application to the 1C database in just a couple of clicks.

This mechanism designed to solve several common problems:

  • Uploading/downloading data to/from an application solution;
  • Integration with websites (online stores);
  • Increasing the functionality of the application solution without changing the configuration;
  • Integration with other corporate systems (sometimes without additional programming).

The OData REST interface can be used to exchange data between 1C databases, but since other, more convenient mechanisms already exist for this, the main purpose of the OData REST interface is seen in integration with third-party systems.

And this is really convenient, considering that OData clients exist on all major platforms, the corresponding libraries can be downloaded.

In this article I will try to talk in detail about what the OData REST interface is and how it can be used.

Publishing a REST OData Interface

To use the OData interface, it needs to be published, and for this we need a web server - Apache 2.2 or IIS (starting from version also Apache 2.4). Then, you need to go to the “Administration” menu -> “Publish on a web server...”.

In the window that opens, fill in the required fields and click “Publish”:

After this, you will need to determine the composition of the OData interface, i.e. indicate which configuration objects are included in it and which are not (initially it does not contain a single object).

You can do it something like this:

&OnServer Procedure SetODataOnServer() tArray = New Array; tArray.Add(Metadata.Directories.Products); SetComposition ofStandardInterfaceOData(tArray); End of Procedure

&On server

Procedure SetODataOnServer()

tArray= New Array;

tArray. Add(Metadata. Directories. Products) ;

SetComposition ofStandardInterfaceOData(tArray) ;

End of Procedure


Print (Ctrl+P)

You can watch the second part

General information

In platform version 8.3.5.1068 , published in September 2015, a mechanism for integrating 1C with external programs through technology REST interface. The platform uses the OData protocol as an access protocol. It is an open web protocol for querying and updating data. It allows you to manipulate data using HTTP commands as requests. In version 8.3.5.1068 it was possible to receive answers only in the format Atom/XML . However, starting with release 8.3.8.1652 in August 2017, a second option appeared for receiving data in JSON (JavaScript Object Notation) format. . Compared to XML, it is easy to read by people and takes up less space. In addition, all browsers have built-in tools for working with JSON.

Working with the OData protocol on the 1C: Enterprise platform can be found in the book 1C: Developer's Guide in Chapter 17 Mechanisms of Internet services, paragraph 17.2.1 Standard OData interface. You can also look at examples of extending support for the OData protocol,

Advantage of using REST interface. concludes that in order to gain access to system data from an external application, modification of the application solution code is not required (for example, if the application solution is supported). To obtain this access, you must publish the application to the Web server in a specific way and specify which configuration objects will be used in this way. Third-party systems can then access your application using HTTP requests.

Publishing the standard OData interface is performed using the publishing dialog on the web server (Administration - Publishing to web server) and described in the book 1C:Enterprise 8.3. “Administrator's Guide”.
Important! In order for configuration objects to become available through standard interface OData, need to resolve this using global context method SetComposition ofStandardInterfaceOData().
The mechanism for setting the composition of objects available using the standard OData interface can be done as external processing. This does not require modification of the application solution.

To interact with an external REST web server from 1C:Enterprise, we use the tools available in the platform for working with HTTP: objects HTTPConnection, HTTPRequest and HTTPResponse.

In this series of articles, I will show examples of typical operations using the corresponding HTTP method;

  • Receiving data - method GET;
  • Creating an Object - Method POST;
  • Update data: method PATCH– in this case, you can specify only those properties that need to be updated; method PUT– in this case, it is necessary to indicate all the properties of the entity;
  • Deleting data - method DELETE.

1. Examples of data acquisition. HTTP GET method

The server will be a database published on the web server with the name WebBuh(Demo database “Enterprise Accounting 3.0”). I will use the JSON format as the data exchange format. More information about working with JSON is written in the documentation available. To receive data from the server using the HTTP GET method, you need to create an object Reading JSON to read JSON data sequentially from a file or string. To organize sequential recording of objects and texts on the server using the HTTP POST PATCH PUT method, you need to create an object JSON entry. Note that the DELETE method does not require JSON.

To illustrate the flow of reading and writing JSON when accessing the REST interface, I will call the following custom function general purpose Call HTTPMethodOnServer :

&On server // <Описание функции>// // Options: // - A string containing the name of the HTTP method for the request ("POST"."PATCH", "PUT" ,"GET","DELETE" // - HTTPConnection object //<АдресРесурса>- String of the http resource to which the HTTP request will be sent. //<ОтправляемыеДанные>- A structure or match containing data sent to the specified address for processing // on the server using the specified HTTP method "POST" or "PATCH" or "PUT" // Return value: // The structure of the server response depending on the HTTPMethod// Function Call HTTPMethodOnServer(HTTPMethod, HTTPConnection, ResourceAddress, SentData = Undefined ) // Create an HTTP Request Headers = new Match(); Headings.Insert("Content-Type", "application/json"); HTTP Request = New HTTP Request ( ResourceAddress, Headers ); // Write Json to create and update data If HTTPMethod = "POST" or HTTPMethod = "PATCH" or HTTPMethod = "PUT" Then JSON Record = New JSON Record ; ParametersJSON = New ParametersRecordsJSON(Line WrapJSON.Auto,"",True); RecordJSON.SetString(ParametersJSON); WriteJSON(WriteJSON, SentData ); // SentData are required in this case LineForBody = RecordJSON.Close(); RequestHTTP.SetBodyFromString(StringForBody, TextEncoding.UTF8, UsingByteOrderMark.Do Not Use); endIf; // Call the HTTPConnection Method ResponseHTTP = HTTPConnection.CallHTTPMethod(HTTPMethod, HTTPRequest) ; Answer Structure= New Structure ; Answer Structure.Insert("StatusCode", ResponseHTTP.StatusCode); // Read JSON for GET method only If HTTPMethod="GET" Then TryReadJSON = NewReadJSON ; ServerResponse = ResponseHTTP.GetBodyAsString("UTF-8"); ReadJSON.SetString(ServerResponse); Match = ReadJSON(ReadJSON,True); Response Structure.Insert("ServerResponse",Correspondence) ; Answer Structure.Insert (" Server ResponseUndecrypted", ServerResponse); Exception Report(ErrorDescription()); Return Undefined; EndAttempt; EndIf ; Return Answer Structure ; EndFunction // Call HTTPMethodOnServer()

To receive from the server in JSON format when accessing the REST interface of an application solution, you need to specify in the resource address $format=json. Or specify the MIME type "application/json" in the title:

Headers = new Match(); Headings.Insert("Content-Type", "application/json") ; ResourceAddress = " WebBuh/odata/standard.odata/ ?$format=json" RequestHTTP = New HTTPRequest(ResourceAddress, Headers);

Feature of the global context ReadJSON(ReadJSON, True)

  • If the second parameter is set to True, read the object JSON will be completed in Correspondence.If set to False, objects will be read into an object of type Structure.
  • When deserializing JSON objects into a structure, you need to be aware of the structure key requirements. If, when deserializing an object, a property name is found that is not valid for a structure key, an exception will be thrown.

1. 1 Configuring HTTP connection parameters

To organize the client part of interaction with an external REST web server, I created a client configuration based on the BSP from scratch. Using this configuration, I created a reference for setting up connection parameters (see Fig. 1)

Fig. 1 Directory for setting parameters for HTTP connection to external information security via the rest interface

After pressing the button Check the server response, a procedure is called in which the client will try to receive a response from the server. The program code for the procedure is written below:

&OnClient Procedure CheckConnection(Command) Address = Object.ServerAddress; User = Object.User; Password = Object.Password; DatabaseName = Object.Name; Port = ? (Object.Port<>0,Object.Port,80); HTTPConnection = New HTTPConnection(Address, Port, User, Password); ResourceAddress = DatabaseName + "/odata/standard.odata/ $metadata "; //Call a custom function Answer Structure= B Call HTTPMethodOnServer("GET" , HTTPConnection, ResourceAddress) ; If Answer Structure <> Undefined Then General PurposeClientServer.NotifyUser("Status Code"+Response Structure.Status Code); Endless; End of Procedure

The purpose of this procedure is checking the service and whether the user entered the connection parameters correctly. To do this, just perform a GET request:
HTTPConnection.CallHTTPMethod( "GET", HTTP Request);
using the resource address:
ResourceAddress =BaseName+ /odata/standard.odata/ “;
You can also check the service in your browser using
URL
http://host/WebBuh/odata/standard.odata. The result of such a query is only a list of entities. To obtain a complete description of the standard OData interface (list of available entities, their attributes and functions in the form of XML-
document.) you must perform a GET request using the parameter $metadata. URL http://host/WebBuh/odata/standard.odata/$metadata. Detailed description The document can be obtained at http://www.odata.org/documentation/ (in English).
You can receive answers in the format Atom/XML or JSON. HTTP response status codes can be viewed Responses in the ranges:

  • 100-199 – informational responses indicating that the client’s request has been accepted and is being processed.
  • 200-299 – means that the client’s request was processed successfully.
  • 300-399 means that the request was not completed and the client needs to take some action to satisfy the request.
  • 400-499 – informs about errors on the client application side. These codes may also indicate that additional information is required from the client.
  • 500-599 - Informs about a server-side error, indicating that the server has encountered an error and will likely be unable to fulfill the client's request.

1.2 Searching for an object by ID

The next function is designed to search for a directory or document by a unique identifier on the server. If the object is found, then the function returns the string value of the identifier (Ref_Key), otherwise it returns undefined. The following parameters are passed to the function:

  • HTTPConnection – Object of type HTTPConnection
  • PublicationName – The name of the published server database
  • Element – ​​object entity identifier, for example, Catalog_Organizations or Document_- directory of the Organization.
  • Identifier – The identifier of the object to be searched on the server, e.g. Organization.UniqueIdentifier()
&OnServer Function SearchObjectByGUID (HTTPConnection,PublicationName,Element,UniqueIdentifier) GUID = String(UniqueIdentifier); // convert to the string ResourceAddress = + Element+ "(guid""+ GUID+ "")?$format=json" ; Answer Structure = BCall HTTPMethodOnServer("GET" , HTTPConnection, ResourceAddress) ; If Answer Structure .StatusCode >= 400 Then //General PurposeClientServer.NotifyUser(Element+ "Error"+ResponseStructure.StatusCode+ //GeneralPurposeClientServer.NotifyUser(ResponseStructure.ServerResponseUndecrypted); Return undefined; EndIf ; Match = Answer Structure. ReplyServer a; Array = Match["value"]; If Array = Undefined Then Return Match["Ref_Key"] Else Return Array["Ref_Key"]; endIf; EndFunction

Parameter ResourceAddress used to access a REST service. To check the operation of the service, you can specify the resource in the browser like this

http://(WebServerAddress)/(PublicationName)/odata/standard.odata/(Element)?(Parameters) ,Where

  • WebServer Address– The address of the web server on which the service is published, for example Localhost
  • NamePublications- Name information base indicated when publishing the decision
  • /odata/standard.odata/ – Sign of access to the standard OData interface
  • Element – resource identifier or predefined resources. For example, Catalog_Account(guid’value’).
  • Options– resource parameters. Used, for example, for selection, in the accepted way for HTTP requests: ?key=value&key2=value2

1.3 Searching for an object using search fields

The following user-defined function is designed to search for an object by search fields in the case where the object is by identification number. Function objects string Ref_Key –an identification number.

&OnServer Function P searchObjectBySearchFields(HTTPConnection,PublicationName,Element,SearchFields) Condition = "" ; For Each KeyValue From Search Field Loop Condition = Condition + KeyValue.Key+ "eq"" + KeyValue.Value+ "" and "; EndCycle; Request Text =Lev(Condition, StrLength(Condition)-5); // remove the last 5 characters ResourceAddress= PublicationName+ "/odata/standard.odata/" +Element+ "?$filter=" + Request Text+ "&$format=json& $select=Ref_Key" ; //Call my custom function Answer Structure= CallHTTPMethodOnServer( "GET",HTTPConnection,ResourceAddress); If Answer Structure .StatusCode >= 400 Then //General PurposeClientServer.NotifyUser(Element+ "Error"+ResponseStructure.StatusCode); //General PurposeClientServer.NotifyUser(ResponseStructure.ServerResponseUndecrypted); Return undefined; endIf; Match = Answer Structure. ReplyServer a; Array = Match["value" ]; If Array = Undefined Then Return Match ["Ref_Key" ] Else Return Array ["Ref_Key" ]; endIf; EndFunction

As can be seen from the body of the procedure P searchObjectBySearchFields, selection starts with the keyword$filterin the resource address. Formal parameterSearch Fields –this is a correspondence that contains the names and values ​​of the details.

Please note that the names of the details are sometimes not obvious. It is necessary to remember that for reference books:

  • Code - code,
  • Description – Name
  • DeletionMark – deletion mark,
  • IsFolder – group sign,
  • Parent_Key – parent.
  • If the attribute is of a reference type, the _Key suffix should be added to its name, for example Account_Key.

For documents:

  • Number – document number,
  • Date – document date.

Logical selection operations

  • eq - Equal; /Catalog_Cities?$filter=Name eq ‘Main’;
  • ne - Not equal; /Catalog_Cities?$filter=Name ne ‘Perm’;
  • gt - More; /Catalog_Products?$filter= Price gt 10;
  • ge - Greater than or equal to; /Catalog_Products?$filter=Price ge 10;
  • lt - Less; /Catalog_Products?$filter=Price lt 10;
  • le - Less than or equal to; /Catalog_Products?$filter=Price le 10;
  • or - Logical OR; /Catalog_ Products ?$filter= Price lt 10 or Price gt 100;
  • and - Logical AND; / Catalog _Products?$ filter =Price g t 10 and Price l t 100;
  • not - Negation; /Catalog_ Products ?$filter=not (Price eq 10);

Note also that the value of the actual parameter Element(or entity)) which I pass to the function is formed according to the following rule:

Name Prefix_ConfigurationObjectName_Name Suffix.

Using the standard OData interface, you can access the following objects ( Name Prefix):

  • Directory - Catalog;
  • Document - Document;
  • Document Journal - DocumentJournal;
  • Constant - Constant;
  • Exchange plan - ExchangePlan;
  • Chart of accounts - ChartOfAccounts
  • Chart of calculation types - ChartOfCalculationTypes;
  • Characteristic types chart - ChartOfCharacteristicTypes;
  • Information Register - InformationRegister;
  • Accumulation Register - AccumulationRegister;
  • Calculation register - CalculationRegister;
  • Accounting Register - AccountingRegister;
  • Business process - BusinessProcess;
  • Task - Task.

ConfigurationObjectName- the “Name” property of the configuration object as it is specified in the configurator.

Name Suffix- needed to clarify the resource name, optional, can take the following values:

  • The name of the tabular part of the object;
  • Name of the object's virtual table;
  • RowType - row of the tabular part of the object;
  • RecordType - a separate register entry.

Parameters for accessing resources

After forming the resource name, you need to define the parameters for accessing the resource, for example, ?$filter= Meaning &$format=json& $select= Ref_Key ,

  • $filter- selection when receiving data
  • $format- indicates the format of the returned data,
  • $select- listing of entity properties that will be included in the query result;
  • $metadata- returns a description of the standard OData interface (used without specifying a name suffix, example in one of the images above);
  • $top- limiting the number of records returned;
  • $skip- removes the specified number of records from the query result;
  • $count- returns the number of records in the query selection;
  • $inlinecount=allpage(=none)- adds information about the number of records to the query result
  • $orderby=<Реквизит1>asc,<Реквизит2>desc- sorting the query result
  • allowOnly- only allowed ones (used without the “$” sign).

1.4 Get an array of information register entries

Let's look at an example of obtaining an array of register entries for information about full names of individuals, for example, the history of changes in full names individual

NamePublications = "WebBuh"; Element = "InformationRegister_Name of Individuals"; Period = Undefined; ReferenceType Data= new Structure(); D DataReferenceType.Insert("Individual",Individual_Key); DataNON-ReferenceType= new Structure(); DataNON-ReferenceType.Insert("Individual_Type", "StandardODATA.Catalog_Individuals") Array = GetRegisterInfoSet(HTTPConnection,PublicationName,Element,Period, DimensionsReferenceType, Non-ReferenceType Dimensions)

The body of the GetInfoRegisterRecordSet function, which is called in this example, is shown below

&OnServer Function GetSetRecordRegisterInformation(HTTPConnection,PublicationName,Element,Period =Undefined, DimensionsReferenceType= Undefined Non-ReferenceType Dimensions= Undefined) RequestText = "" ; If Period<>Undefined Then FormattedPeriod= Format (Period,"DF=yyyy-MM-ddTHH:mm:ss"); RequestText = "Period = datetime"" + FormattedPeriod + """ ; endIf; If DimensionsReferenceType <>Undefined Then For Each KeyValue Of DimensionsReferenceType Cycle Powered = ? ( ValueFilled(QueryText), "," ,""); RequestText = RequestText+ Powered up + KeyValue.Key+ "=guid(""+ KeyValue.Value+ "")"; EndCycle; EndIf; If Non-ReferenceType Dimensions<> Undefined Then For Each KeyMeaning Of Non-ReferenceType Dimensions Cycle Asked = ? ( ValueFilled(QueryText), "," ,""); QueryText = QueryText + Fed+ K keyMeaning.Key + "=" + KeyValue.Value; EndCycle; endIf; ResourceAddress=PublicationName + " /odata/standard.odata/" + Element + "("+ Query Text + + ") ?$format=json"; //Call my custom function Answer Structure = Call HTTPMethodOnServer("GET",HTTPConnection,ResourceAddress); If Answer Structure.StatusCode >= 400 Then//General PurposeClientServer.NotifyUser(Element+ "Error"+ResponseStructure.StatusCode); //General PurposeClientServer.NotifyUser(ResponseStructure.ServerResponseUndecrypted); Return undefined; endIf; Match = 0

In 1C:Enterprise, starting from version 8.3.5, the platform can automatically generate a REST interface for the entire configuration. It works using the OData protocol and it allows you to work with directories, documents and registers through a web server. In general, the speed of receiving data is several orders of magnitude faster than through COM or files, which is good news.

Different queries are used for different operations:

  • GET – used to receive data;
  • POST – used to create objects;
  • PATCH – modification of an existing object;
  • DELETE – deleting an object.

Prefixes are used to access various objects:

  • Directory - Catalog;
  • Document - Document;
  • Document Journal - DocumentJournal;
  • Constant - Constant;
  • Exchange plan - ExchangePlan;
  • Chart of accounts - ChartOfAccounts
  • Chart of calculation types - ChartOfCalculationTypes;
  • Characteristic types chart - ChartOfCharacteristicTypes;
  • Information Register - InformationRegister;
  • Accumulation Register - AccumulationRegister;
  • Calculation register - CalculationRegister;
  • Accounting Register - AccountingRegister;
  • Business process - BusinessProcess;
  • Task - Task.

Using the ODATA protocol, you can also use the built-in methods of objects when performing POST requests.

  • For a document – ​​Post() and Unpost();
  • For a task – ExecuteTask();
  • For a business process – Start();
  • For the information register – SliceLast() and SliceFirst();
  • For the accumulation register and the accounting register – Balance(), Turnovers() and BalanceAndTurnovers();
  • For the calculation register – ScheduleData(), ActualActionPeriod(),<ИмяПерерасчета>() and Base<Имя базового регистра расчета>().

To start working with this interface you need to publish it. This is done through the configurator menu “Administration” – “Publish on a web server”, check the box “Publish standard OData interface” and click “Publish”.

After publication, the protocol can be checked at http://<ИмяСервера>/<ИмяБазы>/odata/standard.odata. In the answer we should receive the entire composition of the published tables. It should look similar to the picture below.


If, after publishing the REST interface, the composition of the published data is empty, then you need to use the Set Contents of the Standard OData Interface method. At the input it has 1 parameter of the “array” type. You need to add the metadata that needs to be published to the array.

Composition = new Array;
Composition.Add(Metadata.Directories.Counterparties);
SetCompositionofStandardInterfaceOData(Composition);

http://<ИмяСервера>/<ИмяБазы><ИмяСправочника>

When requesting, you can use the following parameters:

select – in this parameter we indicate the fields we need;

format – set the format in which we want to receive the response (XML or JSON), default XML

odata – if we don’t need a metadata description in the response, then write “odata=nometadata”

filter – here we indicate selections.

As I wrote above, we can get the answer in two XML formats or JSON, default is XML. In order to receive data in JSON format, you need to add “?$format=application/json” to the URL address.

http://<ИмяСервера>/<ИмяБазы>/odata/standard.odata/Catalog_<ИмяСправочника>?$format=application/json

Basically we need to get a specific directory element, and not all its entries. To do this we use the magic word "filter".

http://<ИмяСервера>/<ИмяБазы>/odata/standard.odata/Catalog_<ИмяСправочника>?$format=application/json&$filter=Ref_Key eq guid’UID’

If you noticed, the URL contains two parameters $format and $filter, they can be located in any order, the main thing is that there is a “ sign before the first parameter ? “, and before the second “ & “. The logic here is this: we indicate the directory address in the first part, and the parameters in the second. These parts are separated by the sign “ ? “, but the parameters themselves are separated by the sign “ & “. If you depict it schematically, it looks like this

AddressTable ? $Parameter1=Parameter1Value & $Parameter2=Parameter2Value

What are the most important requirements for business applications? Some of the most important tasks are the following:

  • Ease of changing/adapting application logic to changing business tasks.
  • Easy integration with other applications.
How the first task is solved in 1C was briefly described in the “Customization and Support” section of this article; We will return to this interesting topic in a future article. Today we will talk about the second task, integration.

Integration tasks

Integration tasks can be different. To solve some problems, a simple interactive data exchange is sufficient - for example, to transfer a list of employees to a bank for issuing salary plastic cards. For more complex tasks, fully automated data exchange may be necessary, possibly with reference to the business logic of an external system. There are tasks that are specialized in nature, such as integration with external equipment (for example, retail equipment, mobile scanners, etc.) or with legacy or highly specialized systems (for example, with RFID tag recognition systems). It is extremely important to select the most appropriate integration mechanism for each task.

Integration options with 1C

There are different approaches to implementing integration with 1C applications; which one to choose depends on the requirements of the task.