synapse_pay 0.0.1

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 (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