akatus 0.1.0 → 1.0.0

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.
Files changed (47) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +1 -16
  3. data/.rspec +2 -0
  4. data/LICENSE +1 -1
  5. data/Rakefile +6 -1
  6. data/akatus.gemspec +18 -11
  7. data/config/i18n.rb +3 -0
  8. data/lib/akatus.rb +34 -4
  9. data/lib/akatus/address.rb +11 -0
  10. data/lib/akatus/configuration.rb +43 -0
  11. data/lib/akatus/errors.rb +4 -0
  12. data/lib/akatus/formatters.rb +22 -0
  13. data/lib/akatus/installment.rb +6 -0
  14. data/lib/akatus/installment_options.rb +24 -0
  15. data/lib/akatus/item.rb +24 -0
  16. data/lib/akatus/payer.rb +35 -0
  17. data/lib/akatus/payment.rb +61 -0
  18. data/lib/akatus/payment_option.rb +6 -0
  19. data/lib/akatus/payment_types.rb +37 -0
  20. data/lib/akatus/phone.rb +6 -0
  21. data/lib/akatus/receiver.rb +6 -0
  22. data/lib/akatus/service.rb +34 -0
  23. data/lib/akatus/services/installments.rb +54 -0
  24. data/lib/akatus/services/payment_options.rb +95 -0
  25. data/lib/akatus/services/transaction.rb +50 -0
  26. data/lib/akatus/split_fee.rb +6 -0
  27. data/lib/akatus/transferrable.rb +58 -0
  28. data/lib/akatus/version.rb +1 -1
  29. data/locales/pt-BR.yml +69 -0
  30. data/spec/address_spec.rb +38 -0
  31. data/spec/factories/address_factories.rb +18 -0
  32. data/spec/factories/item_factories.rb +35 -0
  33. data/spec/factories/payer_factories.rb +8 -0
  34. data/spec/factories/phone_factories.rb +6 -0
  35. data/spec/item_spec.rb +42 -0
  36. data/spec/payer_spec.rb +31 -0
  37. data/spec/phone_spec.rb +23 -0
  38. data/spec/services/installments_spec.rb +36 -0
  39. data/spec/services/payment_options_spec.rb +22 -0
  40. data/spec/services/transaction_spec.rb +80 -0
  41. data/spec/spec_helper.rb +31 -0
  42. data/spec/support/configuration.rb +7 -0
  43. data/spec/support/shared_examples/transferrable_example.rb +22 -0
  44. metadata +142 -12
  45. data/LICENSE.txt +0 -22
  46. data/lib/akatus/configuracao.rb +0 -40
  47. data/lib/akatus/formatadores.rb +0 -7
