Giter Site home page Giter Site logo

florianv / swap Goto Github PK

View Code? Open in Web Editor NEW
1.3K 37.0 138.0 966 KB

:currency_exchange: Currency exchange rates library

Home Page: https://florianv.github.io/swap/

License: MIT License

PHP 100.00%
php currency exchange-rates currency-exchange-rates money currency-exchange currency-converter currency-rates

swap's Introduction

Swap

Build status Total Downloads Version

Swap allows you to retrieve currency exchange rates from various services such as Fixer, Currency Data or Exchange Rates Data and optionally cache the results. It is integrated to other libraries like moneyphp/money and provides a Symfony Bundle and a Laravel Package.

Sponsors

Fixer is a simple and lightweight API for foreign exchange rates that supports up to 170 world currencies.
currencylayer provides reliable exchange rates and currency conversions for your business up to 168 world currencies.
exchangerates provides reliable exchange rates and currency conversions for your business with over 15 data sources.

QuickStart

$ composer require php-http/curl-client nyholm/psr7 php-http/message florianv/swap
use Swap\Builder;

// Build Swap
$swap = (new Builder())

    // Use the Fixer service as first level provider
    ->add('apilayer_fixer', ['api_key' => 'Get your key here: https://fixer.io/'])
     
    // Use the currencylayer service as first fallback
    ->add('apilayer_currency_data', ['api_key' => 'Get your key here: https://currencylayer.com'])
    
    // Use the exchangerates service as second fallback
    ->add('apilayer_exchange_rates_data', ['api_key' => 'Get your key here: https://exchangeratesapi.io/'])
->build();
    
// Get the latest EUR/USD rate
$rate = $swap->latest('EUR/USD');

// 1.129
$rate->getValue();

// 2016-08-26
$rate->getDate()->format('Y-m-d');

// Get the EUR/USD rate 15 days ago
$rate = $swap->historical('EUR/USD', (new \DateTime())->modify('-15 days'));

We recommend to use the services that support our project, providing a free plan up to 100 requests per month.

Documentation

The documentation for the current branch can be found here.

Services

Here is the list of the currently implemented services:

Service Base Currency Quote Currency Historical
Fixer EUR (free, no SSL), * (paid) * Yes
Currency Data USD (free), * (paid) * Yes
Exchange Rates Data USD (free), * (paid) * Yes
Abstract * * Yes
coinlayer * Crypto (Limited standard currencies) * Crypto (Limited standard currencies) Yes
Fixer EUR (free, no SSL), * (paid) * Yes
Currency Data USD (free), * (paid) * Yes
exchangeratesapi USD (free), * (paid) * Yes
European Central Bank EUR * Yes
National Bank of Georgia * GEL Yes
National Bank of the Republic of Belarus * BYN (from 01-07-2016),
BYR (01-01-2000 - 30-06-2016),
BYB (25-05-1992 - 31-12-1999)
Yes
National Bank of Romania RON, AED, AUD, BGN, BRL, CAD, CHF, CNY, CZK, DKK, EGP, EUR, GBP, HRK, HUF, INR, JPY, KRW, MDL, MXN, NOK, NZD, PLN, RSD, RUB, SEK, TRY, UAH, USD, XAU, XDR, ZAR RON, AED, AUD, BGN, BRL, CAD, CHF, CNY, CZK, DKK, EGP, EUR, GBP, HRK, HUF, INR, JPY, KRW, MDL, MXN, NOK, NZD, PLN, RSD, RUB, SEK, TRY, UAH, USD, XAU, XDR, ZAR Yes
National Bank of Ukranie * UAH Yes
Central Bank of the Republic of Turkey * TRY Yes
Central Bank of the Republic of Uzbekistan * UZS Yes
Central Bank of the Czech Republic * CZK Yes
Central Bank of Russia * RUB Yes
Bulgarian National Bank * BGN Yes
WebserviceX * * No
1Forge * (free but limited or paid) * (free but limited or paid) No
Cryptonator * Crypto (Limited standard currencies) * Crypto (Limited standard currencies) No
CurrencyDataFeed * (free but limited or paid) * (free but limited or paid) No
Open Exchange Rates USD (free), * (paid) * Yes
Xignite * * Yes
Currency Converter API * * Yes (free but limited or paid)
xChangeApi.com * * Yes
fastFOREX.io USD (free), * (paid) * No
exchangerate.host * * Yes
Array * * Yes

