Skip to content

Instantly share code, notes, and snippets.

@cblair
Created June 20, 2024 16:21
Show Gist options
  • Save cblair/3bd372c6cccd558407640e090ea5a328 to your computer and use it in GitHub Desktop.
Save cblair/3bd372c6cccd558407640e090ea5a328 to your computer and use it in GitHub Desktop.
const express = require('express');
const app = express();
const port = 4000;
// Payments
// In the real world, we would use a real database like Postgres or MongoDB. Just in memory for the sake of this example.
const payments = {};
/** POST /payment - Create a payment.
* @typedef Payment
* @property {number} amount - The amount of the payment.
* @property {string} fullName - The full name on the card.
* @property {string} exp - The expiration date.
* @property {string} ccv - The ccv.
* @property {string} cardNumber - The last 4 digits of the card number.
*
*/
app.post('/payment', async (req, res) => {
const { amount, fullName, cardNumber, exp, ccv } = req.body;
const id = uuidv4();
payments[id] = { amount, fullName, exp, ccv, ccLast4: filterCreditCardNumber(cardNumber),
// Only store this token until we run the charge, then delete.
token: getPaymentToken()
};
// Asynchronous token retrieval; more performant, but more complex to keep our data consistent.
// getPaymentToken.then(token => {
// payments[id].token = token;
// });
// Syncronous token retrieval; less performant, but simpler to keep our data consistent.
await getPaymentToken(amount, fullName, cardNumber, exp, ccv)
.then(token => {
payments[id].token = token;
res.status(201).json({id});
})
.catch(err => {
// Ping oncall
// i.e. Bugsnag.notify(err) or Sentry
res.status(500).json({error: 'Failed to get payment token'});
});
});
/** GET /payment - Get all payments.
*
*/
app.get('/payment', (req, res) => {
const paymentsArray = Object.entries(payments).map(({token, ...props}) => ({ ...props }));
res.json({payments: paymentsArray});
});
function filterCreditCardNumber() {
const last4Digits = cardNumber.slice(-4);
return last4Digits;
}
/**
* Get a payment token from the payment processor. Token then can be used to charge card later.
*
* @param {number} amount - The amount to charge.
* @param {string} fullName - The full name on the card.
* @param {string} cardNumber - The card number.
* @param {string} exp - The expiration date.
* @param {string} ccv - The ccv.
* @returns {Promise<string>} - The payment token.
*/
async function getPaymentToken(amount, fullName, cardNumber, exp, ccv) {
// Fake; in real life, we would call the payment processor's API like Stripe.
return uuidv4();
};
// Start the app.
app.listen(port, () => {});
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment