solidus_mp 0.0.1 → 0.0.2

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: f08d541bb494c19f221bbe8e5c7e68e9a38efe758daa3b68e81fc18e08db679d
4
- data.tar.gz: a0aaedf2cfc676a78f4eb5998e7ab1e02b12ae73aef56733b8bb20c1dadc6b10
3
+ metadata.gz: aa21ea1f258cffe8857cf595e61fcb222a9ca1a144919e93890aa785cbed5427
4
+ data.tar.gz: d4db2b7c782bf3eaf93834b26354c52a70f465112f8c23eb01f046204caa60e4
5
5
  SHA512:
6
- metadata.gz: 0b65781a19527fb669df86296612ead960f9df96554f2d96305732e17c3170649a98318e477b50190d8d20e50fd33841183c964da7da98dff6ebe7feeb5ba13c
7
- data.tar.gz: 331f578e0e6961b5e34aebac7001d8332ece8d01bb9b138bcdbbd056ab66901a82bdf476b52870656731b40c867efbb3c2e123e5d5f52fa588ed282144acb377
6
+ metadata.gz: c5057b3b6735ca61db77b199c3a1d1ddd1bd086b069aa26e060e94b82d53e7be61b48cdbc4287ddcfedfd8a9977f8df8782f3aad9c57a50e6c604a99c8381f41
7
+ data.tar.gz: 033f3e6624c5f9f22b2b36db894676002fc1f5843b62f93e774095c93a6dce30137b129471db44e2d5dcf2bfe5cc1238b0db0231f1ec87978e013cc78540cb40
data/LICENSE CHANGED
@@ -1,4 +1,4 @@
1
- Copyright (c) 2023 ulysses-bull
1
+ Copyright (c) 2023 caio
2
2
  All rights reserved.
3
3
 
4
4
  Redistribution and use in source and binary forms, with or without modification,