Additionally, you can add your own services as long as they implement the ExchangeRateService interface.

Integrations

Credits

License

The MIT License (MIT). Please see LICENSE for more information.

swap's People

Contributors

0xflotus avatar ahubers avatar albertodiaz avatar andreicio avatar arjanwestdorp avatar avataru avatar dannyweeks avatar ddinchev avatar florianv avatar necenzurat avatar nyholm avatar pascalheidmann avatar pborreli avatar rickogden avatar tyx avatar ugurerkan avatar vinkla avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

swap's Issues

Add change log

We should add a change log that describes how one should migrate from 2.x to 3.0

Introducing HTTPlug

Hey there,

Not sure you heard, but ivory http adapter is going to be deprecated in favor of HTTPlug. There are many advantages in it over ivory. It is basically an HTTP abstraction layer (like ivory) and provides adapters (like ivory). A key difference is that it is an abstraction for CLIENTS, not adapters. So if one day a client decides to implement HTTPlug, the adapter can be deprecated.

We are also planning to submit it as a proposal for an HTTP Client PSR.

Would you be interested in a PR replacing ivory with httplug? Although it is not stable yet (RC1 currently) we plan to release a stable next week.

getDate() format in hour

Hi all,

Can not $rate->getDate() be formatted to Y-m-d H:i? I needed the hour as well and tried
$rate->getDate()->format('Y-m-d H:i') However it just returns 00:00.

Here is the dump of $rate->getDate()

object(DateTime)#6244 (3) {
  ["date"]=>
  string(26) "2018-04-09 00:00:00.000000"
  ["timezone_type"]=>
  int(3)
  ["timezone"]=>
  string(9) "ETC/GMT-3"
  }

Thanks for your effort on this package @florianv.

Local adapter

In some of my applications we work with fixed conversion rates. A local adapter could find rates from a simple hashmap. PR?

PHP warning on GoogleFinanceProvider

Finding this error in our logs:

ERROR - 2016-03-06 00:40:01 --> Severity: Warning  --> DOMDocument::loadHTML(): Unexpected end tag : div in Entity, line: 369 /var/app/current/vendor/florianv/swap/src/Provider/GoogleFinanceProvider.php 36

I'll take a look and submit a pull request if I can find the issue, must be some parsing discrepancy.

Return 1 as exchange rate when currencies are identical

When I ask Swap::latest('EUR/EUR') for the latest exchange rate, it appears that it's actually contacting all the providers:

The chain resulted in 3 exception(s):
Exchanger\Exception\UnsupportedCurrencyPairException: The currency pair "EUR/EUR" is not supported by the service "Exchanger\Service\Fixer".
RuntimeException: Unable to parse JSON data: JSON_ERROR_SYNTAX - Syntax error, malformed JSON
Exchanger\Exception\UnsupportedCurrencyPairException: The currency pair "EUR/EUR" is not supported by the service "Exchanger\Service\EuropeanCentralBank".

This doesn't seem right to me.

I looked at the code (both Swap and Exchanger) to see if I could create a PR to address this. I found out that in https://github.com/florianv/exchanger/blob/master/src/Exchanger.php#L46 it is smart enough to return new ExchangeRate(1) when the currencies are identical.

I could add these checks to all ExchangeRateProvider implementations, but that does seem a bit ugly to me. What if an implementation forgets to add this.

