...

Реализация своих методов API

Тема в разделе "Примеры решений и дополнительных модулей", создана пользователем kamyshev, 11 фев 2022.

  1. kamyshev

    kamyshev New Member

    Часто на проектах возникают ситуации когда необходимо реализовать свои собственные методы API. Один из ярких примеров с одного из моих проектов: возникла необходимость интегрировать сторонний frontend-интерфейс с ELMA365. В данном случае платформа ELMA365 выступает как backend-сервер. И для интеграции понадобилось создания точек интеграции между двумя системами.

    Для общения систем спроектируем свой API. При проектировании своих методов необходимо придерживаться архитектурного стиля REST. Подробнее с этим стилем и теорией по протоколу http предлагаю ознакомиться здесь и на Wikipedia (EN).

    Платформа ELMA365 предоставляет удобные инструменты для создания своих методов API. Они реализуются в рамках модулей и ознакомиться с функционалом можно в статье справки. Ниже приведу пример работы с этим функционалом.

    Рассмотрим работу с методом GET. Согласно спецификации клиент может передавать параметры выполнения запроса в URI целевого ресурса после символа '?'. Нам необходимо будет разобрать эту строку:

    Код:
    
    async function getAppForGuardianship(reqFetchRequest): Promise<HttpResponse void> {
        
    // Создаем новый экземпляр объекта для ответа клиенту
        
    const response = new HttpResponse()
        const 
    phonesstring[] = []
        
    // Здесь как раз получаем параметр id из строки запроса
        
    const id req.query?.['id'] as string

        
    const result await Global.ns._clients.app._leads.search().size(10000).where(=> f.__id.eq(id)).first()

        if (
    result) {
            for (
    let phone of result.data.contact_phone!) {
                
    phones.push(phone.tel)
            }

            
    //  "Собираем" наш ответ клиенту
            
    response
                
    .status(200// Обязательно указываем код статуса! 200 - успех, подробнее по ссылкам в конце статьи
                // Собираем тело ответа в виде JSON объекта, stringify применять уже не надо
                
    .json({
                    
    msg'success',
                    
    nameresult.data.__name result.data.__name 'name is empty',
                    
    parent_fullnameresult.data.parent_fullname,
                    
    child_fullnameresult.data.child_fullname,
                    
    child_birthdateresult.data.birthdate!.format('DD.MM.YYYY'),
                    
    cityresult.data.city,
                    
    child_citizenshipresult.data.citizenship,
                    
    emailresult.data.email result.data.email.email 'e-mail не указан',
                    
    contact_phonephones,
                    
    pa_diagnosisresult.data.pa_diagnosis
                
    })
                .
    set('Content-Type''application/json'// Явно указываем тип содержимого ответа
        
    }
        else {
            
    // При разработке REST API важно обрабатывать все ошибки и отдавать клиенту вразумительный ответ, чтобы можно было обработать его допустим на фронте
            
    response
                
    .status(404)
                .
    json({
                    
    msg'error: App for Guardianship not found'
                
    })
                .
    set('Content-Type''application/json')
        }

        return 
    response
    }
    Вызов этого метода на клиенте:
    Код:
    
    async function getUserDataFromElma() {
        const 
    elmaUserId = $('#elma-id').html();
        const 
    apiUrl = `https://aeql4vg6lxcee.elma365.ru/api/extensions/3d15932c-766e-4e91-b8ff-fed442649de2/script/get/appgs?id=${elmaUserId}`;
        return 
    await fetch(apiUrl, {
            
    method'GET',
            
    headers: {
                
    'Content-Type''application/json',
                
    'Authorization''Bearer 8657d620-f5eb-4552-997d-d3ec41688c39',
            }
        })
    }
    Теперь рассмотрим работу с методом POST. Согласно спецификации содержимое запроса передается в его теле, т.е. нам необходимо будет разобрать содержимое тела запроса:
    Код:
    
    async function createAppForGuardianship(reqFetchRequest): Promise<HttpResponse void> {
        
    // Создаем новый экземпляр объекта для ответа клиенту
        
    const response = new HttpResponse()
        
    // Клиент передал нам содержимое в виде JSON-пакета, поэтому разберем его в массив
        
    const request JSON.parse(req.body! as string)

        try {
            const 
    result = Global.ns._clients.app._leads.create()
            
    result.data.contact_phone = []
            
    result.data.parent_fullname request['form_submit_data']['parent-name']
            
    result.data.child_fullname request['form_submit_data']['child-name']
            
    result.data.birthdate = new Datetime(request['form_submit_data']['date-birth'], "d.m.Y").getDate()
            
    result.data.city request['form_submit_data']['city']
            
    result.data.email result.fields.email.create(request['form_submit_data']['your-email'])
            
    result.data.contact_phone.push(result.fields.contact_phone.create(request['form_submit_data']['your-number'], PhoneType.Main))
            
    result.data.pa_diagnosis request['form_submit_data']['diagnosis']
            
    result.data.description request['form_submit_data']['your-condition']

            
    await result.save()
            
    await result.setStatus(result.fields.__status.groups.wards.variants.new)

            
    // Формируем ответ клиенту
            
    response
                
    .status(200)
                .
    json({
                    
    msg'success',
                    
    idresult.data.__id
                
    })
                .
    set('Content-Type''application/json')
        }
        catch (
    e) {
            
    // Отдаем ошибку клиенту, если что-то пошло не так
            
    response
                
    .status(500)
                .
    json({
                    
    msg'error: new app do not create',
                })
                .
    set('Content-Type''application/json')
        }

        return 
    response
    }
    Пример вызова метода на стороне клиента:
    Код:
    
    async function updateUserDataFromElma() {
        const 
    urlParam formId 'medical' 'main';
        const 
    apiUrl = `https://aeql4vg6lxcee.elma365.ru/api/extensions/3d15932c-766e-4e91-b8ff-fed442649de2/script/ward/${urlParam}/update`;
        
    requestBody JSON.stringify({
                        
    iduserId,
                        
    form_idformId,
                        
    contextcontextObject.context
                    
    })
        return 
    await fetch(apiUrl, {
            
    method'POST',
            
    headers: {
                
    'Content-Type''application/json',
                
    'Authorization''Bearer 8657d620-f5eb-4552-997d-d3ec41688c39',
            },
            
    bodyrequestBody
        
    })
    }
    Подведём итог. Для работы со строкой запроса метода GET используем поле FetchRequest.query, а для работы с телом метода POST парсим поле FetchRequest.body как JSON объект. Ниже приведу полное описание полей и методов интерфейсов FetchRequest и HttpResponse.
    Код:
    
    reqFetchRequest

    req
    .body тело запросатип string или FormData
    req
    .headers заголовки запросаможно разобрать методами get() для типа Record
    req
    .method тип метода запроса
    req
    .query строка из самого запроса

    const response = new HttpResponse()
    response
      
    .content('') - отдать содержимое в виде строкиможно формировать html страницы
      
    .cookie('','') - установить кукуформат (параметр,значение)
      .
    redirect('') - выполнить редирект (важно отдать код из группы 300), можно таким образом поддерживать устаревшие методы
      
    .setFile(file,'') - отдать в теле ответа файл
      
    .status(200) - указать код статуса ответа
      
    .json({}) - сформировать тело ответа в виде JSON объекта
      
    .set('Content-Type''application/json')
    Особое внимание необходимо уделить адекватным кодам статусов ответов. Ознакомиться с ними можно здесь.
     
    Последнее редактирование: 11 фев 2022
  2. a.sysoev

    a.sysoev New Member

    Вот тут точно должно быть так:
    const elmaUserId = $('#elma-id').html();

    Т.е. мы в elmaUserId передаём HTML-код?

    Если #elma-id -- это у нас input, то логичнее было бы:
    const elmaUserId = $('#elma-id').val();
     
  3. kamyshev

    kamyshev New Member

    На стороне фронтенда для теста был просто div с данным id, роли в данной статье абсолютно не играет
     
  4. ioyamaleev

    ioyamaleev New Member

    Добрый день. Подскажите, а примера как получить данные если body не строка а FormData имеются? Задача стоит получить файлы и данные из другой системы в формате FormData и сохранить их в ELMA.