spree_bitpay 1.0.2 → 2.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (56) hide show
  1. checksums.yaml +4 -4
  2. metadata +44 -1243
  3. data/.gitignore +0 -26
  4. data/.rspec +0 -1
  5. data/.travis.yml +0 -18
  6. data/Gemfile +0 -7
  7. data/LICENSE.txt +0 -22
  8. data/README.md +0 -79
  9. data/Rakefile +0 -21
  10. data/app/assets/images/BC_nBG_64px.png +0 -0
  11. data/app/assets/images/bitcoin.png +0 -0
  12. data/app/assets/javascripts/easyModal.js-master/.gitignore +0 -1
  13. data/app/assets/javascripts/easyModal.js-master/README.md +0 -3
  14. data/app/assets/javascripts/easyModal.js-master/bower.json +0 -20
  15. data/app/assets/javascripts/easyModal.js-master/jquery.easyModal.js +0 -161
  16. data/app/assets/javascripts/spree/backend/spree_bitpay.js +0 -3
  17. data/app/assets/javascripts/spree/frontend/spree_bitpay.js +0 -86
  18. data/app/assets/stylesheets/spree/backend/spree_bitpay.css +0 -3
  19. data/app/assets/stylesheets/spree/frontend/spree_bitpay.css +0 -58
  20. data/app/controllers/spree/bitpay_controller.rb +0 -243
  21. data/app/models/order_decorator.rb +0 -17
  22. data/app/models/spree/bitpay_invoice.rb +0 -23
  23. data/app/models/spree/payment_method/bitpay.rb +0 -64
  24. data/app/overrides/spree/payments/_payment/bitpay_payment_params.html.erb.deface +0 -55
  25. data/app/views/spree/admin/payments/source_views/_bitpay.html.erb +0 -23
  26. data/app/views/spree/checkout/payment/_bitpay.html.erb +0 -4
  27. data/bin/rails +0 -7
  28. data/config/locales/en.yml +0 -16
  29. data/config/routes.rb +0 -9
  30. data/db/migrate/20140720052959_create_spree_bitpay_invoices.rb +0 -8
  31. data/db/migrate/20140725200946_add_fields_to_spree_bitpay_invoice.rb +0 -14
  32. data/db/migrate/20140729192827_add_index_to_spree_payments.rb +0 -5
  33. data/lib/generators/spree_bitpay/install/install_generator.rb +0 -32
  34. data/lib/spree_bitpay.rb +0 -3
  35. data/lib/spree_bitpay/engine.rb +0 -28
  36. data/lib/spree_bitpay/factories.rb +0 -6
  37. data/lib/spree_bitpay/version.rb +0 -3
  38. data/script/rails +0 -7
  39. data/spec/factories/bitpay_test_factories.rb +0 -58
  40. data/spec/features/bitpay_plugin_spec.rb +0 -75
  41. data/spec/fixtures/valid_confirmed_callback.json +0 -27
  42. data/spec/fixtures/valid_confirmed_invoice.json +0 -15
  43. data/spec/fixtures/valid_expired_invoice.json +0 -16
  44. data/spec/fixtures/valid_invalid_callback.json +0 -27
  45. data/spec/fixtures/valid_invalid_invoice.json +0 -15
  46. data/spec/fixtures/valid_new_invoice.json +0 -15
  47. data/spec/fixtures/valid_overpaid_callback.json +0 -27
  48. data/spec/fixtures/valid_overpaid_invoice.json +0 -15
  49. data/spec/fixtures/valid_paid_callback.json +0 -27
  50. data/spec/fixtures/valid_paid_invoice.json +0 -15
  51. data/spec/models/spree/order_spec.rb +0 -41
  52. data/spec/models/spree/payment_method/bitpay.rb +0 -26
  53. data/spec/requests/notifications_spec.rb +0 -218
  54. data/spec/spec_helper.rb +0 -131
  55. data/spree_bitpay.gemspec +0 -40
  56. data/testapp.sh +0 -6
