solidus_braintree 0.2.1 → 1.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.
- checksums.yaml +4 -4
- data/.travis.yml +18 -2
- data/CHANGELOG.md +2 -0
- data/Gemfile +6 -1
- data/README.md +7 -0
- data/app/controllers/spree/api/braintree_client_token_controller.rb +2 -0
- data/app/helpers/braintree_view_helpers.rb +20 -0
- data/app/models/concerns/solidus_braintree/add_name_validation_concern.rb +8 -0
- data/app/models/concerns/solidus_braintree/inject_device_data_concern.rb +18 -0
- data/app/models/concerns/solidus_braintree/payment_braintree_nonce_concern.rb +8 -0
- data/app/models/concerns/solidus_braintree/permitted_attributes_concern.rb +11 -0
- data/app/models/concerns/solidus_braintree/skip_require_card_numbers_concern.rb +14 -0
- data/app/models/concerns/solidus_braintree/use_data_field_concern.rb +23 -0
- data/app/models/payment_decorator.rb +1 -0
- data/app/models/solidus/gateway/braintree_gateway.rb +46 -5
- data/app/overrides/spree/checkout/_confirm/braintree_security.html.erb.deface +9 -0
- data/app/views/spree/admin/payments/source_forms/_braintree.html.erb +38 -0
- data/app/views/spree/admin/payments/source_views/_braintree.html.erb +30 -0
- data/app/views/spree/checkout/payment/_braintree.html.erb +55 -0
- data/app/views/spree/checkout/payment/_braintree_initialization.html.erb +12 -0
- data/config/initializers/braintree.rb +1 -0
- data/config/locales/en.yml +4 -0
- data/db/migrate/20150910170527_add_data_to_credit_card.rb +1 -1
- data/db/migrate/20160426221931_add_braintree_device_data_to_order.rb +5 -0
- data/lib/assets/javascripts/spree/backend/braintree/solidus_braintree.js +15 -12
- data/lib/assets/javascripts/spree/frontend/braintree/solidus_braintree.js +144 -0
- data/lib/assets/javascripts/vendor/braintree.js +8 -0
- data/lib/assets/stylesheets/spree/frontend/solidus_braintree.scss +26 -0
- data/lib/generators/solidus_braintree/install/install_generator.rb +9 -0
- data/lib/solidus_braintree/version.rb +1 -1
- data/solidus_braintree.gemspec +9 -6
- metadata +78 -22
- data/Guardfile +0 -70
- data/app/models/concerns/add_name_validation_concern.rb +0 -6
- data/app/models/concerns/payment_braintree_nonce_concern.rb +0 -6
- data/app/models/concerns/permitted_attributes_concern.rb +0 -5
- data/app/models/concerns/skip_require_card_numbers_concern.rb +0 -12
- data/app/models/concerns/use_data_field_concern.rb +0 -21
- data/app/overrides/admin_payment_add_braintree_dropin.rb +0 -10
- data/app/overrides/admin_payment_remove_credit_card_fields.rb +0 -5
- data/lib/assets/javascripts/vendor/braintree-2.14.0.js +0 -7
- data/out.json +0 -0
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 28f5f6d8e3a10296a22d9b5d9bf9f96f7146b5bb
|
4
|
+
data.tar.gz: f4718eedf1bcc717672fc6b97ff5cf9542f48566
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 54b07c41d17e102b686ff466b4361b07bc6b0b051c53953ee229ea163e05b0dc19f8841e9f866c5ac9bc169b8098f816ae7e3e39fd0d6dff12fc773343c7e4fc
|
7
|
+
data.tar.gz: 7875589e8a6034511cbeed423e44f83cd9adb66de4bea5f94fe5b5d45bbd7ced33c7f58f1f4dce6a339e36979a11afd8224f6582f4c0d55adf8768ec0a119ffa
|
data/.travis.yml
CHANGED
@@ -1,4 +1,20 @@
|
|
1
|
+
sudo: false
|
2
|
+
cache: bundler
|
1
3
|
language: ruby
|
4
|
+
addons:
|
5
|
+
postgresql: "9.3"
|
6
|
+
env:
|
7
|
+
matrix:
|
8
|
+
- SOLIDUS_BRANCH=v1.1 DB=postgres
|
9
|
+
- SOLIDUS_BRANCH=v1.2 DB=postgres
|
10
|
+
- SOLIDUS_BRANCH=v1.3 DB=postgres
|
11
|
+
- SOLIDUS_BRANCH=master DB=postgres
|
12
|
+
- SOLIDUS_BRANCH=v1.1 DB=mysql
|
13
|
+
- SOLIDUS_BRANCH=v1.2 DB=mysql
|
14
|
+
- SOLIDUS_BRANCH=v1.3 DB=mysql
|
15
|
+
- SOLIDUS_BRANCH=master DB=mysql
|
16
|
+
script:
|
17
|
+
- bundle exec rake test_app
|
18
|
+
- bundle exec rspec
|
2
19
|
rvm:
|
3
|
-
- 2.1.
|
4
|
-
before_install: gem install bundler -v 1.10.5
|
20
|
+
- 2.1.8
|
data/CHANGELOG.md
CHANGED
data/Gemfile
CHANGED
@@ -1,5 +1,10 @@
|
|
1
1
|
source 'https://rubygems.org'
|
2
2
|
|
3
3
|
# Specify your gem's dependencies in solidus_braintree.gemspec
|
4
|
-
|
4
|
+
branch = ENV.fetch('SOLIDUS_BRANCH', 'master')
|
5
|
+
gem "solidus", github: "solidusio/solidus", branch: branch
|
6
|
+
|
7
|
+
gem 'pg'
|
8
|
+
gem 'mysql2'
|
9
|
+
|
5
10
|
gemspec
|
data/README.md
CHANGED
@@ -19,6 +19,13 @@ And then execute:
|
|
19
19
|
$ bundle
|
20
20
|
$ bundle exec rails g solidus_braintree:install
|
21
21
|
|
22
|
+
|
23
|
+
## Fraud detection
|
24
|
+
|
25
|
+
This gem has support for the advanced fraud tools flow from Braintree, to activate
|
26
|
+
fully the associated Braintree account must enable advanced fraud tools in the
|
27
|
+
Control Panel.
|
28
|
+
|
22
29
|
## Usage
|
23
30
|
|
24
31
|
This gem extends your solidus application by adding a `POST /api/payment_client_token` endpoint to you application to generate Braintree payment client token. This endpoint requires an authentication token in your request header.
|
@@ -0,0 +1,20 @@
|
|
1
|
+
module BraintreeViewHelpers
|
2
|
+
# Returns a link to the Braintree web UI for the given Braintree +payment_id+
|
3
|
+
# (e.g. from Spree::Payment#response_code), or just the +payment_id+ if
|
4
|
+
# Braintree's merchant ID is not configured or +payment_id+ is blank
|
5
|
+
def braintree_transaction_link(payment_id)
|
6
|
+
env = ENV['BRAINTREE_ENV'] == 'production' ? 'www' : 'sandbox'
|
7
|
+
merchant = ENV['BRAINTREE_MERCHANT_ID']
|
8
|
+
|
9
|
+
if payment_id.present? && merchant.present?
|
10
|
+
link_to(
|
11
|
+
payment_id,
|
12
|
+
"https://#{env}.braintreegateway.com/merchants/#{merchant}/transactions/#{payment_id}",
|
13
|
+
title: 'Show payment on Braintree',
|
14
|
+
target: '_blank'
|
15
|
+
)
|
16
|
+
else
|
17
|
+
payment_id
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
module SolidusBraintree
|
2
|
+
module InjectDeviceDataConcern
|
3
|
+
extend ActiveSupport::Concern
|
4
|
+
included do
|
5
|
+
prepend(InstanceMethods)
|
6
|
+
end
|
7
|
+
|
8
|
+
module InstanceMethods
|
9
|
+
def gateway_options
|
10
|
+
options = super
|
11
|
+
|
12
|
+
options[:device_data] = order.braintree_device_data if order.braintree_device_data
|
13
|
+
|
14
|
+
options
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
@@ -0,0 +1,14 @@
|
|
1
|
+
module SolidusBraintree
|
2
|
+
module SkipRequireCardNumbersConcern
|
3
|
+
extend ActiveSupport::Concern
|
4
|
+
included do
|
5
|
+
prepend(InstanceMethods)
|
6
|
+
end
|
7
|
+
|
8
|
+
module InstanceMethods
|
9
|
+
def require_card_numbers?
|
10
|
+
super && !self.payment_method.kind_of?(Solidus::Gateway::BraintreeGateway)
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
module SolidusBraintree
|
2
|
+
module UseDataFieldConcern
|
3
|
+
extend ActiveSupport::Concern
|
4
|
+
included do
|
5
|
+
prepend(InstanceMethods)
|
6
|
+
end
|
7
|
+
|
8
|
+
module InstanceMethods
|
9
|
+
|
10
|
+
def email
|
11
|
+
data["email"]
|
12
|
+
end
|
13
|
+
|
14
|
+
def display_number
|
15
|
+
cc_type == 'paypal' ? email : super
|
16
|
+
end
|
17
|
+
|
18
|
+
def data
|
19
|
+
super.is_a?(String) ? JSON.parse(super) : super
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
@@ -21,6 +21,10 @@ module Solidus
|
|
21
21
|
'Visa' => 'visa',
|
22
22
|
}
|
23
23
|
|
24
|
+
def method_type
|
25
|
+
'braintree'
|
26
|
+
end
|
27
|
+
|
24
28
|
def gateway_options
|
25
29
|
{
|
26
30
|
environment: preferred_environment.to_sym,
|
@@ -49,12 +53,13 @@ module Solidus
|
|
49
53
|
return if source.gateway_customer_profile_id.present? || payment.payment_method_nonce.nil?
|
50
54
|
|
51
55
|
user = payment.order.user
|
56
|
+
email = user ? user.email : payment.order.email
|
52
57
|
address = (payment.source.address || payment.order.bill_address).try(:active_merchant_hash)
|
53
58
|
|
54
59
|
params = {
|
55
60
|
first_name: source.first_name,
|
56
61
|
last_name: source.last_name,
|
57
|
-
email:
|
62
|
+
email: email,
|
58
63
|
credit_card: {
|
59
64
|
cardholder_name: source.name,
|
60
65
|
billing_address: map_address(address),
|
@@ -63,6 +68,7 @@ module Solidus
|
|
63
68
|
verify_card: true,
|
64
69
|
},
|
65
70
|
},
|
71
|
+
device_data: payment.order.braintree_device_data
|
66
72
|
}
|
67
73
|
|
68
74
|
result = braintree_gateway.customer.create(params)
|
@@ -119,9 +125,19 @@ module Solidus
|
|
119
125
|
end
|
120
126
|
|
121
127
|
def void(authorization_code, source = {}, options = {})
|
122
|
-
|
123
|
-
|
124
|
-
|
128
|
+
# Allows voiding payments that are in a checkout state
|
129
|
+
if authorization_code.nil?
|
130
|
+
# Fake response since we don't need to void anything with Braintree
|
131
|
+
ActiveMerchant::Billing::Response.new(
|
132
|
+
true,
|
133
|
+
"OK",
|
134
|
+
{},
|
135
|
+
{}
|
136
|
+
)
|
137
|
+
else
|
138
|
+
result = braintree_gateway.transaction.void(authorization_code)
|
139
|
+
handle_result(result)
|
140
|
+
end
|
125
141
|
end
|
126
142
|
|
127
143
|
def credit(cents, source, authorization_code, options = {})
|
@@ -137,6 +153,18 @@ module Solidus
|
|
137
153
|
].include?(transaction.status)
|
138
154
|
end
|
139
155
|
|
156
|
+
def card_number_placeholder
|
157
|
+
'4141 4141 4141 4141'
|
158
|
+
end
|
159
|
+
|
160
|
+
def expiration_date_placeholder
|
161
|
+
'01/2020'
|
162
|
+
end
|
163
|
+
|
164
|
+
def card_code_placeholder
|
165
|
+
'123'
|
166
|
+
end
|
167
|
+
|
140
168
|
private
|
141
169
|
def message_from_result(result)
|
142
170
|
if result.success?
|
@@ -150,12 +178,25 @@ module Solidus
|
|
150
178
|
end
|
151
179
|
end
|
152
180
|
|
181
|
+
def build_results_hash(result)
|
182
|
+
if result.success?
|
183
|
+
{
|
184
|
+
authorization: result.transaction.id,
|
185
|
+
avs_result: {
|
186
|
+
code: result.transaction.avs_street_address_response_code
|
187
|
+
}
|
188
|
+
}
|
189
|
+
else
|
190
|
+
{}
|
191
|
+
end
|
192
|
+
end
|
193
|
+
|
153
194
|
def handle_result(result)
|
154
195
|
ActiveMerchant::Billing::Response.new(
|
155
196
|
result.success?,
|
156
197
|
message_from_result(result),
|
157
198
|
{},
|
158
|
-
|
199
|
+
build_results_hash(result)
|
159
200
|
)
|
160
201
|
end
|
161
202
|
|
@@ -0,0 +1,9 @@
|
|
1
|
+
<!-- insert_before "erb[loud]:contains('place_order')" -->
|
2
|
+
|
3
|
+
<%
|
4
|
+
# Currently we assume we only have one braintree
|
5
|
+
# payment method. In practice this should be true and it simplifies the code.
|
6
|
+
braintree_payment = @order.unprocessed_payments.find {|p| p.payment_method.class == Solidus::Gateway::BraintreeGateway }
|
7
|
+
if braintree_payment %>
|
8
|
+
<%= render 'spree/checkout/payment/braintree_initialization', payment_method: braintree_payment.payment_method %>
|
9
|
+
<% end %>
|
@@ -0,0 +1,38 @@
|
|
1
|
+
<fieldset data-id='credit-card' class="no-border-bottom">
|
2
|
+
<div class="field" data-hook="previous_cards">
|
3
|
+
<% if previous_cards.any? %>
|
4
|
+
<% previous_cards.each do |card| %>
|
5
|
+
<label><%= radio_button_tag :card, card.id, card == previous_cards.first %> <%= card.display_number %><br /></label>
|
6
|
+
<% end %>
|
7
|
+
<label><%= radio_button_tag :card, 'new', false, { id: "card_new#{payment_method.id}" } %> <%= Spree.t(:use_new_cc) %></label>
|
8
|
+
<% end %>
|
9
|
+
</div>
|
10
|
+
|
11
|
+
<div id="card_form<%= payment_method.id %>" data-hook>
|
12
|
+
<% param_prefix = "payment_source[#{payment_method.id}]" %>
|
13
|
+
|
14
|
+
<div class="clear"></div>
|
15
|
+
|
16
|
+
<div class="alpha four columns">
|
17
|
+
<div data-hook="card_name">
|
18
|
+
<div class="field">
|
19
|
+
<%= label_tag "card_name#{payment_method.id}", Spree::CreditCard.human_attribute_name(:name), class: 'required' %>
|
20
|
+
<%= text_field_tag "#{param_prefix}[name]", '', id: "card_name#{payment_method.id}", class: 'required fullwidth', maxlength: 19 %>
|
21
|
+
</div>
|
22
|
+
</div>
|
23
|
+
</div>
|
24
|
+
|
25
|
+
<div id="braintree-dropin"></div>
|
26
|
+
<input type="hidden" id="payment_method_nonce" name="payment[payment_method_nonce]">
|
27
|
+
|
28
|
+
<div class="clear"></div>
|
29
|
+
|
30
|
+
<%= label_tag "card_address#{payment_method.id}", Spree.t(:billing_address) %>
|
31
|
+
<% address = @order.bill_address || @order.ship_address || Spree::Address.build_default %>
|
32
|
+
<%= fields_for "#{param_prefix}[address_attributes]", address do |f| %>
|
33
|
+
<%= render :partial => 'spree/admin/shared/address_form', :locals => { :f => f, :type => "billing" } %>
|
34
|
+
<% end %>
|
35
|
+
|
36
|
+
<div class="clear"></div>
|
37
|
+
</div>
|
38
|
+
</fieldset>
|
@@ -0,0 +1,30 @@
|
|
1
|
+
<fieldset data-hook="credit_card">
|
2
|
+
<legend align="center"><%= Spree::CreditCard.model_name.human %></legend>
|
3
|
+
|
4
|
+
<div class="row">
|
5
|
+
<div class="alpha six columns">
|
6
|
+
<dl>
|
7
|
+
<dt><%= Spree.t(:identifier) %>:</dt>
|
8
|
+
<dd><%= payment.number %></dd>
|
9
|
+
|
10
|
+
<dt><%= Spree.t(:response_code) %>:</dt>
|
11
|
+
<dd><%= braintree_transaction_link(payment.response_code) %></dd>
|
12
|
+
|
13
|
+
<dt><%= Spree.t(:name_on_card) %>:</dt>
|
14
|
+
<dd><%= payment.source.name %></dd>
|
15
|
+
|
16
|
+
<dt><%= Spree::CreditCard.human_attribute_name(:cc_type) %>:</dt>
|
17
|
+
<dd><%= payment.source.cc_type %></dd>
|
18
|
+
|
19
|
+
<dt><%= Spree::CreditCard.human_attribute_name(:number) %>:</dt>
|
20
|
+
<dd><%= payment.source.display_number %></dd>
|
21
|
+
|
22
|
+
<dt><%= Spree::CreditCard.human_attribute_name(:expiration) %>:</dt>
|
23
|
+
<dd><%= payment.source.month %>/<%= payment.source.year %></dd>
|
24
|
+
</dl>
|
25
|
+
<% if payment.source.address %>
|
26
|
+
<%= render partial: 'spree/admin/shared/address', locals: {address: payment.source.address} %>
|
27
|
+
<% end %>
|
28
|
+
</div>
|
29
|
+
</div>
|
30
|
+
</fieldset>
|
@@ -0,0 +1,55 @@
|
|
1
|
+
<div class="braintree-payment">
|
2
|
+
<%= render 'spree/checkout/payment/braintree_initialization', payment_method: payment_method %>
|
3
|
+
|
4
|
+
<div class="braintree-paypal-input">
|
5
|
+
<div class="braintree-paypal-header">
|
6
|
+
<%= t('solidus_braintree.paypal_header_html') %>
|
7
|
+
</div>
|
8
|
+
<div id="#braintree_paypal_container"></div>
|
9
|
+
</div>
|
10
|
+
|
11
|
+
<div class="braintree-cc-input">
|
12
|
+
<div class="braintree-cc-header">
|
13
|
+
<%= t('solidus_braintree.creditcard_header_html') %>
|
14
|
+
<%= image_tag 'credit_cards/credit_card.gif', :id => 'credit-card-image' %>
|
15
|
+
</div>
|
16
|
+
<% param_prefix = "payment_source[#{payment_method.id}]" %>
|
17
|
+
|
18
|
+
<p class="field">
|
19
|
+
<%= label_tag "name_on_card_#{payment_method.id}", Spree.t(:name_on_card) %><span class="required">*</span><br />
|
20
|
+
<%= text_field_tag "#{param_prefix}[name]", "#{@order.billing_firstname} #{@order.billing_lastname}", { id: "name_on_card_#{payment_method.id}", :autocomplete => "cc-name" } %>
|
21
|
+
</p>
|
22
|
+
|
23
|
+
<p class="field" data-hook="card_number">
|
24
|
+
<%= label_tag "braintree_card_number", Spree.t(:card_number) %><span class="required">*</span><br />
|
25
|
+
<label for="braintree_card_number" id="braintree_card_number" class="braintree-hosted-field"></label>
|
26
|
+
|
27
|
+
<span id="card_type" style="display:none;">
|
28
|
+
( <span id="looks_like" ><%= Spree.t(:card_type_is) %> <span id="type"></span></span>
|
29
|
+
<span id="unrecognized"><%= Spree.t(:unrecognized_card_type) %></span>
|
30
|
+
)
|
31
|
+
</span>
|
32
|
+
</p>
|
33
|
+
|
34
|
+
<p class="field" data-hook="card_expiration">
|
35
|
+
<%= label_tag "braintree_card_expiry", Spree.t(:expiration) %><span class="required">*</span><br />
|
36
|
+
<label for="braintree_card_expiry" id="braintree_card_expiry" class="braintree-hosted-field"></label>
|
37
|
+
</p>
|
38
|
+
|
39
|
+
<p class="field" data-hook="card_code">
|
40
|
+
<%= label_tag "braintree_card_code", Spree.t(:card_code) %><span class="required">*</span><br />
|
41
|
+
|
42
|
+
<label for="braintree_card_code" id="braintree_card_code" class="braintree-hosted-field card-code"></label>
|
43
|
+
<%= link_to "(#{Spree.t(:what_is_this)})", spree.cvv_path, :target => '_blank', "data-hook" => "cvv_link", :id => "cvv_link" %>
|
44
|
+
</p>
|
45
|
+
</div>
|
46
|
+
|
47
|
+
<% if @order.bill_address %>
|
48
|
+
<%= fields_for "#{param_prefix}[address_attributes]", @order.bill_address do |f| %>
|
49
|
+
<%= render :partial => 'spree/address/form_hidden', :locals => { :form => f } %>
|
50
|
+
<% end %>
|
51
|
+
<% end %>
|
52
|
+
|
53
|
+
<%= hidden_field_tag "#{param_prefix}[cc_type]", '', :id => "cc_type", :class => 'ccType' %>
|
54
|
+
<%= hidden_field_tag "order[payments_attributes][][payment_method_nonce]", '', :id => "payment_method_nonce" %>
|
55
|
+
</div>
|
@@ -0,0 +1,12 @@
|
|
1
|
+
<% content_for :head do %>
|
2
|
+
<%= javascript_tag do %>
|
3
|
+
braintree.environment = "<%= payment_method.preferred_environment %>"
|
4
|
+
braintree.placeholders = {
|
5
|
+
"number": "<%= payment_method.card_number_placeholder %>",
|
6
|
+
"expirationDate": "<%= payment_method.expiration_date_placeholder %>",
|
7
|
+
"cvv": "<%= payment_method.card_code_placeholder %>"
|
8
|
+
}
|
9
|
+
<% end %>
|
10
|
+
<% end %>
|
11
|
+
|
12
|
+
<%= hidden_field_tag "order[braintree_device_data]", '', :id => "device_data" %>
|