- Add SendSmsMessage class for encapsulating SMS message data. - Create KavehNegarProvider and RanginehProvider classes implementing SmsProviderInterface for sending SMS. - Implement SmsLogRepository and SmsTemplateRepository for managing SMS logs and templates. - Develop SendSmsHandler for handling SMS sending messages. - Create SmsService to manage SMS dispatching and logging. - Add UserProfileController for managing user profiles with CRUD operations. - Implement UserProfile entity and repository for user profile data management. - Update symfony.lock and bootstrap.php for project dependencies and environment setup.
100 lines
3.0 KiB
Markdown
100 lines
3.0 KiB
Markdown
# نکات پیادهسازی — تسک ۱۵: ماژول پرداخت
|
||
|
||
## درگاههای واقعی پروژه (از کد 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 → عمومی (درگاه پرداخت)
|
||
```
|