tray-checkout 0.0.0 → 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
data/CHANGELOG.rdoc CHANGED
@@ -1,2 +1,5 @@
1
+ == Version 0.0.1
2
+ - First stable version.
3
+
1
4
  == Version 0.0.0
2
5
  - First version, unstable yet.
data/README.rdoc CHANGED
@@ -7,6 +7,7 @@ Tray Checkout API
7
7
  === Gemfile
8
8
  gem 'tray-checkout'
9
9
 
10
+
10
11
  === Direct installation
11
12
  $ gem install tray-checkout
12
13
 
@@ -15,7 +16,91 @@ Tray Checkout API
15
16
 
16
17
  require 'tray-checkout'
17
18
 
18
- t = Tray::Checkout::Transaction.new
19
+ transaction = Tray::Checkout::Transaction.new
20
+
21
+ Getting an existing transaction:
22
+ txn = transaction.get("522045453u5uu32e0u8014f060uuu5uu")
23
+ txn[:success] # => true
24
+ txn[:transaction_token] # => "522045453u5uu32e0u8014f060uuu5uu"
25
+ txn[:transaction_id] # => 501
26
+ txn[:status] # => :waiting_payment
27
+ txn[:payment_method] # => :boleto
28
+ txn[:price_payment] # => 213.21
29
+ txn[:price_seller] # => 199.19
30
+ txn[:split] # => 1
31
+ txn[:payment][:url_payment] # => "http://checkout.sandbox.tray.com.br/payment/billet/u9uuu8731319u59u3073u9011uu6u6uu"
32
+ txn[:date_transaction].strftime("%d/%m/%Y") # => "03/12/2012"
33
+
34
+ When the transaction is not found:
35
+ txn = transaction.get("xxxxx00000yyyy")
36
+ txn[:success] # => false
37
+ txn[:transaction_id] # => nil
38
+ txn[:errors].first[:code] # => "003042"
39
+ txn[:errors].first[:message] # => "Transação não encontrada"
40
+
41
+ Creating a successful transaction:
42
+ txn = transaction.create(
43
+ token_account: "949u5uu9ef36f7u",
44
+ customer: {
45
+ name: "Pedro Bonamides",
46
+ cpf: "18565842673",
47
+ email: "pedro@bo.com.br",
48
+ sex: :male,
49
+ marital_status: :single,
50
+ contacts: [
51
+ { contact_type: :home,
52
+ number_contact: "1142360873"
53
+ }
54
+ ],
55
+ addresses: [
56
+ { address_type: :billing,
57
+ street: "Avenida Pedro Alvares Cabral",
58
+ number: "123",
59
+ neighborhood: "Parque Ibirapuera",
60
+ postal_code: "04094050",
61
+ city: "São Paulo",
62
+ state: "SP"
63
+ }
64
+ ]
65
+ },
66
+ transaction: {
67
+ order_number: "R1245",
68
+ shipping_type: "Sedex",
69
+ shipping_price: 13.94,
70
+ url_notification: "http://prodis.blog.br/tray_notification"
71
+ },
72
+ transaction_product: [
73
+ { code: "LOGO-8278",
74
+ quantity: 2,
75
+ price_unit: 100.99,
76
+ description: "Logo Prodis"
77
+ },
78
+ { code: "877",
79
+ quantity: 1,
80
+ price_unit: 10.00,
81
+ description: "Outro produto"
82
+ }
83
+ ],
84
+ payment: {
85
+ payment_method: :mastercard,
86
+ split: 3,
87
+ card_name: "ZEFINHA NOCEGA",
88
+ card_number: "5105105105105100",
89
+ card_expdate_month: "09",
90
+ card_expdate_year: "2015",
91
+ card_cvv: "123"
92
+ }
93
+ )
94
+ txn[:success] # => true
95
+ txn[:transaction_token] # => "87654321u5uu92e4u09876543uuu5uu"
96
+ txn[:transaction_id] # => 503
97
+ txn[:status] # => :approved
98
+ txn[:status_name] # => "Aprovada"
99
+ txn[:payment_method] # => :mastercard
100
+ txn[:payment_method_name] # => "Mastercard"
101
+ txn[:price_payment] # => 213.21
102
+ txn[:price_seller] # => 199.19
103
+ txn[:date_payment].strftime("%d/%m/%Y") # => "05/12/2012"
19
104
 
