Всем привет! Я прошёл сложный путь от создания бота до получения первых платежей, поэтому, как порядочный разработчик, хочу поделить информацией, за которую, я уверен, кто-то кому-то платит большие деньги, а в это время ваши полезные труды пылятся на задворках интернета.
Краткая инструкция
Создаём своего бота BotFather в приложении Telegram (это может сделать любой пользователь, на этом этапе не надо быть программистом).
Прописываем полезную, нужную людям логику бота на вашем языке программирования (здесь надо искать готовые решения или кодить как я).
Вы считаете, что бот готов. Теперь максимально тестируем своего бота сами, потом просим протестировать друзей, потом напоминаем им об этом, правим логику, снова тестируем сами, потом снова друзья. Вот теперь бот готов и протестирован, его можно вывести в люди и тестирование продолжится на них. Вы даже не представляете, что творят люди в боте! Вопросы и варианты выбора надо сделать максимально простыми. Представьте, что вы показываете бота детям в садике. Поможет логирование действий пользователей!
За пару-тройку месяцев использования бота реальными подписчиками вы поправите его ~96 раз. Только спустя пол года, действия пользователей перестают пугать, т.к. теперь вы знаете, что хочет общая масса. Теперь, в идеале, спустя столько времени, можно продавать подписку на дополнительный, улучшенный функционал бота.
Оформляем самозанятость. Это очень легко сделать через Госуслуги. Ставим себе приложение Мой налог. Всё очень просто и понятно. ИП и ООО оформлять тоже не сложно, но тут сами смотрите как лучше именно для вас.
-
Подключаем платёжную систему. Заходим в BotFather, выбираем через кого будем получать платежи. Вот первая шестёрка финалистов. Я выбрал того, с кем мне было понятнее всего продолжать после поиска в стиле "платежи Телеграм для самозанятого". Не рекламирую, за это сразу летят дизлайки, типа подкупили и т.д. Далее по тексту поймёте кого выбрал.
На данном этапе бот готов, протестирован, Вы самозанятый, подключена платёжная система. Пора продавать платную подписку на плюшки! А как? Я не менеджер по продажам. Решил сделать пресловутое Приведи друга.
И вот к чему это привело..
Инструкция по приёму платежей
Я создал личный кабинет для приёма платежей на сайте. Заполнил все данные для договора и в течении 5 дней заключил его (подписывал через смс). Также выбрал авто отправку чеков в ФНС, за это платим 1,2 % комиссии с каждого перевода. Это освобождает от рутины делать чеки своими руками в приложении Мой налог и отправляет чек покупателю. За каждый платёж тоже комиссия (у каждого своя, писать нельзя, скажу, что до 4%).
Важный момент, если Вы подключаете авто отправку чеков в налоговую, то надо предусмотреть в коде, чтобы у покупателя запрашивался телефон или почта. Остальные нюансы и обработчик опишу в коде.
Java код логики приёма и обработки платежей Java (экономлю Вам нервы и время)
// Должно присутствовать в коде:
// 1. обработчик успешного платежа
} else if (update.hasMessage() && update.getMessage().hasSuccessfulPayment()) {
handler.successfulPaymentHandler(update.getMessage().getSuccessfulPayment());
// 2. проверка
} else if (update.hasPreCheckoutQuery()) {
handler.paymentPreCheckout(update.getPreCheckoutQuery());
/* ВОТ ТАКОЕ РАБОЧЕЕ, ГОТОВОЕ НЕПРОСТО НАЙТИ, ДЕЛЮСЬ */
// Проверка перед платежом.
// AnswerPreCheckoutQuery прям должен быть в коде!
public void paymentPreCheckout(PreCheckoutQuery query) {
AnswerPreCheckoutQuery answer = new AnswerPreCheckoutQuery();
if (query != null && query.getInvoicePayload().startsWith("avandy-news")) {
answer.setOk(true);
answer.setPreCheckoutQueryId(query.getId());
} else {
answer.setOk(false);
answer.setErrorMessage("Попробуйте снова!");
}
try {
messageService.execute(answer);
} catch (TelegramApiException e) {
log.error("paymentPreCheckout error = {}", e.getMessage());
}
}
// Обработчик успешного платежа
// ВАЖНО! в sum учитываются копейки, т.е. 25000 = 250,00 рублей
public void handlePayment(SuccessfulPayment successfulPayment) {
String payload = successfulPayment.getInvoicePayload();
long chatId = Long.parseLong(payload.substring(payload.indexOf("#") + 1));
String currency = successfulPayment.getCurrency();
String providerPaymentChargeId = successfulPayment.getProviderPaymentChargeId();
if (successfulPayment.getInvoicePayload().startsWith("avandy-news")) {
Integer totalAmount = successfulPayment.getTotalAmount(); // здесь 25000
// в базу запишем реальные 250 рублей, а не 25000 копеек
double sum = (double) totalAmount / 100; // Учитываются копейки, т.е. 25000 = 250р.
// Сохранить чек в БД
// сохраняйте String providerPaymentChargeId, так потом проще возврат оформить
paymentsService.save(new Payments(chatId, sum, currency, providerPaymentChargeId));
sendMessage(chatId, "Оплата прошла успешно! " + premiumActivatedText);
} else {
sendMessage(chatId, "Ошибка оплаты, попробуйте снова!");
}
}
// Выставление счёта через Юкассу
public void getInvoice(long chatId, int type) {
String description = "Подписка на получение премиальных возможности бота";
List<LabeledPrice> labeledPrices = new ArrayList<>();
String label = pay1month;
labeledPrices.add(new LabeledPrice(label, type * 100)); // умножаем на 100, чтобы были копейки 00
try {
SendInvoice invoice = getSendInvoice(chatId, description, labeledPrices);
// Отправка счёта
messageService.execute(invoice);
} catch (TelegramApiException e) {
log.error("{}: {} {}", "Ошибка при отправке счёта на оплату", chatId, e.getMessage());
}
}
/* И ВОТ САМЫЙ СОК, СКОЛЬКО Ж Я НАМУЧИЛСЯ С МЕЛОЧАМИ */
// Создание чека/инвоиса на одну услугу
private SendInvoice getSendInvoice(long chatId, String description, List<LabeledPrice> labeledPrices) {
SendInvoice invoice = new SendInvoice();
String label = labeledPrices.get(0).getLabel();
int amount = labeledPrices.get(0).getAmount() / 100;
// Если телефон не сохранён в БД, то запроси его при платеже
// иначе некуда отправлять чек ФНС. Это обязательное требование.
// Можно запрашивать email. Т.е. или email или телефон должны быть,
// если выбрана авто отправка чеков в ФНС и покупателю (фискализация)
// ВАЖНО! А вот здесь уже 25000 != 250р. Дурдом :)
// поэтому предыдущие 25000 делим на 100
String phoneNumber = userService.getPhoneNumber(chatId);
if (phoneNumber == null || phoneNumber.isEmpty()) {
invoice.setNeedPhoneNumber(true);
invoice.setSendPhoneNumberToProvider(true);
}
invoice.setChatId(String.valueOf(chatId));
invoice.setProviderToken(PROVIDER_TOKEN); //Токен получаете после подписания договора
invoice.setTitle("Avandy News");
invoice.setDescription(description);
invoice.setPayload("avandy-news#" + chatId);
invoice.setStartParameter("payment-invoice");
invoice.setCurrency("RUB");
invoice.setPrices(labeledPrices);
// Без этого тоже не пройдёт платёж, т.к. подключена фискализация
JSONObject jsonObject = new JSONObject();
jsonObject.put("receipt",
new JSONObject()
.put("items", new JSONArray().put(
new JSONObject()
.put("description", label)
.put("amount", new JSONObject()
.put("value", amount + ".00") // ВОТ ДОГАДАЙСЯ САМ, ЧТО НАДО ТАК!!
.put("currency", "RUB"))
.put("vat_code", 1) // Это НДС так называется, 1 значит БЕЗ НДС
.put("quantity", 1))));
invoice.setProviderData(jsonObject.toString());
return invoice;
}
Алгоритм действий пользователя:
Пользователь нажимает в боте кнопку, которую сделали Вы, с желаемым периодом подписки;
Телеграм присылает ему сообщение с кнопкой Оплатить (эту кнопку делает Телеграм);
Нажимает Оплатить и переходит на страницу платежа (её мы не программируем), вводит карту, подтверждает платёж;
Получает из бота сообщение, что ему подключена премиум подписка;
Получает официальный чек платежа на телефон, а для нас в приложении Мой налог отобразится чек с суммой и налогом 6% (ФНС даёт скидку для начинающих самозанятых);
-
В личном кабинете также будет отображена сумма покупки, плюс уведомления о платеже на вашу почту и телефон.
Пример:
Создание реферальной системы продаж "Приведи друга"
"Так это же сетевой маркетинг и это плохо!". Как оказывается это прекрасно для таких как я, которые сидят, кодят себе в удовольствие в своём уголке и читают эту статью до этих слов. Я не косметику предлагаю, а абстрактного бота, который что-то делает.
Суть
Я говорю своим друзьям: "Предложите моего бота своим знакомым и когда они купят подписку на год, то 10% получите лично вы за каждую их оплату".
Т.е. позовёт мой друг троих человек, они купят подписку по 2000 р. на год и он получит свои 2000 * 3 человека * 10% = 600р. улыбнётся и забудет, НО.. сидит он на рыбалке себе спокойно, пьёт чай, ага, и тут ему прилетает тысяча рублей, с чего бы.. а с того, что эти трое пригласили в сумме ещё 20 человек, 10 из них купили подписку.
Друзья, которых позвал он это первый уровень, друзья друзей это 2 уровень и так до бесконечности.
Я соорудил такую конструкцию бонусов (кэшбэком их назвал):
за 1 уровень мой друг получает 10% от продаж [я пригласил троих, итого 3 покупателя]
за 2 и 3 уровни он получает 5% [друзья 1 уровня пригласили двадцать пользователей, десять из них о оформили подписку, итого 13 покупателей]
4 и ниже уровни это 1% бонуса (1% сделано чтобы не разориться, выплачивая всем цепочкам бонусы) [итого миллиард покупателей]
Главное чтобы ваши друзья были активны в плане предложения бота другим знакомым, ну и чтобы ваш бот был востребован и как-то облегчал жизнь людям, иначе кто купит подписку? Лучшая картинка, описывающая эту пресловутую схему.
Как десерт это мои страшные, но подробные расчёты по схеме премий [10-5-5-1-1-1-....1], которые показывают чистую прибыль (минус налог, комиссии, выплаты бонусов пользователям) бота при 13 покупках годовой подписки стоимостью в 2000 рублей в 18 298 р. / 26 000 [70,3%].
И это я пригласил только одного Арсика и забыл про это! Только одного человека! Потому бонус = 1% c 4 уровня, чтобы не разориться, выплачивая каждую пятницу в 20:00 ваши бонусы.
Процесс приглашения
В боте в Меню - Инфо я добавил кнопку Пригласить
В эти три ёлочки зашит Ваш уникальный chat_id, который даёт Telegram, но преобразованный, б - безопасность. Ссылка под капотом выглядит так:
"<a href=\"https://t.me/AvandyNewsBot?start=" + chatId + "\"><b>»»»</b></a>"
В итоге когда тот кому вы перешлёте это сообщение перейдёт в бота - в базу данных Postgres запишется ваш уникальный chat_id в поле "кто пригласил". Этого достаточно для жёстких иерархических рекурсивных запросов, чтобы получить всё что нужно.
Пример рекурсивного запроса в Spring Boot
// Цепь приглашённых пользователей и расчёт бонуса, исходя из уровня [1 ур.-10%, 2-3 ур.-5%, >= 4 ур.-1%]
@NamedNativeQuery(
name = "FindReferalls",
query = "with recursive referral_chain as (select *, 0 as level from users where chat_id = ?1" +
" union all" +
" select u.*, r.level + 1 from users u" +
" join referral_chain r on u.referall_id = r.chat_id)" +
" select level," +
" r.chat_id," +
" coalesce(r.user_name, r.first_name) as user_name," +
" sum," +
" case" +
" when (p.sum > 0 and r.level = 1) then p.sum * 0.10" +
" when (p.sum > 0 and r.level in (2, 3)) then p.sum * 0.05" +
" when (p.sum > 0 and r.level >= 4) then p.sum * 0.01" +
" else 0 end as award, " +
" p.currency," +
" r.referall_theme" +
" from referral_chain r " +
" left join payments p on p.chat_id = r.chat_id" +
" where r.chat_id != ?1" +
" order by r.level, r.user_name",
resultSetMapping = "ReferallResultMapping")
Итоги
Сделан Telegram bot
Вы самозанятый
Ваш бот продаётся сам по себе (если он не .. плохой), а вы только смотрите в табличку с поступившими платежами и автоматически рассчитанными бонусами, чтобы порадовать подписчиков бота в пятницу вечером.
Просто попробуйте..
Комментарии (32)
aleksandy
18.07.2024 12:55Итить
Integer totalAmount = successfulPayment.getTotalAmount(); // здесь 25000
// в базу запишем реальные 250 рублей, а не 25000 копеек
double sum = (double) totalAmount / 100; // Учитываются кЕсли деньги считаются в
копейкахминимальном номинале, то типом должен бытьlong
.Деньги и вещественные типы данных никогда не должны пересекаться. Вообще.
mrprogre Автор
18.07.2024 12:55Про long принято, про вещественные не понял.. double и деньги не должны пересекаться?
dtkdtk
18.07.2024 12:55+1Не должны пересекаться, скорее всего, потому, что вычисления вещественных неточные. Если вы сложите 0.1 и 0.2 - получите отнюдь не 0.3, а 0.300000014. Это может казаться нестрашным, но сам факт погрешности при вычисления с деньгами...
На это можно "забить", но я бы, например, так делать не стал.
mrprogre Автор
18.07.2024 12:55да да, про эти приколы дабла я знаю. Спасибо, отличный совет! Теперь буду использовать long! Уже не зря дизлайков нахватал :)
nki
18.07.2024 12:55+1Сдаю ботов в аренду. Платёж настроил для банка, которого нет в списка телеги. По партнёрской программе выплачиваю два первых платежа от приведённого клиента.
mrprogre Автор
18.07.2024 12:55За что дизлайки то ставите? почему -4 за рекламу реклама? что я рекламирую? уже все ссылки на своего бота убрал!
Rafriell
18.07.2024 12:55+3Полезно для саморазвития. Автор - пришли ссылку на бота
EverySeeingEye
18.07.2024 12:55+2Побольше бы таких статей!
mrprogre Автор
18.07.2024 12:55после такой волны негатива Ваш комментарий как глоток свежего воздуха))
crazy_kayaker
18.07.2024 12:55Чуть потыкал бота и заметил, что кнопки не перестают мигать после обработки. Может быть это у меня проблемы, но возможно ты забыл где-то отправлять answer на колбэки
mrprogre Автор
18.07.2024 12:55А на что жали? По идее все кнопки задействованы, после каждой какой-то ответ.
crazy_kayaker
18.07.2024 12:55Еще возник вопрос. А как происходит выплата по реферальной системе? Это как-то автоматизированно в коде или как-то иначе это работает?
mrprogre Автор
18.07.2024 12:55Сделал так. По команде Меню - /cashback показываются все юзеры, которые перешли по приглашению этого человека, их оплаты, если есть, и будущая премия . Как только один из этих юзеров оплатит подписку, то буквально минут через 5-10 пригласивший увидит свою премию в том же разделе /cashback. Вот выплачиваю пока руками сам по пятницам в 20:00 МСК, но таблица с премиями заполняется автоматически. Т.е. мне сделать только 1 селект и всё! Также надо с НДФЛ разобраться, в ФНС письмо написал. По идее надо 13% ещё за человека уплачивать ,если физ лицу премию пуляешь.. но это я ещё уточню и здесь напишу!
Вот как выглядит мой личный кабинет в /cashback
mrprogre Автор
18.07.2024 12:55всё закодировано полностью! сам делаешь чек, сам пуляешь его телеграму, сам обрабатываешь ответ, всё сам, своим кодом :) в этом и сложность такого дела! Я куски кода в статье привел над которыми помучился знатно. Поэтоум многие выбирают готовых ботов и т.д. Я всё сам :)
SuharkovMP
Не если купят, а когда купят...
Вариант "Нет" отсутствует...
А вы с оптимизмом смотрите в будущее.
mrprogre Автор
Оптимизм, к некотором роде, двигатель прогресса. Если всё сразу отрицать, то можно ничего и не сделать. Я понимаю о чём Вы, не факт что много заработаешь. Но я же что-то сделал, чтобы такой шанс вообще появился, понимаете и поделился схемой! Точнее рассказал очевидное, но тем не менее. Нет теперь есть.