baby-braspag 0.1.3

Sign up to get free protection for your applications and to get access to all the features.
data/.gitignore ADDED
@@ -0,0 +1,9 @@
1
+ nbproject
2
+ pkg
3
+ doc
4
+ tags
5
+ *.sw*
6
+ .bundle
7
+ .rvmrc
8
+ Gemfile.lock
9
+
data/.rspec ADDED
@@ -0,0 +1 @@
1
+ --colour
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source "http://rubygems.org"
2
+
3
+ # Specify your gem's dependencies in rbraspag.gemspec
4
+ gemspec
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/rbraspag.rb$}) { "spec" }
8
+ watch(%r{^lib/rbraspag/(.*)\.rb$}) { |m| "spec/#{m[1]}_spec.rb" }
9
+ watch('spec/spec_helper.rb') { "spec" }
10
+ end
data/README.md ADDED
@@ -0,0 +1,60 @@
1
+ # Baby Braspag
2
+
3
+ baby-braspag gem to use Braspag gateway
4
+
5
+ * This gem need RACK_ENV environment variable to identify the environment
6
+
7
+ # How to install
8
+
9
+ ## for Rails 3 app
10
+
11
+ ### Add on your Gemfile
12
+
13
+ gem "baby-braspag"
14
+
15
+ ### Create a config/braspag.yml file
16
+
17
+ $ rails generate braspag:install
18
+
19
+ ### Set RACK_ENV (our suggest)
20
+
21
+ # add last line in config/environment.rb
22
+ # ...
23
+ # ENV["RACK_ENV"] ||= ENV["RAILS_ENV"]
24
+
25
+ ### Edit config/braspag.yml with your Braspag merchant_id
26
+
27
+ # Examples
28
+
29
+ ## to create a Bill (Boleto/Bloqueto for brazilian guys)
30
+ @bill = Braspag::Bill.generate({
31
+ :order_id => 1,
32
+ :amount => 3,
33
+ :payment_method => 10
34
+ })
35
+
36
+ # License
37
+
38
+ (The MIT License)
39
+
40
+ Copyright (c) 2010
41
+
42
+ Permission is hereby granted, free of charge, to any person obtaining
43
+ a copy of this software and associated documentation files (the
44
+ 'Software'), to deal in the Software without restriction, including
45
+ without limitation the rights to use, copy, modify, merge, publish,
46
+ distribute, sublicense, and/or sell copies of the Software, and to
47
+ permit persons to whom the Software is furnished to do so, subject to
48
+ the following conditions:
49
+
50
+ The above copyright notice and this permission notice shall be
51
+ included in all copies or substantial portions of the Software.
52
+
53
+ THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
54
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
55
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
56
+ IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
57
+ CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
58
+ TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
59
+ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
60
+
data/RELEASES.md ADDED
@@ -0,0 +1,20 @@
1
+ # RELEASES
2
+
3
+ ## For next release
4
+
5
+ d2b9a7a Voltando a usar o HTTPI
6
+
7
+ ## 0.1.1 - 09/01/2012
8
+
9
+ 9ffbcbd adicionando novos códigos de métodos de pagamento
10
+
11
+
12
+ ## 0.1.0 - 09/01/2012
13
+
14
+ 5cf697e adicionando Gemfile.lock ao .gitignore
15
+ a6b1f54 removendo Gemfile.lock; modificando verificação do argumento has_interest
16
+ a663e0a baixando a versão mínima requerida do nokogiri
17
+ 628d108 refatorando testes e implementação
18
+ 087549a moving Connection exceptions to errors.rb; tests for Utils class
19
+ 9a727eb bump up version
20
+ 6e5b1c3 refatorando para suportar o ambiente de produção da Braspag
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
@@ -0,0 +1,33 @@
1
+ # -*- encoding: utf-8 -*-
2
+ $:.push File.expand_path("../lib", __FILE__)
3
+ require "baby-braspag/version"
4
+
5
+ Gem::Specification.new do |s|
6
+ s.name = "baby-braspag"
7
+ s.version = Braspag::VERSION
8
+ s.authors = ["baby dev"]
9
+ s.email = %w["dev-team@baby.com.br"]
10
+ s.homepage = "https://github.com/Baby-com-br/braspag"
11
+ s.summary = "baby braspag gem to use Braspag gateway"
12
+ s.description = "baby braspag gem to use Braspag gateway"
13
+
14
+ s.rubyforge_project = "baby-braspag"
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
+
21
+ s.add_dependency 'httpi', '>= 0.9.6'
22
+ s.add_dependency 'json', '>= 1.6.1'
23
+ s.add_dependency 'nokogiri', '>= 1.4.7'
24
+ s.add_dependency 'savon', '>= 0.9.9'
25
+
26
+ s.add_development_dependency "rake"
27
+ s.add_development_dependency "rspec"
28
+ s.add_development_dependency "fakeweb"
29
+ s.add_development_dependency "shoulda-matchers"
30
+ s.add_development_dependency "guard-rspec"
31
+ s.add_development_dependency "guard-bundler"
32
+ s.add_development_dependency "debugger"
33
+ end
@@ -0,0 +1,17 @@
1
+ development:
2
+ environment: "homologation"
3
+ merchant_id: "{84BE7E7F-698A-6C74-F820-AE359C2A07C2}"
4
+ crypto_url: "http://localhost:9292"
5
+ crypto_key: "1234561246"
6
+
7
+ test:
8
+ environment: "homologation"
9
+ merchant_id: "{84BE7E7F-698A-6C74-F820-AE359C2A07C2}"
10
+ crypto_url: "http://localhost:9292"
11
+ crypto_key: "1234561246"
12
+
13
+ production:
14
+ environment: "production"
15
+ merchant_id: "{84BE7E7F-698A-6C74-F820-AE359C2A07C2}"
16
+ crypto_url: "http://localhost:9292"
17
+ crypto_key: "1234561246"
@@ -0,0 +1,45 @@
1
+ require 'singleton'
2
+ require 'httpi'
3
+ require 'nokogiri'
4
+ require 'json'
5
+ require 'savon'
6
+
7
+ require "baby-braspag/version"
8
+ require 'baby-braspag/connection'
9
+ require 'baby-braspag/payment_method'
10
+ require 'baby-braspag/crypto/jar_webservice'
11
+ require 'baby-braspag/crypto/webservice'
12
+ require 'baby-braspag/bill'
13
+ require 'baby-braspag/poster'
14
+ require 'baby-braspag/credit_card'
15
+ require 'baby-braspag/protected_credit_card'
16
+ require 'baby-braspag/eft'
17
+ require 'baby-braspag/errors'
18
+ require 'baby-braspag/utils'
19
+ require 'baby-braspag/order'
20
+
21
+ module Braspag
22
+ def self.logger=(value)
23
+ @logger = value
24
+ end
25
+
26
+ def self.logger
27
+ @logger
28
+ end
29
+
30
+ def self.config_file_path=(path)
31
+ @config_path = path
32
+ end
33
+
34
+ def self.config_file_path
35
+ @config_path || 'config/braspag.yml'
36
+ end
37
+
38
+ def self.proxy_address=(value)
39
+ @proxy_address = value
40
+ end
41
+
42
+ def self.proxy_address
43
+ @proxy_address
44
+ end
45
+ end
@@ -0,0 +1,160 @@
1
+ require "bigdecimal"
2
+
3
+ module Braspag
4
+ class Bill < PaymentMethod
5
+
6
+ PAYMENT_METHODS = {
7
+ :bradesco => "06",
8
+ :cef => "07",
9
+ :hsbc => "08",
10
+ :bb => "09",
11
+ :real => "10",
12
+ :citibank => "13",
13
+ :itau => "14",
14
+ :unibanco => "26"
15
+ }
16
+
17
+ MAPPING = {
18
+ :merchant_id => "merchantId",
19
+ :order_id => "orderId",
20
+ :customer_name => "customerName",
21
+ :customer_id => "customerIdNumber",
22
+ :amount => "amount",
23
+ :payment_method => "paymentMethod",
24
+ :number => "boletoNumber",
25
+ :instructions => "instructions",
26
+ :expiration_date => "expirationDate",
27
+ :emails => "emails"
28
+ }
29
+
30
+ PRODUCTION_INFO_URI = "/webservices/pagador/pedido.asmx/GetDadosBoleto"
31
+ HOMOLOGATION_INFO_URI = "/pagador/webservice/pedido.asmx/GetDadosBoleto"
32
+ CREATION_URI = "/webservices/pagador/Boleto.asmx/CreateBoleto"
33
+
34
+ def self.generate(params)
35
+ connection = Braspag::Connection.instance
36
+ params[:merchant_id] = connection.merchant_id
37
+
38
+ params = self.normalize_params(params)
39
+ self.check_params(params)
40
+
41
+ data = {}
42
+
43
+ MAPPING.each do |k, v|
44
+ case k
45
+ when :payment_method
46
+ data[v] = PAYMENT_METHODS[params[:payment_method]]
47
+ when :amount
48
+ data[v] = Utils.convert_decimal_to_string(params[:amount])
49
+ else
50
+ data[v] = params[k] || ""
51
+ end
52
+ end
53
+
54
+ request = ::HTTPI::Request.new(self.creation_url)
55
+ request.body = data
56
+
57
+ response = Utils::convert_to_map(::HTTPI.post(request).body,
58
+ {
59
+ :url => nil,
60
+ :amount => nil,
61
+ :number => "boletoNumber",
62
+ :expiration_date => Proc.new { |document|
63
+ begin
64
+ Date.parse(document.search("expirationDate").first.to_s)
65
+ rescue
66
+ nil
67
+ end
68
+ },
69
+ :return_code => "returnCode",
70
+ :status => nil,
71
+ :message => nil
72
+ })
73
+
74
+ raise InvalidMerchantId if response[:message] == "Invalid merchantId"
75
+ raise InvalidAmount if response[:message] == "Invalid purchase amount"
76
+ raise InvalidPaymentMethod if response[:message] == "Invalid payment method"
77
+ raise InvalidStringFormat if response[:message] == "Input string was not in a correct format."
78
+ raise UnknownError if response[:status].nil?
79
+
80
+ response[:amount] = BigDecimal.new(response[:amount])
81
+
82
+ response
83
+ end
84
+
85
+ def self.normalize_params(params)
86
+ params = super
87
+
88
+ if params[:expiration_date].respond_to?(:strftime)
89
+ params[:expiration_date] = params[:expiration_date].strftime("%d/%m/%y")
90
+ end
91
+
92
+ params
93
+ end
94
+
95
+ def self.check_params(params)
96
+ super
97
+
98
+ if params[:number]
99
+ raise InvalidNumber unless (1..255).include?(params[:number].to_s.size)
100
+ end
101
+
102
+ if params[:instructions]
103
+ raise InvalidInstructions unless (1..512).include?(params[:instructions].to_s.size)
104
+ end
105
+
106
+ if params[:expiration_date]
107
+ matches = params[:expiration_date].to_s.match /(\d{2})\/(\d{2})\/(\d{2})/
108
+ raise InvalidExpirationDate unless matches
109
+ begin
110
+ Date.new(matches[3].to_i, matches[2].to_i, matches[1].to_i)
111
+ rescue ArgumentError
112
+ raise InvalidExpirationDate
113
+ end
114
+ end
115
+ end
116
+
117
+ def self.info_url
118
+ connection = Braspag::Connection.instance
119
+ connection.braspag_url + (connection.production? ? PRODUCTION_INFO_URI : HOMOLOGATION_INFO_URI)
120
+ end
121
+
122
+ def self.creation_url
123
+ Braspag::Connection.instance.braspag_url + CREATION_URI
124
+ end
125
+
126
+ def self.info(order_id)
127
+ connection = Braspag::Connection.instance
128
+
129
+ raise InvalidOrderId unless self.valid_order_id?(order_id)
130
+
131
+ request = ::HTTPI::Request.new(self.info_url)
132
+ request.body = {
133
+ :loja => connection.merchant_id,
134
+ :numeroPedido => order_id.to_s
135
+ }
136
+
137
+ response = ::HTTPI.post(request)
138
+
139
+ response = Utils::convert_to_map(response.body, {
140
+ :document_number => "NumeroDocumento",
141
+ :payer => "Sacado",
142
+ :our_number => "NossoNumero",
143
+ :bill_line => "LinhaDigitavel",
144
+ :document_date => "DataDocumento",
145
+ :expiration_date => "DataVencimento",
146
+ :receiver => "Cedente",
147
+ :bank => "Banco",
148
+ :agency => "Agencia",
149
+ :account => "Conta",
150
+ :wallet => "Carteira",
151
+ :amount => "ValorDocumento",
152
+ :amount_invoice => "ValorPago",
153
+ :invoice_date => "DataCredito"
154
+ })
155
+
156
+ raise UnknownError if response[:document_number].nil?
157
+ response
158
+ end
159
+ end
160
+ end
@@ -0,0 +1,37 @@
1
+ module Braspag
2
+ class Connection
3
+ include Singleton
4
+
5
+ PRODUCTION_URL = "https://transaction.pagador.com.br"
6
+ HOMOLOGATION_URL = "https://homologacao.pagador.com.br"
7
+
8
+ PROTECTED_CARD_PRODUCTION_URL = "https://cartaoprotegido.braspag.com.br/Services"
9
+ PROTECTED_CARD_HOMOLOGATION_URL = "https://homologacao.braspag.com.br/services/testenvironment"
10
+
11
+ attr_reader :braspag_url, :protected_card_url, :merchant_id, :crypto_url, :crypto_key, :options, :environment
12
+
13
+ def initialize
14
+ raise InvalidEnv if ENV["BRASPAG_ENV"].nil? || ENV["BRASPAG_ENV"].empty?
15
+
16
+ @options = YAML.load_file(Braspag.config_file_path)[ ENV['BRASPAG_ENV'] ]
17
+ @merchant_id = @options['merchant_id']
18
+
19
+ raise InvalidMerchantId unless @merchant_id =~ /\{[a-z0-9]{8}-([a-z0-9]{4}-){3}[a-z0-9]{12}\}/i
20
+
21
+ @crypto_key = @options["crypto_key"]
22
+ @crypto_url = @options["crypto_url"]
23
+ @environment = @options["environment"] == 'production' ? 'production' : 'homologation'
24
+
25
+ @braspag_url = self.production? ? PRODUCTION_URL : HOMOLOGATION_URL
26
+ @protected_card_url = self.production? ? PROTECTED_CARD_PRODUCTION_URL : PROTECTED_CARD_HOMOLOGATION_URL
27
+ end
28
+
29
+ def production?
30
+ @environment == 'production'
31
+ end
32
+
33
+ def homologation?
34
+ @environment == 'homologation'
35
+ end
36
+ end
37
+ end
@@ -0,0 +1,210 @@
1
+ module Braspag
2
+ class CreditCard < PaymentMethod
3
+
4
+ MAPPING = {
5
+ :merchant_id => "merchantId",
6
+ :order => 'order',
7
+ :order_id => "orderId",
8
+ :customer_name => "customerName",
9
+ :amount => "amount",
10
+ :payment_method => "paymentMethod",
11
+ :holder => "holder",
12
+ :card_number => "cardNumber",
13
+ :expiration => "expiration",
14
+ :security_code => "securityCode",
15
+ :number_payments => "numberPayments",
16
+ :type => "typePayment"
17
+ }
18
+
19
+ AUTHORIZE_URI = "/webservices/pagador/Pagador.asmx/Authorize"
20
+ CAPTURE_URI = "/webservices/pagador/Pagador.asmx/Capture"
21
+ PARTIAL_CAPTURE_URI = "/webservices/pagador/Pagador.asmx/CapturePartial"
22
+ CANCELLATION_URI = "/webservices/pagador/Pagador.asmx/VoidTransaction"
23
+ PRODUCTION_INFO_URI = "/webservices/pagador/pedido.asmx/GetDadosCartao"
24
+ HOMOLOGATION_INFO_URI = "/pagador/webservice/pedido.asmx/GetDadosCartao"
25
+
26
+ def self.authorize(params = {})
27
+ connection = Braspag::Connection.instance
28
+ params[:merchant_id] = connection.merchant_id
29
+
30
+ self.check_params(params)
31
+
32
+ data = {}
33
+ MAPPING.each do |k, v|
34
+ case k
35
+ when :payment_method
36
+ data[v] = Braspag::Connection.instance.homologation? ? PAYMENT_METHODS[:braspag] : PAYMENT_METHODS[params[:payment_method]]
37
+ when :amount
38
+ data[v] = Utils.convert_decimal_to_string(params[:amount])
39
+ else
40
+ data[v] = params[k] || ""
41
+ end
42
+ end
43
+
44
+ response = Braspag::Poster.new(self.authorize_url).do_post(:authorize, data)
45
+
46
+ Utils::convert_to_map(response.body, {
47
+ :amount => nil,
48
+ :number => "authorisationNumber",
49
+ :message => 'message',
50
+ :return_code => 'returnCode',
51
+ :status => 'status',
52
+ :transaction_id => "transactionId"
53
+ })
54
+ end
55
+
56
+ def self.capture(order_id)
57
+ connection = Braspag::Connection.instance
58
+ merchant_id = connection.merchant_id
59
+
60
+ raise InvalidOrderId unless self.valid_order_id?(order_id)
61
+
62
+ data = {
63
+ MAPPING[:order_id] => order_id,
64
+ MAPPING[:merchant_id] => merchant_id
65
+ }
66
+
67
+ response = Braspag::Poster.new(self.capture_url).do_post(:capture, data)
68
+
69
+ Utils::convert_to_map(response.body, {
70
+ :amount => nil,
71
+ :number => "authorisationNumber",
72
+ :message => 'message',
73
+ :return_code => 'returnCode',
74
+ :status => 'status',
75
+ :transaction_id => "transactionId"
76
+ })
77
+ end
78
+
79
+ def self.partial_capture(order_id, amount)
80
+ connection = Braspag::Connection.instance
81
+ merchant_id = connection.merchant_id
82
+
83
+ raise InvalidOrderId unless self.valid_order_id?(order_id)
84
+
85
+ data = {
86
+ MAPPING[:order_id] => order_id,
87
+ MAPPING[:merchant_id] => merchant_id,
88
+ "captureAmount" => Utils.convert_decimal_to_string(amount)
89
+ }
90
+
91
+ response = Braspag::Poster.new(self.partial_capture_url).do_post(:partial_capture, data)
92
+
93
+ Utils::convert_to_map(response.body, {
94
+ :amount => nil,
95
+ :number => "authorisationNumber",
96
+ :message => 'message',
97
+ :return_code => 'returnCode',
98
+ :status => 'status',
99
+ :transaction_id => "transactionId"
100
+ })
101
+ end
102
+
103
+ def self.void(order_id)
104
+ connection = Braspag::Connection.instance
105
+ merchant_id = connection.merchant_id
106
+
107
+ raise InvalidOrderId unless self.valid_order_id?(order_id)
108
+
109
+ data = {
110
+ MAPPING[:order] => order_id,
111
+ MAPPING[:merchant_id] => merchant_id
112
+ }
113
+
114
+ response = Braspag::Poster.new(self.cancellation_url).do_post(:void, data)
115
+
116
+ Utils::convert_to_map(response.body, {
117
+ :amount => nil,
118
+ :number => "authorisationNumber",
119
+ :message => 'message',
120
+ :return_code => 'returnCode',
121
+ :status => 'status',
122
+ :transaction_id => "transactionId"
123
+ })
124
+ end
125
+
126
+ def self.info(order_id)
127
+ connection = Braspag::Connection.instance
128
+
129
+ raise InvalidOrderId unless self.valid_order_id?(order_id)
130
+
131
+ data = {:loja => connection.merchant_id, :numeroPedido => order_id.to_s}
132
+ response = Braspag::Poster.new(self.info_url).do_post(:info_credit_card, data)
133
+
134
+ response = Utils::convert_to_map(response.body, {
135
+ :checking_number => "NumeroComprovante",
136
+ :certified => "Autenticada",
137
+ :autorization_number => "NumeroAutorizacao",
138
+ :card_number => "NumeroCartao",
139
+ :transaction_number => "NumeroTransacao"
140
+ })
141
+
142
+ raise UnknownError if response[:checking_number].nil?
143
+ response
144
+ end
145
+
146
+ def self.check_params(params)
147
+ super
148
+
149
+ [:customer_name, :holder, :card_number, :expiration, :security_code, :number_payments, :type].each do |param|
150
+ raise IncompleteParams if params[param].nil?
151
+ end
152
+
153
+ raise InvalidHolder if params[:holder].to_s.size < 1 || params[:holder].to_s.size > 100
154
+
155
+ matches = params[:expiration].to_s.match /^(\d{2})\/(\d{2,4})$/
156
+ raise InvalidExpirationDate unless matches
157
+ begin
158
+ year = matches[2].to_i
159
+ year = "20#{year}" if year.size == 2
160
+
161
+ Date.new(year.to_i, matches[1].to_i)
162
+ rescue ArgumentError
163
+ raise InvalidExpirationDate
164
+ end
165
+
166
+ raise InvalidSecurityCode if params[:security_code].to_s.size < 1 || params[:security_code].to_s.size > 4
167
+
168
+ raise InvalidNumberPayments if params[:number_payments].to_i < 1 || params[:number_payments].to_i > 99
169
+ end
170
+
171
+ # <b>DEPRECATED:</b> Please use <tt>ProtectedCreditCard.save</tt> instead.
172
+ def self.save(params)
173
+ warn "[DEPRECATION] `CreditCard.save` is deprecated. Please use `ProtectedCreditCard.save` instead."
174
+ ProtectedCreditCard.save(params)
175
+ end
176
+
177
+ # <b>DEPRECATED:</b> Please use <tt>ProtectedCreditCard.get</tt> instead.
178
+ def self.get(just_click_key)
179
+ warn "[DEPRECATION] `CreditCard.get` is deprecated. Please use `ProtectedCreditCard.get` instead."
180
+ ProtectedCreditCard.get(just_click_key)
181
+ end
182
+
183
+ # <b>DEPRECATED:</b> Please use <tt>ProtectedCreditCard.just_click_shop</tt> instead.
184
+ def self.just_click_shop(params = {})
185
+ warn "[DEPRECATION] `CreditCard.just_click_shop` is deprecated. Please use `ProtectedCreditCard.just_click_shop` instead."
186
+ ProtectedCreditCard.just_click_shop(params)
187
+ end
188
+
189
+ def self.info_url
190
+ connection = Braspag::Connection.instance
191
+ connection.braspag_url + (connection.production? ? PRODUCTION_INFO_URI : HOMOLOGATION_INFO_URI)
192
+ end
193
+
194
+ def self.authorize_url
195
+ Braspag::Connection.instance.braspag_url + AUTHORIZE_URI
196
+ end
197
+
198
+ def self.capture_url
199
+ Braspag::Connection.instance.braspag_url + CAPTURE_URI
200
+ end
201
+
202
+ def self.partial_capture_url
203
+ Braspag::Connection.instance.braspag_url + PARTIAL_CAPTURE_URI
204
+ end
205
+
206
+ def self.cancellation_url
207
+ Braspag::Connection.instance.braspag_url + CANCELLATION_URI
208
+ end
209
+ end
210
+ end