fix payment

This commit is contained in:
javad committed 2026-10-07 13:39:29 +03:30
1 parent 4f7486152c
commit bb3ddd1610
47 files changed
+2137 -51

No files matched your search

+9 -2
View File
@@ -18,11 +18,12 @@
- اعلامیه، فیش و تصمیم تأیید مستقل‌اند. ثبت تصویر یا تأیید یک نفر از دو نفر، پرداخت را نهایی نمی‌کند.
- مبلغ عدد صحیح **ریال** است؛ نمایش حروفی تومان در مرورگر با BigInt انجام می‌شود و مقدار ریال به سرور می‌رود.
- نمایش تاریخ شمسی و انتخاب سه‌قسمتی است. سرور با jdatetime روز/ماه/سال را مستقل از JS بررسی و Gregorian را در DateField ذخیره می‌کند. تاریخ ناقص، غیرواقعی، آینده و خارج از بازه مجاز رد می‌شود.
- شناسه‌ها، شماره‌ها و شبا رشته‌اند؛ صفر ابتدایی حفظ می‌شود. شبا و کارت موجود اعتبارسنجی می‌شوند.
- شماره حساب، کارت و شبا رشته‌اند و صفر ابتدایی آن‌ها حفظ می‌شود. شناسه واریز رشته است اما صفرهای ابتدایی آن پس از محاسبه رقم کنترل حذف می‌شوند؛ تولید، ذخیره و نمایش همین مقدار را استفاده می‌کنند. migration `0006_normalize_deposit_identifiers` شناسه اعلامیه‌ها و نسخه‌های فیش قبلی را هماهنگ می‌کند و snapshot بانکی یا ممیزی تاریخی را تغییر نمی‌دهد. شبا و کارت موجود اعتبارسنجی می‌شوند.
- حساب شناسه‌دار در صدور اعلامیه الزاماً شناسه می‌خواهد. در ثبت فیش، شناسه اعلامیه فقط برای **همان حساب** معتبر است؛ مقصد متفاوت شناسه خودش را لازم دارد.
- حساب فقط فعال در پنل کارشناسان، در زمینه اعلامیه اختصاصی همان مشتری قابل استفاده است؛ در واریز مستقل قابل استفاده نیست. غیرفعال کلی بودن، ثبت جدید را متوقف می‌کند و سوابق را پنهان نمی‌کند.
- snapshot حساب و شناسه اعلامیه حفظ می‌شود؛ ویرایش بانک، شماره تاریخی اعلامیه یا نسخه فیش را تغییر نمی‌دهد.
- فرم صدور و فرم فیش nonce دارند؛ ارسال تکراری همان داده رکورد یا پیامک جدید ایجاد نمی‌کند. استفاده مجدد از nonce برای اطلاعات مالی متفاوت رد می‌شود.
- فرم مشترک فیش مشتری، کارشناس، دسترسی لینک پرداخت و اصلاح فیش، تصویر را با XMLHttpRequest ارسال می‌کند: درصد و حجم واقعی درخواست، زمان سپری‌شده و تخمین زمان باقی‌مانده نمایش داده می‌شوند. پس از پایان انتقال، مرحله بررسی و ثبت سرور جداگانه نمایش داده می‌شود. دکمه ارسال و فیلدها تا پاسخ سرور قفل‌اند؛ در خطا، تصویر و nonce حفظ می‌شوند و امکان تلاش مجدد وجود دارد. درخواست دارای `Accept: application/json` مقصد ادامه را در `redirect_url` یا خطاهای فرم را با وضعیت ۴۲۲ دریافت می‌کند؛ ارسال معمولی بدون JavaScript همچنان از redirect استفاده می‌کند.
- وضعیت اعلامیه از مبلغ نسخه جاری فیش‌های تأییدشده بدون مغایرت مقصد محاسبه می‌شود؛ پرداخت جزئی و باقی‌مانده نمایش داده می‌شوند.
## تنظیمات ضروری پیش از استفاده مالی واقعی
@@ -75,7 +76,13 @@
`recipient_name`, `company_name`, `notice_number`, `receipt_number`, `amount_rial`, `invoice_number`, `payment_link`
صف فعلی `NotificationJob` و worker `process_notifications` به کار می‌روند. اعلامیه به معنی صف‌شدن پیامک است؛ دریافت پیامک نیازمند اجرای worker و تنظیم provider است. وضعیت ارسال و دلیوری مستقل از وضعیت مالی است. متن و نسخه الگو در اولین تلاش موفق آماده‌سازی snapshot می‌شود؛ retry همان متن را حفظ می‌کند. تلاش ناموفقِ آماده‌سازی قالب یا ارتباط provider نیز تاریخچه دارد. URL پیامک ورود کامل مشتری را لازم دارد.
صف فعلی `NotificationJob` و worker `process_notifications` به کار می‌روند. اعلامیه به معنی صف‌شدن پیامک است؛ دریافت پیامک نیازمند اجرای worker و تنظیم provider است. وضعیت ارسال و دلیوری مستقل از وضعیت مالی است. متن و نسخه الگو در اولین تلاش موفق آماده‌سازی snapshot می‌شود؛ retry همان متن را حفظ می‌کند. تلاش ناموفقِ آماده‌سازی قالب یا ارتباط provider نیز تاریخچه دارد. URL پیامک لینک موقت مستقل از ورود کامل مشتری است.
در جزئیات اعلامیه کارشناسان، «ارسال مجدد پیامک اعلامیه واریز» از مسیر POST `notices/<uuid>/resend-sms/` یک job و `PaymentNotification` مستقل می‌سازد؛ ارسال‌های قبلی و نتیجه دریافت آن‌ها بازنویسی نمی‌شوند. کلید UUID فرم درخواست تکراری را یکسان می‌کند و قفل مشتری سپس اعلامیه، درخواست‌های همزمان را هماهنگ می‌کند. تا پایان job در صف/پردازش/تلاش خودکار، درخواست جدید ثبت نمی‌شود. مجوز ایجاد در دامنه واحد و دسترسی به اعلامیه، فعال بودن مشتری و لغو/حذف نشدن اعلامیه بررسی می‌شوند؛ رویداد `NOTICE_SMS_RESEND_REQUESTED` ممیزی می‌شود. worker همان handler و قالب‌های فعلی را استفاده می‌کند و برای هر ارسال مجدد لینک پرداخت تازه می‌سازد.
سوابق، زمان درخواست و ارسال، درخواست‌کننده، متن آماده‌شده، تمام تلاش‌های ارسال با خطا و شناسه و کد provider، وضعیت دریافت، شرح/کد و زمان آخرین استعلام و استعلام بعدی را نمایش می‌دهند. `SENT` فقط پذیرش سرویس است؛ رسیدن به گوشی نیاز به نتیجه قطعی دلیوری دارد. پاسخ‌های غیرقطعی یا پایان پایش بدون تأیید دریافت، صریحاً غیرقطعی نمایش داده می‌شوند. سوابق با تازه‌سازی صفحه به‌روز می‌شوند.
میز پرداخت کارشناسان به‌طور پیش‌فرض فیش‌های «نیازمند اقدام من» را نمایش می‌دهد؛ `?tab=receipts` همه فیش‌های مجاز و `?tab=notices` اعلامیه‌ها را انتخاب می‌کند. صفحه‌بندی ۲۵تایی با شمارنده صفحه و محدوده نتایج، تب و فیلترها را نگه می‌دارد.
در آزمون‌ها provider mock شده است؛ پیامک واقعی برای مشتری ارسال نشده و worker روی صف واقعی توسعه اجرا نشده است.
+6
View File
@@ -23,6 +23,12 @@
شماره حساب، شبا و سایر اطلاعات از snapshot اعلامیه نمایش داده می‌شوند. شناسه واریز و تذکر آن قرمز است. امضای مسیر بدون ورود از `SiteBranding.developer_credit_text` خوانده می‌شود.
## کپی اطلاعات و اشتراک صفحه
شناسه واریز در تولید، ذخیره، نمایش و متن کپی بدون صفرهای ابتدایی است؛ رقم کنترل و صفرهای داخلی حفظ می‌شوند. در صورت وجود شناسه، متن کپی کامل صریحاً می‌گوید وارد کردن شناسه واریز هنگام پرداخت الزامی و اجباری است.
زیر دکمه کپی کامل در جزئیات واریز، «کپی لینک کوتاه این صفحه برای ارسال به دیگران» قرار دارد. درخواست POST با CSRF و کنترل مالکیت/محدوده اجرا می‌شود. مشتری واردشده می‌تواند لینک موقت همین اعلامیه را بسازد؛ پیامکی ارسال نمی‌شود. بازدیدکننده ناشناس فقط لینک معتبر دریافت‌شده را کپی می‌کند؛ انقضا یا محدوده دسترسی تمدید نمی‌شود. برای کپی پس از redirect، توکن در نشست سمت سرور نگهداری می‌شود؛ مدل لینک همچنان فقط هش توکن را ذخیره می‌کند. نشست‌های قدیمی فاقد توکن باید لینک دریافتی را دوباره باز کنند. Clipboard ناموجود، کپی دستی قابل انتخاب را نمایش می‌دهد.
## تست دائمی
از WSL و در ریشه پروژه اجرا کنید:
+41
View File
@@ -0,0 +1,41 @@
# اطلاع‌رسانی فیش مشتری
پس از ثبت موفق فیش مشتری، اپ `payments` اعلان‌ها را در صف `NotificationJob` قرار می‌دهد. ثبت از حساب مشتری و لینک کوتاه پرداخت هر دو پشتیبانی می‌شوند. فیشی که کارشناس به نمایندگی از مشتری ثبت می‌کند اعلان ندارد. تصویر هر نسخه مستقل است؛ گزینه «اطلاع‌رسانی فیش اصلاح‌شده مشتری» تعیین می‌کند نسخه‌های اصلاحی نیز اعلان داشته باشند.
## راه‌اندازی
۱. migration `payments.0007_receipt_alerts` را اجرا کنید. هر دو کانال در شروع خاموش‌اند و بدون تنظیمات هیچ اعلانی ساخته نمی‌شود.
۲. در Django Admin، بخش پرداخت‌ها، «تنظیمات اطلاع‌رسانی فیش مشتری» را باز کنید:
`/x5admin/payments/paymentreceiptalertconfiguration/`
- بله: توکن ربات، شناسه گروه و متن همراه تصویر را وارد و کانال را فعال کنید. ربات باید مجوز ارسال به گروه داشته باشد. این توکن از `BALE_BOT_TOKEN` مربوط به تیکت‌ها مستقل است.
- پیامک: کانال را فعال کنید، متن پیامک را تنظیم کنید و در جدول همان صفحه مدیران دریافت‌کننده را با نام و شماره موبایل اضافه کنید. هر مدیر گزینه فعال مستقل دارد. شماره‌ها با قالب موبایل فعلی پروژه یکسان‌سازی می‌شوند و شماره تکراری پذیرفته نمی‌شود. درگاه پیامک فعلی پروژه استفاده می‌شود.
- برای حفظ توکن ذخیره‌شده، فیلد توکن را خالی بگذارید. برای تعویض، توکن تازه وارد کنید. برای حذف، ابتدا بله را خاموش و گزینه پاک‌کردن توکن را انتخاب کنید. مقدار توکن در HTML فرم و ممیزی پرداخت درج نمی‌شود؛ توکن در دیتابیس تنظیمات نگهداری می‌شود و دسترسی دیتابیس/نسخه پشتیبان باید محدود باشد.
۳. Worker موجود `process_notifications` باید با نسخه جدید کد اجرا شود و به storage تصاویر فیش دسترسی داشته باشد. در محیط تولید از محیط مجازی همان سرور استفاده کنید. اجرای Worker قبلی را پس از انتشار بازراه‌اندازی کنید؛ Worker جدید جداگانه لازم نیست.
مجوز مدیریت تنظیمات و مدیران: `payments.manage_receipt_alerts`. مدیرعامل یا superuser فعال با حساب STAFF نیز مطابق سیاست فعلی پرداخت دسترسی دارد.
## متن و سابقه
تگ‌های متن: `{amount_rial}` (ریال)، `{customer_name}`، `{customer_mobile}`، `{received_at}` (تاریخ و ساعت شمسی)، `{paid_date}` (تاریخ واریز شمسی)، `{receipt_number}`، `{revision_version}`، `{receipt_link}` و `{manager_name}`. نام خالی مشتری با «نام ثبت نشده» جایگزین می‌شود. قالب‌بندی اضافی یا دسترسی به ویژگی‌های شیء در تگ‌ها پذیرفته نمی‌شود.
بله فایل خصوصی را مستقیماً همراه متن دریافت می‌کند؛ آدرس عمومی تصویر ایجاد نمی‌شود. لینک پیش‌فرض متن به جزئیات محافظت‌شده کارشناسان است. PNG/JPEG به‌صورت تصویر و دیگر فرمت‌های مجاز فیش به‌صورت فایل تصویری ارسال می‌شوند.
صفحه سوابق:
`/x5admin/payments/paymentreceiptalert/`
برای هر نسخه و مقصد، سابقه مستقل شامل گیرنده، متن، کانال، تعداد تلاش، خطای آخر و نتیجه دریافت پیامک وجود دارد. پذیرش سرویس پیامک با رسیدن به گوشی متفاوت است؛ نتیجه دریافت از استعلام Worker و قابلیت درگاه می‌آید. سوابق فقط خواندنی‌اند.
## رفتار هنگام خطا و تغییر تنظیمات
- ثبت فیش هیچ درخواست شبکه‌ای برای اعلان انجام نمی‌دهد. ساخت صف در همان تراکنش است؛ rollback ثبت فیش، صف آن را نیز حذف می‌کند. nonce و کلید یکتای نسخه/کانال/گیرنده جلوی ساخت اعلان تکراری را می‌گیرند.
- خرابی صف یک مقصد با savepoint جدا مدیریت می‌شود؛ مقصدهای دیگر و ثبت فیش ادامه پیدا می‌کنند. اگر خواندن تنظیمات یا ساخت صف ممکن نباشد، خطای بدون اطلاعات محرمانه در لاگ ثبت می‌شود؛ چنین خطایی صف قابل تلاش مجدد ایجاد نمی‌کند.
- خطای شبکه/درگاه/فایل در Worker به خطای اعلان تبدیل می‌شود. تلاش مجدد از سیاست محدود فعلی پیامک و بله پیروی می‌کند و ثبت یا بررسی فیش را تغییر نمی‌دهد. خطای یک اعلان پردازش مقصدهای دیگر را متوقف نمی‌کند.
- خاموش‌کردن کانال یا مدیر، یا تغییر شماره/شناسه گروه، اعلان‌های قبلی ارسال‌نشده آن مقصد را لغو می‌کند. توکن جدید برای تلاش‌های بعدی خوانده می‌شود. متن و اطلاعات مشتری/گیرنده مربوط به زمان ثبت نسخه حفظ می‌شوند؛ تغییر متن، پیام‌های جدید را تغییر می‌دهد.
- همانند صف فعلی پروژه، اگر سرویس پیام را بپذیرد ولی پاسخ شبکه گم شود، تلاش بعدی ممکن است ارسال بیرونی را تکرار کند؛ سرویس بیرونی تضمین exactly-once ندارد.
تست‌ها در `tests/test_payment_receipt_alerts.py` تمام ارسال‌ها را mock می‌کنند و به گروه یا موبایل واقعی پیام نمی‌فرستند.