diff --git a/src/app/Backends/OpenExchangeRates.php b/src/app/Backends/OpenExchangeRates.php new file mode 100644 --- /dev/null +++ b/src/app/Backends/OpenExchangeRates.php @@ -0,0 +1,52 @@ + $apiKey, 'base' => 'USD']); + $url = 'https://openexchangerates.org/api/latest.json?' . $query; + $html = file_get_contents($url, false); + $rates = []; + + if ($html && ($result = json_decode($html, true)) && !empty($result['rates'])) { + foreach ($result['rates'] as $code => $rate) { + $rates[strtoupper($code)] = $rate; + } + + if ($baseCurrency != 'USD') { + if ($base = $rates[$baseCurrency]) { + foreach ($rates as $code => $rate) { + $rates[$code] = $rate / $base; + } + } else { + $rates = []; + } + } + + foreach ($rates as $code => $rate) { + \Log::debug(sprintf("Update %s: %0.8f", $code, $rate)); + } + } else { + throw new \Exception("Failed to parse exchange rates"); + } + + if (count($rates) > 1) { + $rates[$baseCurrency] = 1; + return $rates; + } + + throw new \Exception("Failed to retrieve exchange rates"); + } +} diff --git a/src/app/Console/Commands/Data/Import/ExchangerateCommand.php b/src/app/Console/Commands/Data/Import/ExchangerateCommand.php new file mode 100644 --- /dev/null +++ b/src/app/Console/Commands/Data/Import/ExchangerateCommand.php @@ -0,0 +1,48 @@ +argument('sourceCurrency')); + $rates = \App\Backends\OpenExchangeRates::retrieveRates($sourceCurrency); + + // + // export + // + $file = resource_path("exchangerates-$sourceCurrency.php"); + + $out = " $rate) { + $out .= sprintf(" '%s' => '%s',\n", $countryCode, $rate); + } + + $out .= "];\n"; + + file_put_contents($file, $out); + } +} diff --git a/src/app/Providers/Payment/Mollie.php b/src/app/Providers/Payment/Mollie.php --- a/src/app/Providers/Payment/Mollie.php +++ b/src/app/Providers/Payment/Mollie.php @@ -562,17 +562,17 @@ $providerMethods = array_merge( // Fallback to EUR methods (later provider methods will override earlier ones) - //mollie()->methods()->allActive( - // [ - // 'sequenceType' => $type, - // 'amount' => [ - // 'value' => '1.00', - // 'currency' => 'EUR' - // ] - // ] - //), + (array) mollie()->methods()->allActive( + [ + 'sequenceType' => $type, + 'amount' => [ + 'value' => '1.00', + 'currency' => 'EUR' + ] + ] + ), // Prefer CHF methods - (array)mollie()->methods()->allActive( + (array) mollie()->methods()->allActive( [ 'sequenceType' => $type, 'amount' => [ diff --git a/src/app/Providers/PaymentProvider.php b/src/app/Providers/PaymentProvider.php --- a/src/app/Providers/PaymentProvider.php +++ b/src/app/Providers/PaymentProvider.php @@ -199,8 +199,7 @@ protected function exchangeRate(string $sourceCurrency, string $targetCurrency): float { if (strcasecmp($sourceCurrency, $targetCurrency)) { - throw new \Exception("Currency conversion is not yet implemented."); - //FIXME Not yet implemented + return \App\Utils::exchangeRate($sourceCurrency, $targetCurrency); } return 1.0; } @@ -312,11 +311,10 @@ 'id' => self::METHOD_PAYPAL, 'icon' => self::$paymentMethodIcons[self::METHOD_PAYPAL] ], - // TODO Enable once we're ready to offer them - // self::METHOD_BANKTRANSFER => [ - // 'id' => self::METHOD_BANKTRANSFER, - // 'icon' => self::$paymentMethodIcons[self::METHOD_BANKTRANSFER] - // ] + self::METHOD_BANKTRANSFER => [ + 'id' => self::METHOD_BANKTRANSFER, + 'icon' => self::$paymentMethodIcons[self::METHOD_BANKTRANSFER] + ] ]; case PaymentProvider::TYPE_RECURRING: return [ diff --git a/src/app/Utils.php b/src/app/Utils.php --- a/src/app/Utils.php +++ b/src/app/Utils.php @@ -5,6 +5,7 @@ use Carbon\Carbon; use Illuminate\Support\Facades\Auth; use Ramsey\Uuid\Uuid; +use Illuminate\Support\Facades\Cache; /** * Small utility functions for App. @@ -406,4 +407,24 @@ return $env; } + + + /** + * Retrieve an exchange rate. + * + * @param string $sourceCurrency: Currency from which to convert + * @param string $targetCurrency: Currency to convert to + * + * @return float Exchange rate + */ + public static function exchangeRate(string $sourceCurrency, string $targetCurrency): float + { + $rates = include resource_path("exchangerates-$sourceCurrency.php"); + + if (!isset($rates[$targetCurrency])) { + throw new \Exception("Failed to find exchange rate for " . $targetCurrency); + } + + return floatval($rates[$targetCurrency]); + } } diff --git a/src/config/currency.php b/src/config/currency.php --- a/src/config/currency.php +++ b/src/config/currency.php @@ -1,116 +1,5 @@ 'USD', - - /* - |-------------------------------------------------------------------------- - | API Key for OpenExchangeRates.org - |-------------------------------------------------------------------------- - | - | Only required if you with to use the Open Exchange Rates api. You can - | always just use Yahoo, the current default. - | - */ - - 'api_key' => env('OPENEXCHANGERATES_API_KEY', null), - - /* - |-------------------------------------------------------------------------- - | Default Storage Driver - |-------------------------------------------------------------------------- - | - | Here you may specify the default storage driver that should be used - | by the framework. - | - | Supported: "database", "filesystem" - | - */ - - 'driver' => 'filesystem', - - /* - |-------------------------------------------------------------------------- - | Default Storage Driver - |-------------------------------------------------------------------------- - | - | Here you may specify the default cache driver that should be used - | by the framework. - | - | Supported: all cache drivers supported by Laravel - | - */ - - 'cache_driver' => null, - - /* - |-------------------------------------------------------------------------- - | Storage Specific Configuration - |-------------------------------------------------------------------------- - | - | Here you may configure as many storage drivers as you wish. - | - */ - - 'drivers' => [ - - 'database' => [ - 'class' => \Torann\Currency\Drivers\Database::class, - 'connection' => null, - 'table' => 'currencies', - ], - - 'filesystem' => [ - 'class' => \Torann\Currency\Drivers\Filesystem::class, - 'disk' => null, - 'path' => 'currencies.json', - ], - - ], - - /* - |-------------------------------------------------------------------------- - | Currency Formatter - |-------------------------------------------------------------------------- - | - | Here you may configure a custom formatting of currencies. The reason for - | this is to help further internationalize the formatting past the basic - | format column in the table. When set to `null` the package will use the - | format from storage. - | - | More info: - | http://lyften.com/projects/laravel-currency/doc/formatting.html - | - */ - - 'formatter' => null, - - /* - |-------------------------------------------------------------------------- - | Currency Formatter Specific Configuration - |-------------------------------------------------------------------------- - | - | Here you may configure as many currency formatters as you wish. - | - */ - - 'formatters' => [ - - 'php_intl' => [ - 'class' => \Torann\Currency\Formatters\PHPIntl::class, - ], - - ], + 'openexchangerates_api_key' => env('OPENEXCHANGERATES_API_KEY', null), ]; diff --git a/src/resources/exchangerates-CHF.php b/src/resources/exchangerates-CHF.php new file mode 100644 --- /dev/null +++ b/src/resources/exchangerates-CHF.php @@ -0,0 +1,172 @@ + '3.9552959825289', + 'AFN' => '83.613671484215', + 'ALL' => '111.47078618895', + 'AMD' => '568.26008190657', + 'ANG' => '1.9326009913646', + 'AOA' => '674.30453178322', + 'ARS' => '98.608363602295', + 'AUD' => '1.4005248654184', + 'AWG' => '1.9383622346732', + 'AZN' => '1.8315423225241', + 'BAM' => '1.765440939718', + 'BBD' => '2.1537358163036', + 'BDT' => '91.161248046831', + 'BGN' => '1.76640258276', + 'BHD' => '0.40598781631649', + 'BIF' => '2095.7472160272', + 'BMD' => '1.0768679081518', + 'BND' => '1.4428166987753', + 'BOB' => '7.4343600550926', + 'BRL' => '5.9304203338506', + 'BSD' => '1.0768679081518', + 'BTC' => '1.9792923685602E-5', + 'BTN' => '77.837962608992', + 'BWP' => '11.786340792079', + 'BYN' => '2.7980743448066', + 'BZD' => '2.1702905066556', + 'CAD' => '1.3518138224611', + 'CDF' => '2116.9551990644', + 'CHF' => '1', + 'CLF' => '0.027974874517967', + 'CLP' => '771.89865273056', + 'CNH' => '7.0074023900006', + 'CNY' => '7.0104100820681', + 'COP' => '3842.7175763149', + 'CRC' => '657.98680298379', + 'CUC' => '1.0768679081518', + 'CUP' => '27.729348634908', + 'CVE' => '61.047641713125', + 'CZK' => '23.665033775962', + 'DJF' => '191.67469005049', + 'DKK' => '6.7297783052037', + 'DOP' => '61.257419889104', + 'DZD' => '143.75354477994', + 'EGP' => '16.95528521385', + 'ERN' => '16.154426088633', + 'ETB' => '44.007619917318', + 'EUR' => '0.90503424978382', + 'FJD' => '2.1941722062547', + 'FKP' => '0.77972343878383', + 'GBP' => '0.77972343878383', + 'GEL' => '3.5805857946047', + 'GGP' => '0.77972343878383', + 'GHS' => '6.1747045882111', + 'GIP' => '0.77972343878383', + 'GMD' => '55.189480292779', + 'GNF' => '10817.922694883', + 'GTQ' => '8.3118318707672', + 'GYD' => '225.03202066725', + 'HKD' => '8.3636130641307', + 'HNL' => '25.899206240665', + 'HRK' => '6.85609491083', + 'HTG' => '85.509264833048', + 'HUF' => '331.7893366386', + 'IDR' => '15495.725407298', + 'ILS' => '3.5472890388846', + 'IMP' => '0.77972343878383', + 'INR' => '77.954048969491', + 'IQD' => '1570.6716338994', + 'IRR' => '45341.523272731', + 'ISK' => '135.22230322662', + 'JEP' => '0.77972343878383', + 'JMD' => '157.70066841191', + 'JOD' => '0.76349934687961', + 'JPY' => '117.11369248314', + 'KES' => '118.29393971047', + 'KGS' => '91.318753977681', + 'KHR' => '4376.275274359', + 'KMF' => '444.07379452714', + 'KPW' => '969.1811173366', + 'KRW' => '1215.4069376138', + 'KWD' => '0.32537563844806', + 'KYD' => '0.89714942296033', + 'KZT' => '453.27712011062', + 'LAK' => '10084.767400839', + 'LBP' => '1627.9546875522', + 'LKR' => '213.44889346438', + 'LRD' => '186.83658529494', + 'LSL' => '15.830499914389', + 'LYD' => '4.8516237552753', + 'MAD' => '9.6543512463131', + 'MDL' => '19.238468090789', + 'MGA' => '4077.6026098971', + 'MKD' => '55.639268634391', + 'MMK' => '1518.1264813664', + 'MNT' => '3063.4631479649', + 'MOP' => '8.6120551054846', + 'MRO' => '384.44165798891', + 'MRU' => '38.706188436808', + 'MUR' => '43.397775621649', + 'MVR' => '16.648377860027', + 'MWK' => '845.13715851173', + 'MXN' => '22.260479270831', + 'MYR' => '4.4366957815853', + 'MZN' => '77.618485083764', + 'NAD' => '15.851495607994', + 'NGN' => '443.32165505983', + 'NIO' => '37.576054334447', + 'NOK' => '9.1987650478829', + 'NPR' => '124.54219760741', + 'NZD' => '1.5235527164531', + 'OMR' => '0.41463183501522', + 'PAB' => '1.0768679081518', + 'PEN' => '3.9984923849286', + 'PGK' => '3.7984060201224', + 'PHP' => '52.354625524569', + 'PKR' => '167.28288781513', + 'PLN' => '4.1605933111427', + 'PYG' => '7037.5479933105', + 'QAR' => '3.9208760535806', + 'RON' => '4.4244625621487', + 'RSD' => '106.13422512354', + 'RUB' => '81.443654502008', + 'RWF' => '1070.2236170055', + 'SAR' => '4.0385831002812', + 'SBD' => '8.5811651495393', + 'SCR' => '22.836425918488', + 'SDG' => '409.74823905175', + 'SEK' => '9.2106892062299', + 'SGD' => '1.4442252419991', + 'SHP' => '0.77972343878383', + 'SLL' => '11009.305450352', + 'SOS' => '622.83776231156', + 'SRD' => '15.24198837198', + 'SSP' => '140.27281371585', + 'STD' => '22204.04937224', + 'STN' => '22.291165698742', + 'SVC' => '9.4201120157998', + 'SYP' => '1086.8852521863', + 'SZL' => '15.823320436045', + 'THB' => '33.332123292761', + 'TJS' => '12.273947657758', + 'TMT' => '3.7690376785312', + 'TND' => '2.9457721627492', + 'TOP' => '2.4455788649597', + 'TRY' => '8.3189327377536', + 'TTD' => '7.3114183534905', + 'TWD' => '30.643246584444', + 'TZS' => '2497.256679004', + 'UAH' => '29.808460735781', + 'UGX' => '3945.9795987375', + 'USD' => '1.0768679081518', + 'UYU' => '47.707876965688', + 'UZS' => '11308.539064999', + 'VES' => '1941046.2073111', + 'VND' => '24912.524365752', + 'VUV' => '116.88367026735', + 'WST' => '2.7063122766172', + 'XAF' => '593.66326771259', + 'XAG' => '0.042055320858178', + 'XAU' => '0.0006191236664337', + 'XCD' => '2.9102893651756', + 'XDR' => '0.75382584246069', + 'XOF' => '593.66326771259', + 'XPD' => '0.00041475567482466', + 'XPF' => '107.99926234548', + 'XPT' => '0.00091222557367446', + 'YER' => '269.64770697132', + 'ZAR' => '15.946586274888', + 'ZMW' => '23.740867890922', + 'ZWL' => '346.75146642487', +];