Created
June 20, 2024 16:21
-
-
Save cblair/3bd372c6cccd558407640e090ea5a328 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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