Setup Summary
Choose the configuration that matches your deployment scenario. Each setup type has a concise checklist to get you operational quickly.
Self-Hosted — Single Tenant
Your organisation deploys its own instance with custom branding on a private domain.
- Clone or download the repository.
- Set
VITE_TENANT_ID=your-organisationin your environment. - Add your Merchant Warrior credentials:
VITE_YOUR_MW_MERCHANT_UUID
VITE_YOUR_MW_API_KEY
VITE_YOUR_MW_PASSPHRASE - Set production gateway URLs:
VITE_YOUR_MW_PAYFRAME_JS_URL
VITE_YOUR_MW_PAYFRAME_URL
VITE_YOUR_MW_SUBMIT_URL - Configure EmailJS variables (optional):
VITE_YOUR_EMAILJS_SERVICE_ID
VITE_YOUR_EMAILJS_PUBLIC_KEY
VITE_YOUR_ADMIN_EMAIL - Run
npm run buildand deploy to your domain. - Test with a live payment.
securetest.merchantwarrior.com URLs during testing and switch to secure.merchantwarrior.com for production.Multi-Tenant SaaS Hosting
One deployment serves multiple organisations, each with its own merchant account, branding, and email configuration.
- Add a tenant configuration block for each organisation in
src/config/tenantConfig.ts. - In your hosting platform (Netlify, Vercel, etc.) set all tenant-prefixed environment variables (e.g.,
VITE_ALTIMA_MW_MERCHANT_UUID,VITE_CHARITY_MW_MERCHANT_UUID, …). - Configure DNS: either wildcard CNAME (
*.yourgateway.com) or path-based routing. - Run a single
npm run build— all tenants share the same build. - Verify each tenant via URL parameter:
?tenant=your-tenant-id - Test emails and payment processing for every tenant before go-live.
Application Integration
Embed payment processing into an existing web application by redirecting to the gateway and handling the return URL.
- Ensure the gateway is running (any scenario above).
- Build a redirect URL with URL parameters:
?tenant=&amount=&name=&email=&phone=&address=&city=&postcode=&return_url= - Redirect the user to the gateway URL.
- On your return page, read
payment_status,transaction_id, andamountfrom the query string. - Update your application state accordingly.
Development & Testing
Run locally against the Merchant Warrior test environment to develop and verify before going live.
- Clone the repository.
- Run
npm install. - Copy
.env.exampleto.env. - Leave test credentials as-is (safe defaults are already in the code).
- Confirm test URLs are set:
VITE_MW_PAYFRAME_JS_URL=https://securetest.merchantwarrior.com/payframe/payframe.js - Run
npm run devand openlocalhost:5173. - Use the TenantSelector UI to switch between tenant configurations.
- Test using Merchant Warrior's published test card numbers.
Environment Variable Quick Reference
All tenant environment variable names follow the pattern VITE_{TENANT_PREFIX}_{KEY} where the tenant prefix matches the tenant configuration block identifier (converted to uppercase, hyphens replaced with underscores).
| Variable Pattern | Purpose | Required |
|---|---|---|
VITE_{PREFIX}_MW_MERCHANT_UUID | Merchant Warrior merchant UUID | Yes |
VITE_{PREFIX}_MW_API_KEY | Merchant Warrior API key | Yes |
VITE_{PREFIX}_MW_PASSPHRASE | Merchant Warrior passphrase (for hash) | Yes |
VITE_{PREFIX}_MW_PAYFRAME_JS_URL | PayFrame JS library URL | Yes |
VITE_{PREFIX}_MW_PAYFRAME_URL | PayFrame iFrame URL | Yes |
VITE_{PREFIX}_MW_SUBMIT_URL | Transaction submission URL | Yes |
VITE_{PREFIX}_EMAILJS_SERVICE_ID | EmailJS service identifier | Optional |
VITE_{PREFIX}_EMAILJS_PUBLIC_KEY | EmailJS public key | Optional |
VITE_{PREFIX}_EMAILJS_USER_SUCCESS_TEMPLATE_ID | Customer success email template | Optional |
VITE_{PREFIX}_EMAILJS_USER_FAILURE_TEMPLATE_ID | Customer failure email template | Optional |
VITE_{PREFIX}_EMAILJS_ADMIN_NOTIFICATION_TEMPLATE_ID | Admin notification template | Optional |
VITE_{PREFIX}_ADMIN_EMAIL | Admin email address for notifications | Optional |
VITE_{PREFIX}_EXCHANGE_RATE_API_KEY | exchangeratesapi.io key (VATU conversion) | Optional |
VITE_TENANT_ID | Force a specific tenant (self-hosting) | Self-host only |
securetest.merchantwarrior.com / base.merchantwarrior.com. Production — secure.merchantwarrior.com / api.merchantwarrior.com.Overview & Features
Altima Pay is a modern, secure payment gateway built on Merchant Warrior PayFrame. It provides full multi-tenant support, enabling a single deployment to serve unlimited organisations with completely separate configurations, merchant accounts, and branding.
Live Demo & Tenant Reference
The application is deployed at:
| Tenant | Example URL | Features | Status |
|---|---|---|---|
| Default | /?amount=50.00 |
Test credentials, basic features | Demo |
| Altima Community | /?tenant=altima-community&vatu=5000 |
VATU converter, community branding | Live |
| Gotoogle Pty Ltd | /?tenant=gotoogle&amount=100.00 |
Corporate branding, AUD payments | Live |
| Freshwater Plantation Aore | /?tenant=freshwater-aore&vatu=10000 |
VATU converter, hospitality branding | Live |
| StarFish Beach Bar Santo | /?tenant=starfish-santo&vatu=7500 |
VATU converter, beach bar branding | Live |
| Altima Linux | /?tenant=altima-linux&amount=150.00 |
Tech branding, AUD only | Live |
| Charity Network | /?tenant=charity-donations&amount=25.00 |
Charity branding, demo credentials | Demo |
| Education Foundation | /?tenant=education-foundation&amount=75.00 |
Education branding, demo credentials | Demo |
Key Features
Multi-Tenant Architecture
Single deployment supporting unlimited organisations with separate configurations, merchant accounts, and branding.
Secure Payment Processing
Full integration with Merchant Warrior PayFrame for PCI DSS compliant card processing — no card data touches your servers.
Currency Conversion
Real-time VATU to AUD conversion using live exchange rates, configurable per tenant.
Email Notifications
Automated email confirmations for customers and admin notifications with complete text receipts including address and postcode.
URL Parameters
Pre-populate forms via URL parameters for seamless integration with existing applications and workflows.
Return to Application
Automatic return to spawning application with payment status, enabling complex multi-application workflows.
White-Label Solutions
Custom branding per tenant: company names, colours, logos, and feature toggles.
Responsive Design
Works on all devices with React 18, TypeScript, and Tailwind CSS.
Multi-Tenant Architecture
The application supports multiple tenant configurations without separate builds, enabling both hosted multi-tenancy and self-hosting scenarios with complete configuration isolation.
Tenant Detection & Configuration Flow
Tenant Detection Methods
The system resolves the active tenant using the following priority order. The first method that returns a valid tenant ID wins.
| Priority | Method | Example | Use Case |
|---|---|---|---|
| 1 | URL Parameter | ?tenant=altima-community |
Dynamic switching, testing |
| 2 | URL Path | /tenant/charity-donations/ |
RESTful routing |
| 3 | Subdomain | altima.gateway.com |
Multi-tenant hosting |
| 4 | Environment Variable | VITE_TENANT_ID=altima |
Self-hosting |
| 5 | Local Storage | Persisted selection | User preference |
| 6 | Default | Test configuration | Fallback |
Detection Examples
# URL Parameter (highest priority) https://paymentgateway.com/?tenant=altima-community&amount=50.00 # Path Method https://paymentgateway.com/tenant/charity-donations/?amount=25.00 # Subdomain Method https://altima.paymentgateway.com/?amount=100.00 # Self-Hosting (environment variable) https://payments.altima-community.org/?amount=75.00
Tenant Configuration Structure
Each tenant can have completely separate settings across four areas:
Merchant Warrior Accounts
Different merchant UUIDs, API keys, passphrases, and gateway URLs per tenant.
Email Settings
Separate EmailJS configurations, templates, and admin email addresses.
Branding
Custom company names, colours, logos, and visual identity.
Feature Flags
Enable/disable VATU converter, email notifications, streamlined flow per tenant.
Tenant Configuration Example
'altima-community': {
tenantId: 'altima-community',
tenantName: 'Altima Community',
merchantWarrior: {
merchantUUID: import.meta.env.VITE_ALTIMA_MW_MERCHANT_UUID,
apiKey: import.meta.env.VITE_ALTIMA_MW_API_KEY,
passphrase: import.meta.env.VITE_ALTIMA_MW_PASSPHRASE,
payframeJsUrl:import.meta.env.VITE_ALTIMA_MW_PAYFRAME_JS_URL,
payframeUrl: import.meta.env.VITE_ALTIMA_MW_PAYFRAME_URL,
submitUrl: import.meta.env.VITE_ALTIMA_MW_SUBMIT_URL,
},
email: {
serviceId: import.meta.env.VITE_ALTIMA_EMAILJS_SERVICE_ID,
adminEmail: 'admin@altima-community.org',
// ... template IDs
},
branding: {
companyName: 'Altima Community',
primaryColor: '#059669',
secondaryColor: '#047857',
supportEmail: 'support@altima-community.org',
},
features: {
vatuConverter: true,
emailNotifications: true,
streamlinedFlow: true,
customReturnUrls: true,
}
}
Adding a New Tenant — 3 Steps
Add Tenant Configuration Block
Append a new block to src/config/tenantConfig.ts:
'your-organisation': {
tenantId: 'your-organisation',
tenantName: 'Your Organisation Name',
merchantWarrior: {
merchantUUID: import.meta.env.VITE_YOUR_MW_MERCHANT_UUID || 'test_fallback',
apiKey: import.meta.env.VITE_YOUR_MW_API_KEY || 'test_fallback',
passphrase: import.meta.env.VITE_YOUR_MW_PASSPHRASE || 'test_fallback',
// ... other MW config
},
branding: {
companyName: 'Your Organisation',
primaryColor: '#007b8f',
supportEmail: 'support@yourorganisation.com',
},
features: {
vatuConverter: false,
emailNotifications: true,
streamlinedFlow: true,
customReturnUrls: true,
}
}
Set Environment Variables
# Your Organisation — add to deployment platform environment VITE_YOUR_MW_MERCHANT_UUID=live_merchant_uuid VITE_YOUR_MW_API_KEY=live_api_key VITE_YOUR_MW_PASSPHRASE=live_passphrase VITE_YOUR_MW_PAYFRAME_JS_URL=https://secure.merchantwarrior.com/payframe/payframe.js VITE_YOUR_MW_PAYFRAME_URL=https://secure.merchantwarrior.com/payframe/ VITE_YOUR_MW_SUBMIT_URL=https://api.merchantwarrior.com/payframe/ VITE_YOUR_EMAILJS_SERVICE_ID=service_your_org VITE_YOUR_EMAILJS_PUBLIC_KEY=your_public_key VITE_YOUR_ADMIN_EMAIL=admin@yourcompany.com
Deploy Once
A single build serves all tenants — existing and new — with zero downtime for other tenants.
?tenant=your-organisation&amount=10.00 on the deployed app to confirm detection.URL Parameters & Integration
The gateway accepts a comprehensive set of URL query parameters that pre-populate form fields, select tenants, configure amounts, and control post-payment behaviour.
?param=value. Every subsequent parameter uses ¶m=value. The examples in the tables below show each parameter as it would appear after other parameters are already present.Tenant Selection
| Parameter | Description | Example |
|---|---|---|
tenant |
Select a specific tenant configuration (overrides all other detection methods) | ?tenant=altima-community |
t |
Short-form alias for tenant |
?t=charity-donations |
Amount & Currency
| Parameter | Description | Example (as additional parameter) |
|---|---|---|
amount |
Pre-fills the AUD amount directly and disables the VATU converter | &amount=50.00 |
vatu |
Pre-fills a VATU amount and shows real-time AUD conversion | &vatu=5000 |
Customer Information
These parameters pre-fill the customer form. When all required parameters are supplied (see Streamlined Flow), the form step is skipped entirely.
| Parameter | Description | Example (as additional parameter) |
|---|---|---|
name | Customer full name | &name=John%20Doe |
email | Customer email address | &email=john@example.com |
phone | Customer phone number | &phone=+61400000000 |
address | Street address | &address=123%20Main%20St |
city | City or suburb | &city=Sydney |
state | State or province | &state=NSW |
postcode | Postal / post code | &postcode=2000 |
country | ISO country code (defaults to AU) | &country=AU |
product | Product or service description | &product=Computer%20Donation |
Return URL
| Parameter | Description | Example (as additional parameter) |
|---|---|---|
return_url |
URL to redirect to after payment completion (URL-encoded) | &return_url=https%3A%2F%2Fmyapp.com%2Fdashboard |
returnUrl |
Alternative camelCase alias for return_url |
&returnUrl=https%3A%2F%2Fmyapp.com%2Fdashboard |
Integration Examples
Direct AUD Payment with Pre-filled Customer
VATU Conversion Payment
Fully Pre-filled — Streamlined Flow (no form shown)
Payment with Return URL
JavaScript Integration Example
// Redirect to the payment gateway from your application
function initiatePayment(customerData, amount, tenant = 'default') {
const baseUrl = 'https://altimapay.com/demo';
const returnUrl = encodeURIComponent(window.location.origin + '/payment-complete');
const params = new URLSearchParams({
tenant,
amount: amount.toString(),
name: customerData.name,
email: customerData.email,
phone: customerData.phone,
address: customerData.address,
city: customerData.city,
state: customerData.state,
postcode: customerData.postcode,
country: customerData.country || 'AU',
product: customerData.product || 'Purchase',
return_url: returnUrl,
});
window.location.href = baseUrl + '?' + params.toString();
}
// Handle the user returning from the gateway
function handlePaymentReturn() {
const p = new URLSearchParams(window.location.search);
const paymentStatus = p.get('payment_status'); // 'success' | 'failed'
const transactionId = p.get('transaction_id');
const amount = p.get('amount');
if (paymentStatus === 'success') {
console.log(`Payment OK — Transaction: ${transactionId}, Amount: $${amount}`);
} else {
console.log('Payment failed or cancelled');
}
}
Return URL Parameters
After payment the gateway appends the following to the return_url:
| Parameter | Description | Example Values |
|---|---|---|
payment_status | Payment outcome | success, failed |
transaction_id | Merchant Warrior transaction ID | 12345678 |
amount | Amount charged in AUD | 50.00 |
tenant | Tenant that processed the payment | altima-community |
Payment Flow
The gateway supports two distinct flows depending on how much information is supplied via URL parameters.
Standard Flow
Used when partial or no customer information is pre-filled. The user completes a customer information form before proceeding to card entry.
- Customer Information Form — user enters personal details; URL parameters pre-fill known fields.
- Currency Conversion — optional VATU to AUD conversion with live exchange rates (tenant configurable).
- Secure Payment — PayFrame loads card input fields hosted by Merchant Warrior.
- Comprehensive Response — transaction receipt, download option, next-step buttons.
- Email Notifications — customer confirmation and admin notification sent via tenant-specific templates.
Streamlined Flow
name, email, phone, address, city, postcode, plus amount or vatu.When all required data is already known, the customer form is skipped and the user is taken directly to card entry.
- Skip Form — no customer data entry step; user goes straight to card input.
- Automatic VATU Conversion — AUD equivalent displayed if
vatuparameter was used. - Simple Response — success shows a Finish button; failure shows a Retry button.
- Automatic Return — seamless redirect to
return_urlwith payment status parameters. - Minimal UI — focused, distraction-free interface suited for embedded scenarios.
Email Notifications
Both flows trigger email notifications on payment completion, sent via the tenant's configured EmailJS service.
Customer Email
Success or failure confirmation sent to the customer's email address. Uses tenant-specific success/failure templates.
Admin Notification
Full transaction details sent to the tenant's admin email, including a complete text receipt with customer address and postcode.
receipt_text parameter containing a formatted plain-text receipt. Individual fields are also available as template variables: {{customer_address}}, {{customer_postcode}}, {{transaction_id}}, {{amount}}, etc.Security & Configuration
Enterprise-grade security with comprehensive environment variable support. Sensitive configuration data is never hard-coded in production builds.
Environment Variables
Multi-Tenant Example
# Altima Community Tenant VITE_ALTIMA_MW_MERCHANT_UUID=altima_live_uuid VITE_ALTIMA_MW_API_KEY=altima_live_key VITE_ALTIMA_MW_PASSPHRASE=altima_live_passphrase VITE_ALTIMA_MW_PAYFRAME_JS_URL=https://secure.merchantwarrior.com/payframe/payframe.js VITE_ALTIMA_MW_PAYFRAME_URL=https://secure.merchantwarrior.com/payframe/ VITE_ALTIMA_MW_SUBMIT_URL=https://api.merchantwarrior.com/payframe/ VITE_ALTIMA_EMAILJS_SERVICE_ID=service_altima VITE_ALTIMA_EMAILJS_PUBLIC_KEY=altima_public_key VITE_ALTIMA_EMAILJS_USER_SUCCESS_TEMPLATE_ID=template_altima_success VITE_ALTIMA_EMAILJS_USER_FAILURE_TEMPLATE_ID=template_altima_failure VITE_ALTIMA_EMAILJS_ADMIN_NOTIFICATION_TEMPLATE_ID=template_altima_admin VITE_ALTIMA_ADMIN_EMAIL=admin@altima-community.org VITE_ALTIMA_EXCHANGE_RATE_API_KEY=altima_fx_api_key # Charity Tenant VITE_CHARITY_MW_MERCHANT_UUID=charity_live_uuid VITE_CHARITY_MW_API_KEY=charity_live_key VITE_CHARITY_MW_PASSPHRASE=charity_live_passphrase VITE_CHARITY_EMAILJS_SERVICE_ID=service_charity VITE_CHARITY_EMAILJS_PUBLIC_KEY=charity_public_key VITE_CHARITY_ADMIN_EMAIL=donations@charity.org
Self-Hosting Example
# Force a specific tenant VITE_TENANT_ID=your-organisation # Gateway credentials VITE_YOUR_MW_MERCHANT_UUID=your_merchant_uuid VITE_YOUR_MW_API_KEY=your_api_key VITE_YOUR_MW_PASSPHRASE=your_passphrase VITE_YOUR_MW_PAYFRAME_JS_URL=https://secure.merchantwarrior.com/payframe/payframe.js VITE_YOUR_MW_PAYFRAME_URL=https://secure.merchantwarrior.com/payframe/ VITE_YOUR_MW_SUBMIT_URL=https://api.merchantwarrior.com/payframe/ # Email notifications VITE_YOUR_EMAILJS_SERVICE_ID=service_your_org VITE_YOUR_EMAILJS_PUBLIC_KEY=your_public_key VITE_YOUR_ADMIN_EMAIL=admin@yourcompany.com
Gateway URLs by Environment
| Environment | PayFrame JS URL | PayFrame URL | Submit URL |
|---|---|---|---|
| Test | securetest.merchantwarrior.com/payframe/payframe.js |
securetest.merchantwarrior.com/payframe/ |
base.merchantwarrior.com/payframe/ |
| Production | secure.merchantwarrior.com/payframe/payframe.js |
secure.merchantwarrior.com/payframe/ |
api.merchantwarrior.com/payframe/ |
Security Best Practices
.env files containing live credentials. Always store production credentials as environment variables in your hosting platform. Add .env, .env.local, and .env.production to .gitignore.| Security Layer | Implementation | Benefit |
|---|---|---|
| Payment Processing | Merchant Warrior PayFrame | PCI DSS compliant — card data never touches the application |
| API Authentication | MD5 hash with passphrase + multiple elements | Tamper-evident API communication |
| Data Transmission | HTTPS / TLS | All data encrypted in transit |
| Configuration | Environment variables (Vite prefix) | Credentials never exposed in source code |
| Input Validation | Client-side form validation | Prevents malformed data reaching the gateway |
| Tenant Isolation | Dynamic configuration loading | Complete separation between tenant credentials |
| Card Data | Masked card numbers only (last 4 digits) | PCI compliance — no full card data stored or emailed |
Deployment & Hosting
The application supports multiple deployment scenarios — from a multi-tenant SaaS platform serving dozens of organisations to a self-hosted single-organisation installation.
Multi-Tenant Hosting
A single build serves all configured tenants. Tenant routing is resolved by subdomain, URL path, or query parameter.
npm run buildDNS — Subdomain Routing
# Wildcard CNAME covers all tenants automatically *.yourgateway.com → yourgateway.com altima.yourgateway.com → yourgateway.com charity.yourgateway.com → yourgateway.com
Benefits of Multi-Tenant Hosting
Cost Effective
One deployment, one maintenance contract, unlimited tenants.
Easy Updates
Deploy once to push security patches and new features to all tenants simultaneously.
Scalable
Add tenants by config block + env vars — no infrastructure changes.
Isolated
Complete credential and configuration separation between tenants.
Self-Hosting
Deploy on your organisation's own domain with custom branding by forcing a single tenant via environment variable.
Set Tenant ID
VITE_TENANT_ID=your-organisation
Configure Credentials
VITE_YOUR_MW_MERCHANT_UUID=live_uuid VITE_YOUR_MW_API_KEY=live_key VITE_YOUR_MW_PASSPHRASE=live_passphrase VITE_YOUR_MW_PAYFRAME_JS_URL=https://secure.merchantwarrior.com/payframe/payframe.js VITE_YOUR_MW_PAYFRAME_URL=https://secure.merchantwarrior.com/payframe/ VITE_YOUR_MW_SUBMIT_URL=https://api.merchantwarrior.com/payframe/ VITE_YOUR_EMAILJS_SERVICE_ID=service_id VITE_YOUR_EMAILJS_PUBLIC_KEY=public_key VITE_YOUR_ADMIN_EMAIL=admin@yourcompany.com
Deploy to Your Domain
payments.yourcompany.com pay.yourorganisation.org gateway.yourbusiness.net
Hosting Platform Examples
Netlify
Set environment variables under Site Settings → Environment Variables. Enable branch deploy previews for staging. Configure redirect rules for SPA routing:
# netlify.toml [[redirects]] from = "/*" to = "/index.html" status = 200
Vercel
Set environment variables under Project Settings → Environment Variables. Vercel handles SPA rewrites automatically for Vite projects.
Any Static Host (S3, GitHub Pages, cPanel)
Build locally with npm run build, upload the dist/ folder, and configure your server to serve index.html for all routes (SPA fallback).
Technical Reference
Architecture, technology stack, component structure, and API integration details.
Technology Stack
| Layer | Technology | Purpose |
|---|---|---|
| Frontend Framework | React 18 + TypeScript | Type-safe component UI |
| Build Tool | Vite | Fast builds and HMR in development |
| Styling | Tailwind CSS | Utility-first responsive CSS |
| Payment Processing | Merchant Warrior PayFrame | PCI DSS compliant card capture (hosted fields) |
| Email Service | EmailJS | Client-side email dispatch (no server required) |
| Currency API | exchangeratesapi.io | Real-time VUV → AUD exchange rates |
| Icons | Lucide React | SVG icon library |
| State Management | React Hooks | Local component and shared state |
| Hash Utility | crypto-js | MD5 hash generation for Merchant Warrior auth |
Component & File Structure
src/
├── components/
│ ├── CustomerForm.tsx # Customer information form
│ ├── VatuConverter.tsx # VATU → AUD conversion display
│ ├── PayFrameContainer.tsx # Merchant Warrior PayFrame wrapper
│ ├── PaymentResponse.tsx # Transaction result screen
│ ├── SurchargeDisplay.tsx # Surcharge calculation display
│ └── TenantSelector.tsx # Dev-only tenant switcher
├── services/
│ ├── emailService.ts # Tenant-aware EmailJS integration
│ ├── receiptService.ts # Text receipt generation
│ ├── fxService.ts # Exchange rate API service
│ └── currencyService.ts # Currency formatting utilities
├── config/
│ ├── tenantConfig.ts # Multi-tenant configuration map
│ ├── settings.ts # Legacy settings (backward compat)
│ └── merchantWarrior.ts # Dynamic payment gateway config
├── hooks/
│ ├── useUrlParams.ts # URL parameter parsing
│ └── useTenantColors.ts # CSS variable injection for branding
└── types/
└── payment.ts # TypeScript interfaces
Application State Machine
The top-level App component manages a simple three-state flow:
API Integration — Return URL Handling
Express.js Example
// Server-side return URL handler
app.get('/payment-complete', async (req, res) => {
const { payment_status, transaction_id, amount, tenant } = req.query;
if (payment_status === 'success') {
console.log(`Payment OK — ${transaction_id} for $${amount} (${tenant})`);
switch (tenant) {
case 'altima-community':
await processEducationDonation(transaction_id, amount);
break;
case 'charity-donations':
await processCharityDonation(transaction_id, amount);
break;
}
}
res.redirect('/dashboard');
});
React Component Example
function PaymentButton({ customerData, amount, tenant }) {
const initiatePayment = () => {
const params = new URLSearchParams({
tenant,
amount: amount.toString(),
name: customerData.name,
email: customerData.email,
phone: customerData.phone,
address: customerData.address,
city: customerData.city,
state: customerData.state,
postcode: customerData.postcode,
country: customerData.country || 'AU',
product: customerData.product || 'Purchase',
return_url: encodeURIComponent(window.location.origin + '/payment-complete'),
});
window.location.href = 'https://altimapay.com/demo?' + params.toString();
};
return <button onClick={initiatePayment}>Pay ${amount} AUD</button>;
}
Troubleshooting & Support
Common issues, their causes, and solutions. For all issues, start by opening the browser developer console — the application logs detailed configuration and error information.
Tenant Detection Issues
| Symptom | Likely Cause | Solution |
|---|---|---|
| Wrong tenant loads | Conflicting detection methods (e.g., localStorage vs URL param) | Check priority order. Clear localStorage: localStorage.removeItem('tenantId') |
| Default config always loads | Tenant ID not found in tenantConfig.ts |
Verify the ID matches exactly (case-sensitive, hyphens preserved) |
| Subdomain not detected | DNS CNAME not propagated or missing wildcard record | Check CNAME records; allow up to 48 hours for DNS propagation |
| Environment variable ignored | Variable name typo or wrong prefix | Verify prefix matches tenant config key (uppercase, underscores for hyphens) |
Payment Processing Issues
| Symptom | Likely Cause | Solution |
|---|---|---|
| PayFrame does not load | Incorrect Merchant Warrior UUID, API key, or passphrase | Verify all three MW credentials for the active tenant |
| Payment fails with hash error | Passphrase mismatch or encoding issue | Check passphrase — no leading/trailing spaces, correct character encoding |
| Test cards not working | Live gateway URL used with test credentials | Ensure securetest.merchantwarrior.com URLs are set for test environment |
| Live payments not processed | Test gateway URL used in production | Switch to secure.merchantwarrior.com and api.merchantwarrior.com |
Email Notification Issues
| Symptom | Likely Cause | Solution |
|---|---|---|
| No emails sent at all | EmailJS service ID or public key not configured | Verify VITE_{PREFIX}_EMAILJS_SERVICE_ID and VITE_{PREFIX}_EMAILJS_PUBLIC_KEY |
| Customer emails missing | Template ID not set or set to placeholder value | Check VITE_{PREFIX}_EMAILJS_USER_SUCCESS_TEMPLATE_ID |
| Admin email not sent | Admin email address not configured or template missing | Verify VITE_{PREFIX}_ADMIN_EMAIL and admin template ID |
| Template variables show blank | Mismatch between parameter names sent and template variable names | Check EmailJS template uses correct variable names (e.g., {{customer_postcode}}) |
Debugging Tools
Browser Console Debug Commands
// Check which tenant is active
console.log('Tenant:', getCurrentTenantConfig());
// Check email configuration status
EmailService.initialize(); // Logs all config checks to console
// Manually set tenant via localStorage (for testing)
localStorage.setItem('tenantId', 'altima-community');
location.reload();
Testing Tenant Detection Methods
# 1. URL Parameter (append to any URL)
?tenant=altima-community&amount=10.00
# 2. Path-based
/tenant/charity-donations/?amount=25.00
# 3. Subdomain (requires DNS)
https://altima.yourgateway.com/?amount=10.00
# 4. Environment variable (rebuild required)
VITE_TENANT_ID=altima-community
# 5. localStorage (browser console)
localStorage.setItem('tenantId', 'charity-donations');
Support Resources
Documentation
- README.md — general setup and configuration
- DEPLOYMENT.md — platform-specific deployment guides
- TEXT_RECEIPT_SETUP.md — EmailJS template configuration
- SECURITY.md — security model and practices
External Resources
- Merchant Warrior Developer Documentation
- EmailJS Documentation — emailjs.com/docs
- exchangeratesapi.io for currency API keys
- Vite documentation for build configuration