@@ -0,0 +1,6 @@
1
+ module Akatus
2
+ class Receiver
3
+ include Transferrable
4
+ transferrable_attrs :email, :api_key
5
+ end
6
+ end
@@ -0,0 +1,34 @@
1
+ module Akatus
2
+
3
+ class Service
4
+
5
+ def send_request
6
+
7
+ path = self.class::PATH
8
+ method = self.class::METHOD
9
+
10
+ url = Akatus.config.api_url + path + ".json"
11
+ payload = self.to_payload
12
+
13
+ begin
14
+
15
+ if method == :post
16
+ data = RestClient.post(url, payload.to_json, :content_type => :json, :accept => :json)
17
+ elsif method == :get
18
+ data = RestClient.get(url, { :params => payload })
19
+ else
20
+ raise "Invalid method: #{method}"
21
+ end
22
+
23
+ JSON.parse(data)['resposta']
24
+
25
+ rescue RestClient::UnprocessableEntity => exc
26
+ message = JSON.load(exc.response)['resposta']['descricao']
27
+ raise Akatus::UnprocessableEntityError.new(message)
28
+ end
29
+
30
+ end
31
+
32
+ end
33
+
34
+ end
@@ -0,0 +1,54 @@
1
+ module Akatus
2
+
3
+ module Services
4
+
5
+ class Installments < Akatus::Service
6
+
7
+ PATH = 'parcelamento/simulacao'
8
+ METHOD = :get
9
+
10
+ def self.calculate(payment)
11
+ self.new.calculate(payment)
12
+ end
13
+
14
+ def calculate(payment)
15
+
16
+ @payment = payment
17
+
18
+ unless payment.payment_method.is_a?(CreditCard)
19
+ return InstallmentOptions.blank(payment)
20
+ end
21
+
22
+ data = send_request
23
+
24
+ options = InstallmentOptions.new
25
+
26
+ options.description = data['descricao']
27
+ options.taken_installments = data['parcelas_assumidas']
28
+
29
+ options.installments = data['parcelas'].map do |parcela|
30
+ Installment.new({
31
+ :quantity => parcela['quantidade'],
32
+ :unitary_amount => BigDecimal.new(parcela['valor']),
33
+ :total_amount => BigDecimal.new(parcela['total'])
34
+ })
35
+ end
36
+
37
+ options
38
+
39
+ end
40
+
41
+ def to_payload
42
+ {
43
+ :email => @payment.receiver.email,
44
+ :amount => @payment.total_amount,
45
+ :payment_method => @payment.payment_method.brand,
46
+ :api_key => @payment.receiver.api_key
47
+ }
48
+ end
49
+
50
+ end
51
+
52
+ end
53
+
54
+ end
@@ -0,0 +1,95 @@
1
+ # encoding: utf-8
2
+
3
+ module Akatus
4
+
5
+ module Services
6
+
7
+ class PaymentOptions < Akatus::Service
8
+
9
+ PATH = 'meios-de-pagamento'
10
+ METHOD = :post
11
+
12
+ def self.available
13
+ self.new.available
14
+ end
15
+
16
+ def self.available_with_installments(*args)
17
+ self.new.available_with_installments(*args)
18
+ end
19
+
20
+ def available
21
+ data = send_request
22
+ result = {}
23
+
24
+ data['meios_de_pagamento'].each do |payment_type|
25
+
26
+ key = payment_description_to_type(payment_type['descricao'])
27
+
28
+ options = payment_type['bandeiras'].map do |payment_option|
29
+ PaymentOption.new({
30
+ :code => payment_option['codigo'],
31
+ :description => payment_option['descricao'],
32
+ :installments => payment_option['parcelas']
33
+ })
34
+ end
35
+
36
+ result[key] = {
37
+ :name => payment_type['descricao'],
38
+ :options => options
39
+ }
40
+
41
+ end
42
+
43
+ result
44
+ end
45
+
46
+ def available_with_installments(transaction)
47
+
48
+ result = available()
49
+
50
+ result.each do |type, group|
51
+ group[:options].each do |option|
52
+ transaction.payment_method = payment_type_to_class(type).new({ :brand => option.code })
53
+ option.installments = Installments.calculate(transaction)
54
+ end
55
+ end
56
+
57
+ result
58
+
59
+ end
60
+
61
+ def payment_description_to_type(group)
62
+ case group
63
+ when 'Boleto Bancário' then :boleto
64
+ when 'Cartão de Crédito' then :credit_card
65
+ when 'TEF' then :eft
66
+ else raise "Unknown payment group: #{group}"
67
+ end
68
+ end
69
+
70
+ def payment_type_to_class(type)
71
+ case type
72
+ when :boleto then Akatus::BoletoBancario
73
+ when :credit_card then Akatus::CreditCard
74
+ when :eft then Akatus::ElectronicFundsTransfer
75
+ else raise "Unknown payment group: #{group}"
76
+ end
77
+ end
78
+
79
+
80
+ def to_payload
81
+ {
82
+ :meios_de_pagamento => {
83
+ :correntista => {
84
+ :email => Akatus.config.email,
85
+ :api_key => Akatus.config.api_key
86
+ }
87
+ }
88
+ }
89
+ end
90
+
91
+ end
92
+
93
+ end
94
+
95
+ end
@@ -0,0 +1,50 @@
1
+ module Akatus
2
+
3
+ module Services
4
+
5
+ class Transaction < Akatus::Service
6
+
7
+ PATH = 'carrinho'
8
+ METHOD = :post
9
+
10
+ def self.form_url
11
+ Akatus.config.base_url + PATH
12
+ end
13
+
14
+ def self.create(*args)
15
+ self.new.create(*args)
16
+ end
17
+
18
+ def create(payment)
19
+
20
+ @payment = payment
21
+
22
+ data = send_request
23
+
24
+ @payment.id = data['carrinho']
25
+
26
+ # TODO: improve; use constants?
27
+ @payment.status = data['status']
28
+ @payment.transaction_id = data['transacao']
29
+
30
+ if data['url_retorno']
31
+ @payment.url = data['url_retorno'].sub("https://www.akatus.com/", Akatus.config.base_url)
32
+ end
33
+
34
+ @payment
35
+
36
+ end
37
+
38
+ def status
39
+ # TODO: implement.
40
+ end
41
+
42
+ def to_payload
43
+ @payment.to_payload
44
+ end
45
+
46
+ end
47
+
48
+ end
49
+
50
+ end
@@ -0,0 +1,6 @@
1
+ module Akatus
2
+ class SplitFee
3
+ include Transferrable
4
+ transferrable_attrs :receiver, :type, :amount
5
+ end
6
+ end
@@ -0,0 +1,58 @@
1
+ module Akatus
2
+
3
+ module Transferrable
4
+
5
+ def self.included(klass)
6
+ klass.send(:extend, ClassMethods)
7
+ end
8
+
9
+ def initialize(attrs = {})
10
+ attrs.each { |attr, val| send("#{attr}=", val) }
11
+ end
12
+
13
+ def to_payload(include_root = true)
14
+ class_key = self.class.name.demodulize.underscore
15
+
16
+ payload = Hash[(self.class.attributes || []).map do |attr|
17
+
18
+ attr_value = send(attr)
19
+
20
+ next if attr_value.nil?
21
+
22
+ if attr_value.respond_to?(:to_payload)
23
+ attr_value = attr_value.to_payload(false)
24
+ end
25
+
26
+ if NUMERIC_FIELDS.include?(attr)
27
+ attr_value = Akatus.format_number(attr_value)
28
+ end
29
+
30
+ if (INTEGER_FIELDS + STRING_FIELDS).include?(attr)
31
+ attr_value = attr_value.to_s
32
+ end
33
+
34
+ [ I18n.t(attr, :locale => "pt-BR", :scope => [:payload, :attributes, class_key]), attr_value ]
35
+ end]
36
+
37
+ if include_root
38
+ { I18n.t(class_key, :locale => "pt-BR", :scope => [:payload]) => payload }
39
+ else
40
+ payload
41
+ end
42
+
43
+ end
44
+
45
+ module ClassMethods
46
+ def attributes
47
+ @attributes
48
+ end
49
+
50
+ def transferrable_attrs(*args)
51
+ @attributes = *args
52
+ attr_accessor(*args)
53
+ end
54
+ end
55
+
56
+ end
57
+
58
+ end
@@ -1,3 +1,3 @@
1
1
  module Akatus
