При недоплате нельзя автоматически выдавать заказ, а при переплате нельзя автоматически отправлять возврат. Сначала подтвердите сеть, настоящий контракт токена, адрес получателя, статус и сумму транзакции. Затем примените заранее записанное правило и оформите один однозначный результат.
В GramPayBot ожидается точная сумма. Меньший перевод классифицируется как частичный, больший — как переплата; ни один из них незаметно не становится обычным оплаченным инвойсом.
Таблица решений
| Проверенный результат | Статус для решения | Типичное действие |
|---|---|---|
| Получена точная ожидаемая сумма | Можно штатно сопоставить после подтверждения | Исполнить после статуса paid |
| Получено меньше | Недоплата / частичная оплата | Зафиксировать разницу и дать инструкцию |
| Получено больше | Переплата | Решить, принять ли, зачесть или вернуть излишек |
| С инвойсом связаны несколько переводов | Неоднозначная ситуация | Проверить каждый хеш вручную |
| Неверны токен, сеть или получатель | Это не оплата данного инвойса | Перейти к сценарию ошибки маршрута |
Если выбрана неправильная сеть, используйте инструкцию по проверке и восстановлению. Если расхождение суммы связано с просроченным или заменяющим инвойсом, сначала пройдите сценарий для неоплаченных, поздних и просроченных инвойсов и только потом просите новый платёж.
BTCPay Server также отделяет частично оплаченные и переплаченные счета от обычного settled-инвойса. В традиционных платежах Stripe отдельно учитывает остаток и переплату. Это не заменяет правила вашего бизнеса, но показывает, зачем исключениям нужны собственные состояния.
Почему возникает недоплата
- покупатель округлил сумму вместо полного копирования;
- он неправильно понял комиссию кошелька или биржи;
- отправил тестовую сумму и решил, что система автоматически её прибавит;
- использовал старую инструкцию или просроченный инвойс;
- в интеграции неверно обработаны десятичные знаки токена;
- несколько людей пытались оплатить один заказ;
- покупатель сознательно удержал часть суммы из-за спора.
Комиссии вывода работают по-разному и меняются. Binance, например, сообщает, что комиссия вывода динамическая и показывается на странице вывода. Поэтому нельзя обещать универсальное «сеть всегда вычитает комиссию из суммы». Покупатель должен проверить финальное превью и убедиться, что получателю придёт точная сумма.
Почему возникает переплата
- вместо суммы токена скопирована фиатная цена;
- комиссия прибавлена к сумме получателя, хотя кошелёк списывает её отдельно;
- инвойс оплачен дважды;
- после тестового перевода отправлена вся сумма;
- покупатель пытался компенсировать неопределённость по старому счёту;
- допущена ошибка в единицах или количестве знаков.
В интерфейсе USDT и USDC отображаются десятичными числами, но on-chain значение хранится в целых минимальных единицах. В официальном примере Circle показана обработка USDC с шестью десятичными знаками. Интеграция должна детерминированно преобразовывать единицы, а не сравнивать приблизительные числа с плавающей точкой.
Сначала проверьте сам перевод
- Откройте исходный хеш в обозревателе нужной сети.
- Убедитесь, что транзакция успешна и достаточно подтверждена.
- Проверьте контракт или mint, а не только тикер USDT/USDC.
- Сравните полный адрес получателя с инвойсом.
- Возьмите сумму из события token transfer или изменения баланса.
- Сравните её со всей точной суммой checkout.
- Проверьте, не привязан ли другой перевод к этому инвойсу.
- Сопоставьте время блока со сроком действия.
Если контракт неправильный, это не просто недоплата или переплата, а другой актив. Используйте инструкцию проверки контрактов 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 адрес отправителя. Биржа могла выполнить вывод из общего кошелька, который не зачисляет входящие возвраты конкретному пользователю.
Аутентифицируйте клиента через исходный заказ, запросите адрес в той же сети, подтвердите комиссии и сохраните хеш исходящей транзакции. Возврат — новый перевод, а не отмена старого.
Какие правила определить заранее
- допустима ли погрешность недоплаты и как она считается;
- разрешены ли отдельные инвойсы на остаток;
- минимальный экономически разумный возврат с учётом комиссии;
- поддерживается ли клиентский кредит;
- кто согласует ручное принятие и возврат;
- как обрабатываются дубли;
- сколько хранится журнал исключений.
Если есть допуск, применяйте его одинаково и не подменяйте им штатное точное сопоставление без явной поддержки интеграцией.
Инструкция покупателю
- Открыть актуальный инвойс, а не адрес из старого сообщения.
- Выбрать точно указанные токен и сеть.
- Скопировать сумму со всеми десятичными знаками.
- Проверить, уменьшает ли биржа сумму получателя на комиссию.
- Сверить recipient amount на финальном экране.
- Отправить один раз и сохранить хеш.
- Остановиться и написать продавцу, если уже был тестовый платёж или срок истёк.
Полный процесс описан в статье как оплатить инвойс в USDT или USDC.
Журнал исключения
Сохраните ID инвойса и заказа, ожидаемый маршрут и сумму, все связанные хеши, подтверждённую сумму каждого перевода, разницу, сроки, способ проверки клиента, решение и согласовавшего, а также ссылку на новый инвойс, кредит или возврат.
Это не даёт учесть один перевод дважды и позволяет другому сотруднику воспроизвести решение.
Частые вопросы
Завершит ли второй платёж недоплаченный инвойс автоматически?
Не рассчитывайте на это. Штатный matcher ожидает один точный перевод и не складывает произвольные частичные транзакции. Дождитесь нового инвойса или явной инструкции продавца.
Можно ли округлить сумму checkout?
Нет. Отправляйте полное число: дробные знаки могут участвовать в идентификации инвойса.
Переплаченный инвойс автоматически считается оплаченным?
Нет. Это исключение для ручной проверки.
Возвращать на адрес отправителя?
Не автоматически. Сначала подтвердите клиента и подходящий адрес возврата, особенно если платёж пришёл с биржи.
Настоящий перевод USDT доказывает оплату заказа?
Нет. Должны совпасть сеть, контракт, получатель, сумма, окно оплаты и сам уникальный хеш; транзакция должна быть подтверждена.
Следующий шаг
Создайте отслеживаемую ссылку на оплату
Выставьте счёт в USDT или USDC вручную, отправьте hosted checkout и отслеживайте статус без API.
Ссылки на оплату →