ecommerce-client 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (41) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +31 -0
  3. data/.rspec +2 -0
  4. data/Gemfile +4 -0
  5. data/LICENSE.txt +22 -0
  6. data/README.md +29 -0
  7. data/Rakefile +5 -0
  8. data/ecommerce-client.gemspec +29 -0
  9. data/lib/ecommerce.rb +25 -0
  10. data/lib/ecommerce/attribute_handler.rb +51 -0
  11. data/lib/ecommerce/client.rb +45 -0
  12. data/lib/ecommerce/configuration.rb +14 -0
  13. data/lib/ecommerce/exception.rb +11 -0
  14. data/lib/ecommerce/request.rb +49 -0
  15. data/lib/ecommerce/resources/base.rb +28 -0
  16. data/lib/ecommerce/resources/order.rb +91 -0
  17. data/lib/ecommerce/resources/order_collection.rb +62 -0
  18. data/lib/ecommerce/response.rb +34 -0
  19. data/lib/ecommerce/version.rb +3 -0
  20. data/spec/ecommerce/attribute_handler_spec.rb +54 -0
  21. data/spec/ecommerce/client_spec.rb +26 -0
  22. data/spec/ecommerce/configuration_spec.rb +21 -0
  23. data/spec/ecommerce/request_spec.rb +23 -0
  24. data/spec/ecommerce/resources/order_collection_spec.rb +82 -0
  25. data/spec/ecommerce/resources/order_spec.rb +155 -0
  26. data/spec/ecommerce/response_spec.rb +35 -0
  27. data/spec/ecommerce_spec.rb +48 -0
  28. data/spec/spec_helper.rb +24 -0
  29. data/spec/support/vcr.rb +7 -0
  30. data/spec/vcr_cassettes/Ecommerce/Resources_Order_create_when_success_returns_body.yml +64 -0
  31. data/spec/vcr_cassettes/Ecommerce/Resources_Order_create_when_success_when_sending_not_all_required_parameters_raises_.yml +46 -0
  32. data/spec/vcr_cassettes/Ecommerce/Resources_Order_destroy_when_not_found_raises_NotFound.yml +46 -0
  33. data/spec/vcr_cassettes/Ecommerce/Resources_Order_destroy_when_success_returns_empty_body.yml +48 -0
  34. data/spec/vcr_cassettes/Ecommerce/Resources_Order_find_all_when_not_found_raises_NotFound.yml +46 -0
  35. data/spec/vcr_cassettes/Ecommerce/Resources_Order_find_all_when_success_returns_a_find_all_of_orders.yml +99 -0
  36. data/spec/vcr_cassettes/Ecommerce/Resources_Order_find_when_not_found_raises_NotFound.yml +46 -0
  37. data/spec/vcr_cassettes/Ecommerce/Resources_Order_find_when_success_returns_order_object.yml +58 -0
  38. data/spec/vcr_cassettes/client/authenticated/false.yml +47 -0
  39. data/spec/vcr_cassettes/client/authenticated/true.yml +56 -0
  40. data/tasks/rspec.rake +2 -0
  41. metadata +206 -0
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 24d72bc986b677e164e6714aa8e0b559eecf1b60
4
+ data.tar.gz: 45fcc9b6a2077c57ae2f59e119741023fc70a8fe
5
+ SHA512:
6
+ metadata.gz: 570eb44019d806ac722c895353b59387b82c23da6e03102dcd3c41e6c03b567ccb6b337fee43cd0d88bb00d0f29c5553aebd71e0ba73e21fd21e37a84f7696d1
7
+ data.tar.gz: faccd7f123c023d785013bf794a2c71bd5d32bd1dd476f0f2d5ad93ca20681c1ec0461ae0f018298063dbc42e1b146281f7c46d71f13a75f5cf98474d74564f9
data/.gitignore ADDED
@@ -0,0 +1,31 @@
1
+ *.gem
2
+ *.rbc
3
+ .bundle
4
+ .config
5
+ .yardoc
6
+ .env
7
+ .envrc
8
+ Gemfile.lock
9
+ InstalledFiles
10
+ _yardoc
11
+ coverage
12
+ doc/
13
+ lib/bundler/man
14
+ pkg
15
+ rdoc
16
+ spec/reports
17
+ test/tmp
18
+ test/version_tmp
19
+ tmp
20
+ vendor
21
+ *.bundle
22
+ *.so
23
+ *.o
24
+ *.a
25
+ mkmf.log
26
+ *.swp
27
+ *.swo
28
+ *~
29
+ .ruby-gemset
30
+ .ruby-version
31
+ doc
data/.rspec ADDED
@@ -0,0 +1,2 @@
1
+ --format progress
2
+ --color
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in ecommerce-client-ruby.gemspec
4
+ gemspec
data/LICENSE.txt ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2015 Free Communities Consultoria Em Informática Ltda.
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,29 @@
1
+ # Ecommerce Client
2
+
3
+ A Ruby client for Myfreecomm's Ecommerce REST API
4
+
5
+ ## Installation
6
+
7
+ Add this line to your application's Gemfile:
8
+
9
+ gem 'ecommerce-client-ruby'
10
+
11
+ And then execute:
12
+
13
+ $ bundle
14
+
15
+ Or install it yourself as:
16
+
17
+ $ gem install ecommerce-client-ruby
18
+
19
+ ## Usage
20
+
21
+ TODO: Write usage instructions here
22
+
23
+ ## Contributing
24
+
25
+ 1. Fork it ( http://github.com/<my-github-username>/ecommerce-client-ruby/fork )
26
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
27
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
28
+ 4. Push to the branch (`git push origin my-new-feature`)
29
+ 5. Create new Pull Request
data/Rakefile ADDED
@@ -0,0 +1,5 @@
1
+ require "bundler/gem_tasks"
2
+
3
+ Dir.glob('tasks/**/*.rake').each(&method(:import))
4
+
5
+ task default: :spec
@@ -0,0 +1,29 @@
1
+ lib = File.expand_path('../lib', __FILE__)
2
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
3
+
4
+ require 'ecommerce/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = "ecommerce-client"
8
+ spec.version = Ecommerce::VERSION
9
+ spec.authors = ["Rafael B. Tauil", "Eduardo Hertz", "Rodrigo Tassinari"]
10
+ spec.email = ["rafael@tauil.com.br", "eduardohertz@gmail.com", "rodrigo@pittlandia.net"]
11
+ spec.summary = %q{Official Ruby client for Myfreecomm's Ecommerce API.}
12
+ spec.description = %q{Official Ruby client for Myfreecomm's Ecommerce API. Ecommerce is a solution to control payments for your products.}
13
+ spec.homepage = "https://github.com/myfreecomm/ecommerce-client-ruby"
14
+ spec.license = "MIT"
15
+
16
+ spec.files = `git ls-files -z`.split("\x0")
17
+ spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
18
+ spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
19
+ spec.require_paths = ["lib"]
20
+
21
+ spec.add_dependency "typhoeus", "~> 0.7.1"
22
+ spec.add_dependency "multi_json", "~> 1.11"
23
+
24
+ spec.add_development_dependency "bundler", "~> 1.7"
25
+ spec.add_development_dependency "rake", "~> 10.0"
26
+ spec.add_development_dependency 'rspec', "~> 3.2"
27
+ spec.add_development_dependency "pry", "~> 0.10"
28
+ spec.add_development_dependency "vcr", "~> 2.9"
29
+ end
data/lib/ecommerce.rb ADDED
@@ -0,0 +1,25 @@
1
+ require "typhoeus"
2
+ require "multi_json"
3
+
4
+ require "ecommerce/version"
5
+ require "ecommerce/configuration"
6
+ require "ecommerce/client"
7
+ require "ecommerce/attribute_handler"
8
+
9
+ require "ecommerce/resources/base"
10
+ require "ecommerce/resources/order"
11
+ require "ecommerce/resources/order_collection"
12
+
13
+ module Ecommerce
14
+ def self.configuration
15
+ @configuration ||= Configuration.new
16
+ end
17
+
18
+ def self.configure
19
+ yield(configuration) if block_given?
20
+ end
21
+
22
+ def self.client
23
+ Client.new(Ecommerce.configuration.token, Ecommerce.configuration.secret)
24
+ end
25
+ end
@@ -0,0 +1,51 @@
1
+ require 'bigdecimal'
2
+
3
+ module Ecommerce
4
+ class AttributeHandler
5
+
6
+ KINDS = [:decimal, :date, :datetime]
7
+
8
+ attr_reader :attribute
9
+
10
+ def initialize(attribute)
11
+ @attribute = attribute
12
+ end
13
+
14
+ def self.handle(attribute)
15
+ self.new(attribute).handle
16
+ end
17
+
18
+ def handle
19
+ KINDS.each do |kind|
20
+ return send("as_#{kind}") if send("is_#{kind}?")
21
+ end
22
+ attribute
23
+ end
24
+
25
+ private
26
+
27
+ def is_decimal?
28
+ attribute =~ /\A\d+\.\d+\Z/
29
+ end
30
+
31
+ def is_date?
32
+ attribute =~ /\A\d+{4}\-\d+{2}\-\d+{2}\Z/
33
+ end
34
+
35
+ def is_datetime?
36
+ attribute =~ /\A\d+{4}\-\d+{2}\-\d+{2}[T ]?\d+{2}\:\d+{2}\:\d+{2}[Z]?\Z/
37
+ end
38
+
39
+ def as_decimal
40
+ BigDecimal.new(attribute)
41
+ end
42
+
43
+ def as_date
44
+ Date.parse(attribute)
45
+ end
46
+
47
+ def as_datetime
48
+ DateTime.parse(attribute)
49
+ end
50
+ end
51
+ end
@@ -0,0 +1,45 @@
1
+ require "ecommerce/request"
2
+ require "ecommerce/response"
3
+
4
+ module Ecommerce
5
+ class Client
6
+ attr_reader :token, :secret
7
+
8
+ def initialize(token, secret)
9
+ @token = token
10
+ @secret = secret
11
+ end
12
+
13
+ def authenticated?(plan)
14
+ get("/api/orders/#{plan}/") { |response| response.code == 200 }
15
+ rescue RequestError => e
16
+ raise e unless [401, 403].include?(e.code)
17
+ false
18
+ end
19
+
20
+ %w[get post delete put patch].each do |m|
21
+ define_method(m) do |path, options = {}, &block|
22
+ send_request(m.to_sym, path, options, &block)
23
+ end
24
+ end
25
+
26
+ private
27
+
28
+ def send_request(method, path, options, &block)
29
+ request = Request.new(options.merge!({
30
+ method: method,
31
+ authorization_hash: authorization_hash,
32
+ url: "#{Ecommerce.configuration.url}#{path}",
33
+ user_agent: Ecommerce.configuration.user_agent
34
+ }))
35
+
36
+ response = Response.new(request.run)
37
+
38
+ response.resolve!(&block)
39
+ end
40
+
41
+ def authorization_hash
42
+ ::Base64.strict_encode64("#{token}:#{secret}")
43
+ end
44
+ end
45
+ end
@@ -0,0 +1,14 @@
1
+ require "base64"
2
+
3
+ module Ecommerce
4
+ class Configuration
5
+ attr_accessor :url, :user_agent, :token, :secret
6
+
7
+ def initialize
8
+ @url = "https://ecommerce.myfreecomm.com.br"
9
+ @user_agent = "Ecommerce Ruby Client v#{Ecommerce::VERSION}"
10
+ @token = nil
11
+ @secret = nil
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,11 @@
1
+ module Ecommerce
2
+ class Exception < StandardError
3
+ attr_accessor :code, :body
4
+
5
+ def initialize(args = {})
6
+ super(args[:message])
7
+ @code = args[:code]
8
+ @body = args[:body]
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,49 @@
1
+ module Ecommerce
2
+ class Request
3
+
4
+ def initialize(args)
5
+ @args = args
6
+ end
7
+
8
+ def run
9
+ request.run
10
+ request.response
11
+ end
12
+
13
+ private
14
+
15
+ attr_reader :args
16
+
17
+ def request
18
+ @request ||= Typhoeus::Request.new(args[:url], options)
19
+ end
20
+
21
+ def options
22
+ {
23
+ method: args[:method],
24
+ params: args[:params],
25
+ body: body,
26
+ headers: headers,
27
+ accept_encoding: "gzip"
28
+ }.reject {|k,v| v.nil?}
29
+ end
30
+
31
+ def headers
32
+ headers = args.fetch(:headers) { {} }
33
+
34
+ {
35
+ "Accept" => "application/json",
36
+ "Content-Type" => "application/json",
37
+ "User-Agent" => args[:user_agent],
38
+ "Authorization" => "Basic #{args[:authorization_hash]}"
39
+ }.merge(headers)
40
+ end
41
+
42
+ def body
43
+ body = args[:body]
44
+ body = MultiJson.dump(body) if body.is_a?(Hash)
45
+ body
46
+ end
47
+
48
+ end
49
+ end
@@ -0,0 +1,28 @@
1
+ module Ecommerce
2
+ module Resources
3
+ class Base
4
+ def initialize(attribute={})
5
+ attribute.each do |k, v|
6
+ set_attribute(k, v)
7
+ end
8
+ end
9
+
10
+ def self.client
11
+ Ecommerce.client
12
+ end
13
+
14
+ private
15
+
16
+ def self.parsed_body(response)
17
+ MultiJson.load(response.body)
18
+ rescue MultiJson::ParseError
19
+ {}
20
+ end
21
+
22
+ def set_attribute(key, value)
23
+ object_value = Ecommerce::AttributeHandler.handle(value)
24
+ instance_variable_set("@#{key}", object_value)
25
+ end
26
+ end
27
+ end
28
+ end
@@ -0,0 +1,91 @@
1
+ module Ecommerce
2
+ module Resources
3
+
4
+ #
5
+ # A wrapper to Ecommerce orders API
6
+ #
7
+ # [API]
8
+ # Documentation: http://myfreecomm.github.io/passaporte-web/ecommerce/api/index.html
9
+ #
10
+
11
+ class Order < Base
12
+
13
+ attr_reader :is_paid, :address_number, :plan_change_urls, :activation_expired, :number, :is_trial,
14
+ :address_state, :global_account, :api_url, :document_number, :checkout_url, :active_until,
15
+ :charge_day, :address_quarter, :activated_at, :is_active, :user_code, :address, :is_recurring,
16
+ :address_city, :plan_slug, :address_complement, :discounts_url, :created_at, :adjustments_url,
17
+ :next_payment_at, :amount, :client_email, :client_name, :invoices_url, :zip_code
18
+
19
+ #
20
+ # Creates an Order
21
+ #
22
+ # [API]
23
+ # Method: <tt>POST /api/orders/:slug/</tt>
24
+ #
25
+ # Documentation: http://myfreecomm.github.io/passaporte-web/ecommerce/api/orders.html#criacao-de-ordem-de-compra
26
+ #
27
+
28
+ def self.create(slug, params)
29
+ client.post("/api/orders/#{slug}/", { body: params }) do |response|
30
+ build_order(response)
31
+ end
32
+ end
33
+
34
+ #
35
+ # Lists all Orders of a slug and return a collection with orders and pagination information (represented by Ecommerce::Resources::OrderCollection)
36
+ #
37
+ # [API]
38
+ # Method: <tt>GET /api/orders/:slug/</tt>
39
+ #
40
+ # Documentation: http://myfreecomm.github.io/passaporte-web/ecommerce/api/orders.html#listagem-de-ordens-de-compra
41
+ #
42
+
43
+ def self.find_all(slug, page = 1, limit = 20)
44
+ client.get("/api/orders/#{slug}/", { body: {page: page, limit: limit} }) do |response|
45
+ Ecommerce::Resources::OrderCollection.build(response)
46
+ end
47
+ end
48
+
49
+ #
50
+ # Finds an Order
51
+ #
52
+ # [API]
53
+ # Method: <tt>GET /api/orders/:slug/:order_id/</tt>
54
+ #
55
+ # Documentation: http://myfreecomm.github.io/passaporte-web/ecommerce/api/orders.html#detalhes-de-uma-ordem-de-compra
56
+ #
57
+
58
+ def self.find(order_id, slug)
59
+ client.get("/api/orders/#{slug}/#{order_id}/") do |response|
60
+ build_order(response)
61
+ end
62
+ end
63
+
64
+ #
65
+ # Destroys an Order
66
+ #
67
+ # [API]
68
+ # Method: <tt>DELETE /api/orders/:slug/:order_id/</tt>
69
+ #
70
+ # Documentation: http://myfreecomm.github.io/passaporte-web/ecommerce/api/orders.html#delete-api-orders-slug-id
71
+ #
72
+
73
+ def self.destroy(order_id, slug)
74
+ client.delete("/api/orders/#{slug}/#{order_id}/") do |response|
75
+ build_order(response)
76
+ end
77
+ end
78
+
79
+ def destroy
80
+ self.class.destroy(number, plan_slug)
81
+ end
82
+
83
+ private
84
+
85
+ def self.build_order(response)
86
+ order_attributes = parsed_body(response)
87
+ order_attributes.empty? ? {} : self.new(order_attributes)
88
+ end
89
+ end
90
+ end
91
+ end