Москва: проверенные б/у ноутбуки с гарантией и проверкой перед оплатой
+7 906 722-94-45

Главная → Статьи → Платёжные отчёты и сверка операций

Сверка платежей с отчётом провайдера: поиск расхождений

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

Прямой ответ

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

Сопоставление выполняется по идентификатору операции у провайдера:

SELECT p.id, p.provider_id, p.status AS local_status,
       r.provider_status, p.amount_minor, r.amount_minor AS report_amount
FROM payments p
FULL OUTER JOIN provider_report r ON r.provider_id = p.provider_id
WHERE p.provider_id IS NULL          -- есть в отчёте, нет в базе
   OR r.provider_id IS NULL          -- есть в базе, нет в отчёте
   OR p.status <> r.provider_status  -- расхождение статуса
   OR p.amount_minor <> r.amount_minor;

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

import csv, httpx

with httpx.stream("GET", f"{API}/v1/reports/{report_id}/download",
                  auth=(SHOP_ID, SECRET_KEY)) as resp:
    rows = list(csv.DictReader(resp.iter_lines()))
Тип расхождения Причина Действие
Есть в отчёте, нет в базе Пропущено уведомление Создать запись, уточнить статус
Есть в базе, нет в отчёте Платёж вне периода отчёта либо ошибка Проверить период и идентификатор
Расхождение статуса Уведомление не обработано Обновить статус по отчёту
Расхождение суммы Ошибка формирования либо возврат Разбор операции
Возврат в отчёте, нет в базе Возврат выполнен вне сервиса Учесть возврат

Сверка выполняется за период, поэтому граница периода определяется явно: операция на границе попадает в один из двух периодов, и двойной учёт исключается фильтром по дате.

Классификация расхождений и порядок разбора

Не каждое расхождение означает ошибку. Четыре категории требуют разного действия.

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

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

Операция вне сервиса. Возврат либо отмена выполнены через панель провайдера, поэтому в сервисе отсутствуют. Учёт дополняется по отчёту.

Фактическая ошибка. Двойное списание, неверная сумма, отсутствие платежа при фактическом списании. Требует возврата либо исправления.

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

Отдельный вопрос — полнота отчёта. Отчёт провайдера формируется с задержкой, поэтому сверка за текущий день выполняется после завершения формирования. Проверка числа операций в отчёте с ожидаемым числом выявляет неполный отчёт.

Сверка сумм выполняется по агрегатам, а не только по отдельным операциям:

SELECT COUNT(*) AS cnt, SUM(amount_minor) AS total
FROM payments
WHERE status = 'succeeded' AND created_at >= $1 AND created_at < $2;

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

Практика: организация сверки платежей

1. Загружайте отчёт в отдельную таблицу. Формат отчёта отличается от схемы платежей, поэтому прямое сравнение невозможно.

2. Сопоставляйте по идентификатору провайдера. Внутренний идентификатор отсутствует в отчёте, поэтому используется идентификатор операции.

3. Фиксируйте границу периода явно. Операция на границе периода учитывается один раз.

4. Проверяйте полноту отчёта. Число операций в отчёте сравнивается с ожидаемым, иначе неполный отчёт даёт ложные расхождения.

5. Классифицируйте расхождения. Автоматическое исправление применяется только к категориям с однозначным действием.

6. Сверяйте агрегаты и отдельные операции. Совпадение итогов не означает совпадения состава.

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

8. Сохраняйте результат сверки. История сверки показывает динамику расхождений и момент появления проблемы.

Рекомендации:

  1. Не исправляйте расхождения автоматически без категории. Обновление статуса по отчёту допустимо, изменение суммы — нет.
  2. Различайте сверку и обработку уведомлений. Сверка выявляет пропущенные обновления, но не заменяет обработку; о приёме уведомлений — в статье про платёжные вебхуки.
  3. Учитывайте валюту при сопоставлении сумм. Операции в разных валютах не суммируются без пересчёта.
  4. Проверяйте комиссию провайдера отдельно. Комиссия не входит в сумму платежа, поэтому сверка сумм без учёта комиссии даёт расхождение.
  5. Документируйте причину каждого типа расхождения. Категория определяет действие, поэтому классификация фиксируется вместе с процедурой сверки.

Практический сценарий: расхождение итоговой суммы при совпадении числа операций

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

  1. Диагностика. Число операций в отчёте и в базе совпало, итоговая сумма различалась. Построчное сопоставление выявило три операции с расхождением суммы: две в большую сторону в базе, одну в меньшую.
  2. Причина. Сумма в базе сохранялась до применения скидки провайдера, а отчёт содержал фактически списанную сумму. Одновременное отклонение одного платежа в базе при фактическом списании у провайдера компенсировало часть расхождения.
  3. Действия. (а) Добавили построчное сопоставление сумм, а не только сравнение агрегатов; (б) сохранили фактическую сумму из ответа провайдера отдельно от суммы заказа; (в) обновили статус отклонённого платежа по отчёту и разобрали причину пропуска уведомления; (г) добавили проверку расхождения сумм по каждой операции в ежедневную сверку; (д) выполнили возврат по операции, списанной у провайдера при отклонённом статусе в базе.
  4. Результат. Расхождение суммы обнаруживается построчно, а компенсирующие ошибки не скрываются совпадением агрегатов.

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

FAQ

Как часто выполнять сверку? Ежедневно за завершённый период. Отчёт провайдера формируется с задержкой, поэтому сверка за текущий день выполняется после завершения формирования.

Можно ли автоматически исправлять расхождения? Обновление статуса по отчёту допустимо при однозначной категории. Изменение суммы требует разбора операции.

Что делать при операции в отчёте, отсутствующей в базе? Проверить, не относится ли операция к соседнему периоду, затем создать запись и уточнить статус у провайдера.

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

Источники: Stripe reports, PostgreSQL aggregate functions, Python csv — ссылки в шапке.