При недоплате нельзя автоматически выдавать заказ, а при переплате нельзя автоматически отправлять возврат. Сначала подтвердите сеть, настоящий контракт токена, адрес получателя, статус и сумму транзакции. Затем примените заранее записанное правило и оформите один однозначный результат.

В GramPayBot ожидается точная сумма. Меньший перевод классифицируется как частичный, больший — как переплата; ни один из них незаметно не становится обычным оплаченным инвойсом.

Таблица решений

Проверенный результат Статус для решения Типичное действие
Получена точная ожидаемая сумма Можно штатно сопоставить после подтверждения Исполнить после статуса paid
Получено меньше Недоплата / частичная оплата Зафиксировать разницу и дать инструкцию
Получено больше Переплата Решить, принять ли, зачесть или вернуть излишек
С инвойсом связаны несколько переводов Неоднозначная ситуация Проверить каждый хеш вручную
Неверны токен, сеть или получатель Это не оплата данного инвойса Перейти к сценарию ошибки маршрута

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

BTCPay Server также отделяет частично оплаченные и переплаченные счета от обычного settled-инвойса. В традиционных платежах Stripe отдельно учитывает остаток и переплату. Это не заменяет правила вашего бизнеса, но показывает, зачем исключениям нужны собственные состояния.

Почему возникает недоплата

  • покупатель округлил сумму вместо полного копирования;
  • он неправильно понял комиссию кошелька или биржи;
  • отправил тестовую сумму и решил, что система автоматически её прибавит;
  • использовал старую инструкцию или просроченный инвойс;
  • в интеграции неверно обработаны десятичные знаки токена;
  • несколько людей пытались оплатить один заказ;
  • покупатель сознательно удержал часть суммы из-за спора.

Комиссии вывода работают по-разному и меняются. Binance, например, сообщает, что комиссия вывода динамическая и показывается на странице вывода. Поэтому нельзя обещать универсальное «сеть всегда вычитает комиссию из суммы». Покупатель должен проверить финальное превью и убедиться, что получателю придёт точная сумма.

Почему возникает переплата

  • вместо суммы токена скопирована фиатная цена;
  • комиссия прибавлена к сумме получателя, хотя кошелёк списывает её отдельно;
  • инвойс оплачен дважды;
  • после тестового перевода отправлена вся сумма;
  • покупатель пытался компенсировать неопределённость по старому счёту;
  • допущена ошибка в единицах или количестве знаков.

В интерфейсе USDT и USDC отображаются десятичными числами, но on-chain значение хранится в целых минимальных единицах. В официальном примере Circle показана обработка USDC с шестью десятичными знаками. Интеграция должна детерминированно преобразовывать единицы, а не сравнивать приблизительные числа с плавающей точкой.

Сначала проверьте сам перевод

  1. Откройте исходный хеш в обозревателе нужной сети.
  2. Убедитесь, что транзакция успешна и достаточно подтверждена.
  3. Проверьте контракт или mint, а не только тикер USDT/USDC.
  4. Сравните полный адрес получателя с инвойсом.
  5. Возьмите сумму из события token transfer или изменения баланса.
  6. Сравните её со всей точной суммой checkout.
  7. Проверьте, не привязан ли другой перевод к этому инвойсу.
  8. Сопоставьте время блока со сроком действия.

Если контракт неправильный, это не просто недоплата или переплата, а другой актив. Используйте инструкцию проверки контрактов USDT и USDC.

После проверки привяжите каждый принятый хеш ровно к одному инвойсу и заказу. Инструкция по сопоставлению платежей с заказами показывает, как сохранить эту связь без скриншотов и Telegram username.

Точное сопоставление в GramPayBot

GramPayBot заранее фиксирует ожидаемые сеть, токен, получателя и сумму. Текущая сумма на checkout содержит не более четырёх знаков после запятой и может включать идентифицирующий дробный хвост. Поэтому надо отправить всё показанное число — например, 180.0134 USDT, а не округлённые 180 USDT. У USDT или USDC в блокчейне может быть шесть десятичных разрядов базовых единиц, но это не означает, что GramPayBot показывает шестизначный хвост инвойса.

  • точный подтверждённый перевод может оплатить инвойс;
  • меньший классифицируется как partial;
  • больший — как overpaid;
  • несколько подходящих или уже использованный перевод не считаются чистым совпадением.

