solidus_conekta_card 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 +7 -0
- data/LICENSE +26 -0
- data/README.md +39 -0
- data/Rakefile +23 -0
- data/app/assets/javascripts/spree/backend/solidus_conekta_card.js +24 -0
- data/app/assets/javascripts/spree/conekta.js +1213 -0
- data/app/assets/javascripts/spree/frontend/solidus_conekta_card.js +24 -0
- data/app/assets/stylesheets/spree/backend/solidus_conekta_card.css +4 -0
- data/app/assets/stylesheets/spree/frontend/solidus_conekta_card.css +4 -0
- data/app/controllers/spree/admin/payments_controller_decorator.rb +39 -0
- data/app/controllers/spree/checkout_controller_decorator.rb +27 -0
- data/app/models/spree/gateway/conekta_card_gateway.rb +73 -0
- data/app/models/spree/payment_method/conekta_card.rb +29 -0
- data/app/views/spree/admin/payments/source_forms/_conekta_card.html.erb +56 -0
- data/app/views/spree/admin/payments/source_views/_conekta_card.html.erb +1 -0
- data/app/views/spree/api/source_views/_conekta_card.json.jbuilder +1 -0
- data/app/views/spree/checkout/payment/_conekta_card.html.erb +57 -0
- data/config/locales/en.yml +8 -0
- data/config/locales/es-MX.yml +6 -0
- data/config/routes.rb +5 -0
- data/db/migrate/20181204175053_create_conekta_card_payments.rb +9 -0
- data/lib/generators/solidus_conekta_card/install/install_generator.rb +34 -0
- data/lib/solidus_conekta_card/engine.rb +26 -0
- data/lib/solidus_conekta_card/factories.rb +8 -0
- data/lib/solidus_conekta_card/version.rb +5 -0
- data/lib/solidus_conekta_card.rb +6 -0
- metadata +312 -0
@@ -0,0 +1,24 @@
|
|
1
|
+
$(document).ready(function() {
|
2
|
+
|
3
|
+
var conektaSuccessResponseHandler = function(token) {
|
4
|
+
var $form = $("#checkout_form_payment");
|
5
|
+
//Add the token_id in the form
|
6
|
+
$form.append($('<input type="hidden" name="conektaTokenId" id="conektaTokenId">').val(token.id));
|
7
|
+
$form.get(0).submit(); //Submit
|
8
|
+
};
|
9
|
+
var conektaErrorResponseHandler = function(response) {
|
10
|
+
var $form = $("#checkout_form_payment");
|
11
|
+
$form.find(".card-errors").text(response.message_to_purchaser);
|
12
|
+
};
|
13
|
+
|
14
|
+
//jQuery generate the token on submit.
|
15
|
+
$(function () {
|
16
|
+
$("#checkout_form_payment").submit(function(event) {
|
17
|
+
var $form = $(this);
|
18
|
+
if ($(creditCardPaymentId).prop('checked')) {
|
19
|
+
Conekta.Token.create($form, conektaSuccessResponseHandler, conektaErrorResponseHandler);
|
20
|
+
return false;
|
21
|
+
}
|
22
|
+
});
|
23
|
+
});
|
24
|
+
});
|
@@ -0,0 +1,39 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module AdminPaymentsDecorator
|
4
|
+
extend ActiveSupport::Concern
|
5
|
+
|
6
|
+
included do
|
7
|
+
def create
|
8
|
+
@payment = Spree::PaymentCreate.new(@order, object_params).build
|
9
|
+
if @payment.payment_method.source_required? && params[:card].present? && params[:card] != 'new'
|
10
|
+
@payment.source = @payment.payment_method.payment_source_class.find_by(id: params[:card])
|
11
|
+
end
|
12
|
+
|
13
|
+
if @payment.save
|
14
|
+
if @order.completed?
|
15
|
+
# If the order was already complete then go ahead and process the payment
|
16
|
+
# (auth and/or capture depending on payment method configuration)
|
17
|
+
if params[:conektaTokenId]
|
18
|
+
@order.payments.last.source.update_attributes(gateway_payment_profile_id: params[:conektaTokenId])
|
19
|
+
end
|
20
|
+
@payment.process! if @payment.checkout?
|
21
|
+
else
|
22
|
+
# Transition order as far as it will go.
|
23
|
+
while @order.next; end
|
24
|
+
end
|
25
|
+
|
26
|
+
flash[:success] = flash_message_for(@payment, :successfully_created)
|
27
|
+
redirect_to admin_order_payments_path(@order)
|
28
|
+
else
|
29
|
+
flash[:error] = t('spree.payment_could_not_be_created')
|
30
|
+
render :new
|
31
|
+
end
|
32
|
+
rescue Spree::Core::GatewayError => e
|
33
|
+
flash[:error] = e.message.to_s
|
34
|
+
redirect_to new_admin_order_payment_path(@order)
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
Spree::Admin::PaymentsController.include(AdminPaymentsDecorator)
|
@@ -0,0 +1,27 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
Spree::CheckoutController.class_eval do
|
4
|
+
def update
|
5
|
+
if update_order
|
6
|
+
assign_temp_address
|
7
|
+
|
8
|
+
if params[:conektaTokenId]
|
9
|
+
@order.payments.last.source.update_attributes(gateway_payment_profile_id: params[:conektaTokenId])
|
10
|
+
end
|
11
|
+
|
12
|
+
unless transition_forward
|
13
|
+
redirect_on_failure
|
14
|
+
return
|
15
|
+
end
|
16
|
+
|
17
|
+
if @order.completed?
|
18
|
+
finalize_order
|
19
|
+
else
|
20
|
+
send_to_next_state
|
21
|
+
end
|
22
|
+
|
23
|
+
else
|
24
|
+
render :edit
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
@@ -0,0 +1,73 @@
|
|
1
|
+
require 'conekta'
|
2
|
+
|
3
|
+
module Spree
|
4
|
+
class Gateway::ConektaCardGateway < Spree::CreditCard
|
5
|
+
attr_accessor :server, :test_mode, :auth_token, :public_auth_token, :source_method
|
6
|
+
|
7
|
+
def purchase(money, source, gateway_options)
|
8
|
+
::Conekta.api_key = auth_token ? auth_token : ''
|
9
|
+
::Conekta.api_version = '2.0.0'
|
10
|
+
|
11
|
+
begin
|
12
|
+
order = Spree::Order.find(gateway_options[:originator].order_id)
|
13
|
+
|
14
|
+
unless order.conekta_order_id
|
15
|
+
conekta_order = ::Conekta::Order.create(payload(order, source))
|
16
|
+
end
|
17
|
+
|
18
|
+
conekta_order = ::Conekta::Order.find(order.conekta_order_id)
|
19
|
+
ActiveMerchant::Billing::Response.new(true, 'Orden creada satisfactoriamente', {}, parse_response(conekta_order))
|
20
|
+
rescue ::Conekta::Error => error
|
21
|
+
ActiveMerchant::Billing::Response.new(false, error.details.map(&:message).join(', '))
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
def name
|
26
|
+
'Conekta Card'
|
27
|
+
end
|
28
|
+
|
29
|
+
private
|
30
|
+
|
31
|
+
def payload(order, source)
|
32
|
+
{
|
33
|
+
currency: 'MXN',
|
34
|
+
customer_info: {
|
35
|
+
name: order.ship_address.full_name,
|
36
|
+
email: order.email,
|
37
|
+
phone: order.ship_address.phone
|
38
|
+
},
|
39
|
+
charges: [
|
40
|
+
{
|
41
|
+
payment_method: {
|
42
|
+
type: 'card',
|
43
|
+
token_id: source.gateway_payment_profile_id
|
44
|
+
}
|
45
|
+
}
|
46
|
+
],
|
47
|
+
line_items: order_line_items(order),
|
48
|
+
shipping_lines: shipping_lines(order),
|
49
|
+
shipping_contact: {
|
50
|
+
address: {
|
51
|
+
street1: order.ship_address.address1,
|
52
|
+
postal_code: order.ship_address.zipcode,
|
53
|
+
country: 'MX'
|
54
|
+
}
|
55
|
+
}
|
56
|
+
}
|
57
|
+
end
|
58
|
+
|
59
|
+
def order_line_items(order)
|
60
|
+
order.line_items.map { |li| {name: li.product.name, unit_price: (li.price * 100).to_i, quantity: li.quantity} }
|
61
|
+
end
|
62
|
+
|
63
|
+
def parse_response(response)
|
64
|
+
{
|
65
|
+
conekta_order_id: response.id
|
66
|
+
}
|
67
|
+
end
|
68
|
+
|
69
|
+
def shipping_lines(order)
|
70
|
+
order.shipments.map {|s| {id: s.id, carrier: s.shipping_method.name, amount: (s.cost * 100).to_i} }
|
71
|
+
end
|
72
|
+
end
|
73
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Spree
|
4
|
+
class PaymentMethod::ConektaCard < PaymentMethod::CreditCard
|
5
|
+
preference :auth_token, :string
|
6
|
+
preference :public_auth_token, :string
|
7
|
+
preference :source_method, :string, default: 'card'
|
8
|
+
|
9
|
+
def auto_capture
|
10
|
+
true
|
11
|
+
end
|
12
|
+
|
13
|
+
def partial_name
|
14
|
+
'conekta_card'
|
15
|
+
end
|
16
|
+
|
17
|
+
def gateway_class
|
18
|
+
Spree::Gateway::ConektaCardGateway
|
19
|
+
end
|
20
|
+
|
21
|
+
def payment_source_class
|
22
|
+
Spree::Gateway::ConektaCardGateway
|
23
|
+
end
|
24
|
+
|
25
|
+
def payment_profiles_supported?
|
26
|
+
false
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
@@ -0,0 +1,56 @@
|
|
1
|
+
<% param_prefix = "payment_source[#{payment_method.id}]" %>
|
2
|
+
<span class="card-errors"></span>
|
3
|
+
<div>
|
4
|
+
<label>
|
5
|
+
<span>Cardholder name</span>
|
6
|
+
<%= text_field_tag "#{param_prefix}[name]",
|
7
|
+
"#{@order.billing_firstname} #{@order.billing_lastname}",
|
8
|
+
{ id: "name_on_card_#{payment_method.id}",
|
9
|
+
data: { conekta: 'card[name]' } } %>
|
10
|
+
</label>
|
11
|
+
</div>
|
12
|
+
<div>
|
13
|
+
<label>
|
14
|
+
<span>Card number</span>
|
15
|
+
<% options_hash = Rails.env.production? ? { autocomplete: 'off' } : {} %>
|
16
|
+
<%= text_field_tag "#{param_prefix}[number]",
|
17
|
+
'',
|
18
|
+
options_hash.merge(id: 'card_number',
|
19
|
+
class: 'required cardNumber',
|
20
|
+
size: 19,
|
21
|
+
maxlength: 19,
|
22
|
+
autocomplete: "off",
|
23
|
+
data: { conekta: 'card[number]' }) %>
|
24
|
+
</label>
|
25
|
+
</div>
|
26
|
+
<div>
|
27
|
+
<label>
|
28
|
+
<span>CVC</span>
|
29
|
+
<%= text_field_tag "#{param_prefix}[verification_value]",
|
30
|
+
'',
|
31
|
+
options_hash.merge(id: 'card_code',
|
32
|
+
class: 'required cardCode',
|
33
|
+
size: 5,
|
34
|
+
data: { conekta: 'card[cvc]' } ) %>
|
35
|
+
</label>
|
36
|
+
</div>
|
37
|
+
<div>
|
38
|
+
<label>
|
39
|
+
<span>Expiration date (MM/YYYY)</span>
|
40
|
+
<%= select_month(Date.today,
|
41
|
+
{ prefix: param_prefix, field_name: 'month', use_month_numbers: true },
|
42
|
+
class: 'required',
|
43
|
+
id: "card_month",
|
44
|
+
data: { conekta: 'card[exp_month]' }) %>
|
45
|
+
</label>
|
46
|
+
<span>/</span>
|
47
|
+
<%= select_year(Date.today,
|
48
|
+
{ prefix: param_prefix, field_name: 'year', start_year: Date.today.year, end_year: Date.today.year + 15 },
|
49
|
+
class: 'required',
|
50
|
+
id: "card_year",
|
51
|
+
data: { conekta: 'card[exp_year]' }) %>
|
52
|
+
</div>
|
53
|
+
<%= javascript_tag do %>
|
54
|
+
var creditCardPaymentId = '#order_payments_attributes__payment_method_id_<%= payment_method.id %>'
|
55
|
+
Conekta.setPublicKey('<%= payment_method.preferences[:public_auth_token] %>');
|
56
|
+
<% end %>
|
@@ -0,0 +1 @@
|
|
1
|
+
<%= render "spree/admin/payments/source_views/gateway", payment: payment %>
|
@@ -0,0 +1 @@
|
|
1
|
+
# frozen_string_literal: true
|
@@ -0,0 +1,57 @@
|
|
1
|
+
<% param_prefix = "payment_source[#{payment_method.id}]" %>
|
2
|
+
<span class="card-errors"></span>
|
3
|
+
<div>
|
4
|
+
<label>
|
5
|
+
<span>Cardholder name</span>
|
6
|
+
<%= text_field_tag "#{param_prefix}[name]",
|
7
|
+
"#{@order.billing_firstname} #{@order.billing_lastname}",
|
8
|
+
{ id: "name_on_card_#{payment_method.id}",
|
9
|
+
data: { conekta: 'card[name]' } } %>
|
10
|
+
</label>
|
11
|
+
</div>
|
12
|
+
<div>
|
13
|
+
<label>
|
14
|
+
<span>Card number</span>
|
15
|
+
<% options_hash = Rails.env.production? ? { autocomplete: 'off' } : {} %>
|
16
|
+
<%= text_field_tag "#{param_prefix}[number]",
|
17
|
+
'',
|
18
|
+
options_hash.merge(id: 'card_number',
|
19
|
+
class: 'required cardNumber',
|
20
|
+
size: 19,
|
21
|
+
maxlength: 19,
|
22
|
+
autocomplete: "off",
|
23
|
+
data: { conekta: 'card[number]' }) %>
|
24
|
+
</label>
|
25
|
+
</div>
|
26
|
+
<div>
|
27
|
+
<label>
|
28
|
+
<span>CVC</span>
|
29
|
+
<%= text_field_tag "#{param_prefix}[verification_value]",
|
30
|
+
'',
|
31
|
+
options_hash.merge(id: 'card_code',
|
32
|
+
class: 'required cardCode',
|
33
|
+
size: 5,
|
34
|
+
data: { conekta: 'card[cvc]' } ) %>
|
35
|
+
</label>
|
36
|
+
</div>
|
37
|
+
<div>
|
38
|
+
<label>
|
39
|
+
<span>Expiration date (MM/YYYY)</span>
|
40
|
+
<%= select_month(Date.today,
|
41
|
+
{ prefix: param_prefix, field_name: 'month', use_month_numbers: true },
|
42
|
+
class: 'required',
|
43
|
+
id: "card_month",
|
44
|
+
data: { conekta: 'card[exp_month]' }) %>
|
45
|
+
</label>
|
46
|
+
<span>/</span>
|
47
|
+
<%= select_year(Date.today,
|
48
|
+
{ prefix: param_prefix, field_name: 'year', start_year: Date.today.year, end_year: Date.today.year + 15 },
|
49
|
+
class: 'required',
|
50
|
+
id: "card_year",
|
51
|
+
data: { conekta: 'card[exp_year]' }) %>
|
52
|
+
</div>
|
53
|
+
|
54
|
+
<%= javascript_tag do %>
|
55
|
+
var creditCardPaymentId = '#order_payments_attributes__payment_method_id_<%= payment_method.id %>'
|
56
|
+
Conekta.setPublicKey('<%= payment_method.preferences[:public_auth_token] %>');
|
57
|
+
<% end %>
|
@@ -0,0 +1,8 @@
|
|
1
|
+
# Sample localization file for English. Add more files in this directory for other locales.
|
2
|
+
# See https://github.com/svenfuchs/rails-i18n/tree/master/rails%2Flocale for starting points.
|
3
|
+
|
4
|
+
en:
|
5
|
+
activerecord:
|
6
|
+
attributes:
|
7
|
+
spree/gateway/conekta_card_gateway:
|
8
|
+
number: Card Number
|
data/config/routes.rb
ADDED
@@ -0,0 +1,34 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module SolidusConektaCard
|
4
|
+
module Generators
|
5
|
+
class InstallGenerator < Rails::Generators::Base
|
6
|
+
class_option :auto_run_migrations, type: :boolean, default: false
|
7
|
+
|
8
|
+
def add_javascripts
|
9
|
+
append_file 'vendor/assets/javascripts/spree/backend/all.js', "//= require spree/conekta\n"
|
10
|
+
append_file 'vendor/assets/javascripts/spree/backend/all.js', "//= require spree/backend/solidus_conekta_card\n"
|
11
|
+
append_file 'vendor/assets/javascripts/spree/frontend/all.js', "//= require spree/frontend/solidus_conekta_card\n"
|
12
|
+
append_file 'vendor/assets/javascripts/spree/frontend/all.js', "//= require spree/conekta\n"
|
13
|
+
end
|
14
|
+
|
15
|
+
def add_stylesheets
|
16
|
+
inject_into_file 'vendor/assets/stylesheets/spree/frontend/all.css', " *= require spree/frontend/solidus_conekta_card\n", before: /\*\//, verbose: true
|
17
|
+
inject_into_file 'vendor/assets/stylesheets/spree/backend/all.css', " *= require spree/backend/solidus_conekta_card\n", before: /\*\//, verbose: true
|
18
|
+
end
|
19
|
+
|
20
|
+
def add_migrations
|
21
|
+
run 'bundle exec rake railties:install:migrations FROM=solidus_conekta_card'
|
22
|
+
end
|
23
|
+
|
24
|
+
def run_migrations
|
25
|
+
run_migrations = options[:auto_run_migrations] || ['', 'y', 'Y'].include?(ask('Would you like to run the migrations now? [Y/n]'))
|
26
|
+
if run_migrations
|
27
|
+
run 'bundle exec rake db:migrate'
|
28
|
+
else
|
29
|
+
puts 'Skipping rake db:migrate, don\'t forget to run it!'
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module SolidusConektaCard
|
4
|
+
class Engine < Rails::Engine
|
5
|
+
require 'spree/core'
|
6
|
+
isolate_namespace Spree
|
7
|
+
engine_name 'solidus_conekta_card'
|
8
|
+
|
9
|
+
# use rspec for tests
|
10
|
+
config.generators do |g|
|
11
|
+
g.test_framework :rspec
|
12
|
+
end
|
13
|
+
|
14
|
+
initializer 'spree_payment_network.register.payment_methods' do |app|
|
15
|
+
app.config.spree.payment_methods << Spree::PaymentMethod::ConektaCard
|
16
|
+
end
|
17
|
+
|
18
|
+
def self.activate
|
19
|
+
Dir.glob(File.join(File.dirname(__FILE__), '../../app/**/*_decorator*.rb')) do |c|
|
20
|
+
Rails.configuration.cache_classes ? require(c) : load(c)
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
config.to_prepare(&method(:activate).to_proc)
|
25
|
+
end
|
26
|
+
end
|
@@ -0,0 +1,8 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
FactoryBot.define do
|
4
|
+
# Define your Spree extensions Factories within this file to enable applications, and other extensions to use and override them.
|
5
|
+
#
|
6
|
+
# Example adding this to your spec_helper will load these Factories for use:
|
7
|
+
# require 'solidus_conekta_card/factories'
|
8
|
+
end
|