Middle+
Колдонуучу 100 рублдык төлөм баскычын басат, POST суроо серверге жөнөтүлөт, бирок жооп келбейт — тайм-аут. Экинчи жолу жөнөтүү эки эсе эсепке алууга алып келбеши үчүн кандай кылуу керек? Бул тапшырма фронтендде жана архитектурада кандай чечилет?
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 })
});
Таким образом, даже если запрос повторится из-за таймаута, сервер не спишет деньги дважды.