--- /dev/null
+import requests
+from django.conf import settings
+from django.http import JsonResponse
+from django.shortcuts import redirect, render, get_object_or_404
+from django.urls import reverse
+from django.utils import timezone
+from django.views import View
+
+from sistema.models import Percorso, Pagamenti
+
+
+# Classe per ottenere il token PayPal
+class GetPayPalToken:
+ @staticmethod
+ def obtain_access_token():
+ """Ottieni il token di accesso da PayPal."""
+ url = f"{settings.PAYPAL_BASE_URL}/v1/oauth2/token"
+ client_id = settings.PAYPAL_ID
+ client_secret = settings.PAYPAL_SECRET
+
+ response = requests.post(
+ url,
+ headers={
+ 'Accept': 'application/json',
+ 'Accept-Language': 'en_US',
+ },
+ auth=(client_id, client_secret),
+ data={'grant_type': 'client_credentials'}
+ )
+
+ if response.status_code == 200:
+ return response.json().get('access_token')
+ else:
+ raise Exception("Error obtaining PayPal token")
+
+
+# Classe per gestire il checkout
+class CheckoutView(View):
+ def get(self, request, percorso_id):
+ """Visualizza la pagina di checkout."""
+ percorso = Percorso.objects.get(pk=percorso_id)
+ return render(request, 'pagamenti_checkout.html', {'percorso': percorso})
+
+ def post(self, request, percorso_id):
+ """Gestisce la creazione del pagamento PayPal e reindirizza l'utente."""
+ # Ottieni il percorso selezionato
+ percorso = Percorso.objects.get(pk=percorso_id)
+
+ try:
+ # Ottieni il token di accesso
+ access_token = GetPayPalToken.obtain_access_token()
+
+ # Crea il pagamento PayPal
+ response = self.create_paypal_payment(access_token, percorso)
+
+ if response.status_code == 201:
+ # Analizza la risposta per ottenere l'URL di approvazione
+ approval_url = self.get_approval_url(response.json())
+ if approval_url:
+ request.session['percorso_id'] = percorso_id
+ return redirect(approval_url)
+ else:
+ return JsonResponse({'error': 'Approval URL not found in PayPal response'}, status=500)
+ else:
+ return JsonResponse({'error': f'Error creating payment: {response.text}'}, status=response.status_code)
+
+ except Exception as e:
+ return JsonResponse({'error': str(e)}, status=500)
+
+ def create_paypal_payment(self, access_token, percorso):
+ """Crea il pagamento su PayPal."""
+ url = f"{settings.PAYPAL_BASE_URL}/v1/payments/payment"
+ headers = self.get_paypal_headers(access_token)
+ payment_data = self.build_payment_data(percorso)
+
+ response = requests.post(url, json=payment_data, headers=headers)
+ return response
+
+ def get_paypal_headers(self, access_token):
+ """Crea l'header di autorizzazione con il token di accesso PayPal."""
+ return {
+ 'Content-Type': 'application/json',
+ 'Authorization': f"Bearer {access_token}",
+ }
+
+ def build_payment_data(self, percorso):
+ """Costruisce il JSON dei dati di pagamento per PayPal."""
+ return {
+ "intent": "sale",
+ "payer": {
+ "payment_method": "paypal"
+ },
+ "transactions": [{
+ "amount": {
+ "total": str(percorso.prezzo),
+ "currency": "EUR"
+ },
+ "description": percorso.descrizione
+ }],
+ "redirect_urls": {
+ "return_url": self.build_absolute_uri(reverse('pagamenti:payment_success')), # Utilizza reverse per generare le URL dinamicamente
+ "cancel_url": self.build_absolute_uri(reverse('pagamenti:payment_cancel')),
+ }
+ }
+
+ def build_absolute_uri(self, relative_url):
+ """Costruisce l'URL completa a partire da un'URL relativa."""
+ request = self.request # Si assume che self sia una view con accesso al request
+ return request.build_absolute_uri(relative_url)
+
+ def get_approval_url(self, payment_response):
+ """Estrae l'URL di approvazione dalla risposta del pagamento."""
+ for link in payment_response.get('links', []):
+ if link.get('rel') == 'approval_url':
+ return link.get('href')
+ return None
+
+
+class PaymentSuccessView(View):
+ def get(self, request):
+ # Stampa i parametri per debug
+
+ payment_id = request.GET.get('paymentId')
+ payer_id = request.GET.get('PayerID')
+
+ # Se mancano i parametri, restituisci un errore
+ if not payment_id or not payer_id:
+ return JsonResponse({'error': 'Missing payment details'}, status=400)
+
+
+ # Esegui il pagamento su PayPal usando il paymentId e payerId
+ try:
+ # Ottieni il token di accesso PayPal
+ access_token = GetPayPalToken.obtain_access_token()
+
+ # Esegui il pagamento (aggiungiamo il metodo 'execute_payment' qui sotto)
+ execute_response = self.execute_payment(access_token, payment_id, payer_id)
+
+ # Verifica che la risposta di esecuzione sia corretta
+ if 'id' not in execute_response:
+ return JsonResponse({'error': 'Failed to execute payment'}, status=400)
+
+ # Aggiungi ulteriore logica per salvare il pagamento nel database, se necessario
+ # E.g., salvataggio in un modello `Pagamenti`
+ percorso_id = request.session.get('percorso_id')
+
+ if not percorso_id:
+ return JsonResponse({'error': 'Percorso ID not found in session'}, status=400)
+
+ user = request.user
+ if not user.is_authenticated:
+ return JsonResponse({'error': 'User not authenticated'}, status=403)
+
+ # Salva il pagamento nel DB
+ pagamento = Pagamenti.objects.create(
+ user=user,
+ percorso_id=percorso_id,
+ data_acquisto=timezone.now()
+ )
+
+ data_locale = timezone.localtime(pagamento.data_acquisto)
+
+ return render(request, 'payment_success.html', {'data_acquisto': data_locale})
+
+ except Exception as e:
+ return JsonResponse({'error': str(e)}, status=500)
+
+ def execute_payment(self, access_token, payment_id, payer_id):
+ """Esegue il pagamento su PayPal."""
+ url = f"{settings.PAYPAL_BASE_URL}/v1/payments/payment/{payment_id}/execute"
+ headers = {
+ 'Content-Type': 'application/json',
+ 'Authorization': f"Bearer {access_token}",
+ }
+ payload = {
+ 'payer_id': payer_id
+ }
+
+ # Esegui la richiesta a PayPal per eseguire il pagamento
+ response = requests.post(url, json=payload, headers=headers)
+
+ # Controlla lo stato della risposta e ritorna il JSON se è stato eseguito con successo
+ if response.status_code == 200:
+ return response.json()
+ else:
+ raise Exception(f"Failed to execute payment. Status: {response.status_code}, Content: {response.content}")
+
+
+# Classe per gestire l'annullamento del pagamento
+class PaymentCancelView(View):
+ def get(self, request):
+ return render(request, 'payment_failed.html')