Sobes.tech
Middle+

Օգտագործողը սեղմում է 100 ռուբլի վճարման կոճակը, POST հարցում է ուղարկվում սերվերին, բայց պատասխան չի գալիս — timeout. Ինչպես ապահովել, որ կրկնակի ուղարկումը չպատճառի կրկնակի վճարումներ: Ինչպես է այս խնդիրն լուծվում ֆրոնտենդում և ճարտարապետությունում?

sobes.tech AI

Պատասխան AI-ից

Чтобы избежать двойного списания при повторной отправке запроса оплаты из-за таймаута, применяются следующие подходы:

На фронтенде:

  • После первого нажатия кнопки оплаты блокировать кнопку, чтобы пользователь не мог отправить запрос повторно.
  • Использовать уникальный идентификатор транзакции (например, UUID), который генерируется на клиенте и отправляется на сервер вместе с запросом. При повторной отправке с тем же ID сервер понимает, что это повтор и не создает новую оплату.
  • Показывать пользователю индикатор загрузки и сообщение о том, что запрос обрабатывается.

В архитектуре и на сервере:

  • Идempotency key — сервер сохраняет состояние обработки запроса с данным уникальным ключом. Если приходит повторный запрос с тем же ключом, сервер возвращает тот же результат, не создавая новую операцию.
  • Транзакционность и атомарность операций в базе данных: списание средств и запись транзакции должны быть одной атомарной операцией.

Пример генерации idempotency key на фронтенде (JavaScript):

function generateIdempotencyKey() {
  return crypto.randomUUID();
}

const idempotencyKey = generateIdempotencyKey();
fetch('/api/pay', {
  method: 'POST',
  headers: {
    'Content-Type': 'application/json',
    'Idempotency-Key': idempotencyKey
  },
  body: JSON.stringify({ amount: 100 })
});

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