synapse_pay 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (64) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +4 -0
  3. data/.travis.yml +16 -0
  4. data/Gemfile +8 -0
  5. data/LICENSE +21 -0
  6. data/README.md +54 -0
  7. data/Rakefile +8 -0
  8. data/VERSION +1 -0
  9. data/bin/synapse_pay-console +7 -0
  10. data/gemfiles/default-with-activesupport.gemfile +10 -0
  11. data/gemfiles/json.gemfile +12 -0
  12. data/gemfiles/yajl.gemfile +12 -0
  13. data/lib/synapse_pay.rb +78 -0
  14. data/lib/synapse_pay/apibits/api_client.rb +29 -0
  15. data/lib/synapse_pay/apibits/api_endpoint.rb +9 -0
  16. data/lib/synapse_pay/apibits/api_list.rb +88 -0
  17. data/lib/synapse_pay/apibits/api_method.rb +97 -0
  18. data/lib/synapse_pay/apibits/api_object.rb +52 -0
  19. data/lib/synapse_pay/apibits/api_resource.rb +127 -0
  20. data/lib/synapse_pay/apibits/headers_builder.rb +47 -0
  21. data/lib/synapse_pay/apibits/params_builder.rb +30 -0
  22. data/lib/synapse_pay/apibits/path_builder.rb +38 -0
  23. data/lib/synapse_pay/apibits/requester.rb +104 -0
  24. data/lib/synapse_pay/apibits/util.rb +51 -0
  25. data/lib/synapse_pay/client.rb +89 -0
  26. data/lib/synapse_pay/endpoints/bank_endpoint.rb +47 -0
  27. data/lib/synapse_pay/endpoints/bank_mfa_device_endpoint.rb +5 -0
  28. data/lib/synapse_pay/endpoints/bank_mfa_questions_endpoint.rb +5 -0
  29. data/lib/synapse_pay/endpoints/bank_status_endpoint.rb +11 -0
  30. data/lib/synapse_pay/endpoints/card_endpoint.rb +26 -0
  31. data/lib/synapse_pay/endpoints/deposit_endpoint.rb +23 -0
  32. data/lib/synapse_pay/endpoints/mass_pay_endpoint.rb +26 -0
  33. data/lib/synapse_pay/endpoints/order_endpoint.rb +44 -0
  34. data/lib/synapse_pay/endpoints/user_endpoint.rb +26 -0
  35. data/lib/synapse_pay/endpoints/wire_endpoint.rb +29 -0
  36. data/lib/synapse_pay/endpoints/withdrawal_endpoint.rb +17 -0
  37. data/lib/synapse_pay/errors/api_connection_error.rb +4 -0
  38. data/lib/synapse_pay/errors/api_error.rb +32 -0
  39. data/lib/synapse_pay/errors/authentication_error.rb +4 -0
  40. data/lib/synapse_pay/errors/synapse_pay_error.rb +13 -0
  41. data/lib/synapse_pay/nested_list.rb +32 -0
  42. data/lib/synapse_pay/resources/bank.rb +46 -0
  43. data/lib/synapse_pay/resources/bank_mfa_device.rb +32 -0
  44. data/lib/synapse_pay/resources/bank_mfa_questions.rb +28 -0
  45. data/lib/synapse_pay/resources/bank_status.rb +21 -0
  46. data/lib/synapse_pay/resources/card.rb +32 -0
  47. data/lib/synapse_pay/resources/deposit.rb +25 -0
  48. data/lib/synapse_pay/resources/mass_pay.rb +38 -0
  49. data/lib/synapse_pay/resources/order.rb +63 -0
  50. data/lib/synapse_pay/resources/user.rb +80 -0
  51. data/lib/synapse_pay/resources/wire.rb +31 -0
  52. data/lib/synapse_pay/resources/withdrawal.rb +29 -0
  53. data/lib/synapse_pay/version.rb +3 -0
  54. data/synapse_pay.gemspec +29 -0
  55. data/test/synapse_pay/api_list_test.rb +23 -0
  56. data/test/synapse_pay/api_method_test.rb +89 -0
  57. data/test/synapse_pay/headers_builder_test.rb +39 -0
  58. data/test/synapse_pay/params_builder_test.rb +57 -0
  59. data/test/synapse_pay/path_builder_test.rb +50 -0
  60. data/test/synapse_pay/requester_test.rb +86 -0
  61. data/test/synapse_pay/util_test.rb +51 -0
  62. data/test/test_data.rb +72 -0
  63. data/test/test_helper.rb +41 -0
  64. metadata +220 -0
