Legan Studio
Все статьи
~ 15 мин чтения

Возвраты и чеки в Telegram-боте

Как организовать возвраты в Telegram-боте: законные сроки, фискальные чеки на возврат, refundStarPayment, СБП-возвраты и UX отказа.

  • Telegram
  • оплата
  • юр.аспекты

Возврат — обязательная часть платёжного процесса в любом коммерческом боте. Закон даёт пользователю широкий набор прав на отказ от покупки, а провайдеры платежей и Telegram — техническую возможность вернуть деньги. Но между правом и фактическим переводом денег обратно лежит цепочка: проверка оснований, обращение в платёжный шлюз, формирование чека «возврат прихода» по 54-ФЗ, корректировка учёта, уведомление пользователя. Если хоть одно звено отвалилось — получаете либо штраф от ФНС, либо чарджбек, либо разгромный отзыв в публичном канале. Разбираем, как корректно настроить возвраты, какие документы выпускать и как это упаковать в UX.

Правовая база возвратов в РФ

Базис — Закон «О защите прав потребителей» (ЗоЗПП), 54-ФЗ о ККТ и Гражданский кодекс. Ключевые статьи:

НормаЧто регулируетДля бота
ст. 25 ЗоЗППВозврат непродовольственного товара надлежащего качества в офлайн-магазине, 14 днейРедко применима к ботам — но если вы курьер или ПВЗ, помнить надо
ст. 26.1 ЗоЗППДистанционная торговля: 7 дней после получения, без объяснения причинБот-каталог с физической доставкой — ваш базовый сценарий
ст. 32 ЗоЗПППраво отказа от услуг в любой момент с оплатой фактически понесённых расходовПодписки, консультации, обучение через бот
ст. 26.1 п. 4 ЗоЗППЦифровой контент: возврат не предусмотрен после получения, если оферта не говорит иноеStars, доступ к контенту, файлы
ст. 18 ЗоЗППВозврат товара ненадлежащего качества: 15 дней — техника, гарантийный срок — прочееБрак цифрового продукта тоже сюда
54-ФЗ ст. 4.7Чек «возврат прихода» обязателен при возврате денег физлицуЛюбой возврат, кроме Stars
ст. 438 ГК РФОплата = акцепт оферты, со всеми её условиямиСильный аргумент в спорах при чёткой оферте

Если оферта молчит про возврат — спор решается в пользу потребителя по общему правилу. Поэтому первое правило: прописывайте порядок возврата в оферте явно, со сроками, способами и исключениями.

Возврат цифровых товаров

Самая мутная зона. По умолчанию ст. 26.1 ЗоЗПП говорит: цифровой контент возврату не подлежит после загрузки/просмотра/активации, если иное не предусмотрено договором. На практике это работает так:

  • Если оферта прямо разрешает возврат цифры в N дней — возвращаете по своим правилам. Хороший пример: Steam с 14-дневным окном и лимитом наигранных часов.
  • Если оферта молчит — пользователь почти всегда отыгрывает дело при претензии в Роспотребнадзор. Суды трактуют тишину против бизнеса.
  • Если оферта запрещает явно, но услуга не оказана — отказ всё равно работает по ст. 32 (отказ от услуги до начала исполнения).
  • Брак цифры (файл не открывается, доступ не выдан, контент не соответствует описанию) — обязан вернуть всегда, по ст. 18.

Практика: ставьте 24–72-часовое окно «холодного возврата» цифрового контента до первой активации. Это снимает 80% претензий и не сильно бьёт по выручке (фактически активируют сразу почти все).

Возврат подписок

Подписка — это длящаяся услуга. По ст. 32 ЗоЗПП пользователь вправе отказаться в любой момент, оплатив фактически понесённые расходы. Применительно к подписке-боту это значит:

  • До начала периода (купил, но активация ещё не наступила) — возврат полной суммы.
  • В середине периода — возврат пропорционально неиспользованным дням. Формула: сумма × (осталось_дней / всего_дней).
  • Период полностью использован — возврат не положен, кроме случая нарушения качества.

Как это работает в коде:

from datetime import datetime, timezone

def calc_refund(order: Order) -> int:
    """Возвращает сумму возврата в копейках."""
    now = datetime.now(timezone.utc)
    if now < order.period_start:
        return order.amount  # ещё не активирована
    if now >= order.period_end:
        return 0
    total_days = (order.period_end - order.period_start).days
    used_days = (now - order.period_start).days
    remaining = total_days - used_days
    return int(order.amount * remaining / total_days)

