cbraspag 0.9.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.
@@ -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