slimpay 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: da6174b556ef0ad19597db53786c756bb69f45cc
4
+ data.tar.gz: 2359c26e53cdab82ee2b14c88710465cc3485dca
5
+ SHA512:
6
+ metadata.gz: 2c7a087742b691ad7b73477dafb57c970d25131d93ddad0d44e17c5858790eae2f16de1e7ecbf2875a23f80a1a3c88a812df61e1addf3327fc58bdc7d1734257
7
+ data.tar.gz: 7de499353a64bd599284e87854305c86fbccd26399268d99433f25eea67a8bc1a79d22ac185e3c00bd41a676bd8619b382af55d32b24a03fc591738c7e6932a1
data/.gitignore ADDED
@@ -0,0 +1,11 @@
1
+ /.bundle/
2
+ /.yardoc
3
+ /Gemfile.lock
4
+ /_yardoc/
5
+ /coverage/
6
+ /doc/
7
+ /pkg/
8
+ /spec/reports/
9
+ /tmp/
10
+ builds/
11
+ *.DS_Store
data/.gitlab-ci.yml ADDED
@@ -0,0 +1,12 @@
1
+ before_script:
2
+ - gem install bundler -v 1.10.4
3
+ - bundle install
4
+
5
+ rspec:
6
+ script:
7
+ - 'rake spec'
8
+ - 'rubocop --config .rubocop.yml --force-exclusion'
9
+ tags:
10
+ - ruby
11
+ only:
12
+ - branches
data/.rspec ADDED
@@ -0,0 +1,2 @@
1
+ --format documentation
2
+ --color
data/.rubocop.yml ADDED
@@ -0,0 +1,134 @@
1
+ AllCops:
2
+ Exclude:
3
+ - 'bin/**/*'
4
+ RunRailsCops: false
5
+
6
+ LineLength:
7
+ Max: 160
8
+ Severity: error
9
+
10
+ MethodLength:
11
+ Max: 40
12
+ Severity: error
13
+
14
+ AbcSize:
15
+ Max: 35
16
+
17
+ PerceivedComplexity:
18
+ Max: 8
19
+
20
+ TrailingBlankLines:
21
+ Severity: error
22
+
23
+ EndOfLine:
24
+ Severity: error
25
+
26
+ TrailingComma:
27
+ EnforcedStyleForMultiline: no_comma
28
+ Severity: error
29
+
30
+ EmptyLines:
31
+ Severity: error
32
+
33
+ ### Disabled checks
34
+
35
+ Documentation:
36
+ Enabled: false
37
+
38
+ DotPosition:
39
+ Enabled: false
40
+
41
+ StringLiterals:
42
+ Enabled: false
43
+
44
+ NumericLiterals:
45
+ Enabled: false
46
+
47
+ AccessModifierIndentation:
48
+ Enabled: false
49
+
50
+ EmptyLinesAroundAccessModifier:
51
+ Enabled: false
52
+
53
+ AssignmentInCondition:
54
+ Enabled: false
55
+
56
+ WordArray:
57
+ Enabled: false
58
+
59
+ RedundantBegin:
60
+ Enabled: false
61
+
62
+ RaiseArgs:
63
+ Enabled: false
64
+
65
+ HandleExceptions:
66
+ Enabled: false
67
+
68
+ RedundantSelf:
69
+ Enabled: false
70
+
71
+ SignalException:
72
+ Enabled: false
73
+
74
+ PredicateName:
75
+ Enabled: false
76
+
77
+ BlockComments:
78
+ Enabled: false
79
+
80
+ UnusedBlockArgument:
81
+ Enabled: false
82
+
83
+ PercentLiteralDelimiters:
84
+ Enabled: false
85
+
86
+ ### Following checks should be enabled once we decide on the style to use
87
+
88
+ IfUnlessModifier:
89
+ Enabled: false
90
+
91
+ AlignArray:
92
+ Enabled: false
93
+
94
+ AlignHash:
95
+ Enabled: false
96
+
97
+ AlignParameters:
98
+ Enabled: false
99
+
100
+ SpaceBeforeBlockBraces:
101
+ Enabled: false
102
+
103
+ SpaceInsideBlockBraces:
104
+ Enabled: false
105
+
106
+ SpaceInsideHashLiteralBraces:
107
+ Enabled: false
108
+
109
+ HashSyntax:
110
+ Enabled: false
111
+
112
+ ParenthesesAroundCondition:
113
+ Enabled: false
114
+
115
+ CollectionMethods:
116
+ Enabled: false
117
+
118
+ AndOr:
119
+ Enabled: false
120
+
121
+ RescueModifier:
122
+ Enabled: false
123
+
124
+ ClassLength:
125
+ Enabled: false
126
+
127
+ IndentationWidth:
128
+ Enabled: false
129
+
130
+ EndAlignment:
131
+ Enabled: false
132
+
133
+ CyclomaticComplexity:
134
+ Enabled: false
data/.travis.yml ADDED
@@ -0,0 +1,8 @@
1
+
2
+ language: ruby
3
+ cache: bundler
4
+ rvm:
5
+ - "2.2.3"
6
+ script:
7
+ - bundle exec rspec
8
+ - bundle exec rubocop -R --config .rubocop.yml --fail-level error --force-exclusion
@@ -0,0 +1,13 @@
1
+ # Contributor Code of Conduct
2
+
3
+ As contributors and maintainers of this project, we pledge to respect all people who contribute through reporting issues, posting feature requests, updating documentation, submitting pull requests or patches, and other activities.
4
+
5
+ We are committed to making participation in this project a harassment-free experience for everyone, regardless of level of experience, gender, gender identity and expression, sexual orientation, disability, personal appearance, body size, race, ethnicity, age, or religion.
6
+
7
+ Examples of unacceptable behavior by participants include the use of sexual language or imagery, derogatory comments or personal attacks, trolling, public or private harassment, insults, or other unprofessional conduct.
8
+
9
+ Project maintainers have the right and responsibility to remove, edit, or reject comments, commits, code, wiki edits, issues, and other contributions that are not aligned to this Code of Conduct. Project maintainers who do not follow the Code of Conduct may be removed from the project team.
10
+
11
+ Instances of abusive, harassing, or otherwise unacceptable behavior may be reported by opening an issue or contacting one or more of the project maintainers.
12
+
13
+ This Code of Conduct is adapted from the [Contributor Covenant](http://contributor-covenant.org), version 1.0.0, available at [http://contributor-covenant.org/version/1/0/0/](http://contributor-covenant.org/version/1/0/0/)
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in slimpay.gemspec
4
+ gemspec
data/LICENSE.txt ADDED
@@ -0,0 +1,21 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2015 Gregory Durelle
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.
data/README.md ADDED
@@ -0,0 +1,172 @@
1
+ [![Build Status](https://travis-ci.org/novagile/slimpay.svg)](https://travis-ci.org/novagile/slimpay)
2
+
3
+ # Slimpay
4
+
5
+ Ruby implementation of the Slimpay Hypermedia API.
6
+
7
+ ## Installation
8
+
9
+ Add this line to your application's Gemfile:
10
+
11
+ ```ruby
12
+ gem 'slimpay'
13
+ ```
14
+
15
+ And then execute:
16
+
17
+ $ bundle
18
+
19
+ Or install it yourself as:
20
+
21
+ $ gem install slimpay
22
+
23
+
24
+ ## Usage
25
+
26
+ **API Docs: https://api-sandbox.slimpay.net/docs/**
27
+
28
+ ### Configuration
29
+
30
+ If you use _Rails_ place this code in _config/initializers/slimpay.rb_:
31
+
32
+ ```ruby
33
+ Slimpay.configure do |config|
34
+ config.client_id = "your_client_id"
35
+ config.client_secret = "your_client_secret"
36
+ config.creditor_reference = "your_creditor_reference"
37
+ config.sandbox = true
38
+ config.notify_url = 'you_notifications_url'
39
+ config.return_url = 'your_return_url'
40
+ end
41
+ ```
42
+
43
+ ### Notification and return URLs
44
+
45
+ The notification URL is the point of your application where Slimpay will send a POST request with the result of the current order.
46
+ The state of the order will be either **close.completed** or **closed.aborted.aborted_byclient** if everything worked normally, or one of those quoted in the [API Order documentation](https://api-sandbox.slimpay.net/docs/alps/v1/orders/).
47
+
48
+ The return URL is the point of your application where your user/customer will be redirected to when he will have finish signing its mandate with Slimpay.
49
+
50
+ ### The root endpoint:
51
+
52
+ The Slimpay API uses self-discovery. It means that each time you will perform a request, the answer will be a Hash of links to follow in order to perform more requestq.
53
+
54
+ The more you do requests, the more methods will appear.
55
+
56
+ When you emplement any class, it will inherits from the root-endpoint and thus already have available methods.
57
+
58
+ ```ruby
59
+ slimpay = Slimpay::Base.new(client_id = '1234', client_secret = '987654321', creditor_reference = 'azerty')
60
+ slimpay.api_methods
61
+ ```
62
+ :warning: If you call ```Slimpay::Base.new``` without arguments, the _Sandbox_ credentials will be used.
63
+
64
+ Result will be a Hash:
65
+
66
+ ```ruby
67
+ {"self"=>"https://api-sandbox.slimpay.net/"
68
+ "post_token"=>"https://api-sandbox.slimpay.net/oauth/token",
69
+ "create_orders"=>"https://api-sandbox.slimpay.net/orders",
70
+ "get_creditors"=>"https://api-sandbox.slimpay.net/creditors{?reference}",
71
+ "get_orders"=>"https://api-sandbox.slimpay.net/orders{?creditorReference,reference}",
72
+ "get_mandates"=>"https://api-sandbox.slimpay.net/mandates{?creditorReference,rum}",
73
+ "create_documents"=>"https://api-sandbox.slimpay.net/documents",
74
+ "get_documents"=>"https://api-sandbox.slimpay.net/documents{?creditorReference,entityReference,reference}",
75
+ "create_direct_debits"=>"https://api-sandbox.slimpay.net/direct-debits",
76
+ "get_direct_debits"=>"https://api-sandbox.slimpay.net/direct-debits{?id}",
77
+ "create_recurrent_direct_debits"=>"https://api-sandbox.slimpay.net/recurrent-direct-debits",
78
+ "get_recurrent_direct_debits"=>"https://api-sandbox.slimpay.net/recurrent-direct-debits{?id}",
79
+ "get_card_transactions"=>"https://api-sandbox.slimpay.net/card-transactions{?id}",
80
+ "get_card_transaction_issues"=>"https://api-sandbox.slimpay.net/card-transaction-issues{?id}",
81
+ "profile"=>"https://api-sandbox.slimpay.net/alps/v1"}
82
+ ```
83
+
84
+ The keys of this Hash are the methods name you can call on the class instance (here Slimpay::Base).
85
+ The value is the URL that will be used, with its arguments.
86
+
87
+ **Example:**
88
+
89
+ ```ruby
90
+ "get_orders"=>"https://api-sandbox.slimpay.net/orders{?creditorReference,reference}",
91
+ ```
92
+
93
+ The arguments will be _creditorReference_ and _reference_. You can give them as a Hash.
94
+ See below for an example.
95
+
96
+ Some methods as been added to this gem as shortcuts to these root methods.
97
+
98
+ ### Available resources :
99
+ **Order**, **Mandate**, **App**
100
+
101
+ Each resource inherit from _Resource_ wich itself inherits from _Base_.
102
+ _Base_ defines root methods according to the Slimpay API.
103
+
104
+ **Example:**
105
+
106
+ The official API method:
107
+
108
+ ```ruby
109
+ orders = Slimpay::Order.new(client_id = '1234', client_secret = '987654321', creditor_reference = 'azerty')
110
+ orders.get_orders({creditorReference: 'mysellername', reference: 1234})
111
+ ```
112
+
113
+ The shortcut:
114
+
115
+ ```ruby
116
+ orders = Slimpay::Order.new(client_id = '1234', client_secret = '987654321', creditor_reference = 'azerty')
117
+ orders.get_one(1234)
118
+ ```
119
+
120
+ Result will be a Hash:
121
+
122
+ ```json
123
+ {"_links"=>
124
+ {"self"=>{"href"=>"https://api-sandbox.slimpay.net/creditors/democreditor/orders/1"},
125
+ "https://api.slimpay.net/alps#get-creditor"=>{"href"=>"https://api-sandbox.slimpay.net/creditors/democreditor"},
126
+ "https://api.slimpay.net/alps#get-subscriber"=>{"href"=>"https://api-sandbox.slimpay.net/creditors/democreditor/orders/1/subscribers/subscriber01"},
127
+ "https://api.slimpay.net/alps#user-approval"=>{"href"=>"https://slimpay.net/slimpaytpe16/userApproval?accessCode=spK534N0cuZztBGwj2FjC6eKzcsKFRzXbfy8buloUHiZV6p9PhIfcPgV7c507R"},
128
+ "https://api.slimpay.net/alps#get-order-items"=>{"href"=>"https://api-sandbox.slimpay.net/creditors/democreditor/orders/1/items"},
129
+ "https://api.slimpay.net/alps#get-mandate"=>{"href"=>"https://api-sandbox.slimpay.net/creditors/democreditor/mandates/1"}},
130
+ "reference"=>"1",
131
+ "state"=>"closed.completed",
132
+ "started"=>true,
133
+ "dateCreated"=>"2014-12-12T09:35:39.000+0000",
134
+ "mandateReused"=>false}
135
+ ```
136
+
137
+ Now you can call new methods : get_creditor, get_subscriber, user_approval, get_order_items, get_mandate
138
+
139
+ **NB:** Note that the methods in the resulting Hash are dashed-named, but the generated methods are camelcased.
140
+
141
+ ## Credentials
142
+ The sanbox let you test credentials connection and few methods.
143
+
144
+ You will need a test environment setted up by Slimpay to go further.
145
+
146
+ ### SANDBOX
147
+
148
+ * client_id = 'democreditor01'
149
+ * client_secret = 'demosecret01'
150
+ * creditor_reference : democreditor
151
+
152
+ ### Test
153
+
154
+ * IBAN : FR1420041010050500013M02606
155
+ * BIC : PSSTFRPP
156
+ * Code for phone verification : 0000
157
+
158
+ ## Development
159
+
160
+ After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake rspec` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
161
+
162
+ To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and tags, and push the `.gem` file to [rubygems.org](https://rubygems.org).
163
+
164
+ ## Contributing
165
+
166
+ Bug reports and pull requests are welcome on GitHub at https://github.com/novagile/slimpay. This project is intended to be a safe, welcoming space for collaboration, and contributors are expected to adhere to the [Contributor Covenant](contributor-covenant.org) code of conduct.
167
+
168
+
169
+ ## License
170
+
171
+ The gem is available as open source under the terms of the [MIT License](http://opensource.org/licenses/MIT).
172
+
data/Rakefile ADDED
@@ -0,0 +1,15 @@
1
+ require 'bundler/gem_tasks'
2
+ require 'rspec/core/rake_task'
3
+ require 'rubocop/rake_task'
4
+
5
+ desc 'Run RuboCop on the lib directory'
6
+ RuboCop::RakeTask.new(:rubocop) do |task|
7
+ task.patterns = ['lib/**/*.rb', 'spec/**/*.rb']
8
+ task.formatters = ['progress']
9
+ task.fail_on_error = false
10
+ task.options = ["--config", ".rubocop.yml", "--force-exclusion"]
11
+ end
12
+
13
+ RSpec::Core::RakeTask.new(:spec)
14
+
15
+ task default: [:spec, :rubocop]
data/bin/console ADDED
@@ -0,0 +1,14 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'bundler/setup'
4
+ require 'slimpay'
5
+
6
+ # You can add fixtures and/or initialization code here to make experimenting
7
+ # with your gem easier. You can also use a different console, if you like.
8
+
9
+ # (If you use this, don't forget to add pry to your Gemfile!)
10
+ # require 'pry'
11
+ # Pry.start
12
+
13
+ require 'irb'
14
+ IRB.start
data/bin/setup ADDED
@@ -0,0 +1,7 @@
1
+ #!/bin/bash
2
+ set -euo pipefail
3
+ IFS=$'\n\t'
4
+
5
+ bundle install
6
+
7
+ # Do any other automated setup that you need to do here
@@ -0,0 +1,54 @@
1
+ module Slimpay
2
+ # Used only to get and set callback URLs.
3
+ class App < Resource
4
+ # Prepare an admin token for app requests.
5
+ #
6
+ # Arguments:
7
+ # username: Your Slimpay admin username
8
+ # password: Your Slimpay admin password
9
+ def initialize(username = nil, password = nil)
10
+ init_config
11
+ @username = username || Slimpay.configuration.username
12
+ @password = password || Slimpay.configuration.password
13
+ @basic_auth = { username: "#{@creditor_reference}##{@username}", password: @password }
14
+ response = HTTParty.post(@token_endpoint, basic_auth: @basic_auth, body: app_options)
15
+ @token = response['access_token']
16
+ end
17
+
18
+ # Change the returnUrl
19
+ # ===== Example:
20
+ # app = Slimpay::App.new
21
+ # app.return_url = "mywebsite.com/client/123/"
22
+ def return_url(url)
23
+ response = HTTParty.patch("#{@endpoint}/creditors/#{@creditor_reference}/apps/#{@client_id}", body: { returnUrl: url }.to_json, headers: options)
24
+ Slimpay.answer(response)
25
+ end
26
+
27
+ # Change the notifyUrl
28
+ def notify_url(url)
29
+ response = HTTParty.patch("#{@endpoint}/creditors/#{@creditor_reference}/apps/#{@client_id}", body: { notifyUrl: url }.to_json, headers: options)
30
+ Slimpay.answer(response)
31
+ end
32
+
33
+ # Change the notification and return URLs.
34
+ #
35
+ # ===== Arguments:
36
+ # returnUrl: (String) URL to your app the customer is gonna be redirected to when leaving Slimpay platform.
37
+ # notifyUrl: (String) URL to your app Slimpay is gonna send a notification to, to confirm a Signature, a payment, etc.
38
+ def change_urls(urls_params)
39
+ response = HTTParty.patch("#{@endpoint}/creditors/#{@creditor_reference}/apps/#{@client_id}", body: urls_params.to_json, headers: options)
40
+ Slimpay.answer(response)
41
+ end
42
+
43
+ private
44
+
45
+ def app_options
46
+ {
47
+ 'Accept' => API_HEADER,
48
+ 'Content-type' => 'application/hal+json',
49
+ 'grant_type' => 'client_credentials',
50
+ 'scope' => 'api_admin'
51
+ }
52
+ end
53
+ end
54
+ end
@@ -0,0 +1,176 @@
1
+ module Slimpay
2
+ # Defines constants, main variables, requests options.
3
+ #
4
+ # Connect to the HAPI through OAuth2 and generates HAPI's first resources GET methods.
5
+ # ===== Usage:
6
+ # slimpay = Slimpay::Base.new(client_id = '1234', client_secret = '987654321', creditor_reference = 'azerty')
7
+ # slimpay.api_methods
8
+ # =>
9
+ # { "post_token"=>"https://api-sandbox.slimpay.net/oauth/token",
10
+ # "create_orders"=>"https://api-sandbox.slimpay.net/orders",
11
+ # "get_creditors"=>"https://api-sandbox.slimpay.net/creditors{?reference}",
12
+ # "get_orders"=>"https://api-sandbox.slimpay.net/orders{?creditorReference,reference}",
13
+ # "get_mandates"=>"https://api-sandbox.slimpay.net/mandates{?creditorReference,rum}",
14
+ # "create_documents"=>"https://api-sandbox.slimpay.net/documents",
15
+ # "get_documents"=>"https://api-sandbox.slimpay.net/documents{?creditorReference,entityReference,reference}",
16
+ # "create_direct_debits"=>"https://api-sandbox.slimpay.net/direct-debits",
17
+ # "get_direct_debits"=>"https://api-sandbox.slimpay.net/direct-debits{?id}",
18
+ # "create_recurrent_direct_debits"=>"https://api-sandbox.slimpay.net/recurrent-direct-debits",
19
+ # "get_recurrent_direct_debits"=>"https://api-sandbox.slimpay.net/recurrent-direct-debits{?id}",
20
+ # "get_card_transactions"=>"https://api-sandbox.slimpay.net/card-transactions{?id}",
21
+ # "get_card_transaction_issues"=>"https://api-sandbox.slimpay.net/card-transaction-issues{?id}",
22
+ # "profile"=>"https://api-sandbox.slimpay.net/alps/v1"}
23
+ #
24
+ # ===== Arguments
25
+ # client_id: (String)
26
+ # client_secret: (String)
27
+ # creditor_reference: (String)
28
+ class Base
29
+ def initialize
30
+ init_config
31
+ connect_api_with_oauth
32
+ api_response = JSON.parse(request_to_api)
33
+ generate_api_methods(api_response)
34
+ end
35
+
36
+ # Root endpoint provides GET links to resources.
37
+ # This methods create a method for each resources.
38
+ # It will also create new methods from future answers.
39
+ def generate_api_methods(response)
40
+ methods = {}
41
+ links = response['_links']
42
+ links = links.merge(response['_embedded']['items'].first['_links']) if response['_embedded'] && response['_embedded']['items']
43
+ return if links.nil?
44
+ links.each do |k, v|
45
+ name = k.gsub('https://api.slimpay.net/alps#', '').underscore
46
+ next if @methods && @methods.keys.include?(name) && !k.eql?('self')
47
+ url = v['href']
48
+ api_args = url.scan(/{\?(.*),?}/).flatten.first
49
+ methods[name] = generate_method(name, url, api_args)
50
+ end
51
+ list_api_methods(methods)
52
+ end
53
+
54
+ private
55
+
56
+ def init_config
57
+ Slimpay.configuration ||= Slimpay::Configuration.new
58
+ @client_id = Slimpay.configuration.client_id
59
+ @client_secret = Slimpay.configuration.client_secret
60
+ @creditor_reference = Slimpay.configuration.creditor_reference
61
+ @sandbox = Slimpay.configuration.sandbox
62
+ @return_url = Slimpay.configuration.return_url
63
+ @notify_url = Slimpay.configuration.notify_url
64
+ @endpoint = sandbox? ? SANDBOX_ENDPOINT : PRODUCTION_ENDPOINT
65
+ @token_endpoint = @endpoint + '/oauth/token'
66
+ end
67
+
68
+ # A request call to the endpoint.
69
+ # An empty call will return list of available methods in the API.
70
+ def request_to_api(url = '')
71
+ response = HTTParty.get("#{@endpoint}/#{url}", headers: options)
72
+ Slimpay.answer response
73
+ end
74
+
75
+ # OAuth2 call to retrieve the token
76
+ def connect_api_with_oauth
77
+ client = OAuth2::Client.new(@client_id, @client_secret, site: @token_endpoint, headers: oauth_options)
78
+ response = client.client_credentials.get_token
79
+ @token = response.token
80
+ end
81
+
82
+ # === Arguments:
83
+ # name: (String) The method name
84
+ # url: (String) URL called in the method block
85
+ # api_args: (String) API arguments for this URL.
86
+ def generate_method(name, url, api_args)
87
+ if name.start_with?('create', 'post')
88
+ generate_post_method(name, url)
89
+ elsif name.start_with?('patch')
90
+ generate_patch_method(name, url)
91
+ else
92
+ generate_get_method(name, url, api_args)
93
+ end
94
+ url
95
+ end
96
+
97
+ def generate_get_method(name, url, api_args)
98
+ self.class.send(:define_method, name) do |method_arguments = nil|
99
+ if api_args.nil?
100
+ response = HTTParty.get(url, headers: options)
101
+ follow_up_api(response)
102
+ else
103
+ clean_url = url.gsub(/{\?.*/, '')
104
+ url_args = format_html_arguments(api_args, method_arguments)
105
+ response = HTTParty.get("#{clean_url}?#{url_args}", headers: options)
106
+ follow_up_api(response)
107
+ end
108
+ end
109
+ end
110
+
111
+ def generate_post_method(name, url)
112
+ self.class.send(:define_method, name) do |method_arguments = nil|
113
+ response = HTTParty.post(url, body: method_arguments.to_json, headers: options)
114
+ follow_up_api(response)
115
+ end
116
+ end
117
+
118
+ def generate_patch_method(name, url)
119
+ self.class.send(:define_method, name) do |method_arguments = nil|
120
+ response = HTTParty.patch(url, body: method_arguments.to_json, headers: options)
121
+ follow_up_api(response)
122
+ end
123
+ end
124
+
125
+ # Change APIs documented URL's arguments into real HTTP arguments through given method arguments
126
+ # ===== Arguments
127
+ # api_args: (String) Slimpay given argument within URLs. Formated like: ?{arg1, arg2}
128
+ # method_arguments: (String) Arguments called on the currently defined method.
129
+ def format_html_arguments(api_args, method_arguments)
130
+ url_args = ''
131
+ api_args.split(',').each_with_index do |arg, index|
132
+ url_args += "#{arg}=#{method_arguments[arg.to_sym]}"
133
+ url_args += '&' if (index + 1) < api_args.size
134
+ end
135
+ url_args
136
+ end
137
+
138
+ # Create the 'api_methods' instance method to retrieve an array of API methods previously created.
139
+ #
140
+ # ===== Usage:
141
+ # slim = Slimpay::Base.new
142
+ # slim.api_methods
143
+ # => [apps, creditors, direct_debits, mandates, orders, recurrent_direct_debits, subscribers, ...]
144
+ def list_api_methods(methods)
145
+ @methods ||= methods
146
+ self.class.send(:define_method, 'api_methods') do
147
+ @methods = @methods.merge(methods) if @methods != methods
148
+ @methods
149
+ end
150
+ end
151
+
152
+ # Catch up potential errors and generate new methods if needed.
153
+ def follow_up_api(response)
154
+ answer = Slimpay.answer(response)
155
+ generate_api_methods(JSON.parse(response))
156
+ answer
157
+ end
158
+
159
+ def oauth_options
160
+ {
161
+ 'Accept' => @sandbox ? SANDBOX_API_HEADER : API_HEADER,
162
+ 'Content-type' => 'application/hal+json',
163
+ 'grant_type' => 'client_credentials',
164
+ 'scope' => 'api_admin'
165
+ }
166
+ end
167
+
168
+ def options
169
+ { 'Authorization' => "Bearer #{@token}", 'Content-type' => 'application/json' }
170
+ end
171
+
172
+ def sandbox?
173
+ @sandbox || @client_id.eql?('democreditor01') ? true : false
174
+ end
175
+ end
176
+ end
@@ -0,0 +1,21 @@
1
+ module Slimpay
2
+ class Configuration
3
+ attr_accessor :client_id
4
+ attr_accessor :client_secret
5
+ attr_accessor :creditor_reference
6
+ attr_accessor :sandbox
7
+ attr_accessor :return_url
8
+ attr_accessor :notify_url
9
+ attr_accessor :username
10
+ attr_accessor :password
11
+
12
+ def initialize
13
+ @client_id = Slimpay::SANDBOX_CLIENT_ID
14
+ @client_secret = Slimpay::SANDBOX_SECRET_ID
15
+ @creditor_reference = Slimpay::SANDBOX_CREDITOR
16
+ @sandbox = true
17
+ @return_url = 'localhost:5000'
18
+ @notify_url = 'localhost:5000'
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,38 @@
1
+ module Slimpay
2
+ class DirectDebit < Resource
3
+ # Override the Resource#get_one method because the url is not the same for DirectDebits
4
+ #
5
+ def get_one(reference = 1)
6
+ url = "#{@endpoint}/#{@resource_name}/#{reference}"
7
+ response = HTTParty.get(url, headers: options)
8
+ generate_api_methods(JSON.parse(response))
9
+ Slimpay.answer(response)
10
+ end
11
+
12
+ # Alias method for create_direct_debits
13
+ # ===== Arguments
14
+ # debit_hash: (Hash) Your payment informations. See API DirectDebit documentation for details.
15
+ #
16
+ # /!\ Amount as to be rounded to maximum 2 numbers after comma.
17
+ # If not you'll receive an error : { "code" : 100, "message" : "Internal error : Rounding necessary" }
18
+ def make_payment(debit_hash = default_debit_hash)
19
+ self.create_direct_debits(debit_hash)
20
+ end
21
+
22
+ private
23
+
24
+ def default_debit_hash
25
+ {
26
+ creditor: {
27
+ reference: @creditor_reference
28
+ },
29
+ mandate: {
30
+ rum: '1'
31
+ },
32
+ amount: 100.00,
33
+ label: 'The label',
34
+ paymentReference: 'Payment 123'
35
+ }
36
+ end
37
+ end
38
+ end
@@ -0,0 +1,80 @@
1
+ module Slimpay
2
+ # To display Slimpay error messages with the HTTP code.
3
+ #
4
+ # ==== Possible HAPI errors
5
+ # * code: 906 message: "Error : Could not find acceptable representation"
6
+ # * code: 906 message: "Error : Request method 'POST' not supported"
7
+ # * code: 906 message: "Error : Content type 'application/x-www-form-urlencoded' not supported"
8
+ # * code: 904 message: "Access denied : cannot access creditor democreditor"
9
+ # * error:"invalid_token", error_description: "Invalid access token: 1234-123456-abcdef-123456"
10
+ # * code: 205, message: "Client data are inconsistent : missing query parameters creditorReference and/or rum"
11
+ class Error < StandardError
12
+ attr_reader :message
13
+ # If the HTTP response is nil or empty returns an actual message.
14
+ def self.empty
15
+ { code: 418, message: 'The answer was empty.' }
16
+ end
17
+
18
+ # Returns either formated error with its HTTP code or the raw HTTP response.
19
+ # ===== Arguments:
20
+ # http_response: (HTTParty::Response)
21
+ def initialize(http_response)
22
+ if defined?(http_response.code)
23
+ display_http_error(http_response)
24
+ else
25
+ @message = JSON.parse(http_response)
26
+ end
27
+ fail self, @message
28
+ end
29
+
30
+ def to_s
31
+ @message
32
+ end
33
+
34
+ private
35
+
36
+ def display_http_error(http_response)
37
+ case http_response.code
38
+ when 400
39
+ @message = bad_request(http_response)
40
+ when 401
41
+ @message = unauthorized(http_response)
42
+ when 403
43
+ @message = forbidden(http_response)
44
+ when 404
45
+ @message = not_found
46
+ when 406
47
+ @message = not_acceptable(http_response)
48
+ else
49
+ @message = http_response
50
+ end
51
+ end
52
+
53
+ def bad_request(http_message)
54
+ { code: 400, message: "HTTP Bad Request. #{slimpay_error(http_message)}" }
55
+ end
56
+
57
+ def unauthorized(http_message)
58
+ { code: 401, message: "HTTP Unauthorized. #{slimpay_error(http_message)}"}
59
+ end
60
+
61
+ def forbidden(http_message)
62
+ { code: 403, message: "HTTP Forbidden. #{slimpay_error(http_message)}" }
63
+ end
64
+
65
+ def not_found
66
+ { code: 404, message: 'URI not found.' }
67
+ end
68
+
69
+ def not_acceptable(http_message)
70
+ { code: 406, message: "HTTP Not Acceptable. #{slimpay_error(http_message)}" }
71
+ end
72
+
73
+ def slimpay_error(http_message)
74
+ slimpay_error = http_message.is_a?(Hash) ? http_message : JSON.parse(http_message)
75
+ slimpay_code = slimpay_error['code']
76
+ slimpay_message = slimpay_error['message'] || slimpay_error['error_description']
77
+ "Slimpay #{slimpay_code} : #{slimpay_message}"
78
+ end
79
+ end
80
+ end
@@ -0,0 +1,4 @@
1
+ module Slimpay
2
+ class Mandate < Resource
3
+ end
4
+ end
@@ -0,0 +1,104 @@
1
+ module Slimpay
2
+ # Inherits from Resouce and thus defines its associated resource's methods.
3
+ #
4
+ # Defines shortcut methods for the create_order method with various arguments.
5
+ class Order < Resource
6
+ # Override the Resource#get_one method because the url is not the same for Orders
7
+ #
8
+ # ===== Example:
9
+ # orders = Slimpay::Order.new
10
+ # orders.get_one
11
+ # =>
12
+ # {"_links"=>
13
+ # {"self"=>{"href"=>"https://api-sandbox.slimpay.net/creditors/democreditor/orders/1"},
14
+ # "https://api.slimpay.net/alps#get-creditor"=>{"href"=>"https://api-sandbox.slimpay.net/creditors/democreditor"},
15
+ # "https://api.slimpay.net/alps#get-subscriber" =>
16
+ # {"href"=>"https://api-sandbox.slimpay.net/creditors/democreditor/orders/1/subscribers/subscriber01"},
17
+ # "https://api.slimpay.net/alps#user-approval" =>
18
+ # {"href"=>"https://slimpay.net/slimpaytpe16/userApproval?accessCode=spK534N0cuZztBGwj2FjC6eKzcsKFRzXbfy8buloUHiZV6p9PhIfcPgV7c507R"},
19
+ # "https://api.slimpay.net/alps#get-order-items"=>{"href"=>"https://api-sandbox.slimpay.net/creditors/democreditor/orders/1/items"},
20
+ # "https://api.slimpay.net/alps#get-mandate"=>{"href"=>"https://api-sandbox.slimpay.net/creditors/democreditor/mandates/1"}},
21
+ # "reference"=>"1",
22
+ # "state"=>"closed.completed",
23
+ # "started"=>true,
24
+ # "dateCreated"=>"2014-12-12T09:35:39.000+0000",
25
+ # "mandateReused"=>false}
26
+ # ===== Arguments:
27
+ # reference: (String)
28
+ def get_one(reference = 1)
29
+ query_options = "creditorReference=#{@creditor_reference}&reference=#{reference}"
30
+ response = HTTParty.get("#{@endpoint}/#{@resource_name}?#{query_options}", headers: options)
31
+ follow_up_api(response)
32
+ end
33
+
34
+ # POST
35
+ def login(reference = 'subscriber01')
36
+ url = 'orders'
37
+ body_options = {
38
+ creditor: {
39
+ reference: @creditor_reference
40
+ },
41
+ subscriber: {
42
+ reference: reference
43
+ },
44
+ items: [{
45
+ type: 'subscriberLogin'
46
+ }],
47
+ started: true
48
+ }
49
+ response = HTTParty.post("#{@endpoint}/#{url}", body: body_options.to_json, headers: options)
50
+ follow_up_api(response)
51
+ end
52
+
53
+ # POST
54
+ # This will send a create_order request with given signatory (subscriber Hash with infos)
55
+ #
56
+ # In case of success, this will generate a method accessible via the _.api_methods_ method.
57
+ # This method let you redirect the customer to the approval page : orders.api_methods['user_approval']
58
+ # ===== Arguments
59
+ # reference: (String) The reference to your User in your application. Use a unique key. Slimpay will refer to it for future answers.
60
+ # signatory: (Hash) Your customer informations. See API Order documentation for details.
61
+ # ===== Returns
62
+ # a Hash representing the Mandate.
63
+ def sign_mandate(reference = 'subscriber01', signatory = default_signatory)
64
+ url = 'orders'
65
+ body_options = {
66
+ creditor: {
67
+ reference: @creditor_reference
68
+ },
69
+ subscriber: {
70
+ reference: reference
71
+ },
72
+ items: [{
73
+ type: 'signMandate',
74
+ mandate: {
75
+ standard: 'SEPA',
76
+ signatory: signatory
77
+ }
78
+ }],
79
+ started: true
80
+ }
81
+ response = HTTParty.post("#{@endpoint}/#{url}", body: body_options.to_json, headers: options)
82
+ JSON.parse(follow_up_api(response))
83
+ end
84
+
85
+ private
86
+
87
+ def default_signatory
88
+ {
89
+ honorificPrefix: 'Mr',
90
+ familyName: 'Doe',
91
+ givenName: 'John',
92
+ telephone: '+33612345678',
93
+ email: 'john.doe@gmail.com',
94
+ billingAddress: {
95
+ street1: '27 rue des fleurs',
96
+ street2: 'Bat 2',
97
+ postalCode: '75008',
98
+ city: 'Paris',
99
+ country: 'FR'
100
+ }
101
+ }
102
+ end
103
+ end
104
+ end
@@ -0,0 +1,29 @@
1
+ module Slimpay
2
+ # An abstract resource to be inherited from.
3
+ #
4
+ # Defines HAPI resource non-semantic methods.
5
+ class Resource < Base
6
+ def initialize
7
+ @resource_name = self.class.to_s.demodulize.underscore.dasherize.pluralize
8
+ super
9
+ end
10
+
11
+ # Shortcut method to get a resource with only resource's reference.
12
+ #
13
+ # The above example shall return the same result as
14
+ # mandates = Slimpay::Mandate.new
15
+ # mandates.get_mandates({creditorReference: @creditor_reference, reference: 1})
16
+ #
17
+ # ===== Example:
18
+ # mandates = Slimpay::Mandate.new
19
+ # mandates.get_one(1)
20
+ # ===== Arguments:
21
+ # reference: (String)
22
+ def get_one(reference = 1)
23
+ url = "#{@endpoint}/creditors/#{@creditor_reference}/#{@resource_name}/#{reference}"
24
+ response = HTTParty.get(url, headers: options)
25
+ generate_api_methods(JSON.parse(response))
26
+ Slimpay.answer(response)
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,3 @@
1
+ module Slimpay
2
+ VERSION = '1.0.0'
3
+ end
data/lib/slimpay.rb ADDED
@@ -0,0 +1,61 @@
1
+ require 'slimpay/version'
2
+ require 'oauth2'
3
+ require 'httparty'
4
+
5
+ require 'active_support/core_ext/string/inflections'
6
+
7
+ require 'slimpay/configuration'
8
+ require 'slimpay/error'
9
+ require 'slimpay/base'
10
+ require 'slimpay/resource'
11
+ require 'slimpay/app'
12
+ require 'slimpay/mandate'
13
+ require 'slimpay/order'
14
+ require 'slimpay/direct_debit'
15
+
16
+ # :main: README.md
17
+
18
+ # Slimpay module defines Simpay's HAPI constants and require dependencies.
19
+ # TODO: If-None-Match support. (next answer ?= 304)
20
+ # TODO: wiki/doc full worflow: 1. App to change URls, 2. Order to sign mandate, 3. DirectDebit to pay with mandate.
21
+ module Slimpay
22
+ PRODUCTION_ENDPOINT = 'https://api.slimpay.net'
23
+ API_HEADER = "application/hal+json; profile='https://api.slimpay.net/alps/v1'"
24
+ SANDBOX_API_HEADER = "application/hal+json; profile='https://api-sandbox.slimpay.net/alps/v1'"
25
+ SANDBOX_ENDPOINT = 'https://api-sandbox.slimpay.net'
26
+ SANDBOX_CLIENT_ID = 'democreditor01'
27
+ SANDBOX_SECRET_ID = 'demosecret01'
28
+ SANDBOX_CREDITOR = 'democreditor'
29
+
30
+ class << self
31
+ attr_accessor :configuration
32
+ end
33
+
34
+ # Sets the initial configuration for client_id, client_secret and creditor_reference
35
+ # ===== Usage:
36
+ # Slimpay.configure do |config|
37
+ # config.client_id = "your_client_id"
38
+ # config.client_secret = "your_client_secret"
39
+ # config.creditor_reference = "your_creditor_reference"
40
+ # config.sandbox = true
41
+ # config.notify_url = 'you_notifications_url'
42
+ # config.return_url = 'your_return_url'
43
+ # end
44
+ def self.configure
45
+ self.configuration ||= Configuration.new
46
+ yield(configuration)
47
+ end
48
+
49
+ # Used to display HTTP requests responses nicely in case of error.
50
+ #
51
+ # ===== Arguments:
52
+ # http_response: (HTTParty::Response)
53
+ def self.answer(http_response)
54
+ return Slimpay::Error.empty if http_response.nil?
55
+ if http_response.code >= 400
56
+ Slimpay::Error.new(http_response)
57
+ else
58
+ http_response
59
+ end
60
+ end
61
+ end
data/slimpay.gemspec ADDED
@@ -0,0 +1,42 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'slimpay/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = 'slimpay'
8
+ spec.version = Slimpay::VERSION
9
+ spec.authors = ['Gregory Durelle']
10
+ spec.email = ['gregory.durelle@gmail.com']
11
+
12
+ spec.summary = %(Slimpay HAPI for Ruby.)
13
+ spec.description = %(Ruby library for Slimpay's Hypermedia API.)
14
+ spec.homepage = "https://github.com/novagile/slimpay"
15
+ spec.license = 'MIT'
16
+
17
+ spec.post_install_message = %(Please refer to Slimpay's API https://api-sandbox.slimpay.net/docs for more informations.)
18
+
19
+ # Prevent pushing this gem to RubyGems.org by setting 'allowed_push_host', or
20
+ # delete this section to allow pushing this gem to any host.
21
+ # if spec.respond_to?(:metadata)
22
+ # spec.metadata['allowed_push_host'] = "TODO: Set to 'http://mygemserver.com'"
23
+ # else
24
+ # fail 'RubyGems 2.0 or newer is required to protect against public gem pushes.'
25
+ # end
26
+
27
+ spec.files = `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
28
+ spec.bindir = 'exe'
29
+ spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
30
+ spec.require_paths = ['lib']
31
+
32
+ spec.add_dependency 'oauth2', '~> 0.9.0'
33
+ spec.add_dependency 'httparty', '~> 0.13.5'
34
+ spec.add_dependency 'activesupport', '~> 4.0.0'
35
+
36
+ spec.add_development_dependency 'bundler', '~> 1.10'
37
+ spec.add_development_dependency 'rake', '~> 10.0'
38
+ spec.add_development_dependency 'rspec', '~> 3.3.0'
39
+ spec.add_development_dependency 'vcr', '~> 2.9.0'
40
+ spec.add_development_dependency 'webmock', '~> 1.21.0'
41
+ spec.add_development_dependency 'rubocop', '~> 0.32.1'
42
+ end
metadata ADDED
@@ -0,0 +1,194 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: slimpay
3
+ version: !ruby/object:Gem::Version
4
+ version: 1.0.0
5
+ platform: ruby
6
+ authors:
7
+ - Gregory Durelle
8
+ autorequire:
9
+ bindir: exe
10
+ cert_chain: []
11
+ date: 2015-11-18 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: oauth2
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: 0.9.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.9.0
27
+ - !ruby/object:Gem::Dependency
28
+ name: httparty
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: 0.13.5
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: 0.13.5
41
+ - !ruby/object:Gem::Dependency
42
+ name: activesupport
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: 4.0.0
48
+ type: :runtime
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: 4.0.0
55
+ - !ruby/object:Gem::Dependency
56
+ name: bundler
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - "~>"
60
+ - !ruby/object:Gem::Version
61
+ version: '1.10'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - "~>"
67
+ - !ruby/object:Gem::Version
68
+ version: '1.10'
69
+ - !ruby/object:Gem::Dependency
70
+ name: rake
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - "~>"
74
+ - !ruby/object:Gem::Version
75
+ version: '10.0'
76
+ type: :development
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - "~>"
81
+ - !ruby/object:Gem::Version
82
+ version: '10.0'
83
+ - !ruby/object:Gem::Dependency
84
+ name: rspec
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - "~>"
88
+ - !ruby/object:Gem::Version
89
+ version: 3.3.0
90
+ type: :development
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - "~>"
95
+ - !ruby/object:Gem::Version
96
+ version: 3.3.0
97
+ - !ruby/object:Gem::Dependency
98
+ name: vcr
99
+ requirement: !ruby/object:Gem::Requirement
100
+ requirements:
101
+ - - "~>"
102
+ - !ruby/object:Gem::Version
103
+ version: 2.9.0
104
+ type: :development
105
+ prerelease: false
106
+ version_requirements: !ruby/object:Gem::Requirement
107
+ requirements:
108
+ - - "~>"
109
+ - !ruby/object:Gem::Version
110
+ version: 2.9.0
111
+ - !ruby/object:Gem::Dependency
112
+ name: webmock
113
+ requirement: !ruby/object:Gem::Requirement
114
+ requirements:
115
+ - - "~>"
116
+ - !ruby/object:Gem::Version
117
+ version: 1.21.0
118
+ type: :development
119
+ prerelease: false
120
+ version_requirements: !ruby/object:Gem::Requirement
121
+ requirements:
122
+ - - "~>"
123
+ - !ruby/object:Gem::Version
124
+ version: 1.21.0
125
+ - !ruby/object:Gem::Dependency
126
+ name: rubocop
127
+ requirement: !ruby/object:Gem::Requirement
128
+ requirements:
129
+ - - "~>"
130
+ - !ruby/object:Gem::Version
131
+ version: 0.32.1
132
+ type: :development
133
+ prerelease: false
134
+ version_requirements: !ruby/object:Gem::Requirement
135
+ requirements:
136
+ - - "~>"
137
+ - !ruby/object:Gem::Version
138
+ version: 0.32.1
139
+ description: Ruby library for Slimpay's Hypermedia API.
140
+ email:
141
+ - gregory.durelle@gmail.com
142
+ executables: []
143
+ extensions: []
144
+ extra_rdoc_files: []
145
+ files:
146
+ - ".gitignore"
147
+ - ".gitlab-ci.yml"
148
+ - ".rspec"
149
+ - ".rubocop.yml"
150
+ - ".travis.yml"
151
+ - CODE_OF_CONDUCT.md
152
+ - Gemfile
153
+ - LICENSE.txt
154
+ - README.md
155
+ - Rakefile
156
+ - bin/console
157
+ - bin/setup
158
+ - lib/slimpay.rb
159
+ - lib/slimpay/app.rb
160
+ - lib/slimpay/base.rb
161
+ - lib/slimpay/configuration.rb
162
+ - lib/slimpay/direct_debit.rb
163
+ - lib/slimpay/error.rb
164
+ - lib/slimpay/mandate.rb
165
+ - lib/slimpay/order.rb
166
+ - lib/slimpay/resource.rb
167
+ - lib/slimpay/version.rb
168
+ - slimpay.gemspec
169
+ homepage: https://github.com/novagile/slimpay
170
+ licenses:
171
+ - MIT
172
+ metadata: {}
173
+ post_install_message: Please refer to Slimpay's API https://api-sandbox.slimpay.net/docs
174
+ for more informations.
175
+ rdoc_options: []
176
+ require_paths:
177
+ - lib
178
+ required_ruby_version: !ruby/object:Gem::Requirement
179
+ requirements:
180
+ - - ">="
181
+ - !ruby/object:Gem::Version
182
+ version: '0'
183
+ required_rubygems_version: !ruby/object:Gem::Requirement
184
+ requirements:
185
+ - - ">="
186
+ - !ruby/object:Gem::Version
187
+ version: '0'
188
+ requirements: []
189
+ rubyforge_project:
190
+ rubygems_version: 2.4.5
191
+ signing_key:
192
+ specification_version: 4
193
+ summary: Slimpay HAPI for Ruby.
194
+ test_files: []