managarten/apps-archived/bauntown/apps/landing/netlify/functions/create-paypal-order.js
Till-JS 61d181fbc2 chore: archive inactive projects to apps-archived/
Move inactive projects out of active workspace:
- bauntown (community website)
- maerchenzauber (AI story generation)
- memoro (voice memo app)
- news (news aggregation)
- nutriphi (nutrition tracking)
- reader (reading app)
- uload (URL shortener)
- wisekeep (AI wisdom extraction)

Update CLAUDE.md documentation:
- Add presi to active projects
- Document archived projects section
- Update workspace configuration

Archived apps can be re-activated by moving back to apps/

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-29 07:03:59 +01:00

152 lines
3.7 KiB
JavaScript

// Netlify Function für PayPal Order
// Erfordert PAYPAL_CLIENT_ID und PAYPAL_CLIENT_SECRET als Umgebungsvariablen
const fetch = require('node-fetch');
// PayPal OAuth Token holen
async function getPayPalAccessToken() {
const auth = Buffer.from(
`${process.env.PAYPAL_CLIENT_ID}:${process.env.PAYPAL_CLIENT_SECRET}`
).toString('base64');
const response = await fetch('https://api-m.sandbox.paypal.com/v1/oauth2/token', {
method: 'POST',
headers: {
'Content-Type': 'application/x-www-form-urlencoded',
Authorization: `Basic ${auth}`,
},
body: 'grant_type=client_credentials',
});
const data = await response.json();
return data.access_token;
}
// PayPal Order erstellen
async function createPayPalOrder(accessToken, amount, isRecurring, priceId, coffeeSize) {
const url = isRecurring
? 'https://api-m.sandbox.paypal.com/v1/billing/plans'
: 'https://api-m.sandbox.paypal.com/v2/checkout/orders';
if (isRecurring) {
// Vereinfachtes Beispiel für ein Abonnement
// In einer echten Anwendung sollten Sie Pläne vorab erstellen
const planData = {
name: `BaunTown Monthly ${coffeeSize}`,
description: `Monthly ${coffeeSize} support for BaunTown (${amount}€)`,
type: 'FIXED',
payment_definitions: [
{
name: `Monthly ${coffeeSize}`,
type: 'REGULAR',
frequency: 'MONTH',
frequency_interval: '1',
amount: {
value: amount,
currency: 'EUR',
},
cycles: '0',
},
],
merchant_preferences: {
return_url: `${process.env.URL || 'http://localhost:3000'}/support-success`,
cancel_url: `${process.env.URL || 'http://localhost:3000'}/support-cancel`,
},
};
const response = await fetch(url, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
Authorization: `Bearer ${accessToken}`,
},
body: JSON.stringify(planData),
});
return response.json();
} else {
// Normale einmalige Zahlung
const orderData = {
intent: 'CAPTURE',
purchase_units: [
{
amount: {
currency_code: 'EUR',
value: amount,
},
description: `${coffeeSize} für BaunTown (${amount}€)`,
custom_id: priceId,
},
],
application_context: {
return_url: `${process.env.URL || 'http://localhost:3000'}/support-success?amount=${amount}&type=${isRecurring ? 'recurring' : 'one-time'}&provider=paypal&coffeeSize=${encodeURIComponent(coffeeSize)}`,
cancel_url: `${process.env.URL || 'http://localhost:3000'}/support-cancel`,
},
};
const response = await fetch(url, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
Authorization: `Bearer ${accessToken}`,
},
body: JSON.stringify(orderData),
});
return response.json();
}
}
exports.handler = async (event, context) => {
// CORS Headers
const headers = {
'Access-Control-Allow-Origin': '*',
'Access-Control-Allow-Headers': 'Content-Type',
'Access-Control-Allow-Methods': 'POST, OPTIONS',
};
// Handle OPTIONS request (CORS preflight)
if (event.httpMethod === 'OPTIONS') {
return {
statusCode: 200,
headers,
body: '',
};
}
try {
// Request-Body parsen
const data = JSON.parse(event.body);
const { amount, isRecurring, priceId, coffeeSize } = data;
// PayPal Access Token holen
const accessToken = await getPayPalAccessToken();
// Order oder Plan erstellen mit zusätzlichen Metadaten
const paypalResponse = await createPayPalOrder(
accessToken,
amount,
isRecurring,
priceId,
coffeeSize
);
return {
statusCode: 200,
headers,
body: JSON.stringify(paypalResponse),
};
} catch (error) {
console.error('PayPal error:', error);
return {
statusCode: 500,
headers,
body: JSON.stringify({
error: {
message: error.message || 'Internal server error',
},
}),
};
}
};