Skip to content

Commit

Permalink
Merge pull request #42 from YashSahsani/payments
Browse files Browse the repository at this point in the history
msg - Stripe implementation
  • Loading branch information
param623 authored Jul 10, 2024
2 parents 6dfbd10 + 391877e commit ad41709
Show file tree
Hide file tree
Showing 5 changed files with 180 additions and 36 deletions.
18 changes: 18 additions & 0 deletions payments/migrations/0008_payment_stripe_payment_intent_id.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
# Generated by Django 4.2.13 on 2024-07-09 19:17

from django.db import migrations, models


class Migration(migrations.Migration):

dependencies = [
('payments', '0007_alter_payment_city'),
]

operations = [
migrations.AddField(
model_name='payment',
name='stripe_payment_intent_id',
field=models.CharField(blank=True, max_length=255, null=True),
),
]
1 change: 1 addition & 0 deletions payments/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -117,6 +117,7 @@ class Payment(models.Model):
city = models.CharField(max_length=264, choices=CITY_CHOICES, blank=True, default='TOR')
Amount = models.DecimalField(max_digits=10, decimal_places=2)
Email = models.EmailField()
stripe_payment_intent_id = models.CharField(max_length=255, blank=True, null=True)

def __str__(self):
return f"{self.Email} - {self.Amount}"
89 changes: 58 additions & 31 deletions payments/static/payments/styles.css
Original file line number Diff line number Diff line change
@@ -1,60 +1,87 @@
.payment-page {
/* payments/static/payments/styles.css */

/* General Styles */
body {
font-family: Arial, sans-serif;
background-color: #f4f4f9;
background-color: #f9f9f9;
color: #333;
margin: 0;
padding: 0;
display: flex;
justify-content: center;
align-items: center;
min-height: 100vh;
padding: 20px;
height: 100vh;
}

.payment-container {
background-color: #fff;
h1 {
text-align: center;
color: #333;
}

form {
background: #fff;
padding: 20px;
border-radius: 8px;
box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1);
box-shadow: 0 0 10px rgba(0, 0, 0, 0.1);
max-width: 400px;
width: 100%;
margin: 20px auto;
}

.payment-container h1 {
font-size: 24px;
margin-bottom: 20px;
color: #333;
}

.payment-container form {
display: flex;
flex-direction: column;
form div {
margin-bottom: 15px;
}

.payment-container label {
margin-bottom: 5px;
label {
display: block;
font-weight: bold;
margin-bottom: 5px;
}

.payment-container input[type="text"],
.payment-container input[type="email"],
.payment-container input[type="number"],
.payment-container select {
input,
button {
width: 100%;
padding: 10px;
margin-bottom: 15px;
border: 1px solid #ccc;
border-radius: 4px;
font-size: 16px;
width: 100%; /* Ensure inputs take full width */
border: 1px solid #ddd;
box-sizing: border-box;
}

.payment-container button {
padding: 10px;
button {
background-color: #28a745;
color: #fff;
border: none;
border-radius: 4px;
cursor: pointer;
font-size: 16px;
}

.payment-container button:hover {
button:hover {
background-color: #218838;
}

/* Stripe Card Element */
#card-element {
border: 1px solid #ddd;
padding: 10px;
border-radius: 4px;
margin-bottom: 10px;
}

/* Error Message */
#card-error {
color: #e74c3c;
margin-top: 10px;
text-align: center;
}

/* Success Message */
.success {
color: #28a745;
text-align: center;
}

/* Responsive Design */
@media (max-width: 600px) {
form {
padding: 15px;
}
}
83 changes: 83 additions & 0 deletions payments/templates/payments/checkout.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
<!-- payments/templates/payments/checkout.html -->
{% load static %}
<!DOCTYPE html>
<html>
<head>
<title>Checkout</title>
<link rel="stylesheet" type="text/css" href="{% static 'payments/styles.css' %}">
<script src="https://js.stripe.com/v3/"></script>
</head>
<body>
<h1>Checkout</h1>
<form id="payment-form">
<div>
<label for="name">Name</label>
<input type="text" id="name" name="name" required>
</div>
<div>
<label for="email">Email</label>
<input type="email" id="email" name="email" required>
</div>
<div>
<label for="amount">Amount</label>
<input type="number" id="amount" name="amount" required>
</div>
<div>
<label for="description">Description</label>
<input type="text" id="description" name="description">
</div>
<div id="card-element">
<!-- A Stripe Element will be inserted here. -->
</div>
<div id="card-error" role="alert"></div>
<button id="submit">Pay</button>
</form>

<script>
// Initialize Stripe
var stripe = Stripe('{{ STRIPE_PUBLISHABLE_KEY }}'); // Replace with your Stripe publishable key
var elements = stripe.elements();

// Create an instance of the card Element
var cardElement = elements.create('card');

// Add an instance of the card Element into the `card-element` <div>
cardElement.mount('#card-element');

// Handle real-time validation errors from the card Element
cardElement.on('change', function(event) {
var displayError = document.getElementById('card-error');
if (event.error) {
displayError.textContent = event.error.message;
} else {
displayError.textContent = '';
}
});

// Handle form submission
var form = document.getElementById('payment-form');
form.addEventListener('submit', function(event) {
event.preventDefault();

stripe.confirmCardPayment('{{ payment_intent_client_secret }}', {
payment_method: {
card: cardElement,
billing_details: {
name: form.querySelector('input[name="name"]').value,
email: form.querySelector('input[name="email"]').value,
}
}
}).then(function(result) {
if (result.error) {
// Show error to your customer (e.g., insufficient funds)
var errorElement = document.getElementById('card-error');
errorElement.textContent = result.error.message;
} else {
// The payment succeeded!
window.location.href = "{% url 'payments:payment_success' %}";
}
});
});
</script>
</body>
</html>
25 changes: 20 additions & 5 deletions payments/views.py
Original file line number Diff line number Diff line change
@@ -1,16 +1,31 @@
from django.conf import settings
from django.shortcuts import render, redirect
from django.views.decorators.csrf import csrf_exempt
from .forms import PaymentForm
from .models import Payment
import stripe


stripe.api_key = settings.STRIPE_SECRET_KEY

def payment_view(request):
form = PaymentForm()
if request.method == 'POST':
form = PaymentForm(request.POST)
if form.is_valid():
form.save()
return redirect('payments:payment_success') # Ensure 'payment_success' matches the name in urls.py
else:
form = PaymentForm()

payment = form.save(commit=False)
payment_intent = stripe.PaymentIntent.create(
amount=int(payment.Amount * 100), # Stripe expects the amount in cents
currency='cad',
metadata={'email': payment.Email}
)
payment.stripe_payment_intent_id = payment_intent['id']
payment.save()
return render(request, 'payments/checkout.html', {
'payment_intent_client_secret': payment_intent['client_secret'],
'STRIPE_PUBLISHABLE_KEY': settings.STRIPE_PUBLISHABLE_KEY,
'payment': payment
})
return render(request, 'payments/payment_form.html', {'form': form})


Expand Down

0 comments on commit ad41709

Please sign in to comment.