All files / src/apis/p2p p2p.ts

100% Statements 26/26
100% Branches 7/7
100% Functions 5/5
100% Lines 26/26

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162  5x 5x 5x 5x 5x 5x 5x 5x           5x                 5x 5x   5x 5x 5x   5x 5x 5x                   5x 5x   5x                           5x                         2x                                       1x                         5x     5x                                                                                                   1x      
import type { RequestHandler } from "express";
import { ApiClass } from "../api";
import { environment } from "../shared/environment";
import { SimpleJsonHttp } from "../shared/http";
import { url } from "../shared/url";
import { USER_AGENT } from "../shared/identity";
import { P2pBillsApi } from "./bills.api";
import { mapHttpErrors } from "./p2p.errors";
import {
  BillRequestHandler,
  MiddlewareOptions,
  createP2pNotificationMiddleware
} from "./p2p.middleware";
import type { P2pApiOptions } from "./p2p.options";
import { BillCurrency, BillPaySource, BillStatus } from "./p2p.types";
 
/**
 * # P2P-счета
 * [Документация QIWI](https://developer.qiwi.com/ru/p2p-payments/)
 *
 * @export
 * @class P2p
 */
export class P2p extends ApiClass<P2pApiOptions> {
  static readonly BillsApi = P2pBillsApi;
 
  static readonly BillCurrency = BillCurrency;
  static readonly BillPaySource = BillPaySource;
  static readonly BillStatus = BillStatus;
 
  static readonly Currency = BillCurrency;
  static readonly PaySource = BillPaySource;
  static readonly Status = BillStatus;
 
  /**
   *
   *
   * @static
   * @param {string} secretKey
   * @return {SimpleJsonHttp} SimpleJsonHttp
   * @memberof P2p
   */
  static httpClientFactory = (secretKey: string): SimpleJsonHttp => {
    const http = new SimpleJsonHttp();
 
    http.client.options = {
      ...http.client.options,
      baseURL: url`https://api.qiwi.com/partner/bill/v1/bills/`(),
      headers: {
        Accept: "application/json",
        "Content-Type": "application/json",
        "User-Agent": USER_AGENT,
        Authorization: `Bearer ${secretKey}`
      },
      okStatusCodes: [200],
      timeout: 10_000,
      mapHttpErrors
    };
 
    return http;
  };
 
  /**
   *
   *
   * @static
   * @param {string} secretKey
   * @param {string} [publicKey=""]
   * @return {P2p} P2p
   * @memberof P2p
   */
  static create(secretKey: string, publicKey = ""): P2p {
    return new this({
      http: this.httpClientFactory(secretKey),
      publicKey,
      secretKey
    });
  }
 
  /**
   *
   *
   * @static
   * @param {string} [secretKey=process.env.QIWI_SECRET_KEY]
   * @param {string} [publicKey=process.env.QIWI_PUBLIC_KEY]
   * @return {P2p} P2p
   * @memberof P2p
   */
  static env(
    secretKey = environment.QIWI_SECRET_KEY,
    publicKey = environment.QIWI_PUBLIC_KEY
  ): P2p {
    return this.create(secretKey, publicKey);
  }
 
  /**
   * Creates an instance of P2p.
   * @param {P2pApiOptions} [options]
   * @memberof P2p
   */
  constructor({
    publicKey = "",
    secretKey = "",
    http = P2p.httpClientFactory(secretKey)
  }: Partial<P2pApiOptions> = {}) {
    super({ publicKey, secretKey, http });
  }
 
  readonly bills = new P2p.BillsApi(this._options);
 
  /**
   * `[Экспериментально]` Упрощает интеграцию с `express`
   *
   * ## Это middleware кидает ошибки, позаботьтесь об их обработке
   *
   * @param {Object} [options] Параметры обработки запроса
   * @param {boolean} [options.memo=true] Флаг для включения/отключения пропуска повторяющихся запросов, если один из них был успешно обработан
   *
   * @param {RequestHandler<Record<string, string>, any, BillStatusNotificationBody>} handler
   *
   * @return {RequestHandler}
   *
   * ##### Пример:
   * **В начале файла**
   * ```js
   * const p2p = new QIWI.P2P(process.env.QIWI_PRIVATE_KEY);
   * ```
   * *`Вариант 1 - Классический`*
   *
   * ```js
   * app.post('/webhook/qiwi', p2p.notificationMiddleware(), (req, res) => {
   *  req.body // Это `BillStatusNotificationBody`
   * })
   * ```
   *
   * *`Вариант 2 - Если нужны подсказки типов`*
   *
   * ```js
   * app.post('/webhook/qiwi', p2p.notificationMiddleware({}, (req, res) => {
   *  req.body // Это `BillStatusNotificationBody`
   * }))
   * ```
   *
   * **Обработка ошибок**
   * ```js
   * app.use((error, request, response, next) => {
   *  console.log(error); // [Error: Notification signature mismatch]
   * })
   * ```
   */
  notificationMiddleware(
    /* istanbul ignore next */
    options: MiddlewareOptions = {},
 
    // Стандартный middleware. Не нуждается в тестировании
    /* istanbul ignore next */
    handler?: BillRequestHandler
  ): RequestHandler {
    return createP2pNotificationMiddleware(this.bills, options, handler);
  }
}