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
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:
@@ -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']
|
||||
|
@@ -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"
|
||||
|
||||
# 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
|
||||
|
100
backend/src/payments/test.py
Normal file
100
backend/src/payments/test.py
Normal 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"]
|
||||
|
Reference in New Issue
Block a user