# 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_code` hardcoded to `'IDR'` in `form-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): ```php 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: ```php 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:** ```php // 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:** ```php // 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.*