spree_affirm 0.2.3

Sign up to get free protection for your applications and to get access to all the features.
Files changed (40) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +15 -0
  3. data/Gemfile +19 -0
  4. data/LICENSE +29 -0
  5. data/README.md +51 -0
  6. data/Rakefile +15 -0
  7. data/Versionfile +5 -0
  8. data/app/assets/javascripts/spree/backend/spree_affirm.js +3 -0
  9. data/app/assets/javascripts/spree/frontend/spree_affirm.js +2 -0
  10. data/app/assets/stylesheets/spree/backend/spree_affirm.css +4 -0
  11. data/app/assets/stylesheets/spree/frontend/spree_affirm.css +4 -0
  12. data/app/controllers/spree/affirm_controller.rb +68 -0
  13. data/app/models/spree/affirm_checkout.rb +38 -0
  14. data/app/models/spree/gateway/affirm.rb +51 -0
  15. data/app/views/spree/admin/log_entries/_affirm.html.erb +4 -0
  16. data/app/views/spree/admin/log_entries/index.html.erb +28 -0
  17. data/app/views/spree/admin/payments/source_forms/_affirm.html.erb +19 -0
  18. data/app/views/spree/admin/payments/source_views/_affirm.html.erb +12 -0
  19. data/app/views/spree/checkout/payment/_affirm.html.erb +195 -0
  20. data/bin/rails +7 -0
  21. data/config/locales/en.yml +29 -0
  22. data/config/routes.rb +5 -0
  23. data/db/migrate/20140514194315_create_affirm_checkout.rb +10 -0
  24. data/lib/active_merchant/billing/affirm.rb +161 -0
  25. data/lib/generators/spree_affirm/install/install_generator.rb +21 -0
  26. data/lib/spree_affirm/engine.rb +27 -0
  27. data/lib/spree_affirm/factories/affirm_checkout_factory.rb +211 -0
  28. data/lib/spree_affirm/factories/affirm_payment_method_factory.rb +8 -0
  29. data/lib/spree_affirm/factories/payment_factory.rb +10 -0
  30. data/lib/spree_affirm/factories.rb +5 -0
  31. data/lib/spree_affirm/version.rb +3 -0
  32. data/lib/spree_affirm.rb +2 -0
  33. data/spec/controllers/affirm_controller_spec.rb +138 -0
  34. data/spec/lib/active_merchant/billing/affirm_spec.rb +294 -0
  35. data/spec/models/affirm_address_validator_spec.rb +13 -0
  36. data/spec/models/spree_affirm_checkout_spec.rb +328 -0
  37. data/spec/models/spree_gateway_affirm_spec.rb +134 -0
  38. data/spec/spec_helper.rb +98 -0
  39. data/spree_affirm.gemspec +30 -0
  40. metadata +190 -0
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: 960cab60304d9c975f1b96c7dd949cc336d5fccf559b02fd41613556169831ab
4
+ data.tar.gz: '09c73710797e4961e7f3839474fb0c559165f38d75d98f1d4935c188102ccdca'
5
+ SHA512:
6
+ metadata.gz: 6b43bf2de8cdd3012af7320f56fb5b0ad327c15c7fc9b5d5d80036b86d1dd407f5025f52b3ed2d550a33d842a38212eeff07dc928d96d05bab6570f9d37ea0af
7
+ data.tar.gz: df9bff0eebd0b99e5ce7f3faa973fab0ec511c3eab78db2df3607a21ccbd2cdd049ab88164dce85c4ee49f7067a1fa2f5be5b950cf55ecb3e94ba8a8784639a0
data/.gitignore ADDED
@@ -0,0 +1,15 @@
1
+ \#*
2
+ *~
3
+ .#*
4
+ .DS_Store
5
+ .idea
6
+ .project
7
+ .sass-cache
8
+ coverage
9
+ Gemfile.lock
10
+ tmp
11
+ nbproject
12
+ pkg
13
+ *.swp
14
+ spec/dummy
15
+ .rspec
data/Gemfile ADDED
@@ -0,0 +1,19 @@
1
+ source 'https://rubygems.org'
2
+
3
+ gem 'spree', github: 'spree/spree', tag: 'v0.2.25'
4
+ gem 'spree_gateway', github: 'spree/spree_gateway', tag: 'v0.2.25'
5
+ gem 'spree_auth_devise', github: 'spree/spree_auth_devise', tag: 'v0.2.25'
6
+
7
+ group :test do
8
+ gem 'coffee-rails'
9
+ gem 'sass-rails', '~> 4.0.3'
10
+ gem 'money', '6.5.1'
11
+ gem 'rspec-rails', '~> 2.10'
12
+ gem 'shoulda-matchers', '2.2.0'
13
+ gem 'simplecov', :require => false
14
+ gem 'simplecov-rcov'
15
+ gem 'database_cleaner'
16
+ gem 'minitest'
17
+ end
18
+
19
+ gemspec
data/LICENSE ADDED
@@ -0,0 +1,29 @@
1
+ BSD 3-Clause License
2
+
3
+ Copyright (c) 2019, Affirm
4
+ All rights reserved.
5
+
6
+ Redistribution and use in source and binary forms, with or without
7
+ modification, are permitted provided that the following conditions are met:
8
+
9
+ * Redistributions of source code must retain the above copyright notice, this
10
+ list of conditions and the following disclaimer.
11
+
12
+ * Redistributions in binary form must reproduce the above copyright notice,
13
+ this list of conditions and the following disclaimer in the documentation
14
+ and/or other materials provided with the distribution.
15
+
16
+ * Neither the name of the copyright holder nor the names of its
17
+ contributors may be used to endorse or promote products derived from
18
+ this software without specific prior written permission.
19
+
20
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
21
+ AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
23
+ DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
24
+ FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25
+ DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
26
+ SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
27
+ CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
28
+ OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
29
+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
data/README.md ADDED
@@ -0,0 +1,51 @@
1
+ SpreeAffirm
2
+ ===========
3
+
4
+ Installation
5
+ ------------
6
+
7
+ 1. Add this extension to your Gemfile with this line:
8
+
9
+ gem 'spree_affirm', :github => "affirm/spree_affirm"
10
+
11
+ 2. Install the gem using Bundler:
12
+
13
+ bundle install
14
+
15
+ 3. Copy & run migrations
16
+
17
+ bundle exec rails g spree_affirm:install
18
+
19
+ 4. Restart your server
20
+
21
+ Documentation
22
+ ------------------
23
+ https://docs.affirm.com/Spree
24
+
25
+ ## Contributing
26
+
27
+ 1. Fork it
28
+ 2. Create your feature branch (```git checkout -b my-new-feature```).
29
+ 3. Commit your changes (```git commit -am 'Added some feature'```)
30
+ 4. Push to the branch (```git push origin my-new-feature```)
31
+ 5. Create new Pull Request
32
+
33
+ Testing
34
+ -------
35
+
36
+ Be sure to bundle your dependencies and then create a dummy test app for the specs to run against.
37
+
38
+ ```shell
39
+ bundle
40
+ bundle exec rake test_app
41
+ bundle exec rspec spec
42
+ ```
43
+
44
+ When testing your applications integration with this extension you may use its factories.
45
+ Simply add this require statement to your spec_helper:
46
+
47
+ ```ruby
48
+ require 'spree_affirm/factories'
49
+ ```
50
+
51
+ Copyright (c) 2019 Affirm, released under the New BSD License
data/Rakefile ADDED
@@ -0,0 +1,15 @@
1
+ require 'bundler'
2
+ Bundler::GemHelper.install_tasks
3
+
4
+ require 'rspec/core/rake_task'
5
+ require 'spree/testing_support/extension_rake'
6
+
7
+ RSpec::Core::RakeTask.new
8
+
9
+ task :default => [:spec]
10
+
11
+ desc 'Generates a dummy app for testing'
12
+ task :test_app do
13
+ ENV['LIB_NAME'] = 'spree_affirm'
14
+ Rake::Task['extension:test_app'].invoke
15
+ end
data/Versionfile ADDED
@@ -0,0 +1,5 @@
1
+ # This file is used to designate compatibilty with different versions of Spree
2
+ # Please see http://spreecommerce.com/documentation/extensions.html#versionfile for details
3
+
4
+ "2.2.x" => { :branch => "master" }
5
+ "2.0.x" => { :branch => "2-0-stable" }
@@ -0,0 +1,3 @@
1
+ // Placeholder manifest file.
2
+ // the installer will append this file to the app vendored assets here: vendor/assets/javascripts/spree/backend/all.js'
3
+ //
@@ -0,0 +1,2 @@
1
+ // Placeholder manifest file.
2
+ // the installer will append this file to the app vendored assets here: vendor/assets/javascripts/spree/frontend/all.js'
@@ -0,0 +1,4 @@
1
+ /*
2
+ Placeholder manifest file.
3
+ the installer will append this file to the app vendored assets here: 'vendor/assets/stylesheets/spree/backend/all.css'
4
+ */
@@ -0,0 +1,4 @@
1
+ /*
2
+ Placeholder manifest file.
3
+ the installer will append this file to the app vendored assets here: 'vendor/assets/stylesheets/spree/frontend/all.css'
4
+ */
@@ -0,0 +1,68 @@
1
+ module Spree
2
+ class AffirmController < Spree::StoreController
3
+ helper 'spree/orders'
4
+
5
+ #the confirm will do it's own protection by making calls to affirm
6
+ protect_from_forgery :except => [:confirm]
7
+
8
+ def confirm
9
+ order = current_order || raise(ActiveRecord::RecordNotFound)
10
+
11
+ if !params[:checkout_token]
12
+ flash[:notice] = "Invalid order confirmation data."
13
+ return redirect_to checkout_state_path(current_order.state)
14
+ end
15
+
16
+ if order.complete?
17
+ flash[:notice] = "Order already completed."
18
+ return redirect_to completion_route order
19
+ end
20
+
21
+ _affirm_checkout = Spree::AffirmCheckout.new(
22
+ order: order,
23
+ token: params[:checkout_token],
24
+ payment_method: payment_method
25
+ )
26
+
27
+ order.save
28
+
29
+ _affirm_checkout.save
30
+
31
+ _affirm_payment = order.payments.create!({
32
+ payment_method: payment_method,
33
+ amount: order.total,
34
+ source: _affirm_checkout
35
+ })
36
+
37
+ # transition to confirm or complete
38
+ order.next
39
+
40
+ if order.completed?
41
+ session[:order_id] = nil
42
+ flash.notice = Spree.t(:order_processed_successfully)
43
+ flash[:order_completed] = true
44
+ redirect_to completion_route order
45
+ else
46
+ redirect_to checkout_state_path(order.state)
47
+ end
48
+ end
49
+
50
+ def cancel
51
+ redirect_to checkout_state_path(current_order.state)
52
+ end
53
+
54
+ private
55
+
56
+ def payment_method
57
+ Spree::PaymentMethod.find(params[:payment_method_id])
58
+ end
59
+
60
+ def provider
61
+ payment_method.provider
62
+ end
63
+
64
+ def completion_route(order)
65
+ spree.order_path(order)
66
+ end
67
+ end
68
+ end
@@ -0,0 +1,38 @@
1
+ module Spree
2
+ class AffirmCheckout < ActiveRecord::Base
3
+ belongs_to :payment_method
4
+ belongs_to :order
5
+
6
+ scope :with_payment_profile, -> { all }
7
+
8
+ def name
9
+ "Affirm Checkout"
10
+ end
11
+
12
+ def details
13
+ @details ||= payment_method.provider.get_checkout token
14
+ end
15
+
16
+ def actions
17
+ %w{capture void credit}
18
+ end
19
+
20
+ # Indicates whether its possible to capture the payment
21
+ def can_capture?(payment)
22
+ (payment.pending? || payment.checkout?) && !payment.response_code.blank?
23
+ end
24
+
25
+ # Indicates whether its possible to void the payment.
26
+ def can_void?(payment)
27
+ !payment.void? && payment.pending? && !payment.response_code.blank?
28
+ end
29
+
30
+ # Indicates whether its possible to credit the payment. Note that most gateways require that the
31
+ # payment be settled first which generally happens within 12-24 hours of the transaction.
32
+ def can_credit?(payment)
33
+ return false unless payment.completed?
34
+ return false unless payment.order.payment_state == 'credit_owed'
35
+ payment.credit_allowed > 0
36
+ end
37
+ end
38
+ end
@@ -0,0 +1,51 @@
1
+ module Spree
2
+ class Gateway::Affirm < Gateway
3
+ preference :api_key, :string
4
+ preference :secret_key, :string
5
+ preference :test_mode, :boolean, default: true
6
+ preference :server, :string, default: 'sandbox.affirm.com'
7
+
8
+ def provider_class
9
+ ActiveMerchant::Billing::Affirm
10
+ end
11
+
12
+ def payment_source_class
13
+ Spree::AffirmCheckout
14
+ end
15
+
16
+ def source_required?
17
+ true
18
+ end
19
+
20
+ def method_type
21
+ 'affirm'
22
+ end
23
+
24
+ def actions
25
+ %w{capture void credit}
26
+ end
27
+
28
+ def supports?(source)
29
+ source.is_a? payment_source_class
30
+ end
31
+
32
+ def self.version
33
+ Gem::Specification.find_by_name('spree_affirm').version.to_s
34
+ end
35
+
36
+ def cancel(charge_ari)
37
+ _payment = Spree::Payment.valid.where(
38
+ response_code: charge_ari,
39
+ source_type: payment_source_class.to_s
40
+ ).first
41
+
42
+ return if _payment.nil?
43
+
44
+ if _payment.pending?
45
+ _payment.void_transaction!
46
+ elsif _payment.completed? && _payment.can_credit?
47
+ provider.refund(_payment.credit_allowed.to_money.cents, charge_ari)
48
+ end
49
+ end
50
+ end
51
+ end
@@ -0,0 +1,4 @@
1
+ <tr>
2
+ <td><%= Spree.t(:message, :scope => [:log_entry, :affirm]) %></td>
3
+ <td><%= entry.parsed_details.message %></td>
4
+ </tr>
@@ -0,0 +1,28 @@
1
+ <%= render :partial => 'spree/admin/shared/order_tabs', locals: { current: 'Payments' }%>
2
+
3
+ <% content_for :page_title do %>
4
+ <i class="icon-arrow-right"></i>
5
+ <%= I18n.t(:one, scope: "activerecord.models.spree/payment") %>
6
+ <i class="icon-arrow-right"></i>
7
+ <%= Spree.t(:log_entries) %>
8
+ <% end %>
9
+
10
+ <% content_for :page_actions do %>
11
+ <li><%= button_link_to Spree.t(:logs), spree.admin_order_payment_log_entries_url(@order, @payment), :icon => 'icon-archive' %></li>
12
+ <li><%= button_link_to Spree.t(:back_to_payment), spree.admin_order_payment_url(@order, @payment), :icon => 'icon-arrow-left' %></li>
13
+ <% end %>
14
+
15
+ <table class='index' id='listing_log_entries'>
16
+ <% @log_entries.each do |entry| %>
17
+ <thead>
18
+ <tr class="log_entry <%= entry.parsed_details.success? ? 'success' : 'fail' %>">
19
+ <td colspan='2'>
20
+ <h4><i class='icon icon-<%= entry.parsed_details.success? ? 'ok-circle' : 'remove-sign' %>'></i> <%= pretty_time(entry.created_at) %></h4>
21
+ </td>
22
+ </tr>
23
+ </thead>
24
+ <tbody>
25
+ <%= render "spree/admin/log_entries/#{@payment.payment_method.method_type.gsub(' ', '').underscore}", entry: entry rescue render "spree/admin/log_entries/#{@payment.payment_method.name.gsub(' ', '').underscore}", entry: entry %>
26
+ </tbody>
27
+ <% end %>
28
+ </table>
@@ -0,0 +1,19 @@
1
+ <script>
2
+ function showAffirmError(method_id) {
3
+ if (method_id === AffirmPaymentMethodID) {
4
+ $('.payment-method-settings').prepend("<strong id=\"affirm-warning\">You cannot charge Affirm accounts through the admin backend at this time.</strong>");
5
+ } else {
6
+ $('#affirm-warning').remove();
7
+ }
8
+ }
9
+ AffirmPaymentMethodID = "<%= payment_method.id %>"
10
+
11
+ $(function() {
12
+ var checked_method_id = $('[data-hook="payment_method_field"] input[type="radio"]:checked').val();
13
+ showAffirmError(checked_method_id);
14
+
15
+ $('[data-hook="payment_method_field"] input[type="radio"]').click(function (e) {
16
+ showAffirmError($(e.target).val());
17
+ });
18
+ })
19
+ </script>
@@ -0,0 +1,12 @@
1
+ <fieldset data-hook="credit_card">
2
+ <legend align="center">Affirm Payment</legend>
3
+
4
+ <div class="row">
5
+ <div class="alpha six columns">
6
+ <dl>
7
+ <dt>Charge Id:</dt>
8
+ <dd><%= payment.response_code %></dd>
9
+ </dl>
10
+ </div>
11
+ </div>
12
+ </fieldset>
@@ -0,0 +1,195 @@
1
+ <script>
2
+ (function(){
3
+ /* only include this setup once */
4
+ if (!window.AffirmPaymentMethods) {
5
+
6
+ /*****************************************************\
7
+ Include the affirm js snippet
8
+ \*****************************************************/
9
+ var _affirm_config = {
10
+ public_api_key: "<%= payment_method.preferred_api_key %>",
11
+ script: "https://<%= payment_method.preferences[:test_mode] ? 'cdn1-sandbox.affirm.com' : 'cdn1.affirm.com' %>/js/v2/affirm.js"
12
+ };
13
+ (function(l,g,m,e,a,f,b){var d,c=l[m]||{},h=document.createElement(f),n=document.getElementsByTagName(f)[0],k=function(a,b,c){return function(){a[b]._.push([c,arguments])}};c[e]=k(c,e,"set");d=c[e];c[a]={};c[a]._=[];d._=[];c[a][b]=k(c,a,b);a=0;for(b="set add save post open empty reset on off trigger ready setProduct".split(" ");a<b.length;a++)d[b[a]]=k(c,e,b[a]);a=0;for(b=["get","token","url","items"];a<b.length;a++)d[b[a]]=function(){};h.async=!0;h.src=g[f];n.parentNode.insertBefore(h,n);delete g[f];d(g);l[m]=c})(window,_affirm_config,"affirm","checkout","ui","script","ready");
14
+
15
+ /*****************************************************\
16
+ set the shared checkout data
17
+ \*****************************************************/
18
+ affirm.checkout({
19
+ total: <%= (@order.total * 100).to_i %>,
20
+ currency: "USD",
21
+ tax_amount: <%= (@order.additional_tax_total * 100).to_i %>,
22
+ order_id: "<%= @order.number %>",
23
+ discount_code: "<%= @order.coupon_code %>",
24
+ shipping_type: "<%= @order.shipments.first.shipping_method.name if @order.shipments.exists? %>",
25
+ shipping_amount: <%= (@order.shipment_total * 100).to_i %>,
26
+
27
+ shipping: {
28
+ name: {
29
+ full: "<%= @order.ship_address.full_name %>",
30
+ },
31
+ address: {
32
+ line1: "<%= @order.ship_address.address1 %>",
33
+ line2: "<%= @order.ship_address.address2 %>",
34
+ city: "<%= @order.ship_address.city %>",
35
+ state: "<%= @order.ship_address.state_text %>",
36
+ country: "<%= @order.ship_address.country.iso %>",
37
+ zipcode: "<%= @order.ship_address.zipcode %>",
38
+ }
39
+ },
40
+
41
+ billing: {
42
+ email: "<%= @order.email %>",
43
+ name: {
44
+ full: "<%= @order.bill_address.full_name %>"
45
+ },
46
+ address: {
47
+ line1: "<%= @order.bill_address.address1 %>",
48
+ line2: "<%= @order.bill_address.address2 %>",
49
+ city: "<%= @order.bill_address.city %>",
50
+ state: "<%= @order.bill_address.state_text %>",
51
+ country: "<%= @order.bill_address.country.iso %>",
52
+ zipcode: "<%= @order.bill_address.zipcode %>",
53
+ }
54
+ },
55
+
56
+
57
+ metadata: {
58
+ "platform_type": "Spree Commerce",
59
+ "platform_version": "<%= Spree.version %>",
60
+ "platform_affirm": "<%= Spree::Gateway::Affirm.version %>",
61
+ },
62
+
63
+ meta: {
64
+ source: {
65
+ data: {
66
+ <% if spree_current_user %>
67
+ order_count: "<%= spree_current_user.orders.complete.count %>",
68
+ account_created: "<%= spree_current_user.created_at %>",
69
+
70
+ <% if spree_current_user.orders.complete.any? %>
71
+ last_order_date: "<%= spree_current_user.orders.complete.last.completed_at %>",
72
+ <% end %>
73
+
74
+ <% end %>
75
+ is_logged_in: <%= !!spree_current_user %>,
76
+ }
77
+ }
78
+ },
79
+
80
+ merchant: {
81
+ user_confirmation_url: "<%= confirm_affirm_url(:payment_method_id => payment_method.id) %>",
82
+ user_cancel_url: "<%= cancel_affirm_url(:payment_method_id => payment_method.id) %>",
83
+ },
84
+
85
+ config: {
86
+ required_billing_fields: "name,address,email",
87
+ },
88
+
89
+
90
+ <% if @order.promotions.any? %>
91
+ discounts: {
92
+ <% @order.adjustments.promotion.each do |adjustment| %>
93
+ "<%= adjustment.label %>": {
94
+ discount_amount: <%= (0-adjustment.amount*100).to_i %>,
95
+ discount_display_name: "<%= adjustment.label %>"
96
+ },
97
+ <% end %>
98
+ },
99
+ <% end %>
100
+
101
+ items: [
102
+ <% @order.line_items.each do |item| %>
103
+ {
104
+ <% if item.variant.images.any? %>
105
+ item_image_url: "<%= URI.join(root_url, item.variant.images.first.attachment.url(:large)) %>",
106
+ <% elsif item.variant.product.images.any? %>
107
+ item_image_url: "<%= URI.join(root_url, item.variant.product.images.first.attachment.url(:large)) %>",
108
+ <% end %>
109
+
110
+ qty: <%= item.quantity %>,
111
+ sku: "<%= item.variant.sku %>",
112
+ item_url: "<%= product_url(item.product) %>",
113
+ unit_price: <%= item.price * 100 %>,
114
+ display_name: "<%= raw(item.variant.product.name) %>"
115
+ },
116
+ <% end %>
117
+ ]
118
+ });
119
+
120
+
121
+ /* wait for the DOM to be ready */
122
+ affirm.ui.ready(function(){
123
+ $(function() {
124
+
125
+ /*****************************************************\
126
+ change the payment method name
127
+ \*****************************************************/
128
+
129
+ $( ".payment-option" ).each(function() {
130
+
131
+ if($( this )[0].innerText === "Affirm"){
132
+
133
+ $( this )[0].lastChild.data = "Affirm Monthly Payments";
134
+ }
135
+ });
136
+
137
+ /*****************************************************\
138
+ setup loading and cancel events for the form
139
+ \*****************************************************/
140
+
141
+ affirm.checkout.on("cancel", function(){
142
+ $("#checkout_form_payment input.disabled")
143
+ .attr("disabled", false)
144
+ .removeClass("disabled");
145
+ });
146
+
147
+ /*****************************************************\
148
+ handle continue button clicks with .open()
149
+ \*****************************************************/
150
+ $('#checkout_form_payment').submit(function(e){
151
+ var checkedPaymentMethod = $('div[data-hook="checkout_payment_step"] input[type="radio"]:checked').val();
152
+
153
+ if (window.AffirmPaymentMethods[checkedPaymentMethod]) {
154
+
155
+ var $submit_button = $(this).find("input[type='submit']");
156
+
157
+ // update with checkout method details
158
+ affirm.checkout(window.AffirmPaymentMethods[checkedPaymentMethod]);
159
+
160
+ // submit the checkout
161
+ affirm.checkout.open({
162
+ target: $submit_button
163
+ });
164
+
165
+ e.preventDefault();
166
+ return false;
167
+ }
168
+ });
169
+ });
170
+
171
+ /*****************************************************\
172
+ remove the payment source empty box from UI
173
+ \*****************************************************/
174
+ $(document).on('click', '#checkout_form_payment'
175
+ , function (event) {
176
+ if($('div[data-hook="checkout_payment_step"] input[type="radio"]:checked')[0].parentNode.outerText === "Affirm Monthly Payments") $('.payment-sources').hide();
177
+ }
178
+ )
179
+ });
180
+
181
+ window.AffirmPaymentMethods = {};
182
+ }
183
+
184
+
185
+ /*****************************************************\
186
+ set the product/button specific data to be
187
+ used when the continue button is directly
188
+ clicked
189
+ \*****************************************************/
190
+ window.AffirmPaymentMethods["<%= payment_method.id %>"] = {
191
+ public_api_key: "<%= payment_method.preferred_api_key %>"
192
+ };
193
+ }());
194
+
195
+ </script>
data/bin/rails ADDED
@@ -0,0 +1,7 @@
1
+ # This command will automatically be run when you run "rails" with Rails 3 gems installed from the root of your application.
2
+
3
+ ENGINE_ROOT = File.expand_path('../..', __FILE__)
4
+ ENGINE_PATH = File.expand_path('../../lib/spree_affirm/engine', __FILE__)
5
+
6
+ require 'rails/all'
7
+ require 'rails/engine/commands'
@@ -0,0 +1,29 @@
1
+ # Sample localization file for English. Add more files in this directory for other locales.
2
+ # See https://github.com/svenfuchs/rails-i18n/tree/master/rails%2Flocale for starting points.
3
+
4
+ en:
5
+ spree:
6
+ affirm_checkout: "Affirm Checkout"
7
+ activerecord:
8
+ models:
9
+ "spree/affirm_checkout":
10
+ "Order size mismatch": "Order size mismatch"
11
+ "Line Item not in checkout details": "Line Item not in checkout details"
12
+ "Quantity mismatch": "Quantity mismatch"
13
+ "Price mismatch": "Price mismatch"
14
+ "Billing email mismatch": "Billing email mismatch"
15
+ "city mismatch": "city mismatch"
16
+ "street1 mismatch": "street1 mismatch"
17
+ "street2 mismatch": "street2 mismatch"
18
+ "postal_code mismatch": "postal_code mismatch"
19
+ "region1_code mismatch": "region1_code mismatch"
20
+ "First/Last name mismatch": "First/Last name mismatch"
21
+ "Full name mismatch": "Full name mismatch"
22
+
23
+ attributes:
24
+ "spree/affirm_checkout":
25
+ line_items: "items"
26
+ billing_address: "billing address"
27
+ shipping_address: "shipping address"
28
+ billing_email: "email"
29
+
data/config/routes.rb ADDED
@@ -0,0 +1,5 @@
1
+ Spree::Core::Engine.routes.draw do
2
+ # Add your extension routes here
3
+ post '/affirm/confirm', :to => "affirm#confirm", :as => :confirm_affirm
4
+ get '/affirm/cancel', :to => "affirm#cancel", :as => :cancel_affirm
5
+ end
@@ -0,0 +1,10 @@
1
+ class CreateAffirmCheckout < ActiveRecord::Migration
2
+ def change
3
+ create_table :spree_affirm_checkouts do |t|
4
+ t.string :token
5
+ t.references :order
6
+ t.references :payment_method
7
+ t.timestamps
8
+ end
9
+ end
10
+ end