РуководстваОпубликовано: 29.10.2026• 0 просмотров

Экспорт счёта API не сходится: сверяем ID запроса, повторы и часовой пояс

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

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

Сначала зафиксируйте три суммы

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

Записывайте строку как request_id, attempt_id, created_at, settled_at, model, input_units, output_units, amount, currency, status и parent_request_id. Если сервис не выдаёт поле, оставьте его пустым и укажите «поле не предоставлено». Не подменяйте отсутствующий идентификатор локальным временем или придуманным значением. Сначала полезно прочитать о границах запросов и оплаты в API-посреднике, а затем добавить правила идентификаторов, повторов и времени из этой статьи.

Разделяйте запрос и попытку повтора

Один клик пользователя может создать одну бизнес-задачу и несколько сетевых попыток. У задачи обычно есть локальный job_id, у каждой отправки — attempt_id, а вышестоящий сервис может вернуть request_id. Не объединяйте эти понятия: вторая попытка той же задачи может завершиться успешно, пока первая уже стоит в очереди и тоже породила расход.

Группируйте в таком порядке: сначала по выданному сервисом request_id, затем по parent_request_id, и только потом по локальному job_id с временным окном. Временное окно является подсказкой, а не доказательством тождественности. Тайм-аут или отмена клиента также не означают автоматически нулевую стоимость. Границы отмены следует проверять вместе с уровнями передачи сигнала в статье отмена генерации и сверка счёта.

Приведите часовые пояса к UTC

Экспорт может показывать UTC, часовой пояс сервиса или настройку аккаунта. Не соединяйте таблицы по строке даты. Сохраните исходное время и его часовой пояс, преобразуйте момент в UTC, а затем вычислите отдельную финансовую дату, например beijing_date.

Например, 2026-10-29 00:05 по Пекину — это 2026-10-28 16:05 UTC. По строкам даты эти записи попали бы в разные дни, хотя момент один. Сервис также может делить расчётный день по собственной границе, поэтому «стоимость запросов за день» и «счёт за день» сравнимы только при одинаковом определении суток. Для запроса через полночь сохраняйте и created_at, и settled_at; время экспорта не заменяет время события.

Минимальная таблица сверки

Сохраните CSV или таблицу базы данных со следующими колонками:

ПолеНазначениеЧто нельзя выводить напрямую
request_idСвязь с деталями сервисаЭто не гарантия единственного списания
attempt_idРазделение попыток отправкиПопытка не обязательно успешна
created_at_utcВход запроса в системуЭто не время расчёта
settled_at_utcМомент проводкиМожет быть пустым или отложенным
amount, currencyСумма и валютаНе включает разницу обменного курса
statusУспех, ошибка, отменаСамо по себе не доказывает оплату
sourceДетали, сводка или платёжИсточники могут обновляться с задержкой

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

Локальный скрипт для поиска повторов

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

function reconcile(rows) {
  if (!Array.isArray(rows)) throw new TypeError('rows must be an array')
  const groups = new Map()
  for (const row of rows) {
    if (!row || typeof row.request_id !== 'string' || !row.request_id) continue
    const amount = Number(row.amount)
    if (!Number.isFinite(amount)) continue
    const group = groups.get(row.request_id) ?? { requestId: row.request_id, rows: [], total: 0 }
    group.rows.push(row)
    group.total += amount
    groups.set(row.request_id, group)
  }
  return [...groups.values()].map(group => ({
    ...group,
    duplicateCandidates: group.rows.length > 1,
    total: Math.round(group.total * 1e8) / 1e8,
  }))
}

const sample = [
  { request_id: 'r-100', attempt_id: 'a-1', amount: '0.012', status: 'timeout' },
  { request_id: 'r-100', attempt_id: 'a-2', amount: '0.012', status: 'succeeded' },
  { request_id: 'r-101', attempt_id: 'a-3', amount: '0.004', status: 'succeeded' },
]
console.log(reconcile(sample))

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

Разложите расхождение баланса по источникам

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

конечный баланс = начальный баланс + пополнения - возвраты - стоимость запросов + изменение бонусов - комиссии

Это способ организации сверки, а не универсальное правило конкретной площадки. Если позиция отсутствует, оставьте разницу «не объяснена» и сохраните время экспорта и фильтры. Когда одна задача встречается дважды, выясните, является ли одна строка резервированием, а другая окончательным расчётом, или это две отдельные сетевые попытки. Совпадение сумм само по себе не разрешает объединение. Для возврата храните отдельно уплаченную часть, бонус, использованную сумму и комиссию; полезна памятка по доказательствам для возврата баланса.

Сохраните доказательства и сформулируйте запрос

Храните исходный файл, условия фильтра, время экспорта, обезличенный идентификатор аккаунта и описание часового пояса. В поддержку отправляйте только необходимый request_id, сумму, валюту, время в UTC и статус. Не прикладывайте API Key, полный промпт или конфиденциальный ответ. В рабочую таблицу добавьте колонки «текст сервиса», «локальный вывод» и «нужно подтвердить», чтобы гипотеза не стала утверждением.

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

После исправления повторите проверку на новом безопасном локальном сценарии, который можно отменить. Не создавайте реальный платный запрос ради «тестовой строки» и не переписывайте исходный экспорт, чтобы свести итог. Разницу можно пометить объяснённой только после проверки идентификаторов, временной шкалы, связи повторов, валюты и движения баланса.

Опубликовано: 29 октября 2026 г.
最后更新: 29.10.2026

Похожие статьи

Руководства

Длинный ID из API изменился во фронтенде? Точность JavaScript и передача строк

Изменились последние цифры ID, поиск вернул 404 или номера в счёте слились? Проверьте текст JSON, разбор, хранение и повторную отправку; узнайте, почему String и BigInt иногда уже не помогут, и проверьте передачу строковых ID на локальных примерах.

Руководства

Как считать стабильность API: исходные запросы, повторы и конечная успешность

Успех после повтора нельзя считать новым независимым успехом. Статья разделяет request_id, попытки и конечные состояния, объясняет границы 429, 503, тайм-аутов и идемпотентности, а локальный скрипт считает конечную успешность и усиление повторами.

Руководства

API вернул 202 без результата: состояния асинхронных заданий, опрос и повторная отправка

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

Отказ от ответственности

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

© 2026 Выбор API. All rights reserved.