# نکات پیاده‌سازی — تسک ۱۵: ماژول پرداخت

## درگاه‌های واقعی پروژه (از کد Drupal)

### ۱. بانک ملت (Mellat) — پروتکل SOAP
```php
// وب‌سرویس SOAP با متدهای:
// bpPayRequest      → شروع تراکنش
// bpVerifyRequest   → تأیید پرداخت
// bpInquiryRequest  → استعلام وضعیت
// bpSettleRequest   → تسویه
// bpReversalRequest → برگشت تراکنش

// پارامترهای پیکربندی:
terminal_id, username, password
wsdl_endpoint, gate_url
test_mode (boolean)
callback_url, callback_url_test
```

### ۲. SEP (سامان) — درگاه دوم
در `sep_payment/src/Plugin/MyPayment/SepPayment.php` پیاده‌سازی شده.

### پیاده‌سازی در Symfony
```php
interface PaymentGatewayInterface {
    public function pay(array $data): array;    // { success, ref_id, gateway_url }
    public function verify(array $callbackData, int $orderId): array;
    public function refund(array $data): array;
}
```

پیکربندی در `.env`:
```
PAYMENT_GATEWAY=mellat   # mellat | sep
MELLAT_TERMINAL_ID=...
MELLAT_USERNAME=...
MELLAT_PASSWORD=...
MELLAT_TEST_MODE=true
```

## وضعیت پرداخت (از کد واقعی)
```
pending   → بعد از ایجاد پرداخت
received  → بعد از تأیید موفق (نه "paid"!)
failed    → پرداخت ناموفق
```
⚠️ در Drupal status موفق `received` است نه `paid`.

## شرط ایجاد پرداخت
**appointment باید status=`waiting_for_payment` داشته باشد.**
اگر status متفاوت باشد → 400 error.

## قیمت از Config (نه Request)
```php
// مبلغ از پیکربندی خوانده می‌شود، نه از request body!
$amount = $config->get('payment.settings')['price'];
```
→ در `.env` یا config:
```
APPOINTMENT_PRICE=500000
```

## frontend_address
پرداخت دارای `frontend_address` است — URL فرانت برای redirect بعد از پرداخت.
این به representation مرتبط است (سیستم multi-tenant).

## Callback Mellat
```
POST /payment/callback/mellat
  RefId=...
  ResCode=0
  SaleOrderId=...
  SaleReferenceId=...

جریان:
1. ResCode === '0' باشد
2. bpVerifyRequest → اگر موفق نبود → bpInquiryRequest → اگر موفق نبود → bpReversalRequest
3. bpSettleRequest (resCode='0' یا '45' = قبلاً تسویه شده)
4. appointment.status = confirmed
5. payment.status = received
6. payment.ref_id = SaleReferenceId
```

## Idempotency
اگر callback دوبار بیاید، دوبار process نشود:
```php
if ($payment->getStatus() === 'received') {
    return; // قبلاً پردازش شده
}
```

## مجوزها
```
POST   /payment              → احراز هویت‌شده
GET    /payment/{uuid}       → owner یا ROLE_ADMIN یا دکتر مرتبط
GET    /my-payments          → owner
GET/POST callback            → عمومی (درگاه پرداخت)
```
