dune-balanced-creditcard 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 (86) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +20 -0
  3. data/.rspec +2 -0
  4. data/.travis.yml +13 -0
  5. data/CHANGELOG.md +5 -0
  6. data/Gemfile +6 -0
  7. data/LICENSE.txt +22 -0
  8. data/README.md +48 -0
  9. data/Rakefile +34 -0
  10. data/app/assets/images/dune/balanced/creditcard/.gitkeep +0 -0
  11. data/app/assets/javascripts/dune/balanced/creditcard/flash.js.coffee +15 -0
  12. data/app/assets/javascripts/dune/balanced/creditcard/payments.js.coffee.erb +86 -0
  13. data/app/assets/javascripts/dune-balanced-creditcard.js +1 -0
  14. data/app/assets/stylesheets/dune/balanced/creditcard/application.css +16 -0
  15. data/app/controllers/dune/balanced/creditcard/application_controller.rb +4 -0
  16. data/app/controllers/dune/balanced/creditcard/payments_controller.rb +84 -0
  17. data/app/models/dune/balanced/creditcard/payment.rb +94 -0
  18. data/app/models/dune/balanced/creditcard/transaction_additional_fee_calculator.rb +12 -0
  19. data/app/models/dune/balanced/creditcard/transaction_fee_calculator_base.rb +31 -0
  20. data/app/models/dune/balanced/creditcard/transaction_inclusive_fee_calculator.rb +13 -0
  21. data/app/views/dune/balanced/creditcard/.gitkeep +0 -0
  22. data/app/views/dune/balanced/creditcard/payments/new.html.slim +98 -0
  23. data/bin/rails +8 -0
  24. data/config/initializers/registration.rb +5 -0
  25. data/config/locales/en.yml +32 -0
  26. data/config/locales/simple_form.en.yml +12 -0
  27. data/config/routes.rb +5 -0
  28. data/dune-balanced-creditcard.gemspec +27 -0
  29. data/lib/dune/balanced/creditcard/engine.rb +9 -0
  30. data/lib/dune/balanced/creditcard/interface.rb +27 -0
  31. data/lib/dune/balanced/creditcard/version.rb +7 -0
  32. data/lib/dune/balanced/creditcard.rb +11 -0
  33. data/lib/float_extensions.rb +11 -0
  34. data/spec/controllers/neighborly/balanced/creditcard/payments_controller_spec.rb +199 -0
  35. data/spec/dummy/README.rdoc +28 -0
  36. data/spec/dummy/Rakefile +6 -0
  37. data/spec/dummy/app/assets/images/.keep +0 -0
  38. data/spec/dummy/app/assets/javascripts/application.js +13 -0
  39. data/spec/dummy/app/assets/stylesheets/application.css +13 -0
  40. data/spec/dummy/app/controllers/application_controller.rb +5 -0
  41. data/spec/dummy/app/controllers/concerns/.keep +0 -0
  42. data/spec/dummy/app/helpers/application_helper.rb +2 -0
  43. data/spec/dummy/app/mailers/.keep +0 -0
  44. data/spec/dummy/app/models/.keep +0 -0
  45. data/spec/dummy/app/models/concerns/.keep +0 -0
  46. data/spec/dummy/app/models/configuration.rb +9 -0
  47. data/spec/dummy/app/models/contribution.rb +32 -0
  48. data/spec/dummy/app/models/match.rb +31 -0
  49. data/spec/dummy/app/models/payment_engine.rb +5 -0
  50. data/spec/dummy/app/models/project.rb +9 -0
  51. data/spec/dummy/app/models/user.rb +2 -0
  52. data/spec/dummy/app/views/layouts/application.html.erb +14 -0
  53. data/spec/dummy/bin/bundle +3 -0
  54. data/spec/dummy/bin/rails +4 -0
  55. data/spec/dummy/bin/rake +4 -0
  56. data/spec/dummy/config/application.rb +24 -0
  57. data/spec/dummy/config/boot.rb +5 -0
  58. data/spec/dummy/config/database.yml +25 -0
  59. data/spec/dummy/config/environment.rb +5 -0
  60. data/spec/dummy/config/environments/development.rb +29 -0
  61. data/spec/dummy/config/environments/production.rb +80 -0
  62. data/spec/dummy/config/environments/test.rb +36 -0
  63. data/spec/dummy/config/initializers/backtrace_silencers.rb +7 -0
  64. data/spec/dummy/config/initializers/filter_parameter_logging.rb +4 -0
  65. data/spec/dummy/config/initializers/inflections.rb +16 -0
  66. data/spec/dummy/config/initializers/mime_types.rb +5 -0
  67. data/spec/dummy/config/initializers/secret_token.rb +12 -0
  68. data/spec/dummy/config/initializers/session_store.rb +3 -0
  69. data/spec/dummy/config/initializers/wrap_parameters.rb +14 -0
  70. data/spec/dummy/config/locales/en.yml +23 -0
  71. data/spec/dummy/config/routes.rb +8 -0
  72. data/spec/dummy/config.ru +4 -0
  73. data/spec/dummy/db/schema.rb +27 -0
  74. data/spec/dummy/db/test.sqlite3 +0 -0
  75. data/spec/dummy/lib/assets/.keep +0 -0
  76. data/spec/dummy/log/.keep +0 -0
  77. data/spec/dummy/public/404.html +58 -0
  78. data/spec/dummy/public/422.html +58 -0
  79. data/spec/dummy/public/500.html +57 -0
  80. data/spec/dummy/public/favicon.ico +0 -0
  81. data/spec/lib/neighborly/balanced/creditcard/interface_spec.rb +37 -0
  82. data/spec/models/neighborly/balanced/creditcard/payment_spec.rb +223 -0
  83. data/spec/models/neighborly/balanced/creditcard/transaction_additional_fee_calculator_spec.rb +38 -0
  84. data/spec/models/neighborly/balanced/creditcard/transaction_inclusive_fee_calculator_spec.rb +19 -0
  85. data/spec/spec_helper.rb +15 -0
  86. metadata +252 -0
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 14effd0d0371b543d21fe4c045d35dd4109e1e40
4
+ data.tar.gz: 68ef4267ea6a24e978c7d318a348c859e95493fc
5
+ SHA512:
6
+ metadata.gz: a5dc95a5b2653b6351b5744446157b1812ecf94a98977980017eb24e266ac94fae07a46a91a2e51cc427218d7be8143642feb6b1a5abaeea133aa6e215644db9
7
+ data.tar.gz: c38c301ed8689a0b1701c2a3773e7478cf627ca8cc4776bb932cc76d28abc5142064f18898d229a1f0bb176f3c8a2b8720d293b400d21b8ab8591565116d1582
data/.gitignore ADDED
@@ -0,0 +1,20 @@
1
+ *.gem
2
+ *.log
3
+ *.rbc
4
+ .bundle
5
+ .config
6
+ .yardoc
7
+ Gemfile.lock
8
+ InstalledFiles
9
+ _yardoc
10
+ coverage
11
+ doc/
12
+ lib/bundler/man
13
+ pkg
14
+ rdoc
15
+ spec/reports
16
+ spec/dummy/db/*.sqlite3
17
+ test/tmp
18
+ test/version_tmp
19
+ tmp
20
+ spec/dummy/log/*.log
data/.rspec ADDED
@@ -0,0 +1,2 @@
1
+ --color
2
+ --format d
data/.travis.yml ADDED
@@ -0,0 +1,13 @@
1
+ rvm:
2
+ - 2.1.5
3
+
4
+ before_install: gem update --remote bundler
5
+
6
+ before_script:
7
+ - "bundle install"
8
+
9
+ script:
10
+ - "bundle exec rspec"
11
+
12
+ notifications:
13
+ webhooks: https://ci.neighbor.ly/projects/421aaf06-fc95-41a4-9677-701f9c809fc6/status
data/CHANGELOG.md ADDED
@@ -0,0 +1,5 @@
1
+ # CHANGELOG
2
+
3
+ ## 1.0.0
4
+
5
+ * First refactor from neighborly-balanced-creditcard
data/Gemfile ADDED
@@ -0,0 +1,6 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in dune-balanced-creditcard.gemspec
4
+ gemspec
5
+
6
+ gem 'dune-balanced', github: 'FromUte/dune-balanced', branch: :master
data/LICENSE.txt ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2014 Legrand Pierre
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,48 @@
1
+ # Dune::Balanced::Creditcard
2
+
3
+
4
+ ## What
5
+
6
+ This is an integration between [Balanced](https://www.balancedpayments.com/) and [dune-investissement](https://github.com/FromUte/dune-donate), a crowdfunding platform.
7
+
8
+ ## How
9
+
10
+ Include this gem as dependency of your project, adding the following line in your `Gemfile`.
11
+
12
+ ```ruby
13
+ # Gemfile
14
+ gem 'dune-balanced-creditcard'
15
+ ```
16
+
17
+ Dune::Balanced::Creditcard is a Rails Engine, integrating with your (dune-investissement) Rails application with very little of effort. To turn the engine on, mount it in an appropriate route:
18
+
19
+ ```ruby
20
+ # config/routes.rb
21
+ mount Dune::Balanced::Creditcard::Engine => '/balanced/creditcard/', as: :dune_balanced_creditcard
22
+ ```
23
+
24
+ And load our JavaScript:
25
+
26
+ ```coffeescript
27
+ //= require dune-balanced-creditcard
28
+ ```
29
+
30
+ ## Contributing
31
+
32
+ 1. Fork it
33
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
34
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
35
+ 4. Push to the branch (`git push origin my-new-feature`)
36
+ 5. Create new Pull Request
37
+
38
+ ### Running specs
39
+
40
+ We prize for our test suite and coverage, so it would be great if you could run the specs to ensure that your patch is not breaking the existing codebase.
41
+
42
+ ```
43
+ bundle exec rspec
44
+ ```
45
+
46
+ ## License
47
+
48
+ Licensed under the [MIT license](LICENSE.txt).
data/Rakefile ADDED
@@ -0,0 +1,34 @@
1
+ begin
2
+ require 'bundler/setup'
3
+ rescue LoadError
4
+ puts 'You must `gem install bundler` and `bundle install` to run rake tasks'
5
+ end
6
+
7
+ require 'rdoc/task'
8
+
9
+ RDoc::Task.new(:rdoc) do |rdoc|
10
+ rdoc.rdoc_dir = 'rdoc'
11
+ rdoc.title = 'Dune::Balanced::Creditcard'
12
+ rdoc.options << '--line-numbers'
13
+ rdoc.rdoc_files.include('README.rdoc')
14
+ rdoc.rdoc_files.include('lib/**/*.rb')
15
+ end
16
+
17
+ APP_RAKEFILE = File.expand_path("../spec/dummy/Rakefile", __FILE__)
18
+ load 'rails/tasks/engine.rake'
19
+
20
+
21
+
22
+ Bundler::GemHelper.install_tasks
23
+
24
+ require 'rake/testtask'
25
+
26
+ Rake::TestTask.new(:test) do |t|
27
+ t.libs << 'lib'
28
+ t.libs << 'test'
29
+ t.pattern = 'test/**/*_test.rb'
30
+ t.verbose = false
31
+ end
32
+
33
+
34
+ task default: :test
@@ -0,0 +1,15 @@
1
+ Dune.Dune ?= {}
2
+ Dune.Dune.Balanced ?= {}
3
+ Dune.Dune.Balanced.Creditcard ?= {}
4
+
5
+ Dune.Dune.Balanced.Creditcard.Flash =
6
+ message: (text)->
7
+ this.remove()
8
+ alertBox = $('<div>', { 'class': 'alert-box error text-center', 'html':
9
+ $('<h5>', { 'html': text })
10
+ } )
11
+ errorBoxWrapper = $('<div>', { 'class': 'error-box large-12 columns hide', 'html': alertBox}).insertBefore('.dune-balanced-creditcard-form .submit')
12
+ errorBoxWrapper.fadeIn(300)
13
+
14
+ remove: ->
15
+ $('.error-box').remove()
@@ -0,0 +1,86 @@
1
+ Dune.Dune ?= {}
2
+ Dune.Dune.Balanced ?= {}
3
+ Dune.Dune.Balanced.Creditcard ?= {}
4
+ Dune.Dune.Balanced.Creditcard.Payments ?= {}
5
+
6
+ Dune.Dune.Balanced.Creditcard.Payments.New = Backbone.View.extend
7
+ el: '.dune-balanced-creditcard-form'
8
+
9
+ initialize: ->
10
+ _.bindAll(this, 'submit', 'submitToBalanced', 'toggleAddNewCard', 'toggleSelected')
11
+ this.Flash = Dune.Dune.Balanced.Creditcard.Flash
12
+
13
+ $.getScript 'https://js.balancedpayments.com/1.1/balanced.js'
14
+
15
+ this.$button = this.$('input[type=submit]')
16
+ this.$('form').bind('submit', this.submit)
17
+ this.$('input[type=radio]').bind('change', this.toggleAddNewCard)
18
+ this.$('input[type=radio]').bind('change', this.toggleSelected)
19
+ this.toggleSelected()
20
+
21
+ submit: (event) ->
22
+ selectedCard = this.$('[name="payment[use_card]"]:checked, [name="payment[use_card]"]:hidden')
23
+ return if $.inArray(selectedCard.val(), ['new', '']) == -1
24
+
25
+ event.preventDefault()
26
+ this.submitToBalanced(selectedCard)
27
+ # This return is necessary because of jquery_ujs was disabling the submit
28
+ # button even when we enable it.
29
+ return false
30
+
31
+ submitToBalanced: (selectedCard) ->
32
+ that = this
33
+ $.rails.disableFormElements(that.$el)
34
+
35
+ creditCardData =
36
+ number: this.$('#payment_card_number').val()
37
+ expiration_month: this.$('#payment_expiration_month').val()
38
+ expiration_year: this.$('#payment_expiration_year').val()
39
+ cvv: this.$('#payment_security_code').val()
40
+ name: this.$('#payment_user_name').val()
41
+ address:
42
+ postal_code: this.$('#payment_user_address_zip_code').val()
43
+ country_code: 'USA'
44
+
45
+ balanced_callback_for_201 = (response) ->
46
+ selectedCard.val(response.cards[0].href)
47
+ that.$('[data-balanced-credit-card-input]').val('')
48
+ that.$('form').submit()
49
+ that.Flash.remove()
50
+
51
+ <% i18n_scope = 'dune.balanced.creditcard.payments.new.errors' %>
52
+
53
+ balanced_callback_for_400 = (response) ->
54
+ that.Flash.message('<%= I18n.t("#{i18n_scope}.invalid_card") %>')
55
+
56
+ balanced_callback_for_402 = (response) ->
57
+ that.Flash.message('<%= I18n.t("#{i18n_scope}.card_tokenization_error") %>')
58
+
59
+ balanced_callback_for_404 = (response) ->
60
+ that.Flash.message('<%= I18n.t("#{i18n_scope}.marketplace_uri") %>')
61
+
62
+ balanced_callback_for_500 = (response) ->
63
+ that.Flash.message('<%= I18n.t("#{i18n_scope}.balanced") %>')
64
+
65
+ balanced.card.create creditCardData, (response) ->
66
+ switch response.status_code
67
+ when 201 then balanced_callback_for_201(response)
68
+ when 400 then balanced_callback_for_400(response)
69
+ when 402 then balanced_callback_for_402(response)
70
+ when 404 then balanced_callback_for_404(response)
71
+ when 500 then balanced_callback_for_500(response)
72
+
73
+ if response.status != 201
74
+ $.rails.enableFormElements(that.$el)
75
+ $submit = that.$('input[type=submit]')
76
+ $submit.val($submit.data('enable-with'))
77
+
78
+ toggleSelected: ->
79
+ this.$('.card-box').removeClass('selected')
80
+ this.$('input[type=radio]:checked').parents('.card-box').addClass('selected')
81
+
82
+ toggleAddNewCard: ->
83
+ if this.$('#payment_use_card_new').is(':checked')
84
+ this.$('.add-new-creditcard-form').removeClass('hide')
85
+ else
86
+ this.$('.add-new-creditcard-form').addClass('hide')
@@ -0,0 +1 @@
1
+ //= require_tree .
@@ -0,0 +1,16 @@
1
+ /*
2
+ * This is a manifest file that'll be compiled into application.css, which will include all the files
3
+ * listed below.
4
+ *
5
+ * Any CSS and SCSS file within this directory, lib/assets/stylesheets, vendor/assets/stylesheets,
6
+ * or vendor/assets/stylesheets of plugins, if any, can be referenced here using a relative path.
7
+ *
8
+ * You're free to add application-wide styles to this file and they'll appear at the bottom of the
9
+ * compiled file so the styles you add here take precedence over styles defined in any styles
10
+ * defined in the other CSS/SCSS files in this directory. It is generally better to create a new
11
+ * file per style scope.
12
+ *
13
+ *= require_tree .
14
+ *= require_self
15
+ */
16
+
@@ -0,0 +1,4 @@
1
+ module Dune::Balanced::Creditcard
2
+ class ApplicationController < ActionController::Base
3
+ end
4
+ end
@@ -0,0 +1,84 @@
1
+ module Dune::Balanced::Creditcard
2
+ class PaymentsController < ActionController::Base
3
+ before_filter :authenticate_user!
4
+
5
+ def new
6
+ @cards = customer.cards
7
+ end
8
+
9
+ def create
10
+ attach_card_to_customer
11
+ update_customer
12
+
13
+ payment = Payment.new('balanced-creditcard',
14
+ customer,
15
+ resource,
16
+ resource_params)
17
+ payment.checkout!
18
+ redirect_to(*checkout_response_params(resource, payment.successful?))
19
+ end
20
+
21
+ private
22
+ def resource
23
+ @resource ||= if params[:payment][:match_id].present?
24
+ Match.find(params[:payment].fetch(:match_id))
25
+ else
26
+ Contribution.find(params[:payment].fetch(:contribution_id))
27
+ end
28
+ end
29
+
30
+ def resource_name
31
+ resource.class.model_name.singular.to_sym
32
+ end
33
+
34
+ def checkout_response_params(resource, success)
35
+ status = success ? :succeeded : :failed
36
+ route_params = [resource.project.permalink, resource.id]
37
+
38
+ {
39
+ contribution: {
40
+ succeeded: [
41
+ main_app.project_contribution_path(*route_params)
42
+ ],
43
+ failed: [
44
+ main_app.edit_project_contribution_path(*route_params),
45
+ alert: t('.errors.default')
46
+ ]
47
+ },
48
+ match: {
49
+ succeeded: [
50
+ main_app.project_match_path(*route_params)
51
+ ],
52
+ failed: [
53
+ main_app.edit_project_match_path(*route_params),
54
+ alert: t('.errors.default')
55
+ ]
56
+ }
57
+ }.fetch(resource_name).fetch(status)
58
+ end
59
+
60
+ def resource_params
61
+ params.require(:payment).
62
+ permit(:contribution_id,
63
+ :match_id,
64
+ :use_card,
65
+ :pay_fee,
66
+ user: {})
67
+ end
68
+
69
+ def attach_card_to_customer
70
+ card = Balanced::Card.fetch(resource_params.fetch(:use_card))
71
+ unless customer.cards.to_a.any? { |c| c.id.eql? card.id }
72
+ card.associate_to_customer(customer)
73
+ end
74
+ end
75
+
76
+ def customer
77
+ @customer ||= Dune::Balanced::Customer.new(current_user, params).fetch
78
+ end
79
+
80
+ def update_customer
81
+ Dune::Balanced::Customer.new(current_user, params).update!
82
+ end
83
+ end
84
+ end
@@ -0,0 +1,94 @@
1
+ module Dune::Balanced::Creditcard
2
+ class Payment
3
+ attr_reader :engine_name, :customer, :resource, :attrs
4
+
5
+ def initialize(engine_name, customer, resource, attrs = {})
6
+ @engine_name = engine_name
7
+ @customer = customer
8
+ @resource = resource
9
+ @attrs = attrs
10
+ end
11
+
12
+ def checkout!
13
+ perform_debit!
14
+ resource.confirm!
15
+ rescue Balanced::PaymentRequired
16
+ resource.cancel!
17
+ ensure
18
+ resource.update_attributes(
19
+ payment_id: @debit.try(:id),
20
+ payment_method: engine_name,
21
+ payment_service_fee: fee_calculator.fees,
22
+ payment_service_fee_paid_by_user: attrs[:pay_fee]
23
+ )
24
+ update_meta(@debit) if @debit
25
+ end
26
+
27
+ def amount_in_cents
28
+ (fee_calculator.gross_amount * 100).round
29
+ end
30
+
31
+ def fee_calculator
32
+ @fee_calculator and return @fee_calculator
33
+
34
+ calculator_class = if ActiveRecord::ConnectionAdapters::Column::TRUE_VALUES.include? attrs[:pay_fee]
35
+ TransactionAdditionalFeeCalculator
36
+ else
37
+ TransactionInclusiveFeeCalculator
38
+ end
39
+
40
+ @fee_calculator = calculator_class.new(resource.value)
41
+ end
42
+
43
+ def debit
44
+ @debit.try(:sanitize)
45
+ end
46
+
47
+ def successful?
48
+ %w(pending succeeded).include? @debit.try(:status)
49
+ end
50
+
51
+ private
52
+
53
+ def perform_debit!
54
+ debit_params = {
55
+ amount: amount_in_cents,
56
+ appears_on_statement_as: ::Configuration[:balanced_appears_on_statement_as],
57
+ description: debit_description,
58
+ meta: meta,
59
+ source: card
60
+ }
61
+
62
+ order = Dune::Balanced::OrderProxy.new(resource.project)
63
+ @debit = order.debit_from(debit_params)
64
+ end
65
+
66
+ def card
67
+ Balanced::Card.fetch(attrs.fetch(:use_card))
68
+ end
69
+
70
+ def update_meta(debit)
71
+ debit.meta = meta
72
+ debit.save
73
+ end
74
+
75
+ def resource_name
76
+ resource.class.model_name.singular
77
+ end
78
+
79
+ def debit_description
80
+ I18n.t('description',
81
+ project_name: resource.try(:project).try(:name),
82
+ scope: "dune.balanced.creditcard.payments.debit.#{resource_name}")
83
+ end
84
+
85
+ def project_owner_customer
86
+ @project_owner_customer ||= Dune::Balanced::Customer.new(
87
+ resource.project.user, {}).fetch
88
+ end
89
+
90
+ def meta
91
+ PayableResourceSerializer.new(resource).to_json
92
+ end
93
+ end
94
+ end
@@ -0,0 +1,12 @@
1
+ require 'float_extensions'
2
+
3
+ module Dune::Balanced::Creditcard
4
+ class TransactionAdditionalFeeCalculator < TransactionFeeCalculatorBase
5
+ using FloatExtensions
6
+
7
+ def net_amount
8
+ transaction_value.to_f.floor_with_two_decimal_places
9
+ end
10
+ end
11
+ end
12
+
@@ -0,0 +1,31 @@
1
+ require 'float_extensions'
2
+
3
+ module Dune::Balanced::Creditcard
4
+ class TransactionFeeCalculatorBase
5
+ using FloatExtensions
6
+
7
+ attr_writer :transaction_value
8
+
9
+ def initialize(transaction_value)
10
+ @transaction_value = transaction_value
11
+ end
12
+
13
+ def transaction_value
14
+ @transaction_value.to_f.floor_with_two_decimal_places
15
+ end
16
+
17
+ def gross_amount
18
+ net_amount + fees
19
+ end
20
+
21
+ def net_amount
22
+ raise NotImplementedError
23
+ end
24
+
25
+ # Base calculation of fees
26
+ # 2.9% + 30¢
27
+ def fees
28
+ (net_amount * 0.029 + 0.3).ceil_with_two_decimal_places
29
+ end
30
+ end
31
+ end
@@ -0,0 +1,13 @@
1
+ require 'float_extensions'
2
+
3
+ module Dune::Balanced::Creditcard
4
+ class TransactionInclusiveFeeCalculator < TransactionFeeCalculatorBase
5
+ using FloatExtensions
6
+
7
+ # Base calculation of fees
8
+ # 2.9% + 30¢
9
+ def net_amount
10
+ ((transaction_value - 0.3) / 1.029).floor_with_two_decimal_places
11
+ end
12
+ end
13
+ end
File without changes
@@ -0,0 +1,98 @@
1
+ = initjs_tag app_name: 'Dune', partial: true
2
+
3
+ .dune-balanced-creditcard-form[data-balanced-credit-card-form]
4
+ = simple_form_for :payment, url: payments_path, html: { novalidate: '' } do |f|
5
+ - if params[:match_id].present?
6
+ = f.input :match_id, as: :hidden, input_html: { value: params[:match_id] }
7
+ - else
8
+ = f.input :contribution_id, as: :hidden, input_html: { value: params[:contribution_id] }
9
+
10
+ = f.input :pay_fee, as: :hidden, input_html: { value: 1, 'data-pay-payment-fee' => '' }
11
+ section.highlighted[class="#{'use-existing-item' if @cards.any?}"]
12
+ - if @cards.any?
13
+ section.use-existing-item.row
14
+ .large-12.columns.title
15
+ h4 = t('.cards.title')
16
+
17
+ - @cards.reverse_each.with_index do |card,index|
18
+ .large-12.columns
19
+ .card-box
20
+ label.row
21
+ dl
22
+ .large-1.columns
23
+ = f.radio_button :use_card, card.href, { checked: index.zero?, label: false }
24
+ .large-6.columns
25
+ dt.hide
26
+ dd = t('.cards.card_ending_in', brand: card.brand, number: card.number)
27
+ .large-5.columns.expiration
28
+ dt = t('.cards.expiration')
29
+ dd = sprintf('%02i/%i', card.expiration_month, card.expiration_year)
30
+
31
+ - else
32
+ = f.input :use_card, as: :hidden
33
+
34
+ .row
35
+ .large-12.columns.title
36
+ h4 = t('.card.title')
37
+
38
+
39
+ section.row
40
+ .large-12.columns
41
+ .card-box[class="#{'new-card' unless @cards.any?}"]
42
+ .row
43
+ - if @cards.any?
44
+ label
45
+ .large-1.columns
46
+ = f.radio_button :use_card, 'new', { checked: false, label: false }
47
+ .large-8.columns
48
+ = t('.add_new_card')
49
+ .large-3.columns.expiration
50
+
51
+ .large-12.columns.add-new-creditcard-form[class="#{'hide with-others-cards' if @cards.any?}"]
52
+ .row
53
+ .large-5.columns
54
+ = f.input :card_number, input_html: { 'data-balanced-credit-card-input' => '' }
55
+ .large-2.columns
56
+ = f.input :security_code, maxlength: 4, input_html: { 'data-balanced-credit-card-input' => '' }
57
+ .large-5.columns
58
+ - date = Date.today + 1.month
59
+ = f.label :expiration
60
+ .row.collapse
61
+ .large-5.small-5.columns
62
+ = select_month date, { use_two_digit_numbers: true }, { name: 'payment[expiration_month]', id: 'payment_expiration_month', 'data-balanced-credit-card-input' => '' }
63
+ .large-1.small-1.columns.text-center.divider
64
+ | /
65
+ .large-6.small-6.columns
66
+ = select_year date, { start_year: date.year, end_year: date.year+15 }, { name: 'payment[expiration_year]', id: 'payment_expiration_year', 'data-balanced-credit-card-input' => '' }
67
+
68
+ section.user-informations.highlighted
69
+ = f.simple_fields_for :user do |fu|
70
+ .row
71
+ .large-12.columns.title
72
+ h4 = t('.billing.title')
73
+
74
+ .row
75
+ .large-6.columns
76
+ = fu.input :name, required: false, input_html: { value: @customer.name }
77
+ .large-6.columns
78
+ = fu.input :address_street, required: false, input_html: { value: @customer.address.try(:[], :line1) }
79
+ .row
80
+ .large-5.columns
81
+ = fu.input :address_city, required: false, input_html: { value: @customer.address.try(:[], :city) }
82
+ .large-4.columns
83
+ = fu.input :address_state, required: false, as: :select, collection: State.array, selected: @customer.address.try(:[], :state), include_blank: false
84
+ .large-3.columns
85
+ = fu.input :address_zip_code, input_html: { value: @customer.address.try(:[], :postal_code) }
86
+
87
+ section
88
+ .row
89
+ .large-12.columns.terms
90
+ = t('.terms', link: link_to(t('.terms-link'), main_app.terms_path(), data: { 'reveal-id' => 'terms-modal', 'reveal-ajax' => true })).html_safe
91
+
92
+ .row
93
+ .large-6.columns.submit
94
+ = f.button :submit, t('.confirm'), data: { disable_with: t('.proccessing'), enable_with: t('.confirm') }
95
+ .large-6.columns.text-right.balanced-seal
96
+ = link_to image_tag('https://balancedpowered.s3.amazonaws.com/secured-1-4.png'), 'https://www.balancedpayments.com/', target: :blank
97
+
98
+ #terms-modal.reveal-modal.small.fixed
data/bin/rails ADDED
@@ -0,0 +1,8 @@
1
+ #!/usr/bin/env ruby
2
+ # This command will automatically be run when you run "rails" with Rails 4 gems installed from the root of your application.
3
+
4
+ ENGINE_ROOT = File.expand_path('../..', __FILE__)
5
+ ENGINE_PATH = File.expand_path('../../lib/dune/balanced/creditcard/engine', __FILE__)
6
+
7
+ require 'rails/all'
8
+ require 'rails/engine/commands'
@@ -0,0 +1,5 @@
1
+ begin
2
+ PaymentEngine.new(Dune::Balanced::Creditcard::Interface.new).save
3
+ rescue Exception => e
4
+ puts "Error while registering payment engine: #{e}"
5
+ end