synapse_client 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 1c31d65fc404f16de0c7758b1006ad8eda2a3037
4
+ data.tar.gz: 025e61fa99b415922116894a44bb2b5a37c7defa
5
+ SHA512:
6
+ metadata.gz: dd5ea5ccec30485c2db93c12f7a4bd4482cd45b344991d77c2e1e41f11cb75975f1199505102b355ddd16fdcb1a408d8b4806a9c6e4b649f9389e0c1d64d1708
7
+ data.tar.gz: f1820556c5b92b014be2152f6a29ebe719676be918ece522d0d4facdc2e2983133b12e6c56734420c45bf3650cfd2f987e2618168fa54ccf782a2a9fd641e643
data/.coveralls.yml ADDED
@@ -0,0 +1 @@
1
+ service_name: travis-ci
data/.gitignore ADDED
@@ -0,0 +1,15 @@
1
+ /.bundle/
2
+ /.yardoc
3
+ /Gemfile.lock
4
+ /_yardoc/
5
+ /coverage/
6
+ /doc/
7
+ /pkg/
8
+ /spec/reports/
9
+ /tmp/
10
+ *.bundle
11
+ *.so
12
+ *.o
13
+ *.a
14
+ mkmf.log
15
+ /notes/
data/.travis.yml ADDED
@@ -0,0 +1,15 @@
1
+ language: ruby
2
+ cache: bundler
3
+
4
+ rvm:
5
+ - 2.1.4
6
+
7
+ script: 'bundle exec rake'
8
+
9
+ notifications:
10
+ email:
11
+ recipients:
12
+ - miles.matthias@gmail.com
13
+ on_failure: change
14
+ on_success: never
15
+
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in synapse_client.gemspec
4
+ gemspec
data/Guardfile ADDED
@@ -0,0 +1,11 @@
1
+ guard 'rspec', cmd: 'bundle exec rspec' do
2
+ # watch /lib/ files
3
+ watch(%r{^lib/(.+).rb$}) do |m|
4
+ "spec/#{m[1]}_spec.rb"
5
+ end
6
+
7
+ # watch /spec/ files
8
+ watch(%r{^spec/(.+).rb$}) do |m|
9
+ "spec/#{m[1]}.rb"
10
+ end
11
+ end
data/LICENSE ADDED
@@ -0,0 +1,22 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2015 Miles Matthias
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
22
+
data/README.md ADDED
@@ -0,0 +1,116 @@
1
+ [![Build Status](https://travis-ci.org/milesmatthias/synapse_client.png?branch=master)](https://travis-ci.org/milesmatthias/synapse_client) [![Gem Version](https://badge.fury.io/rb/synapse_client.png)](http://badge.fury.io/rb/synapse_client) [![Coverage Status](https://coveralls.io/repos/milesmatthias/synapse_client/badge.png)](https://coveralls.io/r/milesmatthias/synapse_client)
2
+
3
+ # synapse_client
4
+
5
+ A ruby client for the SynapsePay.com API.
6
+
7
+ I ripped originally wrote this in a rails app of mine and stripped this out. There's some work left to do to really make it a true ruby gem. See that in the todo section.
8
+
9
+ ## Notes
10
+
11
+ * This is written with the perspective of being the merchant. This gem doesn't support marketplace payments yet, although SynapsePay does support that.
12
+ * This is also written with the assumption that a customer has no knowledge of their Synapse account. This means:
13
+ * that this gem says "Customers" when Synapse says "Users"
14
+ * all orders are bank pay orders
15
+ * customers do not have passwords
16
+
17
+ ## Usage
18
+
19
+ _See the specs for the most up to date usage demo._
20
+
21
+ #### configuration
22
+
23
+ ```ruby
24
+ SynapseClient.client_id = "e06fa0f143a267c2ed8e"
25
+ SynapseClient.client_secret = "f578105bf9ae03d9310e0af6f4637c1bf363998b"
26
+ SynapseClient.merchant_synapse_id = 1
27
+ SynapseClient.dev = true
28
+ ```
29
+
30
+ #### create a customer
31
+
32
+ ```ruby
33
+ SynapseClient::Customer.create({
34
+ :email => "foo@example.com",
35
+ :fullname => "Foo Bar,
36
+ :phonenumber => "5555555555",
37
+ :ip_address => "8.8.8.8"
38
+ })
39
+ ```
40
+
41
+ #### retrieve a customer
42
+
43
+ ```ruby
44
+ SynapseClient::Customer.retrieve("_customer_access_token_")
45
+ ```
46
+
47
+ #### list bank accounts for a customer
48
+
49
+ ```ruby
50
+ @customer.bank_accounts
51
+ ```
52
+
53
+ #### add a bank account to a customer with just account & routing number
54
+
55
+ ```ruby
56
+ @customer.add_bank_account({
57
+ :account_num => "1111111111",
58
+ :routing_num => "084000026",
59
+ :nickname => "Example bank account",
60
+ :account_type => "1",
61
+ :account_class => "1"
62
+ })
63
+ ```
64
+
65
+ #### link a bank account to a customer with bank username/password
66
+
67
+ ```ruby
68
+ @customer.link_bank_account({
69
+ :username => "synapse_good",
70
+ :password => "test1234",
71
+ :pin => "1234",
72
+ :bank => "Bank of America"
73
+ })
74
+ ```
75
+
76
+ #### get recent orders for a customer
77
+
78
+ ```ruby
79
+ @customer.orders
80
+ ```
81
+
82
+ #### add an order for a customer
83
+
84
+ ```ruby
85
+ @customer.add_order({
86
+ :amount => 500, # $500 USD
87
+ :bank_id => 1
88
+ })
89
+ ```
90
+
91
+ #### retrieve an order
92
+
93
+ ```ruby
94
+ SynapseClient::Order.retrieve(4)
95
+ ```
96
+
97
+ ## TODO (in order of priority)
98
+
99
+ * MFAs
100
+ * MassPay
101
+ * View bank account
102
+ * Refresh access tokens
103
+ * Security Questions
104
+ * Deposits
105
+ * Withdrawals
106
+ * Better synapse error handling
107
+ * HTTP Error handling
108
+ * Logging
109
+ * Callbacks?
110
+
111
+
112
+ # Links
113
+
114
+ * [dev.synapsepay.com](http://dev.synapsepay.com)
115
+ * [rubygems.org/gems/synapse_client](https://rubygems.org/gems/synapse_client)
116
+
data/Rakefile ADDED
@@ -0,0 +1,11 @@
1
+ require 'rspec/core/rake_task'
2
+ require 'bundler/gem_tasks'
3
+
4
+ # Default directory to look in is `/specs`
5
+ # Run with `rake spec`
6
+ RSpec::Core::RakeTask.new(:spec) do |task|
7
+ task.rspec_opts = ['--color', '--format', 'documentation']
8
+ end
9
+
10
+ task :default => :spec
11
+
@@ -0,0 +1,137 @@
1
+ # http://dev.synapsepay.com/
2
+
3
+ require "map"
4
+ require "restclient"
5
+ require "synapse_client/api_resource"
6
+ require "synapse_client/api_operations/response"
7
+ require "synapse_client/api_operations/list"
8
+ require "synapse_client/bank_account"
9
+ require "synapse_client/error"
10
+ require "synapse_client/merchant"
11
+ require "synapse_client/mfa"
12
+ require "synapse_client/order"
13
+ require "synapse_client/refreshed_tokens"
14
+ require "synapse_client/security_question"
15
+ require "synapse_client/customer"
16
+ require "synapse_client/util"
17
+ require "synapse_client/version"
18
+
19
+ module SynapseClient
20
+
21
+ class << self
22
+ attr_accessor :client_id, :client_secret
23
+ attr_accessor :merchant_oauth_key, :merchant_email, :merchant_synapse_id
24
+ attr_accessor :dev
25
+ alias_method :dev?, :dev
26
+ end
27
+
28
+ def self.ensure_trailing_slash(url='')
29
+ return url if url.empty?
30
+ return url if url[-1] == "/"
31
+ return url + "/"
32
+ end
33
+
34
+ def self.api_url(url='')
35
+ base_api_url = "https://synapsepay.com"
36
+ base_api_url = "https://sandbox.synapsepay.com" if dev?
37
+
38
+ ret = base_api_url + ensure_trailing_slash(url)
39
+
40
+ if dev?
41
+ ret + "?is_dev=true"
42
+ else
43
+ ret
44
+ end
45
+ end
46
+
47
+ def self.request(method, path, params={}, headers={}, client_id=nil, client_secret=nil, api_base_url=nil)
48
+
49
+ #
50
+ unless (client_id ||= @client_id) && (client_secret ||= @client_secret)
51
+ # TODO - use a custom Error class here
52
+ raise StandardError.new("You need to enter API credentials first.")
53
+ end
54
+
55
+ if client_id =~ /\s/ || client_secret =~ /\s/
56
+ # TODO - use a custom Error class here
57
+ raise StandardError.new("Your API credentials are invalid, as they contain whitespace.")
58
+ end
59
+
60
+ #
61
+ url = api_url(path)
62
+ cookies = params.delete("cookies")
63
+
64
+ case method.to_s.downcase.to_sym
65
+ when :get, :head, :delete
66
+ # Make params into GET parameters
67
+ url += "#{URI.parse(url).query ? '&' : '?'}#{uri_encode(params)}" if params && params.any?
68
+ payload = nil
69
+ else
70
+ if path.include?("oauth2")
71
+ payload = params.to_query
72
+ headers[:content_type] = "application/x-www-form-urlencoded"
73
+ else
74
+ payload = creds(client_id, client_secret).update(params)
75
+
76
+ # dealing with some naming inconsistencies in the api
77
+ payload[:oauth_consumer_key] = payload.delete(:access_token) if payload[:access_token]
78
+ payload[:oauth_consumer_key] = payload.delete("access_token") if payload["access_token"]
79
+ payload[:access_token] = payload.delete("bank_account_token") if payload["bank_account_token"]
80
+ payload[:access_token] = payload.delete(:bank_account_token) if payload[:bank_account_token]
81
+
82
+ payload = payload.to_json
83
+ headers[:content_type] = :json
84
+ end
85
+ end
86
+
87
+ #
88
+ request_opts = {
89
+ :headers => headers,
90
+ :method => method, :open_timeout => 30,
91
+ :payload => payload,
92
+ :url => url, :timeout => 80, :cookies => cookies
93
+ }
94
+
95
+ #
96
+ #begin
97
+ response = execute_request(request_opts)
98
+ # TODO: https://github.com/stripe/stripe-ruby/blob/master/lib/stripe.rb#L127
99
+ #rescue
100
+ #end
101
+
102
+ parse(response)
103
+ end
104
+
105
+ def self.creds(client_id, client_secret)
106
+ {
107
+ :client_id => client_id,
108
+ :client_secret => client_secret
109
+ }
110
+ end
111
+
112
+ def self.execute_request(opts)
113
+ puts "\n"
114
+ puts "SynapseClient: About to send a request with the following opts:"
115
+ puts opts
116
+ puts "\n"
117
+ RestClient::Request.execute(opts)
118
+ end
119
+
120
+ def self.uri_encode(params)
121
+ Util.flatten_params(params).
122
+ map { |k,v| "#{k}=#{Util.url_encode(v)}" }.join('&')
123
+ end
124
+
125
+ def self.parse(response)
126
+ #begin
127
+ body = JSON.parse(response.body)
128
+ #rescue JSON::ParserError
129
+ # TODO
130
+ # raise general_api_error(response.code, response.body)
131
+ #end
132
+
133
+ APIOperations::Response.new(body, response.cookies)
134
+ end
135
+
136
+ end
137
+
@@ -0,0 +1,16 @@
1
+ module Stripe
2
+ module APIOperations
3
+ module Create
4
+ module ClassMethods
5
+ def create(params={}, opts={})
6
+ response, opts = SynapseClient.request(:post, url, params, opts)
7
+ response
8
+ end
9
+ end
10
+
11
+ def self.included(base)
12
+ base.extend(ClassMethods)
13
+ end
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,17 @@
1
+ module SynapseClient
2
+ module APIOperations
3
+ module List
4
+ module ClassMethods
5
+ def list(params={}, list_action="show")
6
+ response = SynapseClient.request(:post, url + list_action, params)
7
+ return response unless response.successful?
8
+ response.data
9
+ end
10
+ end
11
+
12
+ def self.included(base)
13
+ base.extend(ClassMethods)
14
+ end
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,20 @@
1
+ module SynapseClient
2
+ module APIOperations
3
+ class Response
4
+ attr_reader :data
5
+ attr_reader :error_msg
6
+ attr_reader :success
7
+ attr_reader :cookies
8
+ alias_method :successful?, :success
9
+
10
+ def initialize(response, cookies=nil)
11
+ response = Map.new(response)
12
+
13
+ @success = response.delete(:success)
14
+ @error_msg = response.delete(:reason)
15
+ @data = response
16
+ @cookies = cookies
17
+ end
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,50 @@
1
+
2
+ module SynapseClient
3
+ class APIResource
4
+
5
+ attr_accessor :id
6
+
7
+ def self.class_name
8
+ self.name.split('::')[-1]
9
+ end
10
+
11
+ def self.api_resource_name
12
+ class_name.downcase
13
+ end
14
+
15
+ def to_hash
16
+ hash = {}
17
+ instance_variables.each do |var|
18
+ value = instance_variable_get(var)
19
+ hash[var[1..-1].to_sym] = value if value
20
+ end
21
+ hash
22
+ end
23
+
24
+ def self.url
25
+ if self == APIResource
26
+ raise NotImplementedError.new('APIResource is an abstract class. You should perform actions on its subclasses (Customer, Bank Account, Order, etc.)')
27
+ end
28
+ "/api/v2/#{CGI.escape( api_resource_name )}/"
29
+ end
30
+
31
+ def url
32
+ self.class.url
33
+ end
34
+
35
+ def refresh(endpoint="")
36
+ response = SynapseClient.request(:post, url + endpoint, retrieve_params)
37
+
38
+ return response unless response.successful?
39
+ update_attributes(response.data[self.class.class_name.downcase])
40
+ end
41
+
42
+ def self.retrieve(id, opts={})
43
+ opts.merge!(:id => id)
44
+ instance = self.new(opts)
45
+ instance.refresh(retrieve_endpoint)
46
+ instance
47
+ end
48
+
49
+ end
50
+ end