nihaopay-ruby 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (43) hide show
  1. checksums.yaml +7 -0
  2. data/CHANGELOG.md +5 -0
  3. data/LICENSE +22 -0
  4. data/README.md +344 -0
  5. data/lib/nihaopay-ruby.rb +29 -0
  6. data/lib/nihaopay/configure.rb +14 -0
  7. data/lib/nihaopay/credit_card.rb +27 -0
  8. data/lib/nihaopay/errors.rb +6 -0
  9. data/lib/nihaopay/merchant.rb +47 -0
  10. data/lib/nihaopay/mixins/api.rb +41 -0
  11. data/lib/nihaopay/mixins/queryable.rb +41 -0
  12. data/lib/nihaopay/query.rb +61 -0
  13. data/lib/nihaopay/secure_pay/ali_pay.rb +11 -0
  14. data/lib/nihaopay/secure_pay/base.rb +48 -0
  15. data/lib/nihaopay/secure_pay/union_pay.rb +11 -0
  16. data/lib/nihaopay/secure_pay/we_chat_pay.rb +11 -0
  17. data/lib/nihaopay/transactions/authorize.rb +37 -0
  18. data/lib/nihaopay/transactions/base.rb +78 -0
  19. data/lib/nihaopay/transactions/cancel.rb +28 -0
  20. data/lib/nihaopay/transactions/capture.rb +29 -0
  21. data/lib/nihaopay/transactions/purchase.rb +11 -0
  22. data/lib/nihaopay/transactions/refund.rb +31 -0
  23. data/lib/nihaopay/transactions/release.rb +28 -0
  24. data/lib/nihaopay/util/hash_util.rb +30 -0
  25. data/lib/nihaopay/version.rb +3 -0
  26. data/spec/credit_card_spec.rb +56 -0
  27. data/spec/merchant_spec.rb +142 -0
  28. data/spec/mixins/api_spec.rb +81 -0
  29. data/spec/mixins/queryable_spec.rb +95 -0
  30. data/spec/query_spec.rb +129 -0
  31. data/spec/secure_pay/ali_pay_spec.rb +112 -0
  32. data/spec/secure_pay/union_pay_spec.rb +13 -0
  33. data/spec/secure_pay/we_chat_pay_spec.rb +13 -0
  34. data/spec/spec_helper.rb +7 -0
  35. data/spec/transactions/authorize_spec.rb +115 -0
  36. data/spec/transactions/base_spec.rb +184 -0
  37. data/spec/transactions/cancel_spec.rb +83 -0
  38. data/spec/transactions/capture_spec.rb +85 -0
  39. data/spec/transactions/purchase_spec.rb +7 -0
  40. data/spec/transactions/refund_spec.rb +98 -0
  41. data/spec/transactions/release_spec.rb +83 -0
  42. data/spec/util/hash_util_spec.rb +22 -0
  43. metadata +187 -0
