qonto 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 7f24ba0d4ac1660f45b44441bbc3b43ed68b2343
4
+ data.tar.gz: 7512617e196450d36f421dd38f84f5d1017cbbf6
5
+ SHA512:
6
+ metadata.gz: 7c57c3fd514dc333f9a5196e6cf5ccfa91e10039b506dbf3a02cd95dc293b77e18d0890809aa667c17cb355f2e477df5d18d610ca150a2d9093ecf7364d57382
7
+ data.tar.gz: 16aacda3639335db6c7e750e7acb8a89a085687e7c0d609d6f8b9e846efdddea40666d6e18098effee6eed1f7ee32dac166c9c9fd770c2ca3ef8d0069a337539
@@ -0,0 +1,50 @@
1
+ version: 2
2
+ jobs:
3
+ build-latest: &common-build
4
+ working_directory: ~/qonto-api-ruby
5
+ docker:
6
+ - image: circleci/ruby:2.4.1-node
7
+ steps:
8
+ - checkout
9
+
10
+ - type: cache-restore
11
+ name: Restore bundle cache
12
+ keys:
13
+ - bump-bundle-{{ checksum "qonto-api.gemspec" }}
14
+ # fallback to using the latest cache if no exact match is found
15
+ - bump-bundle-
16
+
17
+ - run:
18
+ name: Bundle Install
19
+ command: bundle install --path vendor/bundle
20
+
21
+ - type: cache-save
22
+ name: Store bundle cache
23
+ key: bump-bundle-{{ checksum "qonto-api.gemspec" }}
24
+ paths:
25
+ - vendor/bundle
26
+
27
+ - run:
28
+ name: Run tests
29
+ command: bundle exec rspec
30
+ build-2-3:
31
+ <<: *common-build
32
+ docker:
33
+ - image: circleci/ruby:2.3.4-node
34
+ build-2-2:
35
+ <<: *common-build
36
+ docker:
37
+ - image: circleci/ruby:2.2.7-node
38
+ build-2-1:
39
+ <<: *common-build
40
+ docker:
41
+ - image: circleci/ruby:2.1.10-node
42
+
43
+ workflows:
44
+ version: 2
45
+ build:
46
+ jobs:
47
+ - build-latest
48
+ - build-2-3
49
+ - build-2-2
50
+ - build-2-1
@@ -0,0 +1,7 @@
1
+ /.bundle/
2
+ /Gemfile.lock
3
+ /coverage/
4
+ /doc/
5
+ /spec/reports/
6
+ /tmp/
7
+ .DS_Store
data/.rspec ADDED
@@ -0,0 +1 @@
1
+ --color
@@ -0,0 +1 @@
1
+ 2.4.1
data/Gemfile ADDED
@@ -0,0 +1,3 @@
1
+ source 'https://rubygems.org'
2
+
3
+ gemspec
data/LICENCE ADDED
@@ -0,0 +1,21 @@
1
+ The MIT License
2
+
3
+ Copyright (c) 2017- Sébastien Charrier
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in
13
+ all copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21
+ THE SOFTWARE.
@@ -0,0 +1,72 @@
1
+ # Qonto API Ruby Client
2
+
3
+ The Qonto API Ruby client provides convenient access to the Qonto API from applications written in Ruby language.
4
+ It is currently up to date with the `v1` version. Qonto API documentation is avaible at https://api-doc.qonto.eu.
5
+
6
+ This project is not affiliated with the Qonto company in any way.
7
+
8
+ ## Installation
9
+
10
+ Add this line to your application's Gemfile:
11
+
12
+ gem 'qonto'
13
+
14
+ And then execute:
15
+
16
+ $ bundle
17
+
18
+ Or install it yourself as:
19
+
20
+ $ gem install qonto
21
+
22
+ ## Requirements
23
+
24
+ * Ruby 2.1+.
25
+
26
+ ## Usage
27
+
28
+ The library needs to be configured with your account's secret key and organization
29
+ slug which are available in your organization dashboard on http://qonto.eu.
30
+
31
+ require 'qonto'
32
+
33
+ # Initialize your client
34
+ client = Qonto::Client.new(slug: 'your-organization-slug', secret_key: 'your-secret-key')
35
+
36
+ You can retrieve your organization bank accounts by calling `get_organization`:
37
+
38
+ # Retrieve your organization object
39
+ organization = client.get_organization
40
+ bank_account = organization.bank_accounts.first
41
+
42
+ # Balance is available for each bank account
43
+ puts "Balance: #{bank_account.balance} €"
44
+
45
+ You can list transactions for a given bank account by calling `list_transactions`:
46
+
47
+ # Paginate through the transactions
48
+ transactions = client.list_transactions(
49
+ bank_account: bank_account,
50
+ per_page: 10,
51
+ current_page: 2
52
+ )
53
+
54
+ transactions.each do |transaction|
55
+ puts " #{transaction.side}: #{transaction.amount} #{transaction.currency} - #{transaction.label}"
56
+ end
57
+
58
+ If a request returns an error, the client raises a `Qonto::Error`. This can be simply
59
+ handled by a `begin/rescue` block:
60
+
61
+ begin
62
+ organization = client.get_organization
63
+ puts "Balance: #{organization.bank_accounts.first.balance} €"
64
+ rescue Qonto::Error => e
65
+ puts "Oops: #{e.to_s}"
66
+ end
67
+
68
+ ## Development
69
+
70
+ After checking out the repo, run `bundle install` to install dependencies. Then, run `rake spec` to run the tests.
71
+
72
+ To install this gem onto your local machine, run `bundle exec rake install`.
@@ -0,0 +1,6 @@
1
+ require 'bundler/gem_tasks'
2
+ require 'rspec/core/rake_task'
3
+
4
+ RSpec::Core::RakeTask.new(:spec)
5
+
6
+ task default: :spec
@@ -0,0 +1,5 @@
1
+ module Qonto
2
+ end
3
+
4
+ require 'qonto/version'
5
+ require 'qonto/client'
@@ -0,0 +1,7 @@
1
+ module Qonto
2
+ module Actions
3
+ end
4
+ end
5
+
6
+ require_relative 'actions/organization'
7
+ require_relative 'actions/transactions'
@@ -0,0 +1,26 @@
1
+ module Qonto
2
+ module Actions
3
+ module Organization
4
+ def get_organization
5
+ response = get("/organizations/#{slug}")
6
+ modelize_organization(response.parsed_response['organization'])
7
+ end
8
+
9
+ private
10
+
11
+ def modelize_organization(organization)
12
+ if !organization['bank_accounts'].nil?
13
+ organization['bank_accounts'] = modelize_bank_accounts(organization['bank_accounts'])
14
+ end
15
+
16
+ Qonto::Model::Organization.new(organization)
17
+ end
18
+
19
+ def modelize_bank_accounts(bank_accounts)
20
+ bank_accounts.map do |bank_account|
21
+ Qonto::Model::BankAccount.new(bank_account)
22
+ end
23
+ end
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,31 @@
1
+ module Qonto
2
+ module Actions
3
+ module Transactions
4
+ def list_transactions(bank_account:, current_page: nil, per_page: nil)
5
+ query = prepare_query_string(bank_account, current_page, per_page)
6
+ response = get("/transactions?#{query}")
7
+
8
+ modelize_transactions(response.parsed_response['transactions'])
9
+ end
10
+
11
+ private
12
+
13
+ def prepare_query_string(bank_account, current_page, per_page)
14
+ {
15
+ slug: bank_account.slug,
16
+ iban: bank_account.iban,
17
+ current_page: current_page,
18
+ per_page: per_page
19
+ }.delete_if { |key, value| value.nil? }
20
+ .map { |(key, value)| "#{key}=#{value}" }
21
+ .join('&')
22
+ end
23
+
24
+ def modelize_transactions(transactions)
25
+ transactions.map do |transaction|
26
+ Qonto::Model::Transaction.new(transaction)
27
+ end
28
+ end
29
+ end
30
+ end
31
+ end
@@ -0,0 +1,72 @@
1
+ require 'httparty'
2
+ require 'qonto/actions'
3
+ require 'qonto/error'
4
+ require 'qonto/model'
5
+
6
+ module Qonto
7
+ class Client
8
+ include Qonto::Actions::Organization
9
+ include Qonto::Actions::Transactions
10
+
11
+ API_VERSION = '1'.freeze
12
+ BASE_URL = 'https://thirdparty.qonto.eu/v'.freeze
13
+ USER_AGENT = "qonto-api-ruby/#{VERSION}".freeze
14
+
15
+ def initialize(slug:, secret_key:)
16
+ @slug = slug
17
+ @secret_key = secret_key
18
+ end
19
+
20
+ def base_url
21
+ "#{BASE_URL}#{API_VERSION}"
22
+ end
23
+
24
+ def get(path)
25
+ execute :get, path
26
+ end
27
+
28
+ private
29
+
30
+ attr_reader :slug, :secret_key
31
+
32
+ def execute(method, path)
33
+ begin
34
+ response = request(method, path)
35
+ rescue *Error::NET_HTTP_ERRORS => err
36
+ raise ConnectionError.new, err.message
37
+ end
38
+
39
+ case response.code
40
+ when 200..299
41
+ response
42
+ when 400
43
+ raise BadRequestError.new(response)
44
+ when 401
45
+ raise AuthenticationError.new(response)
46
+ when 404
47
+ raise NotFoundError.new(response)
48
+ when 400..499
49
+ raise ResponseError.new(response)
50
+ when 500
51
+ raise InternalServerError.new(response)
52
+ when 500..599
53
+ raise ServerError.new(response)
54
+ end
55
+ end
56
+
57
+ def request(method, path)
58
+ HTTParty.send(method, base_url + path, base_options)
59
+ end
60
+
61
+ def base_options
62
+ {
63
+ format: :json,
64
+ headers: {
65
+ 'Accept' => 'application/json',
66
+ 'Authorization' => "#{slug}:#{secret_key}",
67
+ 'User-Agent' => USER_AGENT
68
+ }
69
+ }
70
+ end
71
+ end
72
+ end
@@ -0,0 +1,82 @@
1
+ module Qonto
2
+ class Error < StandardError
3
+ NET_HTTP_ERRORS = [
4
+ EOFError,
5
+ Errno::ECONNABORTED,
6
+ Errno::ECONNREFUSED,
7
+ Errno::ECONNRESET,
8
+ Errno::EHOSTUNREACH,
9
+ Errno::EINVAL,
10
+ Errno::ENETUNREACH,
11
+ Net::HTTPBadResponse,
12
+ Net::HTTPHeaderSyntaxError,
13
+ Net::ProtocolError,
14
+ Net::OpenTimeout,
15
+ Net::ReadTimeout,
16
+ SocketError,
17
+ Zlib::GzipFile::Error,
18
+ OpenSSL::SSL::SSLError
19
+ ]
20
+
21
+ attr_reader :http_response
22
+
23
+ def initialize(response = nil)
24
+ @http_response = response
25
+ super(build_error_message)
26
+ end
27
+
28
+ def http_request
29
+ http_response.request
30
+ end
31
+
32
+ private
33
+
34
+ def build_error_message
35
+ return nil if http_response.nil?
36
+
37
+ message = "#{http_request_method} "
38
+ message << "#{http_request.path} : "
39
+ message << "#{http_response.code} - "
40
+ message << response_message unless response_message.nil?
41
+ message
42
+ end
43
+
44
+ def http_request_method
45
+ http_request.http_method.name.split('::').last.upcase
46
+ end
47
+
48
+ def response_message
49
+ content_type = http_response.headers['Content-Type']
50
+ if content_type && content_type.start_with?('application/json')
51
+ http_response.parsed_response['message']
52
+ else
53
+ net_http_response = http_response.response
54
+ "#{net_http_response.code} #{net_http_response.message}"
55
+ end
56
+ end
57
+ end
58
+
59
+ # Raised on errors in the 400-499 range
60
+ class ResponseError < Error; end
61
+
62
+ # Raised when the API returns a 400 HTTP status code
63
+ class BadRequestError < ResponseError; end
64
+
65
+ # Raised when the API returns a 401 HTTP status code
66
+ class AuthenticationError < ResponseError; end
67
+
68
+ # Raised when the API returns a 402 HTTP status code
69
+ class PaymentRequiredError < ResponseError; end
70
+
71
+ # Raised when the API returns a 404 HTTP status code
72
+ class NotFoundError < ResponseError; end
73
+
74
+ # Raised on errors in the 500-599 range
75
+ class ServerError < Error; end
76
+
77
+ # Raised when the API returns a 500 HTTP status code
78
+ class InternalServerError < ServerError; end
79
+
80
+ # Raised when we can't establish a connection to the API or if reading the reponse times out
81
+ class ConnectionError < Error; end
82
+ end
@@ -0,0 +1,16 @@
1
+ module Qonto
2
+ module Model
3
+ class Base
4
+ def initialize(attributes = {})
5
+ attributes.each do |key, value|
6
+ m = "#{key}=".to_sym
7
+ send(m, value) if respond_to?(m)
8
+ end
9
+ end
10
+ end
11
+ end
12
+ end
13
+
14
+ require_relative 'model/bank_account'
15
+ require_relative 'model/organization'
16
+ require_relative 'model/transaction'
@@ -0,0 +1,12 @@
1
+ module Qonto
2
+ module Model
3
+ class BankAccount < Base
4
+ attr_accessor :slug
5
+ attr_accessor :iban
6
+ attr_accessor :bic
7
+ attr_accessor :current
8
+ attr_accessor :balance
9
+ attr_accessor :balance_cents
10
+ end
11
+ end
12
+ end
@@ -0,0 +1,8 @@
1
+ module Qonto
2
+ module Model
3
+ class Organization < Base
4
+ attr_accessor :slug
5
+ attr_accessor :bank_accounts
6
+ end
7
+ end
8
+ end
@@ -0,0 +1,16 @@
1
+ module Qonto
2
+ module Model
3
+ class Transaction < Base
4
+ attr_accessor :amount
5
+ attr_accessor :amount_cents
6
+ attr_accessor :local_amount
7
+ attr_accessor :local_amount_cents
8
+ attr_accessor :side
9
+ attr_accessor :operation_type
10
+ attr_accessor :currency
11
+ attr_accessor :local_currency
12
+ attr_accessor :settled_at
13
+ attr_accessor :label
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,3 @@
1
+ module Qonto
2
+ VERSION = '0.1.0'.freeze
3
+ end
@@ -0,0 +1,25 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'qonto/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = 'qonto'
8
+ spec.version = Qonto::VERSION
9
+ spec.authors = ['Sébastien Charrier']
10
+ spec.email = ['scharrier@gmail.com']
11
+ spec.licenses = ['MIT']
12
+
13
+ spec.summary = 'A Ruby client for the Qonto Api.'
14
+ spec.homepage = 'https://github.com/scharrier/qonto-ruby'
15
+
16
+ spec.files = `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
17
+ spec.require_paths = ['lib']
18
+ spec.required_ruby_version = '>= 2.1.0'
19
+
20
+ spec.add_runtime_dependency 'httparty', '~> 0'
21
+
22
+ spec.add_development_dependency 'rake', '~> 12'
23
+ spec.add_development_dependency 'rspec', '~> 3'
24
+ spec.add_development_dependency 'webmock', '~> 3'
25
+ end
metadata ADDED
@@ -0,0 +1,120 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: qonto
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Sébastien Charrier
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2017-09-18 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: httparty
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '0'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '0'
27
+ - !ruby/object:Gem::Dependency
28
+ name: rake
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '12'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '12'
41
+ - !ruby/object:Gem::Dependency
42
+ name: rspec
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: '3'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: '3'
55
+ - !ruby/object:Gem::Dependency
56
+ name: webmock
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - "~>"
60
+ - !ruby/object:Gem::Version
61
+ version: '3'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - "~>"
67
+ - !ruby/object:Gem::Version
68
+ version: '3'
69
+ description:
70
+ email:
71
+ - scharrier@gmail.com
72
+ executables: []
73
+ extensions: []
74
+ extra_rdoc_files: []
75
+ files:
76
+ - ".circleci/config.yml"
77
+ - ".gitignore"
78
+ - ".rspec"
79
+ - ".ruby-version"
80
+ - Gemfile
81
+ - LICENCE
82
+ - README.md
83
+ - Rakefile
84
+ - lib/qonto.rb
85
+ - lib/qonto/actions.rb
86
+ - lib/qonto/actions/organization.rb
87
+ - lib/qonto/actions/transactions.rb
88
+ - lib/qonto/client.rb
89
+ - lib/qonto/error.rb
90
+ - lib/qonto/model.rb
91
+ - lib/qonto/model/bank_account.rb
92
+ - lib/qonto/model/organization.rb
93
+ - lib/qonto/model/transaction.rb
94
+ - lib/qonto/version.rb
95
+ - qonto.gemspec
96
+ homepage: https://github.com/scharrier/qonto-ruby
97
+ licenses:
98
+ - MIT
99
+ metadata: {}
100
+ post_install_message:
101
+ rdoc_options: []
102
+ require_paths:
103
+ - lib
104
+ required_ruby_version: !ruby/object:Gem::Requirement
105
+ requirements:
106
+ - - ">="
107
+ - !ruby/object:Gem::Version
108
+ version: 2.1.0
109
+ required_rubygems_version: !ruby/object:Gem::Requirement
110
+ requirements:
111
+ - - ">="
112
+ - !ruby/object:Gem::Version
113
+ version: '0'
114
+ requirements: []
115
+ rubyforge_project:
116
+ rubygems_version: 2.6.11
117
+ signing_key:
118
+ specification_version: 4
119
+ summary: A Ruby client for the Qonto Api.
120
+ test_files: []