solidus_mp_dois 0.0.4 → 0.0.5
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/app/models/solidus_mp_dois/card.rb +5 -0
- data/app/models/solidus_mp_dois/credit_card_source.rb +7 -0
- data/app/models/solidus_mp_dois/customer.rb +6 -0
- data/app/models/solidus_mp_dois/mp_card.rb +178 -0
- data/app/models/solidus_mp_dois/mp_gateway.rb +35 -0
- data/app/models/solidus_mp_dois/mp_pix.rb +143 -0
- data/app/models/solidus_mp_dois/pix_source.rb +20 -0
- data/app/views/spree/admin/payments/source_forms/_mercado_pago_card.html.erb +0 -0
- data/app/views/spree/admin/payments/source_forms/_mercado_pago_pix.html.erb +0 -0
- data/app/views/spree/admin/payments/source_views/_mercado_pago_card.html.erb +1 -0
- data/app/views/spree/admin/payments/source_views/_mercado_pago_pix.html.erb +1 -0
- data/app/views/spree/api/payments/source_views/_mercado_pago_card.json.jbuilder +2 -0
- data/app/views/spree/api/payments/source_views/_mercado_pago_pix.json.jbuilder +1 -0
- data/lib/generators/solidus_mp_dois/install/install_generator.rb +38 -0
- data/lib/generators/solidus_mp_dois/install/templates/app/javascript/controllers/card_payment_brick_controller.js +86 -0
- data/lib/generators/solidus_mp_dois/install/templates/app/javascript/controllers/mp_three_ds_controller.js +40 -0
- data/lib/generators/solidus_mp_dois/install/templates/app/javascript/controllers/payment_brick_controller.js +97 -0
- data/lib/solidus_mp_dois/engine.rb +12 -0
- data/lib/solidus_mp_dois.rb +6 -0
- metadata +21 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: e6e4bf85326a054d6a1fd19f60af5aa5eed6140d077ba81f71b159b4e2438aea
|
4
|
+
data.tar.gz: 035767ed834305f06e8a5857a07c73cc323ba25231eca5d4dd7de273f6713108
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 9bfdf0ff84eefbd24ff8df01fd5aa8ac7cdd7cdc99c3ab6a5136a80d93e946dc8465eeb6f5fa7ff97614a6aefc5329d12ae6ae6863e1c04c2da1c44be8675fc0
|
7
|
+
data.tar.gz: d517b16dd8a9934e2b7a0df97b6dd55e23384353bf7db6d7e9be2b42ac5b3b92f0b9e0f0f38c9cac6542d1079ee8b3121897228fffec3f2d176e6898c28f1f46
|
@@ -0,0 +1,178 @@
|
|
1
|
+
module SolidusMpDois
|
2
|
+
class MpCard < Spree::PaymentMethod
|
3
|
+
preference :public_key, :string
|
4
|
+
preference :access_token, :string
|
5
|
+
preference :statement_descriptor, :string
|
6
|
+
|
7
|
+
def payment_source_class
|
8
|
+
CreditCardSource
|
9
|
+
end
|
10
|
+
|
11
|
+
def gateway_class
|
12
|
+
MpGateway
|
13
|
+
end
|
14
|
+
|
15
|
+
def supports?(source)
|
16
|
+
source.is_a?(payment_source_class)
|
17
|
+
end
|
18
|
+
|
19
|
+
def auto_capture?
|
20
|
+
true
|
21
|
+
end
|
22
|
+
|
23
|
+
def partial_name
|
24
|
+
"mercado_pago_card"
|
25
|
+
end
|
26
|
+
|
27
|
+
def find_payment external_id
|
28
|
+
MpApi.configuration.access_token = preferences[:access_token]
|
29
|
+
MpApi::Payment.find_by_id(external_id)
|
30
|
+
end
|
31
|
+
|
32
|
+
def create_payment order, source_params
|
33
|
+
customer = find_or_create_customer(order, source_params)
|
34
|
+
save_credit_card(source_params[:token], customer) if customer
|
35
|
+
|
36
|
+
payment = order.payments.new(amount: order.total, payment_method: self)
|
37
|
+
payment.source = init_source(order, source_params, customer)
|
38
|
+
payment.save
|
39
|
+
|
40
|
+
mp_payment = create_mp_payment(payment.source, customer.try(:external_id))
|
41
|
+
process_payment_response(payment, mp_payment)
|
42
|
+
payment
|
43
|
+
end
|
44
|
+
|
45
|
+
def purchase money, source, options = {}
|
46
|
+
gateway.purchase(money, source, options)
|
47
|
+
end
|
48
|
+
|
49
|
+
private
|
50
|
+
|
51
|
+
def init_source order, source_params, customer
|
52
|
+
tax_id = customer&.tax_id || source_params[:tax_id]
|
53
|
+
document_type = (tax_id.gsub(/\D/, "").length == 11) ? "CPF" : "CNPJ"
|
54
|
+
customer_email = source_params[:payer_email].present? ? source_params[:payer_email] : customer.email
|
55
|
+
|
56
|
+
CreditCardSource.new(
|
57
|
+
amount: order.total,
|
58
|
+
payer_identification_type: document_type,
|
59
|
+
tax_id: tax_id,
|
60
|
+
email: customer_email,
|
61
|
+
issuer_id: source_params[:issuer_id],
|
62
|
+
installments: source_params[:installments],
|
63
|
+
token: source_params[:token],
|
64
|
+
card_brand: source_params[:credit_card_brand],
|
65
|
+
payment_method: self,
|
66
|
+
saved_card: source_params[:saved_card]
|
67
|
+
)
|
68
|
+
end
|
69
|
+
|
70
|
+
def create_mp_payment payment_source, customer_id
|
71
|
+
MpApi.configuration.access_token = preferences[:access_token]
|
72
|
+
MpApi::Payment.new(
|
73
|
+
amount: payment_source.amount.to_f,
|
74
|
+
payment_method: payment_source.card_brand,
|
75
|
+
payer_email: payment_source.email,
|
76
|
+
payer_identification_type: payment_source.payer_identification_type,
|
77
|
+
payer_identification_number: payment_source.tax_id,
|
78
|
+
token: payment_source.token,
|
79
|
+
issuer_id: payment_source.issuer_id,
|
80
|
+
installments: payment_source.installments,
|
81
|
+
three_d_secure_mode: true,
|
82
|
+
statement_descriptor: preferences[:statement_descriptor],
|
83
|
+
saved_card: payment_source.saved_card,
|
84
|
+
customer_id: customer_id
|
85
|
+
).create
|
86
|
+
end
|
87
|
+
|
88
|
+
def find_or_create_customer(order, source_params)
|
89
|
+
return unless order.user
|
90
|
+
customer = SolidusMpDois::Customer.find_by(spree_user_id: order.user.id)
|
91
|
+
if customer.blank?
|
92
|
+
mp_customer = create_mp_customer(order, source_params)
|
93
|
+
if mp_customer.error.blank?
|
94
|
+
customer = SolidusMpDois::Customer.create(
|
95
|
+
external_id: mp_customer.external_id,
|
96
|
+
email: mp_customer.email,
|
97
|
+
first_name: mp_customer.first_name,
|
98
|
+
identification_type: mp_customer.identification_type,
|
99
|
+
tax_id: mp_customer.identification_number,
|
100
|
+
spree_user_id: order.user.id
|
101
|
+
)
|
102
|
+
end
|
103
|
+
end
|
104
|
+
customer
|
105
|
+
end
|
106
|
+
|
107
|
+
def create_mp_customer(order, source_params)
|
108
|
+
MpApi.configuration.access_token = preferences[:access_token]
|
109
|
+
MpApi::Customer.new(
|
110
|
+
email: order.email,
|
111
|
+
first_name: order.ship_address.name,
|
112
|
+
identification_type: source_params[:payer_identification_type],
|
113
|
+
identification_number: source_params[:tax_id]
|
114
|
+
).create
|
115
|
+
end
|
116
|
+
|
117
|
+
def save_credit_card(card_token, customer)
|
118
|
+
return if customer.nil?
|
119
|
+
MpApi.configuration.access_token = preferences[:access_token]
|
120
|
+
mp_credit_card = MpApi::Card.new(token: card_token, customer_id: customer.external_id).create
|
121
|
+
SolidusMpDois::Card.upsert(
|
122
|
+
{
|
123
|
+
external_id: mp_credit_card.external_id,
|
124
|
+
last_four_digits: mp_credit_card.last_four_digits,
|
125
|
+
mp_payment_method_id: mp_credit_card.mp_payment_method_id,
|
126
|
+
customer_id: customer.id
|
127
|
+
}, unique_by: :external_id
|
128
|
+
)
|
129
|
+
end
|
130
|
+
|
131
|
+
def process_payment_response(payment, mp_payment)
|
132
|
+
payment.source.update(
|
133
|
+
external_id: mp_payment.id,
|
134
|
+
three_ds_url: mp_payment.three_ds_info_external_resource_url,
|
135
|
+
three_ds_creq: mp_payment.three_ds_info_creq,
|
136
|
+
last_four_digits: mp_payment.last_four_digits
|
137
|
+
)
|
138
|
+
if mp_payment.error || mp_payment.internal_error
|
139
|
+
handle_payment_error(payment, mp_payment)
|
140
|
+
else
|
141
|
+
payment.order.update(email: payment.source.email)
|
142
|
+
update_payment_status(payment, mp_payment)
|
143
|
+
end
|
144
|
+
end
|
145
|
+
|
146
|
+
def update_payment_status(payment, mp_payment)
|
147
|
+
status = case mp_payment.status
|
148
|
+
when "approved" then "success"
|
149
|
+
when "pending" then "pending"
|
150
|
+
end
|
151
|
+
payment.source.update!(status: status)
|
152
|
+
end
|
153
|
+
|
154
|
+
def handle_payment_error(payment, mp_payment)
|
155
|
+
payment.invalidate
|
156
|
+
error_message = mp_payment.error || "Erro ao criar o pagamento"
|
157
|
+
response = failure_response(error_message)
|
158
|
+
payment.log_entries.create(parsed_payment_response_details_with_fallback: response)
|
159
|
+
payment.source.update(internal_error: error_message, status: "error")
|
160
|
+
end
|
161
|
+
|
162
|
+
def successful_response message, transaction_id
|
163
|
+
ActiveMerchant::Billing::Response.new(
|
164
|
+
true,
|
165
|
+
message,
|
166
|
+
{},
|
167
|
+
authorization: transaction_id
|
168
|
+
)
|
169
|
+
end
|
170
|
+
|
171
|
+
def failure_response message
|
172
|
+
ActiveMerchant::Billing::Response.new(
|
173
|
+
false,
|
174
|
+
message
|
175
|
+
)
|
176
|
+
end
|
177
|
+
end
|
178
|
+
end
|
@@ -0,0 +1,35 @@
|
|
1
|
+
module SolidusMpDois
|
2
|
+
class MpGateway
|
3
|
+
def initialize(options)
|
4
|
+
MpApi.configuration.access_token = options[:access_token]
|
5
|
+
end
|
6
|
+
|
7
|
+
def purchase money, source, options = {}
|
8
|
+
mp_payment = source.retrieve_from_api
|
9
|
+
10.times do
|
10
|
+
break if ["approved", "rejected"].include? mp_payment.status
|
11
|
+
mp_payment = source.retrieve_from_api
|
12
|
+
end
|
13
|
+
if mp_payment.status == "approved"
|
14
|
+
source.update(status: "approved")
|
15
|
+
successful_response("Pagamento realizado", mp_payment.id)
|
16
|
+
else
|
17
|
+
failure_response(mp_payment.status_detail || mp_payment.status)
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
def void(transaction_id, options = {})
|
22
|
+
# Respondendo sempre com successful_response para funcionar o botão de "Cancelar" do pedido. Reembolso deve ser feito por fora.
|
23
|
+
successful_response("Pagamento cancelado. Se necessário, realize o reembolso.", transaction_id)
|
24
|
+
end
|
25
|
+
|
26
|
+
def successful_response message, transaction_id
|
27
|
+
ActiveMerchant::Billing::Response.new(
|
28
|
+
true,
|
29
|
+
message,
|
30
|
+
{},
|
31
|
+
authorization: transaction_id
|
32
|
+
)
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
@@ -0,0 +1,143 @@
|
|
1
|
+
module SolidusMpDois
|
2
|
+
class MpPix < Spree::PaymentMethod
|
3
|
+
preference :public_key, :string
|
4
|
+
preference :access_token, :string
|
5
|
+
preference :statement_descriptor, :string
|
6
|
+
|
7
|
+
def payment_source_class
|
8
|
+
PixSource
|
9
|
+
end
|
10
|
+
|
11
|
+
def gateway_class
|
12
|
+
MpGateway
|
13
|
+
end
|
14
|
+
|
15
|
+
def supports?(source)
|
16
|
+
source.is_a?(payment_source_class)
|
17
|
+
end
|
18
|
+
|
19
|
+
def auto_capture?
|
20
|
+
true
|
21
|
+
end
|
22
|
+
|
23
|
+
def partial_name
|
24
|
+
"mercado_pago_pix"
|
25
|
+
end
|
26
|
+
|
27
|
+
def find_payment external_id
|
28
|
+
MpApi.configuration.access_token = preferences[:access_token]
|
29
|
+
MpApi::Payment.find_by_id(external_id)
|
30
|
+
end
|
31
|
+
|
32
|
+
def create_payment order
|
33
|
+
payment = find_existing_payment(order)
|
34
|
+
return payment if payment_usable?(order, payment)
|
35
|
+
|
36
|
+
payment = order.payments.new(amount: order.total, payment_method: self)
|
37
|
+
payment.source = init_source(order)
|
38
|
+
payment.save
|
39
|
+
|
40
|
+
mp_payment = create_mp_payment(payment.source)
|
41
|
+
process_payment_response(payment, mp_payment)
|
42
|
+
payment
|
43
|
+
end
|
44
|
+
|
45
|
+
def invalidate_payment payment_source
|
46
|
+
return false unless payment_source&.external_id
|
47
|
+
MpApi.configuration.access_token = preferences[:access_token]
|
48
|
+
mp_payment = find_payment(payment_source.external_id)
|
49
|
+
return false if mp_payment.pix_paid?
|
50
|
+
mp_payment.invalidate_pix!
|
51
|
+
payment_source.payments[0].log_entries.create!(parsed_payment_response_details_with_fallback: failure_response("Pagamento cancelado"))
|
52
|
+
payment_source.update(status: "cancelled")
|
53
|
+
true
|
54
|
+
end
|
55
|
+
|
56
|
+
def purchase(money, source, options = {})
|
57
|
+
gateway.purchase(money, source, options)
|
58
|
+
end
|
59
|
+
|
60
|
+
private
|
61
|
+
|
62
|
+
def init_source(order)
|
63
|
+
PixSource.new(
|
64
|
+
amount: order.total,
|
65
|
+
expiration: DateTime.now + 10.minutes,
|
66
|
+
email: order.email,
|
67
|
+
tax_id: order.tax_id,
|
68
|
+
payment_method: self
|
69
|
+
)
|
70
|
+
end
|
71
|
+
|
72
|
+
def create_mp_payment payment_source
|
73
|
+
MpApi.configuration.access_token = preferences[:access_token]
|
74
|
+
identification_type = (payment_source.tax_id.length > 14) ? "CNPJ" : "CPF"
|
75
|
+
MpApi::Payment.new(
|
76
|
+
payer_email: payment_source.email,
|
77
|
+
payer_identification_type: identification_type,
|
78
|
+
payer_identification_number: payment_source.tax_id,
|
79
|
+
payment_method: "pix",
|
80
|
+
amount: payment_source.amount.to_f,
|
81
|
+
statement_descriptor: preferences[:statement_descriptor],
|
82
|
+
description: payment_source.description
|
83
|
+
).create
|
84
|
+
end
|
85
|
+
|
86
|
+
def find_existing_payment(order)
|
87
|
+
pix_payments = order.payments.checkout.where(source_type: "SolidusMpDois::PixSource")
|
88
|
+
raise "More than one valid payment for #{order.number}" if pix_payments.count > 1
|
89
|
+
pix_payments.first
|
90
|
+
end
|
91
|
+
|
92
|
+
def payment_usable?(order, payment)
|
93
|
+
return false if payment.blank?
|
94
|
+
payment.amount == order.total && payment.source.expiration.future?
|
95
|
+
end
|
96
|
+
|
97
|
+
def process_payment_response(payment, mp_payment)
|
98
|
+
payment.update(response_code: mp_payment.id)
|
99
|
+
payment.source.update(
|
100
|
+
external_id: mp_payment.id,
|
101
|
+
qr_code: mp_payment.qr_code,
|
102
|
+
qr_code_base64: mp_payment.qr_code_base_64,
|
103
|
+
ticket_url: mp_payment.ticket_url
|
104
|
+
)
|
105
|
+
if mp_payment.error || mp_payment.internal_error
|
106
|
+
handle_payment_error(payment, mp_payment)
|
107
|
+
else
|
108
|
+
update_payment_status(payment, mp_payment)
|
109
|
+
end
|
110
|
+
end
|
111
|
+
|
112
|
+
def update_payment_status(payment, mp_payment)
|
113
|
+
status = case mp_payment.status
|
114
|
+
when "pending" then "pending"
|
115
|
+
end
|
116
|
+
payment.source.update!(status: status)
|
117
|
+
end
|
118
|
+
|
119
|
+
def handle_payment_error(payment, mp_payment)
|
120
|
+
payment.invalidate
|
121
|
+
error_message = mp_payment.error || "Erro ao criar o pagamento"
|
122
|
+
response = failure_response(error_message)
|
123
|
+
payment.log_entries.create(parsed_payment_response_details_with_fallback: response)
|
124
|
+
payment.source.update(internal_error: error_message, status: "error")
|
125
|
+
end
|
126
|
+
|
127
|
+
def successful_response message, transaction_id
|
128
|
+
ActiveMerchant::Billing::Response.new(
|
129
|
+
true,
|
130
|
+
message,
|
131
|
+
{},
|
132
|
+
authorization: transaction_id
|
133
|
+
)
|
134
|
+
end
|
135
|
+
|
136
|
+
def failure_response message
|
137
|
+
ActiveMerchant::Billing::Response.new(
|
138
|
+
false,
|
139
|
+
message
|
140
|
+
)
|
141
|
+
end
|
142
|
+
end
|
143
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
module SolidusMpDois
|
2
|
+
class PixSource < Spree::PaymentSource
|
3
|
+
def retrieve_from_api
|
4
|
+
payment_method.find_payment(external_id)
|
5
|
+
end
|
6
|
+
|
7
|
+
def expired?
|
8
|
+
expiration.past?
|
9
|
+
end
|
10
|
+
|
11
|
+
def paid?
|
12
|
+
mp_payment = retrieve_from_api
|
13
|
+
mp_payment.pix_paid?
|
14
|
+
end
|
15
|
+
|
16
|
+
def invalidate
|
17
|
+
payment_method.invalidate_payment(self)
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
File without changes
|
File without changes
|
@@ -0,0 +1 @@
|
|
1
|
+
ID do pagamento: <%= payment.source.external_id %>
|
@@ -0,0 +1 @@
|
|
1
|
+
ID do pagamento: <%= payment.source.external_id %>
|
@@ -0,0 +1 @@
|
|
1
|
+
json.call(payment_source, :id, :external_id, :status, :amount, :expiration, :email, :tax_id, :payment_method_id, :qr_code)
|
@@ -0,0 +1,38 @@
|
|
1
|
+
module SolidusMpDois
|
2
|
+
module Generators
|
3
|
+
class InstallGenerator < Rails::Generators::Base
|
4
|
+
class_option :auto_run_migrations, type: :boolean, default: false
|
5
|
+
source_root File.expand_path("templates", __dir__)
|
6
|
+
|
7
|
+
def self.exit_on_failure?
|
8
|
+
true
|
9
|
+
end
|
10
|
+
|
11
|
+
def pin_mp_js
|
12
|
+
run "bin/importmap pin @mercadopago/sdk-js"
|
13
|
+
end
|
14
|
+
|
15
|
+
def add_migrations
|
16
|
+
run "bin/rails railties:install:migrations FROM=solidus_mp_dois"
|
17
|
+
end
|
18
|
+
|
19
|
+
def install_mp_api
|
20
|
+
puts "Installing mp_api gem..."
|
21
|
+
run "bin/rails g mp_api:install"
|
22
|
+
end
|
23
|
+
|
24
|
+
def copy_app_files
|
25
|
+
directory "app", "app"
|
26
|
+
end
|
27
|
+
|
28
|
+
def run_migrations
|
29
|
+
run_migrations = options[:auto_run_migrations] || ["", "y", "Y"].include?(ask("Would you like to run the migrations now? [Y/n]")) # rubocop:disable Layout/LineLength
|
30
|
+
if run_migrations
|
31
|
+
run "bin/rails db:migrate"
|
32
|
+
else
|
33
|
+
puts "Skipping bin/rails db:migrate, don\"t forget to run it!" # rubocop:disable Rails/Output
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
@@ -0,0 +1,86 @@
|
|
1
|
+
import { Controller } from "@hotwired/stimulus"
|
2
|
+
import { loadMercadoPago } from "@mercadopago/sdk-js"
|
3
|
+
|
4
|
+
// Renderiza o Card Payment Brick (apenas cartão)
|
5
|
+
export default class extends Controller {
|
6
|
+
static values = { publicKey: String, amount: Number, email: String }
|
7
|
+
static targets = [
|
8
|
+
"token",
|
9
|
+
"paymentMethodId",
|
10
|
+
"installments",
|
11
|
+
"issuerId",
|
12
|
+
"transactionAmount",
|
13
|
+
"payerIdentificationType",
|
14
|
+
"payerIdentificationNumber",
|
15
|
+
"payerEmail"
|
16
|
+
]
|
17
|
+
async connect() {
|
18
|
+
await loadMercadoPago()
|
19
|
+
const mp = new MercadoPago(this.publicKeyValue, {
|
20
|
+
locale: 'pt-BR'
|
21
|
+
});
|
22
|
+
const bricksBuilder = mp.bricks();
|
23
|
+
const renderCardPaymentBrick = async (bricksBuilder) => {
|
24
|
+
const settings = {
|
25
|
+
initialization: {
|
26
|
+
amount: this.amountValue,
|
27
|
+
payer: {
|
28
|
+
email: this.emailValue
|
29
|
+
},
|
30
|
+
},
|
31
|
+
customization: {
|
32
|
+
visual: {
|
33
|
+
hidePaymentButton: true,
|
34
|
+
style: {
|
35
|
+
customVariables: {
|
36
|
+
theme: 'default'
|
37
|
+
}
|
38
|
+
}
|
39
|
+
},
|
40
|
+
paymentMethods: {
|
41
|
+
maxInstallments: 1,
|
42
|
+
}
|
43
|
+
},
|
44
|
+
callbacks: {
|
45
|
+
onReady: () => {
|
46
|
+
document.getElementById('submit_payment').removeAttribute('disabled')
|
47
|
+
},
|
48
|
+
onSubmit: (cardFormData) => {
|
49
|
+
},
|
50
|
+
onError: (error) => {
|
51
|
+
},
|
52
|
+
},
|
53
|
+
};
|
54
|
+
window.cardPaymentBrickController = await bricksBuilder.create('cardPayment', 'cardPaymentBrick_container', settings);
|
55
|
+
};
|
56
|
+
renderCardPaymentBrick(bricksBuilder);
|
57
|
+
const element = document.getElementById('checkout_form_payment');
|
58
|
+
element.addEventListener('submit', event => {
|
59
|
+
document.getElementById('submit_payment').setAttribute('disabled', "")
|
60
|
+
event.preventDefault();
|
61
|
+
this.createPayment()
|
62
|
+
});
|
63
|
+
}
|
64
|
+
|
65
|
+
async disconnect() {
|
66
|
+
window.cardPaymentBrickController.unmount()
|
67
|
+
}
|
68
|
+
|
69
|
+
createPayment(){
|
70
|
+
window.cardPaymentBrickController.getFormData()
|
71
|
+
.then((cardFormData) => {
|
72
|
+
this.tokenTarget.value = cardFormData.token
|
73
|
+
this.paymentMethodIdTarget.value = cardFormData.payment_method_id
|
74
|
+
this.installmentsTarget.value = cardFormData.installments
|
75
|
+
this.issuerIdTarget.value = cardFormData.issuer_id
|
76
|
+
this.transactionAmountTarget.value = cardFormData.transaction_amount
|
77
|
+
this.payerIdentificationTypeTarget.value = cardFormData.payer.identification.type
|
78
|
+
this.payerIdentificationNumberTarget.value = cardFormData.payer.identification.number
|
79
|
+
this.payerEmailTarget.value = cardFormData.payer.email
|
80
|
+
this.tokenTarget.form.submit()
|
81
|
+
})
|
82
|
+
.catch((error) => {
|
83
|
+
document.getElementById('submit_payment').removeAttribute('disabled')
|
84
|
+
});
|
85
|
+
}
|
86
|
+
}
|
@@ -0,0 +1,40 @@
|
|
1
|
+
import { Controller } from "@hotwired/stimulus"
|
2
|
+
|
3
|
+
// Connects to data-controller="credit-card"
|
4
|
+
export default class extends Controller {
|
5
|
+
|
6
|
+
static values = { threeDsUrl: String, threeDsCreq: String }
|
7
|
+
|
8
|
+
// Anytime the controller is connected to the DOM
|
9
|
+
async connect() {
|
10
|
+
if (!this.threeDsUrlValue) return
|
11
|
+
var iframe = document.createElement('iframe')
|
12
|
+
iframe.height = "460px"
|
13
|
+
iframe.width = "500px"
|
14
|
+
iframe.name = "myframe"
|
15
|
+
iframe.id = "myframe"
|
16
|
+
this.element.appendChild(iframe)
|
17
|
+
var idocument = iframe.contentWindow.document
|
18
|
+
var myform = idocument.createElement("form")
|
19
|
+
myform.name = "myform"
|
20
|
+
myform.setAttribute("target", "myframe")
|
21
|
+
myform.setAttribute("method", "post")
|
22
|
+
myform.setAttribute("action", this.threeDsUrlValue)
|
23
|
+
var hiddenField = idocument.createElement("input")
|
24
|
+
hiddenField.setAttribute("type", "hidden")
|
25
|
+
hiddenField.setAttribute("name", "creq")
|
26
|
+
hiddenField.setAttribute("value", this.threeDsCreqValue)
|
27
|
+
myform.appendChild(hiddenField)
|
28
|
+
iframe.appendChild(myform)
|
29
|
+
var submit_form = document.getElementById("checkout_confirm_button")
|
30
|
+
submit_form.setAttribute("class", "hidden")
|
31
|
+
myform.submit()
|
32
|
+
window.addEventListener("message", (e) => {
|
33
|
+
if (e.data.status === "COMPLETE") {
|
34
|
+
document.getElementById("checkout_form_confirm").submit();
|
35
|
+
}
|
36
|
+
})
|
37
|
+
|
38
|
+
}
|
39
|
+
}
|
40
|
+
|
@@ -0,0 +1,97 @@
|
|
1
|
+
import { Controller } from "@hotwired/stimulus"
|
2
|
+
import { loadMercadoPago } from "@mercadopago/sdk-js"
|
3
|
+
|
4
|
+
// Renderiza o Payment Brick (tem opção de ser vários métodos de pagamento)
|
5
|
+
export default class extends Controller {
|
6
|
+
static values = { publicKey: String, amount: Number, email: String, customerId: String, cardsIds: Array }
|
7
|
+
static targets = [
|
8
|
+
"token",
|
9
|
+
"paymentMethodId",
|
10
|
+
"installments",
|
11
|
+
"issuerId",
|
12
|
+
"transactionAmount",
|
13
|
+
"payerIdentificationType",
|
14
|
+
"payerIdentificationNumber",
|
15
|
+
"payerType",
|
16
|
+
"payerId",
|
17
|
+
"savedCard",
|
18
|
+
"payerEmail"
|
19
|
+
]
|
20
|
+
async connect() {
|
21
|
+
await loadMercadoPago()
|
22
|
+
const mp = new MercadoPago(this.publicKeyValue, {
|
23
|
+
locale: 'pt-BR'
|
24
|
+
});
|
25
|
+
const bricksBuilder = mp.bricks();
|
26
|
+
const renderPaymentBrick = async (bricksBuilder) => {
|
27
|
+
const settings = {
|
28
|
+
initialization: {
|
29
|
+
amount: this.amountValue,
|
30
|
+
payer: {
|
31
|
+
email: this.emailValue,
|
32
|
+
customerId: this.customerIdValue,
|
33
|
+
cardsIds: this.cardsIdsValue
|
34
|
+
}
|
35
|
+
},
|
36
|
+
customization: {
|
37
|
+
visual: {
|
38
|
+
hidePaymentButton: true,
|
39
|
+
},
|
40
|
+
paymentMethods: {
|
41
|
+
creditCard: "all",
|
42
|
+
maxInstallments: 1
|
43
|
+
},
|
44
|
+
},
|
45
|
+
callbacks: {
|
46
|
+
onReady: () => {
|
47
|
+
document.getElementById('submit_payment').removeAttribute('disabled')
|
48
|
+
},
|
49
|
+
onSubmit: ({ selectedPaymentMethod, formData }) => {
|
50
|
+
},
|
51
|
+
onError: (error) => {
|
52
|
+
},
|
53
|
+
},
|
54
|
+
};
|
55
|
+
window.paymentBrickController = await bricksBuilder.create(
|
56
|
+
"payment",
|
57
|
+
"paymentBrick_container",
|
58
|
+
settings
|
59
|
+
);
|
60
|
+
};
|
61
|
+
renderPaymentBrick(bricksBuilder);
|
62
|
+
|
63
|
+
const element = document.getElementById('checkout_form_payment');
|
64
|
+
element.addEventListener('submit', event => {
|
65
|
+
document.getElementById('submit_payment').setAttribute('disabled', "")
|
66
|
+
event.preventDefault();
|
67
|
+
this.createPayment()
|
68
|
+
});
|
69
|
+
}
|
70
|
+
|
71
|
+
async disconnect() {
|
72
|
+
window.paymentBrickController.unmount()
|
73
|
+
}
|
74
|
+
|
75
|
+
createPayment() {
|
76
|
+
window.paymentBrickController.getFormData()
|
77
|
+
.then(({ selectedPaymentMethod, formData }) => {
|
78
|
+
if (selectedPaymentMethod == "credit_card") {
|
79
|
+
this.tokenTarget.value = formData.token
|
80
|
+
this.paymentMethodIdTarget.value = formData.payment_method_id
|
81
|
+
this.installmentsTarget.value = formData.installments
|
82
|
+
this.issuerIdTarget.value = formData.issuer_id
|
83
|
+
this.transactionAmountTarget.value = formData.transaction_amount
|
84
|
+
this.payerIdentificationTypeTarget.value = formData.payer?.identification?.type || "" // Para cartão novo
|
85
|
+
this.payerIdentificationNumberTarget.value = formData.payer?.identification?.number || "" // Para cartão novo
|
86
|
+
this.payerTypeTarget.value = formData.payer?.type || "" // Para cartão salvo
|
87
|
+
this.payerIdTarget.value = formData.payer?.id || "" // Para cartão salvo
|
88
|
+
this.savedCardTarget.value = this.payerTypeTarget.value == "customer"
|
89
|
+
this.payerEmailTarget.value = formData.payer?.email || "" // Para cartão salvo
|
90
|
+
this.tokenTarget.form.submit()
|
91
|
+
}
|
92
|
+
})
|
93
|
+
.catch((error) => {
|
94
|
+
document.getElementById('submit_payment').removeAttribute('disabled')
|
95
|
+
});
|
96
|
+
}
|
97
|
+
}
|
@@ -0,0 +1,12 @@
|
|
1
|
+
module SolidusMpDois
|
2
|
+
class Engine < Rails::Engine
|
3
|
+
isolate_namespace SolidusMpDois
|
4
|
+
|
5
|
+
initializer "solidus_mp_dois.add_payment_method", after: "spree.register.payment_methods" do |app|
|
6
|
+
app.config.spree.payment_methods << "SolidusMpDois::MpCard"
|
7
|
+
app.config.spree.payment_methods << "SolidusMpDois::MpPix"
|
8
|
+
end
|
9
|
+
|
10
|
+
engine_name "solidus_mp_dois"
|
11
|
+
end
|
12
|
+
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: solidus_mp_dois
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.5
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Todas Essas Coisas
|
@@ -44,7 +44,26 @@ email:
|
|
44
44
|
executables: []
|
45
45
|
extensions: []
|
46
46
|
extra_rdoc_files: []
|
47
|
-
files:
|
47
|
+
files:
|
48
|
+
- app/models/solidus_mp_dois/card.rb
|
49
|
+
- app/models/solidus_mp_dois/credit_card_source.rb
|
50
|
+
- app/models/solidus_mp_dois/customer.rb
|
51
|
+
- app/models/solidus_mp_dois/mp_card.rb
|
52
|
+
- app/models/solidus_mp_dois/mp_gateway.rb
|
53
|
+
- app/models/solidus_mp_dois/mp_pix.rb
|
54
|
+
- app/models/solidus_mp_dois/pix_source.rb
|
55
|
+
- app/views/spree/admin/payments/source_forms/_mercado_pago_card.html.erb
|
56
|
+
- app/views/spree/admin/payments/source_forms/_mercado_pago_pix.html.erb
|
57
|
+
- app/views/spree/admin/payments/source_views/_mercado_pago_card.html.erb
|
58
|
+
- app/views/spree/admin/payments/source_views/_mercado_pago_pix.html.erb
|
59
|
+
- app/views/spree/api/payments/source_views/_mercado_pago_card.json.jbuilder
|
60
|
+
- app/views/spree/api/payments/source_views/_mercado_pago_pix.json.jbuilder
|
61
|
+
- lib/generators/solidus_mp_dois/install/install_generator.rb
|
62
|
+
- lib/generators/solidus_mp_dois/install/templates/app/javascript/controllers/card_payment_brick_controller.js
|
63
|
+
- lib/generators/solidus_mp_dois/install/templates/app/javascript/controllers/mp_three_ds_controller.js
|
64
|
+
- lib/generators/solidus_mp_dois/install/templates/app/javascript/controllers/payment_brick_controller.js
|
65
|
+
- lib/solidus_mp_dois.rb
|
66
|
+
- lib/solidus_mp_dois/engine.rb
|
48
67
|
homepage: https://github.com/todasessascoisas/solidus_mp_dois
|
49
68
|
licenses: []
|
50
69
|
metadata: {}
|