moiper 0.1.1 → 0.1.2
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/.travis.yml +10 -0
- data/README.md +11 -1
- data/lib/moiper.rb +25 -9
- data/lib/moiper/notification.rb +25 -0
- data/lib/moiper/notification_controller_helper.rb +27 -0
- data/lib/moiper/payment.rb +31 -9
- data/lib/moiper/railtie.rb +4 -0
- data/lib/moiper/request.rb +15 -4
- data/lib/moiper/response.rb +8 -0
- data/lib/moiper/version.rb +1 -2
- data/spec/moiper/payment_spec.rb +9 -0
- data/spec/moiper/request_spec.rb +1 -2
- metadata +9 -8
data/.travis.yml
ADDED
data/README.md
CHANGED
@@ -1,5 +1,7 @@
|
|
1
1
|
# Moiper
|
2
2
|
|
3
|
+
[](https://travis-ci.org/reu/moiper)
|
4
|
+
|
3
5
|
[Moip payment service](http://moip.com.br/) integration library.
|
4
6
|
|
5
7
|
## Installation
|
@@ -59,7 +61,7 @@ You need to redirect your user to the url returned by `response.checkout_url`. A
|
|
59
61
|
|
60
62
|
### Notifications
|
61
63
|
|
62
|
-
Moip will notify your application about order updates through [NASP](http://labs.moip.com.br/referencia/nasp/). Moiper provides a Rails controller helper
|
64
|
+
Moip will notify your application about order updates through [NASP](http://labs.moip.com.br/referencia/nasp/). Moiper provides a Rails controller helper so you can easily intercept these notifications with the `moip_notification` method.
|
63
65
|
|
64
66
|
```ruby
|
65
67
|
class OrdersController < ApplicationController
|
@@ -81,6 +83,14 @@ class OrdersController < ApplicationController
|
|
81
83
|
end
|
82
84
|
```
|
83
85
|
|
86
|
+
If you are not using Rails, you can manually instantiate a Moiper::Notification class by passing the POST parameters received from Moip's request.
|
87
|
+
|
88
|
+
```ruby
|
89
|
+
post "/moip/callback" do
|
90
|
+
notification = Moiper::Notification.new(params)
|
91
|
+
end
|
92
|
+
```
|
93
|
+
|
84
94
|
#### Payment Status
|
85
95
|
|
86
96
|
Following are the possible payment statuses returned by the `Moip::Notification#payment_status`.
|
data/lib/moiper.rb
CHANGED
@@ -6,31 +6,47 @@ require "moiper/notification"
|
|
6
6
|
require "moiper/railtie" if defined? Rails
|
7
7
|
|
8
8
|
module Moiper
|
9
|
+
# The available Moip entrypoints
|
10
|
+
# @see http://labs.moip.com.br/referencia/autenticacao_api/#ambientes
|
11
|
+
# The Moip's official documentation regarding its entrypoints
|
9
12
|
API_ENTRYPOINTS = {
|
10
13
|
:sandbox => "https://desenvolvedor.moip.com.br/sandbox/",
|
11
14
|
:production => "https://www.moip.com.br/"
|
12
15
|
}
|
13
16
|
|
14
17
|
class << self
|
15
|
-
#
|
18
|
+
# @!group Configurable options
|
19
|
+
|
20
|
+
# @return [String] Moip's API token
|
16
21
|
attr_accessor :token
|
17
22
|
|
18
|
-
#
|
23
|
+
# @return [String] Moip's API key
|
19
24
|
attr_accessor :key
|
20
25
|
|
21
26
|
# Define if requests should be made against Moip's sandbox
|
22
27
|
# environment. This is specially usefull when running
|
23
|
-
# on development or test mode. Default is false
|
28
|
+
# on development or test mode. Default is false
|
29
|
+
#
|
30
|
+
# @see http://labs.moip.com.br/referencia/autenticacao_api/#sandbox
|
31
|
+
# Moip's official documentation regarding sandbox activation
|
24
32
|
#
|
25
|
-
#
|
33
|
+
# @example
|
34
|
+
# Moiper.sandbox = true
|
26
35
|
#
|
36
|
+
# @return [Boolean] current sandbox state
|
27
37
|
attr_accessor :sandbox
|
28
38
|
|
29
|
-
#
|
39
|
+
# @!endgroup
|
40
|
+
|
41
|
+
# Configure Moiper's options
|
42
|
+
#
|
43
|
+
# @yieldparam config [Moiper]
|
44
|
+
# @return [void]
|
30
45
|
#
|
31
|
-
#
|
32
|
-
#
|
33
|
-
#
|
46
|
+
# @example
|
47
|
+
# Moiper.configure do |config|
|
48
|
+
# config.sandbox = true
|
49
|
+
# end
|
34
50
|
#
|
35
51
|
def configure(&block)
|
36
52
|
yield self
|
@@ -41,7 +57,7 @@ module Moiper
|
|
41
57
|
sandbox == true
|
42
58
|
end
|
43
59
|
|
44
|
-
#
|
60
|
+
# @return [String] the Moip API entrypoint based on the current environment
|
45
61
|
def api_entrypoint
|
46
62
|
sandbox? ? API_ENTRYPOINTS[:sandbox] : API_ENTRYPOINTS[:production]
|
47
63
|
end
|
data/lib/moiper/notification.rb
CHANGED
@@ -1,5 +1,7 @@
|
|
1
1
|
module Moiper
|
2
2
|
class Notification
|
3
|
+
# @see http://labs.moip.com.br/parametro/statuspagamento/
|
4
|
+
# The list of payment status on the Moip's official documentation
|
3
5
|
PAYMENT_STATUSES = {
|
4
6
|
1 => :authorized,
|
5
7
|
2 => :started,
|
@@ -11,6 +13,8 @@ module Moiper
|
|
11
13
|
9 => :reimbursed
|
12
14
|
}
|
13
15
|
|
16
|
+
# @see http://labs.moip.com.br/parametro/instituicaopagamento/
|
17
|
+
# The list of financial institutions on the Moip's official documentation
|
14
18
|
FINANCIAL_INSTITUTIONS = {
|
15
19
|
1 => "MoIP",
|
16
20
|
3 => "Visa",
|
@@ -25,6 +29,8 @@ module Moiper
|
|
25
29
|
88 => "Banrisul"
|
26
30
|
}
|
27
31
|
|
32
|
+
# @see http://labs.moip.com.br/parametro/formapagamento/
|
33
|
+
# The list of payment methods on the Moip's official documentation
|
28
34
|
PAYMENT_METHODS = {
|
29
35
|
"BoletoBancario" => :payment_form,
|
30
36
|
"CartaoDeCredito" => :credit_card,
|
@@ -41,38 +47,57 @@ module Moiper
|
|
41
47
|
@params = params
|
42
48
|
end
|
43
49
|
|
50
|
+
# @return [String] informed unique identifier
|
44
51
|
def id
|
45
52
|
params["id_transacao"]
|
46
53
|
end
|
47
54
|
|
55
|
+
# @return [Float] amount paid by the user
|
48
56
|
def price
|
49
57
|
params["valor"].to_i / 100.0
|
50
58
|
end
|
51
59
|
|
60
|
+
# @return [Symbol] payment status
|
61
|
+
# @see PAYMENT_STATUSES The full list of possible payment statuses
|
62
|
+
# returned
|
52
63
|
def payment_status
|
53
64
|
PAYMENT_STATUSES[params["status_pagamento"].to_i]
|
54
65
|
end
|
55
66
|
|
67
|
+
# @return [Integer] the internal Moip identifier for this transaction
|
56
68
|
def moip_id
|
57
69
|
params["cod_moip"].to_i
|
58
70
|
end
|
59
71
|
|
72
|
+
# @return [String] financial institution name
|
73
|
+
# @see FINANCIAL_INSTITUTIONS The full list of possible financial
|
74
|
+
# institutions returned
|
60
75
|
def financial_institution
|
61
76
|
FINANCIAL_INSTITUTIONS[params["forma_pagamento"].to_i]
|
62
77
|
end
|
63
78
|
|
79
|
+
# @return [String] payment method used by this transaction
|
80
|
+
# @see PAYMENT_METHODS The full list of possible payment
|
81
|
+
# method returned
|
64
82
|
def payment_method
|
65
83
|
PAYMENT_METHODS[params["tipo_pagamento"]]
|
66
84
|
end
|
67
85
|
|
86
|
+
# @return [Integer] number of quotas that the payment was
|
87
|
+
# divided
|
68
88
|
def quotas
|
69
89
|
params["parcelas"].to_i
|
70
90
|
end
|
71
91
|
|
92
|
+
# @return [String] user email address
|
72
93
|
def user_email
|
73
94
|
params["email_consumidor"]
|
74
95
|
end
|
75
96
|
|
97
|
+
# @return [String] additional information provided by the financial
|
98
|
+
# institution regarding this transaction when it has a canceled status
|
99
|
+
# @see http://labs.moip.com.br/referencia/classificacao-de-cancelamento/
|
100
|
+
# The Moip's official documentation regarting payment cancelling
|
76
101
|
def additional_info
|
77
102
|
params["classificacao"]
|
78
103
|
end
|
@@ -1,5 +1,32 @@
|
|
1
1
|
module Moiper
|
2
2
|
module NotificationControllerHelper
|
3
|
+
# Helper method to abstract how to create a notification during the Moip's
|
4
|
+
# NASP request.
|
5
|
+
#
|
6
|
+
# @see http://labs.moip.com.br/referencia/nasp/ Moip's NASP documentation
|
7
|
+
#
|
8
|
+
# @param data [Hash] controller parameters
|
9
|
+
# @yieldparam [Notification] notification update from Moip
|
10
|
+
# @return [Notification]
|
11
|
+
#
|
12
|
+
# @example Usage inside a Rails controller
|
13
|
+
# class OrdersController < ApplicationController
|
14
|
+
# include Moiper::NotificationControllerHelper
|
15
|
+
#
|
16
|
+
# def confirm
|
17
|
+
# moip_notification do |notification|
|
18
|
+
# # Here you can update your database with updated information.
|
19
|
+
# # Ex:
|
20
|
+
# @order = Order.find_by_unique_identifier(notification.id)
|
21
|
+
# @order.update_attribute :status, notification.payment_status
|
22
|
+
# @order.save
|
23
|
+
#
|
24
|
+
# # Moip will recognize the request as successfully if the statuses
|
25
|
+
# # are 200, 201, 202, 203, 204, 205, 206 or 207.
|
26
|
+
# head 200
|
27
|
+
# end
|
28
|
+
# end
|
29
|
+
# end
|
3
30
|
def moip_notification(data = params, &block)
|
4
31
|
notification = Notification.new(data)
|
5
32
|
yield notification if block_given?
|
data/lib/moiper/payment.rb
CHANGED
@@ -2,27 +2,44 @@ require "nokogiri"
|
|
2
2
|
|
3
3
|
module Moiper
|
4
4
|
class Payment
|
5
|
-
#
|
6
|
-
#
|
5
|
+
# @return [String] the unique ID you can set for this payment. This is usefull to keep
|
6
|
+
# track of which payment we will receive on the Moip's notification process
|
7
7
|
attr_accessor :id
|
8
8
|
|
9
|
-
#
|
9
|
+
# @return [String] the description of the purchase
|
10
10
|
attr_accessor :description
|
11
11
|
|
12
|
-
#
|
12
|
+
# @return [Float] the amount to be billed from the user
|
13
13
|
attr_accessor :price
|
14
14
|
|
15
|
-
#
|
16
|
-
|
15
|
+
# @return [Float] the amount to be increased from the final price
|
16
|
+
attr_accessor :accretion
|
17
|
+
|
18
|
+
# @return [Float] the amount to be deducted from the final price
|
19
|
+
attr_accessor :deduction
|
20
|
+
|
21
|
+
# @return [String] the URL where the user will be redirected after he finishes the
|
22
|
+
# payment process.
|
17
23
|
attr_accessor :return_url
|
18
24
|
|
19
|
-
#
|
25
|
+
# @return [String] the URL where Moip will send notifications about your purchase updates
|
20
26
|
attr_accessor :notification_url
|
21
27
|
|
22
28
|
# Create a new Moip Payment request
|
29
|
+
#
|
30
|
+
# @param [Hash] options the options to create the payment with
|
31
|
+
# @option options [String] :description {#description}
|
32
|
+
# @option options [String, #to_s] :id {#id}
|
33
|
+
# @option options [#to_f] :price {#price}
|
34
|
+
# @option options [#to_f] :accretion {#accretion}
|
35
|
+
# @option options [#to_f] :deduction {#deduction}
|
36
|
+
# @option options [String, #to_s] :return_url {#return_url}
|
37
|
+
# @option options [String, #to_s] :notification_url {#notification_url}
|
38
|
+
#
|
39
|
+
# @raise [ArgumentError] if description or price options are blank
|
23
40
|
def initialize(options = {})
|
24
|
-
raise ArgumentError if options[:description].nil? || options[:description].empty?
|
25
|
-
raise ArgumentError if options[:price].nil? || options[:price].to_f <= 0
|
41
|
+
raise ArgumentError, "You must inform a description" if options[:description].nil? || options[:description].empty?
|
42
|
+
raise ArgumentError, "You must inform a price" if options[:price].nil? || options[:price].to_f <= 0
|
26
43
|
|
27
44
|
options.each do |attribute, value|
|
28
45
|
send "#{attribute}=", value
|
@@ -30,6 +47,7 @@ module Moiper
|
|
30
47
|
end
|
31
48
|
|
32
49
|
# Create the payment XML representation
|
50
|
+
# @return [String] Moip's formatted XML
|
33
51
|
def to_xml
|
34
52
|
builder = Nokogiri::XML::Builder.new(:encoding => "UTF-8") do |xml|
|
35
53
|
xml.EnviarInstrucao {
|
@@ -39,6 +57,8 @@ module Moiper
|
|
39
57
|
|
40
58
|
xml.Valores {
|
41
59
|
xml.Valor price, :moeda => "BRL"
|
60
|
+
xml.Acrescimo accretion, :moeda => "BRL" if accretion
|
61
|
+
xml.Deducao deduction, :moeda => "BRL" if deduction
|
42
62
|
}
|
43
63
|
|
44
64
|
xml.URLNotificacao notification_url if notification_url
|
@@ -50,6 +70,8 @@ module Moiper
|
|
50
70
|
builder.to_xml
|
51
71
|
end
|
52
72
|
|
73
|
+
# Send a new payment request to Moip
|
74
|
+
# @return [Response] the Moip response
|
53
75
|
def checkout
|
54
76
|
request = Request.new
|
55
77
|
request.process(to_xml)
|
data/lib/moiper/railtie.rb
CHANGED
@@ -2,6 +2,7 @@ module Moiper
|
|
2
2
|
class Railtie < Rails::Railtie
|
3
3
|
# Expose Moiper's configuration to the Rails application configuration.
|
4
4
|
#
|
5
|
+
# @example
|
5
6
|
# module MyApplication
|
6
7
|
# class Application < Rails::Application
|
7
8
|
# config.moiper.sandbox = true
|
@@ -11,10 +12,13 @@ module Moiper
|
|
11
12
|
# end
|
12
13
|
config.moiper = Moiper
|
13
14
|
|
15
|
+
# Load notification controller helper
|
14
16
|
initializer "load notification controller helper" do
|
15
17
|
require "moiper/notification_controller_helper"
|
16
18
|
end
|
17
19
|
|
20
|
+
# Automatically read and configure Moiper with the content
|
21
|
+
# of the config/moiper.yml file if it is present
|
18
22
|
initializer "load moiper.yml file" do
|
19
23
|
config_file = Rails.root.join("config", "moiper.yml")
|
20
24
|
|
data/lib/moiper/request.rb
CHANGED
@@ -5,13 +5,17 @@ module Moiper
|
|
5
5
|
class Request
|
6
6
|
CA_FILE = File.expand_path(File.dirname(__FILE__)) + "/cacert.pem"
|
7
7
|
|
8
|
-
|
9
|
-
|
8
|
+
# Process a given payload
|
9
|
+
# @param payload [String]
|
10
|
+
# @return [Response] the response from Moip
|
10
11
|
def process(payload)
|
11
|
-
|
12
|
-
Response.new(
|
12
|
+
response = post(payload)
|
13
|
+
Response.new(response.body)
|
13
14
|
end
|
14
15
|
|
16
|
+
# @!group HTTP handling
|
17
|
+
|
18
|
+
# @return [Net::HTTP::Session] the http session client
|
15
19
|
def client
|
16
20
|
@client ||= Net::HTTP.new(uri.host, uri.port).tap do |http|
|
17
21
|
http.use_ssl = true
|
@@ -20,6 +24,9 @@ module Moiper
|
|
20
24
|
end
|
21
25
|
end
|
22
26
|
|
27
|
+
# @return [Net::HTTP::Post] the http POST request already
|
28
|
+
# configured with the right agent, content type and
|
29
|
+
# basic authentication headers
|
23
30
|
def request
|
24
31
|
@request ||= Net::HTTP::Post.new(uri.path).tap do |request|
|
25
32
|
request.basic_auth Moiper.token, Moiper.key
|
@@ -28,6 +35,8 @@ module Moiper
|
|
28
35
|
end
|
29
36
|
end
|
30
37
|
|
38
|
+
# @!endgroup
|
39
|
+
|
31
40
|
private
|
32
41
|
|
33
42
|
def post(payload)
|
@@ -39,6 +48,8 @@ module Moiper
|
|
39
48
|
@uri ||= URI(Moiper.api_entrypoint + path)
|
40
49
|
end
|
41
50
|
|
51
|
+
# @api private
|
52
|
+
# @return [String] path where the request should be made
|
42
53
|
def path
|
43
54
|
"ws/alpha/EnviarInstrucao/Unica"
|
44
55
|
end
|
data/lib/moiper/response.rb
CHANGED
@@ -1,21 +1,29 @@
|
|
1
1
|
module Moiper
|
2
2
|
class Response
|
3
|
+
# @param body [String] the response body from Moip
|
3
4
|
def initialize(body)
|
4
5
|
@body = body
|
5
6
|
end
|
6
7
|
|
8
|
+
# Detects if the response was successfully
|
9
|
+
# @return [Boolean]
|
7
10
|
def success?
|
8
11
|
parsed_body.css("Status").text == "Sucesso"
|
9
12
|
end
|
10
13
|
|
14
|
+
# @return [String, nil] the URL which the user should be redirected
|
15
|
+
# to finish payment process or nil if the request was not successfully
|
11
16
|
def checkout_url
|
12
17
|
Moiper.api_entrypoint + "Instrucao.do?token=" + token if success?
|
13
18
|
end
|
14
19
|
|
20
|
+
# @return [String] the response token
|
15
21
|
def token
|
16
22
|
parsed_body.css("Token").text
|
17
23
|
end
|
18
24
|
|
25
|
+
# List the possible errors returned by Moip
|
26
|
+
# @return [Array<String>]
|
19
27
|
def errors
|
20
28
|
parsed_body.css("Erro").map(&:text)
|
21
29
|
end
|
data/lib/moiper/version.rb
CHANGED
data/spec/moiper/payment_spec.rb
CHANGED
@@ -82,6 +82,8 @@ describe Moiper::Payment do
|
|
82
82
|
Moiper::Payment.new(
|
83
83
|
:description => "A chair",
|
84
84
|
:price => 1.99,
|
85
|
+
:accretion => 0.5,
|
86
|
+
:deduction => 0.3,
|
85
87
|
:id => "some unique id",
|
86
88
|
:return_url => "http://example.org/thank_you",
|
87
89
|
:notification_url => "http://example.org/moip/notification"
|
@@ -99,9 +101,16 @@ describe Moiper::Payment do
|
|
99
101
|
it { doc.at_css("InstrucaoUnica > URLNotificacao").should_not be_nil }
|
100
102
|
|
101
103
|
it { doc.at_css("InstrucaoUnica > IdProprio").text.should eq "some unique id"}
|
104
|
+
|
102
105
|
it { doc.at_css("Valores > Valor").text.should eq "1.99"}
|
103
106
|
it { doc.at_css("Valores > Valor").attributes["moeda"].value.should eq "BRL"}
|
104
107
|
|
108
|
+
it { doc.at_css("Valores > Acrescimo").text.should eq "0.5"}
|
109
|
+
it { doc.at_css("Valores > Acrescimo").attributes["moeda"].value.should eq "BRL"}
|
110
|
+
|
111
|
+
it { doc.at_css("Valores > Deducao").text.should eq "0.3"}
|
112
|
+
it { doc.at_css("Valores > Deducao").attributes["moeda"].value.should eq "BRL"}
|
113
|
+
|
105
114
|
it { doc.at_css("InstrucaoUnica > URLRetorno").text.should eq "http://example.org/thank_you" }
|
106
115
|
it { doc.at_css("InstrucaoUnica > URLNotificacao").text.should eq "http://example.org/moip/notification" }
|
107
116
|
|
data/spec/moiper/request_spec.rb
CHANGED
@@ -34,8 +34,7 @@ describe Moiper::Request do
|
|
34
34
|
end
|
35
35
|
|
36
36
|
it "has the correct user agent" do
|
37
|
-
|
38
|
-
headers["User-Agent"].should eq "Moiper/#{Moiper::VERSION}"
|
37
|
+
subject.get_fields("user-agent")[0].should eq "Moiper/#{Moiper::VERSION}"
|
39
38
|
end
|
40
39
|
end
|
41
40
|
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: moiper
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.1.
|
4
|
+
version: 0.1.2
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,11 +9,11 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2013-01-
|
12
|
+
date: 2013-01-25 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: nokogiri
|
16
|
-
requirement: &
|
16
|
+
requirement: &2160708660 !ruby/object:Gem::Requirement
|
17
17
|
none: false
|
18
18
|
requirements:
|
19
19
|
- - ! '>='
|
@@ -21,10 +21,10 @@ dependencies:
|
|
21
21
|
version: '0'
|
22
22
|
type: :runtime
|
23
23
|
prerelease: false
|
24
|
-
version_requirements: *
|
24
|
+
version_requirements: *2160708660
|
25
25
|
- !ruby/object:Gem::Dependency
|
26
26
|
name: rspec
|
27
|
-
requirement: &
|
27
|
+
requirement: &2160708220 !ruby/object:Gem::Requirement
|
28
28
|
none: false
|
29
29
|
requirements:
|
30
30
|
- - ! '>='
|
@@ -32,7 +32,7 @@ dependencies:
|
|
32
32
|
version: '0'
|
33
33
|
type: :development
|
34
34
|
prerelease: false
|
35
|
-
version_requirements: *
|
35
|
+
version_requirements: *2160708220
|
36
36
|
description: Moip payment service integration library.
|
37
37
|
email:
|
38
38
|
- rnavarro1@gmail.com
|
@@ -41,6 +41,7 @@ extensions: []
|
|
41
41
|
extra_rdoc_files: []
|
42
42
|
files:
|
43
43
|
- .gitignore
|
44
|
+
- .travis.yml
|
44
45
|
- Gemfile
|
45
46
|
- LICENSE.txt
|
46
47
|
- README.md
|
@@ -76,7 +77,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
76
77
|
version: '0'
|
77
78
|
segments:
|
78
79
|
- 0
|
79
|
-
hash:
|
80
|
+
hash: -1487992565957500539
|
80
81
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
81
82
|
none: false
|
82
83
|
requirements:
|
@@ -85,7 +86,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
85
86
|
version: '0'
|
86
87
|
segments:
|
87
88
|
- 0
|
88
|
-
hash:
|
89
|
+
hash: -1487992565957500539
|
89
90
|
requirements: []
|
90
91
|
rubyforge_project:
|
91
92
|
rubygems_version: 1.8.11
|