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