spree_affirm 0.2.3 → 0.2.19

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 +5 -5
  2. metadata +26 -75
  3. data/.gitignore +0 -15
  4. data/Gemfile +0 -19
  5. data/LICENSE +0 -29
  6. data/README.md +0 -51
  7. data/Rakefile +0 -15
  8. data/Versionfile +0 -5
  9. data/app/assets/javascripts/spree/backend/spree_affirm.js +0 -3
  10. data/app/assets/javascripts/spree/frontend/spree_affirm.js +0 -2
  11. data/app/assets/stylesheets/spree/backend/spree_affirm.css +0 -4
  12. data/app/assets/stylesheets/spree/frontend/spree_affirm.css +0 -4
  13. data/app/controllers/spree/affirm_controller.rb +0 -68
  14. data/app/models/spree/affirm_checkout.rb +0 -38
  15. data/app/models/spree/gateway/affirm.rb +0 -51
  16. data/app/views/spree/admin/log_entries/_affirm.html.erb +0 -4
  17. data/app/views/spree/admin/log_entries/index.html.erb +0 -28
  18. data/app/views/spree/admin/payments/source_forms/_affirm.html.erb +0 -19
  19. data/app/views/spree/admin/payments/source_views/_affirm.html.erb +0 -12
  20. data/app/views/spree/checkout/payment/_affirm.html.erb +0 -195
  21. data/bin/rails +0 -7
  22. data/config/locales/en.yml +0 -29
  23. data/config/routes.rb +0 -5
  24. data/db/migrate/20140514194315_create_affirm_checkout.rb +0 -10
  25. data/lib/active_merchant/billing/affirm.rb +0 -161
  26. data/lib/generators/spree_affirm/install/install_generator.rb +0 -21
  27. data/lib/spree_affirm.rb +0 -2
  28. data/lib/spree_affirm/engine.rb +0 -27
  29. data/lib/spree_affirm/factories.rb +0 -5
  30. data/lib/spree_affirm/factories/affirm_checkout_factory.rb +0 -211
  31. data/lib/spree_affirm/factories/affirm_payment_method_factory.rb +0 -8
  32. data/lib/spree_affirm/factories/payment_factory.rb +0 -10
  33. data/lib/spree_affirm/version.rb +0 -3
  34. data/spec/controllers/affirm_controller_spec.rb +0 -138
  35. data/spec/lib/active_merchant/billing/affirm_spec.rb +0 -294
  36. data/spec/models/affirm_address_validator_spec.rb +0 -13
  37. data/spec/models/spree_affirm_checkout_spec.rb +0 -328
  38. data/spec/models/spree_gateway_affirm_spec.rb +0 -134
  39. data/spec/spec_helper.rb +0 -98
  40. data/spree_affirm.gemspec +0 -30
