yoomoney-sdk
Version:
⭐ Typed YooMoney Wallet SDK for NodeJS. Supported API's: Auth, Wallet & Notifications
221 lines (190 loc) • 7.18 kB
JavaScript
const inquirer = require("inquirer").default;
const express = require("express");
const untun = require("untun");
const { API, Auth, AuthScope } = require("..");
const { createServer } = require("http");
const _ = console.log.bind(console);
const app = express();
const server = createServer(app);
run();
async function run() {
console.clear();
_("Подключение...");
/**
* @type {number}
*/
const port = await new Promise((resolve) => {
server.listen(0, () => {
resolve(server.address().port);
});
});
const redirectListener = "/ym";
const tunnel = await untun.startTunnel({ port });
const url = await tunnel.getURL();
const redirectUrl = new URL(redirectListener, url).toString();
console.clear();
_("Для получения токена потребуются создать или изменить приложение в YooMoney");
const { has_app } = await inquirer.prompt({
name: "has_app",
message: "У вас уже есть приложение?",
type: "list",
choices: [
{ name: "Да", value: "yes" },
{ name: "Нет", value: "no" }
]
});
if (has_app === "no") {
console.clear();
_("Создание приложения (1/2):");
_(" 1. Откройте https://yoomoney.ru/myservices/new");
_(' 2. В поле "Название для пользователей" введите "Test"');
_(` 3. В поле "Адрес сайта" введите "${url}"`);
_(
' 4. В поле "Почта для связи" введите "test@example.com" или любую вашу почту'
);
_(` 5. В поле "Redirect URI" введите "${redirectUrl}"`);
_(" 6. Можете не устанавливать логотип");
_(' 7. Включите "Проверять подлинность приложения (OAuth2 client_secret)"');
_(' 8. Нажмите "Всё верно" и подтвердите создание приложения');
_();
} else {
console.clear();
_("Обновление приложения (1/2):");
_(" 1. Откройте https://yoomoney.ru/settings?w=other");
_(
' 2. В секции "Подписки и доступ к кошельку" > "Мои" выберите только что созданное приложение и нажмите "Настроить"'
);
_(" 3. Подтвердите действие на телефоне");
_(` 4. В поле "Адрес сайта" введите "${url}"`);
_(` 5. В поле "Redirect URI" введите "${redirectUrl}"`);
_(' 6. Нажмите "Всё верно" и подтвердите действие на телефоне');
_();
}
await inquirer.prompt({
name: "_",
message: "Для продолжения нажмите Enter"
});
console.clear();
_("Получение данных (2/2):");
_(" 1. Откройте https://yoomoney.ru/settings?w=other");
_(
' 2. В секции "Подписки и доступ к кошельку" > "Мои" выберите только что созданное приложение и нажмите "Настроить"'
);
_(" 3. Подтвердите действие на телефоне");
_(
' 4. Скопируйте "Идентификатор приложения (client_id)" и "OAuth2 client_secret" в терминал'
);
const { clientId, clientSecret } = await inquirer.prompt([
{
name: "clientId",
message: "Идентификатор приложения (client_id)",
type: "input",
validate(value) {
return /^[A-F\d]{64}$/.test(value);
}
},
{
name: "clientSecret",
message: "OAuth2 client_secret",
type: "input",
validate(value) {
return /^[A-F\d]{128}$/.test(value);
}
}
]);
console.clear();
const auth = new Auth(clientId, redirectUrl, clientSecret);
app.all(redirectListener, async (req, res) => {
const query = req.query;
const fail = (error) => {
console.error(error);
return res.status(500).json({ ok: false, error: error.toString() });
};
if (query.error) {
return fail(`Ошибка авторизации: ${query.error}`);
}
if (!query.code) {
return fail(`Ошибка авторизации: Не получен код`);
}
try {
const code = query.code;
console.log("Получен код подтверждения:", code);
const token = await auth.exchangeCode2Token(query.code);
console.log("\n\n", "Получен токен:", token, "\n\n");
return res.status(200).json({ ok: true, token });
} catch (error) {
return fail(error);
}
});
while (true) {
const { actions } = await inquirer.prompt({
name: "actions",
message: "Выберите действия",
type: "checkbox",
choices: [
{
name: "Выбрать права токена",
value: "select"
},
{
name: "Ввести или добавить права токена вручную",
value: "manual"
},
{
name: "Назвать токен (instance_name), чтобы не сбивать прошлые авторизации",
value: "name"
}
]
});
const {
selectedScope = [],
addedScope = [],
instanceName
} = await inquirer.prompt([
{
name: "selectedScope",
when: actions.includes("select"),
type: "checkbox",
message: "Выберите права токена",
choices: Object.values(AuthScope)
},
{
name: "addedScope",
message: "Введите дополнительные права токена через пробел",
type: "input",
filter(value) {
return value.split(/\s+/);
},
when: actions.includes("manual")
},
{
name: "instanceName",
message: "Введите название токена (instance_name)",
type: "input",
when: actions.includes("name")
}
]);
const scope = [...selectedScope, ...addedScope];
_("Подтвердите корректность введённых данных:");
_(` Права токена(${scope.length}): ${scope.join(", ")}`);
_(` Имя токена(instance_name): ${instanceName}`);
const { isCorrect } = await inquirer.prompt({
name: "isCorrect",
message: "Правильно?",
type: "confirm"
});
if (!isCorrect) continue;
const url = auth.getAuthUrl(scope, instanceName);
_("\n\n URL авторизации:", url);
const { action } = await inquirer.prompt({
name: "action",
type: "list",
message: "Ожидание токена. Выберите действие",
choices: [
{ name: "Получить новый токен", value: "new" },
{ name: "Выйти", value: "exit" }
]
});
if (action === "exit") process.exit(0);
}
}