Monorepo for Aesthetic.Computer aesthetic.computer
4
fork

Configure Feed

Select the types of activity you want to include in your feed.

at main 159 lines 4.9 kB view raw view rendered
1# PayPal Integration Plan 2 3## Overview 4Integrate PayPal as a payment option on the give page (give.aesthetic.computer) alongside existing USD (Stripe), DKK, and Crypto options. 5 6## Account Details 7- **PayPal Account**: mail@aesthetic.computer 8- **API Environment**: Production (api-m.paypal.com) 9 10## Credentials Storage 11| Location | Purpose | 12|----------|---------| 13| `aesthetic-computer-vault/.env` | Local development, secure storage | 14| MongoDB secrets collection | Netlify functions runtime access | 15 16### Environment Variables 17``` 18PAYPAL_CLIENT_ID=<stored in vault> 19PAYPAL_CLIENT_SECRET=<stored in vault> 20PAYPAL_API_URL=https://api-m.paypal.com 21``` 22 23## API Architecture 24 25### PayPal Orders API v2 26- **Auth**: OAuth 2.0 (Client ID + Secret → Bearer Token) 27- **Create Order**: `POST /v2/checkout/orders` 28- **Capture Payment**: `POST /v2/checkout/orders/{id}/capture` 29 30### Flow 31``` 321. User selects amount on give page 332. Frontend calls /api/paypal (Netlify function) 343. paypal.mjs creates order via PayPal API 354. Returns approval URL 365. User redirected to PayPal to approve 376. PayPal redirects back to give.aesthetic.computer?paypal_success=1 387. Frontend calls /api/paypal/capture with order ID 398. paypal.mjs captures payment 40``` 41 42## Implementation Checklist 43 44### ✅ Completed 45- [x] PayPal tab in currency selector 46- [x] PayPal section UI (header, button, email) 47- [x] PayPal.me direct link button 48- [x] Copyable email address 49- [x] Multi-language support (EN, DA, DE, ES, ZH) 50- [x] PayPal QR code integration 51- [x] CSS styling (blue theme #0070ba) 52- [x] Give button "PP" cycling 53- [x] Credentials stored in vault 54 55### 🔄 In Progress 56- [ ] paypal.mjs Netlify endpoint 57- [ ] MongoDB secrets sync 58 59### ❌ Not Started 60- [ ] Custom amount input (like Stripe) 61- [ ] Payment capture flow 62- [ ] Success/failure handling on redirect 63- [ ] Transaction logging 64 65## Netlify Function: paypal.mjs 66 67### Endpoints 68```javascript 69// Create order 70POST /api/paypal 71Body: { amount: "10.00", currency: "USD" } 72Returns: { id: "ORDER_ID", approval_url: "https://paypal.com/..." } 73 74// Capture payment (optional, if using redirect flow) 75POST /api/paypal/capture 76Body: { order_id: "ORDER_ID" } 77Returns: { status: "COMPLETED", ... } 78``` 79 80### Implementation Pattern 81```javascript 82// Follow give.js pattern 83import { MongoClient } from "mongodb"; 84 85const getSecrets = async () => { 86 const client = await MongoClient.connect(process.env.MONGODB_URI); 87 const db = client.db("aesthetic"); 88 return db.collection("secrets").findOne({ name: "paypal" }); 89}; 90 91const getAccessToken = async (clientId, clientSecret) => { 92 const response = await fetch("https://api-m.paypal.com/v1/oauth2/token", { 93 method: "POST", 94 headers: { 95 Authorization: `Basic ${Buffer.from(`${clientId}:${clientSecret}`).toString("base64")}`, 96 "Content-Type": "application/x-www-form-urlencoded", 97 }, 98 body: "grant_type=client_credentials", 99 }); 100 const data = await response.json(); 101 return data.access_token; 102}; 103 104const createOrder = async (accessToken, amount, currency = "USD") => { 105 const response = await fetch("https://api-m.paypal.com/v2/checkout/orders", { 106 method: "POST", 107 headers: { 108 Authorization: `Bearer ${accessToken}`, 109 "Content-Type": "application/json", 110 }, 111 body: JSON.stringify({ 112 intent: "CAPTURE", 113 purchase_units: [{ 114 amount: { 115 currency_code: currency, 116 value: amount, 117 }, 118 description: "Aesthetic Computer Contribution", 119 }], 120 application_context: { 121 return_url: "https://give.aesthetic.computer?paypal_success=1", 122 cancel_url: "https://give.aesthetic.computer?paypal_cancel=1", 123 brand_name: "Aesthetic Computer", 124 user_action: "PAY_NOW", 125 }, 126 }), 127 }); 128 return response.json(); 129}; 130``` 131 132## Limitations 133- **No Monthly Subscriptions**: Orders API is one-time only 134 - Would need PayPal Subscriptions API for recurring 135 - User acknowledged this is acceptable 136- **Currency Support**: USD, EUR, GBP, etc. (no DKK via PayPal API) 137 138## QR Code 139- **Asset URL**: `https://assets.aesthetic.computer/images/paypal-qrcode.png` 140- **Links to**: PayPal.me/aestheticcomputer 141- **Purpose**: Quick mobile scanning for donations 142 143## Security Notes 1441. Never commit credentials to main repo 1452. Use vault for local dev 1463. Use MongoDB secrets for production 1474. Rotate credentials periodically 1485. Monitor for unauthorized transactions 149 150## Testing 1511. Use PayPal Sandbox for development testing 1522. Create sandbox accounts at developer.paypal.com 1533. Test with small amounts ($0.01) in production 154 155## Related Files 156- `system/public/give.aesthetic.computer/index.html` - Give page UI 157- `system/netlify/functions/give.js` - Stripe endpoint (reference) 158- `system/netlify/functions/paypal.mjs` - PayPal endpoint (to create) 159- `aesthetic-computer-vault/.env` - Credentials storage