Обычный matcher не складывает произвольный второй перевод с первым как автоматическую «доплату». Не просите клиента просто отправить остаток на адрес без нового явного сценария.

Сценарий для недоплаты

1. Рассчитайте подтверждённую разницу

недоплата = точная сумма инвойса − подтверждённая полученная сумма

Сохраните оба числа со всеми знаками в единицах токена.

2. Остановите исполнение

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

3. Выберите один вариант

  • принять недоплату вручную как скидку или списание;
  • создать новый отдельный инвойс на остаток;
  • отменить исполнение и вернуть подтверждённую сумму;
  • передать случай в поддержку или compliance.

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

4. Сообщите результат покупателю

Укажите полученную сумму, разницу, принятое решение и ID нового инвойса или возврата. Сообщение «платёж неполный» без следующего шага бесполезно.

Сценарий для переплаты

1. Исключите дубль и чужой перевод

Проверьте, была ли одна транзакция с лишней суммой или две транзакции, и не относится ли один хеш к другому заказу.

2. Отделите сумму инвойса от излишка

переплата = подтверждённая полученная сумма − точная сумма инвойса

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

3. Примените правило

  • принять инвойс вручную и вернуть излишек;
  • зачислить излишек в согласованный клиентский баланс;
  • принять всю сумму как осознанные чаевые или дополнительную покупку;
  • вернуть весь перевод и выставить счёт заново.

Документация Stripe по частичным платежам наглядно показывает, почему остатки и переплаты требуют формальных правил.

4. Отдельно подтвердите адрес возврата

Не отправляйте излишек автоматически на on-chain адрес отправителя. Биржа могла выполнить вывод из общего кошелька, который не зачисляет входящие возвраты конкретному пользователю.

Аутентифицируйте клиента через исходный заказ, запросите адрес в той же сети, подтвердите комиссии и сохраните хеш исходящей транзакции. Возврат — новый перевод, а не отмена старого.

Какие правила определить заранее

  • допустима ли погрешность недоплаты и как она считается;
  • разрешены ли отдельные инвойсы на остаток;
  • минимальный экономически разумный возврат с учётом комиссии;
  • поддерживается ли клиентский кредит;
  • кто согласует ручное принятие и возврат;
  • как обрабатываются дубли;
  • сколько хранится журнал исключений.

Если есть допуск, применяйте его одинаково и не подменяйте им штатное точное сопоставление без явной поддержки интеграцией.

Инструкция покупателю

  1. Открыть актуальный инвойс, а не адрес из старого сообщения.
  2. Выбрать точно указанные токен и сеть.
  3. Скопировать сумму со всеми десятичными знаками.
  4. Проверить, уменьшает ли биржа сумму получателя на комиссию.
  5. Сверить recipient amount на финальном экране.
  6. Отправить один раз и сохранить хеш.
  7. Остановиться и написать продавцу, если уже был тестовый платёж или срок истёк.

Полный процесс описан в статье как оплатить инвойс в USDT или USDC.

Журнал исключения

Сохраните ID инвойса и заказа, ожидаемый маршрут и сумму, все связанные хеши, подтверждённую сумму каждого перевода, разницу, сроки, способ проверки клиента, решение и согласовавшего, а также ссылку на новый инвойс, кредит или возврат.

Это не даёт учесть один перевод дважды и позволяет другому сотруднику воспроизвести решение.

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

Завершит ли второй платёж недоплаченный инвойс автоматически?

Не рассчитывайте на это. Штатный matcher ожидает один точный перевод и не складывает произвольные частичные транзакции. Дождитесь нового инвойса или явной инструкции продавца.

Можно ли округлить сумму checkout?

Нет. Отправляйте полное число: дробные знаки могут участвовать в идентификации инвойса.

Переплаченный инвойс автоматически считается оплаченным?

Нет. Это исключение для ручной проверки.

Возвращать на адрес отправителя?

Не автоматически. Сначала подтвердите клиента и подходящий адрес возврата, особенно если платёж пришёл с биржи.

Настоящий перевод USDT доказывает оплату заказа?

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

Следующий шаг

Создайте отслеживаемую ссылку на оплату

Выставьте счёт в USDT или USDC вручную, отправьте hosted checkout и отслеживайте статус без API.

Ссылки на оплату →