pensio_api 0.2.1 → 0.2.2
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 +13 -5
- data/.rspec +2 -0
- data/Gemfile +3 -0
- data/Gemfile.lock +83 -0
- data/Guardfile +23 -0
- data/LICENSE +24 -0
- data/README.md +77 -0
- data/lib/pensio_api/billing_address.rb +15 -0
- data/lib/pensio_api/callback.rb +30 -0
- data/lib/pensio_api/credentials.rb +7 -0
- data/lib/pensio_api/ecommerce.rb +13 -0
- data/lib/pensio_api/errors/bad_request.rb +15 -0
- data/lib/pensio_api/errors/gateway_error.rb +21 -0
- data/lib/pensio_api/errors/no_credentials.rb +9 -0
- data/lib/pensio_api/funding_list.rb +30 -0
- data/lib/pensio_api/funding_list_request.rb +15 -0
- data/lib/pensio_api/mixins/has_transactions.rb +36 -0
- data/lib/pensio_api/mixins/id.rb +9 -0
- data/lib/pensio_api/mixins/method_missing.rb +9 -0
- data/lib/pensio_api/mixins/request_defaults.rb +50 -0
- data/lib/pensio_api/mixins/timestamps.rb +13 -0
- data/lib/pensio_api/request.rb +18 -0
- data/lib/pensio_api/reservation.rb +28 -0
- data/lib/pensio_api/responses/base.rb +32 -0
- data/lib/pensio_api/responses/funding_list.rb +43 -0
- data/lib/pensio_api/responses/gateway_url.rb +13 -0
- data/lib/pensio_api/responses/refund.rb +17 -0
- data/lib/pensio_api/responses/reservation.rb +15 -0
- data/lib/pensio_api/responses/reservation_capture.rb +14 -0
- data/lib/pensio_api/responses/reservation_release.rb +6 -0
- data/lib/pensio_api/responses/subscription_charge.rb +21 -0
- data/lib/pensio_api/responses/subscription_failure_callback.rb +21 -0
- data/lib/pensio_api/responses/success_callback.rb +21 -0
- data/lib/pensio_api/responses/terminal.rb +41 -0
- data/lib/pensio_api/responses/transaction.rb +13 -0
- data/lib/pensio_api/subscription.rb +30 -0
- data/lib/pensio_api/terminal.rb +17 -0
- data/lib/pensio_api/transaction.rb +84 -0
- data/lib/pensio_api.rb +36 -0
- data/pensio_api.gemspec +20 -0
- data/spec/lib/pensio_api/billing_address_spec.rb +40 -0
- data/spec/lib/pensio_api/callback_spec.rb +21 -0
- data/spec/lib/pensio_api/ecommerce_spec.rb +22 -0
- data/spec/lib/pensio_api/errors/bad_request_spec.rb +31 -0
- data/spec/lib/pensio_api/errors/gateway_error_spec.rb +38 -0
- data/spec/lib/pensio_api/funding_list_request_spec.rb +17 -0
- data/spec/lib/pensio_api/funding_list_spec.rb +38 -0
- data/spec/lib/pensio_api/request_spec.rb +122 -0
- data/spec/lib/pensio_api/reservation_spec.rb +32 -0
- data/spec/lib/pensio_api/responses/base_spec.rb +68 -0
- data/spec/lib/pensio_api/responses/funding_list_spec.rb +23 -0
- data/spec/lib/pensio_api/responses/gateway_url_spec.rb +17 -0
- data/spec/lib/pensio_api/responses/refund_spec.rb +18 -0
- data/spec/lib/pensio_api/responses/reservation_capture_spec.rb +18 -0
- data/spec/lib/pensio_api/responses/reservation_release_spec.rb +12 -0
- data/spec/lib/pensio_api/responses/reservation_spec.rb +15 -0
- data/spec/lib/pensio_api/responses/subscription_charge_spec.rb +56 -0
- data/spec/lib/pensio_api/responses/subscription_failure_callback_spec.rb +48 -0
- data/spec/lib/pensio_api/responses/success_callback_spec.rb +45 -0
- data/spec/lib/pensio_api/responses/terminal_spec.rb +55 -0
- data/spec/lib/pensio_api/responses/transaction_spec.rb +56 -0
- data/spec/lib/pensio_api/subscription_spec.rb +37 -0
- data/spec/lib/pensio_api/terminal_spec.rb +18 -0
- data/spec/lib/pensio_api/transaction_spec.rb +101 -0
- data/spec/spec_helper.rb +26 -0
- data/spec/support/fixtures/bad_request_error.xml +10 -0
- data/spec/support/fixtures/capture_reservation.xml +84 -0
- data/spec/support/fixtures/charge_subscription.xml +89 -0
- data/spec/support/fixtures/create_multi_payment_request.xml +13 -0
- data/spec/support/fixtures/create_payment_request.xml +13 -0
- data/spec/support/fixtures/failure_callback.xml +76 -0
- data/spec/support/fixtures/funding_download.csv +6 -0
- data/spec/support/fixtures/funding_list.xml +43 -0
- data/spec/support/fixtures/get_terminals.xml +38 -0
- data/spec/support/fixtures/get_terminals_none.xml +12 -0
- data/spec/support/fixtures/get_terminals_single.xml +28 -0
- data/spec/support/fixtures/multiple_payments.xml +146 -0
- data/spec/support/fixtures/payments.xml +80 -0
- data/spec/support/fixtures/payments_none.xml +13 -0
- data/spec/support/fixtures/pensio_error.xml +48 -0
- data/spec/support/fixtures/refund_captured_reservation.xml +88 -0
- data/spec/support/fixtures/release_reservation.xml +72 -0
- data/spec/support/fixtures/reservation_of_fixed_amount.xml +46 -0
- data/spec/support/fixtures/reserve_subscription_charge.xml +86 -0
- data/spec/support/fixtures/setup_subscription.xml +46 -0
- data/spec/support/fixtures/subscription_failure_callback.xml +132 -0
- data/spec/support/fixtures/success_callback.xml +119 -0
- data/spec/support/helpers.rb +38 -0
- metadata +150 -15
checksums.yaml
CHANGED
@@ -1,7 +1,15 @@
|
|
1
1
|
---
|
2
|
-
|
3
|
-
metadata.gz:
|
4
|
-
|
2
|
+
!binary "U0hBMQ==":
|
3
|
+
metadata.gz: !binary |-
|
4
|
+
MmJkMDI1NTg4NzNiYjk4NjQ1ZTFjMGY5YTAxOGMxM2Y1MTgwMWZkZg==
|
5
|
+
data.tar.gz: !binary |-
|
6
|
+
NTEzODc3OWY4Yjc2YjA1NDk0ODQ1MGU2MzE3NTQ1OWI0MThmZTA0NQ==
|
5
7
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
|
8
|
+
metadata.gz: !binary |-
|
9
|
+
N2U3YjYwMjZjYWVlN2UyNTczYmNiZTZhMzE1N2JjYzgwMzAwMmYwZmNlOThh
|
10
|
+
NjM3YzdhOTMwZmVkYTBlMDFiODExNzEzYzNmMzgxMDNmZWU0OTc4MGU4NWI3
|
11
|
+
OTkwOWFkNjVkN2RjMzNhNDkyNjE2ZWM5ODdiYTgxNGEzMjJkYjk=
|
12
|
+
data.tar.gz: !binary |-
|
13
|
+
ODRiYzQzY2JmODhkYmFhMjE4ZTdhZjQzMWJhMzU2ZmRhMGRhNTMwMjgzMTc0
|
14
|
+
NTBlNWE0ZDVlNmE0NDIzNjdlNDE4ODQzMDAwZDBiNTMyNjkxOWNhMjAyMmM0
|
15
|
+
NjBlNzUwMjY0ZDdiMTk0NjhhZDc1NDQxMmRmZjAzZTJmMGE2YjE=
|
data/.rspec
ADDED
data/Gemfile
ADDED
data/Gemfile.lock
ADDED
@@ -0,0 +1,83 @@
|
|
1
|
+
PATH
|
2
|
+
remote: .
|
3
|
+
specs:
|
4
|
+
pensio_api (0.2.2)
|
5
|
+
activesupport (>= 3.2)
|
6
|
+
httparty (>= 0.12.0)
|
7
|
+
multi_xml (>= 0.5.2)
|
8
|
+
|
9
|
+
GEM
|
10
|
+
remote: https://www.rubygems.org/
|
11
|
+
specs:
|
12
|
+
activesupport (4.0.4)
|
13
|
+
i18n (~> 0.6, >= 0.6.9)
|
14
|
+
minitest (~> 4.2)
|
15
|
+
multi_json (~> 1.3)
|
16
|
+
thread_safe (~> 0.1)
|
17
|
+
tzinfo (~> 0.3.37)
|
18
|
+
addressable (2.3.5)
|
19
|
+
celluloid (0.15.2)
|
20
|
+
timers (~> 1.1.0)
|
21
|
+
coderay (1.1.0)
|
22
|
+
crack (0.4.1)
|
23
|
+
safe_yaml (~> 0.9.0)
|
24
|
+
diff-lcs (1.2.5)
|
25
|
+
ffi (1.9.3)
|
26
|
+
formatador (0.2.4)
|
27
|
+
guard (2.2.5)
|
28
|
+
formatador (>= 0.2.4)
|
29
|
+
listen (~> 2.1)
|
30
|
+
lumberjack (~> 1.0)
|
31
|
+
pry (>= 0.9.12)
|
32
|
+
thor (>= 0.18.1)
|
33
|
+
guard-rspec (4.2.4)
|
34
|
+
guard (~> 2.1)
|
35
|
+
rspec (>= 2.14, < 4.0)
|
36
|
+
httparty (0.13.0)
|
37
|
+
json (~> 1.8)
|
38
|
+
multi_xml (>= 0.5.2)
|
39
|
+
i18n (0.6.9)
|
40
|
+
json (1.8.1)
|
41
|
+
listen (2.4.0)
|
42
|
+
celluloid (>= 0.15.2)
|
43
|
+
rb-fsevent (>= 0.9.3)
|
44
|
+
rb-inotify (>= 0.9)
|
45
|
+
lumberjack (1.0.4)
|
46
|
+
method_source (0.8.2)
|
47
|
+
minitest (4.7.5)
|
48
|
+
multi_json (1.9.2)
|
49
|
+
multi_xml (0.5.5)
|
50
|
+
pry (0.9.12.4)
|
51
|
+
coderay (~> 1.0)
|
52
|
+
method_source (~> 0.8)
|
53
|
+
slop (~> 3.4)
|
54
|
+
rb-fsevent (0.9.4)
|
55
|
+
rb-inotify (0.9.3)
|
56
|
+
ffi (>= 0.5.0)
|
57
|
+
rspec (2.14.1)
|
58
|
+
rspec-core (~> 2.14.0)
|
59
|
+
rspec-expectations (~> 2.14.0)
|
60
|
+
rspec-mocks (~> 2.14.0)
|
61
|
+
rspec-core (2.14.7)
|
62
|
+
rspec-expectations (2.14.4)
|
63
|
+
diff-lcs (>= 1.1.3, < 2.0)
|
64
|
+
rspec-mocks (2.14.4)
|
65
|
+
safe_yaml (0.9.7)
|
66
|
+
slop (3.4.7)
|
67
|
+
thor (0.18.1)
|
68
|
+
thread_safe (0.3.2)
|
69
|
+
timers (1.1.0)
|
70
|
+
tzinfo (0.3.39)
|
71
|
+
webmock (1.16.1)
|
72
|
+
addressable (>= 2.2.7)
|
73
|
+
crack (>= 0.3.2)
|
74
|
+
|
75
|
+
PLATFORMS
|
76
|
+
ruby
|
77
|
+
|
78
|
+
DEPENDENCIES
|
79
|
+
guard (~> 2.2.5)
|
80
|
+
guard-rspec (~> 4.2.4)
|
81
|
+
pensio_api!
|
82
|
+
rspec (>= 2.14)
|
83
|
+
webmock (~> 1.16.1)
|
data/Guardfile
ADDED
@@ -0,0 +1,23 @@
|
|
1
|
+
# A sample Guardfile
|
2
|
+
# More info at https://github.com/guard/guard#readme
|
3
|
+
|
4
|
+
guard :rspec do
|
5
|
+
watch(%r{^spec/.+_spec\.rb$})
|
6
|
+
watch(%r{^lib/(.+)\.rb$}) { |m| "spec/lib/#{m[1]}_spec.rb" }
|
7
|
+
watch('spec/spec_helper.rb') { "spec" }
|
8
|
+
|
9
|
+
# Rails example
|
10
|
+
watch(%r{^app/(.+)\.rb$}) { |m| "spec/#{m[1]}_spec.rb" }
|
11
|
+
watch(%r{^app/(.*)(\.erb|\.haml|\.slim)$}) { |m| "spec/#{m[1]}#{m[2]}_spec.rb" }
|
12
|
+
watch(%r{^app/controllers/(.+)_(controller)\.rb$}) { |m| ["spec/routing/#{m[1]}_routing_spec.rb", "spec/#{m[2]}s/#{m[1]}_#{m[2]}_spec.rb", "spec/acceptance/#{m[1]}_spec.rb"] }
|
13
|
+
watch(%r{^spec/support/(.+)\.rb$}) { "spec" }
|
14
|
+
watch('config/routes.rb') { "spec/routing" }
|
15
|
+
watch('app/controllers/application_controller.rb') { "spec/controllers" }
|
16
|
+
|
17
|
+
# Capybara features specs
|
18
|
+
watch(%r{^app/views/(.+)/.*\.(erb|haml|slim)$}) { |m| "spec/features/#{m[1]}_spec.rb" }
|
19
|
+
|
20
|
+
# Turnip features and steps
|
21
|
+
watch(%r{^spec/acceptance/(.+)\.feature$})
|
22
|
+
watch(%r{^spec/acceptance/steps/(.+)_steps\.rb$}) { |m| Dir[File.join("**/#{m[1]}.feature")][0] || 'spec/acceptance' }
|
23
|
+
end
|
data/LICENSE
ADDED
@@ -0,0 +1,24 @@
|
|
1
|
+
Copyright (c) 2014, ASMALLWORLD, AG
|
2
|
+
All rights reserved.
|
3
|
+
|
4
|
+
Redistribution and use in source and binary forms, with or without
|
5
|
+
modification, are permitted provided that the following conditions are met:
|
6
|
+
* Redistributions of source code must retain the above copyright
|
7
|
+
notice, this list of conditions and the following disclaimer.
|
8
|
+
* Redistributions in binary form must reproduce the above copyright
|
9
|
+
notice, this list of conditions and the following disclaimer in the
|
10
|
+
documentation and/or other materials provided with the distribution.
|
11
|
+
* Neither the name of ASMALLWORLD, AG nor the
|
12
|
+
names of its contributors may be used to endorse or promote products
|
13
|
+
derived from this software without specific prior written permission.
|
14
|
+
|
15
|
+
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
16
|
+
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
17
|
+
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
18
|
+
DISCLAIMED. IN NO EVENT SHALL ASMALLWORLD, AG BE LIABLE FOR ANY
|
19
|
+
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
20
|
+
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
21
|
+
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
22
|
+
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
23
|
+
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
24
|
+
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
data/README.md
ADDED
@@ -0,0 +1,77 @@
|
|
1
|
+
# PensioAPI
|
2
|
+
This gem covers most of the Merchant and eCommerce API functionality provided by Pensio (http://www.pensio.com).
|
3
|
+
|
4
|
+
## Getting Started
|
5
|
+
|
6
|
+
First, register your Pensio credentials. For example, if you're using rails, create `config/initializers/pensio.rb` with the following contents:
|
7
|
+
|
8
|
+
```
|
9
|
+
PensioAPI::Credentials.base_uri = 'Your pensio gateway URI'
|
10
|
+
PensioAPI::Credentials.username = 'Your pensio username'
|
11
|
+
PensioAPI::Credentials.password = 'Your pensio password'
|
12
|
+
```
|
13
|
+
|
14
|
+
## Transactions
|
15
|
+
|
16
|
+
To query transactions in your Pensio gateway, use the method `PensioAPI::Transaction.find`. This takes a number of parameters as defined in the Pensio documentation. For example:
|
17
|
+
|
18
|
+
```
|
19
|
+
PensioAPI::Transaction.find(transaction_id: '123')
|
20
|
+
```
|
21
|
+
|
22
|
+
This returns an enumerable `PensioAPI::Responses::Transaction` object as many `PensioAPI::Transaction` objects as match your criteria.
|
23
|
+
|
24
|
+
With a transaction object, you can perform several actions.
|
25
|
+
|
26
|
+
* Determine status via `.status`, `.captured?` and `.reserved`
|
27
|
+
* Refund via `.refund`
|
28
|
+
* Expose terminal details via `.terminal`
|
29
|
+
* Expose billing address via `.billing_address`
|
30
|
+
* Map to a subscription object via `.to_subscription`
|
31
|
+
* Map to a reservation object via `.to_reservation`
|
32
|
+
|
33
|
+
## Funding Lists
|
34
|
+
|
35
|
+
The funding list functionality of the Pensio Merchant API is exposed via `PensioAPI::FundingList.all` which returns an iterable collection of `PensioAPI::FundingList` objects. Calling `.download` on any of these objects downloads and parses the CSV file from the Pensio Gateway.
|
36
|
+
|
37
|
+
## Terminals
|
38
|
+
|
39
|
+
To query terminals, use the method `PensioAPI::Terminal.all`. This will return an enumerable object containing as many `PensioAPI::Terminals` as are associated with your gateway.
|
40
|
+
|
41
|
+
## Reservations
|
42
|
+
|
43
|
+
To create a fixed amount reservation (via the API call '/merchant/API/reservationOfFixedAmount') use the class method `PensioAPI::Reservation.of_fixed_amount`.
|
44
|
+
|
45
|
+
To capture an existing reservation, use `.capture`. Likewise to release it, use `.release`.
|
46
|
+
|
47
|
+
## Subscriptions
|
48
|
+
|
49
|
+
To create a subscription, use the class method `PensioAPI::Subscription.setup`. This takes the arguments documented in Pensio's documentation for the '/merchant/API/setupSubscription' API call.
|
50
|
+
|
51
|
+
With an existing subscription, use `.reserve_charge` to place a charge reservation upon the subscription or `.charge` to attempt a reservation and charge of the associated transaction.
|
52
|
+
|
53
|
+
## eCommerce
|
54
|
+
|
55
|
+
PensioAPI::Ecommerce is a module which exposes the eCommerce API endpoints. Two module methods `.create_payment_request` and `.create_multi_payment_request` can be used to generate payment URLs for a multitude of payment types. Consult the Pensio eCommerce API documentation for parameter details.
|
56
|
+
|
57
|
+
## Callbacks
|
58
|
+
|
59
|
+
`PensioAPI::Callback` provides two methods `.parse_success` and `.parse_failure`. These are designed to parse the callbacks Pensio send to your transaction success and transaction failure endpoints. Each returns a callback response which exposes the transaction details for processing by your app.
|
60
|
+
|
61
|
+
## Error Handling
|
62
|
+
|
63
|
+
The library provides two generic error classes for requests.
|
64
|
+
|
65
|
+
* `PensioAPI::Errors::BadRequest` is raised when the response from Pensio indicates that a request has invalid parameters
|
66
|
+
* `PensioAPI::Errors::GatewayError` is raised when the parameters have been provided correctly, but the gateway was unable to process the request
|
67
|
+
|
68
|
+
Additionally, a third error class `PensioAPI::NoCredentials` is raised if credentials have not been provided. See "Getting Started" for more details.
|
69
|
+
|
70
|
+
## TODO
|
71
|
+
|
72
|
+
* Better documentation - more examples, RDoc docs
|
73
|
+
* Further API implementation
|
74
|
+
|
75
|
+
## Contributing
|
76
|
+
|
77
|
+
Contributions are very welcome. Please submit pull requests with adequately-tested code.
|
@@ -0,0 +1,15 @@
|
|
1
|
+
module PensioAPI
|
2
|
+
class BillingAddress
|
3
|
+
attr_reader :first_name, :last_name, :street_address, :city, :region, :postal_code, :country
|
4
|
+
|
5
|
+
def initialize(address_params)
|
6
|
+
@first_name = address_params['Firstname']
|
7
|
+
@last_name = address_params['Lastname']
|
8
|
+
@street_address = address_params['Address']
|
9
|
+
@city = address_params['City']
|
10
|
+
@region = address_params['Region']
|
11
|
+
@postal_code = address_params['PostalCode']
|
12
|
+
@country = address_params['Country']
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
module PensioAPI
|
2
|
+
module Callback
|
3
|
+
FakeRequest = Struct.new(:headers, :body)
|
4
|
+
|
5
|
+
def self.parse_success(xml)
|
6
|
+
parse(xml, true)
|
7
|
+
end
|
8
|
+
|
9
|
+
def self.parse_failure(xml)
|
10
|
+
parse(xml, false)
|
11
|
+
end
|
12
|
+
|
13
|
+
private
|
14
|
+
|
15
|
+
def self.parse(xml, success)
|
16
|
+
params = MultiXml.parse(xml)
|
17
|
+
|
18
|
+
request = FakeRequest.new(
|
19
|
+
params['APIResponse']['Header'],
|
20
|
+
params['APIResponse']['Body']
|
21
|
+
)
|
22
|
+
|
23
|
+
if success
|
24
|
+
PensioAPI::Responses::SuccessCallback.new(request)
|
25
|
+
else
|
26
|
+
PensioAPI::Responses::SubscriptionFailureCallback.new(request)
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
@@ -0,0 +1,13 @@
|
|
1
|
+
module PensioAPI
|
2
|
+
module Ecommerce
|
3
|
+
def self.create_payment_request(options={})
|
4
|
+
request = Request.new('/merchant/API/createPaymentRequest', options)
|
5
|
+
Responses::GatewayURL.new(request)
|
6
|
+
end
|
7
|
+
|
8
|
+
def self.create_multi_payment_request(options={})
|
9
|
+
request = Request.new('/merchant/API/createMultiPaymentRequest', options)
|
10
|
+
Responses::GatewayURL.new(request)
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
module PensioAPI
|
2
|
+
module Errors
|
3
|
+
class BadRequest < StandardError
|
4
|
+
attr_reader :request_time, :request_path, :error_code
|
5
|
+
|
6
|
+
def initialize(request)
|
7
|
+
super(request.headers['ErrorMessage'])
|
8
|
+
|
9
|
+
@request_time = Time.parse(request.headers['Date'])
|
10
|
+
@request_path = request.headers['Path']
|
11
|
+
@error_code = request.headers['ErrorCode'].to_i
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
module PensioAPI
|
2
|
+
module Errors
|
3
|
+
class GatewayError < StandardError
|
4
|
+
include Mixins::HasTransactions
|
5
|
+
attr_reader :request_time, :request_path, :cardholder_message
|
6
|
+
|
7
|
+
def initialize(request)
|
8
|
+
super(request.body['MerchantErrorMessage'])
|
9
|
+
|
10
|
+
@raw = request.body
|
11
|
+
|
12
|
+
@request_time = Time.parse(request.headers['Date'])
|
13
|
+
@request_path = request.headers['Path']
|
14
|
+
|
15
|
+
@cardholder_message = request.body['CardHolderErrorMessage']
|
16
|
+
|
17
|
+
map_transactions
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
module PensioAPI
|
2
|
+
class FundingList
|
3
|
+
attr_reader :filename
|
4
|
+
attr_reader :amount
|
5
|
+
attr_reader :acquirer
|
6
|
+
attr_reader :funding_date
|
7
|
+
attr_reader :created_at
|
8
|
+
attr_reader :download_link
|
9
|
+
|
10
|
+
def self.all(options={})
|
11
|
+
request = Request.new('/merchant/API/fundingList', options)
|
12
|
+
Responses::FundingList.new(request)
|
13
|
+
end
|
14
|
+
|
15
|
+
def initialize(funding_list_body)
|
16
|
+
@raw = funding_list_body
|
17
|
+
|
18
|
+
@filename = @raw['Filename']
|
19
|
+
@amount = @raw['Amount']
|
20
|
+
@acquirer = @raw['Acquirer']
|
21
|
+
@funding_date = Date.parse(@raw['FundingDate'])
|
22
|
+
@created_at = Date.parse(@raw['CreatedDate'])
|
23
|
+
@download_link = @raw['DownloadLink']
|
24
|
+
end
|
25
|
+
|
26
|
+
def download
|
27
|
+
@result ||= FundingListRequest.new(@download_link).result
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
require 'csv'
|
2
|
+
|
3
|
+
module PensioAPI
|
4
|
+
class FundingListRequest
|
5
|
+
include Mixins::RequestDefaults
|
6
|
+
|
7
|
+
attr_reader :result
|
8
|
+
|
9
|
+
def initialize(path, options={})
|
10
|
+
super(path, options)
|
11
|
+
|
12
|
+
@result = CSV.parse(@response.parsed_response, col_sep: ';', headers: true).reject(&:empty?)
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
@@ -0,0 +1,36 @@
|
|
1
|
+
module PensioAPI
|
2
|
+
module Mixins
|
3
|
+
module HasTransactions
|
4
|
+
def self.included(base)
|
5
|
+
base.send(:include, Enumerable)
|
6
|
+
base.send(:attr_reader, :transactions)
|
7
|
+
end
|
8
|
+
|
9
|
+
def each
|
10
|
+
@transactions.each { |t| yield t }
|
11
|
+
end
|
12
|
+
|
13
|
+
def last
|
14
|
+
@transactions.last
|
15
|
+
end
|
16
|
+
|
17
|
+
private
|
18
|
+
|
19
|
+
def map_transactions
|
20
|
+
@transactions = if raw_transactions.is_a?(Array)
|
21
|
+
raw_transactions.map { |t| PensioAPI::Transaction.new(t) }
|
22
|
+
else
|
23
|
+
[PensioAPI::Transaction.new(raw_transactions)]
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
def raw_transactions
|
28
|
+
@raw_transactions ||= if @raw['Transactions']
|
29
|
+
@raw['Transactions']['Transaction']
|
30
|
+
else
|
31
|
+
[]
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
@@ -0,0 +1,50 @@
|
|
1
|
+
module PensioAPI
|
2
|
+
module Mixins
|
3
|
+
module RequestDefaults
|
4
|
+
def self.included(base)
|
5
|
+
base.send(:include, HTTParty)
|
6
|
+
base.send(:attr_reader, :response)
|
7
|
+
base.extend(ClassMethods)
|
8
|
+
end
|
9
|
+
|
10
|
+
module ClassMethods
|
11
|
+
def set_base_uri
|
12
|
+
self.base_uri PensioAPI::Credentials.base_uri unless self.base_uri
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
HEADERS = {
|
17
|
+
'Content-Type' => 'application/x-www-form-urlencoded'
|
18
|
+
}
|
19
|
+
|
20
|
+
def initialize(path, options={})
|
21
|
+
self.class.set_base_uri
|
22
|
+
|
23
|
+
raise Errors::NoCredentials unless credentials_supplied?
|
24
|
+
|
25
|
+
@response = self.class.post(path, request_options(options))
|
26
|
+
end
|
27
|
+
|
28
|
+
private
|
29
|
+
|
30
|
+
def request_options(options)
|
31
|
+
{
|
32
|
+
basic_auth: auth,
|
33
|
+
headers: (options.delete(:headers) || {}).merge(HEADERS),
|
34
|
+
body: options
|
35
|
+
}
|
36
|
+
end
|
37
|
+
|
38
|
+
def auth
|
39
|
+
{
|
40
|
+
username: PensioAPI::Credentials.username,
|
41
|
+
password: PensioAPI::Credentials.password
|
42
|
+
}
|
43
|
+
end
|
44
|
+
|
45
|
+
def credentials_supplied?
|
46
|
+
Credentials.base_uri && Credentials.username && Credentials.password
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
module PensioAPI
|
2
|
+
class Request
|
3
|
+
include Mixins::RequestDefaults
|
4
|
+
|
5
|
+
attr_reader :headers, :body
|
6
|
+
|
7
|
+
def initialize(path, options={})
|
8
|
+
super(path, options)
|
9
|
+
|
10
|
+
@headers = @response.parsed_response['APIResponse']['Header']
|
11
|
+
@body = @response.parsed_response['APIResponse']['Body']
|
12
|
+
end
|
13
|
+
|
14
|
+
def response_contains?(key)
|
15
|
+
@body && @body.has_key?(key)
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
module PensioAPI
|
2
|
+
class Reservation
|
3
|
+
def self.of_fixed_amount(options={})
|
4
|
+
request = Request.new('/merchant/API/reservationOfFixedAmount', options)
|
5
|
+
Responses::Reservation.new(request)
|
6
|
+
end
|
7
|
+
|
8
|
+
def initialize(transaction)
|
9
|
+
@transaction = transaction
|
10
|
+
end
|
11
|
+
|
12
|
+
def capture(options={})
|
13
|
+
request = Request.new('/merchant/API/captureReservation', options.merge(reservation_options))
|
14
|
+
Responses::ReservationCapture.new(request)
|
15
|
+
end
|
16
|
+
|
17
|
+
def release(options={})
|
18
|
+
request = Request.new('/merchant/API/releaseReservation', options.merge(reservation_options))
|
19
|
+
Responses::ReservationRelease.new(request)
|
20
|
+
end
|
21
|
+
|
22
|
+
private
|
23
|
+
|
24
|
+
def reservation_options
|
25
|
+
{ transaction_id: @transaction.id }
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
@@ -0,0 +1,32 @@
|
|
1
|
+
module PensioAPI
|
2
|
+
module Responses
|
3
|
+
class Base
|
4
|
+
include PensioAPI::Mixins::MethodMissing
|
5
|
+
|
6
|
+
attr_reader :raw
|
7
|
+
|
8
|
+
def initialize(request)
|
9
|
+
@raw = request.body
|
10
|
+
@headers = request.headers
|
11
|
+
unless success?
|
12
|
+
raise PensioAPI::Errors::BadRequest.new(request) unless header_ok
|
13
|
+
raise PensioAPI::Errors::GatewayError.new(request) unless body_ok
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
def success?
|
18
|
+
header_ok && body_ok
|
19
|
+
end
|
20
|
+
|
21
|
+
private
|
22
|
+
|
23
|
+
def header_ok
|
24
|
+
@headers['ErrorCode'].to_i == 0
|
25
|
+
end
|
26
|
+
|
27
|
+
def body_ok
|
28
|
+
!@raw.has_key?('Result') || ['Success', 'OK', nil].include?(@raw['Result'])
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
@@ -0,0 +1,43 @@
|
|
1
|
+
module PensioAPI
|
2
|
+
module Responses
|
3
|
+
class FundingList < Base
|
4
|
+
attr_reader :funding_lists, :page_count
|
5
|
+
|
6
|
+
include Enumerable
|
7
|
+
|
8
|
+
def initialize(request)
|
9
|
+
super(request)
|
10
|
+
|
11
|
+
map_funding_lists
|
12
|
+
|
13
|
+
@page_count = if @raw['Fundings']
|
14
|
+
(@raw['Fundings']['numberOfPages'] || 0).to_i
|
15
|
+
else
|
16
|
+
0
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
def each
|
21
|
+
@funding_lists.each { |fl| yield fl }
|
22
|
+
end
|
23
|
+
|
24
|
+
private
|
25
|
+
|
26
|
+
def map_funding_lists
|
27
|
+
@funding_lists = if raw_funding_lists.is_a?(Array)
|
28
|
+
raw_funding_lists.map { |fl| PensioAPI::FundingList.new(fl) }
|
29
|
+
else
|
30
|
+
[PensioAPI::FundingList.new(raw_funding_lists)]
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
def raw_funding_lists
|
35
|
+
@raw_funding_lists ||= if @raw['Fundings'] && raw['Fundings']['Funding']
|
36
|
+
@raw['Fundings']['Funding']
|
37
|
+
else
|
38
|
+
[]
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|