spree_affirm 0.2.3

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 (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