testing playment not done
Browse files- App/Messages/MessagesRoute.py +28 -5
- App/Messages/Schema.py +10 -1
- App/Payments/Model.py +32 -0
App/Messages/MessagesRoute.py
CHANGED
@@ -1,12 +1,18 @@
|
|
1 |
# App/Messages/Routes.py
|
2 |
from fastapi import APIRouter, HTTPException, Request
|
3 |
from .Model import Message
|
4 |
-
from .Schema import MessageCreate, MessageResponse
|
5 |
from uuid import UUID
|
6 |
from typing import List, Optional
|
7 |
import re
|
8 |
from datetime import datetime
|
9 |
from decimal import Decimal
|
|
|
|
|
|
|
|
|
|
|
|
|
10 |
|
11 |
message_router = APIRouter(tags=["Messages"], prefix="/messages")
|
12 |
|
@@ -15,7 +21,6 @@ message_router = APIRouter(tags=["Messages"], prefix="/messages")
|
|
15 |
async def receive_message(request: Request):
|
16 |
|
17 |
message_raw = await request.json()
|
18 |
-
print(message_raw)
|
19 |
message_data = MessageCreate(**message_raw)
|
20 |
try:
|
21 |
# Extract data from the message content using regex
|
@@ -34,19 +39,37 @@ async def receive_message(request: Request):
|
|
34 |
sim_number=message_data.payload.simNumber,
|
35 |
parsed_data=parsed_data,
|
36 |
)
|
37 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
38 |
except Exception as e:
|
39 |
raise HTTPException(status_code=400, detail=str(e))
|
40 |
|
41 |
|
42 |
-
def parse_message_content(text: str) -> Optional[
|
43 |
# Regular expression to capture the data from the message, allowing for different types of spaces
|
44 |
pattern = r"(\w+)\sConfirmed\.You have received Tsh([\d,]+\.\d{2}) from (\d{12}) - ([A-Z ]+) on (\d{1,2}/\d{1,2}/\d{2}) at ([\d:]+ [APM]+).*?balance\sis\sTsh([\d,]+\.\d{2})"
|
45 |
|
46 |
# Replace non-breaking spaces and other whitespace characters with regular spaces in the input text
|
47 |
text = re.sub(r"\s+", " ", text)
|
48 |
|
49 |
-
matches = re.search(pattern, text)
|
50 |
if matches:
|
51 |
data = {
|
52 |
"transaction_id": matches.group(1),
|
|
|
1 |
# App/Messages/Routes.py
|
2 |
from fastapi import APIRouter, HTTPException, Request
|
3 |
from .Model import Message
|
4 |
+
from .Schema import MessageCreate, MessageResponse, TransactionSchema
|
5 |
from uuid import UUID
|
6 |
from typing import List, Optional
|
7 |
import re
|
8 |
from datetime import datetime
|
9 |
from decimal import Decimal
|
10 |
+
from App.Payments.PaymentsRoutes import create_payment
|
11 |
+
from App.Payments.Schema import CreatePaymentRequest
|
12 |
+
from App.Users.Model import User
|
13 |
+
from App.Payments.Schema import PaymentMethod
|
14 |
+
from App.Payments.Model import Payment
|
15 |
+
from App.Plans.Model import Plan
|
16 |
|
17 |
message_router = APIRouter(tags=["Messages"], prefix="/messages")
|
18 |
|
|
|
21 |
async def receive_message(request: Request):
|
22 |
|
23 |
message_raw = await request.json()
|
|
|
24 |
message_data = MessageCreate(**message_raw)
|
25 |
try:
|
26 |
# Extract data from the message content using regex
|
|
|
39 |
sim_number=message_data.payload.simNumber,
|
40 |
parsed_data=parsed_data,
|
41 |
)
|
42 |
+
|
43 |
+
# Process Mpesa Payments
|
44 |
+
if parsed_data:
|
45 |
+
user: User = User.get_or_none(phoneNumber=parsed_data.phone_number)
|
46 |
+
data_plan: Plan = Plan.get_or_none(
|
47 |
+
amount=Decimal(parsed_data.amount_received)
|
48 |
+
)
|
49 |
+
payment_details = CreatePaymentRequest(
|
50 |
+
user_id=user.id,
|
51 |
+
plan_id=data_plan.id,
|
52 |
+
amount=Decimal(parsed_data.amount_received),
|
53 |
+
payment_method=PaymentMethod.MPESA,
|
54 |
+
transaction_id=parsed_data.transaction_id,
|
55 |
+
)
|
56 |
+
data = MessageResponse.from_orm(new_message)
|
57 |
+
|
58 |
+
payment: Payment = await create_payment(payment_details)
|
59 |
+
await payment.create_subscription_or_balance()
|
60 |
+
return data
|
61 |
except Exception as e:
|
62 |
raise HTTPException(status_code=400, detail=str(e))
|
63 |
|
64 |
|
65 |
+
def parse_message_content(text: str) -> Optional[TransactionSchema]:
|
66 |
# Regular expression to capture the data from the message, allowing for different types of spaces
|
67 |
pattern = r"(\w+)\sConfirmed\.You have received Tsh([\d,]+\.\d{2}) from (\d{12}) - ([A-Z ]+) on (\d{1,2}/\d{1,2}/\d{2}) at ([\d:]+ [APM]+).*?balance\sis\sTsh([\d,]+\.\d{2})"
|
68 |
|
69 |
# Replace non-breaking spaces and other whitespace characters with regular spaces in the input text
|
70 |
text = re.sub(r"\s+", " ", text)
|
71 |
|
72 |
+
matches: TransactionSchema = re.search(pattern, text)
|
73 |
if matches:
|
74 |
data = {
|
75 |
"transaction_id": matches.group(1),
|
App/Messages/Schema.py
CHANGED
@@ -1,9 +1,18 @@
|
|
1 |
# App/Messages/Schema.py
|
2 |
-
from pydantic import BaseModel, UUID4, Field, ConfigDict
|
3 |
from datetime import datetime
|
4 |
from typing import Optional
|
5 |
|
6 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
7 |
class PayloadSchema(BaseModel):
|
8 |
message: str
|
9 |
phoneNumber: str
|
|
|
1 |
# App/Messages/Schema.py
|
2 |
+
from pydantic import BaseModel, UUID4, Field, ConfigDict, condecimal, constr
|
3 |
from datetime import datetime
|
4 |
from typing import Optional
|
5 |
|
6 |
|
7 |
+
class TransactionSchema(BaseModel):
|
8 |
+
transaction_id: str
|
9 |
+
amount_received: float
|
10 |
+
phone_number: str
|
11 |
+
name: str
|
12 |
+
date: datetime
|
13 |
+
new_balance: float
|
14 |
+
|
15 |
+
|
16 |
class PayloadSchema(BaseModel):
|
17 |
message: str
|
18 |
phoneNumber: str
|
App/Payments/Model.py
CHANGED
@@ -66,3 +66,35 @@ class Payment(Model):
|
|
66 |
else:
|
67 |
self.status = "insufficient-funds"
|
68 |
await self.save()
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
66 |
else:
|
67 |
self.status = "insufficient-funds"
|
68 |
await self.save()
|
69 |
+
|
70 |
+
async def create_subscription_or_balance(self):
|
71 |
+
"""
|
72 |
+
Creates a subscription for the user if the payment method is 'cash'
|
73 |
+
and the user has enough balance for the specified plan.
|
74 |
+
"""
|
75 |
+
if self.user and self.plan:
|
76 |
+
if self.amount >= self.plan.amount:
|
77 |
+
expiration_time = datetime.datetime.now() + datetime.timedelta(
|
78 |
+
hours=self.plan.duration
|
79 |
+
)
|
80 |
+
# Create the subscription
|
81 |
+
await Subscription.create(
|
82 |
+
user=self.user,
|
83 |
+
duration=self.plan.duration,
|
84 |
+
download_mb=self.plan.download_speed
|
85 |
+
* 1024, # Converting Mbps to MB
|
86 |
+
upload_mb=self.plan.upload_speed * 1024, # Converting Mbps to MB
|
87 |
+
created_time=datetime.datetime.now(),
|
88 |
+
expiration_time=expiration_time,
|
89 |
+
active=True,
|
90 |
+
)
|
91 |
+
self.status = "subscription-created"
|
92 |
+
else:
|
93 |
+
self.status = "insufficient-funds"
|
94 |
+
await self.save()
|
95 |
+
|
96 |
+
if not self.plan and self.user:
|
97 |
+
self.user.balance += self.amount
|
98 |
+
await self.user.save()
|
99 |
+
self.status = "subscription-created"
|
100 |
+
await self.save()
|