First version with credit card integration and UI
This commit is contained in:
@@ -10,19 +10,23 @@
|
||||
<form id="editor" method="post">
|
||||
<table border="1">
|
||||
<tr>
|
||||
<th>Camp</th>
|
||||
<th>Leader</th>
|
||||
<th>#Issued</th>
|
||||
<th>Camp </th>
|
||||
<th>Leader </th>
|
||||
<th>#Issued </th>
|
||||
<th>#Claimed</th>
|
||||
<th>#Used</th>
|
||||
<th>#Used </th>
|
||||
<th>#Paid </th>
|
||||
<th>$Paid </th>
|
||||
</tr>
|
||||
<% for (const c in camps) { %>
|
||||
<tr>
|
||||
<td><a href="/editcamp?campname=<%= c %>"><%=c%></td>
|
||||
<td><%=camps[c].leader%> </td>
|
||||
<td><%=camps[c].issued%> </td>
|
||||
<td><%=camps[c].leader%> </td>
|
||||
<td><%=camps[c].issued%> </td>
|
||||
<td><%=camps[c].claimed%> </td>
|
||||
<td><%=camps[c].used%> </td>
|
||||
<td><%=camps[c].used%> </td>
|
||||
<td><%=camps[c].npaid%> </td>
|
||||
<td><%=(camps[c].paid/100).toFixed(2)%> </td>
|
||||
</tr>
|
||||
<% } %>
|
||||
<tr>
|
||||
|
||||
@@ -23,7 +23,7 @@
|
||||
<label for="card-postal-element">ZIP Code</label>
|
||||
<div id="card-postal-element"></div>
|
||||
|
||||
<button id="submit-button" type="submit">Pay $19.99</button>
|
||||
<button id="submit-button" type="submit">Pay <%=amount%></button>
|
||||
</form>
|
||||
</div>
|
||||
<!-- Stripe.js -->
|
||||
@@ -51,7 +51,7 @@
|
||||
// 1. Create a PaymentMethod
|
||||
const { paymentMethod, error } = await stripe.createPaymentMethod({
|
||||
type: "card",
|
||||
card: cardElement,
|
||||
card: cardNumberElement,
|
||||
});
|
||||
|
||||
if (error) {
|
||||
|
||||
@@ -22,14 +22,16 @@
|
||||
<th>Ticket#</th>
|
||||
<th>Owner</th>
|
||||
<th>Offered To</th>
|
||||
<th>Paid?</th>
|
||||
<th>Status</th>
|
||||
<th>Action</th>
|
||||
</tr>
|
||||
<% for (const t in tickets) { %>
|
||||
<tr>
|
||||
<td><%=t%></td>
|
||||
<td><a href="oneticket?t=<%=t%>"><%=t%></a></td>
|
||||
<td><input type="text" class="owner" value="<%=tickets[t].owner%>" name="<%=t%>-owner"> </td>
|
||||
<td><input type="text" class="offered" value="<%=tickets[t].offered%>" name="<%=t%>-offered"></td>
|
||||
<td><%=tickets[t].paid>0 ? (tickets[t].paid/100).toFixed(2) : "No"%>
|
||||
<td>
|
||||
<select class="status" name="<%=t%>-status">
|
||||
<option value="i"<%=tickets[t].status=="i" ? " selected" : ""%>>Issued</option>
|
||||
|
||||
@@ -1,9 +1,13 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<title>Error Page</title>
|
||||
<title>Error</title>
|
||||
<link rel="stylesheet" href="styles.css">
|
||||
</head>
|
||||
<body>
|
||||
<h1>Some kind of error</h1>
|
||||
<%- include('partials/nav') %>
|
||||
<div class="content">
|
||||
An error has occurred.
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
@@ -20,12 +20,14 @@
|
||||
<tr>
|
||||
<th>Ticket#</th>
|
||||
<th>Offered To</th>
|
||||
<th>Paid?</th>
|
||||
<th>Action</th>
|
||||
</tr>
|
||||
<% for (const t in tickets) { %>
|
||||
<tr>
|
||||
<td><%=t%></td>
|
||||
<td><a href="oneticket?t=<%=t%>"><%=t%></a></td>
|
||||
<td><input type="text" class="offered" value="<%=tickets[t].offered%>" name="<%=t%>"></td>
|
||||
<td><%=tickets[t].paid>0 ? (tickets[t].paid/100).toFixed(2) : "No"%>
|
||||
<td><button id="<%=t%>-action" type="button"> QRCode </button></td>
|
||||
</tr>
|
||||
<% } %>
|
||||
|
||||
@@ -7,11 +7,22 @@
|
||||
<body>
|
||||
<%- include('partials/nav') %>
|
||||
<div class="content">
|
||||
To use <%=ticket%>, scan this QR Code:<br>
|
||||
To use <%=ticket%>, visit this URL: <%=useurl%><br>
|
||||
Or scan this QR Code:<br>
|
||||
<img class="qrcode-image" width=300 height=300 src="<%=qrcode%>" alt="QR Code"><br>
|
||||
Or visit this URL: "<%=useurl%>"
|
||||
<% if (paid==0) { %>
|
||||
Tickets are pay-what-you-can, minimum $1, suggested $50.<br>
|
||||
To pay for this ticket by credit card, enter an amount:
|
||||
<form id="pay" method="POST" action="/pay0">
|
||||
<input type="hidden" name="ticket" value="<%=ticket%>">
|
||||
<input type="number" min="1.00" max="1000.00" step="0.01" placeholder="50.00" name="amount">
|
||||
<button id="Submit" type="submit">Pay</button>
|
||||
</form>
|
||||
<% } else { %>
|
||||
This ticket has already been paid for. ($<%=(paid/100).toFixed(2)%>)
|
||||
<% } %>
|
||||
<form id="editor" method="POST" action="/oneticket">
|
||||
Or transfer <%=ticket%> to:<br>
|
||||
To transfer <%=ticket%>, enter the recipient's email address:<br>
|
||||
<input type="hidden" name="ticket" value="<%=ticket%>">
|
||||
<input type="email" placeholder="yourfriend@xyz.com" value="<%=offered%>" name="offered">
|
||||
<button id="Submit" type="submit">Transfer</button>
|
||||
|
||||
103
views/pay.ejs
Normal file
103
views/pay.ejs
Normal file
@@ -0,0 +1,103 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<title>Your Ticket</title>
|
||||
<link rel="stylesheet" href="styles.css">
|
||||
</head>
|
||||
<body>
|
||||
<%- include('partials/nav') %>
|
||||
<div class="content">
|
||||
<form id="payment-form">
|
||||
Payment Here!!!<%=amount%>
|
||||
<!-- Stripe Elements will inject the Card Element here -->
|
||||
|
||||
<label for="card-number-element">Card Number</label>
|
||||
<div id="card-number-element"></div>
|
||||
|
||||
<label for="card-expiry-element">Expiration Date</label>
|
||||
<div id="card-expiry-element"></div>
|
||||
|
||||
<label for="card-cvc-element">CVC</label>
|
||||
<div id="card-cvc-element"></div>
|
||||
|
||||
<label for="card-postal-element">ZIP Code</label>
|
||||
<div id="card-postal-element"></div>
|
||||
|
||||
<button id="submit-button" type="submit">Pay <%=amount%> Now</button>
|
||||
</form>
|
||||
</div>
|
||||
<!-- Stripe.js -->
|
||||
<script src="https://js.stripe.com/v3/"></script>
|
||||
<script>
|
||||
// Initialize Stripe
|
||||
const stripe = Stripe("pk_test_51QZlMSCHHjDgpHosSrxdAEHgUCBmyhXCihiELaXjxcXzGtIY9Vw1YgOeiJfNpn7P9WkcMj5FWk13cDRavez3HhyN0001mNBtXW");
|
||||
|
||||
// Set up Stripe.js and Elements
|
||||
const elements = stripe.elements();
|
||||
const cardNumberElement = elements.create('cardNumber');
|
||||
const cardExpiryElement = elements.create('cardExpiry');
|
||||
const cardCvcElement = elements.create('cardCvc');
|
||||
const cardPostalElement = elements.create('postalCode');
|
||||
|
||||
cardNumberElement.mount('#card-number-element');
|
||||
cardExpiryElement.mount('#card-expiry-element');
|
||||
cardCvcElement .mount('#card-cvc-element');
|
||||
cardPostalElement.mount('#card-postal-element');
|
||||
|
||||
const paymentForm = document.getElementById("payment-form");
|
||||
paymentForm.addEventListener("submit", async (e) => {
|
||||
e.preventDefault();
|
||||
|
||||
// 1. Create a PaymentMethod
|
||||
const { paymentMethod, error } = await stripe.createPaymentMethod({
|
||||
type: "card",
|
||||
card: cardNumberElement,
|
||||
});
|
||||
|
||||
if (error) {
|
||||
console.error(error);
|
||||
alert(error.message);
|
||||
return;
|
||||
}
|
||||
|
||||
// 2. Send PaymentMethod ID to server
|
||||
const response = await fetch("/charge", {
|
||||
method: "POST",
|
||||
headers: { "Content-Type": "application/json" },
|
||||
body: JSON.stringify({ paymentMethodId: paymentMethod.id, ticket:"<%=ticket%>", amount:"<%=amount%>" }),
|
||||
});
|
||||
|
||||
const responseData = await response.json();
|
||||
|
||||
if (responseData.error) {
|
||||
console.error(responseData.error);
|
||||
alert(responseData.error);
|
||||
return;
|
||||
}
|
||||
|
||||
if (responseData.requiresAction) {
|
||||
// 3. Handle Additional Action if required (e.g., 3DS)
|
||||
const { error: confirmError } = await stripe.confirmCardPayment(
|
||||
responseData.paymentIntentClientSecret
|
||||
);
|
||||
|
||||
if (confirmError) {
|
||||
console.error(confirmError);
|
||||
alert(confirmError.message);
|
||||
return;
|
||||
}
|
||||
|
||||
alert("Payment succeeded");
|
||||
// redirect or show success message
|
||||
window.location.href = responseData.redirect_url;
|
||||
} else if (responseData.success) {
|
||||
// Payment succeeded without additional action
|
||||
alert("Payment succeeded.");
|
||||
window.location.href = responseData.redirect_url;
|
||||
}
|
||||
});
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
|
||||
Reference in New Issue
Block a user