20
105
 
21
106
  == Author
@@ -0,0 +1,53 @@
1
+ # encoding: UTF-8
2
+
3
+ module Tray
4
+ module Checkout
5
+ PAYMENT_METHOD = {
6
+ diners: 2,
7
+ visa: 3,
8
+ mastercard: 4,
9
+ american_express: 5,
10
+ boleto: 6,
11
+ itau_shopline: 7,
12
+ pagamento_com_saldo: 8,
13
+ peela: 14,
14
+ discover: 15,
15
+ elo: 16
16
+ }
17
+
18
+ TRANSACTION_STATUS = {
19
+ waiting_payment: 4,
20
+ processing: 5,
21
+ approved: 6,
22
+ canceled: 7,
23
+ disputing: 24,
24
+ monitoring: 87,
25
+ recovering: 88,
26
+ disapproved: 89
27
+ }
28
+
29
+ CONTACT_TYPE = {
30
+ home: "H",
31
+ mobile: "M",
32
+ work: "W"
33
+ }
34
+
35
+ ADDRESS_TYPE = {
36
+ billing: "B",
37
+ delivery: "D"
38
+ }
39
+
40
+ SEX = {
41
+ male: "M",
42
+ female: "F"
43
+ }
44
+
45
+ MARITAL_STATUS = {
46
+ single: "S",
47
+ married: "M",
48
+ separated: "A",
49
+ divorced: "D",
50
+ widowed: "W"
51
+ }
52
+ end
53
+ end
@@ -0,0 +1,22 @@
1
+ # encoding: UTF-8
2
+ class Hash
3
+ def symbolize_all_keys!
4
+ symbolize_all_keys_in self
5
+ end
6
+
7
+ private
8
+
9
+ def symbolize_all_keys_in(hash)
10
+ case
11
+ when hash.is_a?(Array)
12
+ hash.each { |value| symbolize_all_keys_in(value) }
13
+ when hash.is_a?(Hash)
14
+ hash.symbolize_keys!
15
+
16
+ hash.each_value do |value|
17
+ value.symbolize_keys! if value.is_a?(Hash)
18
+ symbolize_all_keys_in(value)
19
+ end
20
+ end
21
+ end
22
+ end
@@ -5,48 +5,94 @@ module Tray
5
5
  module Checkout
6
6
  class Parser
7
7
  def response(xml)
8
- puts xml
9
- hash = convert_to_hash(xml)
10
- success?(hash) ? data(hash) : errors(hash)
8
+ create_response_from(xml)
9
+ success? ? data : errors
10
+ end
11
+
12
+ def payment_params!(params)
13
+ customer_params_types! params[:customer]
14
+ payment_params_types! params[:payment]
15
+
16
+ params
11
17
  end
12
18
 
13
19
  private
14
20
 
15
- def convert_to_hash(xml)
16
- symbolize_all_keys!(Hash.from_xml(xml))[:transaction]
21
+ def customer_params_types!(customer)
22
+ return unless customer
23
+ customer[:gender] = SEX[customer[:sex]] if customer[:sex]
24
+ customer[:relationship] = MARITAL_STATUS[customer[:marital_status]] if customer[:marital_status]
25
+ contacts_params_types! customer[:contacts]
26
+ addresses_params_types! customer[:addresses]
17
27
  end
18
28
 
