tray-checkout 0.0.1 → 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/CHANGELOG.rdoc +4 -0
- data/README.rdoc +77 -49
- data/lib/tray/checkout/hash.rb +9 -15
- data/lib/tray/checkout/parser.rb +5 -88
- data/lib/tray/checkout/response.rb +19 -0
- data/lib/tray/checkout/response_parser.rb +114 -0
- data/lib/tray/checkout/transaction.rb +9 -5
- data/lib/tray/checkout/transaction_params_parser.rb +55 -0
- data/lib/tray/checkout/version.rb +1 -1
- data/lib/tray-checkout.rb +3 -0
- data/spec/support/mock_request.rb +1 -0
- data/spec/support/responses/create_failure_validation_errors.xml +1 -0
- data/spec/support/responses/create_success_boleto.xml +53 -236
- data/spec/support/responses/create_success_mastercard.xml +53 -224
- data/spec/support/responses/get_success_boleto.xml +56 -66
- data/spec/support/responses/get_success_mastercard.xml +101 -0
- data/spec/tray/checkout/hash_spec.rb +10 -9
- data/spec/tray/checkout/parser_spec.rb +29 -179
- data/spec/tray/checkout/response_parser_spec.rb +187 -0
- data/spec/tray/checkout/response_spec.rb +16 -0
- data/spec/tray/checkout/transaction_params_parser_spec.rb +126 -0
- data/spec/tray/checkout/transaction_spec.rb +34 -20
- metadata +24 -13
data/CHANGELOG.rdoc
CHANGED
data/README.rdoc
CHANGED
@@ -19,28 +19,41 @@ Tray Checkout API
|
|
19
19
|
transaction = Tray::Checkout::Transaction.new
|
20
20
|
|
21
21
|
Getting an existing transaction:
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
22
|
+
response = transaction.get("522045453u5uu32e0u8014f060uuu5uu")
|
23
|
+
response.success? # => true
|
24
|
+
|
25
|
+
# Transaction
|
26
|
+
response.transaction[:token] # => "522045453u5uu32e0u8014f060uuu5uu"
|
27
|
+
response.transaction[:id] # => 501
|
28
|
+
response.transaction[:status] # => :waiting_payment
|
29
|
+
response.transaction[:status_name] # => "Aguardando Pagamento"
|
30
|
+
response.transaction[:price_payment] # => 213.21
|
31
|
+
response.transaction[:price_seller] # => 199.19
|
32
|
+
response.transaction[:split] # => 1
|
33
|
+
response.transaction[:date_transaction].strftime("%d/%m/%Y") # => "03/12/2012"
|
34
|
+
|
35
|
+
# Payment
|
36
|
+
response.payment[:method] # => :boleto
|
37
|
+
response.payment[:method_name] # => "Boleto Bancario"
|
38
|
+
response.payment[:price] # => 213.21
|
39
|
+
response.payment[:split] # => 1
|
40
|
+
response.payment[:url] # => "http://checkout.sandbox.tray.com.br/payment/billet/u9uuu8731319u59u3073u9011uu6u6uu"
|
41
|
+
|
42
|
+
# Customer
|
43
|
+
response.customer[:name] # => "Pedro Bonamides"
|
44
|
+
response.customer[:email] # => "pedro@bo.com.br"
|
45
|
+
response.customer[:cpf] # => "18565842673"
|
33
46
|
|
34
47
|
When the transaction is not found:
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
48
|
+
response = transaction.get("xxxxx00000yyyy")
|
49
|
+
response.success? # => false
|
50
|
+
response.transaction[:id] # => nil
|
51
|
+
response[:errors].first[:code] # => "003042"
|
52
|
+
response[:errors].first[:message] # => "Transação não encontrada"
|
40
53
|
|
41
54
|
Creating a successful transaction:
|
42
|
-
|
43
|
-
token_account: "
|
55
|
+
response = transaction.create(
|
56
|
+
token_account: "123u5uu9ef36f7u",
|
44
57
|
customer: {
|
45
58
|
name: "Pedro Bonamides",
|
46
59
|
cpf: "18565842673",
|
@@ -48,12 +61,12 @@ Creating a successful transaction:
|
|
48
61
|
sex: :male,
|
49
62
|
marital_status: :single,
|
50
63
|
contacts: [
|
51
|
-
{
|
52
|
-
|
64
|
+
{ type: :home,
|
65
|
+
number: "1142360873"
|
53
66
|
}
|
54
67
|
],
|
55
68
|
addresses: [
|
56
|
-
{
|
69
|
+
{ type: :billing,
|
57
70
|
street: "Avenida Pedro Alvares Cabral",
|
58
71
|
number: "123",
|
59
72
|
neighborhood: "Parque Ibirapuera",
|
@@ -68,39 +81,54 @@ Creating a successful transaction:
|
|
68
81
|
shipping_type: "Sedex",
|
69
82
|
shipping_price: 13.94,
|
70
83
|
url_notification: "http://prodis.blog.br/tray_notification"
|
84
|
+
products: [
|
85
|
+
{ code: "LOGO-8278",
|
86
|
+
quantity: 2,
|
87
|
+
price_unit: 100.99,
|
88
|
+
description: "Logo Prodis"
|
89
|
+
},
|
90
|
+
{ code: "877",
|
91
|
+
quantity: 1,
|
92
|
+
price_unit: 10.00,
|
93
|
+
description: "Outro produto"
|
94
|
+
}
|
95
|
+
]
|
71
96
|
},
|
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
97
|
payment: {
|
85
|
-
|
98
|
+
method: :mastercard,
|
86
99
|
split: 3,
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
100
|
+
card: {
|
101
|
+
name: "ZEFINHA NOCEGA",
|
102
|
+
number: "5105105105105100",
|
103
|
+
expdate_month: "09",
|
104
|
+
expdate_year: "2015",
|
105
|
+
cvv: "123"
|
106
|
+
}
|
92
107
|
}
|
93
108
|
)
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
109
|
+
response.success? # => true
|
110
|
+
|
111
|
+
# Transaction
|
112
|
+
response.transaction[:token] # => "87654321u5uu92e4u09876543uuu5uu"
|
113
|
+
response.transaction[:id] # => 503
|
114
|
+
response.transaction[:status] # => :approved
|
115
|
+
response.transaction[:status_name] # => "Aprovada"
|
116
|
+
response.transaction[:price_payment] # => 213.21
|
117
|
+
response.transaction[:price_seller] # => 199.19
|
118
|
+
response.transaction[:split] # => 3
|
119
|
+
response.transaction[:date_transaction].strftime("%d/%m/%Y") # => "05/12/2012"
|
120
|
+
|
121
|
+
# Payment
|
122
|
+
response.payment[:method] # => :mastercard
|
123
|
+
response.payment[:method_name] # => "Mastercard"
|
124
|
+
response.payment[:price] # => 213.21
|
125
|
+
response.payment[:split] # => 3
|
126
|
+
response.payment[:url] # => "http://checkout.sandbox.tray.com.br/payment/billet/u9uuu8731319u59u3073u9011uu6u6uu"
|
127
|
+
|
128
|
+
# Customer
|
129
|
+
response.customer[:name] # => "Pedro Bonamides"
|
130
|
+
response.customer[:email] # => "pedro@bo.com.br"
|
131
|
+
response.customer[:cpf] # => "18565842673"
|
104
132
|
|
105
133
|
|
106
134
|
== Author
|
data/lib/tray/checkout/hash.rb
CHANGED
@@ -1,21 +1,15 @@
|
|
1
1
|
# encoding: UTF-8
|
2
2
|
class Hash
|
3
|
-
def symbolize_all_keys
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
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!
|
3
|
+
def symbolize_all_keys
|
4
|
+
{}.tap do |results|
|
5
|
+
self.each do |key, value|
|
6
|
+
if value.is_a?(Array)
|
7
|
+
symbolized_value = value.map { |item| item.is_a?(Hash) ? item.symbolize_all_keys : item }
|
8
|
+
else
|
9
|
+
symbolized_value = value.is_a?(Hash) ? value.symbolize_all_keys : value
|
10
|
+
end
|
15
11
|
|
16
|
-
|
17
|
-
value.symbolize_keys! if value.is_a?(Hash)
|
18
|
-
symbolize_all_keys_in(value)
|
12
|
+
results[(key.to_sym rescue key)] = symbolized_value
|
19
13
|
end
|
20
14
|
end
|
21
15
|
end
|
data/lib/tray/checkout/parser.rb
CHANGED
@@ -1,98 +1,15 @@
|
|
1
1
|
# encoding: UTF-8
|
2
|
-
require 'active_support/core_ext'
|
3
|
-
|
4
2
|
module Tray
|
5
3
|
module Checkout
|
6
4
|
class Parser
|
7
5
|
def response(xml)
|
8
|
-
|
9
|
-
|
10
|
-
end
|
11
|
-
|
12
|
-
def payment_params!(params)
|
13
|
-
customer_params_types! params[:customer]
|
14
|
-
payment_params_types! params[:payment]
|
15
|
-
|
16
|
-
params
|
17
|
-
end
|
18
|
-
|
19
|
-
private
|
20
|
-
|
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]
|
27
|
-
end
|
28
|
-
|
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
|
40
|
-
end
|
41
|
-
|
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
|
6
|
+
response_parser = ResponseParser.new(xml)
|
7
|
+
response_parser.parse
|
48
8
|
end
|
49
9
|
|
50
|
-
def
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
def success?
|
55
|
-
@response[:message_response][:message] == "success"
|
56
|
-
end
|
57
|
-
|
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)
|
82
|
-
end
|
83
|
-
|
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
|
10
|
+
def transaction_params(params)
|
11
|
+
transaction_params_parser = Tray::Checkout::TransactionParamsParser.new(params)
|
12
|
+
transaction_params_parser.parse
|
96
13
|
end
|
97
14
|
end
|
98
15
|
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
# encoding: UTF-8
|
2
|
+
module Tray
|
3
|
+
module Checkout
|
4
|
+
class Response
|
5
|
+
attr_accessor :transaction,
|
6
|
+
:payment,
|
7
|
+
:customer,
|
8
|
+
:success,
|
9
|
+
:errors
|
10
|
+
|
11
|
+
alias :success? :success
|
12
|
+
|
13
|
+
def initialize
|
14
|
+
@success = false
|
15
|
+
@errors = []
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,114 @@
|
|
1
|
+
# encoding: UTF-8
|
2
|
+
require 'active_support/core_ext'
|
3
|
+
|
4
|
+
module Tray
|
5
|
+
module Checkout
|
6
|
+
class ResponseParser
|
7
|
+
def initialize(xml)
|
8
|
+
@xml = xml
|
9
|
+
end
|
10
|
+
|
11
|
+
def parse
|
12
|
+
response = Response.new
|
13
|
+
response.success = success?
|
14
|
+
|
15
|
+
if response.success?
|
16
|
+
response.transaction = transaction
|
17
|
+
response.payment = payment
|
18
|
+
response.customer = customer
|
19
|
+
else
|
20
|
+
response.errors = errors
|
21
|
+
end
|
22
|
+
|
23
|
+
response
|
24
|
+
end
|
25
|
+
|
26
|
+
private
|
27
|
+
|
28
|
+
def response_hash
|
29
|
+
@response_hash ||= create_response_hash
|
30
|
+
end
|
31
|
+
|
32
|
+
def create_response_hash
|
33
|
+
Hash.from_xml(@xml).symbolize_all_keys[:transaction]
|
34
|
+
end
|
35
|
+
|
36
|
+
def success?
|
37
|
+
response_hash[:message_response][:message] == "success"
|
38
|
+
end
|
39
|
+
|
40
|
+
def transaction
|
41
|
+
data_clone = data.clone
|
42
|
+
data_clone.delete(:payment)
|
43
|
+
data_clone.delete(:customer)
|
44
|
+
data_clone
|
45
|
+
end
|
46
|
+
|
47
|
+
def payment
|
48
|
+
data[:payment]
|
49
|
+
end
|
50
|
+
|
51
|
+
def customer
|
52
|
+
data[:customer]
|
53
|
+
end
|
54
|
+
|
55
|
+
def data
|
56
|
+
@data ||= create_data_response
|
57
|
+
end
|
58
|
+
|
59
|
+
def create_data_response
|
60
|
+
data_response = response_hash[:data_response][:transaction]
|
61
|
+
transaction_map! data_response
|
62
|
+
payment_map! data_response
|
63
|
+
customer_map! data_response
|
64
|
+
date_to_time! data_response
|
65
|
+
data_response
|
66
|
+
end
|
67
|
+
|
68
|
+
def transaction_map!(transaction)
|
69
|
+
transaction[:status] = TRANSACTION_STATUS.invert[transaction.delete(:status_id)]
|
70
|
+
transaction[:id] = transaction.delete(:transaction_id)
|
71
|
+
transaction[:token] = transaction.delete(:transaction_token)
|
72
|
+
transaction[:affiliates] = transaction.delete(:transaction_affiliates)
|
73
|
+
end
|
74
|
+
|
75
|
+
def payment_map!(transaction)
|
76
|
+
payment = transaction[:payment]
|
77
|
+
payment[:method] = PAYMENT_METHOD.invert[payment.delete(:payment_method_id)]
|
78
|
+
payment[:method_name] = payment.delete(:payment_method_name)
|
79
|
+
payment[:price] = payment.delete(:price_payment)
|
80
|
+
payment[:response] = payment.delete(:payment_response)
|
81
|
+
payment[:url] = payment.delete(:url_payment)
|
82
|
+
end
|
83
|
+
|
84
|
+
def customer_map!(transaction)
|
85
|
+
customer = transaction[:customer]
|
86
|
+
customer[:contacts].each do |contact|
|
87
|
+
contact[:type] = CONTACT_TYPE.invert[contact.delete(:type_contact)]
|
88
|
+
contact[:id] = contact.delete(:contact_id)
|
89
|
+
contact[:number] = contact.delete(:value)
|
90
|
+
end
|
91
|
+
end
|
92
|
+
|
93
|
+
def date_to_time!(hash)
|
94
|
+
hash.each do |key, value|
|
95
|
+
date_to_time!(value) if value.is_a?(Hash)
|
96
|
+
|
97
|
+
if key.to_s.starts_with?("date_") && value
|
98
|
+
hash[key] = (value.to_time rescue value) || value
|
99
|
+
end
|
100
|
+
end
|
101
|
+
end
|
102
|
+
|
103
|
+
def errors
|
104
|
+
error_response = response_hash[:error_response]
|
105
|
+
|
106
|
+
if error_response[:validation_errors]
|
107
|
+
error_response[:errors] = error_response.delete(:validation_errors)
|
108
|
+
end
|
109
|
+
|
110
|
+
error_response[:errors]
|
111
|
+
end
|
112
|
+
end
|
113
|
+
end
|
114
|
+
end
|
@@ -2,20 +2,24 @@
|
|
2
2
|
module Tray
|
3
3
|
module Checkout
|
4
4
|
class Transaction
|
5
|
-
URL = "http://api.sandbox.checkout.tray.com.br/api/transactions"
|
5
|
+
URL = "http://api.sandbox.checkout.tray.com.br/api/v1/transactions"
|
6
6
|
|
7
7
|
def get(token)
|
8
|
-
|
9
|
-
parser.response(response)
|
8
|
+
request("get_by_token", { token: token })
|
10
9
|
end
|
11
10
|
|
12
11
|
def create(params)
|
13
|
-
|
14
|
-
parser.response(response)
|
12
|
+
request("pay_complete", parser.transaction_params(params))
|
15
13
|
end
|
16
14
|
|
17
15
|
private
|
18
16
|
|
17
|
+
def request(path, params)
|
18
|
+
xml = web_service.request!("#{URL}/#{path}", params)
|
19
|
+
#puts xml
|
20
|
+
parser.response(xml)
|
21
|
+
end
|
22
|
+
|
19
23
|
def web_service
|
20
24
|
@web_service ||= Tray::Checkout::WebService.new
|
21
25
|
end
|
@@ -0,0 +1,55 @@
|
|
1
|
+
# encoding: UTF-8
|
2
|
+
module Tray
|
3
|
+
module Checkout
|
4
|
+
class TransactionParamsParser
|
5
|
+
def initialize(params)
|
6
|
+
@params = params.clone
|
7
|
+
end
|
8
|
+
|
9
|
+
def parse
|
10
|
+
customer_map! @params[:customer]
|
11
|
+
payment_map! @params[:payment]
|
12
|
+
products_map! @params
|
13
|
+
@params
|
14
|
+
end
|
15
|
+
|
16
|
+
private
|
17
|
+
|
18
|
+
def customer_map!(customer)
|
19
|
+
return unless customer
|
20
|
+
customer[:gender] = SEX[customer[:sex]] if customer[:sex]
|
21
|
+
customer[:relationship] = MARITAL_STATUS[customer[:marital_status]] if customer[:marital_status]
|
22
|
+
contacts_map! customer[:contacts]
|
23
|
+
addresses_map! customer[:addresses]
|
24
|
+
end
|
25
|
+
|
26
|
+
def payment_map!(payment)
|
27
|
+
return unless payment
|
28
|
+
payment[:payment_method_id] = PAYMENT_METHOD[payment[:method]] if payment[:method]
|
29
|
+
payment[:card].each { |key, value| payment["card_#{key}".to_sym] = value } if payment[:card]
|
30
|
+
end
|
31
|
+
|
32
|
+
def contacts_map!(contacts)
|
33
|
+
return unless contacts
|
34
|
+
|
35
|
+
contacts.each do |contact|
|
36
|
+
contact[:type_contact] = CONTACT_TYPE[contact[:type]] if contact[:type]
|
37
|
+
contact[:number_contact] = contact.delete(:number)
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
def addresses_map!(addresses)
|
42
|
+
return unless addresses
|
43
|
+
|
44
|
+
addresses.each do |address|
|
45
|
+
address[:type_address] = ADDRESS_TYPE[address[:type]] if address[:type]
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
def products_map!(params)
|
50
|
+
return unless params[:transaction]
|
51
|
+
params[:transaction_product] = params[:transaction].delete(:products)
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
data/lib/tray-checkout.rb
CHANGED
@@ -4,5 +4,8 @@ require 'tray/checkout'
|
|
4
4
|
require 'tray/checkout/constants'
|
5
5
|
require 'tray/checkout/hash'
|
6
6
|
require 'tray/checkout/parser'
|
7
|
+
require 'tray/checkout/response'
|
8
|
+
require 'tray/checkout/response_parser'
|
7
9
|
require 'tray/checkout/transaction'
|
10
|
+
require 'tray/checkout/transaction_params_parser'
|
8
11
|
require 'tray/checkout/web_service'
|