archetecture security fix
This commit is contained in:
+111
@@ -0,0 +1,111 @@
|
||||
"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
|
||||
Reference in New Issue
Block a user