spree_bitpay 0.1.1

Sign up to get free protection for your applications and to get access to all the features.
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