Impl. adding a custom Currency Exchange Provider
duraki opened this issue · 3 comments
It seems kinda shitty practice to disallow admins to add new Currency Exchange providers (besides the one that are sponsored and listed in Settings
by default).
Looking at the API -- nothing. Only API routes available is to edit/config a particular predefined Currency Exchange. Furthermore, looking at the API, it all seems hardcoded, notably:
The worst part is hiding the API route for creating an exchange rate provider! You think we aren't looking at the source-code?
- The file ExchangeRateProviderPolicy.php specifically implements an API route (post-auth) that allows creation of exchange providers:
public function create(User $user)
{
...
if (BouncerFacade::can('create-exchange-rate-provider', ExchangeRateProvider::class)) {
return true;
}
Guess what, you will never find create-exchange-rate-provider in Currencies API. Besides;
- [Exch. Rate Drivers] -
example.com/api/v1/config?key=exchange_rate_drivers
are pulled from config API route. - [w. Supported Currencies] -
example.com/api/v1/supported-currencies?driver=open_exchange_rate&key=t&type=FREE
, you see?
Anyway, please add this feature, or at least do some writeup on how to implement it, properly, that is.
Kindly.
I don’t like how you make it sound as if we are trying to scam you into buying exchange-rate services or something. We just collected some free and paid + easy to integrate APIs and patched them here to allow automatic conversion. We have no referral code or any affiliation with the given services.
You are free to modify this software according to your requirements.
I'm just being real, and I think many other issues on this repo will reference to similar situations. There are totally free alternatives, such is fawazahmed0/currency-api repository which updates currency daily and does not rate-limit. CDN is good and uptime is on point. Eh .. 😅
Anyway, Y'all welcome.
// app/Models/ExchangeRateProvider.php
public static function checkExchangeRateProviderStatus($request)
{
switch ($request['driver']) {
case 'cbbh':
// $url = "https://cdn.jsdelivr.net/gh/fawazahmed0/currency-api@1/latest/currencies/usd.json"
/** or **/
// $url = "https://cdn.jsdelivr.net/gh/fawazahmed0/currency-api@1/latest/currencies/".$request->currencies[0]."/".$request->currencies[1].".json";
$response = Http::get($url)->json();
if (array_key_exists('usd', $response)) {
if ($response["usd"] == false) { /* empty ary */
return respondJson($response["error"]["message"], "Error getting exch_rate - via cbbh driver");
}
}
return response()->json([
'exchangeRate' => array_values($response['usd']),
], 200);
break;
...
Additionally, add exchange rate driver in config:
// config/Crater.php
/*
* List of exchange rate drivers
*/
'exchange_rate_drivers' => [
...
['key' => 'settings.exchange_rate.cbbh', 'value' => 'cbbh'],
],
// app/Traits/ExchangeRateProvidersTrait.php
public function getExchangeRate($filter, $baseCurrencyCode, $currencyCode)
{
switch ($filter['driver']) {
case 'cbbh':
$url = "https://cdn.jsdelivr.net/gh/fawazahmed0/currency-api@1/latest/currencies/"; //usd.json";
$url = $url . $currencyCode . "/" . $baseCurrencyCode . ".json";
$response = Http::get($url)->json();
if (str_contains($response["body"], "Package size exceeded")) {
return respondJson($response["error"]["message"], "error in cbbh driver"); }
return response()->json([
'exchangeRate' => array_values([$response[$baseCurrencyCode]]),
], 200);
break;
// ...
}
public function getUrl($request)
{
switch ($request->driver) {
case 'cbbh':
$url = "https://cdn.jsdelivr.net/gh/fawazahmed0/currency-api@1/latest/currencies/usd.json";
return Http::get($url)->json();
break;
// ...
}
public function getSupportedCurrencies($request)
{
// ...
switch ($request->driver) {
case 'cbbh':
$url = "https://cdn.jsdelivr.net/gh/fawazahmed0/currency-api@1/latest/currencies.json";
$response = Http::get($url)->json();
$checkKey = $this->getUrl($request);
if ($response == null || $checkKey == null) {
return respondJson($error_message, $server_message);
}
if ($checkKey['error']['status'] == 404) {
return respondJson($error, $message);
}
return response()->json(['supportedCurrencies' => array_keys($response)]);
break;
// ...
}
// resources/scripts/admin/components/modal-components/ExchangeRateProviderModal.vue
const driverSite = computed(() => {
switch (exchangeRateStore.currentExchangeRate.driver) {
case 'cbbh':
return 'https://github.com/fawazahmed0/currency-api'
// ...
}
Finally, add prefered Locale:
// resources/scripts/locales/en.json
"open_exchange_rate": "Open Exchange Rate",
"cbbh": "Open-source Exchange Rate", // << - driver
Go back to ExchangeRateProviderModal.vue
and add:
// ...
const isCbbhOSSProvider = computer(() => {
return exchangeRateStore.currentExchangeRate.driver == 'cbbh'
})
/**
const isCurrencyConverter = computer(() => { ...
// ...
}
**/
Yeha, don't forget to:
$ docker exec -it crater_app_1 bash
crater-user@f2c5348052eb:/var/www$ composer install --no-interaction --prefer-dist --optimize-autoloader