edools_mymoip 0.8.1
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.
- checksums.yaml +7 -0
- data/.document +5 -0
- data/.gitignore +15 -0
- data/.travis.yml +4 -0
- data/CHANGELOG.md +128 -0
- data/Gemfile +4 -0
- data/LICENSE.txt +20 -0
- data/README.md +3 -0
- data/Rakefile +10 -0
- data/lib/mymoip.rb +57 -0
- data/lib/mymoip/bank_debit.rb +22 -0
- data/lib/mymoip/commission.rb +54 -0
- data/lib/mymoip/credit_card.rb +73 -0
- data/lib/mymoip/exceptions.rb +15 -0
- data/lib/mymoip/formatter.rb +23 -0
- data/lib/mymoip/instruction.rb +134 -0
- data/lib/mymoip/json_parser.rb +11 -0
- data/lib/mymoip/payer.rb +75 -0
- data/lib/mymoip/payment.rb +10 -0
- data/lib/mymoip/payment_methods.rb +46 -0
- data/lib/mymoip/payment_slip.rb +74 -0
- data/lib/mymoip/payments/bank_debit_payment.rb +27 -0
- data/lib/mymoip/payments/credit_card_payment.rb +53 -0
- data/lib/mymoip/payments/payment_slip_payment.rb +12 -0
- data/lib/mymoip/purchase.rb +40 -0
- data/lib/mymoip/request.rb +34 -0
- data/lib/mymoip/requests/payment_request.rb +53 -0
- data/lib/mymoip/requests/transparent_request.rb +36 -0
- data/lib/mymoip/validators.rb +12 -0
- data/lib/mymoip/version.rb +3 -0
- data/mymoip.gemspec +30 -0
- data/test/fixtures/fixture.rb +73 -0
- data/test/fixtures/vcr_cassettes/payment_request.yml +37 -0
- data/test/fixtures/vcr_cassettes/payment_request_with_payment_slip.yml +32 -0
- data/test/fixtures/vcr_cassettes/transparent_request.yml +34 -0
- data/test/fixtures/vcr_cassettes/transparent_request_with_commissions.yml +35 -0
- data/test/lib/test_bank_debit.rb +36 -0
- data/test/lib/test_bank_debit_payment.rb +32 -0
- data/test/lib/test_commission.rb +121 -0
- data/test/lib/test_credit_card_payment.rb +107 -0
- data/test/lib/test_creditcard.rb +206 -0
- data/test/lib/test_formatter.rb +49 -0
- data/test/lib/test_instruction.rb +243 -0
- data/test/lib/test_mymoip.rb +79 -0
- data/test/lib/test_payer.rb +249 -0
- data/test/lib/test_payment.rb +15 -0
- data/test/lib/test_payment_methods.rb +54 -0
- data/test/lib/test_payment_request.rb +120 -0
- data/test/lib/test_payment_slip.rb +78 -0
- data/test/lib/test_payment_slip_payment.rb +8 -0
- data/test/lib/test_purchase.rb +109 -0
- data/test/lib/test_request.rb +88 -0
- data/test/lib/test_transparent_request.rb +71 -0
- data/test/lib/test_validators.rb +13 -0
- data/test/live_test.rb +4 -0
- data/test/test_helper.rb +17 -0
- metadata +251 -0
@@ -0,0 +1,134 @@
|
|
1
|
+
require File.expand_path(File.dirname(__FILE__) + '/validators.rb')
|
2
|
+
module MyMoip
|
3
|
+
class Instruction
|
4
|
+
include Validators
|
5
|
+
include ActiveModel::Validations
|
6
|
+
|
7
|
+
attr_accessor :id, :payment_reason, :values, :payer,
|
8
|
+
:commissions, :fee_payer_login, :payment_receiver_login,
|
9
|
+
:payment_receiver_name, :installments,
|
10
|
+
:notification_url, :return_url,
|
11
|
+
:payment_slip, :payment_methods
|
12
|
+
|
13
|
+
validates_presence_of :id, :payment_reason, :values, :payer
|
14
|
+
validate :commissions_value_must_be_lesser_than_values
|
15
|
+
validate :payment_receiver_presence_in_commissions
|
16
|
+
validate :url_format_validation
|
17
|
+
|
18
|
+
def initialize(attrs)
|
19
|
+
attrs.each do |attr, value|
|
20
|
+
public_send(:"#{attr}=", value)
|
21
|
+
end
|
22
|
+
|
23
|
+
self.commissions ||= []
|
24
|
+
end
|
25
|
+
|
26
|
+
def to_xml(root = nil)
|
27
|
+
raise InvalidPayer if payer.invalid?
|
28
|
+
raise InvalidPaymentSlip if payment_slip and payment_slip.invalid?
|
29
|
+
raise InvalidInstruction if self.invalid?
|
30
|
+
if invalid_commission = commissions.detect { |c| c.invalid? }
|
31
|
+
raise InvalidComission, invalid_commission
|
32
|
+
end
|
33
|
+
|
34
|
+
xml = ""
|
35
|
+
root = Builder::XmlMarkup.new(target: xml)
|
36
|
+
|
37
|
+
root.EnviarInstrucao do |n1|
|
38
|
+
n1.InstrucaoUnica(TipoValidacao: "Transparente") do |n2|
|
39
|
+
n2.Razao(@payment_reason)
|
40
|
+
n2.Valores do |n3|
|
41
|
+
@values.each { |v| n3.Valor("%.2f" % v, moeda: "BRL") }
|
42
|
+
end
|
43
|
+
n2.IdProprio(@id)
|
44
|
+
|
45
|
+
if @installments
|
46
|
+
n2.Parcelamentos do |n4|
|
47
|
+
@installments.each do |installments|
|
48
|
+
n4.Parcelamento do |n5|
|
49
|
+
n5.MinimoParcelas(installments[:min])
|
50
|
+
n5.MaximoParcelas(installments[:max])
|
51
|
+
if installments[:forward_taxes]
|
52
|
+
n5.Repassar(installments[:forward_taxes])
|
53
|
+
end
|
54
|
+
if installments[:receive_in_installments]
|
55
|
+
n5.Recebimento('Parcelado')
|
56
|
+
end
|
57
|
+
n5.Juros(installments[:fee])
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
commissions_to_xml(n2) if commissions.any?
|
64
|
+
payment_receiver_to_xml(n2) if payment_receiver_login
|
65
|
+
|
66
|
+
n2.Pagador { |n3| @payer.to_xml(n3) }
|
67
|
+
|
68
|
+
unless @payment_methods.blank? or @payment_methods.using_all?
|
69
|
+
n2.FormasPagamento { |n3| @payment_methods.to_xml(n3) }
|
70
|
+
end
|
71
|
+
unless @payment_slip.blank?
|
72
|
+
n2.Boleto { |n3| @payment_slip.to_xml(n3) }
|
73
|
+
end
|
74
|
+
unless @notification_url.blank?
|
75
|
+
n2.URLNotificacao(@notification_url)
|
76
|
+
end
|
77
|
+
unless @return_url.blank?
|
78
|
+
n2.URLRetorno(@return_url)
|
79
|
+
end
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|
83
|
+
xml
|
84
|
+
end
|
85
|
+
|
86
|
+
def commissions_sum
|
87
|
+
commissions.inject(0) do |sum, commission|
|
88
|
+
sum + commission.gross_amount(self)
|
89
|
+
end
|
90
|
+
end
|
91
|
+
|
92
|
+
def gross_amount
|
93
|
+
values ? values.reduce(0) { |sum, value| sum + value } : 0
|
94
|
+
end
|
95
|
+
|
96
|
+
protected
|
97
|
+
|
98
|
+
def commissions_value_must_be_lesser_than_values
|
99
|
+
if commissions_sum > gross_amount
|
100
|
+
errors.add(:commissions, "Commissions value sum is greater than instruction value sum")
|
101
|
+
end
|
102
|
+
end
|
103
|
+
|
104
|
+
def payment_receiver_presence_in_commissions
|
105
|
+
if commissions.find { |c| c.receiver_login == payment_receiver_login }
|
106
|
+
errors.add(:payment_receiver_login, "Payment receiver can't be commissioned")
|
107
|
+
end
|
108
|
+
end
|
109
|
+
|
110
|
+
def commissions_to_xml(node)
|
111
|
+
node.Comissoes do |n|
|
112
|
+
commissions.each { |c| c.to_xml(n) }
|
113
|
+
n.PagadorTaxa { |pt| pt.LoginMoIP(fee_payer_login) } if fee_payer_login
|
114
|
+
end
|
115
|
+
end
|
116
|
+
|
117
|
+
def payment_receiver_to_xml(node)
|
118
|
+
node.Recebedor do |n|
|
119
|
+
n.LoginMoIP(payment_receiver_login)
|
120
|
+
n.Apelido(payment_receiver_name)
|
121
|
+
end
|
122
|
+
end
|
123
|
+
|
124
|
+
def url_format_validation
|
125
|
+
if not notification_url.blank? and not valid_url?(notification_url)
|
126
|
+
errors.add(:notification_url, 'Invalid URL format')
|
127
|
+
end
|
128
|
+
|
129
|
+
if not return_url.blank? and not valid_url?(return_url)
|
130
|
+
errors.add(:return_url, 'Invalid URL format.')
|
131
|
+
end
|
132
|
+
end
|
133
|
+
end
|
134
|
+
end
|
data/lib/mymoip/payer.rb
ADDED
@@ -0,0 +1,75 @@
|
|
1
|
+
module MyMoip
|
2
|
+
class Payer
|
3
|
+
include ActiveModel::Validations
|
4
|
+
|
5
|
+
attr_accessor :id, :name, :email,
|
6
|
+
:address_street, :address_street_number,
|
7
|
+
:address_street_extra, :address_neighbourhood,
|
8
|
+
:address_city, :address_state, :address_country,
|
9
|
+
:address_cep, :address_phone
|
10
|
+
|
11
|
+
validates_presence_of :id, :name, :email, :address_street,
|
12
|
+
:address_street_number, :address_neighbourhood,
|
13
|
+
:address_city, :address_state, :address_country,
|
14
|
+
:address_cep, :address_phone
|
15
|
+
validates_length_of :address_state, is: 2
|
16
|
+
validates_length_of :address_country, is: 3
|
17
|
+
validates_length_of :address_cep, is: 8
|
18
|
+
validates_length_of :address_phone, within: 10..11
|
19
|
+
|
20
|
+
def initialize(attrs)
|
21
|
+
attrs.each do |attr, value|
|
22
|
+
public_send(:"#{attr}=", value)
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
def address_cep=(value)
|
27
|
+
value.gsub!(/\D*/, '') unless value.nil?
|
28
|
+
@address_cep = value
|
29
|
+
end
|
30
|
+
|
31
|
+
def address_state=(value)
|
32
|
+
value = value.upcase unless value.nil?
|
33
|
+
@address_state = value
|
34
|
+
end
|
35
|
+
|
36
|
+
def address_country=(value)
|
37
|
+
value = value.upcase unless value.nil?
|
38
|
+
@address_country = value
|
39
|
+
end
|
40
|
+
|
41
|
+
def address_phone=(value)
|
42
|
+
unless value.nil?
|
43
|
+
# Removes non-digits
|
44
|
+
value.gsub!(/\D*/, '')
|
45
|
+
# Removes zeros in the beginning
|
46
|
+
value.gsub!(/\A0*/, '')
|
47
|
+
end
|
48
|
+
@address_phone = value
|
49
|
+
end
|
50
|
+
|
51
|
+
def to_xml(root = nil, formatter = MyMoip::Formatter)
|
52
|
+
if root.nil?
|
53
|
+
xml = ""
|
54
|
+
root ||= Builder::XmlMarkup.new(target: xml)
|
55
|
+
end
|
56
|
+
|
57
|
+
root.Nome(@name)
|
58
|
+
root.Email(@email)
|
59
|
+
root.IdPagador(@id)
|
60
|
+
root.EnderecoCobranca do |n1|
|
61
|
+
n1.Logradouro(@address_street)
|
62
|
+
n1.Numero(@address_street_number)
|
63
|
+
n1.Complemento(@address_street_extra)
|
64
|
+
n1.Bairro(@address_neighbourhood)
|
65
|
+
n1.Cidade(@address_city)
|
66
|
+
n1.Estado(@address_state)
|
67
|
+
n1.Pais(@address_country)
|
68
|
+
n1.CEP(formatter.cep(@address_cep))
|
69
|
+
n1.TelefoneFixo(formatter.phone(@address_phone))
|
70
|
+
end
|
71
|
+
|
72
|
+
xml
|
73
|
+
end
|
74
|
+
end
|
75
|
+
end
|
@@ -0,0 +1,46 @@
|
|
1
|
+
module MyMoip
|
2
|
+
class PaymentMethods
|
3
|
+
include ActiveModel::Validations
|
4
|
+
|
5
|
+
attr_accessor :payment_slip, :credit_card, :debit, :debit_card, :financing,
|
6
|
+
:moip_wallet
|
7
|
+
|
8
|
+
validates_inclusion_of :payment_slip, :credit_card, :debit, :debit_card,
|
9
|
+
:financing, :moip_wallet, in: [true, false]
|
10
|
+
|
11
|
+
def initialize(attrs = {})
|
12
|
+
self.payment_slip = true
|
13
|
+
self.credit_card = true
|
14
|
+
self.debit = true
|
15
|
+
self.debit_card = true
|
16
|
+
self.financing = true
|
17
|
+
self.moip_wallet = true
|
18
|
+
|
19
|
+
attrs.each do |attr, value|
|
20
|
+
public_send(:"#{attr}=", value)
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
def to_xml(root = nil)
|
25
|
+
if root.nil?
|
26
|
+
xml = ""
|
27
|
+
root ||= Builder::XmlMarkup.new(target: xml)
|
28
|
+
end
|
29
|
+
|
30
|
+
if not using_all?
|
31
|
+
root.FormaPagamento('BoletoBancario') if payment_slip
|
32
|
+
root.FormaPagamento('CartaoDeCredito') if credit_card
|
33
|
+
root.FormaPagamento('DebitoBancario') if debit
|
34
|
+
root.FormaPagamento('CartaoDeDebito') if debit_card
|
35
|
+
root.FormaPagamento('FinanciamentoBancario') if financing
|
36
|
+
root.FormaPagamento('CarteiraMoIP') if moip_wallet
|
37
|
+
end
|
38
|
+
|
39
|
+
xml
|
40
|
+
end
|
41
|
+
|
42
|
+
def using_all?
|
43
|
+
payment_slip and credit_card and debit and debit_card and financing and moip_wallet
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
@@ -0,0 +1,74 @@
|
|
1
|
+
module MyMoip
|
2
|
+
class PaymentSlip
|
3
|
+
include Validators
|
4
|
+
include ActiveModel::Validations
|
5
|
+
|
6
|
+
attr_accessor :expiration_date, :expiration_days, :expiration_days_type,
|
7
|
+
:instruction_line_1, :instruction_line_2,
|
8
|
+
:instruction_line_3, :logo_url
|
9
|
+
|
10
|
+
validates_length_of :instruction_line_1, maximum: 63, allow_nil: true
|
11
|
+
validates_length_of :instruction_line_2, maximum: 63, allow_nil: true
|
12
|
+
validates_length_of :instruction_line_3, maximum: 63, allow_nil: true
|
13
|
+
|
14
|
+
validates_numericality_of :expiration_days, less_than_or_equal_to: 99,
|
15
|
+
allow_nil: true
|
16
|
+
validates_inclusion_of :expiration_days_type,
|
17
|
+
in: [:business_day, :calendar_day], allow_nil: true
|
18
|
+
|
19
|
+
validate :logo_url_format
|
20
|
+
validate :expiration_date_format
|
21
|
+
|
22
|
+
def initialize(attrs)
|
23
|
+
attrs.each do |attr, value|
|
24
|
+
public_send(:"#{attr}=", value)
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
def to_xml(root = nil)
|
29
|
+
raise InvalidPaymentSlip if invalid?
|
30
|
+
|
31
|
+
if root.nil?
|
32
|
+
xml = ""
|
33
|
+
root ||= Builder::XmlMarkup.new(target: xml)
|
34
|
+
end
|
35
|
+
|
36
|
+
root.DataVencimento(expiration_date.strftime('%Y-%m-%dT%H:%M:%S.%L%:z')) unless expiration_date.blank?
|
37
|
+
|
38
|
+
if expiration_days
|
39
|
+
type = nil
|
40
|
+
if expiration_days_type
|
41
|
+
if expiration_days_type == :business_day
|
42
|
+
type = {'Tipo' => 'Uteis'}
|
43
|
+
elsif expiration_days_type == :calendar_day
|
44
|
+
type = {'Tipo' => 'Corridos'}
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
root.DiasExpiracao(expiration_days, type)
|
49
|
+
end
|
50
|
+
|
51
|
+
root.Instrucao1(instruction_line_1) unless instruction_line_1.blank?
|
52
|
+
root.Instrucao2(instruction_line_2) unless instruction_line_2.blank?
|
53
|
+
root.Instrucao3(instruction_line_3) unless instruction_line_3.blank?
|
54
|
+
|
55
|
+
root.URLLogo(logo_url) unless logo_url.blank?
|
56
|
+
|
57
|
+
xml
|
58
|
+
end
|
59
|
+
|
60
|
+
private
|
61
|
+
|
62
|
+
def logo_url_format
|
63
|
+
if not logo_url.blank? and not valid_url?(logo_url)
|
64
|
+
errors.add(:logo_url, 'Invalid URL format.')
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
def expiration_date_format
|
69
|
+
if not expiration_date.blank? and not expiration_date.instance_of?(DateTime)
|
70
|
+
errors.add(:expiration_date, 'Expiration date must be a DateTime object.')
|
71
|
+
end
|
72
|
+
end
|
73
|
+
end
|
74
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
module MyMoip
|
2
|
+
class BankDebitPayment < Payment
|
3
|
+
attr_accessor :bank_debit
|
4
|
+
|
5
|
+
def initialize(bank_debit)
|
6
|
+
@bank_debit = bank_debit
|
7
|
+
end
|
8
|
+
|
9
|
+
def to_json
|
10
|
+
raise InvalidBankDebit, "No bank debit information provided." if @bank_debit.nil?
|
11
|
+
raise InvalidBankDebit if @bank_debit.invalid?
|
12
|
+
|
13
|
+
json = {
|
14
|
+
Forma: "DebitoBancario",
|
15
|
+
}
|
16
|
+
|
17
|
+
json[:Instituicao] = {
|
18
|
+
banco_do_brasil: "BancoDoBrasil",
|
19
|
+
bradesco: "Bradesco",
|
20
|
+
banrisul: "Banrisul",
|
21
|
+
itau: "Itau"
|
22
|
+
}.fetch(@bank_debit.bank)
|
23
|
+
|
24
|
+
json
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
@@ -0,0 +1,53 @@
|
|
1
|
+
module MyMoip
|
2
|
+
class CreditCardPayment < Payment
|
3
|
+
attr_accessor :credit_card, :installments
|
4
|
+
|
5
|
+
def initialize(credit_card, opts = {})
|
6
|
+
self.credit_card = credit_card
|
7
|
+
self.installments = opts[:installments] || 1
|
8
|
+
end
|
9
|
+
|
10
|
+
def to_json(formatter = MyMoip::Formatter)
|
11
|
+
raise InvalidCreditCard, 'No credit card provided.' if credit_card.nil?
|
12
|
+
raise InvalidCreditCard if credit_card.invalid?
|
13
|
+
|
14
|
+
json = {
|
15
|
+
Forma: "CartaoCredito",
|
16
|
+
Parcelas: @installments,
|
17
|
+
CartaoCredito: {
|
18
|
+
Numero: credit_card.card_number,
|
19
|
+
Expiracao: credit_card.expiration_date,
|
20
|
+
CodigoSeguranca: credit_card.security_code
|
21
|
+
}
|
22
|
+
}
|
23
|
+
|
24
|
+
json[:CartaoCredito][:Portador] = {
|
25
|
+
Nome: credit_card.owner_name,
|
26
|
+
DataNascimento: (credit_card.owner_birthday and
|
27
|
+
formatter.date(credit_card.owner_birthday)),
|
28
|
+
Telefone: (credit_card.owner_phone and
|
29
|
+
formatter.phone(credit_card.owner_phone)),
|
30
|
+
Identidade: (credit_card.owner_cpf and
|
31
|
+
formatter.cpf(credit_card.owner_cpf))
|
32
|
+
}
|
33
|
+
|
34
|
+
json[:Instituicao] = {
|
35
|
+
american_express: "AmericanExpress",
|
36
|
+
diners: "Diners",
|
37
|
+
hipercard: "Hipercard",
|
38
|
+
mastercard: "Mastercard",
|
39
|
+
visa: "Visa"
|
40
|
+
}.fetch(credit_card.logo)
|
41
|
+
|
42
|
+
if cash?
|
43
|
+
json[:Recebimento] = "AVista"
|
44
|
+
end
|
45
|
+
|
46
|
+
json
|
47
|
+
end
|
48
|
+
|
49
|
+
def cash?
|
50
|
+
@installments == 1
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|