I could also add a check in Swap\Swap::quote to check if the currencies are identical. But the issue is that I need to use Exchanger\CurrencyPair::createFromString (instead of the contract Exchanger\Contract\CurrencyPair to use CurrencyPair::isIdentical.

What's your view on this?

Allow for PSR-16 caching mechanism

Relying on PSR interfaces is great, however, PSR-6 was a bit controversial. It's a more involved interface and many popular frameworks have refused to implement it - so PSR-16 was introduced to allow for simplified caching systems.

Allowing for PSR-16 compatible cache systems would ease the integration of Swap with systems that rely on such systems. I'd introduce this by allowing setHttpCachePool and setSimpleHttpCachePool, with the later expecting PSR-16.

Internally, Exchanger would have its own Cache interface such that would simplify significantly the code of Exchanger, and two adapters, for PSR-6 and PSR-16 cache interfaces, which the adapters would wrap.

If you agree on the value of this and the rough implementation proposal, I would be happy to create a PR.

Determine which service returned a rate

Hi,

We're finding swap really useful, thanks. If we have a few services which can be used by swap, is there a way to know which service actually returned the rate in any particular instance?

Thanks for your help.

Support different currency

Is it possible to support different country currency?
For example, convert the USD dollars to TWD.

Thanks.

Are cryptocurrencies supported by this library?

Hello,

I was wondering if criptocurrencies (DASH, ETH, VTC, XBC, XBT,BTC,XLM,XMR,XRP,ZEC as defined by standard ISO 4217) was supported, i.e:

$example = ( new Builder() )->add('fixer')->build();
$rate = $example->latest( 'BTC/EUR');

Actually it seems not working (btw they are actually showed in Yahoo Finance). Where could I find list of currencies OK with Swap?

Optimize number of requests

Some providers allow to retrieve a whole list of rates (eg ECB).

We should use a runtime cache to avoid querying the service multiple times

NetworkException: cURL error 6: Could not resolve host: www.google.com

I'm trying to get a simple exchange rate but it fails with a cURL exception.

I have debugged it and copy the URL that is trying to connect to and I can access with the browser without problem. Also, I can ping to the servers query.yahoo.com, www.google.com.

I'm using:

  • florianv/swap 3.0.2
  • php-http/message 1.5.0
  • php-http/guzzle6-adapter 1.1.1

The code is:

<?php

require __DIR__ . '/../../../vendor/autoload.php';

use Swap\Builder;

// Create Swap with the provider
$builder = new Builder();
$swap = $builder
  ->add('yahoo')
  ->add('google')
  ->add('european_central_bank')
  ->build();

$rate = $swap->latest('USD/EUR');

var_dump($rate);

And the error is:

( ! ) Fatal error: Uncaught Exchanger\Exception\ChainException: The chain resulted in 2 exception(s): Http\Client\Exception\NetworkException: cURL error 6: Could not resolve host: query.yahooapis.com (see http://curl.haxx.se/libcurl/c/libcurl-errors.html) Http\Client\Exception\NetworkException: cURL error 6: Could not resolve host: www.google.com (see http://curl.haxx.se/libcurl/c/libcurl-errors.html) in /home/jabellota/Proyectos/wsAptana/PaginaPublica/web/areaprivada/vendor/florianv/exchanger/src/Service/Chain.php on line 66
( ! ) Exchanger\Exception\ChainException: The chain resulted in 2 exception(s): Http\Client\Exception\NetworkException: cURL error 6: Could not resolve host: query.yahooapis.com (see http://curl.haxx.se/libcurl/c/libcurl-errors.html) Http\Client\Exception\NetworkException: cURL error 6: Could not resolve host: www.google.com (see http://curl.haxx.se/libcurl/c/libcurl-errors.html) in /home/jabellota/Proyectos/wsAptana/PaginaPublica/web/areaprivada/vendor/florianv/exchanger/src/Service/Chain.php on line 66
Call Stack
#	Time	Memory	Function	Location
1	0.0002	384504	{main}( )	.../borrame.php:0
2	0.0021	500960	Swap\Swap->latest( )	.../borrame.php:15
3	0.0021	500960	Swap\Swap->quote( )	.../Swap.php:51
4	0.0022	503968	Exchanger\Exchanger->getExchangeRate( )	.../Swap.php:91
5	0.0022	503968	Exchanger\Service\Chain->getExchangeRate( )	.../Exchanger.php:54

National Bank of Poland - PR offer

Hello,
I just implemented National Bank of Poland Service in my application using Swap. Would you be interested of me porting it to this package?

Generic HTTP Adapter library

Hi there,

Currently I am working on a generic HTTP Client adapter library utilizing the upcoming PSR for HTTP Messages. I am reaching out for libraries I know whether there is interest for it or not. It collects the best pratices from competitors, and also based on a generic implementation instead of based on needs.

It is unclear where it will be published, but when it gets ready I will be more than happy to open a PR and integrate it into your package.

Are you interested?

Can't install swap

Hi @florianv

composer require florianv/swap php-http/message php-http/guzzle6-adapter

We are unable to install your package, as a follow of florianv/laravel-swap#60

→ composer require florianv/swap php-http/message php-http/guzzle6-adapter
Using version ^3.4 for florianv/swap
Using version ^1.7 for php-http/message
Using version ^2.0 for php-http/guzzle6-adapter
./composer.json has been updated
Loading composer repositories with package information
Updating dependencies (including require-dev)
Your requirements could not be resolved to an installable set of packages.

  Problem 1
    - Conclusion: don't install php-http/guzzle6-adapter v2.0.0
    - don't install php-http/guzzle6-adapter 2.x-dev|install php-http/guzzle6-adapter dev-master
    - Conclusion: remove php-http/httplug v1.1.0
    - Installation request for php-http/guzzle6-adapter ^2.0 -> satisfiable by php-http/guzzle6-adapter[2.x-dev, v2.0.0].
    - Conclusion: don't install php-http/httplug v1.1.0
    - php-http/guzzle6-adapter dev-master requires php-http/httplug ^2.0 -> satisfiable by php-http/httplug[2.0.x-dev, v2.0.0].
    - Can only install one of: php-http/httplug[2.0.x-dev, v1.1.0].
    - Can only install one of: php-http/httplug[v2.0.0, v1.1.0].
    - Installation request for php-http/httplug (locked at v1.1.0) -> satisfiable by php-http/httplug[v1.1.0].


Installation failed, reverting ./composer.json to its original content.

Do you any workaround to allow us to use your package? :)

Best

Yahoo Finance request

Hi,
I have:

$httpAdapter = new \Ivory\HttpAdapter\FileGetContentsHttpAdapter();
$currencyProvider = new \Swap\Provider\YahooFinanceProvider($httpAdapter);
$cache = new \Swap\Cache\DoctrineCache(new FilesystemCache($cachePath), 3600);

$swap = new \Swap\Swap($currencyProvider, $cache);
$rate = $swap->quote("GBP/USD")->getValue();

If I run it I got an Exeption:

PHP TypeError:  Argument 2 passed to Swap\Model\Rate::__construct() must be an instance of DateTime, boolean given, called in /var/www/vendor/florianv/swap/src/Provider/YahooFinanceProvider.php on line 57 in /var/www/vendor/florianv/swap/src/Model/Rate.php on line 30

I started debug it and when you created Yahoo link it returns

{"query":{"count":0,"created":"2017-11-09T14:11:13Z","lang":"en-GB","results":null}}

results: null.
Please fix Yahoo query.

Thanks
Regards.

The "access_key" option must be provided to use fixer.io in project-files/vendor/florianv/exchanger/src/Service/Fixer.php:51

As the fixer.io has changed it API and access_key is required. I am usign Laravel framework. I used "florianv/laravel-swap": "^1.1", and i updated the library today and now i can see one new constant ACCESS_KEY_OPTION = 'access_key' in florianv/exchanger/src/Service/Fixer.php ;
It has these constants now:
const ACCESS_KEY_OPTION = 'access_key';
const LATEST_URL = 'http://data.fixer.io/api/latest?base=%s&access_key=%s';
const HISTORICAL_URL = 'http://data.fixer.io/api/%s?base=%s&access_key=%s';

I have config/swap.php, i tried to pass it the access_key there but it doesnt work.
'currency_layer' => [
'access_key' => '7ca208ea0d6d3323a14427bf9ed21',
// 'enterprise' => true, // Tried also with enabling this.
],

In config/services.php, i tried to pass it but still i can see the above error in laravel log. How to i pass the access_key.
'fixer' => [
'access_key' => '7ca208ea0d6d3323a14427bf9ed21'
],

How to i pass the access key, tried in many ways but its not working.

Drop Interface suffix

I know it's a personal taste, but also a bullshit we learnt from Microsoft, Java, Symfony and the FIG, so I usualy try to convince people to drop it.

My main source is: http://verraes.net/2013/09/sensible-interfaces/

Although in your case it is probably harder, as you have an interface for the main entry point as well.

Error with Google Finance Provider

Using sample code adapted for Google finance:

$httpAdapter = new \Ivory\HttpAdapter\FileGetContentsHttpAdapter();

// Create the Yahoo Finance provider
$googleProvider = new \Swap\Provider\YahooFinanceProvider($httpAdapter);

// Create Swap with the provider
$swap = new \Swap\Swap($yahooProvider);

$rate = $swap->quote('EUR/USD');

Throws this error:

Fatal error: Uncaught exception 'Swap\Exception\Exception' with message 'The currency is not supported or Google changed the response format'

Low value currencies should have their rates calculated inversely

More of a suggestion rather than an issue...

When using a low value currency as the base currency, the rate returned from Yahoo and other providers is given to four decimal points and rounded. This can give some very big errors in the conversion.

It would be interesting to have some kind of table where if isLowValueBase == true, then the base and quote rates are swapped and the inverse of the resulting rate is served.

E.g.
Colombian Peso => US Dollar (COP/USD)
Rate given: 0.0003
US Dollar => Colombian Peso (USD/COP)
Rate given: 2,906.70

COP/USD calculated as inverse of USD/COP
0.000344 (to 6 decimal points)

COP/USD conversion with rates as given by provider for a house worth COP 1,000,000,000
COP 1,000,000,000 * 0.0003 = USD 300,000

COP/USD conversion with inverse of inverted rates for a house worth COP 1,000,000,000
COP 1,000,000,000 * 0.000344 = USD 344,000

$44,000 difference!!

I'm going to implement my own solution as above, storing currencies in an exchange_rates table and saving the inverted rate when needed, but I wonder if it might be a good idea to add this as a feature to Swap.

Caching

I think caching is a great idea in this library, but I think caching should be transparent from Swap point of view.

I would implement a Cache provider which decorates other providers. This provider could accept another provider instance and an implementation of PSR-6 (although doctrine does not implement these interfaces, there are already quite good compatibility libraries: https://github.com/php-cache).

This way caching can be made optional (as it is now) and transparent from Swap's point of view.

WDYT? Would you accept a PR?

Doesn't work with PHP 5.6

Due to the dependency of Nyholm\Psr7 it does not work on anything below PHP 7.1

Need to find an alternative unfortunately due to this

Historical rates

Some providers support retrieving historical rates, we should allow to do that for the providers support it.

Google plugin stopped working

Error has already been quoted in #8 and #9 .
But I ran composer update and some laravel packages have been updated, but error is still happening 😢

Exchanger\Exception\ChainException with message 'The chain resulted in 1 exception(s):
Exchanger\Exception\Exception: The currency is not supported or Google changed the response format'

My code:

$exchange = \Swap::latest('EUR/BRL')->getValue();

PS.: it WAS working until a few days ago, then only EUR started to give a headache after update I tried the composer update now in Tinker none works 😭

Btw, composer update (of SWAP part)

  - Updating php-http/discovery (1.3.0 => 1.4.0): Downloading (100%)         
  - Updating florianv/exchanger (0.7.0 => 1.0.1): Downloading (100%)         
  - Updating florianv/swap (3.2.0 => 3.3.0): Downloading (100%)         
  - Updating florianv/laravel-swap (1.1.0 => 1.2.0): Downloading (100%)

Historical Rates

Hi,

Thank you for this great library! Would it be possible to retrieve historical rates? For example I would like to pull yesterday's or end of last year's exchange rate.

Thanks! Sacha

`Swap\Builder` could just be static

There is no actual need for making Swap\Builder an instantiable class:

  • $currencyConverter = Swap\Builder::fromYahooFinance();
  • $currencyConverter = Swap\Builder::fromGoogleFinance();

These are perfectly fine. If multiple providers are required, then just allow constructor injection in the converter itself, which also plays better with other libraries willing to integrate Swap.

Error with Yahoo Provider

Using sample code:

$httpAdapter = new \Ivory\HttpAdapter\FileGetContentsHttpAdapter();

// Create the Yahoo Finance provider
$yahooProvider = new \Swap\Provider\YahooFinanceProvider($httpAdapter);

// Create Swap with the provider
$swap = new \Swap\Swap($yahooProvider);

$rate = $swap->quote('EUR/USD');

Throws this error:

Catchable fatal error: Argument 2 passed to Swap\Model\Rate::__construct() must be an instance of DateTime, boolean given

PHP Array support historical exchange rates

I'm currently working on a project where e.g. I need to convert COP -> EUR at historical rates. It seems that there is no provider out of the box capable of doing this. The PHP Array solution could serve as a backup if e.g. the project has them already in a database somewhere, providing an array looking like:

Array
(
    [2017-02-01] => Array
        (
            [COP/EUR] => new ExchangeRate(1.5)
        )

    [backup] => Array
        (
            [COP/EUR] => new ExchangeRate(2)
        )

)

The backup key could serve as a backup which is configurable, whether to use it or not.

Would such a PR be interesting to the project, or would it be rejected? I'm happy to submit one if there is interest.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.