UNPKG

yoomoney-sdk

Version:

⭐ Typed YooMoney Wallet SDK for NodeJS. Supported API's: Auth, Wallet & Notifications

137 lines (121 loc) 4.06 kB
import { FormBuilder } from "redirect-form-builder"; import { type Agent, fetch } from "./fetch"; export type AuthScope = | "account-info" | "operation-history" | "operation-details" | "incoming-transfers" | "payment" | "payment-shop" | "payment-p2p" | "money-source" | (string & {}); export const AuthScope: Record<string, AuthScope> = { AccountInfo: "account-info", OperationHistory: "operation-history", OperationDetails: "operation-details", IncomingTransfers: "incoming-transfers", Payment: "payment", PaymentShop: "payment-shop", PaymentP2P: "payment-p2p", MoneySource: "money-source" }; /** * Ошибка в процессе авторизации * @class YMAuthError */ export class YMAuthError extends Error { /** * * @param {string} code Код ошибки */ constructor(public code: string) { super(`API returned error: ${code}`); this.name = "YMAuthError"; } } // Костыль, TypeScript не видит URL в global declare const URL: typeof import("url").URL; /** * Реализует всё необходимое для [авторизации через YooMoney](https://yoomoney.ru/docs/wallet/using-api/authorization/basics) * * @see {@link https://yoomoney.ru/docs/wallet/using-api/authorization/basics|Описание протокола} * @class Auth */ export class Auth { /** * Creates an instance of Auth. * @param {string} clientId ID приложения * @param {string} redirectUrl URL-перенаправления * @param {string=} [clientSecret] Секретное Слово * @param {string} [endpoint="https://yoomoney.ru/oauth"] По умолчанию `https://yoomoney.ru/oauth` * @param {Agent=} [agent] HTTP Agent для использования с Proxy */ constructor( public clientId: string, public redirectUrl: string, public clientSecret?: string, public endpoint = "https://yoomoney.ru/oauth", public agent?: Agent ) {} /** * Генерирует html-форму перенаправления пользователя на авторизацию * * @param {AuthScope[]} scope * @param {string=} instanceName * @return {string} */ getAuthForm(scope: AuthScope[], instanceName?: string): string { const builder = new FormBuilder(`${this.endpoint}/authorize`, "POST", { client_id: this.clientId, response_type: "code", redirect_uri: this.redirectUrl, scope: scope.join(" ") }); if (instanceName) { builder.setField("instance_name", instanceName); } return builder.buildHtml(); } /** * Генерирует URL для перенаправления пользователя на авторизацию * * @param {AuthScope[]} scope * @param {string=} instanceName * @return {string} */ getAuthUrl(scope: AuthScope[], instanceName?: string): string { const url = new URL(`${this.endpoint}/authorize`); url.searchParams.set("client_id", this.clientId); url.searchParams.set("response_type", "code"); url.searchParams.set("redirect_uri", this.redirectUrl); url.searchParams.set("scope", scope.join(" ")); if (instanceName) { url.searchParams.set("instance_name", instanceName); } return url.toString(); } /** * Обменивает временный токен на постоянный токен авторизации * * @throws {YMAuthError} * @param {string} code Временный токен (authorization code) * @return {Promise<string>} Токен авторизации */ async exchangeCode2Token(code: string): Promise<string> { const json = await fetch( `${this.endpoint}/token`, { code, client_id: this.clientId, grant_type: "authorization_code", redirect_uri: this.redirectUrl, client_secret: this.clientSecret }, {}, this.agent ); if (json.error) throw new YMAuthError(json.error); return json.access_token; } }