Если оферта прописывает другую формулу (например, минимальный неснижаемый платёж за месяц подписки) — это допустимо при условии, что условие не противоречит закону и было до акцепта.

Возврат физических товаров через бот-каталог

Это классическая дистанционка по ст. 26.1: 7 дней с момента получения, без объяснения причин. Условия:

  • Товар сохранил товарный вид и потребительские свойства.
  • Есть документ, подтверждающий покупку (для бота — чек ОФД).
  • Не входит в перечень не подлежащих возврату по ПП РФ № 2463 (бельё, парфюмерия в индивидуальной упаковке, ювелирка, бытовая химия и др.).

Если бот не уведомил пользователя письменно о порядке и сроках возврата при доставке (ст. 26.1 п. 3) — окно расширяется до 3 месяцев. Поэтому в момент successful_payment или при отгрузке шлите в чат сообщение со сроками возврата и адресом приёма — с фиксацией факта отправки в БД.

Telegram Stars: refundStarPayment

Stars (XTR) возвращаются через метод refundStarPayment. Особенности:

  • Полный возврат, частичные не поддерживаются.
  • Окно — 21 день с момента платежа.
  • Stars возвращаются как Stars (внутренняя валюта), а не в фиат.
  • Если пользователь уже потратил полученные Stars дальше — вернуть нельзя.
  • Чек по 54-ФЗ не нужен: это не «расчёт» в смысле закона, а возврат внутренней валюты Telegram. В управленческом учёте операцию всё равно отражают.
from aiogram import Bot
from aiogram.exceptions import TelegramBadRequest

async def refund_stars(bot: Bot, user_id: int, charge_id: str) -> bool:
    try:
        await bot.refund_star_payment(
            user_id=user_id,
            telegram_payment_charge_id=charge_id,
        )
        return True
    except TelegramBadRequest as e:
        # CHARGE_ALREADY_REFUNDED, CHARGE_NOT_FOUND, USER_DEACTIVATED и т.д.
        log.warning("stars refund failed: %s", e.message)
        return False

charge_id — это telegram_payment_charge_id из исходного successful_payment. Сохраняйте его при первом приёме денег, без него возврат невозможен.

ЮKassa: refund через API

ЮKassa поддерживает полные и частичные возвраты, и для каждого автоматически выбивает чек коррекции при условии, что в исходном платеже был передан receipt.

import requests
from uuid import uuid4

def yookassa_refund(payment_id: str, amount_rub: str, receipt: dict) -> dict:
    resp = requests.post(
        "https://api.yookassa.ru/v3/refunds",
        auth=(SHOP_ID, SECRET_KEY),
        headers={"Idempotence-Key": str(uuid4())},
        json={
            "amount": {"value": amount_rub, "currency": "RUB"},
            "payment_id": payment_id,
            "description": "Возврат по обращению клиента",
            "receipt": receipt,  # для фискализации возврата
        },
        timeout=10,
    )
    resp.raise_for_status()
    return resp.json()

Idempotence-Key — обязателен. При сетевой ошибке вы повторите тот же запрос с тем же ключом — ЮKassa вернёт исходный результат, не создаст дубль возврата.

В receipt для возврата передаётся та же структура, что и при платеже, но с payment_subject, payment_mode и составом, соответствующим возвращаемой части. Email/телефон в чеке возврата — те же, что в исходном.

Тинькофф, CloudPayments и СБП

ШлюзМетод APIЧастичный возвратЧек коррекцииСрок зачисления
ЮKassaPOST /v3/refundsдаавтоматически при receipt1–10 раб. дней
Тинькофф КассаPOST /v2/Cancelдаавтоматически1–10 раб. дней
CloudPaymentsPOST /payments/refundдачерез отдельный API1–10 раб. дней
СберПэйчерез кабинет или APIдачерез ОФД-партнёра1–5 раб. дней
РобокассаPOST /Merchant/Refundдаавтоматически5–10 раб. дней
СБПчерез банк-эквайердачерез провайдера1–3 банк. дня
Telegram StarsrefundStarPaymentнетне нуженмоментально (Stars)

Деньги физически возвращаются на тот же способ оплаты, которым платили. Это обязательное требование банков и ЦБ — нельзя «вернуть на другую карту» или «выдать промокод вместо возврата», если клиент не согласен письменно.

Архитектура процесса возврата

Хорошо спроектированный возврат — это конечный автомат с чёткими статусами и идемпотентностью на каждом шаге.

