Files
alrahma_sunday_school_api/apps/api/dist/services/paypalService.js
T
2026-06-11 03:22:12 -04:00

111 lines
4.0 KiB
JavaScript

"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.createOrder = createOrder;
exports.captureOrder = captureOrder;
exports.refundCapture = refundCapture;
exports.verifyWebhookEvent = verifyWebhookEvent;
exports.isConfigured = isConfigured;
const BASE_URL = process.env.PAYPAL_BASE_URL ?? 'https://api-m.paypal.com';
const CLIENT_ID = process.env.PAYPAL_CLIENT_ID ?? '';
const CLIENT_SECRET = process.env.PAYPAL_CLIENT_SECRET ?? '';
let cachedToken = null;
async function getAccessToken() {
if (cachedToken && Date.now() < cachedToken.expiresAt - 30_000) {
return cachedToken.token;
}
const res = await fetch(`${BASE_URL}/v1/oauth2/token`, {
method: 'POST',
headers: {
'Content-Type': 'application/x-www-form-urlencoded',
Authorization: `Basic ${Buffer.from(`${CLIENT_ID}:${CLIENT_SECRET}`).toString('base64')}`,
},
body: 'grant_type=client_credentials',
});
if (!res.ok)
throw new Error('PayPal: failed to obtain access token');
const json = await res.json();
cachedToken = { token: json.access_token, expiresAt: Date.now() + json.expires_in * 1000 };
return cachedToken.token;
}
async function ppFetch(path, init) {
const token = await getAccessToken();
const res = await fetch(`${BASE_URL}${path}`, {
...init,
headers: {
'Content-Type': 'application/json',
Authorization: `Bearer ${token}`,
...(init?.headers ?? {}),
},
});
if (!res.ok) {
const err = await res.json().catch(() => ({}));
throw new Error(`PayPal ${path} failed: ${err?.message ?? res.statusText}`);
}
return res.json();
}
async function createOrder(params) {
const json = await ppFetch('/v2/checkout/orders', {
method: 'POST',
body: JSON.stringify({
intent: 'CAPTURE',
purchase_units: [
{
reference_id: params.orderId,
description: params.description,
amount: {
currency_code: params.currency,
value: (params.amount / 100).toFixed(2),
},
},
],
application_context: {
return_url: params.returnUrl,
cancel_url: params.cancelUrl,
brand_name: 'RentalDriveGo',
user_action: 'PAY_NOW',
},
}),
});
const approveLink = json.links?.find((l) => l.rel === 'approve');
return {
orderId: json.id,
approveUrl: approveLink?.href ?? '',
status: json.status,
};
}
async function captureOrder(paypalOrderId) {
return ppFetch(`/v2/checkout/orders/${paypalOrderId}/capture`, { method: 'POST', body: '{}' });
}
async function refundCapture(captureId, amount, currency, note) {
return ppFetch(`/v2/payments/captures/${captureId}/refund`, {
method: 'POST',
body: JSON.stringify({
amount: { currency_code: currency, value: (amount / 100).toFixed(2) },
note_to_payer: note,
}),
});
}
async function verifyWebhookEvent(headers, rawBody) {
try {
const json = await ppFetch('/v1/notifications/verify-webhook-signature', {
method: 'POST',
body: JSON.stringify({
auth_algo: headers['paypal-auth-algo'],
cert_url: headers['paypal-cert-url'],
transmission_id: headers['paypal-transmission-id'],
transmission_sig: headers['paypal-transmission-sig'],
transmission_time: headers['paypal-transmission-time'],
webhook_id: process.env.PAYPAL_WEBHOOK_ID ?? '',
webhook_event: JSON.parse(rawBody),
}),
});
return json.verification_status === 'SUCCESS';
}
catch {
return false;
}
}
function isConfigured() {
return !!(CLIENT_ID && CLIENT_SECRET && CLIENT_ID !== 'your-paypal-client-id');
}
//# sourceMappingURL=paypalService.js.map