]> git.atlas4tour.it Git - pia_atlas.git/commitdiff
Aggiungo file al precedente push
authorVincenzo Carbonara <vincenzo.carbonara@dyrecta.com>
Tue, 15 Oct 2024 08:33:32 +0000 (10:33 +0200)
committerVincenzo Carbonara <vincenzo.carbonara@dyrecta.com>
Tue, 15 Oct 2024 08:33:32 +0000 (10:33 +0200)
pagamenti/__init__.py [new file with mode: 0644]
pagamenti/admin.py [new file with mode: 0644]
pagamenti/apps.py [new file with mode: 0644]
pagamenti/models.py [new file with mode: 0644]
pagamenti/templates/payment_failed.html [new file with mode: 0644]
pagamenti/tests.py [new file with mode: 0644]
pagamenti/views.py [new file with mode: 0644]
requirements.txt
sistema/templates/base.html
sistema/templates/percorsi_cliente_home.html

diff --git a/pagamenti/__init__.py b/pagamenti/__init__.py
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/pagamenti/admin.py b/pagamenti/admin.py
new file mode 100644 (file)
index 0000000..8c38f3f
--- /dev/null
@@ -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 (file)
index 0000000..78160f0
--- /dev/null
@@ -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 (file)
index 0000000..71a8362
--- /dev/null
@@ -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 (file)
index 0000000..7ed26b1
--- /dev/null
@@ -0,0 +1,7 @@
+{% extends 'base.html' %}
+{% block content %}
+<div class="container">
+    <h1>Pagamento fallito!</h1>
+    <p>Ci scusiamo, ma il tuo pagamento non è andato a buon fine.</p>
+</div>
+{% endblock %}
\ No newline at end of file
diff --git a/pagamenti/tests.py b/pagamenti/tests.py
new file mode 100644 (file)
index 0000000..7ce503c
--- /dev/null
@@ -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 (file)
index 0000000..b71ba7d
--- /dev/null
@@ -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')
index a298f856ef1a1988da37ecaf7eb35003be3902c1..559457b74a611dc4dca55ded468cf945e156eabb 100644 (file)
Binary files a/requirements.txt and b/requirements.txt differ
index 05c8639da7bf2055cf503421a1907bb25b400802..d2125bd8c5b40e77c78f3fe6b6b49afdd5de44a5 100644 (file)
                         <a href="{% url 'sistema:tuoi_percorsi_list' %}" class="nav-link">
                             <i class="fas fa-route" style="padding: 6px 28px 7px 6px;"></i><span>Tuoi Percorsi</span></a>
                     </li>
-
-
                 </ul>
             </aside>
         </div>
index b5e632318a5943ee45b2e978ef2adde023835cc6..ba6ef6ec512f5b265866650aec616969c3d647e4 100644 (file)
@@ -52,7 +52,7 @@
                                 <h5 class="card-title route__text">{{ percorso.nome}}</h5>
                                 <p class="card-text route__text">{{ percorso.descrizione }}</p>
                             </div>
-                            <div class="card-footer">
+                            <div class="card-footer p-3">
                                 <div class="d-flex justify-content-between">
                                     <h4>{{ percorso.prezzo|floatformat:2 }} €</h4>
                                     <a href="{% url 'pagamenti:checkout' percorso.pk %}" class="btn btn-success">Acquista ora</a>