PENDING  →  VALIDATED  →  GATEWAY_REQUESTED  →  GATEWAY_CONFIRMED  →  RECEIPT_ISSUED  →  USER_NOTIFIED  →  CLOSED
                ↓                ↓                       ↓
            REJECTED         GATEWAY_FAILED         RECEIPT_FAILED

Шаги:

  1. Запрос пользователя — команда /refund, кнопка в меню заказа или в саппорт-чате. На входе — order_id и причина.
  2. Валидация — оплачено? в окне возврата? товар не использован/не активирован? нет ли уже refund по этому платежу?
  3. Создание refund-записи в БД — со своим idempotency_key (UUID), статусом PENDING, привязкой к payment_id и снятой суммой.
  4. Запрос в шлюз — POST к ЮKassa/Тинькофф/Stars с тем же idempotency_key. Перевод статуса в GATEWAY_REQUESTED.
  5. Webhook о подтверждении — шлюз присылает асинхронный callback. Обновляем статус на GATEWAY_CONFIRMED или GATEWAY_FAILED.
  6. Чек «возврат прихода» — формируется автоматически (если был receipt в платеже) или отдельным вызовом ОФД.
  7. Уведомление пользователю — сообщение в боте со статусом и ETA зачисления.
  8. ЗакрытиеCLOSED, операция уходит в БД для отчётности.

Каждый переход — атомарная транзакция в БД. Webhook должен быть идемпотентным: повторный вызов с тем же event_id не должен задвоить ничего.

Обработка webhook возврата

Пример обработчика webhook ЮKassa для события refund.succeeded:

from fastapi import APIRouter, Request, Header, HTTPException
import hmac, hashlib

router = APIRouter()

@router.post("/webhooks/yookassa")
async def yookassa_webhook(
    request: Request,
    signature: str = Header(alias="Webhook-Signature"),
):
    body = await request.body()
    expected = hmac.new(
        WEBHOOK_SECRET.encode(),
        body,
        hashlib.sha256,
    ).hexdigest()
    if not hmac.compare_digest(expected, signature):
        raise HTTPException(401, "bad signature")

    event = await request.json()
    event_id = event["event"]
    obj = event["object"]

    if event_id == "refund.succeeded":
        refund_id = obj["id"]
        # дедуп по event_id и refund_id
        if await refund_already_processed(refund_id):
            return {"ok": True}

        await mark_refund_confirmed(
            refund_id=refund_id,
            payment_id=obj["payment_id"],
            amount=obj["amount"]["value"],
        )
        await notify_user_refund_done(refund_id)

    return {"ok": True}

Без проверки подписи злоумышленник пришлёт фейковый «возврат прошёл» и спровоцирует двойную выдачу денег по бухгалтерии.

Чек возврата по 54-ФЗ

Закон требует выпускать отдельный чек с признаком расчёта «возврат прихода». Поля чека:

  • Те же позиции, что в исходном чеке, но в составе возвращаемой части.
  • Та же сумма (или меньше при частичном возврате).
  • additional_check_props или специальное поле — ссылка на ФД (фискальный документ) исходного чека.
  • Email/телефон покупателя — те же, что в исходном.
  • Та же СНО (система налогообложения).

Через ЮKassa/Тинькофф с включённой фискализацией всё происходит автоматически — вы передаёте receipt в POST /refunds, провайдер шлёт его в ОФД. Через свою кассу (АТОЛ.Онлайн, ferma.ofd.ru, OFD.ru) — отдельный API-вызов:

# Пример: чек возврата через АТОЛ.Онлайн
import requests, time

def atol_refund_receipt(order: dict, original_fd: str) -> dict:
    payload = {
        "external_id": f"refund_{order['id']}_{int(time.time())}",
        "receipt": {
            "client": {
                "email": order["customer_email"],
            },
            "company": {
                "email": COMPANY_EMAIL,
                "sno": "usn_income",
                "inn": COMPANY_INN,
                "payment_address": "https://t.me/your_bot",
            },
            "items": [{
                "name": item["title"],
                "price": item["price"],
                "quantity": item["qty"],
                "sum": item["price"] * item["qty"],
                "vat": {"type": "none"},
                "payment_method": "full_payment",
                "payment_object": "service",
            } for item in order["items"]],
            "payments": [{
                "type": 1,  # электронные
                "sum": order["refund_amount"],
            }],
            "total": order["refund_amount"],
            "additional_check_props": original_fd,
        },
        "timestamp": time.strftime("%d.%m.%Y %H:%M:%S"),
    }
    resp = requests.post(
        f"{ATOL_BASE}/possystem/v4/{ATOL_GROUP}/sell_refund",
        headers={"Token": atol_token()},
        json=payload,
        timeout=15,
    )
    resp.raise_for_status()
    return resp.json()  # вернёт uuid; реальный ФД прилетит асинхронно

