pensio_api 0.2.3 → 0.3.4
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 +7 -0
- data/.gitignore +3 -0
- data/Gemfile.lock +60 -49
- data/README.md +39 -1
- data/lib/pensio_api.rb +4 -0
- data/lib/pensio_api/callback.rb +13 -6
- data/lib/pensio_api/chargeback_event.rb +25 -0
- data/lib/pensio_api/credentials.rb +48 -2
- data/lib/pensio_api/funding_list.rb +3 -3
- data/lib/pensio_api/funding_list_request.rb +1 -1
- data/lib/pensio_api/mixins/request_defaults.rb +14 -16
- data/lib/pensio_api/request.rb +1 -1
- data/lib/pensio_api/responses/base.rb +9 -5
- data/lib/pensio_api/responses/chargeback_callback.rb +6 -0
- data/lib/pensio_api/responses/refund.rb +1 -1
- data/lib/pensio_api/responses/reservation.rb +11 -7
- data/lib/pensio_api/responses/reservation_capture.rb +6 -3
- data/lib/pensio_api/responses/reservation_release.rb +10 -1
- data/lib/pensio_api/transaction.rb +28 -4
- data/lib/pensio_api/version.rb +3 -0
- data/pensio_api.gemspec +5 -1
- data/spec/lib/pensio_api/callback_spec.rb +10 -2
- data/spec/lib/pensio_api/chargeback_event_spec.rb +37 -0
- data/spec/lib/pensio_api/ecommerce_spec.rb +13 -2
- data/spec/lib/pensio_api/errors/bad_request_spec.rb +1 -1
- data/spec/lib/pensio_api/errors/gateway_error_spec.rb +1 -1
- data/spec/lib/pensio_api/request_spec.rb +32 -15
- data/spec/lib/pensio_api/responses/base_spec.rb +2 -2
- data/spec/lib/pensio_api/responses/chargeback_callback_spec.rb +9 -0
- data/spec/lib/pensio_api/responses/funding_list_spec.rb +1 -1
- data/spec/lib/pensio_api/responses/refund_spec.rb +1 -1
- data/spec/lib/pensio_api/responses/reservation_capture_spec.rb +1 -1
- data/spec/lib/pensio_api/responses/reservation_spec.rb +2 -1
- data/spec/lib/pensio_api/responses/subscription_charge_spec.rb +1 -1
- data/spec/lib/pensio_api/responses/subscription_failure_callback_spec.rb +1 -1
- data/spec/lib/pensio_api/responses/success_callback_spec.rb +1 -1
- data/spec/lib/pensio_api/responses/terminal_spec.rb +1 -1
- data/spec/lib/pensio_api/responses/transaction_spec.rb +1 -1
- data/spec/lib/pensio_api/transaction_spec.rb +8 -4
- data/spec/spec_helper.rb +1 -1
- data/spec/support/fixtures/chargeback_callback.xml +92 -0
- data/spec/support/fixtures/reservation_of_fixed_amount.xml +136 -45
- metadata +37 -44
@@ -9,24 +9,28 @@ module PensioAPI
|
|
9
9
|
@raw = request.body
|
10
10
|
@headers = request.headers
|
11
11
|
unless success?
|
12
|
-
raise PensioAPI::Errors::BadRequest.new(request) unless header_ok
|
13
|
-
raise PensioAPI::Errors::GatewayError.new(request) unless body_ok
|
12
|
+
raise PensioAPI::Errors::BadRequest.new(request) unless header_ok?
|
13
|
+
raise PensioAPI::Errors::GatewayError.new(request) unless body_ok? || chargeback?
|
14
14
|
end
|
15
15
|
end
|
16
16
|
|
17
17
|
def success?
|
18
|
-
header_ok && body_ok
|
18
|
+
header_ok? && (body_ok? || chargeback?)
|
19
19
|
end
|
20
20
|
|
21
21
|
private
|
22
22
|
|
23
|
-
def header_ok
|
23
|
+
def header_ok?
|
24
24
|
@headers['ErrorCode'].to_i == 0
|
25
25
|
end
|
26
26
|
|
27
|
-
def body_ok
|
27
|
+
def body_ok?
|
28
28
|
!@raw.has_key?('Result') || ['Success', 'OK', nil].include?(@raw['Result'])
|
29
29
|
end
|
30
|
+
|
31
|
+
def chargeback?
|
32
|
+
@raw['Result'] == 'ChargebackEvent'
|
33
|
+
end
|
30
34
|
end
|
31
35
|
end
|
32
36
|
end
|
@@ -9,7 +9,7 @@ module PensioAPI
|
|
9
9
|
@transaction = PensioAPI::Transaction.new(
|
10
10
|
transactions['Transaction']
|
11
11
|
)
|
12
|
-
@refund_amount = BigDecimal
|
12
|
+
@refund_amount = BigDecimal(@raw['RefundedAmount'])
|
13
13
|
@refund_currency = @raw['RefundCurrency'].to_i
|
14
14
|
end
|
15
15
|
end
|
@@ -1,15 +1,19 @@
|
|
1
1
|
module PensioAPI
|
2
2
|
module Responses
|
3
|
-
class Reservation <
|
4
|
-
attr_reader :transaction
|
3
|
+
class Reservation < Transaction
|
5
4
|
|
6
|
-
def
|
7
|
-
|
5
|
+
def each
|
6
|
+
[reservation, charge].each { |t| yield t }
|
7
|
+
end
|
8
|
+
|
9
|
+
def reservation
|
10
|
+
@transactions.first
|
11
|
+
end
|
8
12
|
|
9
|
-
|
10
|
-
|
11
|
-
)
|
13
|
+
def charge
|
14
|
+
@transactions.last
|
12
15
|
end
|
16
|
+
|
13
17
|
end
|
14
18
|
end
|
15
19
|
end
|
@@ -1,12 +1,15 @@
|
|
1
1
|
module PensioAPI
|
2
2
|
module Responses
|
3
|
-
class ReservationCapture <
|
4
|
-
attr_reader :capture_amount, :capture_currency
|
3
|
+
class ReservationCapture < Base
|
4
|
+
attr_reader :transaction, :capture_amount, :capture_currency
|
5
5
|
|
6
6
|
def initialize(request)
|
7
7
|
super(request)
|
8
8
|
|
9
|
-
@
|
9
|
+
@transaction = PensioAPI::Transaction.new(
|
10
|
+
transactions['Transaction']
|
11
|
+
)
|
12
|
+
@capture_amount = BigDecimal(@raw['CaptureAmount'])
|
10
13
|
@capture_currency = @raw['CaptureCurrency'].to_i
|
11
14
|
end
|
12
15
|
end
|
@@ -1,6 +1,15 @@
|
|
1
1
|
module PensioAPI
|
2
2
|
module Responses
|
3
|
-
class ReservationRelease <
|
3
|
+
class ReservationRelease < Base
|
4
|
+
attr_reader :transaction
|
5
|
+
|
6
|
+
def initialize(request)
|
7
|
+
super(request)
|
8
|
+
|
9
|
+
@transaction = PensioAPI::Transaction.new(
|
10
|
+
transactions['Transaction']
|
11
|
+
)
|
12
|
+
end
|
4
13
|
end
|
5
14
|
end
|
6
15
|
end
|
@@ -15,6 +15,8 @@ module PensioAPI
|
|
15
15
|
attr_reader :order_id
|
16
16
|
attr_reader :merchant_currency
|
17
17
|
attr_reader :card_holder_currency
|
18
|
+
attr_reader :payment_source
|
19
|
+
attr_reader :chargeback_events
|
18
20
|
|
19
21
|
# constants for transaction statuses
|
20
22
|
STATUS_RECURRING_CONFIRMED = 'recurring_confirmed'
|
@@ -30,10 +32,10 @@ module PensioAPI
|
|
30
32
|
|
31
33
|
@status = @raw['TransactionStatus']
|
32
34
|
|
33
|
-
@captured_amount = BigDecimal
|
34
|
-
@reserved_amount = BigDecimal
|
35
|
-
@refunded_amount = BigDecimal
|
36
|
-
@recurring_default_amount = BigDecimal
|
35
|
+
@captured_amount = BigDecimal(@raw['CapturedAmount'])
|
36
|
+
@reserved_amount = BigDecimal(@raw['ReservedAmount'])
|
37
|
+
@refunded_amount = BigDecimal(@raw['RefundedAmount'])
|
38
|
+
@recurring_default_amount = BigDecimal(@raw['RecurringDefaultAmount'])
|
37
39
|
|
38
40
|
@card_status = @raw['CardStatus']
|
39
41
|
@card_token = @raw['CreditCardToken']
|
@@ -43,6 +45,10 @@ module PensioAPI
|
|
43
45
|
|
44
46
|
@merchant_currency = @raw['MerchantCurrency'].to_i
|
45
47
|
@card_holder_currency = @raw['CardHolderCurrency'].to_i
|
48
|
+
|
49
|
+
@payment_source = @raw['PaymentSource']
|
50
|
+
|
51
|
+
map_chargeback_events
|
46
52
|
end
|
47
53
|
|
48
54
|
def self.find(options={})
|
@@ -80,5 +86,23 @@ module PensioAPI
|
|
80
86
|
BillingAddress.new(@raw['CustomerInfo']['BillingAddress'])
|
81
87
|
end
|
82
88
|
end
|
89
|
+
|
90
|
+
private
|
91
|
+
|
92
|
+
def map_chargeback_events
|
93
|
+
@chargeback_events = if raw_chargeback_events.is_a?(Array)
|
94
|
+
raw_chargeback_events.map { |c| PensioAPI::ChargebackEvent.new(c) }
|
95
|
+
else
|
96
|
+
[PensioAPI::ChargebackEvent.new(raw_chargeback_events)]
|
97
|
+
end
|
98
|
+
end
|
99
|
+
|
100
|
+
def raw_chargeback_events
|
101
|
+
@raw_chargeback_events ||= if @raw['ChargebackEvents']
|
102
|
+
@raw['ChargebackEvents']['ChargebackEvent']
|
103
|
+
else
|
104
|
+
[]
|
105
|
+
end
|
106
|
+
end
|
83
107
|
end
|
84
108
|
end
|
data/pensio_api.gemspec
CHANGED
@@ -1,6 +1,10 @@
|
|
1
|
+
lib = File.expand_path('lib', __dir__)
|
2
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
3
|
+
require 'pensio_api/version'
|
4
|
+
|
1
5
|
Gem::Specification.new do |s|
|
2
6
|
s.name = 'pensio_api'
|
3
|
-
s.version =
|
7
|
+
s.version = PensioAPI::VERSION
|
4
8
|
s.license = 'BSD-3-Clause'
|
5
9
|
s.summary = "Provides integration for the Pensio Merchant API"
|
6
10
|
s.authors = ['Michael Sell', 'Rory Sinclair']
|
@@ -6,7 +6,7 @@ describe PensioAPI::Callback do
|
|
6
6
|
let(:response) { PensioAPI::Callback.parse_success(file_fixture("success_callback.xml")) }
|
7
7
|
it "should return a SuccessCallback response" do
|
8
8
|
expect(response).to be_an_instance_of(PensioAPI::Responses::SuccessCallback)
|
9
|
-
expect(response.success?).to
|
9
|
+
expect(response.success?).to be true
|
10
10
|
end
|
11
11
|
end
|
12
12
|
|
@@ -14,7 +14,15 @@ describe PensioAPI::Callback do
|
|
14
14
|
let(:response) { PensioAPI::Callback.parse_failure(file_fixture("subscription_failure_callback.xml")) }
|
15
15
|
it "should return a SubscriptionFailureCallback response" do
|
16
16
|
expect(response).to be_an_instance_of(PensioAPI::Responses::SubscriptionFailureCallback)
|
17
|
-
expect(response.success?).to
|
17
|
+
expect(response.success?).to be true
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
describe ".parse_chargeback" do
|
22
|
+
let(:response) { PensioAPI::Callback.parse_chargeback(file_fixture("chargeback_callback.xml")) }
|
23
|
+
it "should return a ChargebackCallback response" do
|
24
|
+
expect(response).to be_an_instance_of(PensioAPI::Responses::ChargebackCallback)
|
25
|
+
expect(response.success?).to be true
|
18
26
|
end
|
19
27
|
end
|
20
28
|
end
|
@@ -0,0 +1,37 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe PensioAPI::ChargebackEvent do
|
4
|
+
let(:response) { PensioAPI::Callback.parse_chargeback(file_fixture("chargeback_callback.xml")) }
|
5
|
+
let(:transaction) { response.transactions.last }
|
6
|
+
let(:chargeback_event) { transaction.chargeback_events.last }
|
7
|
+
|
8
|
+
describe 'reader attributes' do
|
9
|
+
describe 'type' do
|
10
|
+
specify { expect(chargeback_event.type).to be_an_instance_of(String) }
|
11
|
+
end
|
12
|
+
|
13
|
+
describe 'reason_code' do
|
14
|
+
specify { expect(chargeback_event.reason_code).to be_an_instance_of(Integer) }
|
15
|
+
end
|
16
|
+
|
17
|
+
describe 'reason' do
|
18
|
+
specify { expect(chargeback_event.reason).to be_an_instance_of(String) }
|
19
|
+
end
|
20
|
+
|
21
|
+
describe 'amount' do
|
22
|
+
specify { expect(chargeback_event.amount).to be_an_instance_of(BigDecimal) }
|
23
|
+
end
|
24
|
+
|
25
|
+
describe 'currency' do
|
26
|
+
specify { expect(chargeback_event.currency).to be_an_instance_of(String) }
|
27
|
+
end
|
28
|
+
|
29
|
+
describe 'acquirer_transaction_id' do
|
30
|
+
specify { expect(chargeback_event.acquirer_transaction_id).to be_an_instance_of(String) }
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
describe 'created_at' do
|
35
|
+
specify { expect(chargeback_event.created_at).to be_an_instance_of(Time) }
|
36
|
+
end
|
37
|
+
end
|
@@ -7,14 +7,25 @@ describe PensioAPI::Ecommerce do
|
|
7
7
|
end
|
8
8
|
|
9
9
|
describe '.create_payment_request' do
|
10
|
-
let(:response) {
|
10
|
+
let(:response) {PensioAPI::Ecommerce.create_payment_request(reservation_arguments.merge({timeout: 10}))}
|
11
11
|
it 'returns an instance of PensioAPI::Responses::GatewayURL' do
|
12
|
+
expect(PensioAPI::Request).to receive(:post).with("/merchant/API/createPaymentRequest",
|
13
|
+
{:basic_auth => {:username => "test_user", :password => "password"},
|
14
|
+
:headers => {
|
15
|
+
"Content-Type" => "application/x-www-form-urlencoded; charset=utf-8",
|
16
|
+
'x-altapay-client-version' => "RUBYSDK/#{PensioAPI::VERSION}"
|
17
|
+
},
|
18
|
+
:body => {:terminal => "Pensio Test Terminal",
|
19
|
+
:shop_orderid => "Test Payment",
|
20
|
+
:amount => 123.45,
|
21
|
+
:currency => "eur"},
|
22
|
+
:timeout => 10}).and_call_original
|
12
23
|
expect(response).to be_an_instance_of(PensioAPI::Responses::GatewayURL)
|
13
24
|
end
|
14
25
|
end
|
15
26
|
|
16
27
|
describe '.create_multi_payment_request' do
|
17
|
-
let(:response) {
|
28
|
+
let(:response) {PensioAPI::Ecommerce.create_multi_payment_request(reservation_arguments)}
|
18
29
|
it 'returns an instance of PensioAPI::Responses::GatewayURL' do
|
19
30
|
expect(response).to be_an_instance_of(PensioAPI::Responses::GatewayURL)
|
20
31
|
end
|
@@ -31,7 +31,7 @@ describe PensioAPI::Errors::GatewayError do
|
|
31
31
|
|
32
32
|
describe 'object mapping' do
|
33
33
|
it 'maps transactions to transaction objects' do
|
34
|
-
expect(error.transactions.all? { |r| r.class == PensioAPI::Transaction }).to
|
34
|
+
expect(error.transactions.all? { |r| r.class == PensioAPI::Transaction }).to be true
|
35
35
|
end
|
36
36
|
end
|
37
37
|
end
|
@@ -3,12 +3,12 @@ require 'spec_helper'
|
|
3
3
|
describe PensioAPI::Request do
|
4
4
|
describe '.new' do
|
5
5
|
before :each do
|
6
|
-
PensioAPI::Request.
|
6
|
+
allow(PensioAPI::Request).to receive(:post).and_return(construct_response(nil))
|
7
7
|
end
|
8
8
|
|
9
9
|
it 'POSTs to the given API path and passes in request options' do
|
10
10
|
request_options = PensioAPI::Request.new('/test').send(:request_options, {})
|
11
|
-
PensioAPI::Request.
|
11
|
+
expect(PensioAPI::Request).to receive(:post).with('/test', request_options)
|
12
12
|
PensioAPI::Request.new('/test')
|
13
13
|
end
|
14
14
|
end
|
@@ -16,10 +16,10 @@ describe PensioAPI::Request do
|
|
16
16
|
describe '.response_contains' do
|
17
17
|
context 'with a populated response body' do
|
18
18
|
before :each do
|
19
|
-
PensioAPI::Request.
|
19
|
+
allow(PensioAPI::Request).to receive(:post).and_return(
|
20
20
|
construct_response({
|
21
|
-
|
22
|
-
|
21
|
+
'Test' => 'true'
|
22
|
+
})
|
23
23
|
)
|
24
24
|
end
|
25
25
|
|
@@ -27,33 +27,33 @@ describe PensioAPI::Request do
|
|
27
27
|
|
28
28
|
context 'given a valid key' do
|
29
29
|
it 'returns true' do
|
30
|
-
expect(request.response_contains?('Test')).to
|
30
|
+
expect(request.response_contains?('Test')).to be true
|
31
31
|
end
|
32
32
|
end
|
33
33
|
|
34
34
|
context 'given an invalid key' do
|
35
35
|
it 'returns false' do
|
36
|
-
expect(request.response_contains?('OtherTest')).to
|
36
|
+
expect(request.response_contains?('OtherTest')).to be false
|
37
37
|
end
|
38
38
|
end
|
39
39
|
end
|
40
40
|
|
41
41
|
context 'with an empty response body' do
|
42
42
|
before :each do
|
43
|
-
PensioAPI::Request.
|
43
|
+
allow(PensioAPI::Request).to receive(:post).and_return(construct_response(nil))
|
44
44
|
end
|
45
45
|
|
46
46
|
let(:request) { PensioAPI::Request.new('/test') }
|
47
47
|
|
48
48
|
it 'returns false' do
|
49
|
-
expect(request.response_contains?('Test')).to
|
49
|
+
expect(request.response_contains?('Test')).to be false
|
50
50
|
end
|
51
51
|
end
|
52
52
|
end
|
53
53
|
|
54
54
|
describe '.request_options' do
|
55
55
|
before :each do
|
56
|
-
PensioAPI::Request.
|
56
|
+
allow(PensioAPI::Request).to receive(:post).and_return(construct_response(nil))
|
57
57
|
end
|
58
58
|
|
59
59
|
let(:p) { PensioAPI::Request.new('/test') }
|
@@ -82,6 +82,27 @@ describe PensioAPI::Request do
|
|
82
82
|
expect(p.send(:request_options, {transaction_id: 5432})[:body][:transaction_id]).to eq(5432)
|
83
83
|
end
|
84
84
|
end
|
85
|
+
|
86
|
+
context 'with alternative credentials' do
|
87
|
+
it 'sends the correct credentials' do
|
88
|
+
creds = PensioAPI::Credentials.for(:ticketing)
|
89
|
+
creds.base_uri = 'https://www.test.com'
|
90
|
+
creds.username = 'ticketing_username'
|
91
|
+
creds.password = 'ticketing_password'
|
92
|
+
|
93
|
+
# pass credentials instance
|
94
|
+
req1 = PensioAPI::Request.new('/test', credentials: creds)
|
95
|
+
|
96
|
+
# or pass credentials set name
|
97
|
+
req2 = PensioAPI::Request.new('/test', credentials: :ticketing)
|
98
|
+
|
99
|
+
expect(req1.send(:request_options, {})[:basic_auth]).to_not be_nil
|
100
|
+
expect(req1.send(:request_options, {})[:basic_auth]).to eq({ username: creds.username, password: creds.password})
|
101
|
+
|
102
|
+
expect(req2.send(:request_options, {})[:basic_auth]).to_not be_nil
|
103
|
+
expect(req2.send(:request_options, {})[:basic_auth]).to eq({ username: creds.username, password: creds.password})
|
104
|
+
end
|
105
|
+
end
|
85
106
|
end
|
86
107
|
|
87
108
|
describe 'error handling' do
|
@@ -107,11 +128,7 @@ describe PensioAPI::Request do
|
|
107
128
|
|
108
129
|
context 'with incomplete credentials' do
|
109
130
|
before :each do
|
110
|
-
PensioAPI::Credentials =
|
111
|
-
base_uri: nil,
|
112
|
-
username: nil,
|
113
|
-
password: nil
|
114
|
-
})
|
131
|
+
PensioAPI::Credentials.base_uri = nil
|
115
132
|
end
|
116
133
|
|
117
134
|
it 'raises a PensioAPI::Errors::NoCredentials error' do
|
@@ -40,7 +40,7 @@ describe PensioAPI::Responses::Base do
|
|
40
40
|
context 'with a successful response' do
|
41
41
|
context 'with success specified in the response body' do
|
42
42
|
it 'returns true' do
|
43
|
-
expect(response_object.success?).to
|
43
|
+
expect(response_object.success?).to be true
|
44
44
|
end
|
45
45
|
end
|
46
46
|
|
@@ -60,7 +60,7 @@ describe PensioAPI::Responses::Base do
|
|
60
60
|
let(:response_object) { PensioAPI::Responses::Base.new(test_data) }
|
61
61
|
|
62
62
|
it 'returns true' do
|
63
|
-
expect(response_object.success?).to
|
63
|
+
expect(response_object.success?).to be true
|
64
64
|
end
|
65
65
|
end
|
66
66
|
end
|
@@ -16,7 +16,7 @@ describe PensioAPI::Responses::FundingList do
|
|
16
16
|
|
17
17
|
describe '.page_count' do
|
18
18
|
it 'returns a number of pages' do
|
19
|
-
expect(funding_list.page_count).to be_an_instance_of(
|
19
|
+
expect(funding_list.page_count).to be_an_instance_of(Integer)
|
20
20
|
end
|
21
21
|
end
|
22
22
|
end
|