clearsale 0.1.0

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.
data/.gitignore ADDED
@@ -0,0 +1 @@
1
+ *.sw*
data/.rspec ADDED
@@ -0,0 +1 @@
1
+ --color
data/Gemfile ADDED
@@ -0,0 +1,3 @@
1
+ source "http://rubygems.org"
2
+
3
+ gemspec
data/Gemfile.lock ADDED
@@ -0,0 +1,98 @@
1
+ PATH
2
+ remote: .
3
+ specs:
4
+ clearsale (0.0.1)
5
+ builder
6
+ savon
7
+
8
+ GEM
9
+ remote: http://rubygems.org/
10
+ specs:
11
+ active_support (3.0.0)
12
+ activesupport (= 3.0.0)
13
+ activesupport (3.0.0)
14
+ addressable (2.2.8)
15
+ akami (1.2.0)
16
+ gyoku (>= 0.4.0)
17
+ nokogiri (>= 1.4.0)
18
+ builder (3.0.0)
19
+ columnize (0.3.6)
20
+ crack (0.3.1)
21
+ curb (0.8.1)
22
+ debugger (1.2.0)
23
+ columnize (>= 0.3.1)
24
+ debugger-linecache (~> 1.1.1)
25
+ debugger-ruby_core_source (~> 1.1.3)
26
+ debugger-linecache (1.1.2)
27
+ debugger-ruby_core_source (>= 1.1.1)
28
+ debugger-ruby_core_source (1.1.3)
29
+ diff-lcs (1.1.3)
30
+ ffi (1.0.11)
31
+ guard (1.2.3)
32
+ listen (>= 0.4.2)
33
+ thor (>= 0.14.6)
34
+ guard-bundler (1.0.0)
35
+ bundler (~> 1.0)
36
+ guard (~> 1.1)
37
+ guard-rspec (1.2.0)
38
+ guard (>= 1.1)
39
+ gyoku (0.4.6)
40
+ builder (>= 2.1.2)
41
+ httpi (1.1.1)
42
+ rack
43
+ i18n (0.6.0)
44
+ listen (0.4.7)
45
+ rb-fchange (~> 0.0.5)
46
+ rb-fsevent (~> 0.9.1)
47
+ rb-inotify (~> 0.8.8)
48
+ nokogiri (1.5.5)
49
+ nori (1.1.3)
50
+ rack (1.4.1)
51
+ rake (0.9.2.2)
52
+ rb-fchange (0.0.5)
53
+ ffi
54
+ rb-fsevent (0.9.1)
55
+ rb-inotify (0.8.8)
56
+ ffi (>= 0.5.0)
57
+ rspec (2.10.0)
58
+ rspec-core (~> 2.10.0)
59
+ rspec-expectations (~> 2.10.0)
60
+ rspec-mocks (~> 2.10.0)
61
+ rspec-core (2.10.1)
62
+ rspec-expectations (2.10.0)
63
+ diff-lcs (~> 1.1.3)
64
+ rspec-mocks (2.10.1)
65
+ savon (1.1.0)
66
+ akami (~> 1.2.0)
67
+ builder (>= 2.1.2)
68
+ gyoku (~> 0.4.5)
69
+ httpi (~> 1.1.0)
70
+ nokogiri (>= 1.4.0)
71
+ nori (~> 1.1.0)
72
+ wasabi (~> 2.5.0)
73
+ thor (0.15.4)
74
+ timecop (0.4.1)
75
+ vcr (1.11.3)
76
+ wasabi (2.5.0)
77
+ httpi (~> 1.0)
78
+ nokogiri (>= 1.4.0)
79
+ webmock (1.7.10)
80
+ addressable (~> 2.2, > 2.2.5)
81
+ crack (>= 0.1.7)
82
+
83
+ PLATFORMS
84
+ ruby
85
+
86
+ DEPENDENCIES
87
+ active_support
88
+ clearsale!
89
+ curb
90
+ debugger
91
+ guard-bundler
92
+ guard-rspec
93
+ i18n
94
+ rake
95
+ rspec
96
+ timecop
97
+ vcr (~> 1.11.3)
98
+ webmock (~> 1.7.0)
data/Guardfile ADDED
@@ -0,0 +1,10 @@
1
+ guard 'bundler' do
2
+ watch('Gemfile')
3
+ end
4
+
5
+ guard 'rspec', :version => 2, :bundler => false do
6
+ watch(%r{^spec/(.*)_spec\.rb$})
7
+ watch(%r{^lib/clearsale.rb$}) { "spec" }
8
+ watch(%r{^lib/clearsale/(.*)\.rb$}) { |m| "spec/#{m[1]}_spec.rb" }
9
+ watch('spec/spec_helper.rb') { "spec" }
10
+ end
data/README.rdoc ADDED
@@ -0,0 +1,107 @@
1
+ = Clearsale
2
+
3
+ == Instalação
4
+ Defina a variavél de ambiente CLEARSALE_ENTITYCODE
5
+ export CLEARSALE_ENTITYCODE=03524C82-F434-4A32-8D34-EFFF2023341B
6
+
7
+ Adicione no seu Gemfile
8
+ gem 'clearsale', :github => 'Baby-com-br/clearsale'
9
+
10
+ Execute
11
+ bundle install
12
+
13
+ == Uso
14
+ require 'clearsale'
15
+
16
+ order = {
17
+ :id => 1234,
18
+ :paid_at => 2.seconds.ago,
19
+ :billing_address => {
20
+ :street_name => 'Bla St',
21
+ :number => '123',
22
+ :complement => '',
23
+ :neighborhood => 'Rhode Island',
24
+ :city => 'Mayland',
25
+ :state => 'Maryland',
26
+ :postal_code => '00100-011'
27
+ },
28
+ :shipping_address => {
29
+ :street_name => 'Bla St',
30
+ :number => '123',
31
+ :complement => '',
32
+ :neighborhood => 'Rhode Island',
33
+ :city => 'Mayland',
34
+ :state => 'Maryland',
35
+ :postal_code => '00100-011'
36
+ },
37
+ :installments => 3,
38
+ :total_items => 20.00,
39
+ :total_order => 25.00,
40
+ :items_count => 3,
41
+ :created_at => Time.current,
42
+ :order_items => [
43
+ {
44
+ :product => {
45
+ :id => 5555,
46
+ :name => 'Pogobol',
47
+ :category => { :id => 7777, :name => 'Disney' }
48
+ },
49
+ :price => 5.00,
50
+ :quantity => 2,
51
+ },
52
+ {
53
+ :product => {
54
+ :id => 5555,
55
+ :name => 'Pogobol',
56
+ :category => { :id => 7777, :name => 'Disney' }
57
+ },
58
+ :price => 5.00,
59
+ :quantity => 2,
60
+ },
61
+ ],
62
+ }
63
+
64
+ payment = {
65
+ :card_holder => 'Petter L Griffin',
66
+ :card_number => '1234432111112222',
67
+ :card_expiration => '05/2012',
68
+ :card_security_code => '123',
69
+ :acquirer => 'visa',
70
+ :amount => 50.00,
71
+ }
72
+
73
+ user = {
74
+ :email => 'petergriffin@abc.com',
75
+ :id => 8888,
76
+ :cpf => '248.783.463-37',
77
+ :full_name => 'Peter Löwenbräu Griffin',
78
+ :birthdate => 40.years.ago,
79
+ :phone => '11 8001 1002',
80
+ :gender => 'm',
81
+ :last_sign_in_ip => '127.0.0.1',
82
+ }
83
+
84
+ #Solicitando a analise
85
+ response = Clearsale::Analysis.send_order(order, payment, user)
86
+
87
+ #consultando a analise
88
+ order_id = '1234'
89
+ response = Clearsale::Analysis.get_order_status(order_id)
90
+
91
+ response.order_id
92
+ # => 1234
93
+
94
+ response.score
95
+ # => (0.01..21.11)
96
+
97
+ response.status
98
+ # => :automatic_approval
99
+ # => :manual_approval
100
+ # => :rejected_without_suspicion
101
+ # => :manual_analysis
102
+ # => :error
103
+ # => :waiting
104
+ # => :manual_rejection
105
+ # => :cancelled
106
+ # => :fraud
107
+
data/Rakefile ADDED
@@ -0,0 +1,6 @@
1
+ require 'bundler/gem_tasks'
2
+ require 'rspec/core/rake_task'
3
+
4
+ RSpec::Core::RakeTask.new(:spec)
5
+
6
+ task :default => :spec
data/clearsale.gemspec ADDED
@@ -0,0 +1,34 @@
1
+ # -*- encoding: utf-8 -*-
2
+ $:.push File.expand_path("../lib", __FILE__)
3
+ require "clearsale/version"
4
+
5
+ Gem::Specification.new do |s|
6
+ s.name = "clearsale"
7
+ s.version = Clearsale::VERSION
8
+ s.authors = ["Daniel Konishi"]
9
+ s.email = %w[dkonishi@gmail.com]
10
+ s.homepage = "http://github.com/Baby-com-br/clearsale"
11
+ s.summary = "clearsale gem to use Clearsale service"
12
+ s.description = "clearsale gem to use Clearsale service"
13
+
14
+ s.rubyforge_project = "clearsale"
15
+
16
+ s.files = `git ls-files`.split("\n")
17
+ s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
18
+ s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
19
+ s.require_paths = ["lib"]
20
+ s.add_dependency "builder"
21
+ s.add_dependency "savon"
22
+
23
+ s.add_development_dependency "rake"
24
+ s.add_development_dependency "rspec"
25
+ s.add_development_dependency "webmock", "~> 1.7.0"
26
+ s.add_development_dependency "vcr", "~> 1.11.3"
27
+ s.add_development_dependency "guard-rspec"
28
+ s.add_development_dependency "guard-bundler"
29
+ s.add_development_dependency "debugger"
30
+ s.add_development_dependency "active_support"
31
+ s.add_development_dependency "i18n"
32
+ s.add_development_dependency "curb"
33
+ s.add_development_dependency "timecop"
34
+ end
data/lib/clearsale.rb ADDED
@@ -0,0 +1,11 @@
1
+ require 'active_support/all'
2
+
3
+ module Clearsale
4
+ extend ActiveSupport::Autoload
5
+
6
+ autoload :Object, 'clearsale/object'
7
+ autoload :Order, 'clearsale/order'
8
+ autoload :OrderResponse, 'clearsale/order_response'
9
+ autoload :Connector, 'clearsale/connector'
10
+ autoload :Analysis, 'clearsale/analysis'
11
+ end
@@ -0,0 +1,27 @@
1
+ module Clearsale
2
+ class Analysis
3
+ def self.connector
4
+ @connector ||= Clearsale::Connector.build
5
+ end
6
+
7
+ def self.send_order(order_hash, payment_hash, user_hash)
8
+ order = Object.new(order_hash)
9
+ payment = Object.new(payment_hash)
10
+ user = Object.new(user_hash)
11
+
12
+ order_xml = Clearsale::Order.to_xml(order, payment, user)
13
+ request = {"xml" => order_xml}
14
+
15
+ OrderResponse.build_from_send_order(connector.do_request('SendOrders', request))
16
+ end
17
+
18
+ def self.clear_connector
19
+ @connector = nil
20
+ end
21
+
22
+ def self.get_order_status(order_id)
23
+ request = {'orderID' => order_id}
24
+ OrderResponse.build_from_update(connector.do_request('GetOrderStatus', request))
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,63 @@
1
+ require 'savon'
2
+ require 'nori'
3
+
4
+ Nori.parser = :nokogiri
5
+
6
+ module Clearsale
7
+ class Connector
8
+ NAMESPACE = "http://www.clearsale.com.br/integration"
9
+
10
+ URLs = {
11
+ :homolog => 'http://homologacao.clearsale.com.br/Integracaov2/Service.asmx',
12
+ :production => 'https://www.clearsale.com.br/integracaov2/service.asmx'
13
+ }
14
+
15
+ def self.build(env = ENV['CLEARSALE_ENV'])
16
+ if env == "production"
17
+ new(URLs[:production])
18
+ else
19
+ new(URLs[:homolog])
20
+ end
21
+ end
22
+
23
+ def initialize(endpoint_url)
24
+ @token = ENV['CLEARSALE_ENTITYCODE']
25
+ @client = Savon::Client.new do |wsdl|
26
+ wsdl.endpoint = endpoint_url
27
+ wsdl.namespace = NAMESPACE
28
+ end
29
+ end
30
+
31
+ def do_request(method, request)
32
+ namespaced_request = append_namespace('int', request)
33
+ arguments = namespaced_request.merge({'int:entityCode' => @token})
34
+
35
+ response = @client.request(:int, method) do |soap, _, http, _|
36
+ soap.namespaces = {
37
+ 'xmlns:soap' => "http://www.w3.org/2003/05/soap-envelope",
38
+ 'xmlns:xsd' => "http://www.w3.org/2001/XMLSchema" ,
39
+ 'xmlns:xsi' => "http://www.w3.org/2001/XMLSchema-instance" ,
40
+ 'xmlns:int' => "http://www.clearsale.com.br/integration",
41
+ }
42
+
43
+ soap.env_namespace = :soap
44
+
45
+ soap.body = arguments
46
+ http.headers['SOAPAction'] = "#{NAMESPACE}/#{method}"
47
+ end
48
+
49
+ extract_response_xml(method, response.to_hash)
50
+ end
51
+
52
+ def extract_response_xml(method, response)
53
+ results = response.fetch(:"#{method.snakecase}_response", {})
54
+ response_xml = results.fetch(:"#{method.snakecase}_result", {}).to_s
55
+
56
+ Nori.parse(response_xml.gsub(/^<\?xml.*\?>/, ''))
57
+ end
58
+
59
+ def append_namespace(namespace, hash)
60
+ Hash[hash.map {|key, value| ["#{namespace}:#{key}", value]}]
61
+ end
62
+ end
63
+ end
@@ -0,0 +1,27 @@
1
+ require 'ostruct'
2
+
3
+ module Clearsale
4
+ class Object < OpenStruct
5
+ def new_ostruct_member(name)
6
+ name = name.to_sym
7
+ unless self.respond_to?(name)
8
+ class << self; self; end.class_eval do
9
+ define_method(name) {
10
+ v = @table[name]
11
+ case v
12
+ when Hash
13
+ Object.new(v)
14
+ when Array
15
+ v.each_with_index { |item, index| v[index] = Object.new(item) }
16
+ else
17
+ v
18
+ end
19
+ }
20
+ define_method("#{name}=") { |x| modifiable[name] = x }
21
+ define_method("#{name}_as_a_hash") { @table[name] }
22
+ end
23
+ end
24
+ name
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,122 @@
1
+ require 'builder'
2
+ require 'ostruct'
3
+
4
+ module Clearsale
5
+ class Order
6
+ CARD_TYPE_MAP = {
7
+ :visa => 3,
8
+ :mastercard => 2,
9
+ :amex => 5,
10
+ }
11
+ def self.to_xml(order, payment, user)
12
+ builder = Builder::XmlMarkup.new
13
+ xml = builder.tag!("ClearSale") do |b|
14
+ b.tag!('Orders') do |b|
15
+ b.tag!('Order') do |b|
16
+ build_order(b, order, payment, user)
17
+ end
18
+ end
19
+ end.to_s
20
+ xml
21
+ end
22
+
23
+ def self.build_order(builder, order, payment, user)
24
+ builder.tag!('ID', order.id)
25
+ builder.tag!('Date', order.created_at.strftime("%Y-%m-%dT%H:%M:%S"))
26
+ builder.tag!('Email', user.email)
27
+ builder.tag!('TotalItens', order.total_items)
28
+ builder.tag!('TotalOrder', order.total_order)
29
+ builder.tag!('QtyInstallments', order.installments)
30
+ builder.tag!('QtyItems', order.items_count)
31
+ builder.tag!('IP', user.last_sign_in_ip)
32
+ builder.tag!('CollectionData') do |b|
33
+ build_user_data(b, user, order.billing_address)
34
+ end
35
+ builder.tag!('ShippingData') do |b|
36
+ build_user_data(b, user, order.shipping_address)
37
+ end
38
+
39
+ builder.tag!('Payments') do |b|
40
+ build_payment_data(b, order, payment, user)
41
+ end
42
+
43
+ builder.tag!('Items') do |b|
44
+ order.order_items.each do |order_item|
45
+ build_item(b, order_item)
46
+ end
47
+ end
48
+ end
49
+
50
+ def self.build_user_data(builder, user, billing_address)
51
+ builder.tag!('ID', user.id)
52
+ builder.tag!('Type', 1) # Pessoa Física
53
+ builder.tag!('LegalDocument1', user.cpf.gsub(/[\.\-]*/, '').strip)
54
+ builder.tag!('Name', user.full_name)
55
+ builder.tag!('BirthDate', user.birthdate.to_time.strftime("%Y-%m-%dT%H:%M:%S"))
56
+ builder.tag!('Email', user.email)
57
+ builder.tag!('Genre', user.gender.downcase)
58
+ build_address(builder, billing_address)
59
+ builder.tag!('Phones') do |b|
60
+ build_phone(b, user)
61
+ end
62
+ end
63
+
64
+ def self.build_address(builder, address)
65
+ builder.tag!('Address') do |b|
66
+ builder.tag!('Street', address.street_name)
67
+ builder.tag!('Number', address.number)
68
+ builder.tag!('Comp', address.complement)
69
+ builder.tag!('County', address.neighborhood)
70
+ builder.tag!('City', address.city)
71
+ builder.tag!('State', address.state)
72
+ builder.tag!('ZipCode', address.postal_code)
73
+ end
74
+ end
75
+
76
+ def self.build_phone(builder, user)
77
+ if user.phone.present?
78
+ stripped_phone = user.phone.gsub(/\(*\)*\s*\-*/, '')
79
+
80
+ builder.tag!('Phone') do |b|
81
+ b.tag!('Type', 0) # Undefined
82
+ b.tag!('DDD', stripped_phone[0..1])
83
+ b.tag!('Number', stripped_phone[2..-1])
84
+ end
85
+ end
86
+ end
87
+
88
+ def self.build_payment_data(builder, order, payment, user)
89
+ builder.tag!('Payment') do |b|
90
+ paid_at = order.paid_at || Time.current
91
+
92
+ b.tag!('Date', paid_at.strftime("%Y-%m-%dT%H:%M:%S"))
93
+ b.tag!('Amount', payment.amount)
94
+
95
+ #is_credit_card
96
+ b.tag!('PaymentTypeID', 1)
97
+
98
+ b.tag!('QtyInstallments', order.installments)
99
+
100
+ b.tag!('CardNumber', payment.card_number)
101
+ b.tag!('CardBin', payment.card_number[0..5])
102
+ b.tag!('CardType', CARD_TYPE_MAP.fetch(payment.acquirer, 4)) # Failover is 'outros'
103
+ b.tag!('CardExpirationDate', payment.card_expiration)
104
+ b.tag!('Name', payment.customer_name)
105
+ b.tag!('LegalDocument', user.cpf.gsub(/[\.\-]*/, '').strip)
106
+
107
+ build_address(b, order.billing_address)
108
+ end
109
+ end
110
+
111
+ def self.build_item(builder, order_item)
112
+ builder.tag!('Item') do |b|
113
+ b.tag!('ID', order_item.product.id)
114
+ b.tag!('Name', order_item.product.name)
115
+ b.tag!('ItemValue', order_item.price)
116
+ b.tag!('Qty', order_item.quantity)
117
+ b.tag!('CategoryID', order_item.product.category.id) if order_item.product.category.try(:id).present?
118
+ b.tag!('CategoryName', order_item.product.category.name) if order_item.product.category.try(:name).present?
119
+ end
120
+ end
121
+ end
122
+ end