5 changed files with 381 additions and 41 deletions
-
208apps/transaction/doc.py
-
25apps/transaction/migrations/0004_transactionparticipant_payment_method.py
-
26apps/transaction/migrations/0005_alter_transactionparticipant_payment_method.py
-
8apps/transaction/models.py
-
155apps/transaction/views.py
@ -1,3 +1,7 @@ |
|||||
|
from drf_yasg.utils import swagger_auto_schema |
||||
|
from drf_yasg import openapi |
||||
|
from rest_framework import status |
||||
|
|
||||
def doc_upload_transaction_receipts(): |
def doc_upload_transaction_receipts(): |
||||
return """ |
return """ |
||||
# 🐈 Scenario |
# 🐈 Scenario |
||||
@ -428,11 +432,19 @@ POST /api/transactions/<slug>/join/ |
|||||
|
|
||||
2. **دوره پولی**: |
2. **دوره پولی**: |
||||
- تراکنش با وضعیت 'pending' ایجاد میشود |
- تراکنش با وضعیت 'pending' ایجاد میشود |
||||
- کاربر باید رسید پرداخت خود را آپلود کند |
|
||||
- پس از آپلود رسید، وضعیت به 'waiting_approval' تغییر میکند |
|
||||
- پس از تایید توسط ادمین، وضعیت به 'success' تغییر میکند |
|
||||
|
- سیستم بر اساس موقعیت جغرافیایی کاربر، روش پرداخت مناسب را تعیین میکند |
||||
|
|
||||
|
3. **روش پرداخت (Payment Method)**: |
||||
|
- **Payment_Gateway**: برای کاربران غیر روسی - پرداخت از طریق درگاه پرداخت آنلاین |
||||
|
- **Receipt**: برای کاربران روسی - آپلود رسید پرداخت از طریق واتساپ |
||||
|
|
||||
3. **احراز هویت**: |
|
||||
|
4. **تشخیص موقعیت جغرافیایی**: |
||||
|
- ابتدا از هدر Cloudflare (`CF-IPCountry`) استفاده میشود |
||||
|
- در صورت عدم وجود، از پایگاه داده GeoIP محلی استفاده میشود |
||||
|
- کاربران روسی روش پرداخت Receipt دریافت میکنند |
||||
|
- کاربران سایر کشورها روش پرداخت Payment_Gateway دریافت میکنند |
||||
|
|
||||
|
5. **احراز هویت**: |
||||
- باید توکن احراز هویت را در هدر درخواست ارسال کنید |
- باید توکن احراز هویت را در هدر درخواست ارسال کنید |
||||
|
|
||||
--- |
--- |
||||
@ -445,6 +457,29 @@ POST /api/transactions/<slug>/join/ |
|||||
| `400` | دادههای نامعتبر | |
| `400` | دادههای نامعتبر | |
||||
| `404` | دوره یافت نشد | |
| `404` | دوره یافت نشد | |
||||
|
|
||||
|
### ساختار پاسخ: |
||||
|
| کلید | نوع داده | توضیحات | |
||||
|
|---------------------|-----------|----------------------------------------------------------| |
||||
|
| `message` | String | پیام موفقیتآمیز | |
||||
|
| `transaction_id` | Integer | شناسه تراکنش ایجاد شده | |
||||
|
| `payment_method` | String | روش پرداخت (Payment_Gateway یا Receipt) | |
||||
|
| `payment_link` | String | لینک پرداخت (فقط برای Payment_Gateway) | |
||||
|
| `participant_infos` | Array | لیست اطلاعات شرکتکنندگان | |
||||
|
|
||||
|
--- |
||||
|
|
||||
|
## 💳 روشهای پرداخت: |
||||
|
|
||||
|
### Payment_Gateway (درگاه پرداخت): |
||||
|
- **کاربران**: غیر روسی |
||||
|
- **اقدام کاربر**: کلیک روی `payment_link` و پرداخت آنلاین |
||||
|
- **فرآیند**: پرداخت مستقیم از طریق درگاه پرداخت |
||||
|
|
||||
|
### Receipt (رسید پرداخت): |
||||
|
- **کاربران**: روسی |
||||
|
- **اقدام کاربر**: آپلود رسید پرداخت از طریق واتساپ |
||||
|
- **فرآیند**: آپلود رسید → بررسی توسط ادمین → تایید پرداخت |
||||
|
|
||||
--- |
--- |
||||
|
|
||||
## 📄 نمونه درخواست (JSON Body): |
## 📄 نمونه درخواست (JSON Body): |
||||
@ -465,12 +500,14 @@ POST /api/transactions/<slug>/join/ |
|||||
|
|
||||
--- |
--- |
||||
|
|
||||
## 📄 نمونه پاسخ موفقیتآمیز (دوره رایگان): |
|
||||
|
## 📄 نمونه پاسخ (دوره رایگان): |
||||
|
|
||||
```json |
```json |
||||
{ |
{ |
||||
"message": "Transaction Participant created successfully.", |
"message": "Transaction Participant created successfully.", |
||||
"transaction_id": 123, |
"transaction_id": 123, |
||||
|
"payment_method": Free, |
||||
|
"payment_link": null, |
||||
"participant_infos": [ |
"participant_infos": [ |
||||
{ |
{ |
||||
"fullname": "علی رضایی", |
"fullname": "علی رضایی", |
||||
@ -485,25 +522,49 @@ POST /api/transactions/<slug>/join/ |
|||||
|
|
||||
--- |
--- |
||||
|
|
||||
## 📄 نمونه پاسخ موفقیتآمیز (دوره پولی): |
|
||||
|
## 📄 نمونه پاسخ (دوره پولی - Payment_Gateway): |
||||
|
|
||||
```json |
```json |
||||
{ |
{ |
||||
"message": "Transaction Participant created successfully.", |
"message": "Transaction Participant created successfully.", |
||||
"transaction_id": 124, |
|
||||
|
"transaction_id": 374, |
||||
|
"payment_method": "Payment_Gateway", |
||||
|
"payment_link": "https://russia-payment.com/pay/374", |
||||
"participant_infos": [ |
"participant_infos": [ |
||||
{ |
{ |
||||
"fullname": "سارا احمدی", |
|
||||
"email": "[email protected]", |
|
||||
"phone_number": "+989123456789", |
|
||||
"gender": "female", |
|
||||
"birthdate": "1998-03-20" |
|
||||
|
"fullname": "John Doe", |
||||
|
"email": "[email protected]", |
||||
|
"phone_number": "+1234567890", |
||||
|
"gender": "male", |
||||
|
"birthdate": "1990-01-01" |
||||
|
} |
||||
|
] |
||||
|
} |
||||
|
``` |
||||
|
|
||||
|
--- |
||||
|
|
||||
|
## 📄 نمونه پاسخ (دوره پولی - Receipt): |
||||
|
|
||||
|
```json |
||||
|
{ |
||||
|
"message": "Transaction Participant created successfully.", |
||||
|
"transaction_id": 375, |
||||
|
"payment_method": "receipt", |
||||
|
"payment_link": null, |
||||
|
"participant_infos": [ |
||||
|
{ |
||||
|
"fullname": "Иван Иванов", |
||||
|
"email": "[email protected]", |
||||
|
"phone_number": "+71234567890", |
||||
|
"gender": "male", |
||||
|
"birthdate": "1992-05-15" |
||||
} |
} |
||||
] |
] |
||||
} |
} |
||||
``` |
``` |
||||
|
|
||||
توجه: برای دوره پولی، شما باید با استفاده از `transaction_id` بازگشتی، رسید پرداخت خود را از طریق API آپلود رسید آپلود کنید. |
|
||||
|
**نکته**: برای روش پرداخت Receipt، کاربر باید رسید پرداخت خود را از طریق واتساپ آپلود کند. |
||||
|
|
||||
--- |
--- |
||||
|
|
||||
@ -527,3 +588,124 @@ curl -X POST \\ |
|||||
}' |
}' |
||||
``` |
``` |
||||
""" |
""" |
||||
|
|
||||
|
|
||||
|
hadis_list_swagger = swagger_auto_schema( |
||||
|
operation_description=""" |
||||
|
Retrieve a paginated list of Hadis (traditions) for a specific category. |
||||
|
|
||||
|
**Key Features:** |
||||
|
- Returns hadis entries filtered by category ID |
||||
|
- Supports pagination for large datasets |
||||
|
- Translations are automatically provided based on the Accept-Language header |
||||
|
- Each hadis includes its category information, title, narrator, Arabic text, and translation |
||||
|
|
||||
|
**Usage:** |
||||
|
- Use this endpoint to browse hadis within a specific category |
||||
|
- The response includes pagination links (next/previous) for navigation |
||||
|
- Set the Accept-Language header to get translations in your preferred language (en, fa, ar, ur) |
||||
|
- Only active (status=True) hadis are returned |
||||
|
|
||||
|
**Response Structure:** |
||||
|
- `count`: Total number of hadis in the category |
||||
|
- `next`: URL for the next page (null if on last page) |
||||
|
- `previous`: URL for the previous page (null if on first page) |
||||
|
- `results`: Array of hadis objects with full details |
||||
|
""", |
||||
|
operation_summary="List Hadis by Category", |
||||
|
tags=['Hadis'], |
||||
|
manual_parameters=[ |
||||
|
openapi.Parameter( |
||||
|
'category_slug', |
||||
|
openapi.IN_PATH, |
||||
|
description="Unique identifier of the Hadis category. Must be a valid category ID that exists in the system.", |
||||
|
type=openapi.TYPE_STRING, |
||||
|
required=True, |
||||
|
example='-330' |
||||
|
), |
||||
|
openapi.Parameter( |
||||
|
'page', |
||||
|
openapi.IN_QUERY, |
||||
|
description="Page number for pagination. Starts from 1. If not provided, returns the first page.", |
||||
|
type=openapi.TYPE_INTEGER, |
||||
|
required=False, |
||||
|
example=1 |
||||
|
), |
||||
|
openapi.Parameter( |
||||
|
'Accept-Language', |
||||
|
openapi.IN_HEADER, |
||||
|
description="Language code for translations. Supported codes: 'en' (English), 'fa' (Persian), 'ar' (Arabic), 'ur' (Urdu). Defaults to 'en' if not specified.", |
||||
|
type=openapi.TYPE_STRING, |
||||
|
required=False, |
||||
|
default='en', |
||||
|
enum=['en', 'fa', 'ar', 'ur'] |
||||
|
) |
||||
|
], |
||||
|
responses={ |
||||
|
status.HTTP_200_OK: openapi.Response( |
||||
|
description="Successfully retrieved paginated list of hadis for the specified category", |
||||
|
examples={ |
||||
|
"application/json": { |
||||
|
"count": 150, |
||||
|
"next": "http://example.com/api/hadis/category/1/?page=2", |
||||
|
"previous": None, |
||||
|
"results": [ |
||||
|
{ |
||||
|
"id": 1, |
||||
|
"number": 1, |
||||
|
"title": "The Opening", |
||||
|
"title_narrator": "From Abu Hurairah", |
||||
|
"text": "إنما الأعمال بالنيات وإنما لكل امرئ ما نوى", |
||||
|
"translation": "Actions are but by intention, and every man shall have only what he intended", |
||||
|
"category": { |
||||
|
"id": 1, |
||||
|
"title": "Book of Faith", |
||||
|
"slug": "book-of-faith", |
||||
|
"source_type": "hadith", |
||||
|
"sect_type": "sunni" |
||||
|
}, |
||||
|
"status": { |
||||
|
"id": 130, |
||||
|
"title": "Прерванный", |
||||
|
"color": "orange" |
||||
|
}, |
||||
|
"share_link": "http://example.com/hadis/1" |
||||
|
}, |
||||
|
{ |
||||
|
"id": 2, |
||||
|
"number": 2, |
||||
|
"title": "The Second Hadith", |
||||
|
"title_narrator": "From Umar ibn al-Khattab", |
||||
|
"text": "بينما نحن عند رسول الله صلى الله عليه وسلم ذات يوم", |
||||
|
"translation": "While we were sitting with the Messenger of Allah (peace be upon him) one day", |
||||
|
"category": { |
||||
|
"id": 1, |
||||
|
"title": "Book of Faith", |
||||
|
"slug": "book-of-faith", |
||||
|
"source_type": "hadith", |
||||
|
"sect_type": "sunni" |
||||
|
}, |
||||
|
"status": { |
||||
|
"id": 130, |
||||
|
"title": "Прерванный", |
||||
|
"color": "orange" |
||||
|
}, |
||||
|
"share_link": "http://example.com/hadis/2" |
||||
|
} |
||||
|
] |
||||
|
} |
||||
|
} |
||||
|
), |
||||
|
status.HTTP_404_NOT_FOUND: openapi.Response( |
||||
|
description="The specified category ID does not exist or the category has no active hadis", |
||||
|
examples={ |
||||
|
"application/json": { |
||||
|
"detail": "Not found." |
||||
|
} |
||||
|
} |
||||
|
), |
||||
|
status.HTTP_500_INTERNAL_SERVER_ERROR: openapi.Response( |
||||
|
description="Internal server error occurred while processing the request" |
||||
|
) |
||||
|
} |
||||
|
) |
||||
@ -0,0 +1,25 @@ |
|||||
|
# Generated by Django 4.2.27 on 2025-12-28 11:31 |
||||
|
|
||||
|
from django.db import migrations, models |
||||
|
|
||||
|
|
||||
|
class Migration(migrations.Migration): |
||||
|
dependencies = [ |
||||
|
("transaction", "0003_alter_transactionparticipant_status_and_more"), |
||||
|
] |
||||
|
|
||||
|
operations = [ |
||||
|
migrations.AddField( |
||||
|
model_name="transactionparticipant", |
||||
|
name="payment_method", |
||||
|
field=models.CharField( |
||||
|
choices=[ |
||||
|
("receipt", "Receipt"), |
||||
|
("Payment_Gateway", "Payment Gateway"), |
||||
|
], |
||||
|
default="Payment_Gateway", |
||||
|
max_length=20, |
||||
|
verbose_name="Transaction Payment Method", |
||||
|
), |
||||
|
), |
||||
|
] |
||||
@ -0,0 +1,26 @@ |
|||||
|
# Generated by Django 4.2.27 on 2025-12-28 12:00 |
||||
|
|
||||
|
from django.db import migrations, models |
||||
|
|
||||
|
|
||||
|
class Migration(migrations.Migration): |
||||
|
dependencies = [ |
||||
|
("transaction", "0004_transactionparticipant_payment_method"), |
||||
|
] |
||||
|
|
||||
|
operations = [ |
||||
|
migrations.AlterField( |
||||
|
model_name="transactionparticipant", |
||||
|
name="payment_method", |
||||
|
field=models.CharField( |
||||
|
choices=[ |
||||
|
("receipt", "Receipt"), |
||||
|
("free", "Free"), |
||||
|
("Payment_Gateway", "Payment Gateway"), |
||||
|
], |
||||
|
default="Payment_Gateway", |
||||
|
max_length=20, |
||||
|
verbose_name="Transaction Payment Method", |
||||
|
), |
||||
|
), |
||||
|
] |
||||
@ -14,6 +14,7 @@ from utils.exceptions import AppAPIException |
|||||
from apps.account.models import User |
from apps.account.models import User |
||||
from drf_yasg.utils import swagger_auto_schema |
from drf_yasg.utils import swagger_auto_schema |
||||
from drf_yasg import openapi |
from drf_yasg import openapi |
||||
|
from apps.transaction.models import TransactionParticipant |
||||
from apps.transaction.doc import ( |
from apps.transaction.doc import ( |
||||
doc_upload_transaction_receipts, |
doc_upload_transaction_receipts, |
||||
doc_list_transaction_receipts, |
doc_list_transaction_receipts, |
||||
@ -31,31 +32,111 @@ class TransactionParticipantCreateView(generics.CreateAPIView): |
|||||
permission_classes = [IsAuthenticated] |
permission_classes = [IsAuthenticated] |
||||
|
|
||||
@swagger_auto_schema( |
@swagger_auto_schema( |
||||
operation_description=doc_create_transaction() |
|
||||
|
operation_description=doc_create_transaction(), |
||||
|
responses={ |
||||
|
status.HTTP_201_CREATED: openapi.Response( |
||||
|
description="Transaction participant created successfully", |
||||
|
examples={ |
||||
|
"application/json": { |
||||
|
"message": "Transaction Participant created successfully.", |
||||
|
"transaction_id": 374, |
||||
|
"payment_method": "Payment_Gateway", |
||||
|
"payment_link": "https://russia-payment.com/pay/374", |
||||
|
"participant_infos": [ |
||||
|
{ |
||||
|
"fullname": "string", |
||||
|
"email": "[email protected]", |
||||
|
"phone_number": "string", |
||||
|
"gender": "male", |
||||
|
"birthdate": "2025-12-28" |
||||
|
} |
||||
|
] |
||||
|
} |
||||
|
}, |
||||
|
schema=openapi.Schema( |
||||
|
type=openapi.TYPE_OBJECT, |
||||
|
properties={ |
||||
|
'message': openapi.Schema(type=openapi.TYPE_STRING, description="Success message"), |
||||
|
'transaction_id': openapi.Schema(type=openapi.TYPE_INTEGER, description="Unique transaction identifier"), |
||||
|
'payment_method': openapi.Schema( |
||||
|
type=openapi.TYPE_STRING, |
||||
|
enum=['Payment_Gateway', 'receipt'], |
||||
|
description="Payment method: 'Payment_Gateway' for online payment, 'receipt' for WhatsApp upload" |
||||
|
), |
||||
|
'payment_link': openapi.Schema( |
||||
|
type=openapi.TYPE_STRING, |
||||
|
nullable=True, |
||||
|
description="Payment gateway URL (only present when payment_method is 'Payment_Gateway')" |
||||
|
), |
||||
|
'participant_infos': openapi.Schema( |
||||
|
type=openapi.TYPE_ARRAY, |
||||
|
items=openapi.Schema( |
||||
|
type=openapi.TYPE_OBJECT, |
||||
|
properties={ |
||||
|
'fullname': openapi.Schema(type=openapi.TYPE_STRING), |
||||
|
'email': openapi.Schema(type=openapi.TYPE_STRING), |
||||
|
'phone_number': openapi.Schema(type=openapi.TYPE_STRING), |
||||
|
'gender': openapi.Schema(type=openapi.TYPE_STRING, enum=['male', 'female']), |
||||
|
'birthdate': openapi.Schema(type=openapi.TYPE_STRING, format='date'), |
||||
|
} |
||||
|
), |
||||
|
description="List of participant information" |
||||
|
), |
||||
|
}, |
||||
|
required=['message', 'transaction_id', 'participant_infos'] |
||||
|
) |
||||
|
), |
||||
|
status.HTTP_400_BAD_REQUEST: openapi.Response( |
||||
|
description="Invalid data provided", |
||||
|
schema=openapi.Schema( |
||||
|
type=openapi.TYPE_OBJECT, |
||||
|
properties={ |
||||
|
'detail': openapi.Schema(type=openapi.TYPE_STRING), |
||||
|
} |
||||
|
) |
||||
|
), |
||||
|
status.HTTP_404_NOT_FOUND: openapi.Response( |
||||
|
description="Course not found", |
||||
|
schema=openapi.Schema( |
||||
|
type=openapi.TYPE_OBJECT, |
||||
|
properties={ |
||||
|
'message': openapi.Schema(type=openapi.TYPE_STRING), |
||||
|
} |
||||
|
) |
||||
|
), |
||||
|
}, |
||||
|
tags=['transaction'] |
||||
) |
) |
||||
def create(self, request, *args, **kwargs): |
|
||||
|
def post(self, request, *args, **kwargs): |
||||
|
# Simply call the create method |
||||
|
return self.create(request, *args, **kwargs) |
||||
|
|
||||
|
def create(self, request, *args, **kwargs): |
||||
user = request.user |
user = request.user |
||||
course_slug = self.kwargs.get('slug') # Get the slug from the URL |
|
||||
|
course_slug = self.kwargs.get('slug') |
||||
|
|
||||
|
# 1. Retrieve Course |
||||
try: |
try: |
||||
course = Course.objects.get(slug=course_slug) # Retrieve the Course object |
|
||||
|
course = Course.objects.get(slug=course_slug) |
||||
except Course.DoesNotExist: |
except Course.DoesNotExist: |
||||
raise AppAPIException({'message': "Course not found"}) # Handle course not found |
|
||||
|
raise AppAPIException({'message': "Course not found"}) |
||||
|
|
||||
participant_infos = request.data.get('participant_infos', []) |
participant_infos = request.data.get('participant_infos', []) |
||||
|
|
||||
|
# 2. Validate and Initialize |
||||
serializer = self.get_serializer(data=request.data) |
serializer = self.get_serializer(data=request.data) |
||||
serializer.is_valid(raise_exception=True) |
serializer.is_valid(raise_exception=True) |
||||
statis = TransactionParticipant.TransactionStatus.PENDING |
statis = TransactionParticipant.TransactionStatus.PENDING |
||||
|
|
||||
|
# 3. Handle Free/Self-Enrollment Logic |
||||
if len(participant_infos) == 1 and (course.final_price == 0 or course.is_free): |
if len(participant_infos) == 1 and (course.final_price == 0 or course.is_free): |
||||
participant = participant_infos[0] |
participant = participant_infos[0] |
||||
if participant.get('email') != user.email: |
if participant.get('email') != user.email: |
||||
raise AppAPIException({'message': "The email must be for the requesting user"}) |
raise AppAPIException({'message': "The email must be for the requesting user"}) |
||||
|
|
||||
# به جای تغییر user_type، فقط نقش student را اضافه میکنیم |
|
||||
if not user.has_role('student'): |
if not user.has_role('student'): |
||||
user.add_role('student') |
user.add_role('student') |
||||
|
|
||||
# فیلتر کردن برای چک کردن وجود participant |
|
||||
existing_participant = Participant.objects.filter(student=user, course=course).first() |
existing_participant = Participant.objects.filter(student=user, course=course).first() |
||||
if existing_participant: |
if existing_participant: |
||||
participant = existing_participant |
participant = existing_participant |
||||
@ -63,37 +144,57 @@ class TransactionParticipantCreateView(generics.CreateAPIView): |
|||||
participant = Participant.objects.create(student=user, course=course) |
participant = Participant.objects.create(student=user, course=course) |
||||
statis = TransactionParticipant.TransactionStatus.SUCCESS |
statis = TransactionParticipant.TransactionStatus.SUCCESS |
||||
|
|
||||
|
|
||||
|
|
||||
transaction_participant = serializer.save(user=user, course=course, price=course.final_price, status=statis) |
|
||||
print(f'---> {type(transaction_participant)}/ {transaction_participant}') |
|
||||
|
# 4. Save Transaction |
||||
|
transaction_participant = serializer.save( |
||||
|
user=user, |
||||
|
course=course, |
||||
|
price=course.final_price, |
||||
|
status=statis |
||||
|
) |
||||
|
print(f'---> {type(transaction_participant)}/ {transaction_participant}') |
||||
|
|
||||
# ======================================================= |
|
||||
# NEW LOGIC: GEOLOCATION CHECK |
|
||||
# ======================================================= |
# ======================================================= |
||||
|
# NEW LOGIC: HYBRID GEOLOCATION CHECK (Cloudflare + Local DB) |
||||
|
# ======================================================= |
||||
|
|
||||
|
payment_link = None |
||||
|
|
||||
payment_link = None # Default link |
|
||||
|
|
||||
# Only check IP if transaction is PENDING (needs payment) |
|
||||
|
payment_method = TransactionParticipant.PaymentMethods.FREE |
||||
if statis == TransactionParticipant.TransactionStatus.PENDING: |
if statis == TransactionParticipant.TransactionStatus.PENDING: |
||||
|
|
||||
client_ip = get_client_ip(request) |
|
||||
# "188.93.104.1" |
|
||||
#get_client_ip(request) |
|
||||
country_code = get_country_code(client_ip) |
|
||||
|
|
||||
if country_code == 'RU': |
|
||||
# Generate Russia-specific link (e.g., YooMoney, Mir card, etc.) |
|
||||
|
|
||||
|
# Step A: Fast Path - Check Cloudflare Header |
||||
|
# Cloudflare sends the 2-letter code (e.g., 'RU', 'US') in this header |
||||
|
country_code = request.META.get('HTTP_CF_IPCOUNTRY') |
||||
|
|
||||
|
# Step B: Slow Path - Fallback to Local DB |
||||
|
# If header is missing (e.g., Localhost, direct connection, or CF failed) |
||||
|
if not country_code: |
||||
|
try: |
||||
|
client_ip =get_client_ip(request) |
||||
|
# "188.93.104.1" |
||||
|
# get_client_ip(request) |
||||
|
# Assuming your helper handles errors gracefully and returns None |
||||
|
country_code = get_country_code(client_ip) |
||||
|
except Exception as e: |
||||
|
print(f"GeoIP Lookup Failed: {e}") |
||||
|
country_code = None |
||||
|
payment_method = TransactionParticipant.PaymentMethods.RECEIPT |
||||
|
# Step C: Apply Logic |
||||
|
if country_code != 'RU': |
||||
|
payment_method = TransactionParticipant.PaymentMethods.PAYMENT_GATEWAY |
||||
payment_link = f"https://russia-payment.com/pay/{transaction_participant.id}" |
payment_link = f"https://russia-payment.com/pay/{transaction_participant.id}" |
||||
|
|
||||
|
# Uncomment if you want a global fallback link |
||||
# else: |
# else: |
||||
# # Standard Global Link (e.g., PayPal, Stripe) |
|
||||
# payment_link = f"https://global-payment.com/pay/{transaction_participant.id}" |
# payment_link = f"https://global-payment.com/pay/{transaction_participant.id}" |
||||
|
|
||||
# ======================================================= |
|
||||
|
# ======================================================= |
||||
|
|
||||
return Response({ |
return Response({ |
||||
'message': 'Transaction Participant created successfully.', |
'message': 'Transaction Participant created successfully.', |
||||
'transaction_id': transaction_participant.id, |
'transaction_id': transaction_participant.id, |
||||
'payment_link': payment_link, # <--- Return the dynamic link |
|
||||
|
'payment_method':payment_method, |
||||
|
'payment_link': payment_link, |
||||
'participant_infos': serializer.data['participant_infos'] |
'participant_infos': serializer.data['participant_infos'] |
||||
}, status=status.HTTP_201_CREATED) |
}, status=status.HTTP_201_CREATED) |
||||
|
|
||||
|
|||||
Write
Preview
Loading…
Cancel
Save
Reference in new issue