Обновить

Все потоки

Сначала показывать
Период

Генерация ссылок на оплату через фирменный Tg-бот

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

  • Создавать платёжную ссылку из ЛК Тинькофф неудобно — заказчик не хотел давать доступ к счёту всем менеджерам.

  • Статичный QR-код не подходит — нужно же понимать, за какую бронь пришла оплата.

  • Каких-то других готовых решений без дополнительных комиссий не нашли.

Я показал рабочий пример в моём Tg-боте: там генерируется уникальная ссылка, при переходе по которой клиент платит удобным способом. И не на карту менеджеру, а на расчётный счёт, вполне официально.

На этом варианте и остановились.

Механика работы

  1. Менеджеру даём ссылку на бот с секретным ключом вида t.me/name_of_bot?start=secret_key

  2. Когда менеджер переходит по ней, он автоматически получает право создавать ссылки на оплату для заданного терминала. Это такой очень простой и надёжный вариант авторизации.

  3. Менеджер нажимает "Создать ссылку", указывает номер брони, email клиента (он требуется для отправки чека) и сумму.

  4. Бот через API Тинькофф создаёт ссылку и присылает её менеджеру.

  5. Менеджер пересылает клиенту.

  6. Клиент по ссылке попадает на платёжную страницу Тинькофф, там оплачивает через приложения банков, картой или по СБП.

  7. Менеджеру приходит уведомление, что бронь с таким-то номером оплачена.

Элементарно, работает как часы, заказчик доволен.

Как создаются платёжные ссылки в боте
Как создаются платёжные ссылки в боте

Занятный денежный факт

За создание этого платёжного бота я получил больше денег, чем за всё время существования и разработки своего бота для мониторинга сайтов, из которого эту маленькую функцию и стащил. Но мониторинг не брошу.

Зачем я это написал

Я подумываю сделать решение универсальным сервисом для создания платёжных ссылок. Интересно узнать, сталкивались ли вы с подобной задачей и как решили?

Теги:
+4
Комментарии4

Только ленивый не написал новость о запуске Doom на очередной мультиварке или утюге.

Главный вопрос: кто-то прошел Doom с берданкой на утюге или кофеварке? На каком уровне сложности?

Хочется увидеть walkthrough. Или уже найти что-нибудь иное. Dangerous Dave, Another World или хотя бы Jet Set Willy.

Теги:
+3
Комментарии2

Решил сегодня почитать, что пишут в Ангуляр комьюнити Хабра, и увидел сильно популярный пост с аж 51 лайком и 71 закладкой.

Начал читать и был удивлен примерами. Автор с уверенностью говорит, как писать на Ангуляр грамотно, и при этом приводит плохие практики в качестве примеров. Я дошел до примера с RxJS, который меня немного триггернул.

Не буду разбирать все кейсы указанные в данном посте, покажу лишь самый плохой пример который меня немного тригернул:

Автор условно говорит, что у нас есть плохой пример использования:

this.http.get('/api/data').subscribe((data) =>; {
  this.data = data; // Что если запрос не вернётся?
});

и затем приводит хороший пример с сигналами и RxJs:

readonly data = signal([]);
readonly error = signal(null);

loadData() {
  this.http.get('/api/data').pipe(
    tap(() =>; this.error.set(null)), // Сбрасываем предыдущую ошибку перед загрузкой
    catchError((err) =>; {
      this.error.set('Не удалось загрузить данные');
      return of([]); // Возвращаем пустой массив, чтобы поток не прерывался
    })
  ).subscribe((result) =>; {
    this.data.set(result);
  });
}

я даже не буду указывать на количество антипатернов и плохих практик в данном примере, я просто покажу правильный пример с сигналами и RxJs:

interface State<T = object> {
  data: T[];
  error: string | null;
}

@Component({...})
export class BestRxJs {
  private http = inject(HttpClient);
  private loadDataAction$ = new Subject<void>();

  private state$ = this.loadDataAction$.pipe(
    switchMap(() => 
      this.http.get<State[]>('/api/data').pipe(
        map((result) => ({ data: result, error: null })),
        catchError(() => of({ data: [], error: 'Не удалось загрузить данные' })),
        startWith({ data: [], error: null })
      )
    ),
    shareReplay({ bufferSize: 1, refCount: true })
  );

  readonly private state = toSignal(this.state$, {
    initialValue: { data: [], error: null } 
  });

  readonly protected data = computed(() => this.state().data);
  readonly protected error = computed(() => this.state().error);

  protected loadData(): void {
    this.loadDataAction$.next();
  }
}

Этот пост для новичков, которые, начитавшись популярных статей, могут начать применять вредные практики.

Теги:
+1
Комментарии6

Шаблонный сервис

Я всячески люблю, когда разработка идёт предсказуемо – и многое для этого делаю.  

Давно хотел написать пост о важности шаблонного сервиса, но не было хорошего примера под рукой. И тут мой коллега выложил наш шаблонный сервис на FastAPI, который мы долгое время использовали и развивали.

Так зачем же нужен шаблонный сервис?

Легко ориентироваться в других сервисах. Иногда нужно залезть в сервис коллег, или поддерживаешь несколько сервисов. Никаких проблем – структура везде одинаковая, всё знакомо, не нужно тратить время на раскопки.

Быстрый старт. Стартуете новый сервис? Полчаса – и он готов. Никаких лишних приседаний.

Единые практики. Шаблон определяет, не только структуру, но и то, как мы, например, делаем ретраи, какие у нас зависимости. как устроен circuit breaker, обработка ошибок и т.д.    

Лучшие практики – в одном месте. Если появляется что-то классное, мы добавляем это в шаблон и новые сервисы сразу это наследуют.     

Обсервабилити, логирование, работа с секретами – готово из коробки. И меньше шансов, что кто-то забьёт на логирование до лучших времён»:)    

Онбординг на кошечках. Новый человек сначала изучает шаблонный сервис, понимает подходы, а потом уже ныряет в боевые системы.

Просто экспериментировать. Создал веточку от шаблона – и прикручиваешь свою новую махарайку, не тратя время на базовую структуру.

Унификация линтинга. Конфиги линтеров лежат в шаблоне. Ничего настраивать не нужно, а код-ревью идёт быстрее – обо всём уже однажды договорились и зафиксировали.

Базовый CI/CD. Для шаблонного сервиса существует шаблонный ci/cd – и это очень удобно.

Мы активно использовали шаблонный сервис в микросервисной архитектуре, но и для монолитных решений он тоже отлично зашёл – стартовали с ним несколько проектов.

Понимаю, что это нужно не всем.  Но если вы занимаетесь продуктовой разработкой и играете вдолгую — на мой взгляд, это мастхев.

В общем – заходите, смотрите, ставьте звездочки. И если с чем-то не согласны – пишите в комменты, автор обязательно ответит 🙂

Теги:
+1
Комментарии0