spree_coinbase 2.2.0.1

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