spree_affirm 0.2.3 → 0.2.19

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