Интеграция с ЦБ РФ осуществляется по 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
}
Во вложении находится модуль, в котором реализовано Действие в БП, а также виджет, позволяющие осуществлять данную интеграцию