edools_mymoip 0.8.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (57) hide show
  1. checksums.yaml +7 -0
  2. data/.document +5 -0
  3. data/.gitignore +15 -0
  4. data/.travis.yml +4 -0
  5. data/CHANGELOG.md +128 -0
  6. data/Gemfile +4 -0
  7. data/LICENSE.txt +20 -0
  8. data/README.md +3 -0
  9. data/Rakefile +10 -0
  10. data/lib/mymoip.rb +57 -0
  11. data/lib/mymoip/bank_debit.rb +22 -0
  12. data/lib/mymoip/commission.rb +54 -0
  13. data/lib/mymoip/credit_card.rb +73 -0
  14. data/lib/mymoip/exceptions.rb +15 -0
  15. data/lib/mymoip/formatter.rb +23 -0
  16. data/lib/mymoip/instruction.rb +134 -0
  17. data/lib/mymoip/json_parser.rb +11 -0
  18. data/lib/mymoip/payer.rb +75 -0
  19. data/lib/mymoip/payment.rb +10 -0
  20. data/lib/mymoip/payment_methods.rb +46 -0
  21. data/lib/mymoip/payment_slip.rb +74 -0
  22. data/lib/mymoip/payments/bank_debit_payment.rb +27 -0
  23. data/lib/mymoip/payments/credit_card_payment.rb +53 -0
  24. data/lib/mymoip/payments/payment_slip_payment.rb +12 -0
  25. data/lib/mymoip/purchase.rb +40 -0
  26. data/lib/mymoip/request.rb +34 -0
  27. data/lib/mymoip/requests/payment_request.rb +53 -0
  28. data/lib/mymoip/requests/transparent_request.rb +36 -0
  29. data/lib/mymoip/validators.rb +12 -0
  30. data/lib/mymoip/version.rb +3 -0
  31. data/mymoip.gemspec +30 -0
  32. data/test/fixtures/fixture.rb +73 -0
  33. data/test/fixtures/vcr_cassettes/payment_request.yml +37 -0
  34. data/test/fixtures/vcr_cassettes/payment_request_with_payment_slip.yml +32 -0
  35. data/test/fixtures/vcr_cassettes/transparent_request.yml +34 -0
  36. data/test/fixtures/vcr_cassettes/transparent_request_with_commissions.yml +35 -0
  37. data/test/lib/test_bank_debit.rb +36 -0
  38. data/test/lib/test_bank_debit_payment.rb +32 -0
  39. data/test/lib/test_commission.rb +121 -0
  40. data/test/lib/test_credit_card_payment.rb +107 -0
  41. data/test/lib/test_creditcard.rb +206 -0
  42. data/test/lib/test_formatter.rb +49 -0
  43. data/test/lib/test_instruction.rb +243 -0
  44. data/test/lib/test_mymoip.rb +79 -0
  45. data/test/lib/test_payer.rb +249 -0
  46. data/test/lib/test_payment.rb +15 -0
  47. data/test/lib/test_payment_methods.rb +54 -0
  48. data/test/lib/test_payment_request.rb +120 -0
  49. data/test/lib/test_payment_slip.rb +78 -0
  50. data/test/lib/test_payment_slip_payment.rb +8 -0
  51. data/test/lib/test_purchase.rb +109 -0
  52. data/test/lib/test_request.rb +88 -0
  53. data/test/lib/test_transparent_request.rb +71 -0
  54. data/test/lib/test_validators.rb +13 -0
  55. data/test/live_test.rb +4 -0
  56. data/test/test_helper.rb +17 -0
  57. 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
@@ -0,0 +1,11 @@
1
+ module MyMoip
2
+ class JsonParser
3
+ def self.call(body, format)
4
+ if format == :json
5
+ JSON.parse body.match(/\?\((?<valid_json>.+)\)/)[:valid_json]
6
+ else
7
+ body
8
+ end
9
+ end
10
+ end
11
+ end
@@ -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,10 @@
1
+ module MyMoip
2
+ class Payment
3
+ def self.payment_method
4
+ name.gsub(/^MyMoip::|Payment$/, '').gsub(/([a-z])([A-Z])/,'\1_\2').downcase.to_sym
5
+ end
6
+ end
7
+ end
8
+
9
+ payments = Dir[File.dirname(__FILE__) + "/payments/*.rb"]
10
+ payments.each { |f| require f }
@@ -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
@@ -0,0 +1,12 @@
1
+ module MyMoip
2
+ class PaymentSlipPayment < Payment
3
+
4
+ def to_json
5
+ json = {
6
+ Forma: 'BoletoBancario'
7
+ }
8
+
9
+ json
10
+ end
11
+ end
12
+ end