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.
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,40 @@
1
+ module MyMoip
2
+ class Purchase
3
+ attr_accessor :id, :price, :credit_card, :payer, :reason
4
+ attr_reader :code
5
+
6
+ def initialize(attrs)
7
+ @id = attrs.fetch(:id) { rand }
8
+ @price = attrs.fetch(:price)
9
+ @credit_card = MyMoip::CreditCard.new(attrs.fetch(:credit_card))
10
+ @payer = MyMoip::Payer.new(attrs.fetch(:payer))
11
+ @reason = attrs.fetch(:reason)
12
+ end
13
+
14
+ def checkout!
15
+ authorization = get_authorization!
16
+ payment = MyMoip::CreditCardPayment.new(@credit_card,
17
+ installments: 1)
18
+ request = MyMoip::PaymentRequest.new(@id)
19
+ request.api_call(payment, token: authorization.token)
20
+
21
+ @code = request.code
22
+ request.success?
23
+ end
24
+
25
+ private
26
+
27
+ def get_authorization!
28
+ instruction = MyMoip::Instruction.new(
29
+ id: @id,
30
+ payment_reason: @reason,
31
+ values: [@price],
32
+ payer: @payer
33
+ )
34
+
35
+ request = MyMoip::TransparentRequest.new(@id)
36
+ request.api_call(instruction)
37
+ request
38
+ end
39
+ end
40
+ end
@@ -0,0 +1,34 @@
1
+ module MyMoip
2
+ class Request
3
+ include HTTParty
4
+
5
+ attr_reader :id, :response
6
+
7
+ def initialize(id)
8
+ @id = id
9
+ end
10
+
11
+ def api_call(params, opts = {})
12
+ opts[:logger] ||= MyMoip.logger
13
+ opts[:username] ||= MyMoip.token
14
+ opts[:password] ||= MyMoip.key
15
+
16
+ unless opts[:username].present? && opts[:password].present?
17
+ MyMoip.ensure_key_and_token_set!
18
+ end
19
+
20
+ opts[:logger].info "New #{self.class} being sent to MoIP."
21
+ opts[:logger].debug "#{self.class} of ##{@id} with #{params.inspect}"
22
+
23
+ url = MyMoip.api_url + params.delete(:path)
24
+ params[:basic_auth] = { username: opts[:username], password: opts[:password] }
25
+
26
+ @response = HTTParty.send params.delete(:http_method), url, params
27
+
28
+ opts[:logger].debug "#{self.class} of ##{@id} to #{url} had response #{@response.inspect}"
29
+ end
30
+ end
31
+ end
32
+
33
+ requests = Dir[File.dirname(__FILE__) + "/requests/*.rb"]
34
+ requests.each { |f| require f }
@@ -0,0 +1,53 @@
1
+ module MyMoip
2
+ class PaymentRequest < Request
3
+
4
+ HTTP_METHOD = :get
5
+ PATH = "/rest/pagamento?callback=?"
6
+ REQUIRES_AUTH = false
7
+ FORMAT = :json
8
+ PAYMENT_SLIP_PATH = "/Instrucao.do?token="
9
+
10
+ attr_reader :token
11
+
12
+ def api_call(data, opts)
13
+ @token = opts[:token]
14
+
15
+ opts[:referer_url] ||= MyMoip.default_referer_url
16
+ opts[:parser] ||= MyMoip::JsonParser
17
+
18
+ json = JSON.generate({
19
+ pagamentoWidget: {
20
+ referer: opts[:referer_url],
21
+ token: token,
22
+ dadosPagamento: data.to_json
23
+ }
24
+ })
25
+
26
+ params = {
27
+ query: { pagamentoWidget: json },
28
+ http_method: HTTP_METHOD,
29
+ requires_auth: REQUIRES_AUTH,
30
+ path: PATH,
31
+ format: FORMAT
32
+ }
33
+ params[:parser] = opts.delete(:parser) unless opts[:parser].nil?
34
+
35
+ super(params, opts)
36
+ end
37
+
38
+ def success?
39
+ @response && @response["StatusPagamento"] == "Sucesso"
40
+ end
41
+
42
+ def url
43
+ MyMoip.api_url + PAYMENT_SLIP_PATH + token if success?
44
+ end
45
+
46
+ def code
47
+ @response["CodigoMoIP"]
48
+ rescue NoMethodError => e
49
+ nil
50
+ end
51
+
52
+ end
53
+ end
@@ -0,0 +1,36 @@
1
+ module MyMoip
2
+ class TransparentRequest < Request
3
+
4
+ HTTP_METHOD = :post
5
+ PATH = "/ws/alpha/EnviarInstrucao/Unica"
6
+ REQUIRES_AUTH = true
7
+
8
+ def api_call(data, opts = {})
9
+ params = {
10
+ body: data.to_xml,
11
+ http_method: HTTP_METHOD,
12
+ requires_auth: REQUIRES_AUTH,
13
+ path: PATH
14
+ }
15
+
16
+ super(params, opts)
17
+ end
18
+
19
+ def success?
20
+ @response["EnviarInstrucaoUnicaResponse"]["Resposta"]["Status"] == "Sucesso"
21
+ rescue NoMethodError
22
+ false
23
+ end
24
+
25
+ def token
26
+ @response["EnviarInstrucaoUnicaResponse"]["Resposta"]["Token"]
27
+ rescue NoMethodError
28
+ end
29
+
30
+ def id
31
+ @response["EnviarInstrucaoUnicaResponse"]["Resposta"]["ID"]
32
+ rescue NoMethodError
33
+ end
34
+
35
+ end
36
+ end
@@ -0,0 +1,12 @@
1
+ module MyMoip
2
+ module Validators
3
+ private
4
+
5
+ def valid_url?(url)
6
+ uri = URI.parse(url)
7
+ uri.kind_of?(URI::HTTP) or uri.kind_of?(URI::HTTPS)
8
+ rescue URI::InvalidURIError
9
+ false
10
+ end
11
+ end
12
+ end
@@ -0,0 +1,3 @@
1
+ module MyMoip
2
+ VERSION = '0.8.1'
3
+ end
@@ -0,0 +1,30 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'mymoip/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = "edools_mymoip"
8
+ spec.version = MyMoip::VERSION
9
+ spec.authors = ["Vinicius Magalhaes"]
10
+ spec.email = ["viniciusmkm@gmail.com"]
11
+ spec.description = %q{The easier way to use Moip's transparent checkout.}
12
+ spec.summary = %q{MoIP transactions in a gem to call your own.}
13
+ spec.homepage = "https://github.com/Edools/mymoip"
14
+ spec.license = "MIT"
15
+
16
+ spec.files = `git ls-files`.split($/)
17
+ spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
18
+ spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
19
+ spec.require_paths = ["lib"]
20
+
21
+ spec.add_dependency "activemodel"
22
+ spec.add_dependency "builder"
23
+ spec.add_dependency "httparty"
24
+ spec.add_development_dependency "bundler", "~> 1.3"
25
+ spec.add_development_dependency "mocha"
26
+ spec.add_development_dependency "rake"
27
+ spec.add_development_dependency "rdoc", "~> 3.12"
28
+ spec.add_development_dependency "vcr"
29
+ spec.add_development_dependency "webmock"
30
+ end
@@ -0,0 +1,73 @@
1
+ class Fixture
2
+ def self.payer(params = {})
3
+ params = {
4
+ id: "your_own_payer_id",
5
+ name: "Juquinha da Rocha",
6
+ email: "juquinha@rocha.com",
7
+ address_street: "Felipe Neri",
8
+ address_street_number: "406",
9
+ address_street_extra: "Sala 501",
10
+ address_neighbourhood: "Auxiliadora",
11
+ address_city: "Porto Alegre",
12
+ address_state: "RS",
13
+ address_country: "BRA",
14
+ address_cep: "90440-150",
15
+ address_phone: "(51)3040-5060"
16
+ }.merge(params)
17
+ MyMoip::Payer.new(params)
18
+ end
19
+
20
+ def self.instruction(params={})
21
+ params = {
22
+ id: "your_own_instruction_id",
23
+ payment_reason: "some payment_reason",
24
+ values: [100.0, 200.0],
25
+ payer: payer,
26
+ installments: [
27
+ {min: 2, max: 12, forward_taxes: true, fee: 1.99}
28
+ ]
29
+ }.merge(params)
30
+ MyMoip::Instruction.new(params)
31
+ end
32
+
33
+ def self.credit_card(params = {})
34
+ params = {
35
+ logo: :visa,
36
+ card_number: "4916654211627608",
37
+ expiration_date: "06/15",
38
+ security_code: "000",
39
+ owner_name: "Juquinha da Rocha",
40
+ owner_birthday: Date.new(1984, 11, 3),
41
+ owner_phone: "(51)3040-5060",
42
+ owner_cpf: "522.116.706-95"
43
+ }.merge(params)
44
+ MyMoip::CreditCard.new(params)
45
+ end
46
+
47
+ def self.commission(params = {})
48
+ params = {
49
+ reason: 'Because we can',
50
+ receiver_login: 'commissioned_indentifier',
51
+ fixed_value: 23.4
52
+ }.merge(params)
53
+ MyMoip::Commission.new(params)
54
+ end
55
+
56
+ def self.payment_slip(params = {})
57
+ params = {
58
+ expiration_date: DateTime.new(2020, 1, 1),
59
+ expiration_days: 7,
60
+ expiration_days_type: :business_day,
61
+ instruction_line_1: 'Line 1',
62
+ instruction_line_2: 'Line 2',
63
+ instruction_line_3: 'Line 3',
64
+ logo_url: 'http://www.myurl.com/logo.png'
65
+ }.merge(params)
66
+ MyMoip::PaymentSlip.new(params)
67
+ end
68
+
69
+ def self.bank_debit(params = {})
70
+ params = { bank: :itau }.merge(params)
71
+ MyMoip::BankDebit.new(params)
72
+ end
73
+ end
@@ -0,0 +1,37 @@
1
+ ---
2
+ http_interactions:
3
+ - request:
4
+ method: get
5
+ uri: https://YOUR_MOIP_TOKEN:YOUR_MOIP_KEY@desenvolvedor.moip.com.br/sandbox/rest/pagamento?callback=?&pagamentoWidget=%7B%22pagamentoWidget%22:%7B%22referer%22:%22http://localhost/default%22,%22token%22:%22D2O0U1W2K1P1D1R2C2E3H0N3L5X3A2E4E3X0X030T090T0A1D1V2T8X500E3%22,%22dadosPagamento%22:%7B%22Forma%22:%22CartaoCredito%22,%22Parcelas%22:1,%22CartaoCredito%22:%7B%22Numero%22:%224916654211627608%22,%22Expiracao%22:%2206/15%22,%22CodigoSeguranca%22:%22000%22,%22Portador%22:%7B%22Nome%22:%22Juquinha%20da%20Rocha%22,%22DataNascimento%22:%2203/11/1984%22,%22Telefone%22:%22(51)3040-5060%22,%22Identidade%22:%22522.116.706-95%22%7D%7D,%22Instituicao%22:%22Visa%22,%22Recebimento%22:%22AVista%22%7D%7D%7D
6
+ body:
7
+ encoding: US-ASCII
8
+ string: ''
9
+ headers: {}
10
+ response:
11
+ status:
12
+ code: 200
13
+ message: OK
14
+ headers:
15
+ Date:
16
+ - Tue, 13 Nov 2012 01:03:56 GMT
17
+ Server:
18
+ - Apache/2.2.23 (CentOS)
19
+ Content-Length:
20
+ - '272'
21
+ Vary:
22
+ - Accept-Encoding
23
+ Content-Type:
24
+ - application/json
25
+ body:
26
+ encoding: ASCII-8BIT
27
+ string: !binary |-
28
+ Pyh7IlN0YXR1cyI6IkVtQW5hbGlzZSIsIkNvZGlnbyI6MCwiQ29kaWdvUmV0
29
+ b3JubyI6IiIsIlRheGFNb0lQIjoiMTUuMTkiLCJTdGF0dXNQYWdhbWVudG8i
30
+ OiJTdWNlc3NvIiwiQ2xhc3NpZmljYWNhbyI6eyJDb2RpZ28iOjk5OSwiRGVz
31
+ Y3JpY2FvIjoiTsOjbyBzdXBvcnRhZG8gbm8gYW1iaWVudGUgU2FuZGJveCJ9
32
+ LCJDb2RpZ29Nb0lQIjoxMDI1OTYsIk1lbnNhZ2VtIjoiUmVxdWlzacOnw6Nv
33
+ IHByb2Nlc3NhZGEgY29tIHN1Y2Vzc28iLCJUb3RhbFBhZ28iOiIyMDAuMDAi
34
+ fSk=
35
+ http_version:
36
+ recorded_at: Tue, 13 Nov 2012 01:01:06 GMT
37
+ recorded_with: VCR 2.2.5
@@ -0,0 +1,32 @@
1
+ ---
2
+ http_interactions:
3
+ - request:
4
+ method: get
5
+ uri: https://YOUR_MOIP_TOKEN:YOUR_MOIP_KEY@desenvolvedor.moip.com.br/sandbox/rest/pagamento?callback=?&pagamentoWidget=%7B%22pagamentoWidget%22:%7B%22referer%22:%22http://localhost/default%22,%22token%22:%22D2O0U1W2K1P1D1R2C2E3H0N3L5X3A2E4E3X0X030T090T0A1D1V2T8X500E3%22,%22dadosPagamento%22:%7B%22Forma%22:%22BoletoBancario%22%7D%7D%7D
6
+ body:
7
+ encoding: US-ASCII
8
+ string: ''
9
+ headers: {}
10
+ response:
11
+ status:
12
+ code: 200
13
+ message: OK
14
+ headers:
15
+ Date:
16
+ - Tue, 24 Sep 2013 13:46:21 GMT
17
+ Server:
18
+ - Apache
19
+ Content-Length:
20
+ - '92'
21
+ Vary:
22
+ - Accept-Encoding
23
+ Content-Type:
24
+ - application/json
25
+ body:
26
+ encoding: ASCII-8BIT
27
+ string: !binary |-
28
+ Pyh7IkNvZGlnbyI6MCwiU3RhdHVzUGFnYW1lbnRvIjoiU3VjZXNzbyIsIk1l
29
+ bnNhZ2VtIjoiUmVxdWlzaW8gcHJvY2Vzc2FkYSBjb20gc3VjZXNzbyJ9KQ==
30
+ http_version:
31
+ recorded_at: Tue, 24 Sep 2013 13:46:22 GMT
32
+ recorded_with: VCR 2.5.0
@@ -0,0 +1,34 @@
1
+ ---
2
+ http_interactions:
3
+ - request:
4
+ method: post
5
+ uri: https://YOUR_MOIP_TOKEN:YOUR_MOIP_KEY@desenvolvedor.moip.com.br/sandbox/ws/alpha/EnviarInstrucao/Unica
6
+ body:
7
+ encoding: US-ASCII
8
+ string: <EnviarInstrucao><InstrucaoUnica TipoValidacao="Transparente"><Razao>some
9
+ payment_reason</Razao><Valores><Valor moeda="BRL">100.00</Valor><Valor moeda="BRL">200.00</Valor></Valores><IdProprio>my_new_instruction_id</IdProprio><Pagador><Nome>Juquinha
10
+ da Rocha</Nome><Email>juquinha@rocha.com</Email><IdPagador>your_own_payer_id</IdPagador><EnderecoCobranca><Logradouro>Felipe
11
+ Neri</Logradouro><Numero>406</Numero><Complemento>Sala 501</Complemento><Bairro>Auxiliadora</Bairro><Cidade>Porto
12
+ Alegre</Cidade><Estado>RS</Estado><Pais>BRA</Pais><CEP>90440-150</CEP><TelefoneFixo>(51)3040-5060</TelefoneFixo></EnderecoCobranca></Pagador></InstrucaoUnica></EnviarInstrucao>
13
+ headers: {}
14
+ response:
15
+ status:
16
+ code: 200
17
+ message: OK
18
+ headers:
19
+ Date:
20
+ - Tue, 13 Nov 2012 01:03:52 GMT
21
+ Server:
22
+ - Apache/2.2.23 (CentOS)
23
+ Content-Length:
24
+ - '273'
25
+ Vary:
26
+ - Accept-Encoding
27
+ Content-Type:
28
+ - text/xml;charset=UTF-8
29
+ body:
30
+ encoding: US-ASCII
31
+ string: <ns1:EnviarInstrucaoUnicaResponse xmlns:ns1="http://www.moip.com.br/ws/alpha/"><Resposta><ID>201210171118501100000001102691</ID><Status>Sucesso</Status><Token>D2O0U1W2K1P1D1R2C2E3H0N3L5X3A2E4E3X0X030T090T0A1D1V2T8X500E3</Token></Resposta></ns1:EnviarInstrucaoUnicaResponse>
32
+ http_version:
33
+ recorded_at: Tue, 13 Nov 2012 01:01:02 GMT
34
+ recorded_with: VCR 2.2.5
@@ -0,0 +1,35 @@
1
+ ---
2
+ http_interactions:
3
+ - request:
4
+ method: post
5
+ uri: https://YOUR_MOIP_TOKEN:YOUR_MOIP_KEY@desenvolvedor.moip.com.br/sandbox/ws/alpha/EnviarInstrucao/Unica
6
+ body:
7
+ encoding: US-ASCII
8
+ string: <EnviarInstrucao><InstrucaoUnica TipoValidacao="Transparente"><Razao>some
9
+ payment_reason</Razao><Valores><Valor moeda="BRL">100.00</Valor><Valor moeda="BRL">200.00</Valor></Valores><IdProprio>your_own_instruction_id</IdProprio><Comissoes><Comissionamento><Razao>Because
10
+ we can</Razao><Comissionado><LoginMoIP>commissioned_id</LoginMoIP></Comissionado><ValorFixo>5</ValorFixo></Comissionamento></Comissoes><Pagador><Nome>Juquinha
11
+ da Rocha</Nome><Email>juquinha@rocha.com</Email><IdPagador>your_own_payer_id</IdPagador><EnderecoCobranca><Logradouro>Felipe
12
+ Neri</Logradouro><Numero>406</Numero><Complemento>Sala 501</Complemento><Bairro>Auxiliadora</Bairro><Cidade>Porto
13
+ Alegre</Cidade><Estado>RS</Estado><Pais>BRA</Pais><CEP>90440-150</CEP><TelefoneFixo>(51)3040-5060</TelefoneFixo></EnderecoCobranca></Pagador></InstrucaoUnica></EnviarInstrucao>
14
+ headers: {}
15
+ response:
16
+ status:
17
+ code: 200
18
+ message: OK
19
+ headers:
20
+ Date:
21
+ - Wed, 28 Nov 2012 14:20:49 GMT
22
+ Server:
23
+ - Apache/2.2.23 (CentOS)
24
+ Content-Length:
25
+ - '273'
26
+ Vary:
27
+ - Accept-Encoding
28
+ Content-Type:
29
+ - text/xml;charset=UTF-8
30
+ body:
31
+ encoding: US-ASCII
32
+ string: <ns1:EnviarInstrucaoUnicaResponse xmlns:ns1="http://www.moip.com.br/ws/alpha/"><Resposta><ID>YOUR_REQUEST_ID</ID><Status>Sucesso</Status><Token>YOUR_MOIP_TOKEN</Token></Resposta></ns1:EnviarInstrucaoUnicaResponse>
33
+ http_version:
34
+ recorded_at: Wed, 28 Nov 2012 14:17:23 GMT
35
+ recorded_with: VCR 2.2.5
@@ -0,0 +1,36 @@
1
+ require_relative '../test_helper'
2
+
3
+ class TestBankDebit < Test::Unit::TestCase
4
+ def test_initialization_and_setters
5
+ subject = MyMoip::BankDebit.new(bank: :itau)
6
+ assert_equal :itau, subject.bank
7
+ end
8
+
9
+ def test_initialization_and_setters_with_string_keys
10
+ subject = MyMoip::BankDebit.new('bank' => :itau)
11
+ assert_equal :itau, subject.bank
12
+ end
13
+
14
+ def test_validate_presence_of_bank_attribute
15
+ subject = Fixture.bank_debit(bank: nil)
16
+ assert subject.invalid? && subject.errors[:bank].present?,
17
+ 'should be invalid without a bank name'
18
+ end
19
+
20
+ def test_converts_bank_string_to_symbol
21
+ subject = Fixture.bank_debit(bank: "itau")
22
+ assert_equal :itau, subject.bank
23
+ end
24
+
25
+ def test_accepts_any_bank_from_available_banks_constant
26
+ MyMoip::BankDebit::AVAILABLE_BANKS.each do |bank|
27
+ subject = Fixture.bank_debit(bank: bank)
28
+ assert subject.valid?, 'should be valid'
29
+ end
30
+ end
31
+
32
+ def test_dont_accept_bank_out_of_available_banks_constant
33
+ subject = Fixture.bank_debit(bank: :unavailable_bank)
34
+ assert subject.invalid? && subject.errors[:bank].present?, 'should not be valid'
35
+ end
36
+ end