spree_bitpay 1.0.2 → 2.0.0

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