This is the repository for a checkout web application; HackaWood, built with React and Express. The application uses the PayBox API, which allows business owners to receive payments online through MTN Mobile Money, Vodafone Cash, bank transactions and with a credit or debit card. The PayBox API provides more payment options such as cryptocurrency. The application is hosted on Heroku (view page).
- Visit the hosted site here.
- The home page shows items that have been added to the cart automatically.
- Click on "Proceed" to continue.
- You will be navigated to a page that asks you to choose your preferred payment method. The methods available are MTN Mobile Money, Vodafone Cash and AirtelTigo Money.
- You need to select a payment method before you can proceed.
- The next screen will show you a form corresponding to the payment method you selected before.
- With that you are done.
The application uses Express and Node as the backend and React for the front-end.
The communication with the PayBox API occurs on the backend. There are three routes in total which send post requests to PayBox based on the selected payment option. They are:
-
Card (/payment/card)
-
Mobile Money (/payment/mobile-money)
-
Bank (/payment/bank)
- The users payment credentials are sent to the backend as a JSON object.
- The data is decoded using the express body parser.
- The request package was used to send post requests from the express server.
// Express JSON body parser
app.use(express.json());
// Sending POST requests with "request"
const makeRequest = (req, res) => {
const requestPath = req.body.path;
const globalResponse = res;
request.post(
requestPath,
{
auth: {
bearer: process.env.PAY_BOX_TOKEN,
},
},
function completeRequest(err, res, body) {
if (err) {
globalResponse.status(400).end();
return;
}
globalResponse.status(200).end();
}
);
};
The request is authenticated using a bearer token.
Requests are sent to the express backend using the fetch API from the React front-end.
const useFetch = (setShowLoading, postUrl) => {
const history = useHistory();
const [, setShowSnackbar, , setSnackbarText] = useContext(SnackbarContext);
const [url, setUrl] = useState(null);
useEffect(() => {
// abort controller
const abortController = new AbortController();
if (url) {
fetch(postUrl, {
signal: abortController.signal,
method: "POST",
body: JSON.stringify({
path: url,
}),
headers: { "Content-Type": "application/json" },
})
.then((res) => {
if (res.ok) {
return res.text();
}
throw new Error("Could not complete transaction");
})
.then((_) => {
setShowLoading(false);
setSnackbarText("Transaction Complete");
setShowSnackbar(true);
history.push("/");
setUrl(null);
})
.catch((err) => {
setShowLoading(false);
setSnackbarText(err.message);
setShowSnackbar(true);
setUrl(null);
});
}
return () => abortController.abort();
}, [url]);
return setUrl;
};
The code above shows a custom Hook "useFetch". The Hook handles sending data to the backend and determining if the request was successful. The Hook requires two parameters "setShowLoading" and "postUrl". The first parameter is used to show or hide a loading widget. The second parameter is the URL that is used to access the PayBox API. The URL is built using the credentials the user entered and the mode of payment.
const handleBuildUrl = () => {
const orderId = (Math.random() * 1000).toFixed(0);
const closedCardNumber = cardNumber.split(" ").join("");
const closedCardExpiry = expirationDate.split(" ").join("");
return `https://www.paybox.com.co/pay?amount=20.99¤cy=GHS&mode=Card&card_type=${cardTypes[highlightCard]}&card_name=${cardHolder}&card_number=${closedCardNumber}&card_expiry=${closedCardExpiry}&card_cvc=${cvc}&payload={}&order_id=PB_${orderId}`;
};
The code above is specific to the card payment method.
- Work email: addodevelop@gmail.com
- School email: gerald.tetteh@ashesi.edu.gh
- Website
Fork this repository and clone it to your device. Then run the commands below.
cd Hackathon-Checkout
cd server && npm install
node app.js
cd .. && cd client && npm install
npm start