yoomoney-sdk
Version:
⭐ Typed YooMoney Wallet SDK for NodeJS. Supported API's: Auth, Wallet & Notifications
318 lines (282 loc) • 8.87 kB
text/typescript
import { FormBuilder } from "redirect-form-builder";
import type { URL } from "url";
import type { AutoComplete } from "./autocomplete";
export const PaymentType = {
FromCard: "AC",
FromWallet: "PC",
/** @deprecated **Вариант игнорируется ЮMoney**. Используйте {@link PaymentType.FromCard} (`"AC"`) */
FromMobileBalance: "MC"
} as const;
export type PaymentType = (typeof PaymentType)[keyof typeof PaymentType];
export const QuickPayForm = {
Button: "button"
} as const;
export type QuickPayForm = (typeof QuickPayForm)[keyof typeof QuickPayForm];
export type FormConfig = {
/**
* Номер кошелька ЮMoney, на который нужно зачислять деньги отправителей.
*/
receiver: string;
/**
* Возможные значения:
*
* `button` — единственное валидной значение;
*
* Остальные сохранены для обратной совместимости
*
*
*/
quickPayForm?: AutoComplete<QuickPayForm>;
/**
* Назначение платежа. (До 150 символов)
*
* @deprecated **Поле игнорируется ЮMoney**
*/
targets?: string;
/**
* Способ оплаты. Возможные значения:
*
* `PC` — оплата из кошелька ЮMoney;
*
* `AC` — с банковской карты;
*
*/
paymentType?: AutoComplete<PaymentType>;
/**
* Сумма перевода (спишется с отправителя).
*/
sum: number;
/**
* Название перевода в истории отправителя (для переводов из кошелька или с привязанной карты). Отображается в кошельке отправителя.
*
* Удобнее всего формировать его из названий магазина и товара. Например: `Мой магазин: валенки белые`
*
* @deprecated **Поле игнорируется ЮMoney**
*/
formComment?: string;
/**
* Название перевода на странице подтверждения. Рекомендуем делать его таким же, как `formComment`.
*
* @deprecated **Поле игнорируется ЮMoney**
*
*/
shortDest?: string;
/** Метка, которую сайт или приложение присваивает конкретному переводу. Например, в качестве метки можно указывать код или идентификатор заказа. (До 64 символов) */
label?: string;
/**
* Поле, в котором можно передать комментарий отправителя перевода. (До 200 символов)
*
* @deprecated **Поле игнорируется ЮMoney**
*
*/
comment?: string;
/** URL-адрес для редиректа после совершения перевода. */
successURL?: string;
/**
* Нужны ФИО отправителя.
*
* @deprecated **Поле игнорируется ЮMoney**
*
* */
needFio?: boolean;
/**
* Нужна электронная почты отправителя.
*
* @deprecated **Поле игнорируется ЮMoney**
*
**/
needEmail?: boolean;
/**
* Нужен телефон отправителя.
*
* @deprecated **Поле игнорируется ЮMoney**
*
* */
needPhone?: boolean;
/**
* Нужен адрес отправителя.
*
* @deprecated **Поле игнорируется ЮMoney**
*
* */
needAddress?: boolean;
};
type FormQueryObject = Record<
"receiver" | "quickpay-form" | "paymentType" | "sum",
string
> &
Partial<
Record<
| "formcomment"
| "short-dest"
| "label"
| "comment"
| "successURL"
| "need-fio"
| "need-email"
| "need-phone"
| "need-address"
| "targets",
string
>
>;
/**
*
* @param {FormConfig} config
* @return {FormQueryObject}
*/
function convert(config: FormConfig): FormQueryObject {
return {
"quickpay-form": config.quickPayForm ?? "button",
paymentType: config.paymentType ?? PaymentType.FromCard,
receiver: config.receiver,
sum: config.sum.toString(),
targets: config.targets,
"need-address": String(!!config.needAddress),
"need-email": String(!!config.needEmail),
"need-fio": String(!!config.needFio),
"need-phone": String(!!config.needPhone),
"short-dest": config.shortDest,
comment: config.comment,
formcomment: config.formComment,
label: config.label,
successURL: config.successURL
};
}
const FORM_ACTION_URL = "https://yoomoney.ru/quickpay/confirm.xml";
/**
* Генерирует HTML формы для переводов
* @class PaymentFormBuilder
*/
export class PaymentFormBuilder {
/**
*
* Creates an instance of PaymentFormBuilder.
* @param {FormConfig} [config={
* receiver: "",
* sum: 10,
* }] Изначальные настройки формы
*/
constructor(
public readonly config: FormConfig = { receiver: "", sum: 10 },
public readonly url = FORM_ACTION_URL
) {}
/**
* Генерирует стандартные сеттеры
*
* @param {string} field
* @return {Function}
* @private
*/
private _makeSetter<T extends keyof FormConfig>(
field: T
): (value: FormConfig[T]) => this {
return (value: FormConfig[T]) => Object.defineProperty(this, field, { value });
}
/**
* Задаёт сумму платежа
*
* @alias {@link setSum}
* @param {string | number} amount Сумма
* @return {this}
*/
setAmount(amount: number | string): this {
this.config.sum = Number.parseFloat(
Number.parseFloat(amount.toString()).toFixed(2)
);
return this;
}
/**
* Задаёт сумму платежа
*
* @alias {@link setAmount}
* @param {string | number} amount Сумма
* @return {this}
*/
setSum(amount: number | string): this {
this.config.sum = Number.parseFloat(
Number.parseFloat(amount.toString()).toFixed(2)
);
return this;
}
/**
* Задаёт получателя платежа
*
* @param {string | number} receiver Получатель
* @return {this}
*/
setReceiver(receiver: number | string): this {
this.config.receiver = receiver.toString();
return this;
}
/**
* Задаёт URL перенаправления после успешного платежа
*
* @param {string | URL} url URL
* @return {this}
*/
setSuccessURL(url: string | URL): this {
this.config.successURL = url.toString();
return this;
}
readonly setQuickPayForm = this._makeSetter("quickPayForm");
readonly setPaymentType = this._makeSetter("paymentType");
readonly setLabel = this._makeSetter("label");
/** @deprecated **Поле игнорируется ЮMoney** */
readonly setTargets = this._makeSetter("targets");
/** @deprecated **Поле игнорируется ЮMoney** */
readonly setFormComment = this._makeSetter("formComment");
/** @deprecated **Поле игнорируется ЮMoney** */
readonly setShortDest = this._makeSetter("shortDest");
/** @deprecated **Поле игнорируется ЮMoney** */
readonly setComment = this._makeSetter("comment");
/**
* @deprecated **Поле игнорируется ЮMoney**
*
* @param {boolean} [doRequire=true]
* @return {this}
*/
requireFio(doRequire = true): this {
this.config.needFio = doRequire;
return this;
}
/**
* @deprecated **Поле игнорируется ЮMoney**
*
* @param {boolean} [doRequire=true]
* @return {this}
*/
requireAddress(doRequire = true): this {
this.config.needAddress = doRequire;
return this;
}
/**
* @deprecated **Поле игнорируется ЮMoney**
*
* @param {boolean} [doRequire=true]
* @return {this}
*/
requireEmail(doRequire = true): this {
this.config.needEmail = doRequire;
return this;
}
/**
* @deprecated **Поле игнорируется ЮMoney**
*
* @param {boolean} [doRequire=true]
* @return {this}
*/
requirePhone(doRequire = true): this {
this.config.needPhone = doRequire;
return this;
}
/**
* Генерирует HTML на основе заданных параметров
* @param {boolean} [fullPage=false]
* @return {string}
*/
buildHtml(fullPage = false): string {
const fields = convert(this.config);
return new FormBuilder(this.url, "POST", fields).buildHtml(fullPage);
}
}