cbraspag 0.9.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,235 @@
1
+ module Braspag
2
+ class Connection
3
+ def self.get(order)
4
+ #check if order.is valid for get
5
+ return ::Response
6
+
7
+ response = Braspag::Poster.new(self, self.url_for(:info)).do_post(:info, {
8
+ :loja => self.merchant_id, :numeroPedido => order.id.to_s
9
+ })
10
+
11
+ response = Utils::convert_to_map(response.body, {
12
+ :authorization => "CodigoAutorizacao",
13
+ :error_code => "CodigoErro",
14
+ :error_message => "MensagemErro",
15
+ :payment_method => "CodigoPagamento",
16
+ :payment_method_name => "FormaPagamento",
17
+ :installments => "NumeroParcelas",
18
+ :status => "Status",
19
+ :amount => "Valor",
20
+ :cancelled_at => "DataCancelamento",
21
+ :paid_at => "DataPagamento",
22
+ :order_date => "DataPedido",
23
+ :transaction_id => "TransId",
24
+ :tid => "BraspagTid"
25
+ })
26
+
27
+ # raise InvalidData if response[:authorization].nil?
28
+
29
+ self.get_billet(order)
30
+ self.get_credit_card(order)
31
+ response
32
+ end
33
+
34
+ private
35
+ def self.get_billet(order)
36
+
37
+ request = ::HTTPI::Request.new(self.info_url)
38
+ request.body = {
39
+ :loja => connection.merchant_id,
40
+ :numeroPedido => order_id.to_s
41
+ }
42
+
43
+ response = ::HTTPI.post(request)
44
+
45
+ response = Utils::convert_to_map(response.body, {
46
+ :document_number => "NumeroDocumento",
47
+ :payer => "Sacado",
48
+ :our_number => "NossoNumero",
49
+ :bill_line => "LinhaDigitavel",
50
+ :document_date => "DataDocumento",
51
+ :expiration_date => "DataVencimento",
52
+ :receiver => "Cedente",
53
+ :bank => "Banco",
54
+ :agency => "Agencia",
55
+ :account => "Conta",
56
+ :wallet => "Carteira",
57
+ :amount => "ValorDocumento",
58
+ :amount_invoice => "ValorPago",
59
+ :invoice_date => "DataCredito"
60
+ })
61
+
62
+ raise UnknownError if response[:document_number].nil?
63
+ response
64
+ end
65
+
66
+ def self.get_credit_card(order)
67
+ data = {:loja => self.merchant_id, :numeroPedido => order.id.to_s}
68
+ response = Braspag::Poster.new(self, self.info_url).do_post(:info_credit_card, data)
69
+
70
+ response = Utils::convert_to_map(response.body, {
71
+ :checking_number => "NumeroComprovante",
72
+ :certified => "Autenticada",
73
+ :autorization_number => "NumeroAutorizacao",
74
+ :card_number => "NumeroCartao",
75
+ :transaction_number => "NumeroTransacao"
76
+ })
77
+
78
+ raise UnknownError if response[:checking_number].nil?
79
+ response
80
+ end
81
+
82
+ end
83
+
84
+ class Order
85
+ include ::ActiveAttr::Model
86
+
87
+ class AssociationValidator < ActiveModel::EachValidator
88
+ def validate_each(record, attribute, value)
89
+ unless value.respond_to?(:valid?) && value.try(:valid?, self.options[:on])
90
+ record.errors.add attribute, "invalid data"
91
+ end
92
+ end
93
+ end
94
+
95
+ class PaymentMethodValidator < ActiveModel::EachValidator
96
+ def validate_each(record, attribute, value)
97
+ if Braspag::PAYMENT_METHOD.key(value).nil?
98
+ record.errors.add attribute, "invalid payment code"
99
+ end
100
+ end
101
+ end
102
+
103
+ class InstallmentsTypeValidator < ActiveModel::EachValidator
104
+ def validate_each(record, attribute, value)
105
+ if Braspag::INTEREST.key(value).nil?
106
+ record.errors.add attribute, "invalid installments type"
107
+ end
108
+ end
109
+ end
110
+
111
+ attr_accessor :id, :payment_method, :amount, :customer, :installments, :installments_type
112
+ attr_accessor :gateway_authorization, :gateway_id, :gateway_return_code, :gateway_status, :gateway_message, :gateway_amount
113
+ attr_accessor :gateway_capture_return_code, :gateway_capture_status, :gateway_capture_message, :gateway_capture_amount
114
+ attr_accessor :gateway_void_return_code, :gateway_void_status, :gateway_void_message, :gateway_void_amount
115
+
116
+ [:purchase, :generate, :authorize, :capture, :void, :recurrency].each do |check_on|
117
+ validates :id, :presence => { :on => check_on }
118
+ validates :id, :length => {:minimum => 1, :maximum => 20, :on => check_on }
119
+ validates :id, :format => { :with => /^[0-9]+$/, :on => check_on, :if => :payment_for_cielo? }
120
+ end
121
+
122
+ [:purchase, :generate, :authorize, :recurrency].each do |check_on|
123
+ validates :payment_method, :presence => { :on => check_on }
124
+ validates :payment_method, :payment_method => { :on => check_on }
125
+
126
+ validates :amount, :presence => { :on => check_on }
127
+ validates :amount, :numericality => {:greater_than => 0, :on => check_on}
128
+
129
+ validates :customer, :presence => { :on => check_on }
130
+ validates :customer, :association => { :on => check_on }
131
+ end
132
+
133
+ [:purchase, :authorize, :recurrency].each do |check_on|
134
+ validates :installments, :presence => { :on => check_on }
135
+ validates :installments, :numericality => {:only_integer => true, :greater_than => 0, :less_than => 100, :on => check_on}
136
+ validates :installments, :format => { :with => /1/, :on => check_on, :if => :no_interest? }
137
+ validates :installments_type, :presence => { :on => check_on }
138
+ validates :installments_type, :installments_type => { :on => check_on }
139
+ end
140
+
141
+ def no_interest?
142
+ case installments_type
143
+ when Braspag::INTEREST[:no],
144
+ Braspag::INTEREST[:no_iata]
145
+ true
146
+ end
147
+ end
148
+
149
+ def convert_to(method)
150
+ data = self.send("to_#{method}")
151
+ data.merge!(self.customer.convert_to(method)) if self.customer
152
+ data
153
+ end
154
+
155
+ def to_authorize
156
+ {
157
+ :order_id => self.id.to_s,
158
+ :amount => self.amount,
159
+ :payment_method => self.payment_method,
160
+ :number_payments => self.installments,
161
+ :type => self.installments_type,
162
+ }
163
+ end
164
+
165
+ def to_capture
166
+ {
167
+ :order_id => self.id.to_s
168
+ }
169
+ end
170
+
171
+ def to_void
172
+ {
173
+ :order_id => self.id.to_s
174
+ }
175
+ end
176
+
177
+ def to_generate_billet
178
+ {
179
+ :order_id => self.id.to_s,
180
+ :amount => self.amount,
181
+ :payment_method => self.payment_method
182
+ }
183
+ end
184
+
185
+ def populate!(method, response)
186
+ self.send("populate_#{method}!", response)
187
+ end
188
+
189
+ def populate_authorize!(response)
190
+ self.gateway_authorization = response[:number]
191
+ self.gateway_id = response[:transaction_id]
192
+ self.gateway_return_code = response[:return_code]
193
+ self.gateway_status = response[:status]
194
+ self.gateway_message = response[:message]
195
+ self.gateway_amount = Converter::string_to_decimal(response[:amount])
196
+ end
197
+
198
+ def populate_capture!(response)
199
+ #TODO: CHECK IF IS NECESSARY
200
+ # self.gateway_capture_id = response[:transaction_id]
201
+ self.gateway_capture_return_code = response[:return_code]
202
+ self.gateway_capture_status = response[:status]
203
+ self.gateway_capture_message = response[:message]
204
+ self.gateway_capture_amount = Converter::string_to_decimal(response[:amount])
205
+ end
206
+
207
+ def populate_void!(response)
208
+ #TODO: CHECK IF IS NECESSARY
209
+ # self.gateway_void_id = response[:transaction_id]
210
+ self.gateway_void_return_code = response[:return_code]
211
+ self.gateway_void_status = response[:status]
212
+ self.gateway_void_message = response[:message]
213
+ self.gateway_void_amount = Converter::string_to_decimal(response[:amount])
214
+ end
215
+
216
+ def populate_generate_billet!(response)
217
+ self.gateway_return_code = response[:return_code]
218
+ self.gateway_status = response[:status]
219
+ self.gateway_amount = BigDecimal.new(response[:amount].to_s) if response[:amount]
220
+ end
221
+
222
+ private
223
+ def payment_for_cielo?
224
+ case payment_method
225
+ when Braspag::PAYMENT_METHOD[:cielo_noauth_visa],
226
+ Braspag::PAYMENT_METHOD[:cielo_preauth_visa],
227
+ Braspag::PAYMENT_METHOD[:cielo_noauth_mastercard],
228
+ Braspag::PAYMENT_METHOD[:cielo_preauth_mastercard],
229
+ Braspag::PAYMENT_METHOD[:cielo_noauth_elo],
230
+ Braspag::PAYMENT_METHOD[:cielo_noauth_diners]
231
+ true
232
+ end
233
+ end
234
+ end
235
+ end
@@ -0,0 +1,37 @@
1
+ module Braspag
2
+ class Poster
3
+ def initialize(connection, url)
4
+ @connection = connection
5
+ @request = ::HTTPI::Request.new(url)
6
+ end
7
+
8
+ def do_post(method, data)
9
+ @request.body = data
10
+ @request.proxy = @connection.proxy_address if @connection.proxy_address
11
+
12
+ with_logger(method) do
13
+ ::HTTPI.post @request
14
+ end
15
+ end
16
+
17
+ private
18
+
19
+ def with_logger(method)
20
+ if @connection.logger
21
+ @connection.logger.info("[Braspag] ##{method}: #{@request.url}, data: #{mask_data(@request.body).inspect}")
22
+ response = yield
23
+ @connection.logger.info("[Braspag] ##{method} returns: #{response.body.inspect}")
24
+ else
25
+ response = yield
26
+ end
27
+ response
28
+ end
29
+
30
+ def mask_data(data)
31
+ copy_data = data.dup
32
+ copy_data['cardNumber'] = "************%s" % copy_data['cardNumber'][-4..-1] if copy_data['cardNumber']
33
+ copy_data['securityCode'] = "***" if copy_data['securityCode']
34
+ copy_data
35
+ end
36
+ end
37
+ end
@@ -0,0 +1,25 @@
1
+ module Braspag
2
+ class Response
3
+ attr_reader :params, :message, :test, :authorization, :avs_result, :cvv_result
4
+
5
+ def success?
6
+ @success
7
+ end
8
+
9
+ def test?
10
+ @test
11
+ end
12
+
13
+ def fraud_review?
14
+ @fraud_review
15
+ end
16
+
17
+ def initialize(success, message, params = {}, options = {})
18
+ @success, @message, @params = success, message, params.stringify_keys
19
+ @test = options[:test] || false
20
+ @authorization = options[:authorization]
21
+ @fraud_review = options[:fraud_review]
22
+ end
23
+ end
24
+
25
+ end
@@ -0,0 +1,91 @@
1
+ module Braspag
2
+ module Crypto
3
+ class JarWebservice
4
+ def self.encrypt(map)
5
+ crypto_key = Braspag::Connection.instance.crypto_key
6
+ raise Braspag::IncompleteParams if map.nil?
7
+ raise Braspag::IncompleteParams unless map.is_a?(Hash)
8
+
9
+ request = ::HTTPI::Request.new encrypt_uri
10
+
11
+ data = {:key => crypto_key, :fields => map}
12
+
13
+ request.headers["Content-Type"] = "application/json"
14
+
15
+ request.body = data.to_json
16
+
17
+ response = ::HTTPI.post request
18
+
19
+ begin
20
+ response = JSON.parse(response.body)
21
+ rescue Exception => e
22
+ raise UnknownError
23
+ end
24
+
25
+ raise IncompleteParams if (
26
+ response["msg"] == "INVALID FORMAT" ||
27
+ response["msg"] == "INVALID FIELDS"
28
+ )
29
+
30
+ raise InvalidEncryptedKey if response["msg"] == "INVALID ENCRYPTED STRING"
31
+ raise InvalidCryptKey if response["msg"] == "INVALID KEY"
32
+
33
+ response["encrypt"]
34
+ end
35
+
36
+ def self.decrypt(encrypted, fields)
37
+ crypto_key = Braspag::Connection.instance.crypto_key
38
+ raise Braspag::InvalidEncryptedKey if encrypted.nil?
39
+ raise Braspag::InvalidEncryptedKey unless encrypted.is_a?(String)
40
+
41
+ raise Braspag::IncompleteParams if fields.nil?
42
+ raise Braspag::IncompleteParams unless fields.is_a?(Array)
43
+
44
+
45
+ request = ::HTTPI::Request.new decrypt_uri
46
+ request.body = {
47
+ "key" => crypto_key,
48
+ "encrypted" => encrypted,
49
+ "fields" => fields
50
+ }.to_json
51
+
52
+ request.headers["Content-Type"] = "application/json"
53
+
54
+ response = ::HTTPI.post request
55
+
56
+ begin
57
+ response = JSON.parse(response.body)
58
+ rescue Exception => e
59
+ raise UnknownError
60
+ end
61
+
62
+ raise IncompleteParams if (
63
+ response["msg"] == "INVALID FORMAT" ||
64
+ response["msg"] == "INVALID FIELDS"
65
+ )
66
+
67
+ raise InvalidEncryptedKey if response["msg"] == "INVALID ENCRYPTED STRING"
68
+
69
+ raise InvalidCryptKey if response["msg"] == "INVALID KEY"
70
+
71
+ map = {}
72
+ response["fields"].each do |key,value|
73
+ map[key.downcase.to_sym] = value
74
+ end
75
+ map
76
+ end
77
+
78
+ protected
79
+ def self.encrypt_uri
80
+ connection_uri = Braspag::Connection.instance.crypto_url
81
+ "#{connection_uri}/v1/encrypt.json"
82
+ end
83
+
84
+ def self.decrypt_uri
85
+ connection_uri = Braspag::Connection.instance.crypto_url
86
+ "#{connection_uri}/v1/decrypt.json"
87
+ end
88
+
89
+ end
90
+ end
91
+ end
@@ -0,0 +1,6 @@
1
+ module Braspag
2
+ module Crypto
3
+ class NoCrypto
4
+ end
5
+ end
6
+ end
@@ -0,0 +1,95 @@
1
+ module Braspag
2
+ module Crypto
3
+ class Webservice
4
+ def self.encrypt(map)
5
+ connection = Braspag::Connection.instance
6
+ raise Braspag::IncompleteParams if map.nil?
7
+ raise Braspag::IncompleteParams unless map.is_a?(Hash)
8
+
9
+ request = ::HTTPI::Request.new self.uri
10
+
11
+ fields = "\n"
12
+ map.each do |key, value|
13
+ fields.concat(" <tns:string>#{key}=#{value}</tns:string>\n")
14
+ end
15
+
16
+ request.body = <<-STRING
17
+ <?xml version="1.0" encoding="utf-8"?>
18
+ <env:Envelope xmlns:env="http://www.w3.org/2003/05/soap-envelope">
19
+ <env:Header />
20
+ <env:Body>
21
+ <tns:EncryptRequest xmlns:tns="https://www.pagador.com.br/webservice/BraspagGeneralService">
22
+ <tns:merchantId>#{connection.merchant_id}</tns:merchantId>
23
+ <tns:request>
24
+ #{fields}
25
+ </tns:request>
26
+ </tns:EncryptRequest>
27
+ </env:Body>
28
+ </env:Envelope>
29
+ STRING
30
+
31
+ request.headers["Content-Type"] = "text/xml"
32
+
33
+ response = ::HTTPI.post request
34
+
35
+ document = Nokogiri::XML(response.body)
36
+
37
+ raise Braspag::UnknownError if document.children.empty?
38
+
39
+ #melhorar este parser cof cof
40
+ response = document.children.children.children.children.children.to_s
41
+
42
+ raise Braspag::InvalidMerchantId if (response == 'Erro BP 011' || response == 'Erro BP 012')
43
+ raise Braspag::InvalidIP if (response == 'Erro BP 067' || response == 'Erro BP 068')
44
+
45
+ response
46
+ end
47
+
48
+ def self.decrypt(encripted_text)
49
+ connection = Braspag::Connection.instance
50
+
51
+ raise Braspag::IncompleteParams if encripted_text.nil?
52
+ raise Braspag::IncompleteParams unless encripted_text.is_a?(String)
53
+
54
+ request = ::HTTPI::Request.new self.uri
55
+
56
+ request.body = <<-STRING
57
+ <?xml version="1.0" encoding="utf-8"?>
58
+ <env:Envelope xmlns:env="http://www.w3.org/2003/05/soap-envelope">
59
+ <env:Header />
60
+ <env:Body>
61
+ <tns:DecryptRequest xmlns:tns="https://www.pagador.com.br/webservice/BraspagGeneralService">
62
+ <tns:merchantId>#{connection.merchant_id}</tns:merchantId>
63
+ <tns:cryptString>#{encripted_text}</tns:cryptString>
64
+ </tns:DecryptRequest>
65
+ </env:Body>
66
+ </env:Envelope>
67
+ STRING
68
+
69
+ request.headers["Content-Type"] = "text/xml"
70
+
71
+ response = ::HTTPI.post request
72
+
73
+ document = Nokogiri::XML(response.body)
74
+ raise Braspag::UnknownError if document.children.empty?
75
+
76
+ result_error = document.children.children.children.children.children.first.content.to_s
77
+
78
+ raise Braspag::InvalidMerchantId if (result_error == 'Erro BP 011' || result_error == 'Erro BP 012')
79
+ raise Braspag::InvalidIP if (result_error == 'Erro BP 067' || result_error == 'Erro BP 068')
80
+
81
+ self.convert_request_to_map document
82
+ end
83
+
84
+ protected
85
+ def self.convert_request_to_map(document)
86
+ map = {}
87
+ document.children.children.children.children.children.each do |n|
88
+ values = n.content.to_s.split("=")
89
+ map[values[0].downcase.to_sym] = values[1]
90
+ end
91
+ map
92
+ end
93
+ end
94
+ end
95
+ end