@@ -0,0 +1,129 @@
1
+ require_relative 'spec_helper'
2
+
3
+ describe Nihaopay::Query do
4
+ before do
5
+ Nihaopay.test_mode = true
6
+ Nihaopay.token = token
7
+ end
8
+ let(:token) { '6c4dc4828474fa73c5f438a9eb2f' }
9
+ let(:q) { described_class.new }
10
+
11
+ describe '#limit' do
12
+ it 'should set @limit' do
13
+ q2 = q.limit(5)
14
+ expect(q2).to eq q
15
+ expect(q2.instance_variable_get(:@limit)).to eq 5
16
+ end
17
+ end
18
+
19
+ describe '#before' do
20
+ it 'should set @ending_before' do
21
+ q2 = q.before('2016-07-01T01:00:00Z')
22
+ expect(q2).to eq q
23
+ expect(q2.instance_variable_get(:@ending_before)).to eq '2016-07-01T01:00:00Z'
24
+ end
25
+ end
26
+
27
+ describe '#after' do
28
+ it 'should set @starting_after' do
29
+ q2 = q.after('2016-07-01T01:00:00Z')
30
+ expect(q2).to eq q
31
+ expect(q2.instance_variable_get(:@starting_after)).to eq '2016-07-01T01:00:00Z'
32
+ end
33
+ end
34
+
35
+ describe '#fetch' do
36
+ before { q.limit(5).before('2016-07-01T01:00:00Z').after('2016-06-01T01:00:00Z') }
37
+
38
+ context 'when options not passed' do
39
+ let(:expected_options) do
40
+ { limit: 5,
41
+ starting_after: '2016-06-01T01:00:00Z',
42
+ ending_before: '2016-07-01T01:00:00Z' }
43
+ end
44
+ it { expect(described_class).to receive(:fetch).with(expected_options) }
45
+ after { q.fetch }
46
+ end
47
+
48
+ context 'when options passed' do
49
+ let(:expected_options) { { limit: 3 } }
50
+ it { expect(described_class).to receive(:fetch).with(expected_options) }
51
+ after { q.fetch(limit: 3) }
52
+ end
53
+ end
54
+
55
+ describe '.fetch' do
56
+ before do
57
+ allow(response).to receive(:parsed_response) { parsed_response }
58
+ allow(HTTParty).to receive(:get) { response }
59
+ end
60
+ let(:response) { Object.new }
61
+ let(:parsed_response) do
62
+ { 'transactions' => [{ 'id' => '20160718111604002633', 'type' => 'charge', 'status' => 'success' },
63
+ { 'id' => '20160718111604002634', 'type' => 'charge', 'status' => 'failure' }] }
64
+ end
65
+ let(:url) { 'http://api.test.nihaopay.com/v1.1/transactions' }
66
+ let(:headers) { { 'Authorization' => "Bearer #{token}" } }
67
+
68
+ context 'when options not passed' do
69
+ it { expect(HTTParty).to receive(:get).with(url, headers: headers) }
70
+ after { described_class.fetch }
71
+ end
72
+
73
+ context 'when query present' do
74
+ let(:options) { { limit: 5, starting_after: '2016-07-01T01:00:00Z' } }
75
+ it { expect(HTTParty).to receive(:get).with(url, headers: headers, query: options) }
76
+ after { described_class.fetch(options) }
77
+ end
78
+
79
+ context 'with invalid options' do
80
+ let(:options) { { foo: :bar } }
81
+ it { expect(HTTParty).to receive(:get).with(url, headers: headers) }
82
+ after { described_class.fetch(options) }
83
+ end
84
+
85
+ context 'with blank values' do
86
+ let(:options) { { limit: nil, starting_after: '' } }
87
+ it { expect(HTTParty).to receive(:get).with(url, headers: headers) }
88
+ after { described_class.fetch(options) }
89
+ end
90
+
91
+ describe '.build_transactions' do
92
+ context 'when response does not contain :transactions' do
93
+ let(:parsed_response) do
94
+ { 'id' => '20160718111604002633', 'type' => 'charge', 'status' => 'success' }
95
+ end
96
+ it { expect { described_class.fetch }.to raise_error(Nihaopay::TransactionLookUpError) }
97
+ end
98
+
99
+ context 'when response contains :transactions' do
100
+ it 'should return collection of transaction objects' do
101
+ txns = described_class.fetch
102
+ expect(txns.size).to eq 2
103
+ expect(txns[0]).to be_a Nihaopay::Transactions::Base
104
+ expect(txns[0].transaction_id).to eq '20160718111604002633'
105
+ expect(txns[0].type).to eq 'charge'
106
+ expect(txns[0].status).to eq 'success'
107
+ expect(txns[1]).to be_a Nihaopay::Transactions::Base
108
+ expect(txns[1].transaction_id).to eq '20160718111604002634'
109
+ expect(txns[1].type).to eq 'charge'
110
+ expect(txns[1].status).to eq 'failure'
111
+ end
112
+ end
113
+ end
114
+ end
115
+
116
+ describe '.url' do
117
+ it { expect(described_class.url).to eq 'http://api.test.nihaopay.com/v1.1/transactions' }
118
+ end
119
+
120
+ describe '.request_headers' do
121
+ let(:expected_headers) { { 'Authorization' => "Bearer #{token}" } }
122
+ it { expect(described_class.request_headers).to eq expected_headers }
123
+ end
124
+
125
+ describe '.query_params' do
126
+ let(:options) { { limit: 5, starting_after: nil, foo: :bar } }
127
+ it { expect(described_class.query_params(options)).to eq(limit: 5) }
128
+ end
129
+ end
@@ -0,0 +1,112 @@
1
+ require_relative '../spec_helper'
2
+
3
+ describe Nihaopay::SecurePay::AliPay do
4
+ before do
5
+ Nihaopay.test_mode = true
6
+ Nihaopay.token = token
7
+ end
8
+ let(:token) { '6c4dc4828474fa73c5f438a9eb2f' }
9
+
10
+ describe '.vendor' do
11
+ it { expect(described_class.vendor).to eq :alipay }
12
+ end
13
+
14
+ describe '.start' do
15
+ let(:url) { 'http://api.test.nihaopay.com/v1.1/transactions/securepay' }
16
+ let(:headers) { { 'Authorization' => "Bearer #{token}" } }
17
+
18
+ context 'without options' do
19
+ let(:body) { 'amount=1000&currency=JPY&vendor=alipay&reference=&ipn_url=&callback_url=' }
20
+ let(:response) { OpenStruct.new(code: 200, body: '<html></html>') }
21
+ it { expect(HTTParty).to receive(:post).with(url, headers: headers, body: body) { response } }
22
+ after { described_class.start(1000, 'JPY') }
23
+ end
24
+
25
+ context 'with options' do
26
+ let(:options) do
27
+ { reference: '3461fcc31aec471780ad1a4dc6111947',
28
+ ipn_url: 'http://website.com/ipn',
29
+ callback_url: 'http://website.com/callback' }
30
+ end
31
+ let(:body) do
32
+ 'amount=1000'\
33
+ '&currency=JPY'\
34
+ '&vendor=alipay'\
35
+ '&reference=3461fcc31aec471780ad1a4dc61119'\
36
+ '&ipn_url=http://website.com/ipn'\
37
+ '&callback_url=http://website.com/callback'
38
+ end
39
+ let(:response) { OpenStruct.new(code: 200, body: '<html></html>') }
40
+ it { expect(HTTParty).to receive(:post).with(url, headers: headers, body: body) { response } }
41
+ after { described_class.start(1000, 'JPY', options) }
42
+ end
43
+
44
+ context 'with :token in options' do
45
+ let(:options) do
46
+ { token: '6c4dc4828474fa73c5f438a9eb2g',
47
+ reference: '3461fcc31aec471780ad1a4dc6111947',
48
+ ipn_url: 'http://website.com/ipn',
49
+ callback_url: 'http://website.com/callback' }
50
+ end
51
+ let(:headers) { { 'Authorization' => 'Bearer 6c4dc4828474fa73c5f438a9eb2g' } }
52
+ let(:body) do
53
+ 'amount=1000'\
54
+ '&currency=JPY'\
55
+ '&vendor=alipay'\
56
+ '&reference=3461fcc31aec471780ad1a4dc61119'\
57
+ '&ipn_url=http://website.com/ipn'\
58
+ '&callback_url=http://website.com/callback'
59
+ end
60
+ let(:response) { OpenStruct.new(code: 200, body: '<html></html>') }
61
+ it { expect(HTTParty).to receive(:post).with(url, headers: headers, body: body) { response } }
62
+ after do
63
+ described_class.start(1000, 'JPY', options)
64
+ described_class.instance_variable_set(:@token, nil)
65
+ end
66
+ end
67
+
68
+ context 'with failure response' do
69
+ let(:body) { 'amount=1000&currency=JPY&vendor=alipay&reference=&ipn_url=&callback_url=' }
70
+ let(:response) { OpenStruct.new(code: 401, body: '<html></html>', parsed_response: { message: 'Unauthorized' }) }
71
+ before { allow(HTTParty).to receive(:post) { response } }
72
+ it { expect { described_class.start(1000, 'JPY') }.to raise_error ::Nihaopay::SecurePayTransactionError }
73
+ end
74
+ end
75
+
76
+ describe '.request_url' do
77
+ let(:expected) { 'http://api.test.nihaopay.com/v1.1/transactions/securepay' }
78
+ it { expect(described_class.request_url).to eq expected }
79
+ end
80
+
81
+ describe '.request_headers' do
82
+ let(:expected) { { 'Authorization' => "Bearer #{token}" } }
83
+ it { expect(described_class.request_headers).to eq expected }
84
+ end
85
+
86
+ describe '.request_params' do
87
+ context 'when refrence more than 30 chars' do
88
+ let(:options) do
89
+ { reference: '3461fcc31aec471780ad1a4dc6111947',
90
+ ipn_url: 'http://website.com/ipn',
91
+ callback_url: 'http://website.com/callback' }
92
+ end
93
+ subject { described_class.request_params(1000, 'JPY', options) }
94
+ it { expect(subject[:reference]).to eq '3461fcc31aec471780ad1a4dc61119' }
95
+ end
96
+
97
+ context 'when options not in required format' do
98
+ let(:options) do
99
+ { reference: :a3461fcc,
100
+ ipn_url: 'http://website.com/ipn',
101
+ callback_url: 'http://website.com/callback' }
102
+ end
103
+ subject { described_class.request_params(1000.3, :JPY, options) }
104
+ it { expect(subject[:amount]).to eq 1000 }
105
+ it { expect(subject[:currency]).to eq 'JPY' }
106
+ it { expect(subject[:vendor]).to eq 'alipay' }
107
+ it { expect(subject[:reference]).to eq 'a3461fcc' }
108
+ it { expect(subject[:ipn_url]).to eq 'http://website.com/ipn' }
109
+ it { expect(subject[:callback_url]).to eq 'http://website.com/callback' }
110
+ end
111
+ end
112
+ end
@@ -0,0 +1,13 @@
1
+ require_relative '../spec_helper'
2
+
3
+ describe Nihaopay::SecurePay::UnionPay do
4
+ before do
5
+ Nihaopay.test_mode = true
6
+ Nihaopay.token = token
7
+ end
8
+ let(:token) { '6c4dc4828474fa' }
9
+
10
+ describe '.vendor' do
11
+ it { expect(described_class.vendor).to eq :unionpay }
12
+ end
13
+ end
@@ -0,0 +1,13 @@
1
+ require_relative '../spec_helper'
2
+
3
+ describe Nihaopay::SecurePay::WeChatPay do
4
+ before do
5
+ Nihaopay.test_mode = true
6
+ Nihaopay.token = token
7
+ end
8
+ let(:token) { '6c4dc4828474fa' }
9
+
10
+ describe '.vendor' do
11
+ it { expect(described_class.vendor).to eq :wechatpay }
12
+ end
13
+ end
@@ -0,0 +1,7 @@
1
+ require 'rubygems'
2
+ require 'bundler'
3
+ require 'nihaopay-ruby'
4
+
5
+ RSpec.configure do |config|
6
+ config.order = 'random'
7
+ end
@@ -0,0 +1,115 @@
1
+ require_relative '../spec_helper'
2
+
3
+ describe Nihaopay::Transactions::Authorize do
4
+ before do
5
+ Nihaopay.test_mode = true
6
+ Nihaopay.token = token
7
+ end
8
+ let(:token) { '6c4dc4828474f' }
9
+
10
+ describe '.start' do
11
+ before do
12
+ allow(response).to receive(:parsed_response) { parsed_response }
13
+ allow(HTTParty).to receive(:post) { response }
14
+ end
15
+ let(:cc_attrs) { { number: '6221558812340000', expiry_year: 17, expiry_month: 11, cvv: '123' } }
16
+ let(:cc) { Nihaopay::CreditCard.new(cc_attrs) }
17
+ let(:url) { 'http://api.test.nihaopay.com/v1.1/transactions/expresspay' }
18
+ let(:headers) do
19
+ { 'Authorization' => "Bearer #{token}",
20
+ 'Content-Type' => 'application/x-www-form-urlencoded' }
21
+ end
22
+ let(:response) { Object.new }
23
+ let(:parsed_response) do
24
+ { 'id' => '20160714132438002485',
25
+ 'status' => 'success',
26
+ 'reference' => '3461fcc31aec471780ad1a4dc6111947',
27
+ 'currency' => 'JPY',
28
+ 'amount' => 1000,
29
+ 'captured' => false }
30
+ end
31
+
32
+ context 'without options' do
33
+ let(:body) do
34
+ 'card_number=6221558812340000'\
35
+ '&card_exp_year=17'\
36
+ '&card_exp_month=11'\
37
+ '&card_cvv=123'\
38
+ '&capture=false'\
39
+ '&amount=1000'\
40
+ '&currency=USD'
41
+ end
42
+ it { expect(HTTParty).to receive(:post).with(url, headers: headers, body: body) }
43
+ after { described_class.start(1000, cc) }
44
+ end
45
+
46
+ context 'with options' do
47
+ let(:options) do
48
+ { currency: 'USD',
49
+ description: 'Lorem ipsum',
50
+ note: 'To self',
51
+ reference: '111111' }
52
+ end
53
+ let(:body) do
54
+ 'card_number=6221558812340000'\
55
+ '&card_exp_year=17'\
56
+ '&card_exp_month=11'\
57
+ '&card_cvv=123'\
58
+ '&currency=USD'\
59
+ '&description=Lorem ipsum'\
60
+ '&note=To self'\
61
+ '&reference=111111'\
62
+ '&capture=false'\
63
+ '&amount=1000'
64
+ end
65
+ it { expect(HTTParty).to receive(:post).with(url, headers: headers, body: body) }
66
+ after { described_class.start(1000, cc, options) }
67
+ end
68
+
69
+ context 'with invalid options' do
70
+ let(:options) { { foo: :bar } }
71
+ let(:body) do
72
+ 'card_number=6221558812340000'\
73
+ '&card_exp_year=17'\
74
+ '&card_exp_month=11'\
75
+ '&card_cvv=123'\
76
+ '&capture=false'\
77
+ '&amount=1000'\
78
+ '&currency=USD'
79
+ end
80
+ it { expect(HTTParty).to receive(:post).with(url, headers: headers, body: body) }
81
+ after { described_class.start(1000, cc, options) }
82
+ end
83
+
84
+ context 'with :token in options' do
85
+ let(:options) { { token: 'ec471780ad1' } }
86
+ let(:headers) do
87
+ { 'Authorization' => 'Bearer ec471780ad1',
88
+ 'Content-Type' => 'application/x-www-form-urlencoded' }
89
+ end
90
+ let(:body) do
91
+ 'card_number=6221558812340000'\
92
+ '&card_exp_year=17'\
93
+ '&card_exp_month=11'\
94
+ '&card_cvv=123'\
95
+ '&capture=false'\
96
+ '&amount=1000'\
97
+ '&currency=USD'
98
+ end
99
+ it { expect(HTTParty).to receive(:post).with(url, headers: headers, body: body) }
100
+ after do
101
+ described_class.start(1000, cc, options)
102
+ described_class.instance_variable_set(:@token, nil)
103
+ end
104
+ end
105
+
106
+ describe '.build_from_response!' do
107
+ it 'should return transaction object' do
108
+ txn = described_class.start(1000, cc)
109
+ expect(txn).to be_a Nihaopay::Transactions::Base
110
+ expect(txn.transaction_id).to eq '20160714132438002485'
111
+ expect(txn.status).to eq 'success'
112
+ end
113
+ end
114
+ end
115
+ end
@@ -0,0 +1,184 @@
1
+ require_relative '../spec_helper'
2
+
3
+ describe Nihaopay::Transactions::Base do
4
+ before do
5
+ Nihaopay.test_mode = true
6
+ Nihaopay.token = token
7
+ end
8
+ let(:token) { 'merchanttoken1' }
9
+ let(:txn_id) { '20160714132438002485' }
10
+ let(:attrs) do
11
+ { token: token,
12
+ transaction_id: txn_id,
13
+ type: 'charge',
14
+ status: 'success',
15
+ amount: 1000,
16
+ currency: 'JPY',
17
+ time: '2016-06-01T01:00:00Z',
18
+ reference: 'reference',
19
+ note: 'note-to-self' }
20
+ end
21
+ let(:base) { described_class.new(attrs) }
22
+
23
+ describe '.attr_accessor' do
24
+ subject { base }
25
+ it { is_expected.to respond_to :token= }
26
+ it { is_expected.to respond_to :token }
27
+ it { is_expected.to respond_to :transaction_id= }
28
+ it { is_expected.to respond_to :transaction_id }
29
+ it { is_expected.to respond_to :type= }
30
+ it { is_expected.to respond_to :type }
31
+ it { is_expected.to respond_to :status= }
32
+ it { is_expected.to respond_to :status }
33
+ it { is_expected.to respond_to :captured= }
34
+ it { is_expected.to respond_to :captured }
35
+ it { is_expected.to respond_to :reference= }
36
+ it { is_expected.to respond_to :reference }
37
+ it { is_expected.to respond_to :currency= }
38
+ it { is_expected.to respond_to :currency }
39
+ it { is_expected.to respond_to :amount= }
40
+ it { is_expected.to respond_to :amount }
41
+ it { is_expected.to respond_to :note= }
42
+ it { is_expected.to respond_to :note }
43
+ it { is_expected.to respond_to :time= }
44
+ it { is_expected.to respond_to :time }
45
+ end
46
+
47
+ describe '#initialize' do
48
+ context 'when attributes not passed' do
49
+ subject { described_class.new }
50
+ it { is_expected.to be_a Nihaopay::Transactions::Base }
51
+ end
52
+
53
+ context 'when attributes passed' do
54
+ subject { base }
55
+ it { is_expected.to be_a Nihaopay::Transactions::Base }
56
+ it { expect(subject.token).to eq token }
57
+ it { expect(subject.transaction_id).to eq txn_id }
58
+ it { expect(subject.type).to eq 'charge' }
59
+ it { expect(subject.status).to eq 'success' }
60
+ it { expect(subject.currency).to eq 'JPY' }
61
+ it { expect(subject.reference).to eq 'reference' }
62
+ it { expect(subject.amount).to eq 1000 }
63
+ it { expect(subject.note).to eq 'note-to-self' }
64
+ it { expect(subject.time).to eq '2016-06-01T01:00:00Z' }
65
+ end
66
+
67
+ context 'with invalid attributes' do
68
+ subject { described_class.new(foo: :bar) }
69
+ it { is_expected.to be_a Nihaopay::Transactions::Base }
70
+ end
71
+ end
72
+
73
+ describe '#capture' do
74
+ it { expect(Nihaopay::Transactions::Capture).to receive(:start).with(txn_id, 1000, 'JPY', token: token) }
75
+ after { base.capture }
76
+ end
77
+
78
+ describe '#partial_capture' do
79
+ it { expect(Nihaopay::Transactions::Capture).to receive(:start).with(txn_id, 500, 'JPY', token: token) }
80
+ after { base.partial_capture(500) }
81
+ end
82
+
83
+ describe '#release' do
84
+ it { expect(Nihaopay::Transactions::Release).to receive(:start).with(txn_id, token: token) }
85
+ after { base.release }
86
+ end
87
+
88
+ describe '#cancel' do
89
+ it { expect(Nihaopay::Transactions::Cancel).to receive(:start).with(txn_id, token: token) }
90
+ after { base.cancel }
91
+ end
92
+
93
+ describe '#refund' do
94
+ context 'without options' do
95
+ it { expect(Nihaopay::Transactions::Refund).to receive(:start).with(txn_id, 1000, 'JPY', token: token) }
96
+ after { base.refund }
97
+ end
98
+
99
+ context 'with options' do
100
+ let(:expected_opts) { { reason: 'out of stock', token: token } }
101
+ it { expect(Nihaopay::Transactions::Refund).to receive(:start).with(txn_id, 1000, 'JPY', expected_opts) }
102
+ after { base.refund(reason: 'out of stock') }
103
+ end
104
+ end
105
+
106
+ describe '#partial_refund' do
107
+ context 'without options' do
108
+ it { expect(Nihaopay::Transactions::Refund).to receive(:start).with(txn_id, 500, 'JPY', token: token) }
109
+ after { base.partial_refund(500) }
110
+ end
111
+
112
+ context 'with options' do
113
+ let(:expected_opts) { { reason: 'out of stock', token: token } }
114
+ it { expect(Nihaopay::Transactions::Refund).to receive(:start).with(txn_id, 500, 'JPY', expected_opts) }
115
+ after { base.partial_refund(500, reason: 'out of stock') }
116
+ end
117
+ end
118
+
119
+ describe '.request_headers' do
120
+ let(:expectation) do
121
+ { 'Authorization' => "Bearer #{token}",
122
+ 'Content-Type' => 'application/x-www-form-urlencoded' }
123
+ end
124
+ it { expect(described_class.request_headers).to eq expectation }
125
+ end
126
+
127
+ describe '.build' do
128
+ context 'when options not passed' do
129
+ subject { described_class.build }
130
+ it { is_expected.to be_a Nihaopay::Transactions::Base }
131
+ it { expect(subject.token).to eq token }
132
+ end
133
+
134
+ context 'with options' do
135
+ let(:options) do
136
+ opts = attrs.merge(id: '123456', token: 'merchanttoken2', captured: true)
137
+ opts.delete(:transaction_id)
138
+ opts
139
+ end
140
+ subject { described_class.build(options) }
141
+ it { is_expected.to be_a Nihaopay::Transactions::Base }
142
+ it { expect(subject.transaction_id).to eq '123456' }
143
+ it { expect(subject.token).to eq 'merchanttoken2' }
144
+ it { expect(subject.captured).to be true }
145
+ end
146
+
147
+ context 'with options with string keys' do
148
+ let(:options) do
149
+ opts = Nihaopay::HashUtil.stringify_keys(attrs)
150
+ opts['id'] = '123456'
151
+ opts.delete('transaction_id')
152
+ opts
153
+ end
154
+ subject { described_class.build(options) }
155
+ it { is_expected.to be_a Nihaopay::Transactions::Base }
156
+ it { expect(subject.transaction_id).to eq '123456' }
157
+ end
158
+
159
+ context 'without token' do
160
+ let(:options) do
161
+ opts = attrs
162
+ opts[:id] = '123456'
163
+ opts.delete(:transaction_id)
164
+ opts.delete(:token)
165
+ opts
166
+ end
167
+ subject { described_class.build(options) }
168
+ it { is_expected.to be_a Nihaopay::Transactions::Base }
169
+ it { expect(subject.token).to eq 'merchanttoken1' }
170
+ end
171
+ end
172
+
173
+ describe '.valid_attributes' do
174
+ let(:expectation) do
175
+ %i(token transaction_id type status captured currency reference amount note time)
176
+ end
177
+ it { expect(described_class.valid_attributes).to eq expectation }
178
+ end
179
+
180
+ describe '.response_keys_map' do
181
+ let(:expectation) { { id: :transaction_id } }
182
+ it { expect(described_class.response_keys_map).to eq expectation }
183
+ end
184
+ end