nimbleshop_stripe 0.0.9
Sign up to get free protection for your applications and to get access to all the features.
- data/README.md +35 -0
- data/app/assets/images/nimbleshop_stripe/american_express.png +0 -0
- data/app/assets/images/nimbleshop_stripe/discover.png +0 -0
- data/app/assets/images/nimbleshop_stripe/mastercard.png +0 -0
- data/app/assets/images/nimbleshop_stripe/stripe.png +0 -0
- data/app/assets/images/nimbleshop_stripe/visa.png +0 -0
- data/app/controllers/nimbleshop_stripe/payments_controller.rb +38 -0
- data/app/controllers/nimbleshop_stripe/stripes_controller.rb +50 -0
- data/app/helpers/nimbleshop_stripe/exposed_helper.rb +26 -0
- data/app/models/nimbleshop_stripe/stripe.rb +31 -0
- data/app/views/nimbleshop_stripe/payments/_new.html.erb +118 -0
- data/app/views/nimbleshop_stripe/payments/_order_show_extra_info.html.erb +4 -0
- data/app/views/nimbleshop_stripe/payments/_payment_info_for_buyer.html.erb +6 -0
- data/app/views/nimbleshop_stripe/payments/_stripe_instructions.html.erb +47 -0
- data/app/views/nimbleshop_stripe/payments/_what_is_cvv.html.erb +25 -0
- data/app/views/nimbleshop_stripe/stripes/_edit.html.erb +31 -0
- data/app/views/nimbleshop_stripe/stripes/_form.html.erb +68 -0
- data/config/routes.rb +4 -0
- data/lib/nimbleshop_stripe/engine.rb +17 -0
- data/lib/nimbleshop_stripe/gateway.rb +9 -0
- data/lib/nimbleshop_stripe/processor.rb +134 -0
- data/lib/nimbleshop_stripe/util.rb +32 -0
- data/lib/nimbleshop_stripe.rb +8 -0
- data/lib/tasks/nimbleshop_stripe_tasks.rake +31 -0
- data/test/test_helper.rb +32 -0
- data/test/unit/payment_method_test.rb +21 -0
- data/test/unit/processor_test.rb +241 -0
- data/test/vcr_cassettes/authorize_net/authorize-failure.yml +38 -0
- data/test/vcr_cassettes/authorize_net/authorize-success.yml +38 -0
- data/test/vcr_cassettes/authorize_net/capture-failure.yml +38 -0
- data/test/vcr_cassettes/authorize_net/capture-success.yml +38 -0
- data/test/vcr_cassettes/authorize_net/purchase-failure.yml +38 -0
- data/test/vcr_cassettes/authorize_net/purchase-success.yml +38 -0
- data/test/vcr_cassettes/authorize_net/refund-failure.yml +38 -0
- data/test/vcr_cassettes/authorize_net/refund-success.yml +38 -0
- data/test/vcr_cassettes/authorize_net/void-authorize.yml +38 -0
- data/test/vcr_cassettes/authorize_net/void-failure.yml +38 -0
- data/test/vcr_cassettes/authorize_net/void-success.yml +38 -0
- metadata +120 -0
data/README.md
ADDED
@@ -0,0 +1,35 @@
|
|
1
|
+
# nimbleshop_authorizedotnet extension
|
2
|
+
|
3
|
+
This is stripe extension for [nimbleShop](http://www.nimbleShop.org) .
|
4
|
+
|
5
|
+
# Dependencies
|
6
|
+
|
7
|
+
This gem relies on a model called `PaymentMethod` and this model should
|
8
|
+
have a column called `metadata` of type `text`. Given below is an
|
9
|
+
example that would work
|
10
|
+
|
11
|
+
```
|
12
|
+
class CreatePaymentMethods < ActiveRecord::Migration
|
13
|
+
def change
|
14
|
+
create_table :payment_methods do |t|
|
15
|
+
t.string :name
|
16
|
+
t.text :description
|
17
|
+
t.string :type
|
18
|
+
t.string :permalink, null: false
|
19
|
+
t.text :metadata
|
20
|
+
|
21
|
+
t.timestamps
|
22
|
+
end
|
23
|
+
add_index :payment_methods, :permalink, unique: true
|
24
|
+
end
|
25
|
+
end
|
26
|
+
```
|
27
|
+
|
28
|
+
|
29
|
+
# Documentation
|
30
|
+
|
31
|
+
Documentation is available at [http://nimbleshop.org/authorizedotnet.html](http://nimbleshop.org/authorizedotnet.html) .
|
32
|
+
|
33
|
+
# License
|
34
|
+
|
35
|
+
This gem uses [MIT license](http://www.opensource.org/licenses/mit-license.php) .
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
@@ -0,0 +1,38 @@
|
|
1
|
+
module NimbleshopStripe
|
2
|
+
|
3
|
+
class PaymentsController < ::ActionController::Base
|
4
|
+
|
5
|
+
def create
|
6
|
+
order = Order.find_by_id!(session[:order_id])
|
7
|
+
token = params[:stripeToken]
|
8
|
+
|
9
|
+
address_attrs = order.final_billing_address.to_credit_card_attributes
|
10
|
+
creditcard_attrs = params[:creditcard].merge(address_attrs)
|
11
|
+
creditcard = Creditcard.new(creditcard_attrs)
|
12
|
+
creditcard.perform_validations = false
|
13
|
+
|
14
|
+
payment_method = NimbleshopStripe::Stripe.first
|
15
|
+
processor = NimbleshopStripe::Processor.new({order: order, payment_method: payment_method})
|
16
|
+
|
17
|
+
default_action = Shop.current.default_creditcard_action
|
18
|
+
|
19
|
+
if processor.send(default_action, token: token)
|
20
|
+
url = nimbleshop_simply.order_path(order)
|
21
|
+
@output = "window.location='#{url}'"
|
22
|
+
else
|
23
|
+
error = processor.errors.first
|
24
|
+
Rails.logger.info "Error: #{error}"
|
25
|
+
@output = "alert('#{error}')"
|
26
|
+
end
|
27
|
+
|
28
|
+
respond_to do |format|
|
29
|
+
format.js do
|
30
|
+
render js: @output
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
end
|
35
|
+
|
36
|
+
end
|
37
|
+
|
38
|
+
end
|
@@ -0,0 +1,50 @@
|
|
1
|
+
module NimbleshopStripe
|
2
|
+
|
3
|
+
# this line makes it possible to use this gem without nimbleshop_core
|
4
|
+
klass = defined?(::Admin::PaymentMethodsController) ? ::Admin::PaymentMethodsController : ActionController::Base
|
5
|
+
|
6
|
+
class StripesController < klass
|
7
|
+
|
8
|
+
before_filter :load_payment_method
|
9
|
+
|
10
|
+
def update
|
11
|
+
respond_to do |format|
|
12
|
+
if @payment_method.update_attributes(post_params[:stripe])
|
13
|
+
format.js {
|
14
|
+
flash[:notice] = 'Stripe record was successfully updated'
|
15
|
+
render js: "window.location = '/admin/payment_methods'"
|
16
|
+
}
|
17
|
+
else
|
18
|
+
msg = @payment_method.errors.full_messages.first
|
19
|
+
error = %Q[alert("#{msg}")]
|
20
|
+
format.js { render js: error }
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
def destroy
|
26
|
+
respond_to do |format|
|
27
|
+
if @payment_method.destroy
|
28
|
+
format.js {
|
29
|
+
flash[:notice] = 'Stripe record was successfully deleted'
|
30
|
+
render js: "window.location = '/admin/payment_methods'"
|
31
|
+
}
|
32
|
+
else
|
33
|
+
format.js { render js: 'Stripe record could not be deleted. Please try again later.' }
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
private
|
39
|
+
|
40
|
+
def post_params
|
41
|
+
params.permit(stripe: [:mode, :ssl, :publishable_key, :secret_key, :business_name])
|
42
|
+
end
|
43
|
+
|
44
|
+
def load_payment_method
|
45
|
+
@payment_method = NimbleshopStripe::Stripe.first
|
46
|
+
end
|
47
|
+
|
48
|
+
end
|
49
|
+
|
50
|
+
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
module NimbleshopStripe
|
2
|
+
module ExposedHelper
|
3
|
+
|
4
|
+
def nimbleshop_stripe_crud_form
|
5
|
+
return unless NimbleshopStripe::Stripe.first
|
6
|
+
render partial: '/nimbleshop_stripe/stripes/edit'
|
7
|
+
end
|
8
|
+
|
9
|
+
def nimbleshop_stripe_picture_on_admin_payment_methods
|
10
|
+
image_tag 'engines/nimbleshop_stripe/stripe.png', alt: 'stripe logo'
|
11
|
+
end
|
12
|
+
|
13
|
+
def nimbleshop_stripe_payment_form(order)
|
14
|
+
return unless NimbleshopStripe::Stripe.first
|
15
|
+
render partial: '/nimbleshop_stripe/payments/new', locals: { order: order }
|
16
|
+
end
|
17
|
+
|
18
|
+
def nimbleshop_stripe_icon_for_order_payment(order)
|
19
|
+
if payment_transaction = order.payment_transactions.last
|
20
|
+
cardtype = payment_transaction.metadata[:cardtype]
|
21
|
+
image_tag("engines/nimbleshop_stripe/#{cardtype}.png", height: '10px')
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
end
|
26
|
+
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
module NimbleshopStripe
|
2
|
+
class Stripe < PaymentMethod
|
3
|
+
|
4
|
+
store_accessor :metadata, :publishable_key, :secret_key, :business_name, :mode, :ssl
|
5
|
+
|
6
|
+
before_save :set_mode, :set_ssl
|
7
|
+
|
8
|
+
validates_presence_of :publishable_key, :business_name, :secret_key
|
9
|
+
|
10
|
+
def use_ssl?
|
11
|
+
self.ssl == 'enabled'
|
12
|
+
end
|
13
|
+
|
14
|
+
def kapture!(order)
|
15
|
+
processor = NimbleshopAuthorizedotnet::Processor.new(order)
|
16
|
+
processor.kapture
|
17
|
+
order.kapture!
|
18
|
+
end
|
19
|
+
|
20
|
+
private
|
21
|
+
|
22
|
+
def set_mode
|
23
|
+
self.mode ||= 'test'
|
24
|
+
end
|
25
|
+
|
26
|
+
def set_ssl
|
27
|
+
self.ssl ||= 'disabled'
|
28
|
+
end
|
29
|
+
|
30
|
+
end
|
31
|
+
end
|
@@ -0,0 +1,118 @@
|
|
1
|
+
<br />
|
2
|
+
|
3
|
+
<p>
|
4
|
+
<label class='radio'>
|
5
|
+
<%= radio_button_tag 'payment_choice', 'authorize-net', true %>
|
6
|
+
<label for='payment_choice'>
|
7
|
+
<%= image_tag('engines/nimbleshop_authorizedotnet/visa.png') %>
|
8
|
+
<%= image_tag('engines/nimbleshop_authorizedotnet/mastercard.png') %>
|
9
|
+
<%= image_tag('engines/nimbleshop_authorizedotnet/american_express.png') %>
|
10
|
+
<%= image_tag('engines/nimbleshop_authorizedotnet/discover.png') %>
|
11
|
+
</label>
|
12
|
+
</label>
|
13
|
+
</p>
|
14
|
+
|
15
|
+
<%= form_for @creditcard, url: nimbleshop_stripe.payment_path(format: :js), remote: true, html: { id: 'stripe-payment-form', class: 'form-horizontal' } do |f| %>
|
16
|
+
<div class='nimbleshop_stripe_umbrella'>
|
17
|
+
<% if @creditcard.errors.any? %>
|
18
|
+
<div class="alert alert-error">
|
19
|
+
<ul>
|
20
|
+
<% @creditcard.errors.full_messages.each do |msg| %>
|
21
|
+
<li><%= msg %></li>
|
22
|
+
<% end %>
|
23
|
+
</ul>
|
24
|
+
</div>
|
25
|
+
<% end %>
|
26
|
+
|
27
|
+
<fieldset>
|
28
|
+
<div class='control-group'>
|
29
|
+
<div class='controls'>
|
30
|
+
<input autocomplete="off" class="input-xlarge focus" id="creditcard_number" placeholder="Credit card number" size="30" type="text">
|
31
|
+
<% unless (NimbleshopStripe::Stripe.first.mode == 'production') %>
|
32
|
+
|
33
|
+
<%= link_to 'Valid number', '#stripe-sandboxhelp', 'data-toggle' => "modal" %>
|
34
|
+
<% end %>
|
35
|
+
</div>
|
36
|
+
</div>
|
37
|
+
|
38
|
+
<div class='control-group'>
|
39
|
+
<div class='controls'>
|
40
|
+
<input autocomplete="off" id="creditcard_cvv" placeholder="CVV" size="30" type="text">
|
41
|
+
|
42
|
+
<%= link_to 'What is this?', '#cvvhelp', 'data-toggle' => "modal" %>
|
43
|
+
</div>
|
44
|
+
</div>
|
45
|
+
|
46
|
+
<div class='control-group'>
|
47
|
+
<p style='padding-left:160px;'>
|
48
|
+
Expiration date
|
49
|
+
</p>
|
50
|
+
<div class='controls'>
|
51
|
+
<%= f.date_select :expires_on, discard_day: true, start_year: Date.today.year,
|
52
|
+
end_year: (Date.today.year + 10),
|
53
|
+
add_month_numbers: true,
|
54
|
+
order: [:day, :month, :year] %>
|
55
|
+
</div>
|
56
|
+
</div>
|
57
|
+
</fieldset>
|
58
|
+
</div>
|
59
|
+
|
60
|
+
<div class="form-actions">
|
61
|
+
<%= f.submit 'Submit', class: 'btn btn-primary', 'data-behavior' => 'stripe-submit-button' %>
|
62
|
+
</div>
|
63
|
+
|
64
|
+
<%= render '/nimbleshop_stripe/payments/stripe_instructions' %>
|
65
|
+
<%= render '/nimbleshop_stripe/payments/what_is_cvv' %>
|
66
|
+
<% end %>
|
67
|
+
|
68
|
+
<style>
|
69
|
+
#creditcard_expires_on_2i{
|
70
|
+
width: 130px;
|
71
|
+
}
|
72
|
+
#creditcard_expires_on_1i {
|
73
|
+
width: 100px;
|
74
|
+
}
|
75
|
+
</style>
|
76
|
+
|
77
|
+
<script type="text/javascript" src="https://js.stripe.com/v1/"></script>
|
78
|
+
<script type="text/javascript"> Stripe.setPublishableKey('<%=NimbleshopStripe::Stripe.first.publishable_key%>'); </script>
|
79
|
+
<script>
|
80
|
+
$(document).ready(function(){
|
81
|
+
$('#stripe-payment-form').submit(function(event){
|
82
|
+
$('[data-behavior~=stripe-submit-button]').attr('value', 'processing ...').attr('disabled', 'disabled');
|
83
|
+
|
84
|
+
var $this = $(this);
|
85
|
+
|
86
|
+
function stripeResponseHandler(status, response) {
|
87
|
+
if (response.error) {
|
88
|
+
$('[data-behavior~=stripe-submit-button]').attr('value', 'Submit').removeAttr('disabled');
|
89
|
+
alert(response.error.message);
|
90
|
+
} else {
|
91
|
+
var $form = $("#stripe-payment-form");
|
92
|
+
// token contains id, last4, and card type
|
93
|
+
var token = response['id'];
|
94
|
+
// insert the token into the form so it gets submitted to the server
|
95
|
+
$form.append("<input type='hidden' name='stripeToken' value='" + token + "'/>");
|
96
|
+
|
97
|
+
$.ajax({
|
98
|
+
type: 'POST',
|
99
|
+
url: $this.attr('action'),
|
100
|
+
data: $this.serializeArray()
|
101
|
+
});
|
102
|
+
|
103
|
+
|
104
|
+
}
|
105
|
+
}
|
106
|
+
|
107
|
+
Stripe.createToken({
|
108
|
+
number: $('#creditcard_number').val(),
|
109
|
+
cvc: $('#creditcard_cvv').val(),
|
110
|
+
exp_month: $('#creditcard_expires_on_2i').val(),
|
111
|
+
exp_year: $('#creditcard_expires_on_1i').val()
|
112
|
+
}, stripeResponseHandler);
|
113
|
+
|
114
|
+
// prevent the form from submitting with the default action
|
115
|
+
return false;
|
116
|
+
});
|
117
|
+
});
|
118
|
+
</script>
|
@@ -0,0 +1,47 @@
|
|
1
|
+
<style>
|
2
|
+
#stripe-sandboxhelp li {
|
3
|
+
margin-top: 2px;
|
4
|
+
margin-bottom: 2px;
|
5
|
+
}
|
6
|
+
</style>
|
7
|
+
|
8
|
+
<% if !Rails.env.production? && NimbleshopStripe::Stripe.first %>
|
9
|
+
<div id='stripe-sandboxhelp' class='modal hide fade'>
|
10
|
+
|
11
|
+
<div class='modal-header'>
|
12
|
+
<%= link_to 'x', '#', class: 'close', 'data-dismiss' => 'modal' %>
|
13
|
+
<h3>Valid credit card numbers in Stripe Test mode</h3>
|
14
|
+
</div>
|
15
|
+
<div class="modal-body">
|
16
|
+
<p> The application is running Stripe in <strong>Test</strong> mode. You cannot make real payment. Here are the valid credit card numbers in test mode. </p>
|
17
|
+
|
18
|
+
<ul>
|
19
|
+
<li> Visa: 4242424242424242 </li>
|
20
|
+
<li> Visa: 4012888888881881 </li>
|
21
|
+
<li> Mastercard: 5555555555554444 </li>
|
22
|
+
<li> Mastercard: 5105105105105100 </li>
|
23
|
+
<li> American Express: 378282246310005 </li>
|
24
|
+
<li> American Express: 371449635398431 </li>
|
25
|
+
<li> Discover: 6011111111111117 </li>
|
26
|
+
<li> Discover: 6011000990139424 </li>
|
27
|
+
<li> JCB: 3530111333300000 </li>
|
28
|
+
<li> JCB: 3566002020360505 </li>
|
29
|
+
<li> Diners Club: 30569309025904 </li>
|
30
|
+
<li> Diners Club: 38520000023237 </li>
|
31
|
+
</ul>
|
32
|
+
<br />
|
33
|
+
<ul>
|
34
|
+
<li> Expiration date must be set to the present day or later. </li>
|
35
|
+
<li> Security code for American express must be any 4 digits. For all others use any 3 digits. </li>
|
36
|
+
</ul>
|
37
|
+
</div>
|
38
|
+
<div class="modal-footer">
|
39
|
+
<p>
|
40
|
+
<%= link_to 'More information', '' %> .
|
41
|
+
<small>
|
42
|
+
This message never appears when Stripe is running in live mode .
|
43
|
+
</small>
|
44
|
+
</p>
|
45
|
+
</div>
|
46
|
+
</div>
|
47
|
+
<% end %>
|
@@ -0,0 +1,25 @@
|
|
1
|
+
<div id='cvvhelp' class="modal hide fade" >
|
2
|
+
<div class='modal-header'>
|
3
|
+
<%= link_to 'x', '#', class: 'close', 'data-dismiss' => 'modal' %>
|
4
|
+
<h3>What is CVV ?</h3>
|
5
|
+
</div>
|
6
|
+
<div class="modal-body">
|
7
|
+
<p>
|
8
|
+
The <strong>CVV Number</strong>
|
9
|
+
stands for "<strong>C</strong>ard <strong>V</strong>erification <strong>V</strong>alue" .
|
10
|
+
It is a 3 digit number for VISA, MasterCard and Discover cards.
|
11
|
+
It is a 4 digit number for American Express credit cards.
|
12
|
+
</p>
|
13
|
+
|
14
|
+
<div class="modal_images">
|
15
|
+
<div class="modal_cvv_image">
|
16
|
+
<h4>For Visa, MasterCard and Discover credit cards</h4>
|
17
|
+
<%= image_tag 'https://www.paypalobjects.com/en_US/i/demo/cv_card.gif' %>
|
18
|
+
</div>
|
19
|
+
<div class="modal_cvv_image">
|
20
|
+
<h4>For American Express credit cards</h4>
|
21
|
+
<%= image_tag 'https://www.paypalobjects.com/en_US/i/demo/cv_amex_card.gif' %>
|
22
|
+
</div>
|
23
|
+
</div>
|
24
|
+
</div>
|
25
|
+
</div>
|
@@ -0,0 +1,31 @@
|
|
1
|
+
<div class='payment-method-engine-well'>
|
2
|
+
|
3
|
+
<div>
|
4
|
+
<h2>Stripe</h2>
|
5
|
+
<div class="edit_link">
|
6
|
+
<%= link_to 'Edit', '#', class: 'nimbleshop-payment-method-edit', id: 'nimbleshop-stripe-payment-method-edit' %>
|
7
|
+
<%= link_to nimbleshop_stripe.stripe_path, class: 'nimbleshop-payment-method-delete',
|
8
|
+
confirm: 'Do you really want to delete Stripe payment method', method: :delete, remote: true do %>
|
9
|
+
<i class='icon-remove icon-white'></i>
|
10
|
+
<% end %>
|
11
|
+
</div>
|
12
|
+
|
13
|
+
<%= nimbleshop_stripe_picture_on_admin_payment_methods %>
|
14
|
+
|
15
|
+
<div class='clear'></div>
|
16
|
+
</div>
|
17
|
+
|
18
|
+
<%= render partial: '/nimbleshop_stripe/stripes/form' %>
|
19
|
+
</div>
|
20
|
+
|
21
|
+
<script>
|
22
|
+
$(function(){
|
23
|
+
|
24
|
+
$('#nimbleshop-stripe-payment-method-edit').toggle(function(){
|
25
|
+
$('#nimbleshop-stripe-form-well').show();
|
26
|
+
}, function(){
|
27
|
+
$('#nimbleshop-stripe-form-well').hide();
|
28
|
+
});
|
29
|
+
|
30
|
+
})
|
31
|
+
</script>
|
@@ -0,0 +1,68 @@
|
|
1
|
+
<div class='well nimbleshop-payment-method-form-well' id='nimbleshop-stripe-form-well' style='display:none;'>
|
2
|
+
|
3
|
+
<%= form_for NimbleshopStripe::Stripe.first, url: '/nimbleshop_stripe/stripe',
|
4
|
+
remote: true,
|
5
|
+
html: { method: 'put',
|
6
|
+
id: 'nimbleshop-stripe-form',
|
7
|
+
class: 'nimbleshop-payment-method-form form-horizontal'} do |f| %>
|
8
|
+
|
9
|
+
<fieldset>
|
10
|
+
<div class='control-group'>
|
11
|
+
<%= f.label :publishable_key, nil, class: 'control-label' %>
|
12
|
+
<div class='controls'>
|
13
|
+
<%= f.text_field :publishable_key, class: 'span6' %>
|
14
|
+
</div>
|
15
|
+
</div>
|
16
|
+
|
17
|
+
<div class='control-group'>
|
18
|
+
<%= f.label :secret_key, nil, class: 'control-label' %>
|
19
|
+
<div class='controls'>
|
20
|
+
<%= f.text_field :secret_key, class: 'span6' %>
|
21
|
+
</div>
|
22
|
+
</div>
|
23
|
+
|
24
|
+
<div class='control-group'>
|
25
|
+
<%= f.label :business_name, nil, class: 'control-label' %>
|
26
|
+
<%= link_to '?', '#', 'data-content' => 'Please enter the name of the company as it would appear in the credit card statement. If are not sure what name would appear in the credit card statements then consult your merchant account provider.',
|
27
|
+
'data-original-title' => 'Business name' %>
|
28
|
+
<div class='controls'>
|
29
|
+
<%= f.text_field :business_name, class: 'span6' %>
|
30
|
+
</div>
|
31
|
+
</div>
|
32
|
+
|
33
|
+
<div class='control-group'>
|
34
|
+
<div class='controls'>
|
35
|
+
<label class='checkbox'>
|
36
|
+
<%= f.check_box :mode, {}, 'test', 'production' %> Enable test mode
|
37
|
+
<%= link_to '?', '#', class: 'help', 'data-content' => 'In the test mode real credit card numbers are not accepted.',
|
38
|
+
'data-original-title' => 'Test mode' %>
|
39
|
+
</label>
|
40
|
+
</div>
|
41
|
+
</div>
|
42
|
+
|
43
|
+
<div class='control-group'>
|
44
|
+
<div class='controls'>
|
45
|
+
<label class='checkbox'>
|
46
|
+
<%= f.check_box :ssl, {}, 'enabled', 'disabled' %> Enable SSL requirement
|
47
|
+
<%= link_to '?', '#', class: 'help', 'data-content' => 'Enabling SSL requirement will force the payment page to be on SSL.',
|
48
|
+
'data-original-title' => 'SSL requirement' %>
|
49
|
+
</label>
|
50
|
+
</div>
|
51
|
+
</div>
|
52
|
+
|
53
|
+
</fieldset>
|
54
|
+
|
55
|
+
<div class='form-actions'>
|
56
|
+
<%= f.submit('Submit', class: 'btn btn-primary') %>
|
57
|
+
|
58
|
+
<%= link_to t(:cancel), nimbleshop_stripe.stripe_path, class: 'cancel btn' %>
|
59
|
+
</div>
|
60
|
+
<% end %>
|
61
|
+
|
62
|
+
</div>
|
63
|
+
|
64
|
+
<style>
|
65
|
+
.control-group a.help {
|
66
|
+
float: none;
|
67
|
+
}
|
68
|
+
</style>
|
data/config/routes.rb
ADDED
@@ -0,0 +1,17 @@
|
|
1
|
+
module NimbleshopStripe
|
2
|
+
class Engine < ::Rails::Engine
|
3
|
+
|
4
|
+
isolate_namespace NimbleshopStripe
|
5
|
+
|
6
|
+
config.to_prepare do
|
7
|
+
::NimbleshopStripe::Stripe
|
8
|
+
end
|
9
|
+
|
10
|
+
initializer 'nimbleshop_stripe.action_controller' do |app|
|
11
|
+
ActiveSupport.on_load :action_controller do
|
12
|
+
helper NimbleshopStripe::ExposedHelper
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
end
|
17
|
+
end
|
@@ -0,0 +1,9 @@
|
|
1
|
+
module NimbleshopStripe
|
2
|
+
module Gateway
|
3
|
+
def self.instance(payment_method)
|
4
|
+
ActiveMerchant::Billing::Gateway.logger = Rails.logger if payment_method.mode.to_s == 'test'
|
5
|
+
|
6
|
+
ActiveMerchant::Billing::StripeGateway.new( login: payment_method.secret_key )
|
7
|
+
end
|
8
|
+
end
|
9
|
+
end
|
@@ -0,0 +1,134 @@
|
|
1
|
+
module NimbleshopStripe
|
2
|
+
class Processor < Processor::Base
|
3
|
+
|
4
|
+
attr_reader :order, :payment_method, :errors, :gateway
|
5
|
+
|
6
|
+
def initialize(options)
|
7
|
+
@errors = []
|
8
|
+
@order = options.fetch(:order)
|
9
|
+
@payment_method = options.fetch(:payment_method)
|
10
|
+
@gateway = ::NimbleshopStripe::Gateway.instance(payment_method)
|
11
|
+
::Stripe.api_key = payment_method.secret_key
|
12
|
+
end
|
13
|
+
|
14
|
+
private
|
15
|
+
|
16
|
+
def set_active_merchant_mode # :nodoc:
|
17
|
+
ActiveMerchant::Billing::Base.mode = payment_method.mode.to_sym
|
18
|
+
end
|
19
|
+
|
20
|
+
def do_authorize(options = {})
|
21
|
+
#Stripe does not support authorize operation
|
22
|
+
do_purchase(options)
|
23
|
+
end
|
24
|
+
|
25
|
+
# Creates purchase for the order amount.
|
26
|
+
#
|
27
|
+
# === Options
|
28
|
+
#
|
29
|
+
# * <tt>:token</tt> -- token to be charged. This is a required field.
|
30
|
+
#
|
31
|
+
# This method returns false if purchase fails. Error messages are in <tt>errors</tt> array.
|
32
|
+
# If purchase succeeds then <tt>order.purchase</tt> is invoked.
|
33
|
+
#
|
34
|
+
def do_purchase(options = {})
|
35
|
+
options.symbolize_keys!
|
36
|
+
options.assert_valid_keys(:token)
|
37
|
+
|
38
|
+
token = options[:token]
|
39
|
+
|
40
|
+
response = gateway.purchase(order.total_amount_in_cents, token)
|
41
|
+
token_response = ::Stripe::Token.retrieve(token)
|
42
|
+
|
43
|
+
record_transaction(response, 'purchased',
|
44
|
+
fingerprint: token_response.card.fingerprint,
|
45
|
+
livemode: token_response.livemode,
|
46
|
+
card_number: "XXXX-XXXX-XXXX-#{token_response.card.last4}",
|
47
|
+
cardtype: token_response.card.type.downcase,
|
48
|
+
transaction_gid: token_response.id)
|
49
|
+
|
50
|
+
if response.success?
|
51
|
+
order.update_attributes(payment_method: payment_method)
|
52
|
+
order.purchase!
|
53
|
+
else
|
54
|
+
Rails.logger.info response.params['error']['message']
|
55
|
+
@errors << 'Credit card was declined. Please try again!'
|
56
|
+
return false
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
# Voids the previously authorized transaction.
|
61
|
+
#
|
62
|
+
# === Options
|
63
|
+
#
|
64
|
+
# * <tt>:transaction_gid</tt> -- transaction_gid is the transaction id returned by the gateway. This is a required field.
|
65
|
+
#
|
66
|
+
# This method returns false if void fails. Error messages are in <tt>errors</tt> array.
|
67
|
+
# If void succeeds then <tt>order.void</tt> is invoked.
|
68
|
+
#
|
69
|
+
def do_void(options = {})
|
70
|
+
options.symbolize_keys!
|
71
|
+
options.assert_valid_keys(:transaction_gid)
|
72
|
+
transaction_gid = options[:transaction_gid]
|
73
|
+
|
74
|
+
response = gateway.void(transaction_gid, {})
|
75
|
+
record_transaction(response, 'voided')
|
76
|
+
|
77
|
+
if response.success?
|
78
|
+
order.void
|
79
|
+
else
|
80
|
+
@errors << "Void operation failed"
|
81
|
+
false
|
82
|
+
end
|
83
|
+
end
|
84
|
+
|
85
|
+
# Refunds the given transaction.
|
86
|
+
#
|
87
|
+
# === Options
|
88
|
+
#
|
89
|
+
# * <tt>:transaction_gid</tt> -- transaction_gid is the transaction id returned by the gateway. This is a required field.
|
90
|
+
#
|
91
|
+
# This method returns false if refund fails. Error messages are in <tt>errors</tt> array.
|
92
|
+
# If refund succeeds then <tt>order.refund</tt> is invoked.
|
93
|
+
#
|
94
|
+
def do_refund(options = {})
|
95
|
+
options.symbolize_keys!
|
96
|
+
options.assert_valid_keys(:transaction_gid, :card_number)
|
97
|
+
|
98
|
+
transaction_gid = options[:transaction_gid]
|
99
|
+
card_number = options[:card_number]
|
100
|
+
|
101
|
+
response = gateway.refund(order.total_amount_in_cents, transaction_gid, card_number: card_number)
|
102
|
+
record_transaction(response, 'refunded')
|
103
|
+
|
104
|
+
if response.success?
|
105
|
+
order.refund
|
106
|
+
else
|
107
|
+
@errors << "Refund failed"
|
108
|
+
false
|
109
|
+
end
|
110
|
+
|
111
|
+
end
|
112
|
+
|
113
|
+
def record_transaction(response, operation, additional_options = {}) # :nodoc:
|
114
|
+
transaction_gid = additional_options.fetch(:transaction_gid)
|
115
|
+
|
116
|
+
options = { operation: 'capture',
|
117
|
+
params: response.params,
|
118
|
+
success: true,
|
119
|
+
metadata: additional_options,
|
120
|
+
transaction_gid: transaction_gid }
|
121
|
+
|
122
|
+
if response.success?
|
123
|
+
options.update(amount: order.total_amount_in_cents)
|
124
|
+
end
|
125
|
+
|
126
|
+
order.payment_transactions.create(options)
|
127
|
+
end
|
128
|
+
|
129
|
+
def valid_card?(creditcard) # :nodoc:
|
130
|
+
true
|
131
|
+
end
|
132
|
+
|
133
|
+
end
|
134
|
+
end
|