Comparing version 2.0.5 to 2.1.0
@@ -5,2 +5,3 @@ import { ErrorWithCode } from "../error"; | ||
import { AnyResponse } from "./shared.types"; | ||
import { RequestHandler } from "express"; | ||
/** | ||
@@ -112,2 +113,42 @@ * Ошибка, которую выбрасывает P2P API в случае неправильного | ||
/** | ||
* `[Экспериментально]` Упрощает интеграцию с `express` | ||
* | ||
* ## Это middleware кидает ошибки, позаботьтесь об их обработке | ||
* | ||
* @param {Object} [options={}] Параметры обработки запроса | ||
* @param {boolean} [options.memo=true] Флаг для включения/отключения пропуска повторяющихся запросов, если один из них был успешно обработан | ||
* | ||
* @param {RequestHandler<Record<string, string>, any, types.BillStatusData>} actualHandler | ||
* | ||
* @return {RequestHandler} | ||
* | ||
* ##### Пример: | ||
* **В начале файла** | ||
* ```js | ||
* const p2p = new QIWI.P2P(process.env.QIWI_PRIVATE_KEY); | ||
* | ||
* // Повторяю | ||
* // Это middleware кидает ошибки, позаботьтесь об их обработке | ||
* app.use(errorHandling()) | ||
* ``` | ||
* *`Вариант 1 - Классический`* | ||
* | ||
* ```js | ||
* app.post('/webhook/qiwi', p2p.notificationMiddleware(), (req, res) => { | ||
* req.body // Это `BillStatusData` | ||
* }) | ||
* ``` | ||
* | ||
* *`Вариант 2 - Если нужны подсказки типов`* | ||
* | ||
* ```js | ||
* app.post('/webhook/qiwi', p2p.notificationMiddleware({}, (req, res) => { | ||
* req.body // Это `BillStatusData` | ||
* })) | ||
* ``` | ||
*/ | ||
notificationMiddleware(options?: { | ||
memo?: boolean; | ||
}, actualHandler?: RequestHandler<Record<string, string>, any, types.BillStatusData>): RequestHandler; | ||
/** | ||
* Создаёт ссылку оплаты счёта без запроса к API | ||
@@ -114,0 +155,0 @@ * |
@@ -58,2 +58,22 @@ "use strict"; | ||
/** | ||
* @template {CallableFunction} T | ||
* | ||
* @param {T} function_ | ||
* @return {T} | ||
*/ | ||
function promise(function_) { | ||
const wrapper = (...parameters) => { | ||
try { | ||
const result = function_(...parameters); | ||
if (result instanceof Promise) | ||
return result; | ||
return Promise.resolve(result); | ||
} | ||
catch (error) { | ||
return Promise.reject(error); | ||
} | ||
}; | ||
return wrapper; | ||
} | ||
/** | ||
* Имплементирует [P2P API QIWI](https://developer.qiwi.com/ru/p2p-payments) | ||
@@ -185,2 +205,69 @@ * | ||
/** | ||
* `[Экспериментально]` Упрощает интеграцию с `express` | ||
* | ||
* ## Это middleware кидает ошибки, позаботьтесь об их обработке | ||
* | ||
* @param {Object} [options={}] Параметры обработки запроса | ||
* @param {boolean} [options.memo=true] Флаг для включения/отключения пропуска повторяющихся запросов, если один из них был успешно обработан | ||
* | ||
* @param {RequestHandler<Record<string, string>, any, types.BillStatusData>} actualHandler | ||
* | ||
* @return {RequestHandler} | ||
* | ||
* ##### Пример: | ||
* **В начале файла** | ||
* ```js | ||
* const p2p = new QIWI.P2P(process.env.QIWI_PRIVATE_KEY); | ||
* | ||
* // Повторяю | ||
* // Это middleware кидает ошибки, позаботьтесь об их обработке | ||
* app.use(errorHandling()) | ||
* ``` | ||
* *`Вариант 1 - Классический`* | ||
* | ||
* ```js | ||
* app.post('/webhook/qiwi', p2p.notificationMiddleware(), (req, res) => { | ||
* req.body // Это `BillStatusData` | ||
* }) | ||
* ``` | ||
* | ||
* *`Вариант 2 - Если нужны подсказки типов`* | ||
* | ||
* ```js | ||
* app.post('/webhook/qiwi', p2p.notificationMiddleware({}, (req, res) => { | ||
* req.body // Это `BillStatusData` | ||
* })) | ||
* ``` | ||
*/ | ||
notificationMiddleware(options = {}, actualHandler = (_request, _response, next) => next()) { | ||
const calls = new Set(); | ||
const { memo = true } = options; | ||
return async (request, response, next) => { | ||
let notification = {}; | ||
if (!request.body) { | ||
const text = await new Promise((resolve, reject) => { | ||
let accumulated = ""; | ||
request.on("error", (error) => reject(error)); | ||
request.on("data", (data) => (accumulated += String(data))); | ||
request.on("end", () => resolve(accumulated)); | ||
}); | ||
notification = JSON.parse(text); | ||
} | ||
if (typeof request.body === "object") { | ||
notification = request.body; | ||
} | ||
const hash = request.headers["x-api-signature-sha256"]; | ||
if (memo && calls.has(hash)) | ||
return; | ||
if (this.checkNotificationSignature(hash, notification.bill)) { | ||
throw new Error("Notification signature mismatch"); | ||
} | ||
request.body = notification.bill; | ||
if (!memo) | ||
return actualHandler(request, response, next); | ||
await promise(actualHandler)(request, response, next); | ||
calls.add(hash); | ||
}; | ||
} | ||
/** | ||
* Создаёт ссылку оплаты счёта без запроса к API | ||
@@ -187,0 +274,0 @@ * |
// const QIWI = require('qiwi-sdk'); | ||
const { Personal } = require(".."); | ||
@@ -4,0 +3,0 @@ const { Telegraf } = require("telegraf"); |
{ | ||
"name": "qiwi-sdk", | ||
"version": "2.0.5", | ||
"version": "2.1.0", | ||
"description": "Typed QIWI (Bank) SDK", | ||
@@ -66,2 +66,3 @@ "main": "dist/index.js", | ||
"devDependencies": { | ||
"@types/express": "^4.17.13", | ||
"@types/jest": "^27.0.2", | ||
@@ -68,0 +69,0 @@ "@types/node": "^16.10.3", |
316241
3228
25