Multi-Currency Implementation: - Add currency configuration with 10 supported currencies (NZD, USD, EUR, GBP, AUD, CAD, JPY, CHF, SGD, HKD) - Create client-side and server-side currency utilities for conversion and formatting - Implement currency selector UI component with auto-detection and localStorage persistence - Update Donation model to store multi-currency transactions with NZD equivalents - Update Koha service to handle currency conversion and exchange rate tracking - Update donation form UI to display prices in selected currency - Update transparency dashboard to show donations with currency indicators - Update Stripe setup documentation with currency_options configuration guide Privacy Policy: - Create comprehensive privacy policy page (GDPR compliant) - Add shared footer component with privacy policy link - Update all Koha pages with footer component Technical Details: - Exchange rates stored at donation time for historical accuracy - All donations tracked in both original currency and NZD for transparency - Base currency: NZD (New Zealand Dollar) - Uses Stripe currency_options for monthly subscriptions - Dynamic currency for one-time donations 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
12 KiB
Koha Donation System - Stripe Setup Guide
Project: Tractatus Framework Feature: Phase 3 - Koha (Donation) System Date: 2025-10-08 Status: Development
Overview
The Koha donation system uses the existing Stripe account from passport-consolidated to process donations in multiple currencies. This document guides you through setting up the required Stripe products and webhooks.
Account: Same Stripe test account as passport-consolidated
Currencies: 10 supported (NZD base + USD, EUR, GBP, AUD, CAD, JPY, CHF, SGD, HKD)
Payment Types: Recurring monthly subscriptions + one-time donations
Multi-Currency: Uses Stripe's currency_options feature for automatic conversion
1. Stripe Products to Create
Product: "Tractatus Framework Support"
Description: "Support the development and maintenance of the Tractatus AI Safety Framework. Your donation helps fund hosting, development, research, and community building."
Statement Descriptor: "TRACTATUS FRAMEWORK" Category: Charity/Non-profit
2. Price IDs to Create
2.1 Monthly Tier: $5 NZD/month
Product: Tractatus Framework Support
Price: $5.00 NZD
Billing: Recurring - Monthly
ID: price_<generated_by_stripe>
After creation, copy the Price ID and update .env:
STRIPE_KOHA_5_PRICE_ID=price_<your_actual_price_id>
2.2 Monthly Tier: $15 NZD/month
Product: Tractatus Framework Support
Price: $15.00 NZD
Billing: Recurring - Monthly
ID: price_<generated_by_stripe>
After creation, copy the Price ID and update .env:
STRIPE_KOHA_15_PRICE_ID=price_<your_actual_price_id>
2.3 Monthly Tier: $50 NZD/month
Product: Tractatus Framework Support
Price: $50.00 NZD
Billing: Recurring - Monthly
ID: price_<generated_by_stripe>
After creation, copy the Price ID and update .env:
STRIPE_KOHA_50_PRICE_ID=price_<your_actual_price_id>
2.4 One-Time Donation (Custom Amount)
Note: For one-time donations, we don't create a fixed price. Instead, the donation form sends a custom amount to Stripe Checkout. No Price ID needed for this - the code handles it dynamically.
2.5 Multi-Currency Setup with currency_options
IMPORTANT: To support multiple currencies with a single price ID, configure currency_options for each monthly tier price.
Method 1: Stripe Dashboard (Recommended)
- Go to your product → Select a price (e.g., $5 NZD/month)
- Click Add currency in the pricing section
- Add each supported currency with converted amounts:
| Base (NZD) | USD | EUR | GBP | AUD | CAD | JPY | CHF | SGD | HKD |
|---|---|---|---|---|---|---|---|---|---|
| $5.00 | $3.00 | €2.75 | £2.35 | $4.65 | $4.10 | ¥470 | 2.65 | $4.05 | $23.40 |
| $15.00 | $9.00 | €8.25 | £7.05 | $13.95 | $12.30 | ¥1410 | 7.95 | $12.15 | $70.20 |
| $50.00 | $30.00 | €27.50 | £23.50 | $46.50 | $41.00 | ¥4700 | 26.50 | $40.50 | $234.00 |
- Repeat for all three monthly tier prices
Method 2: Stripe API
Update existing prices via Stripe API:
stripe prices update price_YOUR_5_NZD_PRICE_ID \
--currency-options[usd][unit_amount]=300 \
--currency-options[eur][unit_amount]=275 \
--currency-options[gbp][unit_amount]=235 \
--currency-options[aud][unit_amount]=465 \
--currency-options[cad][unit_amount]=410 \
--currency-options[jpy][unit_amount]=470 \
--currency-options[chf][unit_amount]=265 \
--currency-options[sgd][unit_amount]=405 \
--currency-options[hkd][unit_amount]=2340
Repeat for $15 and $50 tier prices with their corresponding amounts.
Exchange Rate Calculation
Our base currency is NZD. Exchange rates (as of 2025-10-08):
1 NZD = 0.60 USD = 0.55 EUR = 0.47 GBP = 0.93 AUD = 0.82 CAD
= 94.0 JPY = 0.53 CHF = 0.81 SGD = 4.68 HKD
Note: Rates are configurable in src/config/currencies.config.js. Update periodically or integrate live exchange rate API.
One-Time Donations (Dynamic Currency)
For one-time donations, the code dynamically creates Stripe checkout sessions with the selected currency:
sessionParams.line_items = [{
price_data: {
currency: currentCurrency.toLowerCase(), // e.g., 'usd', 'eur'
unit_amount: amount // Amount in cents/smallest currency unit
}
}];
No additional configuration needed - Stripe handles any supported currency.
3. Webhook Configuration
Create Webhook Endpoint
URL (Development):
http://localhost:9000/api/koha/webhook
URL (Production):
https://agenticgovernance.digital/api/koha/webhook
Events to Subscribe To
Select these events in Stripe Dashboard:
- ✅
checkout.session.completed - ✅
payment_intent.succeeded - ✅
payment_intent.payment_failed - ✅
invoice.paid(recurring payments) - ✅
invoice.payment_failed - ✅
customer.subscription.created - ✅
customer.subscription.updated - ✅
customer.subscription.deleted
After Creating Webhook
Copy the Webhook Signing Secret and update .env:
STRIPE_KOHA_WEBHOOK_SECRET=whsec_<your_webhook_secret>
4. Testing Configuration
Stripe Test Cards
Use these test cards for development:
| Card Number | Scenario |
|---|---|
| 4242 4242 4242 4242 | Successful payment |
| 4000 0027 6000 3184 | 3D Secure required |
| 4000 0000 0000 9995 | Payment declined |
| 4000 0000 0000 0341 | Attaching card fails |
Expiry: Any future date CVC: Any 3 digits ZIP: Any valid postal code
5. Step-by-Step Setup Instructions
Step 1: Access Stripe Dashboard
- Go to dashboard.stripe.com
- Ensure you're in Test Mode (toggle in top-right)
- Log in with passport-consolidated credentials
Step 2: Create Product
- Navigate to Products → Add Product
- Product name:
Tractatus Framework Support - Description:
Support the development and maintenance of the Tractatus AI Safety Framework - Image: Upload
/home/theflow/projects/tractatus/public/images/tractatus-icon.svg - Click Save Product
Step 3: Create Price IDs
For each monthly tier ($5, $15, $50):
- In the product page, click Add another price
- Select Recurring
- Billing period: Monthly
- Price: Enter amount (e.g., 5.00)
- Currency: NZD
- Click Save
- Copy the Price ID (starts with
price_) - Paste into
.envfile
Step 4: Set Up Webhook
- Navigate to Developers → Webhooks
- Click Add endpoint
- Endpoint URL:
http://localhost:9000/api/koha/webhook(for development) - Description:
Tractatus Koha - Development - Events to send: Select all 8 events listed in Section 3
- Click Add endpoint
- Copy the Signing Secret (click "Reveal")
- Update
.envwith the webhook secret
Step 5: Verify Configuration
Run this command to test:
npm run dev
Check logs for:
✅ Stripe webhook ready: /api/koha/webhook
✅ Koha service initialized
6. Environment Variables Checklist
After setup, your .env should have:
# Stripe Keys (from passport-consolidated)
STRIPE_SECRET_KEY=sk_test_51RX67k...
STRIPE_PUBLISHABLE_KEY=pk_test_51RX67k...
# Webhook Secret (from Step 4)
STRIPE_KOHA_WEBHOOK_SECRET=whsec_...
# Price IDs (from Step 3)
STRIPE_KOHA_5_PRICE_ID=price_...
STRIPE_KOHA_15_PRICE_ID=price_...
STRIPE_KOHA_50_PRICE_ID=price_...
# Frontend URL
FRONTEND_URL=http://localhost:9000
7. Testing the Integration
Test API Endpoint
Test 1: Monthly donation in NZD
curl -X POST http://localhost:9000/api/koha/checkout \
-H "Content-Type: application/json" \
-d '{
"amount": 1500,
"currency": "NZD",
"frequency": "monthly",
"tier": "15",
"donor": {
"name": "Test Donor",
"email": "test@example.com"
},
"public_acknowledgement": false
}'
Test 2: One-time donation in USD
curl -X POST http://localhost:9000/api/koha/checkout \
-H "Content-Type: application/json" \
-d '{
"amount": 2500,
"currency": "USD",
"frequency": "one_time",
"tier": "custom",
"donor": {
"name": "US Donor",
"email": "us@example.com"
},
"public_acknowledgement": true,
"public_name": "Anonymous US Supporter"
}'
Expected Response:
{
"success": true,
"data": {
"sessionId": "cs_test_...",
"checkoutUrl": "https://checkout.stripe.com/c/pay/cs_test_...",
"frequency": "monthly",
"amount": 15
}
}
Test Webhook Locally
Use Stripe CLI for local webhook testing:
# Install Stripe CLI
brew install stripe/stripe-cli/stripe
# Forward webhooks to local server
stripe listen --forward-to localhost:9000/api/koha/webhook
# Trigger test event
stripe trigger checkout.session.completed
8. Production Setup
Before Going Live
- Switch to Live Mode in Stripe Dashboard
- Create live webhook endpoint:
- URL:
https://agenticgovernance.digital/api/koha/webhook - Same 8 events as development
- URL:
- Obtain live API keys (starts with
sk_live_andpk_live_) - Update production .env with live keys
- Test with real card (small amount)
- Verify webhook delivery in Stripe Dashboard
Production Environment Variables
NODE_ENV=production
STRIPE_SECRET_KEY=sk_live_...
STRIPE_PUBLISHABLE_KEY=pk_live_...
STRIPE_KOHA_WEBHOOK_SECRET=whsec_live_...
FRONTEND_URL=https://agenticgovernance.digital
9. Monitoring & Troubleshooting
Check Webhook Deliveries
- Stripe Dashboard → Developers → Webhooks
- Click on your endpoint
- View Recent deliveries
- Check for failed deliveries (red icons)
Common Issues
| Issue | Solution |
|---|---|
| Webhook signature verification fails | Ensure STRIPE_KOHA_WEBHOOK_SECRET matches Dashboard |
| Price ID not found | Verify Price IDs in .env match Stripe Dashboard |
| Redirects fail after payment | Check FRONTEND_URL is correct |
| Donations not recording | Check MongoDB connection and logs |
Debug Logging
Enable detailed Stripe logs:
# In koha.service.js, logger.info statements will show:
[KOHA] Creating checkout session: monthly donation of USD $9.00 (NZD $15.00)
[KOHA] Checkout session created: cs_test_...
[KOHA] Processing webhook event: checkout.session.completed
[KOHA] Checkout completed: monthly donation, tier: 15, currency: USD
[KOHA] Donation recorded: USD $9.00 (NZD $15.00)
[KOHA] Recurring donation recorded: EUR $8.25 (NZD $15.00)
10. Security Considerations
Webhook Security
- ✅ Signature verification enabled (via
verifyWebhookSignature) - ✅ Raw body parsing for Stripe webhooks
- ✅ HTTPS required in production
- ✅ Rate limiting on API endpoints
Data Privacy
- ✅ Donor emails stored securely (for receipts only)
- ✅ Anonymous donations by default
- ✅ Opt-in public acknowledgement
- ✅ No credit card data stored (handled by Stripe)
PCI Compliance
- ✅ Using Stripe Checkout (PCI compliant)
- ✅ No card data touches our servers
- ✅ Stripe handles all payment processing
11. Next Steps
After completing this setup:
- ✅ Test donation flow end-to-end
- ✅ Create frontend donation form UI
- ✅ Build transparency dashboard
- ✅ Implement receipt email generation
- ✅ Add donor acknowledgement system
- ⏳ Deploy to production
Support
Issues: Report in GitHub Issues Questions: Contact john.stroh.nz@pm.me Stripe Docs: https://stripe.com/docs/api
Last Updated: 2025-10-08 Version: 1.0 Status: Ready for setup