@@ -0,0 +1,29 @@
1
+ $:.unshift(File.join(File.dirname(__FILE__), 'lib'))
2
+
3
+ require 'synapse_pay/version'
4
+
5
+ spec = Gem::Specification.new do |s|
6
+ s.name = 'synapse_pay'
7
+ s.summary = 'Ruby bindings for SynapsePay API'
8
+ s.description = 'SynapsePay allows you to integrate bank payments into your applications'
9
+ s.homepage = 'http://synapsepay.readme.io/v1.0/docs'
10
+ s.authors = ['Apibits.com']
11
+ s.email = ['libraries@apibits.com']
12
+ s.version = SynapsePay::VERSION
13
+ s.license = 'MIT'
14
+
15
+ s.add_dependency('rest-client', '~> 1.4')
16
+ s.add_dependency('mime-types', '>= 1.25', '< 3.0')
17
+ s.add_dependency('json', '~> 1.8.1')
18
+
19
+ s.add_development_dependency('mocha', '~> 0.13.2')
20
+ s.add_development_dependency('shoulda', '~> 3.4.0')
21
+ s.add_development_dependency('test-unit')
22
+ s.add_development_dependency('rake')
23
+
24
+ s.files = `git ls-files`.split("\n")
25
+ s.test_files = `git ls-files -- test/*`.split("\n")
26
+ s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
27
+ s.require_paths = ['lib']
28
+ end
29
+
@@ -0,0 +1,23 @@
1
+ require File.expand_path('../../test_helper', __FILE__)
2
+
3
+ module SynapsePay
4
+ class APIListTest < ::Test::Unit::TestCase
5
+
6
+ context '#new / #initialize' do
7
+ setup do
8
+ @fake_resource = {:data => "fake-data"}
9
+ @list = APIList.new(APIResource, [@fake_resource])
10
+ end
11
+
12
+ should 'set the klass' do
13
+ assert_equal(APIResource, @list.klass)
14
+ end
15
+
16
+ should 'convert the data to klass instances' do
17
+ assert(@list.first.is_a?(APIResource))
18
+ assert_equal(@fake_resource, @list.first.json)
19
+ end
20
+ end
21
+
22
+ end
23
+ end
@@ -0,0 +1,89 @@
1
+ require File.expand_path('../../test_helper', __FILE__)
2
+
3
+ module SynapsePay
4
+ class APIMethodTest < ::Test::Unit::TestCase
5
+ setup do
6
+ @method = :get
7
+ @path = "/testing"
8
+ @params = { :param_a => "1" }
9
+ @headers = { :header_a => "a" }
10
+ @object = mock
11
+ @api_method = APIMethod.new(@method, @path, @params, @headers, @object)
12
+ end
13
+
14
+ context '#new / #initialize' do
15
+ should 'set the api_key' do
16
+ assert_equal(SynapsePay.api_key, @api_method.api_key)
17
+ end
18
+
19
+ should 'set the api_base' do
20
+ assert_equal(SynapsePay.api_base, @api_method.api_base)
21
+ end
22
+
23
+ should 'use PathBuilder with path, object, and params' do
24
+ PathBuilder.expects(:build).with(@path, @object, @params).returns(@path)
25
+ APIMethod.new(@method, @path, @params, @headers, @object)
26
+ end
27
+
28
+ should 'use ParamsBuilder with params' do
29
+ ParamsBuilder.expects(:build).with(@params).returns(@params)
30
+ APIMethod.new(@method, @path, @params, @headers, @object)
31
+ end
32
+
33
+ should 'use HeadersBuilder with headers, api_key, and nil auth_header' do
34
+ HeadersBuilder.expects(:build).with(@headers, SynapsePay.api_key, nil).returns(@headers)
35
+ APIMethod.new(@method, @path, @params, @headers, @object)
36
+ end
37
+
38
+ should 'verify the api key exists' do
39
+ SynapsePay.api_key = nil
40
+ assert_raises(AuthenticationError) do
41
+ APIMethod.new(@method, @path, @params, @headers, @object)
42
+ end
43
+ end
44
+ end
45
+
46
+ context '#execute' do
47
+ setup do
48
+ @mock_response = mock
49
+ @mock_response.stubs(:body).returns('{"status": "success"}')
50
+ @mock_response.stubs(:code).returns(200)
51
+ end
52
+
53
+ should 'call Requester.request with the set attrs' do
54
+ Requester.expects(:request).with(@method, @api_method.url, @api_method.params, @api_method.headers).returns(@mock_response)
55
+ @api_method.execute
56
+ end
57
+
58
+ should 'create an APIError if the request fails' do
59
+ Requester.expects(:request).raises(RestClient::RequestTimeout.new)
60
+
61
+ assert_raises(APIError) { @api_method.execute }
62
+ end
63
+
64
+ should 'return the response parsed as json' do
65
+ Requester.expects(:request).returns(@mock_response)
66
+ assert_equal({:status => "success"}, @api_method.execute)
67
+ end
68
+
69
+ should 'return an AuthenticationError if the status is 401' do
70
+ error = RestClient::ExceptionWithResponse.new
71
+ error.expects(:http_code).returns(401)
72
+
73
+ Requester.expects(:request).raises(error)
74
+ assert_raises(AuthenticationError) { @api_method.execute }
75
+ end
76
+ end
77
+
78
+ context '#response_json' do
79
+ setup do
80
+ @api_method.response_body = 'not-valid-json'
81
+ end
82
+
83
+ should 'throw an error if the response_body isnt valid json' do
84
+ assert_raises(APIError) { @api_method.response_json }
85
+ end
86
+ end
87
+
88
+ end
89
+ end
@@ -0,0 +1,39 @@
1
+ require File.expand_path('../../test_helper', __FILE__)
2
+
3
+ module SynapsePay
4
+ class HeadersBuilderTest < ::Test::Unit::TestCase
5
+
6
+ setup do
7
+ @headers = {
8
+ :dog => "dog-value"
9
+ }
10
+ @api_key = "test-api-key"
11
+ @built_headers = HeadersBuilder.build(@headers, @api_key)
12
+ end
13
+
14
+ should 'set the content_type' do
15
+ assert(@built_headers.has_key?(:content_type))
16
+ assert_equal('application/x-www-form-urlencoded', @built_headers[:content_type])
17
+ end
18
+
19
+ should 'set the user_agent' do
20
+ assert(@built_headers.has_key?(:user_agent))
21
+ assert(@built_headers[:user_agent].include?(SynapsePay::VERSION))
22
+ assert(@built_headers[:user_agent].include?(SynapsePay.api_version))
23
+ end
24
+
25
+ should 'set the basic auth header' do
26
+ assert(@built_headers.has_key?("Authorization"))
27
+ encoded_api_key = Base64.encode64("#{@api_key}:")
28
+ assert(@built_headers["Authorization"].include?(encoded_api_key))
29
+ end
30
+
31
+ should 'set the custom auth header' do
32
+ auth_key = "CLIENT-TOKEN"
33
+ header = HeadersBuilder.build(@headers, @api_key, auth_key)
34
+ assert(header.has_key?(auth_key))
35
+ assert_equal(@api_key, header[auth_key])
36
+ end
37
+
38
+ end
39
+ end
@@ -0,0 +1,57 @@
1
+ require File.expand_path('../../test_helper', __FILE__)
2
+
3
+ module SynapsePay
4
+ class ParamsBuilderTest < ::Test::Unit::TestCase
5
+
6
+ setup do
7
+ @params = {
8
+ :dog => "dog-value",
9
+ "string" => "str-value"
10
+ }
11
+ end
12
+
13
+ context '#clean' do
14
+ setup do
15
+ @built_params = ParamsBuilder.clean(@params)
16
+ end
17
+
18
+ should 'convert keys to symbols' do
19
+ assert(@built_params.has_key?(:string))
20
+ assert_equal(@params["string"], @built_params[:string])
21
+ end
22
+
23
+ should 'not have any string keys' do
24
+ @built_params.each do |k, v|
25
+ assert(k.is_a?(Symbol))
26
+ end
27
+ end
28
+ end
29
+
30
+ context '#merge' do
31
+ setup do
32
+ @to_merge = {
33
+ :string => "other-str-value",
34
+ "cat" => "cat-value"
35
+ }
36
+ @built_params = ParamsBuilder.merge(@params, @to_merge)
37
+ end
38
+
39
+ should 'convert keys to symbols' do
40
+ assert(@built_params.has_key?(:cat))
41
+ assert(@built_params.has_key?(:string))
42
+ assert(!@built_params.has_key?("string"))
43
+ end
44
+
45
+ should 'merge in all values' do
46
+ assert_equal(@params[:dog], @built_params[:dog])
47
+ assert_equal(@to_merge[:string], @built_params[:string])
48
+ assert_equal(@to_merge["cat"], @built_params[:cat])
49
+ end
50
+
51
+ should 'prioritize values in @to_merge' do
52
+ assert_equal(@to_merge[:string], @built_params[:string])
53
+ end
54
+ end
55
+
56
+ end
57
+ end
@@ -0,0 +1,50 @@
1
+ require File.expand_path('../../test_helper', __FILE__)
2
+
3
+ module SynapsePay
4
+ class PathBuilderTest < ::Test::Unit::TestCase
5
+ class FakeClass
6
+ def abc; return "abc-value"; end
7
+ def self.xyz; return "xyz-value"; end
8
+ end
9
+
10
+ setup do
11
+ @params = {
12
+ :dog => "dog-value"
13
+ }
14
+ @obj = FakeClass.new
15
+ end
16
+
17
+ should 'use instance methods' do
18
+ path = "/a/:abc/123"
19
+ expected = "/a/abc-value/123"
20
+
21
+ actual = PathBuilder.build(path, @obj, nil)
22
+ assert_equal(expected, actual)
23
+ end
24
+
25
+ should 'use class methods' do
26
+ path = "/a/:xyz/123"
27
+ expected = "/a/xyz-value/123"
28
+
29
+ actual = PathBuilder.build(path, FakeClass, nil)
30
+ assert_equal(expected, actual)
31
+ end
32
+
33
+ should 'use param values' do
34
+ path = "/a/:dog/123"
35
+ expected = "/a/dog-value/123"
36
+
37
+ actual = PathBuilder.build(path, nil, @params)
38
+ assert_equal(expected, actual)
39
+ end
40
+
41
+ should 'use both methods and params' do
42
+ path = "/a/:dog/:abc/123"
43
+ expected = "/a/dog-value/abc-value/123"
44
+
45
+ actual = PathBuilder.build(path, @obj, @params)
46
+ assert_equal(expected, actual)
47
+ end
48
+
49
+ end
50
+ end
@@ -0,0 +1,86 @@
1
+ require File.expand_path('../../test_helper', __FILE__)
2
+
3
+ module SynapsePay
4
+ class RequesterTest < ::Test::Unit::TestCase
5
+ setup do
6
+ end
7
+
8
+ context '#prepare_params' do
9
+ setup do
10
+ @url = "test_url"
11
+ @params = { :a => 1, :b => [2, 3] }
12
+ end
13
+
14
+ should 'convert :get params to a query string' do
15
+ url, params = Requester.prepare_params(@url, @params, :get)
16
+ assert(url != @url)
17
+ assert(params.nil?)
18
+ end
19
+
20
+ should 'convert :delete params to a query string' do
21
+ url, params = Requester.prepare_params(@url, @params, :delete)
22
+ assert(url != @url)
23
+ assert(params.nil?)
24
+ end
25
+
26
+ should 'convert :head params to a query string' do
27
+ url, params = Requester.prepare_params(@url, @params, :head)
28
+ assert(url != @url)
29
+ assert(params.nil?)
30
+ end
31
+
32
+ context 'method = :post' do
33
+ setup do
34
+ @method = :post
35
+ end
36
+
37
+ should 'not convert params to a query string if a file is in them' do
38
+ expected = { file: File.new(__FILE__) }
39
+ url, params = Requester.prepare_params(@url, expected, @method)
40
+ assert_equal(expected, params)
41
+ end
42
+
43
+ should 'convert params to a query string if a file is not present' do
44
+ url, params = Requester.prepare_params(@url, @params, @method)
45
+ assert(params.is_a?(String))
46
+ end
47
+ end
48
+ end
49
+
50
+ context '#query_string' do
51
+ should 'join #query_array results with an "&"' do
52
+ start = { :a => 1, :b => [2, 3] }
53
+ expected = ["a=1", "b[]=2", "b[]=3"]
54
+
55
+ actual = Requester.query_string(start).split('&')
56
+ actual.each do |str|
57
+ assert(expected.include?(str))
58
+ end
59
+ end
60
+ end
61
+
62
+ context '#query_array' do
63
+ should 'convert { :a => "value" } to []' do
64
+ start = { :a => "value" }
65
+ finish = ["a=value"]
66
+
67
+ assert_equal(finish, Requester.query_array(start))
68
+ end
69
+
70
+ should 'convert { :a => { :b => { :c => "cvalue" } } } to ["a[b][c]=cvalue"]' do
71
+ start = { :a => { :b => { :c => "cvalue" } } }
72
+ finish = ["a[b][c]=cvalue"]
73
+
74
+ assert_equal(finish, Requester.query_array(start))
75
+ end
76
+
77
+ should 'convert { :a => [1, 2] } to ["a[]=1", "a[]=2"]' do
78
+ start = { :a => [1, 2] }
79
+ finish = ["a[]=1", "a[]=2"]
80
+
81
+ assert_equal(finish, Requester.query_array(start))
82
+ end
83
+ end
84
+
85
+ end
86
+ end
@@ -0,0 +1,51 @@
1
+ require File.expand_path('../../test_helper', __FILE__)
2
+
3
+ module SynapsePay
4
+ class UtilTest < ::Test::Unit::TestCase
5
+ context '#symbolize_keys' do
6
+ should "convert keys to symbols" do
7
+ start = {
8
+ 'foo' => 'bar',
9
+ 'array' => [{ 'foo' => 'bar' }],
10
+ 'nested' => {
11
+ 1 => 2,
12
+ :symbol => 9,
13
+ 'string' => nil
14
+ }
15
+ }
16
+ finish = {
17
+ :foo => 'bar',
18
+ :array => [{ :foo => 'bar' }],
19
+ :nested => {
20
+ 1 => 2,
21
+ :symbol => 9,
22
+ :string => nil
23
+ }
24
+ }
25
+
26
+ symbolized = Util.symbolize_keys(start)
27
+ assert_equal(finish, symbolized)
28
+ end
29
+ end
30
+
31
+ context '#sorta_deep_clone' do
32
+ # Super hand wavy test.. but it works for now so whatever.
33
+ should 'clone well enough that we dont accidentally alter json' do
34
+ start = { :a => "abc", :b => [ { :c => "c-1" }, { :c => "c-2" } ] }
35
+ cloned = Util.sorta_deep_clone(start)
36
+
37
+ cloned[:a] = "123"
38
+ cloned[:b] << { :c => "c-3" }
39
+ cloned[:b][0][:c] = "c-one"
40
+
41
+ assert_equal({ :a => "abc", :b => [ { :c => "c-1" }, { :c => "c-2" } ] }, start)
42
+ end
43
+ end
44
+
45
+ context '#constantize' do
46
+ should 'convert :APIResource to the class object' do
47
+ assert_equal(APIResource, Util.constantize(:APIResource))
48
+ end
49
+ end
50
+ end
51
+ end
data/test/test_data.rb ADDED
@@ -0,0 +1,72 @@
1
+ module SynapsePay
2
+ module TestData
3
+
4
+ def test_response(body, code=200)
5
+ # When an exception is raised, restclient clobbers method_missing. Hence we
6
+ # can't just use the stubs interface.
7
+ body = JSON.generate(body) if !(body.kind_of? String)
8
+ m = mock
9
+ m.instance_variable_set('@synapse_pay_values', { :body => body, :code => code })
10
+ def m.body; @synapse_pay_values[:body]; end
11
+ def m.code; @synapse_pay_values[:code]; end
12
+ m
13
+ end
14
+
15
+ def test_mock_resource
16
+ {
17
+ :object => 'mock_resource',
18
+ :name => 'test mr name',
19
+ :nested => {
20
+ :id => 'test_nested_id',
21
+ :object => 'nested_resource',
22
+ :price => 500
23
+ },
24
+ :nested_alt_id => 'nested_alt_id',
25
+ :nested_with => {
26
+ :id => 'nested_with_id',
27
+ :price => 500
28
+ },
29
+ :thash => { :some_key => "some value" },
30
+ :tarray => ["abc", "xyz"],
31
+ :id => 'test_mock_resource_id'
32
+ }
33
+ end
34
+
35
+ def test_mock_resource_list
36
+ {
37
+ :object => 'list',
38
+ :data => [test_mock_resource, test_mock_resource, test_mock_resource],
39
+ }
40
+ end
41
+
42
+
43
+ # Errors
44
+ def test_api_error
45
+ {
46
+ :error => {
47
+ :type => "api_error"
48
+ }
49
+ }
50
+ end
51
+
52
+ def test_invalid_api_key_error
53
+ {
54
+ :error => {
55
+ :type => "invalid_request_error",
56
+ :message => "Invalid API Key provided: invalid"
57
+ }
58
+ }
59
+ end
60
+
61
+ def test_missing_id_error
62
+ {
63
+ :error => {
64
+ :param => "id",
65
+ :type => "invalid_request_error",
66
+ :message => "Missing id"
67
+ }
68
+ }
69
+ end
70
+
71
+ end
72
+ end