adyen_client 0.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: bed3b1c2cd6bad30f1278dedc5bbf0a6eb1192e6
4
+ data.tar.gz: eb471bf5fc009cfaa44ba2c4809602363c3bfdc5
5
+ SHA512:
6
+ metadata.gz: 3b31679659538ec245122826e0c465836b80ab6d02e3a171c5f729dfade0773191d7d570ddf90cdfd50bbc1e92dac245e10bf387b5551387d50d4f3e38a2dfb5
7
+ data.tar.gz: 2f344b0abdd6fd6ad19dfca2db359bbb769ad2c5f702fe9370a0cb9369e80d7890aa9de54eb4055c99a321f57562550ef57629fcc9054980c017a9bc11a5166c
data/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2015 Lukas Rieder
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,128 @@
1
+ # A simple client that talks to the Adyen API
2
+
3
+ [![Inline docs](http://inch-ci.org/github/Overbryd/adyen_client.svg?branch=master)](http://inch-ci.org/github/Overbryd/adyen_client)
4
+
5
+ > Does not try to be smart, stays close to the documentation while adhering to Ruby conventions.
6
+
7
+ ## Setup & Configuration
8
+
9
+ `gem install adyen_client`
10
+
11
+ In your Gemfile:
12
+
13
+ `gem "adyen_client"`
14
+
15
+ Require and configure the client:
16
+
17
+ ```ruby
18
+ require "adyen_client"
19
+
20
+ # Block style
21
+ AdyenClient.configure do |c|
22
+ c.environment = :test
23
+ c.username = "ws_123456@Company.FooBar"
24
+ c.password = "correctbatteryhorsestaple"
25
+ c.cse_public_key = "10001|..."
26
+ c.default_merchant_account = "FooBar123"
27
+ c.default_currency = "EUR"
28
+ end
29
+
30
+ # Hash style works too, string or symbol keys
31
+ AdyenClient.configure(environment: :test, username: "ws_123456@Company.FooBar", ...)
32
+
33
+ # That comes in handy to configure the client from a YAML file
34
+ AdyenClient.configure(YAML.load_file(Rails.root.join("config", "adyen.yml"))[Rails.env.to_s])
35
+
36
+ # You can override all default options for each instance of a client
37
+ client = AdyenClient.new(merchant_account: "FooBarSubMerchant123")
38
+ eur_client = AdyenClient.new(currency: "EUR")
39
+ ```
40
+
41
+ ## Examples
42
+
43
+ ### Simple payment
44
+
45
+ ```ruby
46
+ client = AdyenClient.new
47
+ response = client.authorise(amount: 100, encrypted_card: "adyenjs_0_1_15$OlmG...")
48
+ if response.authorised?
49
+ puts "( ノ ゚ー゚)ノ"
50
+ else
51
+ puts "(-‸ლ)"
52
+ end
53
+ ```
54
+
55
+ ### Setup a recurring contract, charge users later
56
+
57
+ ```ruby
58
+ user = User.create(email: "john@doe.com", last_ip: request.remote_ip)
59
+
60
+ client = AdyenClient.new
61
+ response = client.create_recurring_contract(encrypted_card: "adyenjs_0_1_15$OlmG...", shopper: {
62
+ reference: user.id,
63
+ email: user.email,
64
+ ip: user.last_ip # optional but recommended
65
+ })
66
+ if response.authorised?
67
+ # now we know the users card is valid
68
+ else
69
+ # something is wrong with the users card or we got an error
70
+ end
71
+ ```
72
+
73
+ Later, we want to charge the user based on that contract.
74
+
75
+ ```ruby
76
+ user = User.find_by_email("john@doe.com")
77
+
78
+ client = AdyenClient.new
79
+ response = client.authorise_recurring_payment(amount: 1699, shopper: { reference: user.id })
80
+ if response.authorised?
81
+ # we know the payment is on its way
82
+ else
83
+ # something is wrong, maybe we got an error
84
+ end
85
+ ```
86
+
87
+ ## Documentation
88
+
89
+ All publicly usable [methods and classes are documented here](http://rdoc.info/projects/Overbryd/adyen_client).
90
+
91
+ This library does not try to be too smart, it simply provides a layer of abstraction on top of the Adyen JSON API.
92
+ Also the default `AdyenClient::Response` class basically just wraps the JSON response.
93
+ The only work it does is converting `camelCase` keys to `sneak_case`, removing unnecessary object nestings and providing you with a convenience `authorised?` method.
94
+
95
+ If you want a more sophisticated response class, you can easily hook up your own.
96
+ The only method you need to provide is `::new`. It will receive one argument, the [`HTTParty::Response`](http://www.rubydoc.info/github/jnunemaker/httparty/HTTParty/Response) for the given request.
97
+
98
+ ```ruby
99
+ class MyAdyenResponse
100
+ def self.parse(http_response)
101
+ # ... your fancy code
102
+ end
103
+ end
104
+ ```
105
+
106
+ Hook it up by initialising the client like this: `AdyenClient.new(response_class: MyAdyenResponse)`.
107
+
108
+ Similar, if you want nothing else than the bare `HTTParty::Response`, initialise the client with: `response_class: nil`.
109
+
110
+
111
+ ## Contributing
112
+
113
+ I am very happy to receive pull requests or bug reports for problems with the library.
114
+ Please make sure you are only reporting an actual issue with the library itself, I cannot help with your payment flow or advise you on anything related to the Adyen API.
115
+
116
+ ## Disclaimer
117
+
118
+ I am not associated with Adyen in any way.
119
+ If you have problems with your adyen account or your payment flow, please contact the very helpful Adyen support using `support ät adyen.com`.
120
+
121
+ Please make yourself comfortable [with the Adyen documentation](https://docs.adyen.com/) on how you want to setup your payment flow.
122
+
123
+ ## License
124
+
125
+ The MIT License (MIT), Copyright (c) 2015 Lukas Rieder
126
+
127
+ See [`LICENSE`](https://github.com/Overbryd/adyen_client/blob/master/LICENSE).
128
+
@@ -0,0 +1,27 @@
1
+ class AdyenClient
2
+
3
+ class Configuration
4
+ BASE_URI = "https://pal-%s.adyen.com/pal/servlet"
5
+ attr_accessor :environment
6
+ attr_accessor :username
7
+ attr_accessor :password
8
+ attr_accessor :cse_public_key
9
+ attr_accessor :default_merchant_account
10
+ attr_accessor :default_currency
11
+
12
+ def set(hash)
13
+ hash.each { |k, v| send("#{k}=", v) if respond_to?("#{k}=") }
14
+ end
15
+
16
+ def apply(klass)
17
+ klass.base_uri(BASE_URI % environment)
18
+ klass.basic_auth(username, password)
19
+ # prevent following redirects and raise HTTParty::RedirectionTooDeep
20
+ klass.no_follow(true)
21
+ klass.format(:json)
22
+ klass.headers("Content-Type" => "application/json; charset=utf-8")
23
+ end
24
+ end
25
+
26
+ end
27
+
@@ -0,0 +1,34 @@
1
+ class AdyenClient
2
+
3
+ class Response
4
+ def self.parse(http_response)
5
+ new(http_response.code, Utils.massage_response(http_response.parsed_response))
6
+ end
7
+
8
+ attr_reader :code, :data
9
+ alias_method :to_hash, :data
10
+
11
+ def initialize(code, data)
12
+ @code, @data = code, data
13
+ end
14
+
15
+ def success?
16
+ code == 200
17
+ end
18
+
19
+ def authorised?
20
+ success? && result_code == "Authorised"
21
+ end
22
+ alias_method :authorized?, :authorised? # for our friends abroad
23
+
24
+ def respond_to_missing?(name, include_private = false)
25
+ @data.has_key?(name.to_s) || super
26
+ end
27
+
28
+ def method_missing(name, *args, &block)
29
+ @data.fetch(name.to_s) { super(name, *args, &block) }
30
+ end
31
+ end
32
+
33
+ end
34
+
@@ -0,0 +1,33 @@
1
+ class AdyenClient
2
+
3
+ module Utils
4
+ def massage_response(value, parent = nil)
5
+ case value
6
+ when Array
7
+ value.map { |v| massage_response(v, value) }
8
+ when Hash
9
+ if parent.is_a?(Array) && value.count == 1
10
+ _, v = value.first
11
+ massage_response(v, value)
12
+ else
13
+ Hash[value.map { |k, v| [snake_caseify(k), massage_response(v, value)] }]
14
+ end
15
+ else
16
+ value
17
+ end
18
+ end
19
+
20
+ def snake_caseify(string)
21
+ string
22
+ .gsub("::", "/")
23
+ .gsub(/([A-Z]+)([A-Z][a-z])/, '\1_\2')
24
+ .gsub(/([a-z\d])([A-Z])/, '\1_\2')
25
+ .tr("-", "_")
26
+ .downcase
27
+ end
28
+
29
+ extend self
30
+ end
31
+
32
+ end
33
+
@@ -0,0 +1,253 @@
1
+ require "httparty"
2
+ require "adyen_client/utils"
3
+ require "adyen_client/response"
4
+ require "adyen_client/configuration"
5
+
6
+ class AdyenClient
7
+ include HTTParty
8
+
9
+ # Internal: Access the configuration instance.
10
+ def self.configuration
11
+ @configuration ||= Configuration.new
12
+ end
13
+
14
+ # Public: Configure the AdyenClient class.
15
+ #
16
+ # hash - The configuration to apply. Will be evaluated before &block. (optional if &block is given)
17
+ # &block - Yields the configuration instance. (optional if hash is given)
18
+ #
19
+ # Examples
20
+ #
21
+ # # Block style
22
+ # AdyenClient.configure do |c|
23
+ # c.environment = :test
24
+ # c.username = "ws_123456@Company.FooBar"
25
+ # c.password = "correctbatteryhorsestaple"
26
+ # c.cse_public_key = "10001|..."
27
+ # c.default_merchant_account = "FooBar123"
28
+ # c.default_currency = "EUR"
29
+ # end
30
+ #
31
+ # # Hash style works too, string or symbol keys
32
+ # AdyenClient.configure(environment: :test, username: "ws_123456@Company.FooBar", ...)
33
+ #
34
+ # # That comes in handy to configure the client from a YAML file
35
+ # AdyenClient.configure(YAML.load_file(Rails.root.join("config", "adyen.yml"))[Rails.env.to_s])
36
+ #
37
+ # # You can override all default options for each instance of a client
38
+ # client = AdyenClient.new(merchant_account: "FooBarSubMerchant123")
39
+ # eur_client = AdyenClient.new(currency: "EUR")
40
+ #
41
+ # Yields the configuration singleton.
42
+ #
43
+ # Returns the configuration singleton.
44
+ def self.configure(hash = nil)
45
+ configuration.set(hash) if hash
46
+ yield configuration if block_given?
47
+ configuration.apply(self)
48
+ configuration
49
+ end
50
+
51
+ # Public: Returns an ISO8601 formatted datetime string used in Adyens generationTime.
52
+ def self.generation_time
53
+ Time.now.iso8601
54
+ end
55
+
56
+ # Public: Returns the configured CSE (client side encryption) public key.
57
+ def self.cse_public_key
58
+ configuration.cse_public_key
59
+ end
60
+
61
+ attr_reader :merchant_account
62
+
63
+ # Public: Initializes a new instance of the AdyenClient.
64
+ # You can override merchant_account and currency from the default configuration.
65
+ #
66
+ # :merchant_account - Sets the default_merchant_account for this instance. (optional)
67
+ # :currency - Sets the default_currency for this instance. (optional)
68
+ # :response_class - Use a custom class for handling responses from Adyen. (optional)
69
+ #
70
+ # Returns an AdyenClient::Response or your specific response implementation.
71
+ def initialize(merchant_account: configuration.default_merchant_account, currency: configuration.default_currency, response_class: Response)
72
+ @merchant_account = merchant_account
73
+ @currency = currency
74
+ @response_class = response_class
75
+ end
76
+
77
+ # Public: Charge a user by referencing his stored payment method.
78
+ #
79
+ # :shopper_reference - The user reference id from your side.
80
+ # :amount - The amount to charge in cents.
81
+ # :reference - Your reference id for this transaction.
82
+ # :recurring_reference - Use when referencing a specific payment method stored for the user. (default: "LATEST")
83
+ # :merchant_account - Use a specific merchant account for this transaction. (default: set by the instance or configuration default merchant account)
84
+ # :currency - Use a specific 3-letter currency code. (default: set by the instance or configuration default currency)
85
+ #
86
+ # Returns an AdyenClient::Response or your specific response implementation.
87
+ def authorise_recurring_payment(reference:, shopper_reference:, amount:, recurring_reference: "LATEST", merchant_account: @merchant_account, currency: configuration.default_currency)
88
+ postJSON("/Payment/v12/authorise",
89
+ reference: reference,
90
+ amount: { value: amount, currency: currency },
91
+ merchantAccount: merchant_account,
92
+ shopperReference: shopper_reference,
93
+ selectedRecurringDetailReference: recurring_reference,
94
+ selectedBrand: "",
95
+ recurring: { contract: "RECURRING" },
96
+ shopperInteraction: "ContAuth"
97
+ )
98
+ end
99
+ alias_method :authorize_recurring_payment, :authorise_recurring_payment
100
+
101
+ # Public: List the stored payment methods for a user.
102
+ #
103
+ # :shopper_reference - The user reference id from your side.
104
+ # :merchant_account - Use a specific merchant account for this transaction. (default: set by the instance or configuration default merchant account)
105
+ # :currency - Use a specific 3-letter currency code. (default: set by the instance or configuration default currency)
106
+ #
107
+ # Returns an AdyenClient::Response or your specific response implementation.
108
+ def list_recurring_details(shopper_reference:, merchant_account: @merchant_account, contract: "RECURRING")
109
+ postJSON("/Recurring/v12/listRecurringDetails",
110
+ shopperReference: shopper_reference,
111
+ recurring: { contract: contract },
112
+ merchantAccount: merchant_account
113
+ )
114
+ end
115
+
116
+ # Public: Store a payment method on a reference id for recurring/later use.
117
+ # Does verify the users payment method, but does not create a charge.
118
+ #
119
+ # :encrypted_card - The encrypted credit card information generated by the CSE (client side encryption) javascript integration.
120
+ # :reference - Your reference id for this transaction.
121
+ # :shopper - The hash describing the shopper for this contract:
122
+ # :reference - Your reference id for this shopper/user. (mandatory)
123
+ # :email - The shoppers email address. (optional but recommended)
124
+ # :ip - The shoppers last known ip address. (optional but recommended)
125
+ # :merchant_account - Use a specific merchant account for this transaction. (default: set by the instance or configuration default merchant account)
126
+ # :currency - Use a specific 3-letter currency code. (default: set by the instance or configuration default currency)
127
+ #
128
+ # Returns an AdyenClient::Response or your specific response implementation.
129
+ def create_recurring_contract(encrypted_card:, reference:, shopper:, merchant_account: @merchant_account, currency: @currency)
130
+ postJSON("/Payment/v12/authorise",
131
+ reference: reference,
132
+ additionalData: { "card.encrypted.json": encrypted_card },
133
+ amount: { value: 0, currency: currency },
134
+ merchantAccount: merchant_account,
135
+ shopperEmail: shopper[:email],
136
+ shopperIP: shopper[:ip],
137
+ shopperReference: shopper[:reference],
138
+ recurring: { contract: "RECURRING" }
139
+ )
140
+ end
141
+
142
+ # Public: Charge a credit card.
143
+ #
144
+ # :encrypted_card - The encrypted credit card information generated by the CSE (client side encryption) javascript integration.
145
+ # :amount - The integer amount in cents.
146
+ # :reference - Your reference id for this transaction.
147
+ # :merchant_account - Use a specific merchant account for this transaction. (default: set by the instance or configuration default merchant account)
148
+ # :currency - Use a specific 3-letter currency code. (default: set by the instance or configuration default currency)
149
+ # :shopper - The hash describing the shopper for this transaction, optional but recommended (default: {}):
150
+ # :email - The shoppers email address (optional but recommended).
151
+ # :ip - The shoppers last known ip address (optional but recommended).
152
+ # :reference - Your reference id for this shopper/user (optional).
153
+ #
154
+ # Returns an AdyenClient::Response or your specific response implementation.
155
+ def authorise(encrypted_card:, amount:, reference:, merchant_account: @merchant_account, currency: @currency, shopper: {})
156
+ postJSON("/Payment/v12/authorise",
157
+ reference: reference,
158
+ amount: { value: amount, currency: currency },
159
+ merchantAccount: merchant_account,
160
+ additionalData: { "card.encrypted.json": encrypted_card }
161
+ )
162
+ end
163
+ alias_method :authorize, :authorise
164
+
165
+ # Public: Verify a credit card (does not create a charge, but may be verified for a specified amount).
166
+ #
167
+ # :encrypted_card - The encrypted credit card information generated by the CSE (client side encryption) javascript integration.
168
+ # :reference - Your reference id for this transaction.
169
+ # :amount - The integer amount in cents. Will not be charged on the card. (default: 0)
170
+ # :merchant_account - Use a specific merchant account for this transaction (default: set by the instance or configuration default merchant account).
171
+ # :currency - Use a specific 3-letter currency code (default: set by the instance or configuration default currency).
172
+ # :shopper - The hash describing the shopper for this transaction, optional but recommended (default: {}):
173
+ # :email - The shoppers email address (optional but recommended).
174
+ # :ip - The shoppers last known ip address (optional but recommended).
175
+ # :reference - Your reference id for this shopper/user (optional).
176
+ #
177
+ # Returns an AdyenClient::Response or your specific response implementation.
178
+ def verify(encrypted_card:, reference:, amount: 0, merchant_account: @merchant_account, currency: @currency, shopper: {})
179
+ postJSON("/Payment/v12/authorise",
180
+ reference: reference,
181
+ amount: { value: 0, currency: currency },
182
+ additionalAmount: { value: amount, currency: currency },
183
+ merchantAccount: merchant_account,
184
+ additionalData: { "card.encrypted.json": encrypted_card }
185
+ )
186
+ end
187
+
188
+ # Public: Cancels a credit card transaction.
189
+ #
190
+ # :original_reference - The psp_reference from Adyen for this transaction.
191
+ # :reference - Your reference id for this transaction.
192
+ # :merchant_account - Use a specific merchant account for this transaction (default: set by the instance or configuration default merchant account).
193
+ #
194
+ # Returns an AdyenClient::Response or your specific response implementation.
195
+ def cancel(original_reference:, reference:, merchantAccount: @merchant_account)
196
+ postJSON("/Payment/v12/cancel",
197
+ reference: reference,
198
+ merchantAccount: merchant_account,
199
+ originalReference: original_reference
200
+ )
201
+ end
202
+
203
+ # Public: Refunds a credit card transaction.
204
+ #
205
+ # :original_reference - The psp_reference from Adyen for this transaction.
206
+ # :amount - The amount in cents to be refunded.
207
+ # :reference - Your reference id for this transaction.
208
+ # :merchant_account - Use a specific merchant account for this transaction (default: set by the instance or configuration default merchant account).
209
+ # :currency - Use a specific 3-letter currency code (default: set by the instance or configuration default currency).
210
+ #
211
+ # Returns an AdyenClient::Response or your specific response implementation.
212
+ def refund(original_reference:, amount:, reference:, merchantAccount: @merchant_account, currency: @currency)
213
+ postJSON("/Payment/v12/refund",
214
+ reference: reference,
215
+ merchantAccount: merchant_account,
216
+ modificationAmount: { value: amount, currency: currency },
217
+ originalReference: original_reference
218
+ )
219
+ end
220
+
221
+ # Public: Cancels or refunds a credit card transaction. Use this if you don't know the exact state of a transaction.
222
+ #
223
+ # :original_reference - The psp_reference from Adyen for this transaction.
224
+ # :reference - Your reference id for this transaction.
225
+ # :merchant_account - Use a specific merchant account for this transaction (default: set by the instance or configuration default merchant account).
226
+ #
227
+ # Returns an AdyenClient::Response or your specific response implementation.
228
+ def cancel_or_refund(original_reference:, reference:, merchantAccount: @merchant_account)
229
+ postJSON("/Payment/v12/cancelOrRefund",
230
+ reference: reference,
231
+ merchantAccount: merchant_account,
232
+ originalReference: original_reference
233
+ )
234
+ end
235
+
236
+ # Internal: Send a POST request to the Adyen API.
237
+ #
238
+ # path - The Adyen JSON API endpoint path.
239
+ # data - The Hash describing the JSON body for this request.
240
+ #
241
+ # Returns an AdyenClient::Response or your specific response implementation.
242
+ def postJSON(path, data)
243
+ response = self.class.post(path, body: data.to_json)
244
+ @response_class ? @response_class.parse(response) : response
245
+ end
246
+
247
+ # Internal: Returns the AdyenClient configuration singleton
248
+ def configuration
249
+ self.class.configuration
250
+ end
251
+
252
+ end
253
+
metadata ADDED
@@ -0,0 +1,64 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: adyen_client
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ platform: ruby
6
+ authors:
7
+ - Lukas Rieder
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2015-12-16 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.13.5
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: 0.13.5
27
+ description: Does not try to be smart, stays close to the documentation while adhering
28
+ to ruby conventions.
29
+ email: l.rieder@gmail.com
30
+ executables: []
31
+ extensions: []
32
+ extra_rdoc_files: []
33
+ files:
34
+ - LICENSE
35
+ - README.md
36
+ - lib/adyen_client.rb
37
+ - lib/adyen_client/configuration.rb
38
+ - lib/adyen_client/response.rb
39
+ - lib/adyen_client/utils.rb
40
+ homepage: https://github.com/Overbryd/adyen_client
41
+ licenses:
42
+ - MIT
43
+ metadata: {}
44
+ post_install_message:
45
+ rdoc_options: []
46
+ require_paths:
47
+ - lib
48
+ required_ruby_version: !ruby/object:Gem::Requirement
49
+ requirements:
50
+ - - "~>"
51
+ - !ruby/object:Gem::Version
52
+ version: '2.0'
53
+ required_rubygems_version: !ruby/object:Gem::Requirement
54
+ requirements:
55
+ - - ">="
56
+ - !ruby/object:Gem::Version
57
+ version: '0'
58
+ requirements: []
59
+ rubyforge_project:
60
+ rubygems_version: 2.4.5.1
61
+ signing_key:
62
+ specification_version: 4
63
+ summary: A simple client that talks to the Adyen API
64
+ test_files: []