spree_bitpay 0.1.1

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 (54) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +24 -0
  3. data/.rspec +1 -0
  4. data/.travis.yml +18 -0
  5. data/Gemfile +7 -0
  6. data/LICENSE.txt +22 -0
  7. data/README.md +79 -0
  8. data/Rakefile +21 -0
  9. data/app/assets/images/BC_nBG_64px.png +0 -0
  10. data/app/assets/images/bitcoin.png +0 -0
  11. data/app/assets/javascripts/easyModal.js-master/.gitignore +1 -0
  12. data/app/assets/javascripts/easyModal.js-master/README.md +3 -0
  13. data/app/assets/javascripts/easyModal.js-master/bower.json +20 -0
  14. data/app/assets/javascripts/easyModal.js-master/jquery.easyModal.js +161 -0
  15. data/app/assets/javascripts/spree/backend/spree_bitpay.js +3 -0
  16. data/app/assets/javascripts/spree/frontend/spree_bitpay.js +86 -0
  17. data/app/assets/stylesheets/spree/backend/spree_bitpay.css +3 -0
  18. data/app/assets/stylesheets/spree/frontend/spree_bitpay.css +58 -0
  19. data/app/controllers/spree/bitpay_controller.rb +248 -0
  20. data/app/models/spree/bitpay_invoice.rb +23 -0
  21. data/app/models/spree/payment_method/bitpay.rb +64 -0
  22. data/app/overrides/spree/payments/_payment/bitpay_payment_params.html.erb.deface +55 -0
  23. data/app/views/spree/admin/payments/source_views/_bitpay.html.erb +23 -0
  24. data/app/views/spree/checkout/payment/_bitpay.html.erb +4 -0
  25. data/bin/rails +7 -0
  26. data/config/locales/en.yml +16 -0
  27. data/config/routes.rb +9 -0
  28. data/db/migrate/20140720052959_create_spree_bitpay_invoices.rb +8 -0
  29. data/db/migrate/20140725200946_add_fields_to_spree_bitpay_invoice.rb +14 -0
  30. data/db/migrate/20140729192827_add_index_to_spree_payments.rb +5 -0
  31. data/lib/generators/spree_bitpay/install/install_generator.rb +32 -0
  32. data/lib/spree_bitpay/engine.rb +28 -0
  33. data/lib/spree_bitpay/factories.rb +6 -0
  34. data/lib/spree_bitpay/version.rb +3 -0
  35. data/lib/spree_bitpay.rb +3 -0
  36. data/script/rails +7 -0
  37. data/spec/factories/bitpay_test_factories.rb +54 -0
  38. data/spec/features/bitpay_plugin_spec.rb +75 -0
  39. data/spec/fixtures/valid_confirmed_callback.json +27 -0
  40. data/spec/fixtures/valid_confirmed_invoice.json +15 -0
  41. data/spec/fixtures/valid_expired_invoice.json +16 -0
  42. data/spec/fixtures/valid_invalid_callback.json +27 -0
  43. data/spec/fixtures/valid_invalid_invoice.json +15 -0
  44. data/spec/fixtures/valid_new_invoice.json +15 -0
  45. data/spec/fixtures/valid_overpaid_callback.json +27 -0
  46. data/spec/fixtures/valid_overpaid_invoice.json +15 -0
  47. data/spec/fixtures/valid_paid_callback.json +27 -0
  48. data/spec/fixtures/valid_paid_invoice.json +15 -0
  49. data/spec/models/spree/payment_method/bitpay.rb +27 -0
  50. data/spec/requests/notifications_spec.rb +218 -0
  51. data/spec/spec_helper.rb +131 -0
  52. data/spree_bitpay.gemspec +41 -0
  53. data/testapp.sh +16 -0
  54. metadata +375 -0
