Всем привет! Я прошёл сложный путь от создания бота до получения первых платежей, поэтому, как порядочный разработчик, хочу поделить информацией, за которую, я уверен, кто-то кому-то платит большие деньги, а в это время ваши полезные труды пылятся на задворках интернета.
Краткая инструкция
Создаём своего бота BotFather в приложении Telegram (это может сделать любой пользователь, на этом этапе не надо быть программистом).
Прописываем полезную, нужную людям логику бота на вашем языке программирования (здесь надо искать готовые решения или кодить как я).
Вы считаете, что бот готов. Теперь максимально тестируем своего бота сами, потом просим протестировать друзей, потом напоминаем им об этом, правим логику, снова тестируем сами, потом снова друзья. Вот теперь бот готов и протестирован, его можно вывести в люди и тестирование продолжится на них. Вы даже не представляете, что творят люди в боте! Вопросы и варианты выбора надо сделать максимально простыми. Представьте, что вы показываете бота детям в садике. Поможет логирование действий пользователей!
За пару-тройку месяцев использования бота реальными подписчиками вы поправите его ~96 раз. Только спустя пол года, действия пользователей перестают пугать, т.к. теперь вы знаете, что хочет общая масса. Теперь, в идеале, спустя столько времени, можно продавать подписку на дополнительный, улучшенный функционал бота.
Оформляем самозанятость. Это очень легко сделать через Госуслуги. Ставим себе приложение Мой налог. Всё очень просто и понятно. ИП и ООО оформлять тоже не сложно, но тут сами смотрите как лучше именно для вас.
Подключаем платёжную систему. Заходим в BotFather, выбираем через кого будем получать платежи. Вот первая шестёрка финалистов. Я выбрал того, с кем мне было понятнее всего продолжать после поиска в стиле "платежи Телеграм для самозанятого". Не рекламирую, за это сразу летят дизлайки, типа подкупили и т.д. Далее по тексту поймёте кого выбрал.
На данном этапе бот готов, протестирован, Вы самозанятый, подключена платёжная система. Пора продавать платную подписку на плюшки! А как? Я не менеджер по продажам. Решил сделать пресловутое Приведи друга.
И вот к чему это привело..
Инструкция по приёму платежей
Я создал личный кабинет для приёма платежей на сайте. Заполнил все данные для договора и в течении 5 дней заключил его (подписывал через смс). Также выбрал авто отправку чеков в ФНС, за это платим 1,2 % комиссии с каждого перевода. Это освобождает от рутины делать чеки своими руками в приложении Мой налог и отправляет чек покупателю. За каждый платёж тоже комиссия (у каждого своя, писать нельзя, скажу, что до 4%).
Важный момент, если Вы подключаете авто отправку чеков в налоговую, то надо предусмотреть в коде, чтобы у покупателя запрашивался телефон или почта. Остальные нюансы и обработчик опишу в коде.
Скрытый текст
// Должно присутствовать в коде:
// 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 в поле "кто пригласил". Этого достаточно для жёстких иерархических рекурсивных запросов, чтобы получить всё что нужно.
Скрытый текст
// Цепь приглашённых пользователей и расчёт бонуса, исходя из уровня [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
Вы самозанятый
Ваш бот продаётся сам по себе (если он не .. плохой), а вы только смотрите в табличку с поступившими платежами и автоматически рассчитанными бонусами, чтобы порадовать подписчиков бота в пятницу вечером.
Просто попробуйте..