Запрос выплаты через Telegram бот

На коленке накидал бот, который позволяет создавать выплаты через панель.

:information_source: У нас нет публичного API, который позволяет создавать выплаты по соображениям безопасности. Ниже код, который имитирует запрос, словно он сделан через браузер.

:information_source: Использование

  • /start – пингует бота. Если бот ответил, значит установка правильная
  • /setcookie $cookie – сохраняет обязательный куки, без которого бот будет выдавать ошибку. Инструкция по получению выше
  • /settoken $token – также, как /setcookie
  • /balance – отображает баланс вашего аккаунта
  • /payout $method $purse $sum – запрашивает выплату на указанный реквизит. $method может быть qiwi или card

:building_construction: Установка

  1. Установите на сервер ggram (скачайте и киньте в addons)
  2. По пути addons/ggram-mod/lua/autorun/ggram-launcher.lua скопируйте и вставьте код загрузчика из этой страницы
  3. Создайте файл addons/ggram-mod/lua/ggram/bots/gmdbot/_init.lua и поместите в него код, который ниже
  4. На первой строке укажите токен своего бота. Получить можно в Telegram: Contact @BotFather
  5. На 6й строке замените 123456 на свой telegram id. Получить можно в Telegram: Contact @jsonson_bot
  6. На этом этапе после перезагрузки сервера, у вас в боте должна работать команда /start. Если не работает, значит дальше пока не читайте, пока не разберетесь в проблеме
  7. Если /start ответила “hello”, значит все хорошо. Теперь вам нужно вызвать команды /setcookie и /settoken в боте. :point_down: Информация ниже

Получаем значение для /setcookie

Можете либо извлечь значение куки без плагина или с плагином для браузера.

С плагином

Установите EditThisCookie, на странице выплат откройте окно расширения и скопируйте там это значение: скриншот

Без плагина

  1. Зайдите на сайт, сразу на страницу выплат.
  2. Откройте dev tools (F12)
  3. Обновите страницу и затем вот тут получите куки: скриншот. Копируйте значение после знака “равно” ( = ), но ДО точки с запятой ( ; )

Получаем значение для /settoken

  1. Открываем dev tools на странице выплат
  2. Меняем метод выплаты (например, с киви на карту или наоборот)
  3. Токен будет видно тут: скриншот

:man_technologist: Код бота

Путь: addons/ggram-mod/lua/ggram/bots/gmdbot/_init.lua (не забудьте установить ggram, как написано выше)

👉 Код (кликни сюда)
local bot = require("ggram")("your_bot_token")
require("ggram.polling").start(bot)

function bot.secureCommand(cmd, func)
	return bot.command(cmd, function(ctx)
		if ctx.from.id ~= 123456 then -- СЮДА НУЖНО ВСТАВИТЬ ТВОЙ TELEGRAM ID
			return ctx.reply.text("fak yu")
		end
		return func(ctx)
	end)
end

bot.command("start", function(ctx) ctx.reply.text("hello") end)

-- либа, которая в гмоде сохраняет все в sv.db
local cookie = cookie or require("gmod.cookie")
local HTTP   = HTTP   or require("gmod.globals").HTTP

local BASE_URL = "https://gm-donate.net"

local function request(method, endpoint, parameters_, fSuccess, fError)
	local session = cookie.GetString("gmd_session_cookie")
	assert(session, "Сначала нужно выполнить /setcookie")

	assert(cookie.GetString("gmd_post_token"), "Большинство запросов требуют /settoken")

	HTTP({
		method = method or "GET",
		url = BASE_URL .. endpoint,
		headers = {
			Cookie = "laravel_session=" .. session,
		},
		success = fSuccess,
		failed = fError,
		parameters = parameters_
	})
end

local function get_balance(cb)
	request("GET", "/panel/payouts", nil, function(_, body)
		local bal_str = body:match("fa fa%-rub.-</span>.-([%d,%.]+).*</a>") -- 2,332.65
		local bal_num = bal_str:gsub(",", "")
		cb(true, tonumber(bal_num))
	end, function(err) cb(false, err) end)
end
-- get_balance(print)

local function request_payout(sum, cb)
	request("POST", "/panel/payouts/add", {
		_token = cookie.GetString("gmd_post_token"),
		sum = tostring(sum),
	}, function(_, body)
		local ok = not not body:match("Redirecting to")
		cb(ok, body)
	end, function(err) cb(false, err) end)
end
-- request_payout(13, print)