@@ -0,0 +1,248 @@
1
+ module Spree
2
+ class BitpayController < StoreController
3
+ skip_before_filter :verify_authenticity_token, :only => [:notification]
4
+
5
+ # Generates Bitpay Invoice and returns iframe view
6
+ #
7
+ def pay_now
8
+
9
+ order = current_order || raise(ActiveRecord::RecordNotFound)
10
+
11
+ return redirect_to root_url if order.state != "confirm"
12
+
13
+ # Find the payment by searching for valid payments associated with the order
14
+ # VOID payments are considered valid, so need to exclude those too
15
+ payments = order.payments.where.not(state: %w(failed invalid void))
16
+
17
+ if payments.count > 1 # If there are other completed payments use the one in checkout state
18
+ payment = payments.where(state: "checkout").first
19
+ else
20
+ payment = payments.first
21
+ end
22
+
23
+ logger.debug "Found payment: #{payment.inspect}"
24
+
25
+ case payment.state
26
+ when "checkout"
27
+ # New checkout - create an invoice, and attach its id to the payment.source
28
+ invoice = new_invoice(order, payment)
29
+ payment.source.invoice_id = invoice['id']
30
+ payment.source.save!
31
+ payment.started_processing!
32
+ else
33
+ # An invoice was already created - find it
34
+ invoice = payment.source.find_invoice
35
+ end
36
+
37
+ @invoice_iframe_url = "#{invoice['url']}&view=iframe"
38
+ render json: @invoice_iframe_url
39
+ end
40
+
41
+ # View Invoice with specific ID
42
+ #
43
+ def view_invoice
44
+ invoice = BitpayInvoice.find(params[:source_id]).find_invoice
45
+ redirect_to (invoice["url"] + '&view=iframe')
46
+ end
47
+
48
+ def check_payment_state
49
+ invoice = BitpayInvoice.where(invoice_id: params[:invoice_id]).first
50
+ pm = PaymentMethod.find(invoice.payment_method_id)
51
+ status = pm.scan_the_server(invoice.invoice_id)
52
+ render json: status
53
+ end
54
+
55
+ def cancel
56
+
57
+ order = current_order || raise(ActiveRecord::RecordNotFound)
58
+
59
+ # Find and invalidate Bitpay payment in processing state
60
+ order.payments.with_state("processing").each do |payment|
61
+ if (payment.payment_method.is_a? Spree::PaymentMethod::Bitpay)
62
+ payment.state = "invalid" # Have to set this explicitly since Spree state machine prevents it
63
+ payment.save!
64
+ end
65
+ end
66
+
67
+ redirect_to edit_order_url(order, state: 'payment'), :notice => Spree.t(:checkout_cancelled)
68
+
69
+ end
70
+
71
+ # Fires on receipt of payment received window message
72
+ #
73
+ def payment_sent
74
+
75
+ order = Spree::Order.find(session[:order_id]) || raise(ActiveRecord::RecordNotFound)
76
+
77
+ session[:order_id] = nil # Reset cart
78
+ redirect_to spree.order_path(order), :notice => Spree.t(:order_processed_successfully)
79
+
80
+ end
81
+
82
+ ## Handle IPN from Bitpay server
83
+ # Receives incoming IPN message and retrieves official BitPay invoice for processing
84
+ #
85
+ def notification
86
+
87
+ posData = JSON.parse(params["posData"])
88
+
89
+ order_id = posData["orderID"]
90
+ payment_id = posData["paymentID"]
91
+
92
+ # Get OFFICIAL Invoice from BitPay API
93
+ # Fetching payment this way should prevent any false payment/order mismatch
94
+ order = Spree::Order.find_by_number(order_id) || raise(ActiveRecord::RecordNotFound)
95
+ payment = order.payments.find_by(identifier: payment_id) || raise(ActiveRecord::RecordNotFound)
96
+ invoice = payment.source.find_invoice
97
+
98
+ if invoice
99
+ logger.debug("Bitpay Invoice Content: " + invoice.to_json)
100
+ process_invoice(invoice)
101
+ head :ok
102
+ else
103
+ raise "Spree_Bitpay: No invoice found for notification for #{payment.identifier} from #{request.remote_ip}"
104
+ end
105
+
106
+ rescue
107
+ logger.error "Spree_Bitpay: Unprocessable notification received from #{request.remote_ip}: #{params.inspect}"
108
+ head :unprocessable_entity
109
+ end
110
+
111
+ # Reprocess Invoice and update order status
112
+ #
113
+ def refresh
114
+ payment = Spree::Payment.find(params[:payment]) # Retrieve payment by ID
115
+ old_state = payment.state
116
+ invoice = payment.source.find_invoice # Get associated invoice
117
+ process_invoice(invoice) # Re-process invoice
118
+ new_state = payment.reload.state
119
+ notice = (new_state == old_state) ? Spree.t(:bitpay_payment_not_updated) : (Spree.t(:bitpay_payment_updated) + new_state.titlecase)
120
+ redirect_to (request.referrer || root_path), notice: notice
121
+ end
122
+
123
+ #######################################################################
124
+ ### Private Methods
125
+ #######################################################################
126
+
127
+ private
128
+
129
+ # Call Bitpay API and return new JSON invoice object
130
+ #
131
+ def new_invoice(order, payment)
132
+
133
+ # Have to encode this into a string for proper handling by API
134
+ posDataJson = {paymentID: payment.identifier, orderID: order.number}.to_json
135
+
136
+ invoice_params = {
137
+ price: order.outstanding_balance,
138
+ currency: order.currency,
139
+ orderID: order.number,
140
+ notificationURL: bitpay_notification_url,
141
+ posData: posDataJson,
142
+ fullNotifications: "true"
143
+ }
144
+
145
+ logger.debug "Requesting Invoice with params: #{invoice_params}"
146
+ invoice = payment.payment_method.get_bitpay_client.post 'invoice', invoice_params
147
+ logger.debug "Invoice Generated: #{invoice.inspect}"
148
+
149
+ return invoice
150
+ end
151
+
152
+ # Process the invoice and adjust order state accordingly
153
+ # Accepts BitPay JSON invoice object
154
+ #
155
+ def process_invoice(invoice)
156
+ logger.debug "Processing Bitpay invoice"
157
+
158
+ # Extract posData
159
+ posData = JSON.parse(invoice["posData"])
160
+
161
+ payment_id = posData["paymentID"]
162
+ status = invoice["status"]
163
+ exception_status = invoice["exceptionStatus"]
164
+
165
+ payment = Spree::Payment.find_by(identifier: payment_id) || raise(ActiveRecord::RecordNotFound)
166
+
167
+ logger.debug "Found Payment: #{payment.inspect}"
168
+
169
+ # Advance Payment state according to Spree flow
170
+ # http://guides.spreecommerce.com/user/payment_states.html
171
+
172
+ case status
173
+ when "new"
174
+
175
+ payment.started_processing
176
+
177
+ when "paid"
178
+
179
+ # Move payment to pending state and complete order
180
+
181
+ if payment.state = "processing" # This is the most common scenario
182
+ payment.pend!
183
+ else # In the case it was previously marked invalid due to invoice expiry
184
+ payment.state = "pending"
185
+ payment.save
186
+ end
187
+
188
+ payment.order.update!
189
+ payment.order.next
190
+ if (!payment.order.complete?)
191
+ raise "Can't transition order #{payment.order.number} to COMPLETE state"
192
+ end
193
+
194
+ when "confirmed", "complete"
195
+
196
+ # Move payment to 'complete' state
197
+
198
+ case payment.state
199
+ when "pending" # This is the most common scenario
200
+ payment.complete
201
+ when "completed"
202
+ # Do nothing
203
+ else
204
+ # Something unusual happened - maybe a notification was missed, or
205
+ # Make sure the order is completed
206
+ if !payment.order.complete?
207
+ payment.state = "pending"
208
+ payment.save
209
+ payment.order.next
210
+ if (!payment.order.complete?)
211
+ raise "Can't transition order #{payment.order.number} to COMPLETE state"
212
+ end
213
+ end
214
+ payment.state = "completed" # Can't use Spree payment.complete! method since we are transitioning from weird states
215
+ payment.save
216
+ end
217
+
218
+ when "expired"
219
+
220
+ if (exception_status == false) # This is an abandoned invoice
221
+ payment.state = "invalid" # Have to set this explicitly since Spree state machine prevents it
222
+ payment.save!
223
+ else
224
+ # Don't think this will be anything other than paidPartial exceptionStatus
225
+ unless payment.state == 'void'
226
+ payment.void!
227
+ end
228
+ end
229
+
230
+ when "invalid"
231
+
232
+ unless payment.state == 'failed'
233
+ payment.failure! # Will be flagged risky automatically
234
+ end
235
+
236
+ else
237
+
238
+ raise "Unexpected status received from BitPay: '#{invoice["status"]}' for '#{invoice["url"]}"
239
+
240
+ end
241
+
242
+ logger.debug "New Payment State for #{payment.identifier}: #{payment.state}"
243
+ logger.debug "New Order State for #{payment.order.number}: #{payment.order.state}"
244
+
245
+ end
246
+
247
+ end
248
+ end
@@ -0,0 +1,23 @@
1
+ module Spree
2
+
3
+ class BitpayInvoice < ActiveRecord::Base
4
+ belongs_to :payment_method
5
+ belongs_to :user
6
+ has_many :payments, as: :source
7
+
8
+ # DB fields: user_id, invoice_id
9
+
10
+ attr_accessor :bogus # bogus since we need to have a param that is passed to trigger Payment.build_source
11
+
12
+ def actions
13
+ # TODO: Refund action?
14
+ ["void"]
15
+ end
16
+
17
+ # Gets the JSON invoice from Bitpay
18
+ def find_invoice
19
+ payment_method.find_invoice(invoice_id)
20
+ end
21
+
22
+ end
23
+ end
@@ -0,0 +1,64 @@
1
+ module Spree
2
+ class PaymentMethod::Bitpay < PaymentMethod
3
+ preference :api_key, :string
4
+ preference :api_endpoint, :string, :default => "https://bitpay.com/api"
5
+
6
+ def auto_capture?
7
+ true
8
+ end
9
+
10
+ def payment_source_class
11
+ Spree::BitpayInvoice
12
+ end
13
+
14
+ # Set true to force confirmation step.
15
+ # http://guides.spreecommerce.com/developer/checkout.html#confirmation
16
+ #
17
+ def payment_profiles_supported?
18
+ true
19
+ end
20
+
21
+ ## Dummy method to satisfy test factories
22
+ #
23
+ def create_profile(payment)
24
+ nil
25
+ end
26
+
27
+ def source_required?
28
+ false
29
+ end
30
+
31
+ #######################################################################
32
+ ### Instance Utility Methods
33
+ #######################################################################
34
+
35
+ ## Retreive Invoice by ID from BitPay
36
+ #
37
+ def find_invoice(id)
38
+ id ? ( get_bitpay_client.get ('invoice/' + id) ) : nil
39
+ end
40
+
41
+
42
+ def scan_the_server(id)
43
+ message = get_bitpay_client.get('invoice/' + id)
44
+ status = message["status"]
45
+ return status unless status.nil?
46
+ error = message["error"]["message"] if status.nil?
47
+ return error unless error.nil?
48
+ "unknown error"
49
+ end
50
+
51
+ ## Interface with BitPay
52
+ #
53
+ def get_bitpay_client
54
+ BitPay::Client.new(preferred_api_key, {api_uri: preferred_api_endpoint})
55
+ end
56
+
57
+ ## This is a stub method which simply returns true to allow the cancel on the Spree side
58
+ #
59
+ def void (action, order_id, id)
60
+ ActiveMerchant::Billing::Response.new(true, 'Bogus Gateway: Forced success')
61
+ end
62
+
63
+ end
64
+ end
@@ -0,0 +1,55 @@
1
+ <!-- insert_after 'erb[loud]:contains("payment_method")' -->
2
+
3
+ <% if (payment.payment_method.is_a? Spree::PaymentMethod::Bitpay) && (payment.state != 'void') %>
4
+ <% pm = payment.payment_method %>
5
+ <%= image_tag("BC_nBG_64px.png") %>
6
+ <script type="text/javascript">
7
+ $(document).ready(function() {
8
+ $('[data-hook="buttons"] input[name="commit"]').click(Bitpay.checkout);
9
+ $('#checkout_form_confirm').removeAttr("action");
10
+ $('#checkout_form_confirm').removeAttr("method");
11
+
12
+ $('#bitpay_checkout_modal').easyModal({
13
+ overlayClose: false,
14
+ closeOnEscape: false
15
+ });
16
+
17
+ Bitpay.invoiceUrl = "<%= j bitpay_pay_now_url(pmid: pm.id).html_safe %>";
18
+ Bitpay.checkUrl = "<%= j bitpay_check_url %>";
19
+ Bitpay.apiEndpoint = "<%= pm.get_preference(:api_endpoint) %>";
20
+ })
21
+
22
+ window.addEventListener('message', Bitpay.finishCheckout, false);
23
+
24
+ </script>
25
+
26
+ <div id="bitpay_checkout_modal">
27
+ <div id="bitpay_modal_content">
28
+ <div id="bitpay_invoice">
29
+ <iframe id="bitpay_invoice_iframe"
30
+ scrolling="no"
31
+ allowtransparency="true"
32
+ frameborder="0", >
33
+ </iframe>
34
+ </div>
35
+ <div id="bitpay_checkout_guidance">
36
+ <span id="instructions"><%= simple_format Spree.t(:bitpay_payment_instructions) %></span>
37
+ <span id="completed" style="display:none"><%= Spree.t(:bitpay_payment_completed) %></span>
38
+ <span id="expired" style="display:none"><%= Spree.t(:bitpay_invoice_expired) %></span>
39
+ </br>
40
+ </div>
41
+ <div id="bitpay_payment_buttons" class="form-buttons">
42
+ <a id="continue_to_invoice"
43
+ class="button disabled"
44
+ disabled="disabled"
45
+ href="<%= bitpay_payment_sent_url %>">
46
+ <span><%= Spree.t(:bitpay_view_invoice) %></span>
47
+ </a>
48
+ <%= link_to Spree.t(:bitpay_cancel), bitpay_cancel_url, {id: "choose_another_method", class: "button primary"} %>
49
+ </div>
50
+ </div>
51
+ </div>
52
+
53
+ <% end %>
54
+
55
+
@@ -0,0 +1,23 @@
1
+ <% invoice = @payment.source.find_invoice %>
2
+ <% if invoice %>
3
+ <div class="bitpay_invoice_details">
4
+ <h3>Bitpay Invoice Details</h3>
5
+ <pre><%= JSON.pretty_generate(invoice) %></pre>
6
+ </div>
7
+
8
+ <%= link_to Spree.t(:bitpay_refresh_invoice), bitpay_refresh_url(payment: @payment), {id: "refresh_invoice", class: "button primary", title: Spree.t(:bitpay_refresh_invoice_description)} %>
9
+
10
+ <div class="bitpay_invoice_details">
11
+ <h3>Invoice</h3>
12
+ <iframe id="bitpay_view_invoice_iframe"
13
+ src="<%= j bitpay_view_invoice_url(source_id: @payment.source).html_safe %>"
14
+ scrolling="no"
15
+ allowtransparency="true"
16
+ frameborder="0">
17
+ </iframe>
18
+ <br/>
19
+ <%= link_to Spree.t(:bitpay_view_full_invoice), invoice["url"], {target: "_new"} %>
20
+ </div>
21
+ <% else %>
22
+ <p>No BitPay Invoice Available</p>
23
+ <% end %>
@@ -0,0 +1,4 @@
1
+
2
+ <%= image_tag("BC_nBG_64px.png") %>
3
+ <p><%= Spree.t(:bitpay_payment_method) %></p>
4
+ <%= hidden_field_tag "payment_source[#{payment_method.id}][bogus]", 'bogus', :id => "bogus" %>
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_bitpay/engine', __FILE__)
5
+
6
+ require 'rails/all'
7
+ require 'rails/engine/commands'
@@ -0,0 +1,16 @@
1
+ en:
2
+ spree:
3
+ bitpay_cancel: "Choose another payment method"
4
+ bitpay_checkout_error: "Error with Bitcoin checkout"
5
+ bitpay_payment_completed: "Thank you for your payment."
6
+ bitpay_invoice_expired: "The invoice has expired. Please re-select Bitcoin if you would like to retry."
7
+ bitpay_payment_instructions: |
8
+ Please pay the invoice above to continue.
9
+ The page will automatically refresh in a few seconds when transaction is broadcast.
10
+ bitpay_payment_method: "Payment will be requested following the confirmation."
11
+ bitpay_view_invoice: "Continue to Invoice"
12
+ bitpay_view_full_invoice: "View invoice at BitPay.com"
13
+ bitpay_refresh_invoice: "Reprocess Invoice"
14
+ bitpay_refresh_invoice_description: "Re-poll BitPay invoice and update order status"
15
+ bitpay_payment_updated: "Payment status changed to: "
16
+ bitpay_payment_not_updated: "No status change detected."
data/config/routes.rb ADDED
@@ -0,0 +1,9 @@
1
+ Spree::Core::Engine.routes.draw do
2
+ get '/spree_bitpay/invoice/new', :to => "bitpay#pay_now", :as => :bitpay_pay_now
3
+ get '/spree_bitpay/invoice/view', :to => "bitpay#view_invoice", :as => :bitpay_view_invoice
4
+ get '/spree_bitpay/payment_sent', :to => "bitpay#payment_sent", :as => :bitpay_payment_sent
5
+ get '/spree_bitpay/cancel', :to => "bitpay#cancel", :as => :bitpay_cancel
6
+ get '/spree_bitpay/refresh', :to => "bitpay#refresh", :as => :bitpay_refresh
7
+ get '/spree_bitpay/check', :to => "bitpay#check_payment_state", :as => :bitpay_check
8
+ post '/spree_bitpay/notification', :to => "bitpay#notification", :as => :bitpay_notification
9
+ end
@@ -0,0 +1,8 @@
1
+ class CreateSpreeBitpayInvoices < ActiveRecord::Migration
2
+ def change
3
+ create_table :spree_bitpay_invoices do |t|
4
+ t.string :invoice_id
5
+ t.timestamps
6
+ end
7
+ end
8
+ end
@@ -0,0 +1,14 @@
1
+ class AddFieldsToSpreeBitpayInvoice < ActiveRecord::Migration
2
+ def change
3
+
4
+ unless Spree::BitpayInvoice.column_names.include? "payment_method_id"
5
+ add_column :spree_bitpay_invoices, :payment_method_id, :integer
6
+ add_index :spree_bitpay_invoices, :payment_method_id
7
+ end
8
+
9
+ unless Spree::BitpayInvoice.column_names.include? "user_id"
10
+ add_column :spree_bitpay_invoices, :user_id, :integer
11
+ end
12
+
13
+ end
14
+ end
@@ -0,0 +1,5 @@
1
+ class AddIndexToSpreePayments < ActiveRecord::Migration
2
+ def change
3
+ add_index :spree_payments, :identifier
4
+ end
5
+ end
@@ -0,0 +1,32 @@
1
+ module SpreeBitpay
2
+ module Generators
3
+ class InstallGenerator < Rails::Generators::Base
4
+
5
+ class_option :auto_run_migrations, :type => :boolean, :default => false
6
+
7
+ def add_javascripts
8
+ append_file 'vendor/assets/javascripts/spree/frontend/all.js', "//= require spree/frontend/spree_bitpay\n"
9
+ append_file 'vendor/assets/javascripts/spree/frontend/all.js', "//= require easyModal.js-master/jquery.easyModal\n"
10
+ append_file 'vendor/assets/javascripts/spree/backend/all.js', "//= require spree/backend/spree_bitpay\n"
11
+ end
12
+
13
+ def add_stylesheets
14
+ inject_into_file 'vendor/assets/stylesheets/spree/frontend/all.css', " *= require spree/frontend/spree_bitpay\n", :before => /\*\//, :verbose => true
15
+ inject_into_file 'vendor/assets/stylesheets/spree/backend/all.css', " *= require spree/backend/spree_bitpay\n", :before => /\*\//, :verbose => true
16
+ end
17
+
18
+ def add_migrations
19
+ run 'bundle exec rake railties:install:migrations FROM=spree_bitpay'
20
+ end
21
+
22
+ def run_migrations
23
+ run_migrations = options[:auto_run_migrations] || ['', 'y', 'Y'].include?(ask 'Would you like to run the migrations now? [Y/n]')
24
+ if run_migrations
25
+ run 'bundle exec rake db:migrate'
26
+ else
27
+ puts 'Skipping rake db:migrate, don\'t forget to run it!'
28
+ end
29
+ end
30
+ end
31
+ end
32
+ end
@@ -0,0 +1,28 @@
1
+ require 'bitpay'
2
+
3
+ module SpreeBitpay
4
+ class Engine < Rails::Engine
5
+ require 'spree/core'
6
+ isolate_namespace Spree
7
+ engine_name 'spree_bitpay'
8
+
9
+ # use rspec for tests
10
+ config.generators do |g|
11
+ g.test_framework :rspec
12
+ end
13
+
14
+ initializer "spree.bitpay.payment_methods", :after => "spree.register.payment_methods" do |app|
15
+ app.config.spree.payment_methods << Spree::PaymentMethod::Bitpay
16
+ end
17
+
18
+ def self.activate
19
+ Dir.glob(File.join(File.dirname(__FILE__), '../../app/**/*_decorator*.rb')) do |c|
20
+ Rails.configuration.cache_classes ? require(c) : load(c)
21
+ end
22
+ end
23
+
24
+ config.to_prepare &method(:activate).to_proc
25
+ end
26
+ end
27
+
28
+ Spree::PermittedAttributes.source_attributes.push(:bogus)
@@ -0,0 +1,6 @@
1
+ FactoryGirl.define do
2
+ # Define your Spree extensions Factories within this file to enable applications, and other extensions to use and override them.
3
+ #
4
+ # Example adding this to your spec_helper will load these Factories for use:
5
+ # require 'spree_bitpay/factories'
6
+ end
@@ -0,0 +1,3 @@
1
+ module SpreeBitpay
2
+ VERSION = "1.0.1"
3
+ end
@@ -0,0 +1,3 @@
1
+ require 'spree_core'
2
+ require 'spree_bitpay/version'
3
+ require 'spree_bitpay/engine'
data/script/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_bitpay/engine', __FILE__)
5
+
6
+ require 'rails/all'
7
+ require 'rails/engine/commands'
@@ -0,0 +1,54 @@
1
+ ## Factories for setting up Spree BitPay inflight orders/payments
2
+ #
3
+ #
4
+
5
+ # Easily recognizable dummy values
6
+
7
+ PAYMENT_ID = "123PAYMENTID"
8
+ ORDER_ID = "123ORDERID"
9
+ INVOICE_ID = "123BitPayInvoiceID"
10
+
11
+
12
+ FactoryGirl.define do
13
+ ## Creates a payment in 'processing' state with associated order in 'confirm' state
14
+ #
15
+ factory :abstract_btc_payment, class: Spree::Payment do
16
+ association :payment_method, factory: :bitcoin_payment_method
17
+ association :source, factory: :bitcoin_invoice
18
+ amount { order.total }
19
+ response_code 'BTC'
20
+ after(:create) do |payment|
21
+ payment.identifier = PAYMENT_ID
22
+ payment.save!
23
+ payment.order.update!
24
+ end
25
+
26
+ factory :processing_payment_with_confirming_order do
27
+ state 'processing'
28
+ association :order, factory: :order_with_line_items, state: "confirm", number: ORDER_ID
29
+ end
30
+
31
+ factory :pending_payment_with_complete_order do
32
+ state 'pending'
33
+ association :order, factory: :order_with_line_items, state: "complete", number: ORDER_ID
34
+ end
35
+
36
+ factory :invalid_payment_with_confirming_order do
37
+ state 'invalid'
38
+ association :order, factory: :order_with_line_items, state: "confirm", number: ORDER_ID
39
+ end
40
+
41
+ end
42
+
43
+ factory :bitcoin_payment_method, class: Spree::PaymentMethod::Bitpay do
44
+ name 'Bitcoin Auto'
45
+ environment 'test'
46
+ end
47
+
48
+ factory :bitcoin_invoice, class: Spree::BitpayInvoice do
49
+ association :user
50
+ invoice_id INVOICE_ID
51
+ association :payment_method, factory: :bitcoin_payment_method
52
+ end
53
+
54
+ end