import express from "express";
import fetch from "node-fetch";
const app = express();
app.use(express.json());
const PAYPAL_BASE = process.env.PAYPAL_BASE || "https://api-m.sandbox.paypal.com"; // use api-m.paypal.com in prod
const CLIENT_ID = process.env.PAYPAL_CLIENT_ID;
const CLIENT_SECRET = process.env.PAYPAL_CLIENT_SECRET;
async function appAccessToken(formBody) {
const creds = Buffer.from(`${CLIENT_ID}:${CLIENT_SECRET}`).toString("base64");
const res = await fetch(`${PAYPAL_BASE}/v1/oauth2/token`, {
method: "POST",
headers: {
"Authorization": `Basic ${creds}`,
"Content-Type": "application/x-www-form-urlencoded",
},
body: formBody,
});
const json = await res.json();
return json.access_token;
}
// 1) Return browser-safe client token
app.get("/paypal-api/auth/browser-safe-client-token", async (_req, res) => {
try {
const sdkClientTokenFormBody = "grant_type=client_credentials&response_type=client_token&intent=sdk_init"
const {
access_token
} = await appAccessToken(sdkClientTokenFormBody);
res.json({
clientToken: access_token
});
} catch (e) {
console.error(e);
res.status(500).json({
error: "client_token_error"
});
}
});
// 2) Create order with sample purchase units
app.post("/paypal-api/checkout/orders/create-with-sample-data", async (_req, res) => {
try {
const fullScopeAccessTokenFormBody = "grant_type=client_credentials&response_type=token"
const accessToken = await appAccessToken(fullScopeAccessTokenFormBody);
const r = await fetch(`${PAYPAL_BASE}/v2/checkout/orders`, {
method: "POST",
headers: {
"Content-Type": "application/json",
Authorization: `Bearer ${accessToken}`,
},
body: JSON.stringify({
intent: "CAPTURE",
purchase_units: [{
amount: {
currency_code: "USD",
value: "10.00"
},
}, ],
}),
});
const data = await r.json();
res.json({
id: data.id
});
} catch (e) {
console.error(e);
res.status(500).json({
error: "order_create_error"
});
}
});
// 3) Capture order
app.post("/paypal-api/checkout/orders/:orderId/capture", async (req, res) => {
try {
const fullScopeAccessTokenFormBody = "grant_type=client_credentials&response_type=token"
const accessToken = await appAccessToken(fullScopeAccessTokenFormBody);
const r = await fetch(`${PAYPAL_BASE}/v2/checkout/orders/${req.params.orderId}/capture`, {
method: "POST",
headers: {
"Content-Type": "application/json",
Authorization: `Bearer ${accessToken}`,
},
});
const data = await r.json();
res.json(data);
} catch (e) {
console.error(e);
res.status(500).json({
error: "order_capture_error"
});
}
});
app.listen(3000, () => console.log("Server listening on 3000"));