data/README.md CHANGED
@@ -1,73 +0,0 @@
1
- # Solidus Mp
2
-
3
- [![CircleCI](https://circleci.com/gh/solidusio-contrib/solidus_mp.svg?style=shield)](https://circleci.com/gh/solidusio-contrib/solidus_mp)
4
- [![codecov](https://codecov.io/gh/solidusio-contrib/solidus_mp/branch/master/graph/badge.svg)](https://codecov.io/gh/solidusio-contrib/solidus_mp)
5
-
6
- <!-- Explain what your extension does. -->
7
-
8
- ## Installation
9
-
10
- Add solidus_mp to your Gemfile:
11
-
12
- ```ruby
13
- gem 'solidus_mp'
14
- ```
15
-
16
- Bundle your dependencies and run the installation generator:
17
-
18
- ```shell
19
- bin/rails generate solidus_mp:install
20
- ```
21
-
22
- ## Usage
23
-
24
- <!-- Explain how to use your extension once it's been installed. -->
25
-
26
- ## Development
27
-
28
- ### Testing the extension
29
-
30
- First bundle your dependencies, then run `bin/rake`. `bin/rake` will default to building the dummy
31
- app if it does not exist, then it will run specs. The dummy app can be regenerated by using
32
- `bin/rake extension:test_app`.
33
-
34
- ```shell
35
- bin/rake
36
- ```
37
-
38
- To run [Rubocop](https://github.com/bbatsov/rubocop) static code analysis run
39
-
40
- ```shell
41
- bundle exec rubocop
42
- ```
43
-
44
- When testing your application's integration with this extension you may use its factories.
45
- You can load Solidus core factories along with this extension's factories using this statement:
46
-
47
- ```ruby
48
- SolidusDevSupport::TestingSupport::Factories.load_for(SolidusMp::Engine)
49
- ```
50
-
51
- ### Running the sandbox
52
-
53
- To run this extension in a sandboxed Solidus application, you can run `bin/sandbox`. The path for
54
- the sandbox app is `./sandbox` and `bin/rails` will forward any Rails commands to
55
- `sandbox/bin/rails`.
56
-
57
- Here's an example:
58
-
59
- ```
60
- $ bin/rails server
61
- => Booting Puma
62
- => Rails 6.0.2.1 application starting in development
63
- * Listening on tcp://127.0.0.1:3000
64
- Use Ctrl-C to stop
65
- ```
66
-
67
- ### Releasing new versions
68
-
69
- Please refer to the [dedicated page](https://github.com/solidusio/solidus/wiki/How-to-release-extensions) in the Solidus wiki.
70
-
71
- ## License
72
-
73
- Copyright (c) 2023 ulysses-bull, released under the New BSD License.
@@ -0,0 +1,23 @@
1
+ module SolidusMp
2
+
3
+ class CardPaymentSource < Spree::PaymentSource
4
+
5
+ def actions
6
+ %w(capture void credit)
7
+ end
8
+
9
+ def can_capture?(payment)
10
+ payment.pending? || payment.checkout?
11
+ end
12
+
13
+ def can_void?(payment)
14
+ payment.can_void?
15
+ end
16
+
17
+ def can_credit?(payment)
18
+ payment.completed? && payment.credit_allowed > 0
19
+ end
20
+
21
+ end
22
+
23
+ end
@@ -0,0 +1,69 @@
1
+ module SolidusMp
2
+ class MpCard < Spree::PaymentMethod
3
+
4
+ preference :public_key, :string
5
+ preference :access_token, :string
6
+ preference :callback_url, :string
7
+
8
+ def payment_source_class
9
+ CardPaymentSource
10
+ end
11
+
12
+ def gateway_class
13
+ "MpCard"
14
+ end
15
+
16
+ def supports?(source)
17
+ source.is_a?(payment_source_class)
18
+ end
19
+
20
+ def create_api_payment payment
21
+ begin
22
+ MpApi.configuration.access_token = preferences[:access_token]
23
+ mp_payment = MpApi::Payment.new(amount: payment.amount.to_f, payment_method: payment.source.credit_card_brand, payer_email: payment.source.email, payer_identification_type: payment.source.payer_identification_type, payer_identification_number: payment.source.tax_id, token: payment.source.token, issuer_id: payment.source.issuer_id, installments: payment.source.installments, three_d_secure_mode: true).create
24
+ payment.source.update(external_id: mp_payment.id, three_ds_url: mp_payment.three_ds_info_external_resource_url, three_ds_creq: mp_payment.three_ds_info_creq)
25
+ rescue MpApi::TooManyRequestsError
26
+ payment.invalidate
27
+ end
28
+ end
29
+
30
+ def authorize(money, source, options = {})
31
+ purchase(money, source, options)
32
+ end
33
+
34
+ def purchase(money, source, options = {})
35
+ MpApi.configuration.access_token = preferences[:access_token]
36
+ mp_payment = MpApi::Payment.find_by_id(source.external_id)
37
+ 10.times do
38
+ break if ["approved", "rejected"].include? mp_payment.status
39
+ mp_payment = MpApi::Payment.find_by_id(source.external_id)
40
+ end
41
+ if mp_payment.status == "approved"
42
+ successful_response("Transaction Accredited", mp_payment.id)
43
+ else
44
+ failure_response(mp_payment.status_detail || mp_payment.status)
45
+ end
46
+ end
47
+
48
+ def partial_name
49
+ 'mercado_pago_card'
50
+ end
51
+
52
+ def successful_response message, transaction_id
53
+ ActiveMerchant::Billing::Response.new(
54
+ true,
55
+ message,
56
+ {},
57
+ authorization: transaction_id
58
+ )
59
+ end
60
+
61
+ def failure_response message
62
+ ActiveMerchant::Billing::Response.new(
63
+ false,
64
+ message
65
+ )
66
+ end
67
+
68
+ end
69
+ end
@@ -0,0 +1,65 @@
1
+ module SolidusMp
2
+ class MpPix < Spree::PaymentMethod
3
+
4
+ preference :public_key, :string
5
+ preference :access_token, :string
6
+ preference :callback_url, :string
7
+
8
+ def payment_source_class
9
+ PixPaymentSource
10
+ end
11
+
12
+ def gateway_class
13
+ "MpPix"
14
+ end
15
+
16
+ def supports?(source)
17
+ source.is_a?(payment_source_class)
18
+ end
19
+
20
+ def create_api_payment payment
21
+ begin
22
+ MpApi.configuration.access_token = preferences[:access_token]
23
+ mp_payment = MpApi::Payment.new(payer_email: payment.source.email, payer_identification_type: "CPF", payment_method: "pix", payer_identification_number: payment.source.tax_id, amount: payment.amount.to_f).create
24
+ payment.source.update(external_id: mp_payment.id, qr_code: mp_payment.qr_code, qr_code_base64: mp_payment.qr_code_base_64, ticket_url: mp_payment.ticket_url)
25
+ rescue MpApi::TooManyRequestsError
26
+ payment.invalidate
27
+ end
28
+ end
29
+
30
+ def authorize(money, source, options = {})
31
+ purchase(money, source, options)
32
+ end
33
+
34
+ def purchase(money, source, options = {})
35
+ MpApi.configuration.access_token = preferences[:access_token]
36
+ mp_payment = MpApi::Payment.find_by_id(source.external_id)
37
+ if mp_payment.status == "approved"
38
+ successful_response("Transaction Accredited", mp_payment.id)
39
+ else
40
+ failure_response(mp_payment.status_detail || mp_payment.status)
41
+ end
42
+ end
43
+
44
+ def partial_name
45
+ 'mercado_pago_pix'
46
+ end
47
+
48
+ def successful_response message, transaction_id
49
+ ActiveMerchant::Billing::Response.new(
50
+ true,
51
+ message,
52
+ {},
53
+ authorization: transaction_id
54
+ )
55
+ end
56
+
57
+ def failure_response message
58
+ ActiveMerchant::Billing::Response.new(
59
+ false,
60
+ message
61
+ )
62
+ end
63
+
64
+ end
65
+ end
@@ -0,0 +1,23 @@
1
+ module SolidusMp
2
+
3
+ class PixPaymentSource < Spree::PaymentSource
4
+
5
+ def actions
6
+ %w(capture void credit)
7
+ end
8
+
9
+ def can_capture?(payment)
10
+ payment.pending? || payment.checkout?
11
+ end
12
+
13
+ def can_void?(payment)
14
+ payment.can_void?
15
+ end
16
+
17
+ def can_credit?(payment)
18
+ payment.completed? && payment.credit_allowed > 0
19
+ end
20
+
21
+ end
22
+
23
+ end
@@ -0,0 +1,15 @@
1
+ class CreateSolidusMpPixPaymentSources < ActiveRecord::Migration[7.0]
2
+ def change
3
+ create_table :solidus_mp_pix_payment_sources do |t|
4
+ t.string :external_id
5
+ t.string :email
6
+ t.string :tax_id
7
+ t.integer :payment_method_id
8
+ t.string :qr_code
9
+ t.text :qr_code_base64
10
+ t.string :ticket_url
11
+
12
+ t.timestamps
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,21 @@
1
+ class CreateSolidusMpCardPaymentSources < ActiveRecord::Migration[7.0]
2
+ def change
3
+ create_table :solidus_mp_card_payment_sources do |t|
4
+ t.string :external_id
5
+ t.string :payer_identification_type
6
+ t.string :tax_id
7
+ t.string :email
8
+ t.string :card_holder_name
9
+ t.string :issuer_id
10
+ t.integer :installments
11
+ t.string :token
12
+ t.string :three_ds_mode
13
+ t.string :three_ds_url
14
+ t.string :three_ds_creq
15
+ t.string :credit_card_brand
16
+ t.integer :payment_method_id
17
+
18
+ t.timestamps
19
+ end
20
+ end
21
+ end
@@ -10,6 +10,10 @@ module SolidusMp
10
10
  true
11
11
  end
12
12
 
13
+ def pin_mp_js
14
+ run 'bin/importmap pin @mercadopago/sdk-js'
15
+ end
16
+
13
17
  def copy_initializer
14
18
  template 'initializer.rb', 'config/initializers/solidus_mp.rb'
15
19
  end
@@ -18,6 +22,15 @@ module SolidusMp
18
22
  run 'bin/rails railties:install:migrations FROM=solidus_mp'
19
23
  end
20
24
 
25
+ def install_mp_api
26
+ puts 'Installing mp_api gem...'
27
+ run 'bin/rails g mp_api:install'
28
+ end
29
+
30
+ def copy_app_files
31
+ directory 'app', 'app'
32
+ end
33
+
21
34
  def run_migrations
22
35
  run_migrations = options[:auto_run_migrations] || ['', 'y', 'Y'].include?(ask('Would you like to run the migrations now? [Y/n]')) # rubocop:disable Layout/LineLength
23
36
  if run_migrations
@@ -0,0 +1,220 @@
1
+ import { Controller } from "@hotwired/stimulus"
2
+ import { loadMercadoPago } from "@mercadopago/sdk-js"
3
+
4
+ // Connects to data-controller="credit-card"
5
+ export default class extends Controller {
6
+
7
+ static values = { publicKey: String }
8
+ static targets = ["formCardNumber", "formExpirationDate", "formSecurityCode", "formIssuer", "formInstallments", "paymentMethodId", "paymentMethodThumbnail", "formDocumentType", "formCardHolderName"]
9
+
10
+ // Anytime the controller is connected to the DOM
11
+ async connect() {
12
+ await loadMercadoPago()
13
+ this.mp = new window.MercadoPago('TEST-dc17baa6-3344-4382-af3f-15d37f3ce4ae')
14
+ // estilos dos iframes
15
+ const styles = {
16
+ style: {
17
+ height: "1.5rem",
18
+ padding: "0px",
19
+ margin: "0px",
20
+ fontFamily: "Inter",
21
+ placeholderColor: "#9C99AF",
22
+ fontSize: "1rem"
23
+ },
24
+ customFonts: [
25
+ {
26
+ src: "https://rsms.me/inter/inter.css",
27
+ },
28
+ ]
29
+ }
30
+
31
+ // iframe numero cartao
32
+ const cardNumberElement = this.createIframe('cardNumber', "Número do cartão", styles, 'formCardNumber')
33
+ const expirationDateElement = this.createIframe('expirationDate', "MM/AA", styles, 'formExpirationDate')
34
+ const securityCodeElement = this.createIframe('securityCode', "Código de segurança", styles, 'formSecurityCode')
35
+ let currentBin
36
+ cardNumberElement.on('binChange', async (data) => {
37
+ const { bin } = data
38
+ try {
39
+ if (!bin && this.paymentMethodIdTarget.value) {
40
+ this.clearSelectsAndSetPlaceholders("Banco emissor", "Parcelas")
41
+ this.paymentMethodIdTarget.value = ""
42
+ }
43
+
44
+ if (bin && bin !== currentBin) {
45
+ const { results } = await this.mp.getPaymentMethods({ bin })
46
+ const paymentMethod = results[0]
47
+ this.paymentMethodIdTarget.value = paymentMethod.id
48
+ this.paymentMethodThumbnailTarget.setAttribute('src', paymentMethod.secure_thumbnail)
49
+ this.updatePCIFieldsSettings(paymentMethod, cardNumberElement, securityCodeElement)
50
+ this.updateIssuer(paymentMethod, bin)
51
+ this.updateInstallments(bin)
52
+ }
53
+
54
+ currentBin = bin
55
+ } catch (e) {
56
+ console.error('error getting payment methods: ', e)
57
+ }
58
+ })
59
+
60
+ cardNumberElement.on('focus', this.onFocus(this.formCardNumberTarget))
61
+ cardNumberElement.on('blur', this.onBlur(this.formCardNumberTarget))
62
+
63
+ expirationDateElement.on('focus', this.onFocus(this.formExpirationDateTarget))
64
+ expirationDateElement.on('blur', this.onBlur(this.formExpirationDateTarget))
65
+
66
+ securityCodeElement.on('focus', this.onFocus(this.formSecurityCodeTarget))
67
+ securityCodeElement.on('blur', this.onBlur(this.formSecurityCodeTarget))
68
+ await this.getIdentificationTypes()
69
+
70
+ document.getElementById('checkout_form_payment').addEventListener('submit', e => {
71
+ if (this.formCardHolderNameTarget.value === "") return
72
+ this.createCardToken(e, this.mp)
73
+ })
74
+
75
+ }
76
+
77
+ createIframe(inputName, placeholder, Styles, divId){
78
+ const element = this.mp.fields.create(inputName, {
79
+ placeholder: placeholder,
80
+ ...Styles
81
+ }).mount(divId)
82
+ return element
83
+ }
84
+
85
+ onFocus(divElement) {
86
+ return function (event) {
87
+ divElement.setAttribute('data-focus', 'true')
88
+ }
89
+ }
90
+
91
+ onBlur(divElement) {
92
+ return function (event) {
93
+ divElement.removeAttribute('data-focus')
94
+ }
95
+ }
96
+
97
+ async getIdentificationTypes() {
98
+ try {
99
+ const identificationTypes = await this.mp.getIdentificationTypes()
100
+
101
+ this.createSelectOptions(this.formDocumentTypeTarget, identificationTypes)
102
+ } catch (e) {
103
+ return console.error('Error getting identificationTypes: ', e)
104
+ }
105
+ }
106
+
107
+ createSelectOptions(elem, options, labelsAndKeys = { label: "name", value: "id" }) {
108
+ const { label, value } = labelsAndKeys
109
+
110
+ elem.options.length = 0
111
+
112
+ const tempOptions = document.createDocumentFragment()
113
+
114
+ options.forEach(option => {
115
+ const optValue = option[value]
116
+ const optLabel = option[label]
117
+
118
+ const opt = document.createElement('option')
119
+ opt.value = optValue
120
+ opt.textContent = optLabel
121
+
122
+ tempOptions.appendChild(opt)
123
+ })
124
+
125
+ elem.appendChild(tempOptions)
126
+ }
127
+
128
+ clearSelectsAndSetPlaceholders(issuerPlaceholder, installmentsPlaceholder) {
129
+ clearHTMLSelectChildrenFrom(this.formIssuerTarget)
130
+ createSelectElementPlaceholder(this.formIssuerTarget, issuerPlaceholder)
131
+
132
+ clearHTMLSelectChildrenFrom(this.formInstallmentsTarget)
133
+ createSelectElementPlaceholder(this.formInstallmentsTarget, installmentsPlaceholder)
134
+ }
135
+
136
+ clearHTMLSelectChildrenFrom(element) {
137
+ const currOptions = [...element.children]
138
+ currOptions.forEach(child => child.remove())
139
+ }
140
+
141
+ createSelectElementPlaceholder(element, placeholder) {
142
+ const optionElement = document.createElement('option')
143
+ optionElement.textContent = placeholder
144
+ optionElement.setAttribute('selected', "")
145
+ optionElement.setAttribute('disabled', "")
146
+
147
+ element.appendChild(optionElement)
148
+ }
149
+
150
+ updatePCIFieldsSettings(paymentMethod, cardNumberElement, securityCodeElement) {
151
+ const { settings } = paymentMethod
152
+
153
+ const cardNumberSettings = settings[0].card_number
154
+ cardNumberElement.update({
155
+ settings: cardNumberSettings
156
+ })
157
+
158
+ const securityCodeSettings = settings[0].security_code
159
+ securityCodeElement.update({
160
+ settings: securityCodeSettings
161
+ })
162
+ }
163
+
164
+ async updateIssuer(paymentMethod, bin) {
165
+ const { additional_info_needed, issuer } = paymentMethod
166
+ let issuerOptions = [issuer]
167
+
168
+ if (additional_info_needed.includes('issuer_id')) {
169
+ issuerOptions = await getIssuers(paymentMethod, bin)
170
+ }
171
+
172
+ this.createSelectOptions(this.formIssuerTarget, issuerOptions)
173
+ }
174
+
175
+ async getIssuers(paymentMethod, bin) {
176
+ try {
177
+ const { id: paymentMethodId } = paymentMethod
178
+ return await this.mp.getIssuers({ paymentMethodId, bin })
179
+ } catch (e) {
180
+ console.error('error getting issuers: ', e)
181
+ }
182
+ }
183
+
184
+ async updateInstallments(bin) {
185
+ try {
186
+ const installments = await this.mp.getInstallments({
187
+ amount: document.getElementById('transactionAmount').value,
188
+ bin,
189
+ paymentTypeId: 'credit_card'
190
+ });
191
+ const installmentOptions = installments[0].payer_costs;
192
+ const installmentOptionsKeys = { label: 'recommended_message', value: 'installments' };
193
+ this.createSelectOptions(this.formInstallmentsTarget, installmentOptions, installmentOptionsKeys);
194
+ } catch (error) {
195
+ console.error('error getting installments: ', error)
196
+ }
197
+ }
198
+
199
+ async createCardToken(event, mp) {
200
+ try {
201
+ const tokenElement = document.getElementById('token');
202
+ if (!tokenElement.value) {
203
+ const formElement = document.getElementById('checkout_form_payment');
204
+ event.preventDefault();
205
+ const token = await mp.fields.createCardToken({
206
+ cardholderName: document.getElementById('formCardHolderName').value,
207
+ identificationType: document.getElementById('formDocumentType').value,
208
+ identificationNumber: document.getElementById('tax_id').value,
209
+ });
210
+ tokenElement.value = token.id;
211
+ formElement.submit();
212
+ } else {
213
+ formElement.submit();
214
+ }
215
+ } catch (e) {
216
+ console.error('error creating card token: ', e)
217
+ }
218
+ }
219
+
220
+ }
@@ -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,2 @@
1
+ <div class='w-full' data-controller="three-ds" data-three-ds-three-ds-url-value="<%= payment_source.three_ds_url %>" data-three-ds-three-ds-creq-value="<%= payment_source.three_ds_creq %>">
2
+ </div>
@@ -0,0 +1,29 @@
1
+ <div class="flex justify-between flex-col sm:flex-row gap-5">
2
+ <div>
3
+ <h2 class="text-3xl text-green-700"><%= number_to_currency(@order.total) %></h2>
4
+ <a href="<%= payment_source&.ticket_url %>" target="_blank" class=" text-indigo-800 hover:text-indigo-600">Ver no Mercado Pago→</a>
5
+
6
+ <div>
7
+ <div>
8
+ <div class=" relative mt-2 inline-block items-center hover:text-indigo-600">
9
+ <input type="text" class="rounded-md border-0 py-1.5 pr-14 shadow-sm ring-1 ring-inset ring-gray-300 focus:ring-2 focus:ring-inset sm:text-sm sm:leading-6" value="<%= payment_source&.qr_code %>" disabled />
10
+ <div class="absolute inset-y-0 right-0 flex py-1.5 pr-1.5 ">
11
+ <div class=" w-9">
12
+ <svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" class="h-full">
13
+ <path stroke-linecap="round" stroke-linejoin="round" d="M8.25 7.5V6.108c0-1.135.845-2.098 1.976-2.192.373-.03.748-.057 1.123-.08M15.75 18H18a2.25 2.25 0 002.25-2.25V6.108c0-1.135-.845-2.098-1.976-2.192a48.424 48.424 0 00-1.123-.08M15.75 18.75v-1.875a3.375 3.375 0 00-3.375-3.375h-1.5a1.125 1.125 0 01-1.125-1.125v-1.5A3.375 3.375 0 006.375 7.5H5.25m11.9-3.664A2.251 2.251 0 0015 2.25h-1.5a2.251 2.251 0 00-2.15 1.586m5.8 0c.065.21.1.433.1.664v.75h-6V4.5c0-.231.035-.454.1-.664M6.75 7.5H4.875c-.621 0-1.125.504-1.125 1.125v12c0 .621.504 1.125 1.125 1.125h9.75c.621 0 1.125-.504 1.125-1.125V16.5a9 9 0 00-9-9z" />
14
+ </svg>
15
+ </div>
16
+ </div>
17
+ </div>
18
+ </div>
19
+ </div>
20
+ <div>
21
+ <%# button_to "Atualizar status", "", method: :patch, class: "mt-4 bg-indigo-600 hover:bg-indigo-500 text-white font-bold py-2 px-4 rounded" %>
22
+ </div>
23
+ </div>
24
+
25
+ </div>
26
+
27
+ <div class="flex justify-center">
28
+ <img class="w-80" src="data:image/jpeg;base64,<%= payment_source&.qr_code_base64 %>" />
29
+ </div>
@@ -0,0 +1,51 @@
1
+ <div data-controller="credit-card" >
2
+
3
+ <!-- Numero do cartao -->
4
+ <div class="relative mt-2 flex items-center">
5
+ <div data-credit-card-target="formCardNumber" id="formCardNumber" class="h-[2.125rem] pt-1 px-3 border-[#6b7280] w-full rounded-md border-0 text-gray-900 shadow-sm ring-1 ring-inset ring-gray-300 data-[focus=true]:ring-2 data-[focus=true]:ring-inset data-[focus=true]:ring-indigo-600 sm:text-sm sm:leading-6 bg-white"></div>
6
+ <div class="absolute inset-y-0 right-0 flex py-1.5 pr-1.5">
7
+ <img data-credit-card-target="paymentMethodThumbnail" id= "paymentMethodThumbnail" src="" class="inline-flex items-center rounded px-1">
8
+ </div>
9
+ </div>
10
+
11
+ <!-- data de expiração -->
12
+ <div data-credit-card-target="formExpirationDate" id="formExpirationDate" class="h-[2.125rem] pt-1 px-3 border-[#6b7280] w-full rounded-md border-0 text-gray-900 shadow-sm ring-1 ring-inset ring-gray-300 data-[focus=true]:ring-2 data-[focus=true]:ring-inset data-[focus=true]:ring-indigo-600 sm:text-sm sm:leading-6 bg-white"></div>
13
+
14
+ <!-- codigo de seguranca -->
15
+ <div data-credit-card-target="formSecurityCode" id="formSecurityCode" class="h-[2.125rem] pt-1 px-3 border-[#6b7280] w-full rounded-md border-0 text-gray-900 shadow-sm ring-1 ring-inset ring-gray-300 data-[focus=true]:ring-2 data-[focus=true]:ring-inset data-[focus=true]:ring-indigo-600 sm:text-sm sm:leading-6 bg-white"></div>
16
+
17
+ <!-- nome do titular -->
18
+ <div>
19
+ <input data-credit-card-target="formCardHolderName" id="formCardHolderName" name="payment_source[<%=payment_method.id%>][card_holder_name]" type="text" placeholder="Titular do cartão" class="block w-full rounded-md border-0 py-1.5 text-gray-900 shadow-sm ring-1 ring-inset ring-gray-300 placeholder:text-gray-300 focus:ring-2 focus:ring-inset focus:ring-indigo-600 sm:text-sm sm:leading-6">
20
+ </div>
21
+
22
+ <!-- Banco emissor -->
23
+ <select data-credit-card-target="formIssuer" id="formIssuer" name="payment_source[<%=payment_method.id%>][issuer_id]" class="hidden">
24
+ <option value="" disabled selected>Banco emissor</option>
25
+ </select>
26
+
27
+ <!-- Parcelas -->
28
+ <div>
29
+ <select data-credit-card-target="formInstallments" name="payment_source[<%=payment_method.id%>][installments]" id="formInstallments" class="block w-full rounded-md border-0 py-1.5 text-gray-900 shadow-sm ring-1 ring-inset ring-gray-300 placeholder:text-gray-300 focus:ring-2 focus:ring-inset focus:ring-indigo-600 sm:text-sm sm:leading-6">
30
+ <option value="" disabled selected>Parcelas</option>
31
+ </select>
32
+ </div>
33
+
34
+ <!-- CPF/CNPJ -->
35
+ <div class="relative rounded-md shadow-sm">
36
+ <div class="absolute inset-y-0 left-0 flex items-center">
37
+ <select data-credit-card-target="formDocumentType" name="payment_source[<%=payment_method.id%>][payer_identification_type]" id="formDocumentType" class="h-full rounded-md border-0 bg-transparent py-0 pl-3 pr-7 text-gray-500 focus:outline-none focus:ring-2 focus:ring-inset focus:ring-indigo-600 sm:text-sm">
38
+ </select>
39
+ </div>
40
+ <input type="text" id="tax_id" inputmode="numeric" placeholder="CPF/CNPJ" name="payment_source[<%=payment_method.id%>][tax_id]" class="block w-full rounded-md border-0 py-1.5 pl-20 text-gray-900 ring-1 ring-inset ring-gray-300 placeholder:text-gray-300 focus:outline-none focus:ring-2 focus:ring-inset focus:ring-indigo-600 sm:text-sm sm:leading-6">
41
+ </div>
42
+
43
+ <!--- Email -->
44
+ <div>
45
+ <input type="text" inputmode="numeric" placeholder="E-mail" name="payment_source[<%=payment_method.id%>][email]" class="block w-full rounded-md border-0 py-1.5 text-gray-900 shadow-sm ring-1 ring-inset ring-gray-300 placeholder:text-gray-300 focus:ring-2 focus:ring-inset focus:ring-indigo-600 sm:text-sm sm:leading-6">
46
+ </div>
47
+
48
+ <input id="token" name="payment_source[<%=payment_method.id%>][token]" type="hidden">
49
+ <input data-credit-card-target="paymentMethodId" id="paymentMethodId" name="payment_source[<%=payment_method.id%>][credit_card_brand]" type="hidden">
50
+ <input id="transactionAmount" name="transaction_amount" type="hidden" value="<%= @order.total.to_f %>">
51
+ </div>
@@ -0,0 +1,2 @@
1
+ <input type="text" name="payment_source[<%=payment_method.id%>][tax_id]" placeholder="CPF">
2
+ <input type="text" name="payment_source[<%=payment_method.id%>][email]" placeholder="E-mail">
@@ -11,6 +11,11 @@ module SolidusMp
11
11
 
12
12
  engine_name 'solidus_mp'
13
13
 
14
+ initializer "solidus_mp.add_payment_method", after: "spree.register.payment_methods" do |app|
15
+ app.config.spree.payment_methods << 'SolidusMp::MpCard'
16
+ app.config.spree.payment_methods << 'SolidusMp::MpPix'
17
+ end
18
+
14
19
  # use rspec for tests
15
20
  config.generators do |g|
16
21
  g.test_framework :rspec
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module SolidusMp
4
- VERSION = '0.0.1'
4
+ VERSION = '0.0.2'
5
5
  end
data/lib/solidus_mp.rb CHANGED
@@ -1,5 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require 'mp_api'
3
4
  require 'solidus_mp/configuration'
4
5
  require 'solidus_mp/version'
5
6
  require 'solidus_mp/engine'
data/solidus_mp.gemspec CHANGED
@@ -5,17 +5,17 @@ require_relative 'lib/solidus_mp/version'
5
5
  Gem::Specification.new do |spec|
6
6
  spec.name = 'solidus_mp'
7
7
  spec.version = SolidusMp::VERSION
8
- spec.authors = ['ulysses-bull']
9
- spec.email = 'contato7bulloleo@gmail.com'
8
+ spec.authors = ['caio']
9
+ spec.email = 'caioif4@gmail.com'
10
10
 
11
11
  spec.summary = ''
12
12
  spec.description = ''
13
- spec.homepage = 'https://github.com/ulysses-bull/solidus_mp#readme'
13
+ spec.homepage = 'https://github.com/CaioGarcia1/'
14
14
  spec.license = 'BSD-3-Clause'
15
15
 
16
16
  spec.metadata['homepage_uri'] = spec.homepage
17
- spec.metadata['source_code_uri'] = 'https://github.com/ulysses-bull/solidus_mp'
18
- spec.metadata['changelog_uri'] = 'https://github.com/ulysses-bull/solidus_mp/blob/master/CHANGELOG.md'
17
+ spec.metadata['source_code_uri'] = 'https://github.com/CaioGarcia1/'
18
+ spec.metadata['changelog_uri'] = 'https://github.com/CaioGarcia1/'
19
19
 
20
20
  spec.required_ruby_version = Gem::Requirement.new('>= 2.5', '< 4')
21
21
 
@@ -0,0 +1,7 @@
1
+ require 'rails_helper'
2
+
3
+ module SolidusMp
4
+ RSpec.describe CardPaymentSource, type: :model do
5
+ pending "add some examples to (or delete) #{__FILE__}"
6
+ end
7
+ end
@@ -0,0 +1,7 @@
1
+ require 'rails_helper'
2
+
3
+ module SolidusMp
4
+ RSpec.describe PixPaymentSource, type: :model do
5
+ pending "add some examples to (or delete) #{__FILE__}"
6
+ end
7
+ end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: solidus_mp
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.1
4
+ version: 0.0.2
5
5
  platform: ruby
6
6
  authors:
7
- - ulysses-bull
7
+ - caio
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2023-11-28 00:00:00.000000000 Z
11
+ date: 2023-12-05 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: solidus_core
@@ -73,7 +73,7 @@ dependencies:
73
73
  - !ruby/object:Gem::Version
74
74
  version: '2.7'
75
75
  description: ''
76
- email: contato7bulloleo@gmail.com
76
+ email: caioif4@gmail.com
77
77
  executables: []
78
78
  extensions: []
79
79
  extra_rdoc_files: []
@@ -90,6 +90,10 @@ files:
90
90
  - LICENSE
91
91
  - README.md
92
92
  - Rakefile
93
+ - app/models/solidus_mp/card_payment_source.rb
94
+ - app/models/solidus_mp/mp_card.rb
95
+ - app/models/solidus_mp/mp_pix.rb
96
+ - app/models/solidus_mp/pix_payment_source.rb
93
97
  - bin/console
94
98
  - bin/rails
95
99
  - bin/rails-engine
@@ -99,7 +103,15 @@ files:
99
103
  - bin/setup
100
104
  - config/locales/en.yml
101
105
  - config/routes.rb
106
+ - db/migrate/20231205142655_create_solidus_mp_pix_payment_sources.rb
107
+ - db/migrate/20231205142931_create_solidus_mp_card_payment_sources.rb
102
108
  - lib/generators/solidus_mp/install/install_generator.rb
109
+ - lib/generators/solidus_mp/install/templates/app/javascript/controllers/credit_card_controller.js
110
+ - lib/generators/solidus_mp/install/templates/app/javascript/controllers/three_ds_controller.js
111
+ - lib/generators/solidus_mp/install/templates/app/views/checkouts/confirm/_mercado_pago_card.html.erb
112
+ - lib/generators/solidus_mp/install/templates/app/views/checkouts/confirm/_mercado_pago_pix.html.erb
113
+ - lib/generators/solidus_mp/install/templates/app/views/checkouts/payment/_mercado_pago_card.html.erb
114
+ - lib/generators/solidus_mp/install/templates/app/views/checkouts/payment/_mercado_pago_pix.html.erb
103
115
  - lib/generators/solidus_mp/install/templates/initializer.rb
104
116
  - lib/solidus_mp.rb
105
117
  - lib/solidus_mp/configuration.rb
@@ -107,14 +119,16 @@ files:
107
119
  - lib/solidus_mp/testing_support/factories.rb
108
120
  - lib/solidus_mp/version.rb
109
121
  - solidus_mp.gemspec
122
+ - spec/models/solidus_mp/card_payment_source_spec.rb
123
+ - spec/models/solidus_mp/pix_payment_source_spec.rb
110
124
  - spec/spec_helper.rb
111
- homepage: https://github.com/ulysses-bull/solidus_mp#readme
125
+ homepage: https://github.com/CaioGarcia1/
112
126
  licenses:
113
127
  - BSD-3-Clause
114
128
  metadata:
115
- homepage_uri: https://github.com/ulysses-bull/solidus_mp#readme
116
- source_code_uri: https://github.com/ulysses-bull/solidus_mp
117
- changelog_uri: https://github.com/ulysses-bull/solidus_mp/blob/master/CHANGELOG.md
129
+ homepage_uri: https://github.com/CaioGarcia1/
130
+ source_code_uri: https://github.com/CaioGarcia1/
131
+ changelog_uri: https://github.com/CaioGarcia1/
118
132
  post_install_message:
119
133
  rdoc_options: []
120
134
  require_paths:
@@ -133,9 +147,11 @@ required_rubygems_version: !ruby/object:Gem::Requirement
133
147
  - !ruby/object:Gem::Version
134
148
  version: '0'
135
149
  requirements: []
136
- rubygems_version: 3.4.19
150
+ rubygems_version: 3.4.6
137
151
  signing_key:
138
152
  specification_version: 4
139
153
  summary: ''
140
154
  test_files:
155
+ - spec/models/solidus_mp/card_payment_source_spec.rb
156
+ - spec/models/solidus_mp/pix_payment_source_spec.rb
141
157
  - spec/spec_helper.rb