Ответ от АТОЛ — асинхронный: они вернут UUID операции, статус готового чека опрашивается отдельным GET'ом или прилетает на коллбек. Сохраните UUID и привяжите к refund-записи.

При самозанятости (НПД) чека по 54-ФЗ нет — формируется «корректировка» в приложении «Мой налог», уменьшающая оборот соответствующего месяца.

Маркированные товары и Честный знак

Возврат маркированной продукции (одежда, обувь, парфюмерия, БАДы, молочка и т.д.) — отдельная история. В чеке возврата нужно передать код маркировки (DataMatrix) каждой возвращаемой единицы. Шаги:

  1. При продаже код маркировки уходил в ОФД и в систему «Честный знак» (вывод из оборота).
  2. При возврате код возвращается в оборот: формируется отдельный документ в ЭДО или через API ГИС МТ.
  3. Чек возврата содержит тот же код, бот должен его сохранить из исходной транзакции.

Если бот не работает напрямую с ГИС МТ, эту операцию делает учётная система (1С, МойСклад, Контур.Маркет) — но факт возврата надо передать туда из бота через интеграцию.

Бухгалтерский учёт возвратов

Налоговые последствия:

  • УСН «доходы» — доход признаётся «по факту получения». Возврат уменьшает базу периода, в котором сделан возврат (не периода покупки). Если доход и возврат в одном квартале — выходит ноль; если в разных — корректируется база следующего периода.
  • УСН «доходы минус расходы» — аналогично, плюс надо снять с расходов себестоимость возвращённого товара, если она была учтена.
  • ОСН — корректируется выручка, восстанавливается НДС с возвращённой суммы (если был принят к вычету), оформляется счёт-фактура с признаком «возврат».
  • НПД (самозанятость) — корректировка в «Мой налог», уменьшение оборота соответствующего месяца.

Если возвратов больше 5–10% от оборота, это сигнал ФНС присмотреться: либо у вас плохой продукт, либо схема обналички. Храните основания каждого возврата (заявление, переписку, акты) минимум 4 года.

Чарджбеки и споры с банком

Чарджбек — это требование банка-эмитента вернуть деньги по платежу, инициированное держателем карты в обход продавца. Стандартный кейс: клиент написал в банк «не я платил» или «товар не получен». Процесс:

  1. Банк-эмитент шлёт representment в банк-эквайер (вашему провайдеру).
  2. Эквайер передаёт запрос вам (через ЮKassa/Тинькофф) с дедлайном 7–14 дней на ответ.
  3. Вы предоставляете доказательную базу: факт акцепта оферты, логи бота, переписку, факт доставки/активации, чек ОФД.
  4. Эквайер передаёт пакет обратно эмитенту, тот выносит решение.
  5. Решение можно оспорить — pre-arbitration, arbitration, до итогового вердикта Visa/MC/MIR.

В 60–80% обоснованных чарджбеков эмитент встаёт на сторону держателя карты. Поэтому проще решать вопрос мирно: если возврат явно правомерен — верните сами, без чарджбека. Чарджбек оставляет на провайдере «штрафную метку» и при их количестве > 1% от оборота вас могут отключить.

Доказательная база для бота:

  • лог successful_payment с telegram_payment_charge_id;
  • факт акцепта оферты (нажатие кнопки + IP + время);
  • факт активации услуги/отгрузки товара (логи API + трек-номер);
  • переписка пользователя в чате с ботом;
  • чеки ОФД.

Защита от refund-фрода

Возвратами злоупотребляют. Типовые паттерны: «купил → потребил → потребовал возврат», «купил по промокоду → возврат на полную сумму → ещё промокод», серия одинаковых заказов с возвратами для накрутки чего-то. Защита:

  • Лимит N возвратов на пользователя в окне (например, 3 за 90 дней). Дальше — ручная модерация.
  • Ручная модерация для VIP-сумм (например, > 50 000 ₽).
  • Антифрод-паттерны: платёж и возврат в течение часа, серия мелких возвратов, новая учётка с возвратом сразу.
  • Проверка use-pattern: для подписки — сколько раз заходил, открывал ли контент.
  • Возврат строго на тот же способ оплаты — отрезает схемы с обналом.

