Milehigh.world is a dynamic and inclusive platform that celebrates the art of music, connects musicians worldwide, and provides a supportive environment for learning, inspiration, and collaboration. Whether you're a singer, songwriter, instrumentalist, producer, or music lover, it offers a space to share your passion, grow your skills, and network
@see https://developer.paypal.com/docs/api/orders/v2/#orders_create
*/
const createOrder = async (cart) => {
// use the cart information passed from the front-end to calculate the purchase unit details
console.log(
"shopping cart information passed from the frontend createOrder() callback:",
cart,
);
import express from "express"; import fetch from "node-fetch"; import "dotenv/config"; import path from "path";
const { PAYPAL_CLIENT_ID, PAYPAL_CLIENT_SECRET, PORT = 8888 } = process.env; const base = "https://api-m.sandbox.paypal.com"; const app = express();
app.use(express.static("client/dist")); // parse post params sent in body in json format app.use(express.json());
/**
@see https://developer.paypal.com/api/rest/authentication/ */ const generateAccessToken = async () => { try { if (!PAYPAL_CLIENT_ID || !PAYPAL_CLIENT_SECRET) { throw new Error("MISSING_API_CREDENTIALS"); } const auth = Buffer.from( PAYPAL_CLIENT_ID + ":" + PAYPAL_CLIENT_SECRET, ).toString("base64"); const response = await fetch(
${base}/v1/oauth2/token
, { method: "POST", body: "grant_type=client_credentials", headers: { Authorization:Basic ${auth}
, }, });const data = await response.json(); return data.access_token; } catch (error) { console.error("Failed to generate Access Token:", error); } };
/**
@see https://developer.paypal.com/docs/checkout/advanced/integrate/#link-integratebackend */ const generateClientToken = async () => { const accessToken = await generateAccessToken(); const url =
${base}/v1/identity/generate-token
; const response = await fetch(url, { method: "POST", headers: { Authorization:Bearer ${accessToken}
, "Accept-Language": "en_US", "Content-Type": "application/json", }, });return handleResponse(response); };
/**
@see https://developer.paypal.com/docs/api/orders/v2/#orders_create */ const createOrder = async (cart) => { // use the cart information passed from the front-end to calculate the purchase unit details console.log( "shopping cart information passed from the frontend createOrder() callback:", cart, );
const accessToken = await generateAccessToken(); const url =
${base}/v2/checkout/orders
; const payload = { intent: "CAPTURE", purchase_units: [ { amount: { currency_code: "USD", value: "100.00", }, }, ], };const response = await fetch(url, { headers: { "Content-Type": "application/json", Authorization:
Bearer ${accessToken}
, // Uncomment one of these to force an error for negative testing (in sandbox mode only). Documentation: // https://developer.paypal.com/tools/sandbox/negative-testing/request-headers/ // "PayPal-Mock-Response": '{"mock_application_codes": "MISSING_REQUIRED_PARAMETER"}' // "PayPal-Mock-Response": '{"mock_application_codes": "PERMISSION_DENIED"}' // "PayPal-Mock-Response": '{"mock_application_codes": "INTERNAL_SERVER_ERROR"}' }, method: "POST", body: JSON.stringify(payload), });return handleResponse(response); };
/**
@see https://developer.paypal.com/docs/api/orders/v2/#orders_capture */ const captureOrder = async (orderID) => { const accessToken = await generateAccessToken(); const url =
${base}/v2/checkout/orders/${orderID}/capture
;const response = await fetch(url, { method: "POST", headers: { "Content-Type": "application/json", Authorization:
Bearer ${accessToken}
, // Uncomment one of these to force an error for negative testing (in sandbox mode only). Documentation: // https://developer.paypal.com/tools/sandbox/negative-testing/request-headers/ // "PayPal-Mock-Response": '{"mock_application_codes": "INSTRUMENT_DECLINED"}' // "PayPal-Mock-Response": '{"mock_application_codes": "TRANSACTION_REFUSED"}' // "PayPal-Mock-Response": '{"mock_application_codes": "INTERNAL_SERVER_ERROR"}' }, });return handleResponse(response); };
async function handleResponse(response) { try { const jsonResponse = await response.json(); return { jsonResponse, httpStatusCode: response.status, }; } catch (err) { const errorMessage = await response.text(); throw new Error(errorMessage); } }
// serve index.html app.get("/", (req, res) => { res.sendFile(path.resolve("./client/dist/index.html")); });
// return client token for hosted-fields component app.post("/api/token", async (req, res) => { try { const { jsonResponse, httpStatusCode } = await generateClientToken(); res.status(httpStatusCode).json(jsonResponse); } catch (error) { console.error("Failed to generate client token:", error); res.status(500).send({ error: "Failed to generate client token." }); } });
app.post("/api/orders", async (req, res) => { try { // use the cart information passed from the front-end to calculate the order amount detals const { cart } = req.body; const { jsonResponse, httpStatusCode } = await createOrder(cart); res.status(httpStatusCode).json(jsonResponse); } catch (error) { console.error("Failed to create order:", error); res.status(500).json({ error: "Failed to create order." }); } });
app.post("/api/orders/:orderID/capture", async (req, res) => { try { const { orderID } = req.params; const { jsonResponse, httpStatusCode } = await captureOrder(orderID); res.status(httpStatusCode).json(jsonResponse); } catch (error) { console.error("Failed to create order:", error); res.status(500).json({ error: "Failed to capture order." }); } });
app.listen(PORT, () => { console.log(
Node server listening at http://localhost:${PORT}/
); });