money_mover 0.0.3
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 +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
|