2
- VERSION = "0.1.0"
2
+ VERSION = "1.0.0"
3
3
  end
data/locales/pt-BR.yml ADDED
@@ -0,0 +1,69 @@
1
+ # encoding: utf-8
2
+
3
+ "pt-BR":
4
+
5
+ payload:
6
+
7
+ address: endereco
8
+ credit_card: cartao_de_credito
9
+ item: produto
10
+ payer: pagador
11
+ phone: telefone
12
+ receiver: recebedor
13
+ split_fee: comissionamento
14
+ transaction: carrinho
15
+
16
+ attributes:
17
+
18
+ address:
19
+ additional_details: complemento
20
+ city: cidade
21
+ country: pais
22
+ neighborhood: bairro
23
+ number: numero
24
+ postal_code: cep
25
+ reference: referencia
26
+ state: estado
27
+ street: logradouro
28
+ type: tipo
29
+
30
+ credit_card:
31
+ brand: meio_de_pagamento
32
+ expiration: expiracao
33
+ installments: parcelas
34
+ number: numero
35
+ security_code: codigo_de_seguranca
36
+
37
+ electronic_funds_transfer:
38
+ brand: meio_de_pagamento
39
+
40
+ item:
41
+ description: descricao
42
+ discount: desconto
43
+ price: preco
44
+ quantity: quantidade
45
+ reference: codigo
46
+ shipping_cost: frete
47
+ split_fee: comissionamento
48
+ weight: peso
49
+
50
+ payer:
51
+ name: nome
52
+ email: email
53
+
54
+ phone:
55
+ type: tipo
56
+ number: numero
57
+
58
+ receiver:
59
+ api_key: api_key
60
+ email: email
61
+
62
+ split_fee:
63
+ amount: valor
64
+ receiver: recebedor
65
+ type: tipo
66
+
67
+ transaction:
68
+ payer: pagador
69
+ receiver: recebedor
@@ -0,0 +1,38 @@
1
+ # encoding: utf-8
2
+
3
+ describe Akatus::Address do
4
+
5
+ let(:attrs) {
6
+ {
7
+ :type => 'entrega',
8
+ :street => 'Rua Labib Marrar',
9
+ :number => '129',
10
+ :neighborhood => 'Jardim Santa Cruz',
11
+ :city => 'São Paulo',
12
+ :state => 'SP',
13
+ :country => 'BRA',
14
+ :postal_code => '04182040',
15
+ :additional_details => 'Apto. 33',
16
+ :reference => 'Perto da padaria do Seu Zé'
17
+ }
18
+ }
19
+
20
+ let(:payload) {
21
+ {
22
+ 'endereco' => {
23
+ 'tipo' => 'entrega',
24
+ 'logradouro' => 'Rua Labib Marrar',
25
+ 'numero' => '129',
26
+ 'bairro' => 'Jardim Santa Cruz',
27
+ 'complemento' => 'Apto. 33',
28
+ 'cidade' => 'São Paulo',
29
+ 'estado' => 'SP',
30
+ 'pais' => 'BRA',
31
+ 'cep' => '04182040'
32
+ }
33
+ }
34
+ }
35
+
36
+ it_behaves_like Akatus::Transferrable
37
+
38
+ end
@@ -0,0 +1,18 @@
1
+ # encoding: utf-8
2
+
3
+ FactoryGirl.define do
4
+
5
+ factory :address, :class => Akatus::Address do
6
+ type 'entrega'
7
+ street 'Rua Labib Marrar'
8
+ number '129'
9
+ neighborhood 'Jardim Santa Cruz'
10
+ city 'São Paulo'
11
+ state 'SP'
12
+ country 'BRA'
13
+ postal_code '04182040'
14
+ additional_details 'Apto. 33'
15
+ reference 'Perto da padaria do Seu Zé'
16
+ end
17
+
18
+ end