solidus_conekta_card 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -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,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,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
@@ -0,0 +1,6 @@
1
+
2
+ es-MX:
3
+ activerecord:
4
+ attributes:
5
+ spree/gateway/conekta_card_gateway:
6
+ number: Numero de Tarjeta
data/config/routes.rb ADDED
@@ -0,0 +1,5 @@
1
+ # frozen_string_literal: true
2
+
3
+ Spree::Core::Engine.routes.draw do
4
+ # Add your extension routes here
5
+ end
@@ -0,0 +1,9 @@
1
+ # frozen_string_literal: true
2
+
3
+ class CreateConektaCardPayments < SolidusSupport::Migration[4.2]
4
+ def change
5
+ create_table :spree_conekta_card_payments do |t|
6
+ t.string :conekta_order_id
7
+ end
8
+ end
9
+ end
@@ -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
@@ -0,0 +1,5 @@
1
+ # frozen_string_literal: true
2
+
3
+ module SolidusConektaCard
4
+ VERSION = '1.0.0'
5
+ end
@@ -0,0 +1,6 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'solidus_core'
4
+ require 'solidus_support'
5
+ require 'deface'
6
+ require 'solidus_conekta_card/engine'