integrated supabase in payment process
Some checks failed
Build and deploy the backend to staging / Build and push image (pull_request) Successful in 1m13s
Run linting on the backend code / Build (pull_request) Successful in 3m9s
Run testing on the backend code / Build (pull_request) Failing after 2m32s
Build and deploy the backend to staging / Deploy to staging (pull_request) Failing after 35s
Some checks failed
Build and deploy the backend to staging / Build and push image (pull_request) Successful in 1m13s
Run linting on the backend code / Build (pull_request) Successful in 3m9s
Run testing on the backend code / Build (pull_request) Failing after 2m32s
Build and deploy the backend to staging / Deploy to staging (pull_request) Failing after 35s
This commit is contained in:
@@ -1,20 +1,22 @@
|
||||
import json
|
||||
import logging
|
||||
from typing import Literal
|
||||
from datetime import datetime, timedelta
|
||||
import logging
|
||||
import json
|
||||
|
||||
from pydantic import BaseModel, Field, field_validator
|
||||
import requests
|
||||
from pydantic import BaseModel, Field, field_validator
|
||||
|
||||
from ..configuration.environment import Environment
|
||||
from ..cache import CreditCache, make_credit_cache_key
|
||||
|
||||
|
||||
# Define the base URL, might move that to toml file
|
||||
BASE_URL = 'https://api-m.sandbox.paypal.com'
|
||||
|
||||
# Intialize the logger
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
# Define the base URL, might move that to toml file
|
||||
BASE_URL_PROD = 'https://api-m.paypal.com'
|
||||
BASE_URL_SANDBOX = 'https://api-m.sandbox.paypal.com'
|
||||
|
||||
|
||||
class BasketItem(BaseModel):
|
||||
"""
|
||||
@@ -42,7 +44,7 @@ class Item(BaseModel):
|
||||
name: str
|
||||
description: str
|
||||
unit_price: float
|
||||
anyway_credits: int
|
||||
unit_credits: int
|
||||
|
||||
|
||||
def item_from_sql(item_id: str):
|
||||
@@ -60,8 +62,8 @@ def item_from_sql(item_id: str):
|
||||
id = '12345678',
|
||||
name = 'test_item',
|
||||
description = 'lorem ipsum',
|
||||
unit_price = 420,
|
||||
anyway_credits = 99
|
||||
unit_price = 0.1,
|
||||
unit_credits = 5
|
||||
)
|
||||
|
||||
|
||||
@@ -84,7 +86,8 @@ class OrderRequest(BaseModel):
|
||||
created_at: datetime = Field(default_factory=datetime.now)
|
||||
updated_at: datetime = Field(default_factory=datetime.now)
|
||||
items: list[Item] = Field(default_factory=list)
|
||||
total_price: float = 0
|
||||
total_price: float = None
|
||||
total_credits: int = None
|
||||
|
||||
@field_validator('basket')
|
||||
def validate_basket(cls, v):
|
||||
@@ -104,15 +107,18 @@ class OrderRequest(BaseModel):
|
||||
return
|
||||
|
||||
def load_items_and_price(self):
|
||||
# This should be automatic upon initialization of the class
|
||||
"""
|
||||
Loads item details from database and calculates the total price.
|
||||
Loads item details from database and calculates the total price as well as the total credits to be granted.
|
||||
"""
|
||||
self.items = []
|
||||
self.total_price = 0
|
||||
self.total_credits = 0
|
||||
for basket_item in self.basket:
|
||||
item = item_from_sql(basket_item.id)
|
||||
self.items.append(item)
|
||||
self.total_price += item.unit_price * basket_item.quantity
|
||||
self.total_price += item.unit_price * basket_item.quantity # increment price
|
||||
self.total_credits += item.unit_credits * basket_item.quantity # increment credit balance
|
||||
|
||||
|
||||
def to_paypal_items(self):
|
||||
@@ -138,11 +144,8 @@ class OrderRequest(BaseModel):
|
||||
return item_list
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# Payment handler class for managing PayPal payments
|
||||
class PaypalHandler:
|
||||
class PaypalClient:
|
||||
"""
|
||||
Handles PayPal payment operations.
|
||||
|
||||
@@ -159,7 +162,6 @@ class PaypalHandler:
|
||||
"expires_at": 0
|
||||
}
|
||||
|
||||
order_request = None
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
@@ -178,11 +180,11 @@ class PaypalHandler:
|
||||
if sandbox_mode :
|
||||
self.id = Environment.paypal_id_sandbox
|
||||
self.key = Environment.paypal_key_sandbox
|
||||
self.base_url = BASE_URL
|
||||
self.base_url = BASE_URL_SANDBOX
|
||||
else :
|
||||
self.id = Environment.paypal_id_prod
|
||||
self.key = Environment.paypal_key_prod
|
||||
self.base_url = 'https://api-m.paypal.com'
|
||||
self.base_url = BASE_URL_PROD
|
||||
|
||||
|
||||
|
||||
@@ -239,6 +241,11 @@ class PaypalHandler:
|
||||
Returns:
|
||||
dict | None: PayPal order response JSON, or None if failed.
|
||||
"""
|
||||
|
||||
# Fetch details of order from mart database and compute total credits and price
|
||||
order_request.load_items_and_price()
|
||||
|
||||
# Prepare payload for post request to paypal API
|
||||
order_data = {
|
||||
'intent': 'CAPTURE',
|
||||
'purchase_units': [
|
||||
@@ -286,20 +293,24 @@ class PaypalHandler:
|
||||
# order_id (key): json.loads(order_response.text)["id"]
|
||||
# user_id : order_request.user_id
|
||||
# created_at : order_request.created_at
|
||||
# status : order_request.status
|
||||
# status : PENDING
|
||||
# basket (json) : OrderDetails.jsonify()
|
||||
# total_price : order_request.total_price
|
||||
# currency : order_request.currency
|
||||
# updated_at : order_request.created_at
|
||||
|
||||
# Now we can increment the supabase balance by so many credits as in the balance.
|
||||
#TODO still
|
||||
# Create a cache item for credits to be granted to user
|
||||
CreditCache.set_credits(
|
||||
user_id = order_request.user_id,
|
||||
order_id = json.loads(order_response.text)["id"],
|
||||
credits_to_grant = order_request.total_credits)
|
||||
|
||||
|
||||
return order_response.json()
|
||||
|
||||
|
||||
# Standalone function to capture a payment
|
||||
def capture(self, order_id: str):
|
||||
def capture(self, user_id: str, order_id: str):
|
||||
"""
|
||||
Captures payment for a PayPal order.
|
||||
|
||||
@@ -314,7 +325,7 @@ class PaypalHandler:
|
||||
|
||||
try:
|
||||
capture_response = requests.post(
|
||||
url = f'{BASE_URL}/v2/checkout/orders/{order_id}/capture',
|
||||
url = f'{self.base_url}/v2/checkout/orders/{order_id}/capture',
|
||||
headers = {'Authorization': f'Bearer {access_token}'},
|
||||
json = {},
|
||||
)
|
||||
@@ -322,11 +333,12 @@ class PaypalHandler:
|
||||
logger.error(f'Error while requesting access token: {exc}')
|
||||
return None
|
||||
|
||||
# Raise exception if API call failed
|
||||
capture_response.raise_for_status()
|
||||
|
||||
# todo check status code + try except
|
||||
print(capture_response.text)
|
||||
# order_id = json.loads(response.text)["id"]
|
||||
|
||||
|
||||
# print(capture_response.text)
|
||||
|
||||
# TODO: update status to PAID in sql database
|
||||
|
||||
|
Reference in New Issue
Block a user