spree_coinbase 2.2.0.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.
@@ -0,0 +1,15 @@
1
+ ---
2
+ !binary "U0hBMQ==":
3
+ metadata.gz: !binary |-
4
+ NmI2ZWJiNDU1MDhhZWVhOTFmY2E2NWUyNjhlYTk5NDY0ZTc3MjM3MQ==
5
+ data.tar.gz: !binary |-
6
+ YzgzOTEyNWE2MjNlOTdlOTExZTYyZmY0YTQyNmM0YzMzM2FhMzFhMg==
7
+ SHA512:
8
+ metadata.gz: !binary |-
9
+ ZmNlZmQ2MDgxM2ZmZjg5ZThhMTExYmQ3Nzc5NjJmNWJiZmI2Nzc4YzAxZDJl
10
+ ZjY3ZDVjNTM3NWU5NjUxNWE1YmQ2ZjZmNDMyYTRiNjhmNjUxMDYyNzRkMDAw
11
+ N2M4NWI0ZmRiN2JkMzNlNmQwZDQxNjZjZmEyOTVkYmM1ZTM3ZDM=
12
+ data.tar.gz: !binary |-
13
+ MDJmZTYzZTYwODY4Mjg3YTJhNGMxMzI5YjQwNTg5MDJjMWIxNzhjMmUyNTM5
14
+ ZTVhMmYwMzA0ZTQ2OGNjOGEwMjA1Y2VlYTVlYzViYmQ2OTU2ZWY3ZjE5NDYz
15
+ NGJmMDk5MzhkMTk3ZTYwMDQzMDhmNmZlNTBkZDMyNTc2ZGM3NWY=
@@ -0,0 +1,14 @@
1
+ \#*
2
+ *~
3
+ .#*
4
+ .DS_Store
5
+ .idea
6
+ .project
7
+ .sass-cache
8
+ coverage
9
+ Gemfile.lock
10
+ tmp
11
+ nbproject
12
+ pkg
13
+ *.swp
14
+ spec/dummy
data/.rspec ADDED
@@ -0,0 +1 @@
1
+ --color
data/Gemfile ADDED
@@ -0,0 +1,6 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Provides basic authentication functionality for testing parts of your engine
4
+ gem 'spree_auth_devise', github: 'spree/spree_auth_devise', branch: '2-2-stable'
5
+
6
+ gemspec
data/LICENSE ADDED
@@ -0,0 +1,26 @@
1
+ Copyright (c) 2014 [name of plugin creator]
2
+ All rights reserved.
3
+
4
+ Redistribution and use in source and binary forms, with or without modification,
5
+ are permitted provided that the following conditions are met:
6
+
7
+ * Redistributions of source code must retain the above copyright notice,
8
+ this list of conditions and the following disclaimer.
9
+ * Redistributions in binary form must reproduce the above copyright notice,
10
+ this list of conditions and the following disclaimer in the documentation
11
+ and/or other materials provided with the distribution.
12
+ * Neither the name Spree nor the names of its contributors may be used to
13
+ endorse or promote products derived from this software without specific
14
+ prior written permission.
15
+
16
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17
+ "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18
+ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19
+ A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
20
+ CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
21
+ EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
22
+ PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
23
+ PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
24
+ LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
25
+ NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
26
+ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
@@ -0,0 +1,42 @@
1
+ Spree Coinbase Plugin
2
+ =============
3
+
4
+ Accept bitcoin payments on your Spree store with the official Coinbase Spree plugin. For more information on Coinbase for merchants, visit https://coinbase.com/merchants.
5
+
6
+ Installation
7
+ ------------
8
+
9
+ If you don't have a Coinbase account, sign up at https://coinbase.com/merchants. Coinbase offers daily payouts for merchants in the United States. For more infomation on setting up payouts, see https://coinbase.com/docs/merchant_tools/payouts.
10
+
11
+ Add spree_coinbase to your Gemfile:
12
+
13
+ ```ruby
14
+ gem 'spree_coinbase'
15
+ ```
16
+
17
+ Bundle your dependencies and run the installation generator:
18
+
19
+ ```shell
20
+ bundle
21
+ bundle exec rails g spree_coinbase:install
22
+ ```
23
+
24
+ After installing the gem, go to your Spree admin console and navigate to Configuration > Payment Methods > New Payment Method.
25
+
26
+ ![Configuration](http://i.imgur.com/iGs9l6H.png)
27
+
28
+ Select "Spree::PaymentMethod::Coinbase" from the "Provider" dropdown, enter a name (like "Bitcoin") for the payment method, and click "Create."
29
+
30
+ ![New Payment Method](http://i.imgur.com/5bdGElv.png)
31
+
32
+ Go to https://coinbase.com/settings/api and click '+ New API Key' to generate an API key and secret for this plugin. You should create a 'HMAC' key with the permission 'merchant' only.
33
+
34
+ After generating the API key, click on the shortened representation of it (looks like 'kcyPDdpjgYk...') to view the full API Key + Secret. Copy and paste the API key and API secret into the respective fields on the Edit Payment Method page, then click "Update".
35
+
36
+ Remember to enable the API key on the https://coinbase.com/settings/api page by clicking the "Enable" link. If the API key is not enabled, the plugin will not work.
37
+
38
+ ![Edit Payment Method](http://i.imgur.com/UJImHrA.png)
39
+
40
+ The plugin should now be active!
41
+
42
+ Copyright (c) 2014 Coinbase, released under the New BSD License
@@ -0,0 +1,15 @@
1
+ require 'bundler'
2
+ Bundler::GemHelper.install_tasks
3
+
4
+ require 'rspec/core/rake_task'
5
+ require 'spree/testing_support/extension_rake'
6
+
7
+ RSpec::Core::RakeTask.new
8
+
9
+ task :default => [:spec]
10
+
11
+ desc 'Generates a dummy app for testing'
12
+ task :test_app do
13
+ ENV['LIB_NAME'] = 'spree_coinbase'
14
+ Rake::Task['extension:test_app'].invoke
15
+ end
@@ -0,0 +1,2 @@
1
+ // Placeholder manifest file.
2
+ // the installer will append this file to the app vendored assets here: vendor/assets/javascripts/spree/backend/all.js'
@@ -0,0 +1,39 @@
1
+ SpreeCoinbase = {
2
+ doOnSiteCheckout: function() {
3
+
4
+ $('#checkout_form_payment input.continue').hide();
5
+ $('div[data-hook="checkout_payment_step"]').html("<iframe src=\"" + SpreeCoinbase.checkoutUrl + "\" style=\"width: 500px; height: 160px; border: none; overflow: hidden;\" scrolling=\"no\" allowtransparency=\"true\" frameborder=\"0\"></iframe>" +
6
+ "<p><a href=\"" + SpreeCoinbase.cancelUrl + "\">Cancel and choose another payment method</a></p>");
7
+ }
8
+ }
9
+
10
+ $(document).ready(function() {
11
+ $('#checkout_form_payment input.continue').click(function (e) {
12
+ checkedPaymentMethod = $('div[data-hook="checkout_payment_step"] input[type="radio"]:checked');
13
+
14
+ if (checkedPaymentMethod.val() == SpreeCoinbase.paymentMethodId && !SpreeCoinbase.useOffSite) {
15
+ // On-site checkout!
16
+ SpreeCoinbase.doOnSiteCheckout();
17
+ return false;
18
+ } else {
19
+ return true;
20
+ }
21
+ });
22
+ })
23
+
24
+ window.addEventListener('message', receiveMessage, false);
25
+
26
+ // Listen for messages from the on-site payment iframe
27
+ function receiveMessage(event) {
28
+
29
+ if (event.origin == 'https://coinbase.com') {
30
+ var event_type = event.data.split('|')[0];
31
+ if (event_type == 'coinbase_payment_complete') {
32
+
33
+ // Redirect to success url (wait 1 second for callback to arrive)
34
+ setTimeout(function() {
35
+ window.location = SpreeCoinbase.successUrl;
36
+ }, 1000);
37
+ }
38
+ }
39
+ }
@@ -0,0 +1,4 @@
1
+ /*
2
+ Placeholder manifest file.
3
+ the installer will append this file to the app vendored assets here: 'vendor/assets/stylesheets/spree/backend/all.css'
4
+ */
@@ -0,0 +1,4 @@
1
+ /*
2
+ Placeholder manifest file.
3
+ the installer will append this file to the app vendored assets here: 'vendor/assets/stylesheets/spree/frontend/all.css'
4
+ */
@@ -0,0 +1,44 @@
1
+ -----BEGIN CERTIFICATE-----
2
+ MIIDtzCCAp+gAwIBAgIQDOfg5RfYRv6P5WD8G/AwOTANBgkqhkiG9w0BAQUFADBl
3
+ MQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3
4
+ d3cuZGlnaWNlcnQuY29tMSQwIgYDVQQDExtEaWdpQ2VydCBBc3N1cmVkIElEIFJv
5
+ b3QgQ0EwHhcNMDYxMTEwMDAwMDAwWhcNMzExMTEwMDAwMDAwWjBlMQswCQYDVQQG
6
+ EwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3d3cuZGlnaWNl
7
+ cnQuY29tMSQwIgYDVQQDExtEaWdpQ2VydCBBc3N1cmVkIElEIFJvb3QgQ0EwggEi
8
+ MA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCtDhXO5EOAXLGH87dg+XESpa7c
9
+ JpSIqvTO9SA5KFhgDPiA2qkVlTJhPLWxKISKityfCgyDF3qPkKyK53lTXDGEKvYP
10
+ mDI2dsze3Tyoou9q+yHyUmHfnyDXH+Kx2f4YZNISW1/5WBg1vEfNoTb5a3/UsDg+
11
+ wRvDjDPZ2C8Y/igPs6eD1sNuRMBhNZYW/lmci3Zt1/GiSw0r/wty2p5g0I6QNcZ4
12
+ VYcgoc/lbQrISXwxmDNsIumH0DJaoroTghHtORedmTpyoeb6pNnVFzF1roV9Iq4/
13
+ AUaG9ih5yLHa5FcXxH4cDrC0kqZWs72yl+2qp/C3xag/lRbQ/6GW6whfGHdPAgMB
14
+ AAGjYzBhMA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQW
15
+ BBRF66Kv9JLLgjEtUYunpyGd823IDzAfBgNVHSMEGDAWgBRF66Kv9JLLgjEtUYun
16
+ pyGd823IDzANBgkqhkiG9w0BAQUFAAOCAQEAog683+Lt8ONyc3pklL/3cmbYMuRC
17
+ dWKuh+vy1dneVrOfzM4UKLkNl2BcEkxY5NM9g0lFWJc1aRqoR+pWxnmrEthngYTf
18
+ fwk8lOa4JiwgvT2zKIn3X/8i4peEH+ll74fg38FnSbNd67IJKusm7Xi+fT8r87cm
19
+ NW1fiQG2SVufAQWbqz0lwcy2f8Lxb4bG+mRo64EtlOtCt/qMHt1i8b5QZ7dsvfPx
20
+ H2sMNgcWfzd8qVttevESRmCD1ycEvkvOl77DZypoEd+A5wwzZr8TDRRu838fYxAe
21
+ +o0bJW1sj6W3YQGx0qMmoRBxna3iw/nDmVG3KwcIzi7mULKn+gpFL6Lw8g==
22
+ -----END CERTIFICATE-----
23
+ -----BEGIN CERTIFICATE-----
24
+ MIIDrzCCApegAwIBAgIQCDvgVpBCRrGhdWrJWZHHSjANBgkqhkiG9w0BAQUFADBh
25
+ MQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3
26
+ d3cuZGlnaWNlcnQuY29tMSAwHgYDVQQDExdEaWdpQ2VydCBHbG9iYWwgUm9vdCBD
27
+ QTAeFw0wNjExMTAwMDAwMDBaFw0zMTExMTAwMDAwMDBaMGExCzAJBgNVBAYTAlVT
28
+ MRUwEwYDVQQKEwxEaWdpQ2VydCBJbmMxGTAXBgNVBAsTEHd3dy5kaWdpY2VydC5j
29
+ b20xIDAeBgNVBAMTF0RpZ2lDZXJ0IEdsb2JhbCBSb290IENBMIIBIjANBgkqhkiG
30
+ 9w0BAQEFAAOCAQ8AMIIBCgKCAQEA4jvhEXLeqKTTo1eqUKKPC3eQyaKl7hLOllsB
31
+ CSDMAZOnTjC3U/dDxGkAV53ijSLdhwZAAIEJzs4bg7/fzTtxRuLWZscFs3YnFo97
32
+ nh6Vfe63SKMI2tavegw5BmV/Sl0fvBf4q77uKNd0f3p4mVmFaG5cIzJLv07A6Fpt
33
+ 43C/dxC//AH2hdmoRBBYMql1GNXRor5H4idq9Joz+EkIYIvUX7Q6hL+hqkpMfT7P
34
+ T19sdl6gSzeRntwi5m3OFBqOasv+zbMUZBfHWymeMr/y7vrTC0LUq7dBMtoM1O/4
35
+ gdW7jVg/tRvoSSiicNoxBN33shbyTApOB6jtSj1etX+jkMOvJwIDAQABo2MwYTAO
36
+ BgNVHQ8BAf8EBAMCAYYwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUA95QNVbR
37
+ TLtm8KPiGxvDl7I90VUwHwYDVR0jBBgwFoAUA95QNVbRTLtm8KPiGxvDl7I90VUw
38
+ DQYJKoZIhvcNAQEFBQADggEBAMucN6pIExIK+t1EnE9SsPTfrgT1eXkIoyQY/Esr
39
+ hMAtudXH/vTBH1jLuG2cenTnmCmrEbXjcKChzUyImZOMkXDiqw8cvpOp/2PV5Adg
40
+ 06O/nVsJ8dWO41P0jmP6P6fbtGbfYmbW0W5BjfIttep3Sp+dWOIrWcBAI+0tKIJF
41
+ PnlUkiaY4IBIqDfv8NZ5YBberOgOzW6sRBc4L0na4UU+Krk2U886UAb3LujEV0ls
42
+ YSEY1QSteDwsOoBrp+uvFRTp2InBuThs4pFsiv9kuXclVzDAGySj4dzp30d8tbQk
43
+ CAUw7C29C79Fv1C5qfPrmAESrciIxpg0X40KPMbp1ZWVbd4=
44
+ -----END CERTIFICATE-----
@@ -0,0 +1,15 @@
1
+ module Spree
2
+ CheckoutController.class_eval do
3
+ before_filter :coinbase_redirect, :only => [:update]
4
+
5
+ private
6
+ def coinbase_redirect
7
+ return unless (params[:state] == "payment") && params[:order][:payments_attributes]
8
+
9
+ payment_method = PaymentMethod.find(params[:order][:payments_attributes].first[:payment_method_id])
10
+ if payment_method.kind_of?(Spree::PaymentMethod::Coinbase)
11
+ redirect_to spree_coinbase_redirect_url(:payment_method_id => payment_method.id)
12
+ end
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,181 @@
1
+ require 'httparty'
2
+
3
+ module Spree
4
+ class CoinbaseController < StoreController
5
+ include HTTParty
6
+ ssl_ca_file File.expand_path(File.join(File.dirname(__FILE__), 'ca-coinbase.crt'))
7
+ skip_before_filter :verify_authenticity_token
8
+
9
+ def redirect
10
+ order = current_order || raise(ActiveRecord::RecordNotFound)
11
+
12
+ if order.state != "payment"
13
+ redirect_to root_url() # Order is not ready for payment / has already been paid
14
+ return
15
+ end
16
+
17
+ # Create Coinbase button code
18
+ secret_token = SecureRandom.base64(30)
19
+ button_params = { :button => {
20
+ :name => "Order #%s" % order.number,
21
+ :price_string => order.total,
22
+ :price_currency_iso => order.currency,
23
+ :custom => order.id,
24
+ :custom_secure => true,
25
+ :callback_url => spree_coinbase_callback_url(:payment_method_id => params[:payment_method_id], :secret_token => secret_token),
26
+ :cancel_url => spree_coinbase_cancel_url(:payment_method_id => params[:payment_method_id]),
27
+ :success_url => spree_coinbase_success_url(:payment_method_id => params[:payment_method_id], :order_num => order.number),
28
+ :info_url => root_url(),
29
+ } }
30
+ result = make_coinbase_request :post, "/buttons", button_params
31
+ code = result["button"]["code"]
32
+
33
+ if code
34
+ # Add a "processing" payment that is used to verify the callback
35
+ transaction = CoinbaseTransaction.new
36
+ transaction.button_id = code
37
+ transaction.secret_token = secret_token
38
+ payment = order.payments.create({:amount => order.total,
39
+ :source => transaction,
40
+ :payment_method => payment_method })
41
+ payment.started_processing!
42
+
43
+ use_off_site = payment_method.preferred_use_off_site_payment_page
44
+ redirect_to "https://coinbase.com/%1$s/%2$s" % [use_off_site ? "checkouts" : "inline_payments", code]
45
+ else
46
+ redirect_to edit_order_checkout_url(order, :state => 'payment'),
47
+ :notice => Spree.t(:spree_coinbase_checkout_error)
48
+ end
49
+ end
50
+
51
+ def callback
52
+
53
+ # Download order information from Coinbase (do not trust sent order information)
54
+ cb_order_id = params["order"]["id"]
55
+ cb_order = make_coinbase_request :get, "/orders/%s" % cb_order_id, {}
56
+
57
+ if cb_order.nil?
58
+ render text: "Invalid order ID", status: 400
59
+ return
60
+ end
61
+
62
+ cb_order = cb_order["order"]
63
+
64
+ if cb_order["status"] != "completed"
65
+ render text: "Invalid order status", status: 400
66
+ return
67
+ end
68
+
69
+ # Fetch Spree order information, find relevant payment, and verify button_id
70
+ order_id = cb_order["custom"]
71
+ order = Spree::Order.find(order_id)
72
+ button_id = cb_order["button"]["id"]
73
+ payments = order.payments.where(:state => "processing",
74
+ :payment_method_id => payment_method)
75
+ payment = nil
76
+ payments.each do |p|
77
+ if p.source.button_id == button_id
78
+ payment = p
79
+ end
80
+ end
81
+
82
+ if payment.nil?
83
+ render text: "No matching payment for order", status: 400
84
+ return
85
+ end
86
+
87
+ # Verify secret_token
88
+ if payment.source.secret_token != params[:secret_token]
89
+ render text: "Invalid secret token", status: 400
90
+ return
91
+ end
92
+
93
+ # Now that this callback has been verified, process the payment!
94
+ transaction = payment.source
95
+ transaction.order_id = cb_order_id
96
+ transaction.save
97
+
98
+ # Make payment pending -> make order complete -> make payment complete -> update order
99
+ payment.pend!
100
+ order.next
101
+ if !order.complete?
102
+ render text: "Could not transition order: %s" % order.errors
103
+ return
104
+ end
105
+ payment.complete!
106
+ order.update!
107
+
108
+ # Successful payment!
109
+ render text: "Callback successful"
110
+
111
+ end
112
+
113
+ def cancel
114
+
115
+ order = current_order || raise(ActiveRecord::RecordNotFound)
116
+
117
+ # Void the 'pending' payment created in redirect
118
+ # If doing an on-site checkout params will be nil, so just
119
+ # cancel all Coinbase payments (it is unlikely there will be more than one)
120
+ button_id = params["order"]["button"]["id"] rescue nil
121
+ payments = order.payments.where(:state => "pending",
122
+ :payment_method_id => payment_method)
123
+ payments.each do |payment|
124
+ if payment.source.button_id == button_id || button_id.nil?
125
+ payment.void!
126
+ end
127
+ end
128
+
129
+ redirect_to edit_order_checkout_url(order, :state => 'payment'),
130
+ :notice => Spree.t(:spree_coinbase_checkout_cancelled)
131
+ end
132
+
133
+ def success
134
+
135
+ order = Spree::Order.find_by_number(params[:order_num]) || raise(ActiveRecord::RecordNotFound)
136
+
137
+ if order.complete?
138
+ session[:order_id] = nil # Reset cart
139
+ redirect_to spree.order_path(order), :notice => Spree.t(:order_processed_successfully)
140
+ end
141
+
142
+ # If order not complete, wait for callback to come in... (page will automatically refresh, see view)
143
+ end
144
+
145
+ private
146
+
147
+ def payment_method
148
+ m = Spree::PaymentMethod.find(params[:payment_method_id])
149
+ if !(m.is_a? Spree::PaymentMethod::Coinbase)
150
+ raise "Invalid payment_method_id"
151
+ end
152
+ m
153
+ end
154
+
155
+ # the coinbase-ruby gem is not used because of its dependence on incompatible versions of the money gem
156
+ def make_coinbase_request verb, path, options
157
+
158
+ key = payment_method.preferred_api_key
159
+ secret = payment_method.preferred_api_secret
160
+
161
+ if key.nil? || secret.nil?
162
+ raise "Please enter an API key and secret in Spree payment method settings"
163
+ end
164
+
165
+ base_uri = "https://coinbase.com/api/v1"
166
+ nonce = (Time.now.to_f * 1e6).to_i
167
+ message = nonce.to_s + base_uri + path + options.to_json
168
+ signature = OpenSSL::HMAC.hexdigest(OpenSSL::Digest::Digest.new('sha256'), secret, message)
169
+
170
+ headers = {
171
+ 'ACCESS_KEY' => key,
172
+ 'ACCESS_SIGNATURE' => signature,
173
+ 'ACCESS_NONCE' => nonce.to_s,
174
+ "Content-Type" => "application/json",
175
+ }
176
+
177
+ r = self.class.send(verb, base_uri + path, {headers: headers, body: options.to_json})
178
+ JSON.parse(r.body)
179
+ end
180
+ end
181
+ end
@@ -0,0 +1,10 @@
1
+ module Spree
2
+ class CoinbaseTransaction < ActiveRecord::Base
3
+ has_many :payments, :as => :source
4
+
5
+ def actions
6
+ []
7
+ end
8
+
9
+ end
10
+ end
@@ -0,0 +1,23 @@
1
+ module Spree
2
+ class PaymentMethod::Coinbase < PaymentMethod
3
+ preference :api_key, :string
4
+ preference :api_secret, :string
5
+ preference :use_off_site_payment_page, :boolean
6
+
7
+ def auto_capture?
8
+ false
9
+ end
10
+
11
+ def provider_class
12
+ nil
13
+ end
14
+
15
+ def payment_source_class
16
+ nil
17
+ end
18
+
19
+ def source_required?
20
+ false
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,5 @@
1
+ <p>
2
+ Coinbase order ID: <%= @payment.source.order_id %><br>
3
+ Coinbase button ID: <%= @payment.source.button_id %><br>
4
+ Secret token: <%= @payment.source.secret_token %>
5
+ </p>
@@ -0,0 +1,8 @@
1
+ Pay with bitcoin, a digital currency. Payment instructions will be displayed after you click 'Save and Continue'.
2
+ <script type="text/javascript">
3
+ SpreeCoinbase.paymentMethodId = <%= payment_method.id %>;
4
+ SpreeCoinbase.useOffSite = <%= payment_method.preferred_use_off_site_payment_page == true %>;
5
+ SpreeCoinbase.checkoutUrl = "<%= j spree_coinbase_redirect_url(:payment_method_id => payment_method.id).html_safe %>";
6
+ SpreeCoinbase.cancelUrl = "<%= j spree_coinbase_cancel_url(:payment_method_id => payment_method.id).html_safe %>";
7
+ SpreeCoinbase.successUrl = "<%= j spree_coinbase_success_url(:payment_method_id => payment_method.id, :order_num => current_order.number).html_safe %>";
8
+ </script>
@@ -0,0 +1,2 @@
1
+ <meta http-equiv="refresh" content="3">
2
+ <p>Processing your payment...</p>
@@ -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_coinbase/engine', __FILE__)
5
+
6
+ require 'rails/all'
7
+ require 'rails/engine/commands'
@@ -0,0 +1,4 @@
1
+ en:
2
+ spree:
3
+ spree_coinbase_checkout_error: "There was an error while checking out. Please use a different payment method."
4
+ spree_coinbase_checkout_cancelled: "Payment cancelled."
@@ -0,0 +1,6 @@
1
+ Spree::Core::Engine.routes.draw do
2
+ get '/spree_coinbase/redirect', :to => "coinbase#redirect", :as => :spree_coinbase_redirect
3
+ post '/spree_coinbase/callback', :to => "coinbase#callback", :as => :spree_coinbase_callback
4
+ get '/spree_coinbase/cancel', :to => "coinbase#cancel", :as => :spree_coinbase_cancel
5
+ get '/spree_coinbase/success', :to => "coinbase#success", :as => :spree_coinbase_success
6
+ end
@@ -0,0 +1,9 @@
1
+ class CreateSpreeCoinbaseTransactions < ActiveRecord::Migration
2
+ def change
3
+ create_table :spree_coinbase_transactions do |t|
4
+ t.string :button_id
5
+ t.string :order_id
6
+ t.string :secret_token
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,31 @@
1
+ module SpreeCoinbase
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_coinbase\n"
9
+ append_file 'vendor/assets/javascripts/spree/backend/all.js', "//= require spree/backend/spree_coinbase\n"
10
+ end
11
+
12
+ def add_stylesheets
13
+ inject_into_file 'vendor/assets/stylesheets/spree/frontend/all.css', " *= require spree/frontend/spree_coinbase\n", :before => /\*\//, :verbose => true
14
+ inject_into_file 'vendor/assets/stylesheets/spree/backend/all.css', " *= require spree/backend/spree_coinbase\n", :before => /\*\//, :verbose => true
15
+ end
16
+
17
+ def add_migrations
18
+ run 'bundle exec rake railties:install:migrations FROM=spree_coinbase'
19
+ end
20
+
21
+ def run_migrations
22
+ run_migrations = options[:auto_run_migrations] || ['', 'y', 'Y'].include?(ask 'Would you like to run the migrations now? [Y/n]')
23
+ if run_migrations
24
+ run 'bundle exec rake db:migrate'
25
+ else
26
+ puts 'Skipping rake db:migrate, don\'t forget to run it!'
27
+ end
28
+ end
29
+ end
30
+ end
31
+ end
@@ -0,0 +1,2 @@
1
+ require 'spree_core'
2
+ require 'spree_coinbase/engine'
@@ -0,0 +1,15 @@
1
+ module SpreeCoinbase
2
+ class Engine < Rails::Engine
3
+ engine_name 'spree_coinbase'
4
+
5
+ config.to_prepare do
6
+ Dir.glob(File.join(File.dirname(__FILE__), "../../app/**/*_decorator*.rb")) do |c|
7
+ Rails.configuration.cache_classes ? require(c) : load(c)
8
+ end
9
+ end
10
+
11
+ initializer "spree.spree_coinbase.payment_methods", :after => "spree.register.payment_methods" do |app|
12
+ app.config.spree.payment_methods << Spree::PaymentMethod::Coinbase
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,31 @@
1
+ # encoding: UTF-8
2
+ Gem::Specification.new do |s|
3
+ s.platform = Gem::Platform::RUBY
4
+ s.name = 'spree_coinbase'
5
+ s.version = '2.2.0.1'
6
+ s.summary = 'Accept bitcoin payments on Spree with Coinbase.'
7
+ s.description = 'Accept bitcoin payments on your Spree store with Coinbase.'
8
+ s.required_ruby_version = '>= 1.9.3'
9
+
10
+ s.author = 'Coinbase'
11
+ s.email = 'merchants@coinbase.com'
12
+ s.homepage = 'https://coinbase.com'
13
+
14
+ s.files = `git ls-files`.split("\n")
15
+ #s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
16
+ s.require_path = 'lib'
17
+ s.requirements << 'none'
18
+
19
+ s.add_dependency 'spree_core', '~> 2.2.0'
20
+
21
+ s.add_development_dependency 'capybara', '~> 2.1'
22
+ s.add_development_dependency 'coffee-rails'
23
+ s.add_development_dependency 'database_cleaner'
24
+ s.add_development_dependency 'factory_girl', '~> 4.2'
25
+ s.add_development_dependency 'ffaker'
26
+ s.add_development_dependency 'rspec-rails', '~> 2.13'
27
+ s.add_development_dependency 'sass-rails'
28
+ s.add_development_dependency 'selenium-webdriver'
29
+ s.add_development_dependency 'simplecov'
30
+ s.add_development_dependency 'sqlite3'
31
+ end
metadata ADDED
@@ -0,0 +1,223 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: spree_coinbase
3
+ version: !ruby/object:Gem::Version
4
+ version: 2.2.0.1
5
+ platform: ruby
6
+ authors:
7
+ - Coinbase
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2014-04-02 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: spree_core
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ~>
18
+ - !ruby/object:Gem::Version
19
+ version: 2.2.0
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ~>
25
+ - !ruby/object:Gem::Version
26
+ version: 2.2.0
27
+ - !ruby/object:Gem::Dependency
28
+ name: capybara
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ~>
32
+ - !ruby/object:Gem::Version
33
+ version: '2.1'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ~>
39
+ - !ruby/object:Gem::Version
40
+ version: '2.1'
41
+ - !ruby/object:Gem::Dependency
42
+ name: coffee-rails
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ! '>='
46
+ - !ruby/object:Gem::Version
47
+ version: '0'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ! '>='
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
55
+ - !ruby/object:Gem::Dependency
56
+ name: database_cleaner
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - ! '>='
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - ! '>='
67
+ - !ruby/object:Gem::Version
68
+ version: '0'
69
+ - !ruby/object:Gem::Dependency
70
+ name: factory_girl
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - ~>
74
+ - !ruby/object:Gem::Version
75
+ version: '4.2'
76
+ type: :development
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - ~>
81
+ - !ruby/object:Gem::Version
82
+ version: '4.2'
83
+ - !ruby/object:Gem::Dependency
84
+ name: ffaker
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - ! '>='
88
+ - !ruby/object:Gem::Version
89
+ version: '0'
90
+ type: :development
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - ! '>='
95
+ - !ruby/object:Gem::Version
96
+ version: '0'
97
+ - !ruby/object:Gem::Dependency
98
+ name: rspec-rails
99
+ requirement: !ruby/object:Gem::Requirement
100
+ requirements:
101
+ - - ~>
102
+ - !ruby/object:Gem::Version
103
+ version: '2.13'
104
+ type: :development
105
+ prerelease: false
106
+ version_requirements: !ruby/object:Gem::Requirement
107
+ requirements:
108
+ - - ~>
109
+ - !ruby/object:Gem::Version
110
+ version: '2.13'
111
+ - !ruby/object:Gem::Dependency
112
+ name: sass-rails
113
+ requirement: !ruby/object:Gem::Requirement
114
+ requirements:
115
+ - - ! '>='
116
+ - !ruby/object:Gem::Version
117
+ version: '0'
118
+ type: :development
119
+ prerelease: false
120
+ version_requirements: !ruby/object:Gem::Requirement
121
+ requirements:
122
+ - - ! '>='
123
+ - !ruby/object:Gem::Version
124
+ version: '0'
125
+ - !ruby/object:Gem::Dependency
126
+ name: selenium-webdriver
127
+ requirement: !ruby/object:Gem::Requirement
128
+ requirements:
129
+ - - ! '>='
130
+ - !ruby/object:Gem::Version
131
+ version: '0'
132
+ type: :development
133
+ prerelease: false
134
+ version_requirements: !ruby/object:Gem::Requirement
135
+ requirements:
136
+ - - ! '>='
137
+ - !ruby/object:Gem::Version
138
+ version: '0'
139
+ - !ruby/object:Gem::Dependency
140
+ name: simplecov
141
+ requirement: !ruby/object:Gem::Requirement
142
+ requirements:
143
+ - - ! '>='
144
+ - !ruby/object:Gem::Version
145
+ version: '0'
146
+ type: :development
147
+ prerelease: false
148
+ version_requirements: !ruby/object:Gem::Requirement
149
+ requirements:
150
+ - - ! '>='
151
+ - !ruby/object:Gem::Version
152
+ version: '0'
153
+ - !ruby/object:Gem::Dependency
154
+ name: sqlite3
155
+ requirement: !ruby/object:Gem::Requirement
156
+ requirements:
157
+ - - ! '>='
158
+ - !ruby/object:Gem::Version
159
+ version: '0'
160
+ type: :development
161
+ prerelease: false
162
+ version_requirements: !ruby/object:Gem::Requirement
163
+ requirements:
164
+ - - ! '>='
165
+ - !ruby/object:Gem::Version
166
+ version: '0'
167
+ description: Accept bitcoin payments on your Spree store with Coinbase.
168
+ email: merchants@coinbase.com
169
+ executables: []
170
+ extensions: []
171
+ extra_rdoc_files: []
172
+ files:
173
+ - .gitignore
174
+ - .rspec
175
+ - Gemfile
176
+ - LICENSE
177
+ - README.md
178
+ - Rakefile
179
+ - app/assets/javascripts/spree/backend/spree_coinbase.js
180
+ - app/assets/javascripts/spree/frontend/spree_coinbase.js
181
+ - app/assets/stylesheets/spree/backend/spree_coinbase.css
182
+ - app/assets/stylesheets/spree/frontend/spree_coinbase.css
183
+ - app/controllers/spree/ca-coinbase.crt
184
+ - app/controllers/spree/checkout_controller_decorator.rb
185
+ - app/controllers/spree/coinbase_controller.rb
186
+ - app/models/spree/coinbase_transaction.rb
187
+ - app/models/spree/payment_method/coinbase.rb
188
+ - app/views/spree/admin/payments/source_views/_coinbase.html.erb
189
+ - app/views/spree/checkout/payment/_coinbase.html.erb
190
+ - app/views/spree/coinbase/success.html.erb
191
+ - bin/rails
192
+ - config/locales/en.yml
193
+ - config/routes.rb
194
+ - db/migrate/20140330235546_create_spree_coinbase_transactions.rb
195
+ - lib/generators/spree_coinbase/install/install_generator.rb
196
+ - lib/spree_coinbase.rb
197
+ - lib/spree_coinbase/engine.rb
198
+ - spree_coinbase.gemspec
199
+ homepage: https://coinbase.com
200
+ licenses: []
201
+ metadata: {}
202
+ post_install_message:
203
+ rdoc_options: []
204
+ require_paths:
205
+ - lib
206
+ required_ruby_version: !ruby/object:Gem::Requirement
207
+ requirements:
208
+ - - ! '>='
209
+ - !ruby/object:Gem::Version
210
+ version: 1.9.3
211
+ required_rubygems_version: !ruby/object:Gem::Requirement
212
+ requirements:
213
+ - - ! '>='
214
+ - !ruby/object:Gem::Version
215
+ version: '0'
216
+ requirements:
217
+ - none
218
+ rubyforge_project:
219
+ rubygems_version: 2.2.2
220
+ signing_key:
221
+ specification_version: 4
222
+ summary: Accept bitcoin payments on Spree with Coinbase.
223
+ test_files: []