From: Vincenzo Carbonara Date: Tue, 15 Oct 2024 08:33:32 +0000 (+0200) Subject: Aggiungo file al precedente push X-Git-Url: https://git.atlas4tour.it/?a=commitdiff_plain;h=fd123c42dcabcd04e1abf7b3db1ff5c715c35be4;p=pia_atlas.git Aggiungo file al precedente push --- diff --git a/pagamenti/__init__.py b/pagamenti/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/pagamenti/admin.py b/pagamenti/admin.py new file mode 100644 index 0000000..8c38f3f --- /dev/null +++ b/pagamenti/admin.py @@ -0,0 +1,3 @@ +from django.contrib import admin + +# Register your models here. diff --git a/pagamenti/apps.py b/pagamenti/apps.py new file mode 100644 index 0000000..78160f0 --- /dev/null +++ b/pagamenti/apps.py @@ -0,0 +1,6 @@ +from django.apps import AppConfig + + +class PagamentiConfig(AppConfig): + default_auto_field = 'django.db.models.BigAutoField' + name = 'pagamenti' diff --git a/pagamenti/models.py b/pagamenti/models.py new file mode 100644 index 0000000..71a8362 --- /dev/null +++ b/pagamenti/models.py @@ -0,0 +1,3 @@ +from django.db import models + +# Create your models here. diff --git a/pagamenti/templates/payment_failed.html b/pagamenti/templates/payment_failed.html new file mode 100644 index 0000000..7ed26b1 --- /dev/null +++ b/pagamenti/templates/payment_failed.html @@ -0,0 +1,7 @@ +{% extends 'base.html' %} +{% block content %} +
+

Pagamento fallito!

+

Ci scusiamo, ma il tuo pagamento non è andato a buon fine.

+
+{% endblock %} \ No newline at end of file diff --git a/pagamenti/tests.py b/pagamenti/tests.py new file mode 100644 index 0000000..7ce503c --- /dev/null +++ b/pagamenti/tests.py @@ -0,0 +1,3 @@ +from django.test import TestCase + +# Create your tests here. diff --git a/pagamenti/views.py b/pagamenti/views.py new file mode 100644 index 0000000..b71ba7d --- /dev/null +++ b/pagamenti/views.py @@ -0,0 +1,192 @@ +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') diff --git a/requirements.txt b/requirements.txt index a298f85..559457b 100644 Binary files a/requirements.txt and b/requirements.txt differ diff --git a/sistema/templates/base.html b/sistema/templates/base.html index 05c8639..d2125bd 100644 --- a/sistema/templates/base.html +++ b/sistema/templates/base.html @@ -186,8 +186,6 @@ Tuoi Percorsi - - diff --git a/sistema/templates/percorsi_cliente_home.html b/sistema/templates/percorsi_cliente_home.html index b5e6323..ba6ef6e 100644 --- a/sistema/templates/percorsi_cliente_home.html +++ b/sistema/templates/percorsi_cliente_home.html @@ -52,7 +52,7 @@
{{ percorso.nome}}

{{ percorso.descrizione }}

-