moip-ruby 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
data/.document ADDED
@@ -0,0 +1,5 @@
1
+ README.rdoc
2
+ lib/**/*.rb
3
+ bin/*
4
+ features/**/*.feature
5
+ LICENSE
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ # A sample Gemfile
2
+ source "http://rubygems.org"
3
+
4
+ gemspec
data/Gemfile.lock ADDED
@@ -0,0 +1,35 @@
1
+ PATH
2
+ remote: .
3
+ specs:
4
+ moip (1.0.1)
5
+ activesupport (>= 2.3.2)
6
+ httparty (~> 0.6.1)
7
+ nokogiri (~> 1.4.3)
8
+
9
+ GEM
10
+ remote: http://rubygems.org/
11
+ specs:
12
+ activesupport (3.0.1)
13
+ crack (0.1.8)
14
+ diff-lcs (1.1.2)
15
+ httparty (0.6.1)
16
+ crack (= 0.1.8)
17
+ nokogiri (1.4.3.1)
18
+ rspec (2.1.0)
19
+ rspec-core (~> 2.1.0)
20
+ rspec-expectations (~> 2.1.0)
21
+ rspec-mocks (~> 2.1.0)
22
+ rspec-core (2.1.0)
23
+ rspec-expectations (2.1.0)
24
+ diff-lcs (~> 1.1.2)
25
+ rspec-mocks (2.1.0)
26
+
27
+ PLATFORMS
28
+ ruby
29
+
30
+ DEPENDENCIES
31
+ activesupport (>= 2.3.2)
32
+ httparty (~> 0.6.1)
33
+ moip!
34
+ nokogiri (~> 1.4.3)
35
+ rspec (~> 2.1.0)
data/LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2009 Guilherme Nascimento
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.markdown ADDED
@@ -0,0 +1,86 @@
1
+ # MoIP
2
+
3
+ Esta Gem permite utilizar a API do MoIP, gateway de pagamentos do IG.
4
+
5
+ ## Pagamento direto
6
+
7
+ O Pagamento Direto é um recurso que a MoIP disponibiliza para aqueles clientes que necessitam de uma flexibilidade maior do que a Integração HTML pode oferecer.
8
+
9
+ Diferentemente de como é feito com a Integração HTML, seu cliente não precisa ser redirecionado para o site da MoIP para concluir a compra: tudo é feito dentro do ambiente do seu site, dando ao cliente uma maior segurança e confiança no processo.
10
+
11
+ As formas de pagamento disponibilizadas pela Gem são:
12
+
13
+ * Boleto
14
+ * Débito
15
+ * Cartão de Crédito
16
+
17
+ ## Instalação
18
+
19
+ Instale a Gem
20
+ gem install moip
21
+
22
+ Adicione a Gem ao Gemfile
23
+ gem "moip"
24
+
25
+ ## Utilização
26
+
27
+ O MoIP possui uma SandBox de testes que permite a simulação de pagamentos. Para utilizar a Gem com o SandBox, adicione a seguinte configuração no arquivo do environment que deseja utilizar.
28
+
29
+ ### config/environments/development.rb
30
+
31
+ MoIP.setup do |config|
32
+ config.uri = https://desenvolvedor.moip.com.br/sandbox
33
+ config.token = SEU_TOKEN
34
+ config.key = SUA_KEY
35
+ end
36
+
37
+ Após realizar os testes na SandBox, você poderá fazer a mudança para o ambiente de produção do MoIP de maneira simples. Basta inserir no arquivo de environment de produção o token e chave que serão utilizados. Por padrão a gem já utiliza a URI de produção do MoIP.
38
+
39
+ ###Crie os dados do pagador
40
+
41
+ pagador = { :nome => "Luiz Inácio Lula da Silva",
42
+ :login_moip => "lula",
43
+ :email => "presidente@planalto.gov.br",
44
+ :tel_cel => "(61)9999-9999",
45
+ :apelido => "Lula",
46
+ :identidade => "111.111.111-11",
47
+ :logradouro => "Praça dos Três Poderes",
48
+ :numero => "0",
49
+ :complemento => "Palácio do Planalto",
50
+ :bairro => "Zona Cívico-Administrativa",
51
+ :cidade => "Brasília",
52
+ :estado => "DF",
53
+ :pais => "BRA",
54
+ :cep => "70100-000",
55
+ :tel_fixo => "(61)3211-1221" }
56
+
57
+ ###Dados do boleto
58
+
59
+ boleto = { :valor => "50",
60
+ :id_proprio => "Pag#{rand(1000)}",
61
+ :forma => "BoletoBancario",
62
+ :dias_expiracao => 5,
63
+ :pagador => pagador }
64
+
65
+ ###Checkout
66
+
67
+ def checkout
68
+ response = MoIP::Client.checkout(boleto)
69
+
70
+ # exibe o boleto para impressão
71
+ redirect_to MoIP::Client.moip_page(response["Token"])
72
+ end
73
+
74
+ ###Erros
75
+
76
+ - MoIP::MissingPaymentTypeError - Quando falta a razão do pagamento na requisição.
77
+ - MoIP::MissingPayerError - Quando falta as informações do pagador na requisição.
78
+ - MoIP::WebServerResponseError - Quando há algum erro ao se enviar a solicitação ao servidor. Normalmente a razão do erro vem como resposta da mensagem.
79
+
80
+ ## Futuras implementações
81
+
82
+ * Pagamento Simples
83
+ * Pagamento Recorrente
84
+
85
+
86
+ Baseado no projeto do [Daniel Lopes](http://github.com/danielvlopes/moip_usage).
data/Rakefile ADDED
@@ -0,0 +1,38 @@
1
+ # coding: utf-8
2
+ require 'rubygems'
3
+ require 'rake'
4
+
5
+ require 'rspec/core/rake_task'
6
+
7
+ begin
8
+ require 'jeweler'
9
+ Jeweler::Tasks.new do |gem|
10
+ gem.name = "moip-ruby"
11
+ gem.summary = "Gem para utilização da API MoIP"
12
+ gem.description = "Gem para utilização da API MoIP"
13
+ gem.email = "guilherme.ruby@gmail.com"
14
+ gem.homepage = "http://github.com/guinascimento/moip"
15
+ gem.authors = ["Guilherme Nascimento"]
16
+ gem.add_development_dependency "rspec", "~> 2.1.0"
17
+ gem.add_dependency "nokogiri", "~> 1.4.3"
18
+ gem.add_dependency "httparty", "~> 0.8.1"
19
+ gem.add_dependency "activesupport", '>= 2.3.2'
20
+ end
21
+ Jeweler::GemcutterTasks.new
22
+ rescue LoadError
23
+ puts "Jeweler (or a dependency) not available. Install it with: gem install jeweler"
24
+ end
25
+
26
+ task :default => :spec
27
+ RSpec::Core::RakeTask.new
28
+
29
+ require 'rake/rdoctask'
30
+ Rake::RDocTask.new do |rdoc|
31
+ version = File.exist?('VERSION') ? File.read('VERSION') : ""
32
+
33
+ rdoc.rdoc_dir = 'rdoc'
34
+ rdoc.title = "moip #{version}"
35
+ rdoc.rdoc_files.include('README*')
36
+ rdoc.rdoc_files.include('lib/**/*.rb')
37
+ end
38
+
data/VERSION ADDED
@@ -0,0 +1 @@
1
+ 0.1.0
data/lib/moip.rb ADDED
@@ -0,0 +1,47 @@
1
+ # encoding: utf-8
2
+ require "rubygems"
3
+ require 'active_support/core_ext/module/attribute_accessors'
4
+ require 'active_support/deprecation'
5
+
6
+ module MoIP
7
+ autoload :DirectPayment, 'moip/direct_payment'
8
+ autoload :Client, 'moip/client'
9
+
10
+ # URI para acessar o serviço
11
+ mattr_accessor :uri
12
+ @@uri = 'https://www.moip.com.br'
13
+
14
+ # Token de autenticação
15
+ mattr_accessor :token
16
+
17
+ # Chave de acesso ao serviço
18
+ mattr_accessor :key
19
+
20
+ def self.setup
21
+ yield self
22
+ end
23
+
24
+ STATUS = {1 => "authorized", 2 => "started", 3 => "printed", 4 => "completed", 5 => "canceled", 6 => "analysing"}
25
+
26
+ class << self
27
+ def checkout(attributes = {})
28
+ ActiveSupport::Deprecation.warn("MoIP.checkout has been deprecated. Use MoIP::Client.checkout instead", caller)
29
+ MoIP::Client.checkout(attributes)
30
+ end
31
+
32
+ def query(token)
33
+ ActiveSupport::Deprecation.warn("MoIP.query has been deprecated. Use MoIP::Client.query instead", caller)
34
+ MoIP::Client.query(token)
35
+ end
36
+
37
+ def moip_page(token)
38
+ ActiveSupport::Deprecation.warn("MoIP.moip_page has been deprecated. use MoIP::Client.moip_page instead", caller)
39
+ MoIP::Client.moip_page(token)
40
+ end
41
+
42
+ def notification(params)
43
+ ActiveSupport::Deprecation.warn("MoIP.notification has been deprecated. use MoIP::Client.notification instead", caller)
44
+ MoIP::Client.moip_page(token)
45
+ end
46
+ end
47
+ end
@@ -0,0 +1,62 @@
1
+ # encoding: utf-8
2
+ require 'httparty'
3
+
4
+ module MoIP
5
+ class WebServerResponseError < StandardError ; end
6
+ class MissingTokenError < StandardError ; end
7
+
8
+ class Client
9
+ include HTTParty
10
+
11
+ base_uri "#{MoIP.uri}/ws/alpha"
12
+ basic_auth MoIP.token, MoIP.key
13
+
14
+ class << self
15
+
16
+ # Envia uma instrução para pagamento único
17
+ def checkout(attributes = {})
18
+ full_data = peform_action!(:post, 'EnviarInstrucao/Unica', :body => DirectPayment.body(attributes))
19
+
20
+ get_response!(full_data["ns1:EnviarInstrucaoUnicaResponse"]["Resposta"])
21
+ end
22
+
23
+ # Consulta dos dados das autorizações e pagamentos associados à Instrução
24
+ def query(token)
25
+ full_data = peform_action!(:get, "ConsultarInstrucao/#{token}")
26
+
27
+ get_response!(full_data["ns1:ConsultarTokenResponse"]["RespostaConsultar"])
28
+ end
29
+
30
+ # Retorna a URL de acesso ao MoIP
31
+ def moip_page(token)
32
+ raise(MissingTokenError, "É necessário informar um token para retornar os dados da transação") if token.nil?
33
+ "#{MoIP.uri}/Instrucao.do?token=#{token}"
34
+ end
35
+
36
+ # Monta o NASP
37
+ def notification(params)
38
+ notification = {}
39
+ notification[:transaction_id] = params["id_transacao"]
40
+ notification[:amount] = params["valor"]
41
+ notification[:status] = MoIP::STATUS[params["status_pagamento"].to_i]
42
+ notification[:code] = params["cod_moip"]
43
+ notification[:payment_type] = params["tipo_pagamento"]
44
+ notification[:email] = params["email_consumidor"]
45
+ notification
46
+ end
47
+
48
+ private
49
+
50
+ def peform_action!(action_name, url, options = {})
51
+ response = self.send(action_name, url, options)
52
+ raise(WebServerResponseError, "Ocorreu um erro ao chamar o webservice") if response.nil?
53
+ response
54
+ end
55
+
56
+ def get_response!(data)
57
+ raise(WebServerResponseError, data["Erro"]) if data["Status"] == "Falha"
58
+ data
59
+ end
60
+ end
61
+ end
62
+ end
@@ -0,0 +1,146 @@
1
+ # encoding: utf-8
2
+ require "nokogiri"
3
+
4
+ module MoIP
5
+
6
+ class MissingPaymentTypeError < StandardError ; end
7
+ class MissingPayerError < StandardError ; end
8
+
9
+ class DirectPayment
10
+
11
+ class << self
12
+
13
+ # Cria uma instrução de pagamento direto
14
+ def body(attributes = {})
15
+ raise(MissinPaymentTypeError, "É necessário informar a razão do pagamento") if attributes[:razao].nil?
16
+ raise(MissingPayerError, "É obrigatório passar as informações do pagador") if attributes[:pagador].nil?
17
+
18
+ builder = Nokogiri::XML::Builder.new(:encoding => "UTF-8") do |xml|
19
+
20
+ # Identificador do tipo de instrução
21
+ xml.EnviarInstrucao {
22
+ xml.InstrucaoUnica {
23
+
24
+ # Dados da transação
25
+ xml.Razao {
26
+ xml.text attributes[:razao]
27
+ }
28
+ xml.Valores {
29
+ xml.Valor(:moeda => "BRL") {
30
+ xml.text attributes[:valor]
31
+ }
32
+ }
33
+ xml.IdProprio {
34
+ xml.text attributes[:id_proprio]
35
+ }
36
+
37
+ # Definindo o pagamento direto
38
+ xml.PagamentoDireto {
39
+ xml.Forma {
40
+ xml.text attributes[:forma]
41
+ }
42
+
43
+ # Débito Bancário
44
+ if attributes[:forma] == "DebitoBancario"
45
+ xml.Instituicao {
46
+ xml.text attributes[:instituicao]
47
+ }
48
+ end
49
+
50
+ # Cartão de Crédito
51
+ if attributes[:forma] == "CartaoCredito"
52
+ xml.Instituicao {
53
+ xml.text attributes[:instituicao]
54
+ }
55
+ xml.CartaoCredito {
56
+ xml.Numero {
57
+ xml.text attributes[:numero]
58
+ }
59
+ xml.Expiracao {
60
+ xml.text attributes[:expiracao]
61
+ }
62
+ xml.CodigoSeguranca {
63
+ xml.text attributes[:codigo_seguranca]
64
+ }
65
+ xml.Portador {
66
+ xml.Nome {
67
+ xml.text attributes[:nome]
68
+ }
69
+ xml.Identidade(:Tipo => "CPF") {
70
+ xml.text attributes[:identidade]
71
+ }
72
+ xml.Telefone {
73
+ xml.text attributes[:telefone]
74
+ }
75
+ xml.DataNascimento {
76
+ xml.text attributes[:data_nascimento]
77
+ }
78
+ }
79
+ }
80
+ xml.Parcelamento {
81
+ xml.Parcelas {
82
+ xml.text attributes[:parcelas]
83
+ }
84
+ xml.Recebimento {
85
+ xml.text attributes[:recebimento]
86
+ }
87
+ }
88
+ end
89
+ }
90
+
91
+ # Dados do pagador
92
+ xml.Pagador {
93
+ xml.Nome { xml.text attributes[:pagador][:nome] }
94
+ xml.LoginMoIP { xml.text attributes[:pagador][:login_moip] }
95
+ xml.Email { xml.text attributes[:pagador][:email] }
96
+ xml.TelefoneCelular { xml.text attributes[:pagador][:tel_cel] }
97
+ xml.Apelido { xml.text attributes[:pagador][:apelido] }
98
+ xml.Identidade { xml.text attributes[:pagador][:identidade] }
99
+ xml.EnderecoCobranca {
100
+ xml.Logradouro { xml.text attributes[:pagador][:logradouro] }
101
+ xml.Numero { xml.text attributes[:pagador][:numero] }
102
+ xml.Complemento { xml.text attributes[:pagador][:complemento] }
103
+ xml.Bairro { xml.text attributes[:pagador][:bairro] }
104
+ xml.Cidade { xml.text attributes[:pagador][:cidade] }
105
+ xml.Estado { xml.text attributes[:pagador][:estado] }
106
+ xml.Pais { xml.text attributes[:pagador][:pais] }
107
+ xml.CEP { xml.text attributes[:pagador][:cep] }
108
+ xml.TelefoneFixo { xml.text attributes[:pagador][:tel_fixo] }
109
+ }
110
+ }
111
+
112
+ # Boleto Bancario
113
+ if attributes[:forma] == "BoletoBancario"
114
+ # Dados extras
115
+ xml.Boleto {
116
+ xml.DiasExpiracao(:Tipo => "Corridos") {
117
+ xml.text attributes[:dias_expiracao]
118
+ }
119
+ xml.Instrucao1 {
120
+ xml.text attributes[:instrucao_1]
121
+ }
122
+ xml.URLLogo {
123
+ xml.text attributes[:url_logo]
124
+ }
125
+ }
126
+ end
127
+
128
+ if attributes[:url_retorno]
129
+ # URL de retorno
130
+ xml.URLRetorno {
131
+ xml.text attributes[:url_retorno]
132
+ }
133
+ end
134
+
135
+ }
136
+ }
137
+ end
138
+
139
+ builder.to_xml
140
+ end
141
+
142
+ end
143
+
144
+ end
145
+
146
+ end
data/moip.gemspec ADDED
@@ -0,0 +1,27 @@
1
+ # -*- encoding: utf-8 -*-
2
+
3
+ Gem::Specification.new do |gem|
4
+ gem.name = %q{moip-ruby}
5
+
6
+
7
+ gem.authors = ["Guilherme Nascimento"]
8
+ gem.date = %q{2010-11-10}
9
+ gem.description = %q{Gem para utilização da API MoIP}
10
+ gem.email = %q{guilherme.ruby@gmail.com}
11
+ gem.summary = %q{Gem para utilização da API MoIP}
12
+
13
+ gem.files = `git ls-files`.split("\n")
14
+ gem.test_files = `git ls-files -- spec/*.rb`.split("\n")
15
+
16
+ gem.homepage = %q{http://github.com/moiplabs/moip-ruby}
17
+ gem.require_paths = ["lib"]
18
+
19
+ gem.rdoc_options = ["--charset=UTF-8"]
20
+ gem.extra_rdoc_files = [ "LICENSE", "README.markdown"]
21
+
22
+ gem.add_development_dependency(%q<rspec>, ["~> 2.1.0"])
23
+
24
+ gem.add_runtime_dependency(%q<nokogiri>, ["~> 1.4.2"])
25
+ gem.add_runtime_dependency(%q<httparty>, ["~> 0.8.1"])
26
+ gem.add_runtime_dependency(%q<activesupport>, [">= 2.3.2"])
27
+ end
data/spec/moip_spec.rb ADDED
@@ -0,0 +1,289 @@
1
+ # encoding: utf-8
2
+ require "moip"
3
+
4
+ require "digest/sha1"
5
+
6
+ describe "Make payments with the MoIP API" do
7
+
8
+ before :all do
9
+ MoIP.setup do |config|
10
+ config.uri = 'https://desenvolvedor.moip.com.br/sandbox'
11
+ config.token = 'token'
12
+ config.key = 'key'
13
+ end
14
+
15
+ @pagador = { :nome => "Luiz Inácio Lula da Silva",
16
+ :login_moip => "lula",
17
+ :email => "presidente@planalto.gov.br",
18
+ :tel_cel => "(61)9999-9999",
19
+ :apelido => "Lula",
20
+ :identidade => "111.111.111-11",
21
+ :logradouro => "Praça dos Três Poderes",
22
+ :numero => "0",
23
+ :complemento => "Palácio do Planalto",
24
+ :bairro => "Zona Cívico-Administrativa",
25
+ :cidade => "Brasília",
26
+ :estado => "DF",
27
+ :pais => "BRA",
28
+ :cep => "70100-000",
29
+ :tel_fixo => "(61)3211-1221" }
30
+
31
+ @billet_without_razao = { :value => "8.90", :id_proprio => id,
32
+ :forma => "BoletoBancario", :pagador => @pagador}
33
+ @billet = { :value => "8.90", :id_proprio => id,
34
+ :forma => "BoletoBancario", :pagador => @pagador ,
35
+ :razao=> "Pagamento" }
36
+
37
+ @debit = { :value => "8.90", :id_proprio => id, :forma => "DebitoBancario",
38
+ :instituicao => "BancoDoBrasil", :pagador => @pagador,
39
+ :razao => "Pagamento"}
40
+
41
+ @credit = { :value => "8.90", :id_proprio => id, :forma => "CartaoCredito",
42
+ :instituicao => "AmericanExpress",:numero => "345678901234564",
43
+ :expiracao => "08/11", :codigo_seguranca => "1234",
44
+ :nome => "João Silva", :identidade => "134.277.017.00",
45
+ :telefone => "(21)9208-0547", :data_nascimento => "25/10/1980",
46
+ :parcelas => "2", :recebimento => "AVista",
47
+ :pagador => @pagador, :razao => "Pagamento"}
48
+ end
49
+
50
+ context "checkout" do
51
+ before(:each) do
52
+ MoIP::Client.stub!(:post).
53
+ and_return("ns1:EnviarInstrucaoUnicaResponse"=>
54
+ { "Resposta"=>
55
+ { "ID"=>Time.now.strftime("%y%m%d%H%M%S"),
56
+ "Status"=>"Sucesso",
57
+ "Token" => "T2N0L0X8E0S71217U2H3W1T4F4S4G4K731D010V0S0V0S080M010E0Q082X2"
58
+ }
59
+ })
60
+ end
61
+
62
+ it "with old api should be deprecated" do
63
+ deprecations = collect_deprecations{ MoIP.checkout(@billet) }
64
+
65
+ deprecations.should_not be_empty
66
+ deprecations.any? {|w| w =~ /MoIP.checkout has been deprecated/ }.should be_true
67
+ end
68
+
69
+ context "when it is a billet checkout" do
70
+ it "should raise an exception when razao parameter is not passed" do
71
+ error = "É necessário informar a razão do pagamento"
72
+
73
+ lambda { MoIP::Client.checkout(@billet_without_razao) }.should
74
+ raise_error(MoIP::MissingPaymentTypeError,error)
75
+ end
76
+
77
+ it "should have status 'Sucesso'" do
78
+ response = MoIP::Client.checkout(@billet)
79
+ response["Status"].should == "Sucesso"
80
+ end
81
+ end
82
+
83
+ context "when it is a debit checkout" do
84
+ it "should have status 'Sucesso' with valid arguments" do
85
+ response = MoIP::Client.checkout(@debit)
86
+ response["Status"].should == "Sucesso"
87
+ end
88
+
89
+ it "should have status 'Falha' when a instituition is not passed as argument" do
90
+ @incorrect_debit = { :value => "37.90", :id_proprio => id,
91
+ :forma => "DebitoBancario", :pagador => @pagador,
92
+ :razao => "Pagamento"}
93
+
94
+ error = "Pagamento direto não é possível com a instituição de pagamento enviada"
95
+
96
+ MoIP::Client.stub!(:post)
97
+ .and_return("ns1:EnviarInstrucaoUnicaResponse"=>
98
+ { "Resposta"=>
99
+ {
100
+ "Status"=>"Falha",
101
+ "Erro"=>error
102
+ }
103
+ })
104
+ error = "Pagamento direto não é possível com a instituição de pagamento enviada"
105
+ lambda { MoIP::Client.checkout(@incorrect_debit) }.should
106
+ raise_error(MoIP::WebServerResponseError, error)
107
+ end
108
+
109
+ it "should raise an exception if payer informations were not passed" do
110
+ @incorrect_debit = { :value => "37.90", :id_proprio => id,
111
+ :forma => "DebitoBancario",
112
+ :instituicao => "BancoDoBrasil",
113
+ :razao => "Pagamento"
114
+ }
115
+
116
+ lambda { MoIP::Client.checkout(@incorrect_debit) }.should
117
+ raise_error(MoIP::MissingPayerError, "É obrigatório passar as informações do pagador")
118
+ end
119
+ end
120
+
121
+ context "when it is a credit card checkout" do
122
+ it "should have status 'Sucesso' with valid arguments" do
123
+ response = MoIP::Client.checkout(@credit)
124
+ response["Status"].should == "Sucesso"
125
+ end
126
+
127
+ it "should have status 'Falha' when the card informations were not passed as argument" do
128
+ @incorrect_credit = { :value => "8.90", :id_proprio => id,
129
+ :forma => "CartaoCredito", :pagador => @pagador,
130
+ :razao => "Pagamento"
131
+ }
132
+
133
+ error = "Pagamento direto não é possível com a instituição de pagamento enviada"
134
+ MoIP::Client.stub!(:post)
135
+ .and_return("ns1:EnviarInstrucaoUnicaResponse"=>
136
+ {
137
+ "Resposta"=>
138
+ {
139
+ "Status"=>"Falha",
140
+ "Erro"=>error
141
+ }
142
+ })
143
+
144
+ error = "Pagamento direto não é possível com a instituição de pagamento enviada"
145
+ lambda { MoIP::Client.checkout(@incorrect_credit) }.should
146
+ raise_error(MoIP::WebServerResponseError, error)
147
+ end
148
+ end
149
+
150
+ context "in error scenario" do
151
+ it "should raise an exception if response is nil" do
152
+ MoIP::Client.stub!(:post).and_return(nil)
153
+ lambda { MoIP::Client.checkout(@billet) }.should
154
+ raise_error(StandardError,"Ocorreu um erro ao chamar o webservice")
155
+ end
156
+
157
+ it "should raise an exception if status is fail" do
158
+ MoIP::Client.stub!(:post)
159
+ .and_return("ns1:EnviarInstrucaoUnicaResponse"=>
160
+ { "Resposta"=>
161
+ {"Status"=>"Falha",
162
+ "Erro"=>"O status da resposta é Falha"
163
+ }
164
+ })
165
+
166
+ lambda { MoIP::Client.checkout(@billet) }.should raise_error(StandardError, "O status da resposta é Falha")
167
+ end
168
+ end
169
+ end
170
+
171
+ context "query a transaction token" do
172
+ before(:each) do
173
+ MoIP::Client.stub!(:get)
174
+ .and_return("ns1:ConsultarTokenResponse"=>
175
+ { "RespostaConsultar"=>
176
+ {"Status"=>"Sucesso",
177
+ "ID"=>"201010291031001210000000046760"
178
+ }
179
+ })
180
+ end
181
+
182
+ it "with old api should be deprecated" do
183
+ deprecations = collect_deprecations{ MoIP.query(token) }
184
+
185
+ deprecations.should_not be_empty
186
+ deprecations.any? {|w| w =~ /MoIP.query has been deprecated/ }.should be_true
187
+ end
188
+
189
+ it "should retrieve the transaction" do
190
+ response = MoIP::Client.query(token)
191
+ response["Status"].should == "Sucesso"
192
+ end
193
+
194
+ context "in a error scenario" do
195
+ it "should retrieve status 'Falha'" do
196
+ MoIP::Client.stub!(:get)
197
+ .and_return("ns1:ConsultarTokenResponse"=>
198
+ { "RespostaConsultar"=>
199
+ {"Status"=>"Falha",
200
+ "Erro"=>"Instrução não encontrada",
201
+ "ID"=>"201010291102522860000000046768"
202
+ }
203
+ })
204
+ query = "000000000000000000000000000000000000000000000000000000000000"
205
+ lambda { MoIP::Client.query(query) }.should raise_error(StandardError, "Instrução não encontrada")
206
+ end
207
+ end
208
+ end
209
+
210
+ context "build the MoIP URL" do
211
+ it "with old api should be deprecated" do
212
+ deprecations = collect_deprecations{ MoIP.moip_page(token) }
213
+
214
+ deprecations.should_not be_empty
215
+ deprecations.any? {|w| w =~ /MoIP.moip_page has been deprecated/ }.should be_true
216
+ end
217
+
218
+ it "should build the correct URL" do
219
+ page = "https://desenvolvedor.moip.com.br/sandbox/Instrucao.do?token=#{token}"
220
+ MoIP::Client.moip_page(token).should == page
221
+ end
222
+
223
+ it "should raise an error if the token is not informed" do
224
+ error = "É necessário informar um token para retornar os dados da transação"
225
+ lambda { MoIP::Client.moip_page("").should
226
+ raise_error(ArgumentError, error) }
227
+ end
228
+
229
+ it "should raise an error if nil is passed as the token" do
230
+ error = "É necessário informar um token para retornar os dados da transação"
231
+ lambda { MoIP::Client.moip_page(nil).should
232
+ raise_error(ArgumentError, error) }
233
+ end
234
+ end
235
+
236
+ context "when receive notification" do
237
+ before(:each) do
238
+ @params = { "id_transacao" => "Pag62", "valor" => "8.90",
239
+ "status_pagamento" => "3", "cod_moip" => "001",
240
+ "forma_pagamento" => "73", "tipo_pagamento" => "BoletoBancario",
241
+ "email_consumidor" => "presidente@planalto.gov.br" }
242
+ end
243
+
244
+ it "with old api should be deprecated" do
245
+ deprecations = collect_deprecations{ MoIP.notification(@param) }
246
+
247
+ deprecations.should_not be_empty
248
+ deprecations.any? {|w| w =~ /MoIP.notification has been deprecated/ }.should be_true
249
+ end
250
+
251
+ it "should return a hash with the params extracted from NASP" do
252
+ response = { :transaction_id => "Pag62", :amount => "8.90",
253
+ :status => "printed", :code => "001",
254
+ :payment_type => "BoletoBancario",
255
+ :email => "presidente@planalto.gov.br" }
256
+
257
+ MoIP::Client.notification(@params).should == response
258
+ end
259
+
260
+ it "should return valid status based on status code" do
261
+ MoIP::STATUS[1].should == "authorized"
262
+ MoIP::STATUS[2].should == "started"
263
+ MoIP::STATUS[3].should == "printed"
264
+ MoIP::STATUS[4].should == "completed"
265
+ MoIP::STATUS[5].should == "canceled"
266
+ MoIP::STATUS[6].should == "analysing"
267
+ end
268
+ end
269
+
270
+ def id
271
+ "transaction_" + Digest::SHA1.hexdigest([Time.now, rand].join)
272
+ end
273
+
274
+ def token
275
+ "T2X0Q1N021E0B2S9U1P0V3Y0G1F570Y2P4M0P000M0Z0F0J0G0U4N6C7W5T9"
276
+ end
277
+
278
+ def collect_deprecations
279
+ old_behavior = ActiveSupport::Deprecation.behavior
280
+ deprecations = []
281
+ ActiveSupport::Deprecation.behavior = Proc.new do |message, callstack|
282
+ deprecations << message
283
+ end
284
+ result = yield
285
+ deprecations
286
+ ensure
287
+ ActiveSupport::Deprecation.behavior = old_behavior
288
+ end
289
+ end
metadata ADDED
@@ -0,0 +1,164 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: moip-ruby
3
+ version: !ruby/object:Gem::Version
4
+ prerelease: false
5
+ segments:
6
+ - 0
7
+ - 1
8
+ - 0
9
+ segments_generated: true
10
+ version: 0.1.0
11
+ platform: ruby
12
+ authors:
13
+ - Guilherme Nascimento
14
+ autorequire:
15
+ bindir: bin
16
+ cert_chain: []
17
+
18
+ date: 2012-04-29 00:00:00 -03:00
19
+ default_executable:
20
+ dependencies:
21
+ - !ruby/object:Gem::Dependency
22
+ prerelease: false
23
+ type: :runtime
24
+ name: moip-ruby
25
+ version_requirements: &id001 !ruby/object:Gem::Requirement
26
+ requirements:
27
+ - - ">="
28
+ - !ruby/object:Gem::Version
29
+ segments:
30
+ - 0
31
+ segments_generated: true
32
+ version: "0"
33
+ requirement: *id001
34
+ - !ruby/object:Gem::Dependency
35
+ prerelease: false
36
+ type: :development
37
+ name: rspec
38
+ version_requirements: &id002 !ruby/object:Gem::Requirement
39
+ requirements:
40
+ - - ~>
41
+ - !ruby/object:Gem::Version
42
+ segments:
43
+ - 2
44
+ - 1
45
+ - 0
46
+ segments_generated: true
47
+ version: 2.1.0
48
+ requirement: *id002
49
+ - !ruby/object:Gem::Dependency
50
+ prerelease: false
51
+ type: :development
52
+ name: rspec
53
+ version_requirements: &id003 !ruby/object:Gem::Requirement
54
+ requirements:
55
+ - - ~>
56
+ - !ruby/object:Gem::Version
57
+ segments:
58
+ - 2
59
+ - 1
60
+ - 0
61
+ segments_generated: true
62
+ version: 2.1.0
63
+ requirement: *id003
64
+ - !ruby/object:Gem::Dependency
65
+ prerelease: false
66
+ type: :runtime
67
+ name: nokogiri
68
+ version_requirements: &id004 !ruby/object:Gem::Requirement
69
+ requirements:
70
+ - - ~>
71
+ - !ruby/object:Gem::Version
72
+ segments:
73
+ - 1
74
+ - 4
75
+ - 3
76
+ segments_generated: true
77
+ version: 1.4.3
78
+ requirement: *id004
79
+ - !ruby/object:Gem::Dependency
80
+ prerelease: false
81
+ type: :runtime
82
+ name: httparty
83
+ version_requirements: &id005 !ruby/object:Gem::Requirement
84
+ requirements:
85
+ - - ~>
86
+ - !ruby/object:Gem::Version
87
+ segments:
88
+ - 0
89
+ - 8
90
+ - 1
91
+ segments_generated: true
92
+ version: 0.8.1
93
+ requirement: *id005
94
+ - !ruby/object:Gem::Dependency
95
+ prerelease: false
96
+ type: :runtime
97
+ name: activesupport
98
+ version_requirements: &id006 !ruby/object:Gem::Requirement
99
+ requirements:
100
+ - - ">="
101
+ - !ruby/object:Gem::Version
102
+ segments:
103
+ - 2
104
+ - 3
105
+ - 2
106
+ segments_generated: true
107
+ version: 2.3.2
108
+ requirement: *id006
109
+ description: "Gem para utiliza\xC3\xA7\xC3\xA3o da API MoIP"
110
+ email: guilherme.ruby@gmail.com
111
+ executables: []
112
+
113
+ extensions: []
114
+
115
+ extra_rdoc_files:
116
+ - LICENSE
117
+ - README.markdown
118
+ files:
119
+ - .document
120
+ - Gemfile
121
+ - Gemfile.lock
122
+ - LICENSE
123
+ - README.markdown
124
+ - Rakefile
125
+ - VERSION
126
+ - lib/moip.rb
127
+ - lib/moip/client.rb
128
+ - lib/moip/direct_payment.rb
129
+ - moip.gemspec
130
+ - spec/moip_spec.rb
131
+ has_rdoc: true
132
+ homepage: http://github.com/guinascimento/moip
133
+ licenses: []
134
+
135
+ post_install_message:
136
+ rdoc_options: []
137
+
138
+ require_paths:
139
+ - lib
140
+ required_ruby_version: !ruby/object:Gem::Requirement
141
+ requirements:
142
+ - - ">="
143
+ - !ruby/object:Gem::Version
144
+ segments:
145
+ - 0
146
+ segments_generated: true
147
+ version: "0"
148
+ required_rubygems_version: !ruby/object:Gem::Requirement
149
+ requirements:
150
+ - - ">="
151
+ - !ruby/object:Gem::Version
152
+ segments:
153
+ - 0
154
+ segments_generated: true
155
+ version: "0"
156
+ requirements: []
157
+
158
+ rubyforge_project:
159
+ rubygems_version: 1.3.6
160
+ signing_key:
161
+ specification_version: 3
162
+ summary: "Gem para utiliza\xC3\xA7\xC3\xA3o da API MoIP"
163
+ test_files: []
164
+