overhaul of paypal handler WIP
Some checks failed
Build and deploy the backend to staging / Build and push image (pull_request) Successful in 3m44s
Run linting on the backend code / Build (pull_request) Successful in 23s
Run testing on the backend code / Build (pull_request) Failing after 3m7s
Build and deploy the backend to staging / Deploy to staging (pull_request) Failing after 35s

This commit is contained in:
2025-10-02 13:59:07 +02:00
parent 5549f8b0e5
commit 3bdcdea850
3 changed files with 156 additions and 36 deletions

View File

@@ -13,6 +13,11 @@ load_dotenv(override=True)
@dataclass
class Environment :
# 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
else:
self.logger.error(f"Failed to create payment: {payment.error}")
raise HTTPException(status_code=500, detail="Payment creation failed")
if self.sandbox :
validation_url = "https://api-m.sandbox.paypal.com/v1/oauth2/token"
else :
validation_url = "https://api-m.paypal.com/v1/oauth2/token"
# 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"]