Skip to content

Библиотека для взаимодействия с API Т-Кассы.

License

Notifications You must be signed in to change notification settings

kravetsone/t-kassa-api

Repository files navigation

t-kassa-api

npm npm downloads JSR JSR Score

Библиотека для взаимодействия с API Т-Кассы.

import { TKassa } from "t-kassa-api";

const ткасса = new TKassa(process.env.TERMINAL_KEY, process.env.PASSWORD, {
    server: "https://rest-api-test.tinkoff.ru",
});

const result = await ткасса.init({
    Amount: 1000,
    OrderId: "12",
});

console.log(result);

API Reference

Фичи

Webhook

Пример использования webhook с фреймворком Hono

import { Hono } from "hono";
import { TKassa, webhookHandler, filters } from "t-kassa-api";

const ткасса = new TKassa(process.env.TERMINAL_KEY, process.env.PASSWORD);

ткасса.on(
    filters.and(
        filters.equal("Status", "SUCCESS"),
        filters.notNullable("RebillId")
    ),
    (context) => {
        // при этом типы понимают фильтры
    }
);

const app = new Hono();

app.get("/", webhookHandler(ткасса, "hono"));

Поддерживаемые webhook адаптеры

или любой другой фреймворк

// a non-existing framework for the example
import { App } from "some-http-framework";
import { TKassa } from "t-kassa-api";

const ткасса = new TKassa(process.env.TERMINAL_KEY, process.env.PASSWORD, {
    server: "https://rest-api-test.tinkoff.ru",
});

const app = new App().post("/t-kassa", async (req) => {
    // req.body must be json equivalent to Webhook notification body
    await ткасса.emit(req.body);
});

app.listen(80);

Режим мульти-кассы

Не всегда бывает удобным передача параметров одной кассы в конструктор класса, поэтому и появился режим мульти-кассы. Он позволяет вам не указывать TerminalKey и Password.

import { TKassa } from "t-kassa-api";

const ткасса = new TKassa();

const result = await ткасса.init({
    Amount: 1000,
    OrderId: "12",
    TerminalKey: "12312sf",
    Password: "123123231",
});

console.log(result);

И как вы можете заметить, теперь требуется указывать TerminalKey и Password в теле запроса. И в типах это тоже выражено! Магия? Не иначе.

Но как тогда получать webhook события? (нотификацию)

Для этого вам понадобится указать функцию первым аргументом конструктора.

import { TKassa } from "t-kassa-api";

const ткасса = new TKassa((body) => {
    const [kassa] = await db
        .select()
        .from(kassaTable)
        .where(eq(kassaTable.terminalKey, body.TerminalKey));

    if (!kassa) throw new Error("Касса не найдена");

    return {
        Password: kassa.password,
        custom: { kassa },
    };
});

ткасса.on(
    filters.and(
        filters.equal("Status", "SUCCESS"),
        filters.notNullable("RebillId")
    ),
    (context, { kassa }) => {
        // и тут появляется вторым аргументов переданное вами значение в custom
    }
);

И типы опять же совсем не глупы и делают вам благое дело, указывая верный путь.

RequestsOptions

Вы можете повлиять на поведение запроса

Глобально

const tKassa = new TKassa({
    requestsOptions: {
        headers: {
            "x-awesome": "this library is great",
        },
    },
});

Для одного запроса

await tKassa.getQr(/** some data */, {
    signal: AbortSignal.timeout(500)
});

Таким образом вы можете, например, воспользоваться прокси.

В Node.js

import { ProxyAgent } from "undici";

const proxyAgent = new ProxyAgent("my.proxy.server");

const tKassa = new TKassa({
    requestsOptions: {
        dispatcher: proxyAgent,
    },
});

Несмотря на то что undici работает под капотом Node.js, вам придётся его скачать. Также убедитесь, что у вас нет "lib": ["DOM"] в вашем tsconfig.json, иначе вы не увидите свойства dispatcher (хотя undici всё равно его обработает).

В Bun

const tKassa = new TKassa({
    requestsOptions: {
        proxy: "my.proxy.server",
    },
});

Функции-хелперы

Генерирует подпись для запроса.

const signature = generateSignature(
    { body: "OK" },
    process.env.TERMINAL_KEY,
    process.env.PASSWORD
);

Шифрует данные карты.

const cardData = encryptCardData(тк, {
    PAN: "4000000000000101",
    ExpDate: "1230",
    CVV: "111",
});

const tds = await тк.check3dsVersion({
    PaymentId: response.PaymentId,
    CardData: cardData,
});

Функция, которая отправляет запрос в сервис аутентификации банка (по ACSUrl) в зависимости от версии 3D-Secure. Возвращает Response с HTML формочкой, которую браузер сабмитнет сразу. Вместо этого метода рекомендуется использовать элемент form в <body onload="document.form.submit()">.

const response = await fetchACSUrl(finishAuthorize.ACSUrl, threeDS.version, {
    MD: finishAuthorize.MD,
    PaReq: finishAuthorize.PaReq,
    TermURL: "https://example.com",
    // other data
});

Подробнее

Функция для получения строкового представления creq (нужен для 3DS 2.0)

const str = encryptCReq({
    threeDSServerTransID: data.threeDSServerTransID,
    acsTransID: data.acsTransID,
    challengeWindowSize: data.challengeWindowSize,
    messageType: "CReq",
    messageVersion: threeDS.version,
});

Функция для получения строкового представления ThreeDSMethodData

const tds = await тк.check3dsVersion({
    PaymentId: response.PaymentId,
    CardData: CardData,
});

if (tds.ThreeDSMethodURL && tds.TdsServerTransID) {
    const data = encryptThreeDSMethodData({
        threeDSMethodNotificationURL: tds.ThreeDSMethodURL,
        threeDSServerTransID: tds.TdsServerTransID,
    });
}