@@ -1,38 +0,0 @@
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
@@ -1,51 +0,0 @@
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
@@ -1,4 +0,0 @@
1
- <tr>
2
- <td><%= Spree.t(:message, :scope => [:log_entry, :affirm]) %></td>
3
- <td><%= entry.parsed_details.message %></td>
4
- </tr>
@@ -1,28 +0,0 @@
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>
@@ -1,19 +0,0 @@
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>
@@ -1,12 +0,0 @@
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>
@@ -1,195 +0,0 @@
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 DELETED
@@ -1,7 +0,0 @@
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'
@@ -1,29 +0,0 @@
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
-
@@ -1,5 +0,0 @@
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
@@ -1,10 +0,0 @@
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
@@ -1,161 +0,0 @@
1
- module ActiveMerchant #:nodoc:
2
- module Billing #:nodoc:
3
- class Affirm < Gateway
4
- self.supported_countries = %w(US)
5
- self.default_currency = 'USD'
6
- self.money_format = :cents
7
-
8
- def initialize(options = {})
9
- requires!(options, :api_key, :secret_key, :server)
10
- @api_key = options[:api_key]
11
- @secret_key = options[:secret_key]
12
- super
13
- end
14
-
15
- def set_charge(charge_id)
16
- @charge_id = charge_id
17
- end
18
-
19
- def authorize(money, affirm_source, options = {})
20
- result = commit(:post, "", {"checkout_token"=>affirm_source.token}, options, true)
21
- return result unless result.success?
22
-
23
- if amount(money).to_i != result.params["amount"].to_i
24
- return Response.new(false,
25
- "Auth amount does not match charge amount",
26
- result.params
27
- )
28
- elsif result.params["pending"].to_s != "true"
29
- return Response.new(false,
30
- "There was an error authorizing this Charge",
31
- result.params
32
- )
33
- end
34
- result
35
- end
36
-
37
- # To create a charge on a card or a token, call
38
- #
39
- # purchase(money, card_hash_or_token, { ... })
40
- #
41
- # To create a charge on a customer, call
42
- #
43
- # purchase(money, nil, { :customer => id, ... })
44
- def purchase(money, affirm_source, options = {})
45
- result = authorize(money, affirm_source, options)
46
- return result unless result.success?
47
- capture(money, @charge_id, options)
48
- end
49
-
50
- def capture(money, charge_source, options = {})
51
- post = {:amount => amount(money)}
52
- set_charge(charge_source)
53
- result = commit(:post, "#{@charge_id}/capture", post, options)
54
- return result unless result.success?
55
-
56
- if amount(money).to_i != result.params["amount"].to_i
57
- return Response.new(false,
58
- "Capture amount does not match charge amount",
59
- result.params
60
- )
61
- end
62
- result
63
- end
64
-
65
- def void(charge_source, options = {})
66
- set_charge(charge_source)
67
- commit(:post, "#{@charge_id}/void", {}, options)
68
- end
69
-
70
- def refund(money, charge_source, options = {})
71
- post = {:amount => amount(money)}
72
- set_charge(charge_source)
73
- commit(:post, "#{@charge_id}/refund", post, options)
74
- end
75
-
76
- def credit(money, charge_source, options = {})
77
- set_charge(charge_source)
78
- return Response.new(true ,
79
- "Credited Zero amount",
80
- {},
81
- :authorization => @charge_id,
82
- ) unless money > 0
83
- refund(money, charge_source, options)
84
- end
85
-
86
- def root_url
87
- "#{root_api_url}charges/"
88
- end
89
-
90
- def root_api_url
91
- "https://#{@options[:server]}/api/v2/"
92
- end
93
-
94
- def headers
95
- {
96
- "Content-Type" => "application/json",
97
- "Authorization" => "Basic " + Base64.encode64(@api_key.to_s + ":" + @secret_key.to_s).gsub(/\n/, '').strip,
98
- "User-Agent" => "Affirm/v1 ActiveMerchantBindings",
99
- }
100
- end
101
-
102
- def parse(body)
103
- JSON.parse(body)
104
- end
105
-
106
- def post_data(params)
107
- return nil unless params
108
- params.to_json
109
- end
110
-
111
- def response_error(raw_response)
112
- begin
113
- parse(raw_response)
114
- rescue JSON::ParserError
115
- json_error(raw_response)
116
- end
117
- end
118
-
119
- def json_error(raw_response)
120
- msg = 'Invalid response. Please contact affirm if you continue to receive this message.'
121
- msg += " (The raw response returned by the API was #{raw_response.inspect})"
122
- {
123
- "error" => {
124
- "message" => msg
125
- }
126
- }
127
- end
128
-
129
- def get_checkout(checkout_token)
130
- _url = root_api_url + "checkout/#{checkout_token}"
131
- _raw_response = ssl_request :get, _url, nil, headers
132
-
133
- parse(_raw_response)
134
- end
135
-
136
- def commit(method, url, parameters=nil, options = {}, ret_charge=false)
137
- raw_response = response = nil
138
- success = false
139
- begin
140
- raw_response = ssl_request(method, root_url + url, post_data(parameters), headers)
141
- response = parse(raw_response)
142
- success = !response.key?("status_code") && (!ret_charge || response.key?("id"))
143
- rescue ResponseError => e
144
- raw_response = e.response.body
145
- response = response_error(raw_response)
146
- rescue JSON::ParserError
147
- response = json_error(raw_response)
148
- end
149
-
150
- if success && ret_charge
151
- @charge_id = response["id"]
152
- end
153
- Response.new(success,
154
- success ? "Transaction approved" : response["message"],
155
- response,
156
- :authorization => @charge_id,
157
- )
158
- end
159
- end
160
- end
161
- end