solidus_mp 0.0.1 → 0.0.2

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 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