@@ -1,3 +0,0 @@
1
- /*
2
- *= require spree/backend
3
- */
@@ -1,58 +0,0 @@
1
- /*
2
- *= require spree/frontend
3
- */
4
- // Bitpay Payment Method styling
5
-
6
- // No idea why this element is needed but it seems the first entry is ignored??
7
- // TODO: Is this really needed?
8
-
9
- #throwaway {
10
- width: 20px;
11
- }
12
-
13
- #bitpay_modal_content {
14
- padding:40px;
15
- background-color: #FFF;
16
- }
17
-
18
- #bitpay_invoice_iframe {
19
- width: 500px;
20
- //height: 150px;
21
- border: 1px solid #d9d9db;
22
- overflow: hidden;
23
- padding:20px;
24
- max-width: 100%;
25
- }
26
-
27
-
28
- #bitpay_view_invoice_iframe {
29
- width: 542px;
30
- //height: 150px;
31
- border: 1px solid #d9d9db;
32
- overflow: hidden;
33
- padding:20px;
34
- max-width: 100%;
35
- }
36
-
37
- #bitpay_checkout_guidance {
38
- text-align: center;
39
- margin: auto;
40
- }
41
-
42
- #bitpay_payment_buttons {
43
- padding-top: 10px;
44
- text-align: center;
45
- }
46
-
47
- a.button.disabled {
48
- background-color: #727276;
49
- border-color: #59595c;
50
- color: #CCC;
51
- opacity: .65;
52
- pointer-events: none;
53
- }
54
-
55
- .bitpay_invoice_details {
56
- padding-top: 20px;
57
- padding-bottom: 20px;
58
- }
@@ -1,243 +0,0 @@
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
-
16
- payment = order.get_bitpay_payment
17
-
18
- logger.debug "Found payment: #{payment.inspect}"
19
-
20
- case payment.state
21
- when "checkout"
22
- # New checkout - create an invoice, and attach its id to the payment.source
23
- invoice = new_invoice(order, payment)
24
- payment.source.invoice_id = invoice['id']
25
- payment.source.save!
26
- payment.started_processing!
27
- else
28
- # An invoice was already created - find it
29
- invoice = payment.source.find_invoice
30
- end
31
-
32
- @invoice_iframe_url = "#{invoice['url']}&view=iframe"
33
- render json: @invoice_iframe_url
34
- end
35
-
36
- # View Invoice with specific ID
37
- #
38
- def view_invoice
39
- invoice = BitpayInvoice.find(params[:source_id]).find_invoice
40
- redirect_to (invoice["url"] + '&view=iframe')
41
- end
42
-
43
- def check_payment_state
44
- invoice = BitpayInvoice.where(invoice_id: params[:invoice_id]).first
45
- pm = PaymentMethod.find(invoice.payment_method_id)
46
- status = pm.scan_the_server(invoice.invoice_id)
47
- render json: status
48
- end
49
-
50
- def cancel
51
-
52
- order = current_order || raise(ActiveRecord::RecordNotFound)
53
-
54
- # Find and invalidate Bitpay payment in processing state
55
- order.payments.with_state("processing").each do |payment|
56
- if (payment.payment_method.is_a? Spree::PaymentMethod::Bitpay)
57
- payment.state = "invalid" # Have to set this explicitly since Spree state machine prevents it
58
- payment.save!
59
- end
60
- end
61
-
62
- redirect_to edit_order_url(order, state: 'payment'), :notice => Spree.t(:checkout_cancelled)
63
-
64
- end
65
-
66
- # Fires on receipt of payment received window message
67
- #
68
- def payment_sent
69
-
70
- order = Spree::Order.find(session[:order_id]) || raise(ActiveRecord::RecordNotFound)
71
-
72
- session[:order_id] = nil # Reset cart
73
- redirect_to spree.order_path(order), :notice => Spree.t(:order_processed_successfully)
74
-
75
- end
76
-
77
- ## Handle IPN from Bitpay server
78
- # Receives incoming IPN message and retrieves official BitPay invoice for processing
79
- #
80
- def notification
81
-
82
- posData = JSON.parse(params["posData"])
83
-
84
- order_id = posData["orderID"]
85
- payment_id = posData["paymentID"]
86
-
87
- # Get OFFICIAL Invoice from BitPay API
88
- # Fetching payment this way should prevent any false payment/order mismatch
89
- order = Spree::Order.find_by_number(order_id) || raise(ActiveRecord::RecordNotFound)
90
- payment = order.payments.find_by(identifier: payment_id) || raise(ActiveRecord::RecordNotFound)
91
- invoice = payment.source.find_invoice
92
-
93
- if invoice
94
- logger.debug("Bitpay Invoice Content: " + invoice.to_json)
95
- process_invoice(invoice)
96
- head :ok
97
- else
98
- raise "Spree_Bitpay: No invoice found for notification for #{payment.identifier} from #{request.remote_ip}"
99
- end
100
-
101
- rescue
102
- logger.error "Spree_Bitpay: Unprocessable notification received from #{request.remote_ip}: #{params.inspect}"
103
- head :unprocessable_entity
104
- end
105
-
106
- # Reprocess Invoice and update order status
107
- #
108
- def refresh
109
- payment = Spree::Payment.find(params[:payment]) # Retrieve payment by ID
110
- old_state = payment.state
111
- invoice = payment.source.find_invoice # Get associated invoice
112
- process_invoice(invoice) # Re-process invoice
113
- new_state = payment.reload.state
114
- notice = (new_state == old_state) ? Spree.t(:bitpay_payment_not_updated) : (Spree.t(:bitpay_payment_updated) + new_state.titlecase)
115
- redirect_to (request.referrer || root_path), notice: notice
116
- end
117
-
118
- #######################################################################
119
- ### Private Methods
120
- #######################################################################
121
-
122
- private
123
-
124
- # Call Bitpay API and return new JSON invoice object
125
- #
126
- def new_invoice(order, payment)
127
-
128
- # Have to encode this into a string for proper handling by API
129
- posDataJson = {paymentID: payment.identifier, orderID: order.number}.to_json
130
-
131
- invoice_params = {
132
- price: order.outstanding_balance,
133
- currency: order.currency,
134
- orderID: order.number,
135
- notificationURL: bitpay_notification_url,
136
- posData: posDataJson,
137
- fullNotifications: "true"
138
- }
139
-
140
- logger.debug "Requesting Invoice with params: #{invoice_params}"
141
- invoice = payment.payment_method.get_bitpay_client.post 'invoice', invoice_params
142
- logger.debug "Invoice Generated: #{invoice.inspect}"
143
-
144
- return invoice
145
- end
146
-
147
- # Process the invoice and adjust order state accordingly
148
- # Accepts BitPay JSON invoice object
149
- #
150
- def process_invoice(invoice)
151
- logger.debug "Processing Bitpay invoice"
152
-
153
- # Extract posData
154
- posData = JSON.parse(invoice["posData"])
155
-
156
- payment_id = posData["paymentID"]
157
- status = invoice["status"]
158
- exception_status = invoice["exceptionStatus"]
159
-
160
- payment = Spree::Payment.find_by(identifier: payment_id) || raise(ActiveRecord::RecordNotFound)
161
-
162
- logger.debug "Found Payment: #{payment.inspect}"
163
-
164
- # Advance Payment state according to Spree flow
165
- # http://guides.spreecommerce.com/user/payment_states.html
166
-
167
- case status
168
- when "new"
169
-
170
- payment.started_processing
171
-
172
- when "paid"
173
-
174
- # Move payment to pending state and complete order
175
-
176
- if payment.state = "processing" # This is the most common scenario
177
- payment.pend!
178
- else # In the case it was previously marked invalid due to invoice expiry
179
- payment.state = "pending"
180
- payment.save
181
- end
182
-
183
- payment.order.update!
184
- payment.order.next
185
- if (!payment.order.complete?)
186
- raise "Can't transition order #{payment.order.number} to COMPLETE state"
187
- end
188
-
189
- when "confirmed", "complete"
190
-
191
- # Move payment to 'complete' state
192
-
193
- case payment.state
194
- when "pending" # This is the most common scenario
195
- payment.complete
196
- when "completed"
197
- # Do nothing
198
- else
199
- # Something unusual happened - maybe a notification was missed, or
200
- # Make sure the order is completed
201
- if !payment.order.complete?
202
- payment.state = "pending"
203
- payment.save
204
- payment.order.next
205
- if (!payment.order.complete?)
206
- raise "Can't transition order #{payment.order.number} to COMPLETE state"
207
- end
208
- end
209
- payment.state = "completed" # Can't use Spree payment.complete! method since we are transitioning from weird states
210
- payment.save
211
- end
212
-
213
- when "expired"
214
-
215
- if (exception_status == false) # This is an abandoned invoice
216
- payment.state = "invalid" # Have to set this explicitly since Spree state machine prevents it
217
- payment.save!
218
- else
219
- # Don't think this will be anything other than paidPartial exceptionStatus
220
- unless payment.state == 'void'
221
- payment.void!
222
- end
223
- end
224
-
225
- when "invalid"
226
-
227
- unless payment.state == 'failed'
228
- payment.failure! # Will be flagged risky automatically
229
- end
230
-
231
- else
232
-
233
- raise "Unexpected status received from BitPay: '#{invoice["status"]}' for '#{invoice["url"]}"
234
-
235
- end
236
-
237
- logger.debug "New Payment State for #{payment.identifier}: #{payment.state}"
238
- logger.debug "New Order State for #{payment.order.number}: #{payment.order.state}"
239
-
240
- end
241
-
242
- end
243
- end
@@ -1,17 +0,0 @@
1
- Spree::Order.class_eval do
2
- self.state_machine.before_transition :to => :confirm, :do => :validate_bitpay_payment
3
-
4
- def validate_bitpay_payment
5
- states = payments.map(&:state)
6
- payments.each do |payment|
7
- payment.failure if payment.state == 'processing'
8
- end if (states.include?('checkout') && states.include?('processing'))
9
- end
10
-
11
- def get_bitpay_payment
12
- checkout = payments.select{|payment| payment.state == 'checkout'}
13
- processing = payments.select{|payment| payment.state == 'processing'}
14
- return checkout.last if checkout.any?
15
- return processing.last if processing.any?
16
- end
17
- end
@@ -1,23 +0,0 @@
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
@@ -1,64 +0,0 @@
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
@@ -1,55 +0,0 @@
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
-