Но не перегибайте: блокировать законный возврат — нарушение ст. 18, 25, 26.1, 32 ЗоЗПП. Штраф Роспотребнадзора + возврат в принудительном порядке + моральный ущерб.

Бот для саппорта возвратов

В живом проекте 50–80% возвратов — типовые: «не подошло», «передумал», «двойное списание». Их можно автоматизировать:

  • Автомат: если запрос подходит под правила (в окне, нет признаков фрода, сумма < лимита) — возврат проходит мгновенно через API шлюза, чек выбивается, юзер получает уведомление.
  • Полу-автомат: если выходит за пределы — формируется тикет в чат менеджера с предзаполненными полями (заказ, сумма, причина, история клиента). Менеджер решает в 1 клик.
  • Ручной: спорные кейсы (брак, конфликт, претензия) — стандартный саппорт-флоу с эскалацией.

Соотношение должно быть примерно 70/25/5. Если автомата меньше 50% — у вас плохо настроены правила и саппорт перегружен.

UX возврата

Хороший UX возврата сильно повышает доверие к боту и снижает нагрузку на саппорт. Принципы:

  • Возврат — в 1–2 клика из чата с ботом или из карточки заказа.
  • Понятная сумма к возврату сразу, без «расчёт уточним позже».
  • Прогноз срока зачисления: «1–10 рабочих дней на карту, обычно 1–3».
  • Статус возврата в боте в реальном времени: «принят», «в обработке у банка», «зачислен».
  • Уведомление по факту, когда возврат прошёл (по webhook от банка).
  • Опрос причины — короткая форма для аналитики (без обязательности).

Антипаттерны: писать на email и ждать неделю, требовать сканы паспорта, заставлять звонить, повторно подтверждать акцепт. Это и противозаконно (ст. 22 ЗоЗПП — 10 дней на ответ по претензии), и убивает retention.

Метрики и аналитика

Что считать:

  • Refund rate — % возвратов от общего оборота. Норма: 0.5–3% для цифровых, 3–7% для физических, выше 10% — повод для аудита продукта.
  • Средний срок обработки — от запроса до зачисления. Норма для авто: < 5 минут до отправки в шлюз.
  • Доля авто-возвратов vs ручных. Цель: 70%+.
  • Топ причин — короткий enum (не подошло, брак, двойное списание, передумал, другое) + свободный текст.
  • % chargeback — обязан быть < 1% (иначе санкции от банка).

По этим данным легко увидеть, какие SKU/услуги генерят больше всего возвратов, и работать с продуктом.

Юридические нюансы при отказе в возврате

Если оснований для возврата нет — не молчите. По ст. 22 ЗоЗПП у вас 10 дней на письменный ответ на претензию. Структура отказа:

  1. Реквизиты обращения (дата, ID, ФИО заявителя).
  2. Суть требования.
  3. Основание отказа со ссылкой на конкретный пункт оферты и норму закона.
  4. Альтернативное предложение (скидка, замена, частичный возврат — если уместно).
  5. Указание досудебного порядка и реквизиты для претензии.

Без письменного ответа в срок суд автоматически встаёт на сторону потребителя + штраф по ст. 13 ЗоЗПП (50% от присужденного в пользу истца). Поэтому даже отказ нужно оформлять корректно — лучше через бот с фиксацией факта отправки и acknowledgement.

Итого

Возврат в Telegram-боте — это связка «провайдер для самого refund + фискализация для чека возврата + UX для пользователя + аналитика и антифрод». ЮKassa и Тинькофф закрывают и платёж, и фискальный чек коррекции автоматически. Stars возвращаются через refundStarPayment в течение 21 дня, без чека по 54-ФЗ. Частичные возвраты возможны не везде. Закладывайте сценарий возврата в дизайн с самого начала, а не как костыль; не блокируйте законные возвраты — это и нарушение, и репутационный риск; держите долю авто-возвратов выше 70% и долю чарджбеков ниже 1%; храните доказательную базу по каждой операции минимум 4 года. И помните: хорошо отработанный возврат часто превращает раздражённого клиента в лояльного.

Частые вопросы

В каких случаях пользователь имеет право на возврат в Telegram-боте?

