Middle+
Foydalanuvchi 100 rubllik to'lov tugmasini bosadi, POST so'rovi serverga yuboriladi, lekin javob kelmayapti — timeout. Qayta yuborish ikki marta to'lov qilishga olib kelmasligi uchun qanday qilish mumkin? Bu vazifa frontend va arxitekturada qanday hal qilinadi?
sobes.tech AI
AIdan javob
Чтобы избежать двойного списания при повторной отправке запроса оплаты из-за таймаута, применяются следующие подходы:
На фронтенде:
- После первого нажатия кнопки оплаты блокировать кнопку, чтобы пользователь не мог отправить запрос повторно.
- Использовать уникальный идентификатор транзакции (например, 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 })
});
Таким образом, даже если запрос повторится из-за таймаута, сервер не спишет деньги дважды.