money_mover 0.0.3
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +1 -0
- data/.rspec +2 -0
- data/Gemfile +17 -0
- data/Gemfile.lock +80 -0
- data/lib/money_mover/dwolla/account_client.rb +9 -0
- data/lib/money_mover/dwolla/account_token.rb +24 -0
- data/lib/money_mover/dwolla/api_connection.rb +18 -0
- data/lib/money_mover/dwolla/api_server_response.rb +31 -0
- data/lib/money_mover/dwolla/application_client.rb +9 -0
- data/lib/money_mover/dwolla/application_token.rb +25 -0
- data/lib/money_mover/dwolla/client.rb +24 -0
- data/lib/money_mover/dwolla/config.rb +33 -0
- data/lib/money_mover/dwolla/environment_urls.rb +35 -0
- data/lib/money_mover/dwolla/error_handler.rb +30 -0
- data/lib/money_mover/dwolla/models/account_funding_source.rb +28 -0
- data/lib/money_mover/dwolla/models/api_resource.rb +70 -0
- data/lib/money_mover/dwolla/models/customer.rb +53 -0
- data/lib/money_mover/dwolla/models/document.rb +22 -0
- data/lib/money_mover/dwolla/models/funding_source.rb +30 -0
- data/lib/money_mover/dwolla/models/micro_deposit_initiation.rb +19 -0
- data/lib/money_mover/dwolla/models/micro_deposit_verification.rb +31 -0
- data/lib/money_mover/dwolla/models/receive_only_business_customer.rb +27 -0
- data/lib/money_mover/dwolla/models/receive_only_customer.rb +19 -0
- data/lib/money_mover/dwolla/models/root_account.rb +27 -0
- data/lib/money_mover/dwolla/models/transfer.rb +33 -0
- data/lib/money_mover/dwolla/models/unverified_business_customer.rb +43 -0
- data/lib/money_mover/dwolla/models/unverified_customer.rb +27 -0
- data/lib/money_mover/dwolla/models/verified_business_customer.rb +53 -0
- data/lib/money_mover/dwolla/models/webhook_subscription.rb +36 -0
- data/lib/money_mover/dwolla/token.rb +26 -0
- data/lib/money_mover/dwolla.rb +44 -0
- data/lib/money_mover/standalone_errors.rb +12 -0
- data/lib/money_mover/version.rb +3 -0
- data/lib/money_mover.rb +15 -0
- data/money_mover.gemspec +27 -0
- data/spec/integration/money_mover/dwolla/customers/create_spec.rb +75 -0
- data/spec/integration/money_mover/dwolla/customers/find_spec.rb +71 -0
- data/spec/integration/money_mover/dwolla/customers/funding-sources/create_spec.rb +40 -0
- data/spec/integration/money_mover/dwolla/documents/create_spec.rb +62 -0
- data/spec/integration/money_mover/dwolla/funding-sources/micro-deposits/initiation_spec.rb +52 -0
- data/spec/integration/money_mover/dwolla/funding-sources/micro-deposits/verification_spec.rb +77 -0
- data/spec/integration/money_mover/dwolla/transfers/create_spec.rb +80 -0
- data/spec/lib/money_mover/dwolla/client_spec.rb +101 -0
- data/spec/lib/money_mover/dwolla/config_spec.rb +20 -0
- data/spec/lib/money_mover/dwolla/error_handler_spec.rb +78 -0
- data/spec/lib/money_mover/dwolla/funding_source_spec.rb +94 -0
- data/spec/lib/money_mover/dwolla/microdeposits_initiation_spec.rb +36 -0
- data/spec/lib/money_mover/dwolla/root_account_spec.rb +86 -0
- data/spec/lib/money_mover/dwolla/token_spec.rb +101 -0
- data/spec/lib/money_mover/dwolla/transfer_spec.rb +94 -0
- data/spec/lib/money_mover/dwolla/webhook_subscription_spec.rb +199 -0
- data/spec/spec_helper.rb +121 -0
- data/spec/support/dwolla_helper.rb +330 -0
- data/spec/support/fixtures/sample.jpg +0 -0
- metadata +196 -0
@@ -0,0 +1,77 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe MoneyMover::Dwolla::MicroDepositVerification do
|
4
|
+
let(:funding_source_token) { '9481924a-6795-4e7a-b436-a7a48a4141ca' }
|
5
|
+
|
6
|
+
describe '#save' do
|
7
|
+
context 'valid attributes' do
|
8
|
+
let(:amount1) { 0.01 }
|
9
|
+
let(:amount2) { 0.02 }
|
10
|
+
|
11
|
+
let(:attrs) {{
|
12
|
+
funding_source_id: funding_source_token,
|
13
|
+
amount1: amount1,
|
14
|
+
amount2: amount2
|
15
|
+
}}
|
16
|
+
|
17
|
+
subject { described_class.new(attrs) }
|
18
|
+
|
19
|
+
let(:create_params) {{
|
20
|
+
amount1: {
|
21
|
+
value: amount1,
|
22
|
+
currency: "USD"
|
23
|
+
},
|
24
|
+
amount2: {
|
25
|
+
value: amount2,
|
26
|
+
currency: "USD"
|
27
|
+
}
|
28
|
+
}}
|
29
|
+
|
30
|
+
before do
|
31
|
+
dwolla_helper.stub_funding_source_microdeposits_request funding_source_token, create_params, create_response
|
32
|
+
end
|
33
|
+
|
34
|
+
context 'success' do
|
35
|
+
let(:create_response) {{
|
36
|
+
status: 200,
|
37
|
+
body: ""
|
38
|
+
}}
|
39
|
+
|
40
|
+
it 'creates new resource in dwolla' do
|
41
|
+
expect(subject.save).to eq(true)
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
context 'fail' do
|
46
|
+
let(:create_response) { dwolla_helper.resource_create_error_response error_response }
|
47
|
+
|
48
|
+
let(:error_response) {{
|
49
|
+
code: "ValidationError",
|
50
|
+
message: "Validation error(s) present. See embedded errors list for more details.",
|
51
|
+
_embedded: {
|
52
|
+
errors: [
|
53
|
+
{ code: "Invalid", message: "Invalid amount.", path: "/amount1/value" },
|
54
|
+
{ code: "Invalid", message: "Invalid amount.", path: "/amount2/value" }
|
55
|
+
]
|
56
|
+
}
|
57
|
+
}}
|
58
|
+
|
59
|
+
it 'returns errors' do
|
60
|
+
expect(subject.save).to eq(false)
|
61
|
+
expect(subject.errors[:amount1]).to eq(['Invalid amount.'])
|
62
|
+
expect(subject.errors[:amount2]).to eq(['Invalid amount.'])
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
context 'invalid attributes' do
|
68
|
+
let(:attrs) {{}}
|
69
|
+
|
70
|
+
it 'returns errors' do
|
71
|
+
expect(subject.save).to eq(false)
|
72
|
+
expect(subject.errors[:amount1]).to eq(["can't be blank", "is not a number"])
|
73
|
+
expect(subject.errors[:amount2]).to eq(["can't be blank", "is not a number"])
|
74
|
+
end
|
75
|
+
end
|
76
|
+
end
|
77
|
+
end
|
@@ -0,0 +1,80 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe MoneyMover::Dwolla::Transfer do
|
4
|
+
let(:funding_source_resource_location) { 'some-resource-location' }
|
5
|
+
let(:funding_destination_resource_location) { 'some-resource-location' }
|
6
|
+
let(:amount) { 10.0 }
|
7
|
+
let(:metadata) {{}}
|
8
|
+
|
9
|
+
#let(:attrs) {{
|
10
|
+
#funding_source_resource_location: funding_source_resource_location,
|
11
|
+
#funding_destination_resource_location: funding_destination_resource_location,
|
12
|
+
#amount: amount,
|
13
|
+
#metadata: metadata
|
14
|
+
#}}
|
15
|
+
|
16
|
+
let(:attrs) {{
|
17
|
+
sender_funding_source_token: funding_source_resource_location,
|
18
|
+
destination_funding_source_token: funding_destination_resource_location,
|
19
|
+
transfer_amount: amount,
|
20
|
+
metadata: metadata
|
21
|
+
}}
|
22
|
+
|
23
|
+
subject { described_class.new(attrs) }
|
24
|
+
|
25
|
+
let(:create_params) {{
|
26
|
+
_links: {
|
27
|
+
destination: {
|
28
|
+
href: dwolla_helper.build_dwolla_url("funding-sources/#{funding_source_resource_location}")
|
29
|
+
},
|
30
|
+
source: {
|
31
|
+
href: dwolla_helper.build_dwolla_url("funding-sources/#{funding_destination_resource_location}")
|
32
|
+
}
|
33
|
+
},
|
34
|
+
amount: {
|
35
|
+
value: amount.to_s,
|
36
|
+
currency: "USD"
|
37
|
+
},
|
38
|
+
metadata: metadata
|
39
|
+
}}
|
40
|
+
|
41
|
+
let(:resource_token) { 'some-token' }
|
42
|
+
|
43
|
+
before do
|
44
|
+
dwolla_helper.stub_create_transfer_request create_params, create_response
|
45
|
+
end
|
46
|
+
|
47
|
+
describe '#save' do
|
48
|
+
context 'success' do
|
49
|
+
let(:create_response) { dwolla_helper.transfer_created_response resource_token }
|
50
|
+
|
51
|
+
it 'creates new resource in dwolla' do
|
52
|
+
expect(subject.save).to eq(true)
|
53
|
+
expect(subject.id).to eq(resource_token)
|
54
|
+
expect(subject.resource_location).to eq(dwolla_helper.transfer_endpoint(resource_token))
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
context 'fail' do
|
59
|
+
let(:create_response) { dwolla_helper.resource_create_error_response error_response }
|
60
|
+
|
61
|
+
let(:error_response) {{
|
62
|
+
code: "ValidationError",
|
63
|
+
message: "Validation error(s) present. See embedded errors list for more details.",
|
64
|
+
_embedded: {
|
65
|
+
errors: [
|
66
|
+
{ code: "Duplicate", message: "Invalid destination", path: "/_links/destination/href"
|
67
|
+
}
|
68
|
+
]
|
69
|
+
}
|
70
|
+
}}
|
71
|
+
|
72
|
+
it 'returns errors' do
|
73
|
+
expect(subject.save).to eq(false)
|
74
|
+
expect(subject.errors[:_links]).to eq(['Invalid destination'])
|
75
|
+
expect(subject.id).to be_nil
|
76
|
+
expect(subject.resource_location).to be_nil
|
77
|
+
end
|
78
|
+
end
|
79
|
+
end
|
80
|
+
end
|
@@ -0,0 +1,101 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe MoneyMover::Dwolla::AccountClient do
|
4
|
+
let(:expected_response) { double 'expected response' }
|
5
|
+
let(:server_request) { double 'server request' }
|
6
|
+
|
7
|
+
let(:url_provider) { double 'url provider', api_url: api_url }
|
8
|
+
let(:api_url) { double' api url' }
|
9
|
+
|
10
|
+
subject { described_class.new }
|
11
|
+
|
12
|
+
let(:token) { double 'account token' }
|
13
|
+
let(:dwolla_token_provider) { double 'token provider', access_token: token }
|
14
|
+
|
15
|
+
let(:api_connection) { double 'api connection', connection: faraday_connection }
|
16
|
+
let(:faraday_connection) { double 'faraday connection' }
|
17
|
+
|
18
|
+
before do
|
19
|
+
allow(MoneyMover::Dwolla::ApiConnection).to receive(:new).with(token) { api_connection }
|
20
|
+
allow(MoneyMover::Dwolla::AccountToken).to receive(:new) { dwolla_token_provider }
|
21
|
+
end
|
22
|
+
|
23
|
+
let(:url) { double 'url' }
|
24
|
+
let(:params) { double 'params' }
|
25
|
+
|
26
|
+
describe '#post' do
|
27
|
+
let(:expected_response) { double 'expected response' }
|
28
|
+
let(:server_request) { double 'server request', response: expected_response }
|
29
|
+
|
30
|
+
before do
|
31
|
+
allow(faraday_connection).to receive(:post).with(url, params) { server_request }
|
32
|
+
allow(MoneyMover::Dwolla::ApiServerResponse).to receive(:new).with(server_request) { expected_response }
|
33
|
+
end
|
34
|
+
|
35
|
+
it 'returns success response' do
|
36
|
+
expect(subject.post(url, params)).to eq(expected_response)
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
describe '#delete' do
|
41
|
+
before do
|
42
|
+
allow(faraday_connection).to receive(:delete).with(url, params) { server_request }
|
43
|
+
allow(MoneyMover::Dwolla::ApiServerResponse).to receive(:new).with(server_request) { expected_response }
|
44
|
+
end
|
45
|
+
|
46
|
+
it 'returns SuccessResponse' do
|
47
|
+
expect(subject.delete(url, params)).to eq(expected_response)
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
describe '#get' do
|
52
|
+
before do
|
53
|
+
allow(faraday_connection).to receive(:get).with(url, params) { server_request }
|
54
|
+
allow(MoneyMover::Dwolla::ApiServerResponse).to receive(:new).with(server_request) { expected_response }
|
55
|
+
end
|
56
|
+
|
57
|
+
it 'returns response from token#get' do
|
58
|
+
expect(subject.get(url, params)).to eq(expected_response)
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
describe MoneyMover::Dwolla::AccountClient do
|
64
|
+
describe '#post' do
|
65
|
+
let(:url) { '/customers' }
|
66
|
+
|
67
|
+
let(:params) {{
|
68
|
+
firstName: 'someone first name',
|
69
|
+
lastName: 'someone last name',
|
70
|
+
email: 'email@example.com',
|
71
|
+
businessName: 'some company name',
|
72
|
+
type: 'receive-only'
|
73
|
+
}}
|
74
|
+
|
75
|
+
before do
|
76
|
+
dwolla_helper.stub_create_customer_request(params, create_response)
|
77
|
+
end
|
78
|
+
|
79
|
+
context 'success' do
|
80
|
+
let(:create_response) { dwolla_helper.create_customer_success_response(customer_token) }
|
81
|
+
let(:customer_token) { 'some-customer-token' }
|
82
|
+
|
83
|
+
it 'returns success response' do
|
84
|
+
response = subject.post(url, params)
|
85
|
+
expect(response.resource_id).to eq(customer_token)
|
86
|
+
expect(response.resource_location).to eq(dwolla_helper.customer_url(customer_token))
|
87
|
+
end
|
88
|
+
end
|
89
|
+
|
90
|
+
context 'error' do
|
91
|
+
let(:create_response) {
|
92
|
+
dwolla_helper.error_response :code=>"ValidationError", :message=>"Validation error(s) present. See embedded errors list for more details.", :_embedded=>{:errors=>[{:code=>"Duplicate", :message=>"A customer with the specified email already exists.", :path=>"/email"}]}
|
93
|
+
}
|
94
|
+
|
95
|
+
it 'returns error response' do
|
96
|
+
response = subject.post(url, params)
|
97
|
+
expect(response.errors[:email]).to eq(['A customer with the specified email already exists.'])
|
98
|
+
end
|
99
|
+
end
|
100
|
+
end
|
101
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe MoneyMover::Dwolla::Config do
|
4
|
+
let(:webhook_secret_key) { double 'webhook secret key' }
|
5
|
+
let(:webhook_callback_url) { double 'webhook callback url' }
|
6
|
+
let(:api_key) { double 'api key' }
|
7
|
+
let(:api_secret_key) { double 'api secret key' }
|
8
|
+
let(:environment) { double 'environment' }
|
9
|
+
let(:ach_provider_config) { double 'configatron ach provider store', webhook_secret_key: webhook_secret_key, webhook_callback_url: webhook_callback_url, api_key: api_key, api_secret_key: api_secret_key, environment: environment }
|
10
|
+
|
11
|
+
subject { described_class.new(ach_provider_config) }
|
12
|
+
|
13
|
+
it 'returns expected values' do
|
14
|
+
expect(subject.webhook_secret_key).to eq(webhook_secret_key)
|
15
|
+
expect(subject.webhook_callback_url).to eq(webhook_callback_url)
|
16
|
+
expect(subject.api_key).to eq(api_key)
|
17
|
+
expect(subject.api_secret_key).to eq(api_secret_key)
|
18
|
+
expect(subject.environment).to eq(environment)
|
19
|
+
end
|
20
|
+
end
|
@@ -0,0 +1,78 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe MoneyMover::Dwolla::ErrorHandler do
|
4
|
+
subject { described_class.new(server_error) }
|
5
|
+
|
6
|
+
describe '#errors' do
|
7
|
+
context 'no embedded errors' do
|
8
|
+
let(:server_error) {{
|
9
|
+
code: "DuplicateResource",
|
10
|
+
message: "Bank already exists: id=442efd3e-3f70-4cb1-a393-593dca3464b4",
|
11
|
+
_embedded: nil
|
12
|
+
}}
|
13
|
+
|
14
|
+
it 'sets error correctly' do
|
15
|
+
expect(subject.errors[:base]).to eq(["Bank already exists: id=442efd3e-3f70-4cb1-a393-593dca3464b4"])
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
context 'json pointer path is /routingNumber' do
|
20
|
+
let(:server_error) {{
|
21
|
+
code: "ValidationError",
|
22
|
+
message: "Validation error(s) present. See embedded errors list for more details.",
|
23
|
+
_embedded: {
|
24
|
+
errors: [
|
25
|
+
{
|
26
|
+
:code=>"Invalid",
|
27
|
+
:message=>"Invalid parameter.",
|
28
|
+
:path=>"/routingNumber"
|
29
|
+
}
|
30
|
+
]
|
31
|
+
}
|
32
|
+
}}
|
33
|
+
|
34
|
+
it 'sets error correctly' do
|
35
|
+
expect(subject.errors[:routingNumber]).to eq(["Invalid parameter."])
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
context 'json pointer path is /amount2/value' do
|
40
|
+
let(:server_error) {{
|
41
|
+
code: "ValidationError",
|
42
|
+
message: "Validation error(s) present. See embedded errors list for more details.",
|
43
|
+
_embedded: {
|
44
|
+
errors: [
|
45
|
+
{
|
46
|
+
code: "Invalid",
|
47
|
+
message: "Invalid amount.",
|
48
|
+
path: "/amount2/value"
|
49
|
+
}
|
50
|
+
]
|
51
|
+
}
|
52
|
+
}}
|
53
|
+
|
54
|
+
it 'sets error correctly' do
|
55
|
+
expect(subject.errors[:amount2]).to eq(["Invalid amount."])
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
context 'json pointer path is empty' do
|
60
|
+
let(:server_error) {{
|
61
|
+
code: "ValidationError",
|
62
|
+
message: "Validation error(s) present. See embedded errors list for more details.",
|
63
|
+
_embedded: {
|
64
|
+
errors: [
|
65
|
+
{
|
66
|
+
code: "Invalid",
|
67
|
+
message: "Invalid amount."
|
68
|
+
}
|
69
|
+
]
|
70
|
+
}
|
71
|
+
}}
|
72
|
+
|
73
|
+
it 'sets error correctly' do
|
74
|
+
expect(subject.errors[:base]).to eq(["Invalid amount."])
|
75
|
+
end
|
76
|
+
end
|
77
|
+
end
|
78
|
+
end
|
@@ -0,0 +1,94 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe MoneyMover::Dwolla::FundingSource do
|
4
|
+
let(:customer_id) { double 'customer id' }
|
5
|
+
|
6
|
+
let(:name) { 'some name' }
|
7
|
+
let(:type) { 'checking' }
|
8
|
+
let(:routingNumber) { 'routing number' }
|
9
|
+
let(:accountNumber) { 'account number' }
|
10
|
+
|
11
|
+
let(:attrs) {{
|
12
|
+
name: name,
|
13
|
+
type: type,
|
14
|
+
routingNumber: routingNumber,
|
15
|
+
accountNumber: accountNumber
|
16
|
+
}}
|
17
|
+
|
18
|
+
subject { described_class.new customer_id, attrs }
|
19
|
+
|
20
|
+
let(:dwolla_client) { double 'dwolla client' }
|
21
|
+
|
22
|
+
let(:dwolla_response) { double 'dwolla response', success?: save_success?, resource_location: resource_location, resource_id: resource_id, errors: dwolla_errors }
|
23
|
+
let(:dwolla_errors) { [ ['key1', 'error1'], ['key2', 'error2'] ] }
|
24
|
+
|
25
|
+
let(:resource_location) { double 'resource location' }
|
26
|
+
let(:resource_id) { double 'resource id' }
|
27
|
+
|
28
|
+
before do
|
29
|
+
allow(MoneyMover::Dwolla::AccountClient).to receive(:new) { dwolla_client }
|
30
|
+
end
|
31
|
+
|
32
|
+
it { should validate_presence_of(:name) }
|
33
|
+
it { should validate_presence_of(:type) }
|
34
|
+
it { should validate_presence_of(:routingNumber) }
|
35
|
+
it { should validate_presence_of(:accountNumber) }
|
36
|
+
|
37
|
+
describe '#save' do
|
38
|
+
let(:save_success?) { true }
|
39
|
+
|
40
|
+
let(:create_params) {{
|
41
|
+
name: name,
|
42
|
+
type: type,
|
43
|
+
routingNumber: routingNumber,
|
44
|
+
accountNumber: accountNumber
|
45
|
+
}}
|
46
|
+
|
47
|
+
let(:create_endpoint) { "/customers/#{customer_id}/funding-sources" }
|
48
|
+
|
49
|
+
context 'success' do
|
50
|
+
let(:save_success?) { true }
|
51
|
+
|
52
|
+
it 'returns true and sets resource_location and id' do
|
53
|
+
expect(dwolla_client).to receive(:post).with(create_endpoint, create_params) { dwolla_response }
|
54
|
+
|
55
|
+
expect(subject.save).to eq(true)
|
56
|
+
|
57
|
+
expect(subject.errors).to be_empty
|
58
|
+
expect(subject.resource_location).to eq(resource_location)
|
59
|
+
expect(subject.id).to eq(resource_id)
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
context 'validations fail' do
|
64
|
+
let(:name) { nil }
|
65
|
+
let(:type) { nil }
|
66
|
+
let(:routingNumber) { nil }
|
67
|
+
let(:accountNumber) { nil }
|
68
|
+
|
69
|
+
it 'does not attempt to create transfer and returns false with errors' do
|
70
|
+
expect(dwolla_client).to_not receive(:post)
|
71
|
+
|
72
|
+
expect(subject.save).to eq(false)
|
73
|
+
|
74
|
+
expect(subject.errors[:name]).to eq(["can't be blank"])
|
75
|
+
expect(subject.errors[:type]).to eq(["can't be blank", "is not included in the list"])
|
76
|
+
expect(subject.errors[:routingNumber]).to eq(["can't be blank"])
|
77
|
+
expect(subject.errors[:accountNumber]).to eq(["can't be blank"])
|
78
|
+
end
|
79
|
+
end
|
80
|
+
|
81
|
+
context 'dwolla error' do
|
82
|
+
let(:save_success?) { false }
|
83
|
+
|
84
|
+
it 'returns false and has errors' do
|
85
|
+
expect(dwolla_client).to receive(:post).with(create_endpoint, create_params) { dwolla_response }
|
86
|
+
|
87
|
+
expect(subject.save).to eq(false)
|
88
|
+
|
89
|
+
expect(subject.errors[:key1]).to eq(['error1'])
|
90
|
+
expect(subject.errors[:key2]).to eq(['error2'])
|
91
|
+
end
|
92
|
+
end
|
93
|
+
end
|
94
|
+
end
|
@@ -0,0 +1,36 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe MoneyMover::Dwolla::MicroDepositInitiation do
|
4
|
+
let(:response_errors) { { key1: 'Error1', key2: 'Error2' } }
|
5
|
+
let(:ach_response) { double 'ach response', success?: response_success?, resource_location: resource_location, resource_id: resource_id, errors: response_errors}
|
6
|
+
let(:resource_location) { double 'resource location' }
|
7
|
+
let(:resource_id) { double 'resource id' }
|
8
|
+
let(:ach_client) { double 'Dwolla Client', post: ach_response }
|
9
|
+
|
10
|
+
let(:funding_source_id) { 'some_funding_source_id_token' }
|
11
|
+
|
12
|
+
subject { described_class.new(funding_source_id: funding_source_id) }
|
13
|
+
|
14
|
+
before do
|
15
|
+
allow(MoneyMover::Dwolla::AccountClient).to receive(:new) { ach_client }
|
16
|
+
end
|
17
|
+
|
18
|
+
context 'success' do
|
19
|
+
let(:response_success?) { true }
|
20
|
+
|
21
|
+
it 'posts to ach provider and returns true' do
|
22
|
+
expect(ach_client).to receive(:post).with("/funding-sources/#{funding_source_id}/micro-deposits", {})
|
23
|
+
expect(subject.save).to eq(true)
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
context 'ach failure' do
|
28
|
+
let(:response_success?) { false }
|
29
|
+
|
30
|
+
it 'posts to ach provider and returns false and has errors' do
|
31
|
+
expect(ach_client).to receive(:post).with("/funding-sources/#{funding_source_id}/micro-deposits", {})
|
32
|
+
expect(subject.save).to eq(false)
|
33
|
+
expect(subject.errors.to_a).to eq(["Key1 Error1", "Key2 Error2"])
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
@@ -0,0 +1,86 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe MoneyMover::Dwolla::RootAccount do
|
4
|
+
let(:client) { double 'dwolla account client' }
|
5
|
+
let(:account_token) { "account_token_value" }
|
6
|
+
let(:bank_funding_source_token) { "bank_funding_source_token_value" }
|
7
|
+
|
8
|
+
let(:account_response) { double 'account response', success?: account_success?, body: account_response_body }
|
9
|
+
let(:account_success?) { true }
|
10
|
+
|
11
|
+
let(:account_response_body) do
|
12
|
+
{
|
13
|
+
:_links=>{
|
14
|
+
:account=>{
|
15
|
+
:href=>"https://api-uat.dwolla.com/accounts/#{account_token}"
|
16
|
+
},
|
17
|
+
:customers=>{:href=>"https://api-uat.dwolla.com/customers"}
|
18
|
+
}
|
19
|
+
}
|
20
|
+
end
|
21
|
+
|
22
|
+
let(:funding_response) { double 'funding response', body: funding_response_body }
|
23
|
+
|
24
|
+
let(:funding_response_body) do
|
25
|
+
{
|
26
|
+
:_links=>{
|
27
|
+
:self=>{
|
28
|
+
:href=>"https://api-uat.dwolla.com/accounts/#{account_token}/funding-sources"
|
29
|
+
}
|
30
|
+
},
|
31
|
+
:_embedded=>{
|
32
|
+
:"funding-sources"=>[
|
33
|
+
{
|
34
|
+
:_links=>{
|
35
|
+
:self=>{
|
36
|
+
:href=>"https://api-uat.dwolla.com/funding-sources/#{bank_funding_source_token}"
|
37
|
+
},
|
38
|
+
:account=>{
|
39
|
+
:href=>"https://api-uat.dwolla.com/accounts/#{account_token}"
|
40
|
+
}
|
41
|
+
},
|
42
|
+
:id=>bank_funding_source_token,
|
43
|
+
:status=>"verified",
|
44
|
+
:type=>"bank",
|
45
|
+
:name=>"Superhero Savings Bank",
|
46
|
+
:created=>'2016-03-08 17:43:43 UTC'
|
47
|
+
},
|
48
|
+
{
|
49
|
+
:_links=>{
|
50
|
+
:self=>{
|
51
|
+
:href=>"https://api-uat.dwolla.com/funding-sources/90fa0eff-8ea0-4cab-89eb-72a1f5d93c13"
|
52
|
+
},
|
53
|
+
:account=>{
|
54
|
+
:href=>"https://api-uat.dwolla.com/accounts/#{account_token}"
|
55
|
+
},
|
56
|
+
:"with-available-balance"=>{
|
57
|
+
:href=>"https://api-uat.dwolla.com/funding-sources/90fa0eff-8ea0-4cab-89eb-72a1f5d93c13"
|
58
|
+
}
|
59
|
+
},
|
60
|
+
:id=>"90fa0eff-8ea0-4cab-89eb-72a1f5d93c13",
|
61
|
+
:status=>"verified",
|
62
|
+
:type=>"balance",
|
63
|
+
:name=>"Balance",
|
64
|
+
:created=>'2016-03-08 17:43:42 UTC'
|
65
|
+
}
|
66
|
+
]
|
67
|
+
}
|
68
|
+
}
|
69
|
+
end
|
70
|
+
|
71
|
+
before do
|
72
|
+
allow(MoneyMover::Dwolla::AccountClient).to receive(:new) { client }
|
73
|
+
allow(client).to receive(:get).with('/') { account_response }
|
74
|
+
allow(client).to receive(:get).with("/accounts/#{account_token}/funding-sources") { funding_response }
|
75
|
+
end
|
76
|
+
|
77
|
+
describe '.fetch' do
|
78
|
+
subject { described_class }
|
79
|
+
|
80
|
+
it 'returns expected token hash' do
|
81
|
+
account = subject.fetch
|
82
|
+
expect(account.account_resource_id).to eq(account_token)
|
83
|
+
expect(account.bank_account_funding_source.id).to eq(bank_funding_source_token)
|
84
|
+
end
|
85
|
+
end
|
86
|
+
end
|
@@ -0,0 +1,101 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe MoneyMover::Dwolla::AccountToken do
|
4
|
+
let(:ach_config) { double 'ach config', api_key: ach_config_api_key, api_secret_key: ach_config_api_secret_key, environment: ach_config_environment, account_token_provider: account_token_provider }
|
5
|
+
let(:ach_config_api_key) { double 'ach config api key' }
|
6
|
+
let(:ach_config_api_secret_key) { double 'ach config api secret' }
|
7
|
+
let(:ach_config_environment) { double 'ach config environment' }
|
8
|
+
let(:account_token_provider) { double 'account token provider', access_token: account_access_token, refresh_token: account_refresh_token }
|
9
|
+
let(:account_access_token) { double 'account access token' }
|
10
|
+
let(:account_refresh_token) { double 'account refresh token' }
|
11
|
+
|
12
|
+
let(:attrs) {{}}
|
13
|
+
|
14
|
+
subject { described_class.new attrs, ach_config }
|
15
|
+
|
16
|
+
describe '#access_token' do
|
17
|
+
it 'returns account token from account token provider' do
|
18
|
+
expect(subject.access_token).to eq(account_access_token)
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
describe '#refresh_token' do
|
23
|
+
it 'returns account token from account token provider' do
|
24
|
+
expect(subject.refresh_token).to eq(account_refresh_token)
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
# INTEGRATION TEST
|
30
|
+
describe MoneyMover::Dwolla::AccountToken do
|
31
|
+
let(:invalid_refresh_token_response) {{
|
32
|
+
"error": "access_denied",
|
33
|
+
"error_description": "Invalid refresh token."
|
34
|
+
}}
|
35
|
+
|
36
|
+
let(:expired_refresh_token_error) {{
|
37
|
+
"error": "access_denied",
|
38
|
+
"error_description": "Expired refresh token."
|
39
|
+
}}
|
40
|
+
|
41
|
+
let(:refresh_token_request_params) {{
|
42
|
+
"client_id": "JCGQXLrlfuOqdUYdTcLz3rBiCZQDRvdWIUPkw++GMuGhkem9Bo",
|
43
|
+
"client_secret": "g7QLwvO37aN2HoKx1amekWi8a2g7AIuPbD5C/JSLqXIcDOxfTr",
|
44
|
+
"refresh_token": "Pgk+l9okjwTCfsvIvEDPrsomE1er1txeyoaAkTIBAuXza8WvZY",
|
45
|
+
"grant_type": "refresh_token"
|
46
|
+
}}
|
47
|
+
|
48
|
+
#let(:refresh_token_success_response) {{
|
49
|
+
#"_links": {
|
50
|
+
#"account": {
|
51
|
+
#"href": "https://api-uat.dwolla.com/accounts/ca32853c-48fa-40be-ae75-77b37504581b"
|
52
|
+
#}
|
53
|
+
#},
|
54
|
+
#"access_token": "F3jK4rg7FGlq4yRQ7vWECoXVD4zQq9Xg26VnxzMbHGusZqr7dF",
|
55
|
+
#"expires_in": 3600,
|
56
|
+
#"refresh_token": "DRlqGJ0IFsRK8xzjkKhjTOgz3meet6E91T2oacGCefHGU4h1hj",
|
57
|
+
#"refresh_expires_in": 5184000,
|
58
|
+
#"token_type": "bearer",
|
59
|
+
#"scope": "send|transactions|funding|managecustomers",
|
60
|
+
#"account_id": "ca32853c-48fa-40be-ae75-77b37504581b"
|
61
|
+
#}}
|
62
|
+
|
63
|
+
|
64
|
+
let(:account_id) { "7da912eb-5976-4e5c-b5ab-a5df35ac661b" }
|
65
|
+
let(:new_access_token) { "oNGSeXqucdVxTLAwSRNc1WjG5BTHWNS5z7hccJGUTGvCXusmbC" }
|
66
|
+
let(:new_refresh_token) { "Et380Ps1y9tyiW3A8yf0ws1lbfGUVXl5DLIHfDDELXC0ls7hie" }
|
67
|
+
|
68
|
+
let(:refresh_token_success_response) {{
|
69
|
+
"_links": {
|
70
|
+
"account": {
|
71
|
+
"href":"https://api-uat.dwolla.com/accounts/#{account_id}"
|
72
|
+
}
|
73
|
+
},
|
74
|
+
"access_token": new_access_token,
|
75
|
+
"expires_in":3600,
|
76
|
+
"refresh_token": new_refresh_token,
|
77
|
+
"refresh_expires_in":5184000,
|
78
|
+
"token_type":"bearer",
|
79
|
+
"scope":"accountinfofull|contacts|transactions|balance|send|request|funding|manageaccount|scheduled|email|managecustomers",
|
80
|
+
"account_id": account_id
|
81
|
+
}}
|
82
|
+
|
83
|
+
describe '#request_new_token!' do
|
84
|
+
let(:token_response) { refresh_token_success_response }
|
85
|
+
|
86
|
+
before do
|
87
|
+
dwolla_helper.stub_refresh_token_request(token_response)
|
88
|
+
end
|
89
|
+
|
90
|
+
context 'success' do
|
91
|
+
it 'updates tokens in db' do
|
92
|
+
new_token = subject.request_new_token!
|
93
|
+
|
94
|
+
expect(new_token.account_id).to eq(account_id)
|
95
|
+
expect(new_token.expires_in).to eq(3600)
|
96
|
+
expect(new_token.access_token).to eq(new_access_token)
|
97
|
+
expect(new_token.refresh_token).to eq(new_refresh_token)
|
98
|
+
end
|
99
|
+
end
|
100
|
+
end
|
101
|
+
end
|