Базис — Закон «О защите прав потребителей». Дистанционная торговля физическими товарами (ст. 26.1) — 7 дней без объяснения причин, до 3 месяцев если не уведомили о порядке возврата. Услуги (ст. 32) — отказ в любой момент с оплатой фактически понесённых расходов. Цифровой контент (ст. 26.1 п. 4) — возврат не предусмотрен после получения, если оферта не разрешает явно; при браке — обязателен по ст. 18. Подписки — пропорционально неиспользованному периоду. Если оферта молчит про возврат — спор решается в пользу потребителя. Прописывайте порядок возврата в оферте явно: сроки, способы, исключения, формулу расчёта.

Как технически сделать возврат через ЮKassa в Telegram-боте?

POST на api.yookassa.ru/v3/refunds с Basic-авторизацией (shopId:secret) и обязательным заголовком Idempotence-Key (UUID). В теле — amount, payment_id исходного платежа, описание и блок receipt для фискализации возврата. Поддерживаются полные и частичные возвраты. ЮKassa возвращает refund-объект со статусом, физическое зачисление на карту — 1–10 рабочих дней. Webhook refund.succeeded прилетит асинхронно с подтверждением. При корректно переданном receipt чек коррекции (возврат прихода) выбивается автоматически в ОФД. Тинькофф работает аналогично через POST /v2/Cancel.

Как формировать фискальный чек на возврат по 54-ФЗ?

54-ФЗ ст. 4.7 требует отдельный чек с признаком расчёта «возврат прихода». Состав: те же позиции, что в исходном (или часть при частичном возврате), та же сумма, тот же email/телефон покупателя, та же СНО, ссылка на ФД исходного чека. Через ЮKassa/Тинькофф формируется автоматически при передаче receipt в запросе refund. Через свою кассу (АТОЛ.Онлайн, ferma.ofd.ru) — отдельный API-вызов sell_refund с external_id, реквизитами компании, items, payments и additional_check_props. При самозанятости (НПД) чека нет — корректировка в «Мой налог».

Как вернуть Telegram Stars пользователю?

Метод refundStarPayment(user_id, telegram_payment_charge_id). Возврат только полный, частичные не поддерживаются. Окно — 21 день с момента платежа. Stars возвращаются как Stars (внутренняя валюта), не в фиат. Если пользователь уже потратил полученные Stars дальше — вернуть нельзя, прилетит CHARGE_ALREADY_REFUNDED или аналогичная ошибка. Чек по 54-ФЗ не нужен — это не «расчёт» в смысле закона. Но в управленческом учёте операцию отражают для сверки оборотов с Fragment-выплатами.

Как защититься от чарджбеков и refund-фрода?

Доказательная база: лог successful_payment с charge_id, факт акцепта оферты (нажатие кнопки + IP + время), факт активации/отгрузки, переписка в боте, чеки ОФД. На входящий чарджбек дедлайн 7–14 дней — собираете пакет и отдаёте через провайдера. От фрода: лимит N возвратов на пользователя за окно (3 за 90 дней), ручная модерация для сумм > 50 000 ₽, антифрод-паттерны (платёж и возврат в течение часа), проверка use-pattern, возврат строго на тот же способ оплаты. Но не перегибайте — блокировка законного возврата нарушает ЗоЗПП и приводит к штрафу Роспотребнадзора + 50% штраф по ст. 13.

Как организовать UX возврата в Telegram-боте?

Возврат в 1–2 клика из чата с ботом или карточки заказа. Сразу понятная сумма к возврату без «уточним позже». Прогноз срока зачисления (1–10 рабочих дней на карту, обычно 1–3). Статус возврата в реальном времени: «принят», «в обработке у банка», «зачислен» — по webhook от шлюза. Уведомление по факту зачисления. Короткий опрос причины для аналитики, без обязательности. Антипаттерны: писать на email и ждать неделю, требовать сканы паспорта, повторно подтверждать акцепт. По ст. 22 ЗоЗПП у бизнеса 10 дней на письменный ответ по претензии — превышение даёт автоматический проигрыш в суде.

Какие налоговые последствия у возврата для УСН и ОСН?

УСН «доходы» — возврат уменьшает базу периода, в котором сделан возврат, не периода покупки. Если доход и возврат в одном квартале — выходит ноль; если в разных — корректируется база следующего периода. УСН «доходы минус расходы» — то же плюс снятие с расходов себестоимости, если она была учтена. ОСН — корректировка выручки, восстановление НДС, счёт-фактура с признаком «возврат». НПД (самозанятость) — корректировка в «Мой налог», уменьшение оборота месяца. Если refund rate > 5–10% от оборота, это сигнал ФНС — храните основания каждого возврата (заявления, переписку, акты) минимум 4 года.