Библиотека собеса по PHP | вопросы с собеседований
3.15K subscribers
193 photos
6 videos
134 links
Вопросы с собеседований по PHP и ответы на них.

По рекламе: @proglib_adv

Учиться у нас: https://proglib.io/w/9f3affba

Для обратной связи: @proglibrary_feeedback_bot
Download Telegram
✔️ PHP-тест: Идемпотентность, которой нет

Пользователь нажал «Оплатить» один раз. Деньги списались дважды.

📦 Задание

Фича: интеграция с платёжным шлюзом. Платёж создаётся на бэке, пользователь редиректится на страницу шлюза, после оплаты шлюз дёргает webhook. По webhook'у выдаётся доступ к продукту.

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

// src/Payment/WebhookHandler.php
class WebhookHandler
{
public function __construct(
private PaymentRepository $payments,
private OrderRepository $orders,
private AccessService $access,
private Mailer $mailer,
) {}

public function handle(array $payload): void
{
$externalId = $payload['payment_id'];
$status = $payload['status'];

if ($status !== 'success') {
return;
}

$payment = $this->payments->findByExternalId($externalId);

if ($payment === null) {
return;
}

$order = $this->orders->findById($payment->orderId);

if ($order->status === 'paid') {
return;
}

$this->orders->markAsPaid($payment->orderId);
$this->access->grantForOrder($order);
$this->mailer->sendReceipt($order);
}
}

// src/Repository/OrderRepository.php
class OrderRepository
{
public function __construct(private PDO $pdo) {}

public function findById(int $id): Order
{
$stmt = $this->pdo->prepare(
'SELECT * FROM orders WHERE id = ?'
);
$stmt->execute([$id]);
return Order::fromRow($stmt->fetch(PDO::FETCH_ASSOC));
}

public function markAsPaid(int $orderId): void
{
$stmt = $this->pdo->prepare(
'UPDATE orders SET status = ? WHERE id = ?'
);
$stmt->execute(['paid', $orderId]);
}
}


🔹 Задачи

— Объяснить, как именно возникает двойное списание при одном нажатии пользователя
— Исправить WebhookHandler::handle

Ставьте → 🔥 если нравится формат. Если нет → 🌚

💬 Решения пишите в комменты под спойлер — сравним подходы.
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥52👍1