19
- def success?(hash)
20
- hash[:message_response][:message] == "success"
29
+ def payment_params_types!(payment)
30
+ return unless payment
31
+ payment[:payment_method_id] = PAYMENT_METHOD[payment[:payment_method]] if payment[:payment_method]
32
+ end
33
+
34
+ def contacts_params_types!(contacts)
35
+ return unless contacts
36
+
37
+ contacts.each do |contact|
38
+ contact[:type_contact] = CONTACT_TYPE[contact[:contact_type]] if contact[:contact_type]
39
+ end
21
40
  end
22
41
 
23
- def data(hash)
24
- hash[:data_response]
42
+ def addresses_params_types!(addresses)
43
+ return unless addresses
44
+
45
+ addresses.each do |address|
46
+ address[:type_address] = ADDRESS_TYPE[address[:address_type]] if address[:address_type]
47
+ end
25
48
  end
26
49
 
27
- def errors(hash)
28
- hash[:error_response]
50
+ def create_response_from(xml)
51
+ @response = Hash.from_xml(xml).symbolize_all_keys![:transaction]
29
52
  end
30
53
 
31
- def symbolize_all_keys!(hash)
32
- #TODO: Move to Hash class.
33
- case
34
- when hash.is_a?(Array)
35
- puts "### Array #{hash}"
36
- puts
37
- hash.each { |value| symbolize_all_keys!(value) }
38
- when hash.is_a?(Hash)
39
- puts "$$$ Hash: #{hash}"
40
- puts
41
- hash.symbolize_keys!
54
+ def success?
55
+ @response[:message_response][:message] == "success"
56
+ end
42
57
 
43
- hash.each_value do |value|
44
- value.symbolize_keys! if value.is_a?(Hash)
45
- symbolize_all_keys!(value)
46
- end
58
+ def data
59
+ data_response = @response[:data_response][:transaction]
60
+ transaction_response_types! data_response
61
+ payment_response_types! data_response
62
+ date_to_time! data_response
63
+ data_response[:success] = true
64
+ data_response
65
+ end
66
+
67
+ def transaction_response_types!(transaction)
68
+ transaction[:payment_method] = PAYMENT_METHOD.invert[transaction[:payment_method_id]]
69
+ transaction[:status] = TRANSACTION_STATUS.invert[transaction[:status_id]]
70
+ end
71
+
72
+ def payment_response_types!(transaction)
73
+ payment = transaction[:payment]
74
+ payment[:payment_method] = PAYMENT_METHOD.invert[payment[:payment_method_id]]
75
+ end
76
+
77
+ def errors
78
+ error_response = @response[:error_response]
79
+
80
+ if error_response[:validation_errors]
81
+ error_response[:errors] = error_response.delete(:validation_errors)
47
82
  end
48
83
 
49
- hash
84
+ error_response[:success] = false
85
+ error_response
86
+ end
87
+
88
+ def date_to_time!(hash)
89
+ hash.each do |key, value|
90
+ date_to_time!(value) if value.is_a?(Hash)
91
+
92
+ if key.to_s.starts_with?("date_") && value
93
+ hash[key] = (value.to_time rescue value) || value
94
+ end
95
+ end
50
96
  end
51
97
  end
52
98
  end
@@ -6,8 +6,12 @@ module Tray
6
6
 
7
7
  def get(token)
8
8
  response = web_service.request!("#{URL}/get_by_token", { token: token })
9
- result = parser.response(response)
10
- result
9
+ parser.response(response)
10
+ end
11
+
12
+ def create(params)
13
+ response = web_service.request!("#{URL}/pay_complete", parser.payment_params!(params))
14
+ parser.response(response)
11
15
  end
12
16
 
13
17
  private
@@ -1,7 +1,7 @@
1
1
  # encoding: UTF-8
2
2
  module Tray
3
3
  module Checkout
4
- VERSION = "0.0.0"
4
+ VERSION = "0.0.1"
5
5
  end
6
6
  end
7
7
 
@@ -1,4 +1,5 @@
1
1
  # encoding: UTF-8
2
+ require 'active_support/core_ext'
2
3
  require 'net/http'
