...

Получение курса валют ЦБ РФ

Тема в разделе "Примеры решений и дополнительных модулей", создана пользователем novopashin, 5 июн 2023.

  1. novopashin

    novopashin Новичок

    Интеграция с ЦБ РФ осуществляется по SOAP протоколу. Стоит обратить внимание, что веб-сервис находится на http, поэтому для корректной интеграции нужно использовать серверные сценарии.

    В теле запроса мы передаем XML строку, в которой необходимо указать интересующую нас дату. Кроме этого в Content-Length нужно записать длину этой строки. В ответ нам приходит XML документ в формате System.Data.Dataset, содержащий таблицу [ValuteCursOnDate] XSD, таблица содержит поля:
    • Vname — Название валюты
    • Vnom — Номинал
    • Vcurs — Курс
    • Vcode — ISO Цифровой код валюты
    • VchCode — ISO Символьный код валюты
    Остается только распарсить полученный ответ.
    Код:
    
    interface ProcessedCurrency {
        Vname: string,
        Vnom: number,
        Vcurs: number,
        Vcode: number,
        VchCode: string
    }

    async function integration(): Promise<void> {
        const my_str = `<?xml version="1.0" encoding="utf-8"?><soap:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"><soap:Body><GetCursOnDate xmlns="http://web.cbr.ru/"><On_date>${(new Datetime()).format()}</On_date></GetCursOnDate></soap:Body></soap:Envelope>`
        const request = await fetch('http://www.cbr.ru/DailyInfoWebServ/DailyInfo.asmx', {
            method: "POST",
            headers: {
                'Host': 'www.cbr.ru',
                'Content-Type': 'text/xml; charset=utf-8',
                'Content-Length': `${my_str.length}`,
                'SOAPAction': "http://web.cbr.ru/GetCursOnDate"   
            },
            body: my_str
        });
        if (request.ok) {
            const text =  await request.text()
            // Подготовка массива с Названием валюты
            const array_names = parseXML(text, 'Vname');
            // Подготовка массива с Номиналом валюты
            const array_vnom = parseXML(text, 'Vnom', true);
            // Подготовка массива с Курсом валюты
            const array_curs = parseXML(text, 'Vcurs', true);
            // Подготовка массива с ISO Цифровым кодом валюты
            const array_vcode = parseXML(text, 'Vcode', true);
            // Подготовка массива с ISO Символьным кодом валюты
            const array_vchcode = parseXML(text, 'VchCode');
            if (!array_names || !array_vnom || !array_curs || !array_vcode || !array_vchcode) {
                Context.data.error = 'Ошибка при обработке данных Банка'
                return
            }
            // Создание и заполнение массива обработанных данных по каждой валюте
            const need_length = Math.min(array_names.length, array_curs.length, array_vnom.length, array_vcode.length, array_vchcode.length);
            const array_processed_currencies: ProcessedCurrency[] = [];
            for (let i = 0; i < need_length; i++) {
                const processed_currency: ProcessedCurrency = {
                    Vname: array_names[i] as string,
                    Vnom: array_vnom[i] as number,
                    Vcurs: array_curs[i] as number,
                    Vcode: array_vcode[i] as number,
                    VchCode: array_vchcode[i] as string
                }
                array_processed_currencies.push(processed_currency)
            }
            Context.data.text = JSON.stringify(array_processed_currencies)
        } else {
            Context.data.error = 'Во время запроса произошла ошибка'
        }
    }

    function parseXML(text: string, code: 'Vname' | 'Vnom' | 'Vcurs' | 'Vcode' | 'VchCode', isNumber: boolean = false): string[] | number[] | undefined {
        const regexp = new RegExp(`<${code}>(.*?)<\/${code}>`, 'gs');
        const array = text.match(regexp);
        if (array && array.length > 0) {
            if (!isNumber) {
                return array.map((f) => f.split(`</${code}>`)[0].split(`<${code}>`)[1].trim())
            } else {
                return array.map((f) => Number(f.split(`</${code}>`)[0].split(`<${code}>`)[1].trim()))
            }
        } else return undefined
    }
    Во вложении находится модуль, в котором реализовано Действие в БП, а также виджет, позволяющие осуществлять данную интеграцию

    Вложения:

    Последнее редактирование: 5 июн 2023
  2. victor.alekhin

    victor.alekhin Новичок