- Comprehensive trace of multicurrency functionality - Identified gaps: frontend currency selector, ExchangeRateAPI implementation, conversion logic - Documented defects: hardcoded IDR, empty API class, missing Bank Transfer currency column - Provided implementation order and testing checklist
12 KiB
Formipay — Multicurrency Implementation Audit
Date: April 18, 2026 Scope: Complete trace of multicurrency functionality Purpose: Identify gaps, defects, and opportunities before Phase 4 implementation
Executive Summary
The multicurrency system has a solid foundation in the admin (settings UI, data structures, per-currency pricing) but is incomplete for end-users. The framework exists but critical pieces are missing: frontend currency selection, exchange rate API integration, and actual conversion logic.
Status: 🟡 Partial — Works in admin, broken on frontend
1. What Works ✅
1.1 Admin Settings & Configuration
Location: includes/Settings.php lines 56-133
| Feature | Status | Details |
|---|---|---|
| Enable/disable toggle | ✅ | enable_multicurrency checkbox |
| Currency management | ✅ | multicurrencies repeater with full config |
| Default currency | ✅ | default_currency setting |
| Per-currency decimals | ✅ | Custom decimal_digits, decimal_symbol, thousand_separator |
| Exchange rate fields | ✅ | Manual rate input (API integration non-functional) |
| Gateway association | ✅ | Link currencies to payment gateways |
Data Structure: Currencies stored as code:::name:::symbol (e.g., USD:::United States Dollar:::$)
1.2 Currency Data Source
Location: admin/assets/json/currencies.json
- 196 currencies available
- Loaded via
formipay_currency_array() - Cached via static variable (F1.13 optimization)
- Includes code, name, symbol, flag
1.3 Product Pricing Per Currency
Location: includes/Product.php lines 386-432
Products can have different prices for each currency:
- Static items:
amount_{currency_code}field - Default currency price:
setting_product_price_regular_{code} - Sale price:
setting_product_price_sale_{code}
1.4 Price Formatting
Location: admin/functions.php lines 179-200
formipay_price_format() properly handles:
- Product-specific currency metadata
- Custom decimal digits, symbols, separators
- Format:
{symbol} {formatted_number}
2. What's Broken/Incomplete ❌
2.1 Frontend Currency Selection — MISSING
Problem: Users have NO way to select currency on forms.
What exists:
formipay.currency_codehardcoded to'IDR'inform-action.js:224- Currency data passed to admin via
wp_localize_script()(Form.php:1289-1292) - No UI element rendered on frontend forms
Impact: Multicurrency is admin-only; frontend users always see default currency prices.
2.2 Exchange Rate API — EMPTY CLASS
Location: includes/Integration/ExchangeRateAPI.php
Status: Completely empty class (8 lines total):
class ExchangeRateAPI extends Payment {
use SingletonTrait;
protected function __construct() {
parent::__construct();
// Empty - no implementation
}
}
What's missing:
- No API integration (ExchangeRate-API.io, Fixer.io, etc.)
- No rate fetching logic
- No caching mechanism
- No error handling
- Settings UI exists but non-functional
2.3 Currency Conversion Logic — NOT IMPLEMENTED
Problem: No actual conversion calculations anywhere.
What exists:
- Framework for per-currency prices in products
- Manual exchange rate fields in settings (unused)
formipay_price_format()displays but doesn't convert
Missing:
- Conversion calculation functions
- Dynamic price switching based on user selection
- Conversion indicators on frontend
2.4 Bank Transfer — Missing Currency Tracking
Location: includes/Payment/BankTransfer.php create_db()
Problem: Bank transfer transaction table has NO currency column:
CREATE TABLE `formipay_bank_transfer_trx` (
...
`total` float(10, 2) DEFAULT 0,
-- Missing: `currency_code` text
...
)
Impact: Can't determine which currency was used for bank transfer payments.
2.5 Order Storage — Inconsistent
| Gateway | Currency Stored | Location |
|---|---|---|
| PayPal | ✅ currency_code |
Paypal.php:84 |
| Bank Transfer | ❌ Missing | — |
| General | ⚠️ $this->currency |
Order.php:95 (not in DB schema) |
3. Gaps & Missing Features
3.1 Critical Gaps
| # | Gap | Impact | Priority |
|---|---|---|---|
| 1 | Frontend currency selector | Users can't choose currency | 🔴 High |
| 2 | ExchangeRateAPI implementation | No live rates | 🔴 High |
| 3 | Conversion calculation logic | Prices don't convert | 🔴 High |
| 4 | Bank Transfer currency tracking | Data loss | 🟡 Medium |
| 5 | Dynamic price display on frontend | Always shows default currency | 🔴 High |
3.2 Data Flow Gaps
Expected Flow:
User selects currency → Fetch exchange rate → Convert prices → Display converted prices
Actual Flow:
User selects currency → [NOT IMPLEMENTED] → [NOT IMPLEMENTED] → Shows default currency only
3.3 Missing Validation
- No currency validation on form submission
- No check if selected currency is in allowed currencies
- No validation that required currencies have prices set
4. Defects & Bugs
4.1 Critical Bugs
| # | Bug | Location | Impact |
|---|---|---|---|
| 1 | formipay.currency_code hardcoded to 'IDR' |
public/assets/js/form-action.js:224 |
Frontend always uses IDR |
| 2 | ExchangeRateAPI class is empty | includes/Integration/ExchangeRateAPI.php |
Settings UI does nothing |
| 3 | Bank transfer has no currency column | includes/Payment/BankTransfer.php:40-50 |
Lost currency data |
4.2 Minor Issues
| # | Issue | Location |
|---|---|---|
| 1 | Fallback pattern conflicts | Multiple files |
| 2 | No currency flag in frontend | Render.php |
| 3 | Mixed code/symbol usage | Inconsistent display |
5. Architecture & Data Flow
5.1 Current Architecture
┌─────────────────────────────────────────────────────┐
│ Admin Settings (WPCFTO) │
│ - enable_multicurrency toggle │
│ - multicurrencies[] repeater (currencies + rates) │
│ - default_currency │
└─────────────────────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────┐
│ Product Editor (Vue) │
│ - Per-currency pricing fields │
│ - Variation pricing per currency │
└─────────────────────────────────────────────────────┘
│
▼
┌<>─────────────────────────────────────────────────────┐
│ Form Rendering (PHP SSR) │
│ - formipay.currency_code = 'IDR' (HARDCODED ❌) │
│ - formipay_price_format($amount, $post_id) │
│ - Shows: {symbol} {formatted_amount} │
└─────────────────────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────┐
│ Order Storage │
│ - PayPal: has currency_code ✅ │
│ - Bank Transfer: no currency ❌ │
│ - General: $this->currency (not in DB) ⚠️ │
└─────────────────────────────────────────────────────┘
5.2 Data Structures
Currency Format: code:::name:::symbol
- Example:
USD:::United States Dollar:::$ - Example with symbol:
IDR:::Indonesian Rupiah:::Rp
Product Price Storage:
// Per currency (static items)
$static_item['amount_USD'] = '29.99';
$static_item['amount_IDR'] = '450000';
// Default currency
get_post_meta($post_id, 'product_currency'); // "USD:::..."
get_post_meta($post_id, 'product_currency_decimal_digits'); // 2
Order Currency Storage:
// PayPal (correct)
$currency_code = $currency_parts[0]; // 'USD'
// Bank Transfer (missing)
// No currency stored ❌
6. Opportunities for Improvement
6.1 High Priority (Phase 4)
| # | Opportunity | Benefit | Effort |
|---|---|---|---|
| 1 | Frontend currency dropdown selector | Users can finally use multicurrency | Medium |
| 2 | Complete ExchangeRateAPI with live rates | Accurate pricing, manual entry backup | Medium |
| 3 | Currency conversion calculation layer | Dynamic pricing, better UX | Medium |
| 4 | Add currency column to Bank Transfer table | Data completeness | Low |
| 5 | Real-time price updates on currency change | Better UX, clearer pricing | Medium |
6.2 Medium Priority
| # | Opportunity | Benefit | Effort |
|---|---|---|---|
| 1 | Currency flag icons in frontend | Visual clarity, UX improvement | Low |
| 2 | Currency validation on form submit | Data integrity | Low |
| 3 | Conversion rate history/audit trail | Accounting, debugging | Medium |
| 4 | Multi-currency reports in dashboard | Business insights | Medium |
| 5 | Auto-fetch rates on schedule | Always-current rates without manual entry | Low |
6.3 Nice-to-Have
| # | Opportunity | Benefit |
|---|---|---|
| 1 | Display original + converted prices (e.g., "$29.99 (~Rp 450.000)") | Transparency |
| 2 | Currency switcher widget (cookies remember preference) | UX convenience |
| 3 | GEO IP detection to auto-select currency | Personalization |
| 4 | Admin-side currency conversion calculator | Admin convenience |
| 5 | Support for 3+ decimal currencies (e.g., cryptocurrencies) | Future-proofing |
7. Recommended Implementation Order
Phase 4A — Core Multicurrency (Weeks 11-12)
1. Frontend currency selector dropdown
2. ExchangeRateAPI implementation (one API provider)
3. Conversion calculation functions
4. Fix Bank Transfer currency column
5. Dynamic price display on forms
Phase 4B — Enhanced Features (Weeks 15-16)
6. Currency validation
7. Conversion rate history
8. Multi-currency dashboard reports
9. GEO IP auto-detection
10. Admin conversion calculator
8. Code Locations Reference
| File | Lines | Purpose |
|---|---|---|
includes/Settings.php |
56-133 | Multicurrency settings UI |
admin/functions.php |
28-36, 47-81, 179-200, 202-218 | Currency utility functions |
admin/assets/json/currencies.json |
— | Currency data source (196 currencies) |
public/assets/js/form-action.js |
224 | Currency code (hardcoded bug) |
includes/Product.php |
386-432 | Product pricing per currency |
includes/Order.php |
95 | Order currency property |
includes/Integration/Paypal.php |
75, 84 | PayPal currency handling |
includes/Payment/BankTransfer.php |
40-50 | Bank transfer schema (missing currency) |
includes/Integration/ExchangeRateAPI.php |
all | Empty class (needs implementation) |
9. Testing Checklist
When implementing multicurrency features:
- Enable multicurrency in settings
- Add 3+ currencies
- Set prices for default currency
- Set prices for additional currencies
- Submit form with each currency selected
- Verify order currency stored correctly
- Verify payment gateway receives correct currency
- Test ExchangeRateAPI rate fetching
- Test manual exchange rate override
- Test price conversion calculations
- Test currency formatting display
- Test Bank Transfer with currency column
- Test frontend currency dropdown
- Test GEO IP auto-detection (if implemented)
End of Multicurrency Audit.