- 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.
3.0 KiB
3.0 KiB
نکات پیادهسازی — تسک ۱۵: ماژول پرداخت
درگاههای واقعی پروژه (از کد Drupal)
۱. بانک ملت (Mellat) — پروتکل SOAP
// وبسرویس 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
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)
// مبلغ از پیکربندی خوانده میشود، نه از 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 نشود:
if ($payment->getStatus() === 'received') {
return; // قبلاً پردازش شده
}
مجوزها
POST /payment → احراز هویتشده
GET /payment/{uuid} → owner یا ROLE_ADMIN یا دکتر مرتبط
GET /my-payments → owner
GET/POST callback → عمومی (درگاه پرداخت)