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.
Files changed (56) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +1 -0
  3. data/.rspec +2 -0
  4. data/Gemfile +17 -0
  5. data/Gemfile.lock +80 -0
  6. data/lib/money_mover/dwolla/account_client.rb +9 -0
  7. data/lib/money_mover/dwolla/account_token.rb +24 -0
  8. data/lib/money_mover/dwolla/api_connection.rb +18 -0
  9. data/lib/money_mover/dwolla/api_server_response.rb +31 -0
  10. data/lib/money_mover/dwolla/application_client.rb +9 -0
  11. data/lib/money_mover/dwolla/application_token.rb +25 -0
  12. data/lib/money_mover/dwolla/client.rb +24 -0
  13. data/lib/money_mover/dwolla/config.rb +33 -0
  14. data/lib/money_mover/dwolla/environment_urls.rb +35 -0
  15. data/lib/money_mover/dwolla/error_handler.rb +30 -0
  16. data/lib/money_mover/dwolla/models/account_funding_source.rb +28 -0
  17. data/lib/money_mover/dwolla/models/api_resource.rb +70 -0
  18. data/lib/money_mover/dwolla/models/customer.rb +53 -0
  19. data/lib/money_mover/dwolla/models/document.rb +22 -0
  20. data/lib/money_mover/dwolla/models/funding_source.rb +30 -0
  21. data/lib/money_mover/dwolla/models/micro_deposit_initiation.rb +19 -0
  22. data/lib/money_mover/dwolla/models/micro_deposit_verification.rb +31 -0
  23. data/lib/money_mover/dwolla/models/receive_only_business_customer.rb +27 -0
  24. data/lib/money_mover/dwolla/models/receive_only_customer.rb +19 -0
  25. data/lib/money_mover/dwolla/models/root_account.rb +27 -0
  26. data/lib/money_mover/dwolla/models/transfer.rb +33 -0
  27. data/lib/money_mover/dwolla/models/unverified_business_customer.rb +43 -0
  28. data/lib/money_mover/dwolla/models/unverified_customer.rb +27 -0
  29. data/lib/money_mover/dwolla/models/verified_business_customer.rb +53 -0
  30. data/lib/money_mover/dwolla/models/webhook_subscription.rb +36 -0
  31. data/lib/money_mover/dwolla/token.rb +26 -0
  32. data/lib/money_mover/dwolla.rb +44 -0
  33. data/lib/money_mover/standalone_errors.rb +12 -0
  34. data/lib/money_mover/version.rb +3 -0
  35. data/lib/money_mover.rb +15 -0
  36. data/money_mover.gemspec +27 -0
  37. data/spec/integration/money_mover/dwolla/customers/create_spec.rb +75 -0
  38. data/spec/integration/money_mover/dwolla/customers/find_spec.rb +71 -0
  39. data/spec/integration/money_mover/dwolla/customers/funding-sources/create_spec.rb +40 -0
  40. data/spec/integration/money_mover/dwolla/documents/create_spec.rb +62 -0
  41. data/spec/integration/money_mover/dwolla/funding-sources/micro-deposits/initiation_spec.rb +52 -0
  42. data/spec/integration/money_mover/dwolla/funding-sources/micro-deposits/verification_spec.rb +77 -0
  43. data/spec/integration/money_mover/dwolla/transfers/create_spec.rb +80 -0
  44. data/spec/lib/money_mover/dwolla/client_spec.rb +101 -0
  45. data/spec/lib/money_mover/dwolla/config_spec.rb +20 -0
  46. data/spec/lib/money_mover/dwolla/error_handler_spec.rb +78 -0
  47. data/spec/lib/money_mover/dwolla/funding_source_spec.rb +94 -0
  48. data/spec/lib/money_mover/dwolla/microdeposits_initiation_spec.rb +36 -0
  49. data/spec/lib/money_mover/dwolla/root_account_spec.rb +86 -0
  50. data/spec/lib/money_mover/dwolla/token_spec.rb +101 -0
  51. data/spec/lib/money_mover/dwolla/transfer_spec.rb +94 -0
  52. data/spec/lib/money_mover/dwolla/webhook_subscription_spec.rb +199 -0
  53. data/spec/spec_helper.rb +121 -0
  54. data/spec/support/dwolla_helper.rb +330 -0
  55. data/spec/support/fixtures/sample.jpg +0 -0
  56. 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