3
4
  require 'uri'
4
5
 
@@ -24,7 +25,7 @@ module Tray
24
25
 
25
26
  def build_request(uri, params)
26
27
  request = Net::HTTP::Post.new(uri.path)
27
- request.set_form_data(params)
28
+ request.body = params.to_param
28
29
  request
29
30
  end
30
31
  end
data/lib/tray-checkout.rb CHANGED
@@ -1,6 +1,8 @@
1
1
  # encoding: UTF-8
2
2
  require 'rubygems'
3
3
  require 'tray/checkout'
4
+ require 'tray/checkout/constants'
5
+ require 'tray/checkout/hash'
4
6
  require 'tray/checkout/parser'
5
7
  require 'tray/checkout/transaction'
6
8
  require 'tray/checkout/web_service'
@@ -0,0 +1,23 @@
1
+ # encoding: UTF-8
2
+
3
+ def mock_request_for(response)
4
+ url = Regexp.new(Tray::Checkout::Transaction::URL)
5
+ WebMock::API.stub_request(:post, url).to_return(:status => 200, :body => body_for(response))
6
+ end
7
+
8
+ def body_for(response)
9
+ case response
10
+ when :get_success_boleto,
11
+ :get_failure_not_found,
12
+ :create_success_boleto,
13
+ :create_success_mastercard,
14
+ :create_failure_validation_errors
15
+ read_file_for(response)
16
+ else
17
+ response
18
+ end
19
+ end
20
+
21
+ def read_file_for(filename)
22
+ File.open("#{File.dirname(__FILE__)}/responses/#{filename}.xml").read
23
+ end
@@ -0,0 +1,51 @@
1
+ <transaction>
2
+ <message_response>
3
+ <message>error</message>
4
+ </message_response>
5
+ <error_response>
6
+ <validation_errors type="array">
7
+ <validation_error>
8
+ <code>1</code>
9
+ <message_complete>Tipo n&#227;o pode ficar em branco</message_complete>
10
+ <message>n&#227;o pode ficar em branco</message>
11
+ <field>person_addresses.type_address</field>
12
+ </validation_error>
13
+ <validation_error>
14
+ <code>1</code>
15
+ <message_complete>Logradouro (Rua, Av, Travessa...) n&#227;o pode ficar em branco</message_complete>
16
+ <message>n&#227;o pode ficar em branco</message>
17
+ <field>person_addresses.street</field>
18
+ </validation_error>
19
+ <validation_error>
20
+ <code>1</code>
21
+ <message_complete>Cep n&#227;o pode ficar em branco</message_complete>
22
+ <message>n&#227;o pode ficar em branco</message>
23
+ <field>person_addresses.postal_code</field>
24
+ </validation_error>
25
+ <validation_error>
26
+ <code>1</code>
27
+ <message_complete>Cidade n&#227;o pode ficar em branco</message_complete>
28
+ <message>n&#227;o pode ficar em branco</message>
29
+ <field>person_addresses.city</field>
30
+ </validation_error>
31
+ <validation_error>
32
+ <code>1</code>
33
+ <message_complete>UF n&#227;o pode ficar em branco</message_complete>
34
+ <message>n&#227;o pode ficar em branco</message>
35
+ <field>person_addresses.state</field>
36
+ </validation_error>
37
+ <validation_error>
38
+ <code>1</code>
39
+ <message_complete>N&#250;mero, Lote n&#227;o pode ficar em branco</message_complete>
40
+ <message>n&#227;o pode ficar em branco</message>
41
+ <field>person_addresses.number</field>
42
+ </validation_error>
43
+ <validation_error>
44
+ <code>1</code>
45
+ <message_complete>Bairro n&#227;o pode ficar em branco</message_complete>
46
+ <message>n&#227;o pode ficar em branco</message>
47
+ <field>person_addresses.neighborhood</field>
48
+ </validation_error>
49
+ </validation_errors>
50
+ </error_response>
51
+ </transaction>