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.
@@ -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'