Merge modifications for more separate backend functions #69

Open
kscheidecker wants to merge 39 commits from backend/micro-services-restructuring into main
3 changed files with 156 additions and 36 deletions
Showing only changes of commit 3bdcdea850 - Show all commits

View File

@@ -13,6 +13,11 @@ load_dotenv(override=True)
@dataclass
class Environment :
kscheidecker marked this conversation as resolved
Review

I like this.

I like this.
# Load supabase secrets
supabase_url = os.environ['SUPABASE_URL']
supabase_admin_key = os.environ['SUPABASE_ADMIN_KEY']
supabase_test_user_id = os.environ['SUPABASE_TEST_USER_ID']
# Load paypal secrets
paypal_id_sandbox = os.environ['PAYPAL_ID_SANDBOX']
paypal_key_sandbox = os.environ['PAYPAL_KEY_SANDBOX']

View File

@@ -4,6 +4,9 @@ from pydantic import BaseModel
from fastapi import HTTPException
import logging
import requests
from ..configuration.environment import Environment
# Model for payment request body
class PaymentRequest(BaseModel):
@@ -14,13 +17,22 @@ class PaymentRequest(BaseModel):
# Payment handler class for managing PayPal payments
class PaymentHandler:
class PaypalHandler:
payment_id: str
# PayPal secrets
username = Environment.paypal_id_sandbox
password = Environment.paypal_key_sandbox
def __init__(self, transaction_details: PaymentRequest):
def __init__(
self,
transaction_details: PaymentRequest,
sandbox_mode: bool = False
):
self.details = transaction_details
self.logger = logging.getLogger(__name__)
self.sandbox = sandbox_mode
# Only support purchase of credit 'bundles': 10, 50 or 100 credits worth of trip generation
def fetch_price(self) -> float:
@@ -34,37 +46,40 @@ class PaymentHandler:
self.logger.error(f"Unsupported currency: {self.details.currency}")
return None
def create_paypal_payment(self) -> str:
"""
Creates a PayPal payment and returns the approval URL.
"""
price = self.fetch_price()
payment = paypalrestsdk.Payment({
"intent": "sale",
"payer": {
"payment_method": "paypal"
},
"transactions": [{
"amount": {
"total": f"{price:.2f}",
"currency": self.details.currency
},
"description": self.details.description
}],
"redirect_urls": {
"return_url": "http://localhost:8000/payment/success",
"cancel_url": "http://localhost:8000/payment/cancel"
}
})
if payment.create():
self.logger.info("Payment created successfully")
self.payment_id = payment.id
def validate(self):
# Get the approval URL and return it for the user to approve
for link in payment.links:
if link.rel == "approval_url":
return link.href
if self.sandbox :
validation_url = "https://api-m.sandbox.paypal.com/v1/oauth2/token"
else :
self.logger.error(f"Failed to create payment: {payment.error}")
raise HTTPException(status_code=500, detail="Payment creation failed")
validation_url = "https://api-m.paypal.com/v1/oauth2/token"
remoll marked this conversation as resolved Outdated

Pretty sure that won't work. It should definitely not be hardcoded since the callback will change depending on prod or staging.

Pretty sure that won't work. It should definitely not be hardcoded since the callback will change depending on prod or staging.
# payload for the validation request
validation_data = {'grant_type': 'client_credentials'}
# pass the request
validation_response = requests.post(
url=validation_url,
data=validation_data,
auth=(self.username, self.password)
)
# TODO: continue here
pass
def order(self):
pass
def capture(self):
pass
def cancel(self):
pass

View File

@@ -0,0 +1,100 @@
import requests
import json
from ..configuration.environment import Environment
# DOCUMENTATION AT : https://developer.paypal.com/api/rest/requests/
# username and password
username = Environment.paypal_id_sandbox
password = Environment.paypal_key_sandbox
######## STEP 1: Validation ########
# url for validation post request
validation_url = "https://api-m.sandbox.paypal.com/v1/oauth2/token"
validation_url_prod = "https://api-m.paypal.com/v1/oauth2/token"
# payload for the post request
validation_data = {'grant_type': 'client_credentials'}
# pass the request
validation_response = requests.post(
url=validation_url,
data=validation_data,
auth=(username, password)
)
# todo check status code + try except. Status code 201 ?
print(validation_response.text)
access_token = json.loads(validation_response.text)["access_token"]
######## STEP 2: Create Order ########
# url for post request
order_url = "https://api-m.sandbox.paypal.com/v2/checkout/orders"
order_url_prod = "https://api-m.paypal.com/v2/checkout/orders"
# payload for the request
order_data = {
"intent": "CAPTURE",
"purchase_units": [
{
"items": [
{
"name": "AnyWay Credits",
"description": "50 pack of credits",
"quantity": 1,
"unit_amount": {
"currency_code": "CHF",
"value": "5.00"
}
}
],
"amount": {
"currency_code": "CHF",
"value": "5.00",
"breakdown": {
"item_total": {
"currency_code": "CHF",
"value": "5.00"
}
}
}
}
],
"application_context": {
"return_url": "https://anydev.info",
"cancel_url": "https://anydev.info"
}
}
order_response = requests.post(
url=order_url,
json=order_data,
auth=(username, password)
)
# todo check status code + try except
print(order_response.text)
order_id = json.loads(order_response.text)["id"]
######## STEP 3: capture payment
# url for post request
capture_url = f"https://api-m.sandbox.paypal.com/v2/checkout/orders/{order_id}/capture"
capture_url_prod = f"https://api-m.paypal.com/v2/checkout/orders/{order_id}/capture"
capture_response = requests.post(
url=capture_url,
json={},
auth=(username, password)
)
# todo check status code + try except
print(capture_response.text)
# order_id = json.loads(response.text)["id"]