-- 1 qiwi, 2 card
local function update_payout_method(iMethod, cb)
	request("GET", "/panel/payouts/setPaymentMethod/" .. iMethod, {
		_token = cookie.GetString("gmd_post_token"),
	}, function(code, body)
		if code ~= 200 then -- iMethod = 3 => 404
			cb(false, body)
			return
		end

		if iMethod == 1 then
			local changed = not not body:match("Укажите номер вашего кошелька")
			cb(changed, body)
		elseif iMethod == 2 then
			local changed = not not body:match("Укажите номер банковской карты")
			cb(changed, body)
		end
	end, function(err) cb(false, err) end)
end
-- update_payout_method(2, print)

-- sMethod: qiwi,        card
-- purse:   79134567890, 1111222233334444
local function update_purse(sMethod, purse, cb)
	local param_name = ""
	if sMethod == "qiwi" then
		param_name = "qiwi_phone"
	elseif sMethod == "card" then
		param_name = "card_number"
	end

	local params = {
		_token = cookie.GetString("gmd_post_token"),
		method = sMethod,
	}
	params[param_name] = purse

	request("POST", "/panel/payouts/save-settings", params, function(_, body, headers)
		local redirect = (not not body:match("Redirecting to")) and headers.location
		if redirect then
			local string_PatternSafe = string.PatternSafe or require("gmod.string").PatternSafe
			request("GET", headers.location:gsub( string_PatternSafe(BASE_URL),"" ), nil, function(_, body)
				-- Бывает "Произошла ошибка при смене номера реквизитов, пожалуйста убедитесь что реквизиты указаны верно."
				local success = not not body:match("Вы успешно сменили")
				cb(success, body)
			end, function(err2) cb(false, err2) end)
		else
			cb(false, body)
		end
	end, function(err) cb(false, err) end)
end
-- update_purse("qiwi", "79134567890", print)
-- update_purse("card", "1111222233334444", print)

-- Брать тут: https://file.def.pm/JYOF0cFb.jpg
bot.secureCommand("setcookie", function(ctx)
	local cook = ctx.args()[1]
	if not cook then ctx.reply.text("add cookie string to parameters") return end

	cookie.Set("gmd_session_cookie", cook)
	ctx.reply.text("OK")
end)

-- Брать тут (из post запросов): https://file.def.pm/7d4c86D1.jpg
bot.secureCommand("settoken", function(ctx)
	local token = ctx.args()[1]
	if not token then ctx.reply.text("add token string to parameters") return end

	cookie.Set("gmd_post_token", token)
	ctx.reply.text("OK")
end)

bot.secureCommand("balance", function(ctx)
	get_balance(function(ok, bal)
		local str = ok and ("Баланс: " .. bal) or ("Ошибка запроса: " .. bal)
		ctx.reply.text(str)
	end)
end)

bot.secureCommand("payout", function(ctx)
	local args = ctx.args()
	local method, purse, sum = args[1], args[2], tonumber(args[3])
	if not sum then
		ctx.reply.text("Example: /payout qiwi 79134567890 123.45")
		return
	end

	local iMethod = method == "qiwi" and 1 or method == "card" and 2
	if not iMethod then ctx.reply.text("Указан некорректный метод выплаты") return end

	update_payout_method(iMethod, function(ok1)
		if not ok1 then ctx.reply.text("Ошибка смены метода выплаты") return end

		update_purse(method, purse, function(ok2)
			if not ok2 then ctx.reply.text("Ошибка смены реквизитов") return end

			request_payout(sum, function(ok3)
				ctx.reply.text(ok3 and "Запрос создан" or "Ошибка создания запроса выплаты")
			end)
		end)
	end)
end)

Примечания

  • Код слишком хрупкий, может сломаться в любой момент, поскольку все данные просто парсит из html страницы-ответа, которая в будущем может меняться. Тем не менее, я готов делать фиксы, если это будет востребованно в этой теме
  • Здесь нет проверки статуса выплаты, это сильно усложнило бы код, тем не менее такую функцию можно доделать самостоятельно (после создания выплаты парсите таблицу выплат и проверяете статус раз в пару минут)
  • Код будет работать как на Garry’s Mod, так и на чистом Lua (за пределами гаррисмод). Тестировалось как раз в обычном Lua. Вот здесь я немного писал об этой библиотеке для ботов
  • Мы не принимаем никаких жалоб на то, что у вас украли деньги. Вы сами в ответе за секретные данные и сами отвечаете за их защиту. Если вдруг у вас украдут код сервера, а с ним и сделают выплаты – мы не поможем. Могу лишь порекомендовать не хранить секретные данные в lua файлах или делать выплаты вручную
  • Время от времени куки и токен может потребоваться обновлять. Я не могу точно сказать, насколько часто это нужно будет делать, но полагаю, что не очень часто
1 лайк