Merge modifications for more separate backend functions #69
| @@ -13,6 +13,11 @@ load_dotenv(override=True) | ||||
| @dataclass | ||||
| class Environment : | ||||
| 
					
					kscheidecker marked this conversation as resolved
					
				 | ||||
|  | ||||
|     # 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 | ||||
|         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 | ||||
|   | ||||
							
								
								
									
										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
	
I like this.