first commit
This commit is contained in:
@@ -0,0 +1,172 @@
|
||||
{% extends "tienda/base.html" %}
|
||||
{% load static %}
|
||||
{% load vat_filters %}
|
||||
|
||||
{% block head %}
|
||||
<script src="https://js.stripe.com/v3/"></script>
|
||||
<script src="{% static 'js/checkout.js' %}"></script>
|
||||
<script defer src="https://use.fontawesome.com/releases/v6.4.0/js/all.js"></script>
|
||||
<style>
|
||||
.payment-methods {
|
||||
display: flex;
|
||||
gap: 15px;
|
||||
flex-wrap: wrap;
|
||||
margin-top: 20px;
|
||||
}
|
||||
|
||||
.payment-btn {
|
||||
flex: 1;
|
||||
min-width: 200px;
|
||||
padding: 12px 20px;
|
||||
font-size: 16px;
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
.payment-section {
|
||||
background-color: #f8f9fa;
|
||||
padding: 30px;
|
||||
border-radius: 8px;
|
||||
margin-top: 20px;
|
||||
}
|
||||
|
||||
.payment-section h3 {
|
||||
margin-bottom: 20px;
|
||||
color: #212529;
|
||||
}
|
||||
</style>
|
||||
{% endblock %}
|
||||
|
||||
|
||||
{% block content %}
|
||||
<div class="row mt-2">
|
||||
<div class="col-md-12">
|
||||
<!-- Token CSRF para requests AJAX -->
|
||||
{% csrf_token %}
|
||||
|
||||
<div class="d-flex justify-content-between align-items-center mb-3">
|
||||
<h1>Checkout</h1>
|
||||
<a href="{% url 'view_cart' %}" class="btn btn-outline-secondary">← Volver al carrito</a>
|
||||
</div>
|
||||
|
||||
{% if cart_items %}
|
||||
<div class="table-responsive mb-4">
|
||||
<table class="table table-striped align-middle">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Producto</th>
|
||||
<th class="text-end">Precio (sin IVA)</th>
|
||||
<th class="text-end">Cantidad</th>
|
||||
<th class="text-end">Subtotal (con IVA)</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{% for item in cart_items %}
|
||||
<tr>
|
||||
<td>{{ item.product.name }}</td>
|
||||
<td class="text-end">{{ item.product.price|format_price }}€</td>
|
||||
<td class="text-end">{{ item.quantity }}</td>
|
||||
<td class="text-end">{{ item.get_subtotal_with_vat|format_price }}€</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
<tfoot>
|
||||
<tr>
|
||||
<th colspan="2" class="text-end">Subtotal:</th>
|
||||
<th colspan="2" class="text-end">{{ cart.get_total|format_price }}€</th>
|
||||
</tr>
|
||||
<tr>
|
||||
<th colspan="2" class="text-end">IVA (21%):</th>
|
||||
<th colspan="2" class="text-end text-success">+{{ cart.get_vat_amount|format_price }}€</th>
|
||||
</tr>
|
||||
<tr style="background-color: #f8f9fa;">
|
||||
<th colspan="2" class="text-end" style="font-size: 1.1rem;">Total:</th>
|
||||
<th colspan="2" class="text-end" style="font-size: 1.1rem;">{{ cart.get_total_with_vat|format_price }}€</th>
|
||||
</tr>
|
||||
</tfoot>
|
||||
</table>
|
||||
</div>
|
||||
|
||||
<div class="payment-section">
|
||||
<h3>Selecciona tu método de pago</h3>
|
||||
<div class="payment-methods">
|
||||
<button
|
||||
id="checkout-button"
|
||||
class="btn btn-primary payment-btn"
|
||||
data-config-url="/tienda/config/"
|
||||
data-session-url="/tienda/create-checkout-session/">
|
||||
💳 Pagar con Stripe
|
||||
</button>
|
||||
|
||||
<button
|
||||
id="paypal-button"
|
||||
class="btn btn-warning payment-btn"
|
||||
data-payment-url="{% url 'create_paypal_payment' %}">
|
||||
🅿️ Pagar con PayPal
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
{% else %}
|
||||
<div class="alert alert-info">Tu carrito está vacío.</div>
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
// Manejo del botón de PayPal
|
||||
document.getElementById('paypal-button').addEventListener('click', async function(e) {
|
||||
e.preventDefault();
|
||||
|
||||
const button = this;
|
||||
const originalText = button.innerHTML;
|
||||
button.disabled = true;
|
||||
button.innerHTML = '<span class="spinner-border spinner-border-sm me-2"></span>Procesando...';
|
||||
|
||||
try {
|
||||
// Obtener CSRF token de múltiples formas
|
||||
let csrfToken = document.querySelector('[name=csrfmiddlewaretoken]')?.value;
|
||||
if (!csrfToken) {
|
||||
csrfToken = document.querySelector('input[name="csrfmiddlewaretoken"]')?.value;
|
||||
}
|
||||
if (!csrfToken) {
|
||||
csrfToken = document.cookie.split('; ').find(row => row.startsWith('csrftoken='))?.split('=')[1];
|
||||
}
|
||||
|
||||
console.log('CSRF Token encontrado:', csrfToken ? 'Sí' : 'No');
|
||||
|
||||
const response = await fetch(button.dataset.paymentUrl, {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'X-CSRFToken': csrfToken || '',
|
||||
'Content-Type': 'application/json',
|
||||
}
|
||||
});
|
||||
|
||||
console.log('Response status:', response.status);
|
||||
|
||||
const data = await response.json();
|
||||
console.log('Response data:', data);
|
||||
|
||||
if (response.ok && data.redirect) {
|
||||
// Redirigir a PayPal
|
||||
console.log('Redirigiendo a:', data.redirect);
|
||||
window.location.href = data.redirect;
|
||||
} else if (data.error) {
|
||||
console.error('Error en respuesta:', data.error);
|
||||
alert('Error: ' + data.error);
|
||||
button.disabled = false;
|
||||
button.innerHTML = originalText;
|
||||
} else {
|
||||
console.error('Respuesta inesperada:', data);
|
||||
alert('Error inesperado al procesar el pago');
|
||||
button.disabled = false;
|
||||
button.innerHTML = originalText;
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('Error en fetch:', error);
|
||||
alert('Error al procesar el pago con PayPal: ' + error.message);
|
||||
button.disabled = false;
|
||||
button.innerHTML = originalText;
|
||||
}
|
||||
});
|
||||
</script>
|
||||
{% endblock %}
|
||||
Reference in New Issue
Block a user