vindi-rails 0.2.0 → 0.3.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.
data/WIKI.pt-BR.md CHANGED
@@ -1,246 +1,479 @@
1
- # Wiki do SDK Vindi
2
-
3
- [Read in English (WIKI.md)](./WIKI.md)
4
-
5
- Bem-vindo à Wiki do SDK `vindi-rails`. Este documento detalha todos os recursos mapeados, operações suportadas e guias de uso.
6
-
7
- ---
8
-
9
- ## 1. Design & Arquitetura do SDK
10
-
11
- O SDK utiliza o `RestClient` internamente para se comunicar com a API da Vindi.
12
- Os recursos são representados como objetos Ruby que herdam de `Vindi::Resource`. Os atributos retornados pela API são acessíveis através de métodos getter dinâmicos nas instâncias.
13
-
14
- ### Tratamento de Erros
15
-
16
- O SDK lança exceções específicas de acordo com os códigos de status HTTP retornados. Todos os erros herdam de `Vindi::Error`:
17
-
18
- - `Vindi::UnauthorizedError` (401)
19
- - `Vindi::ForbiddenError` (403)
20
- - `Vindi::NotFoundError` (404)
21
- - `Vindi::UnprocessableEntityError` (422)
22
- - `Vindi::RateLimitError` (429)
23
- - `Vindi::InternalServerError` (500+)
24
- - `Vindi::APIError` (Tratamento genérico para outros códigos HTTP)
25
-
26
- ---
27
-
28
- ## 2. Mapeamento de Recursos e Operações CRUD
29
-
30
- A tabela abaixo lista todos os recursos mapeados e suas operações disponíveis:
31
-
32
- | Classe do Recurso | Endpoint | Operações CRUD Habilitadas |
33
- | :--- | :--- | :--- |
34
- | `Vindi::Customer` | `customers` | `list`, `create`, `update`, `delete` |
35
- | `Vindi::PaymentProfile` | `payment_profiles` | `list`, `create`, `delete` |
36
- | `Vindi::Subscription` | `subscriptions` | `list`, `create`, `update`, `delete` |
37
- | `Vindi::Charge` | `charges` | `list`, `create`, `update` |
38
- | `Vindi::Plan` | `plans` | `list`, `create`, `update`, `delete` |
39
- | `Vindi::Product` | `products` | `list`, `create`, `update`, `delete` |
40
- | `Vindi::ProductItem` | `product_items` | `list`, `create`, `update`, `delete` |
41
- | `Vindi::Discount` | `discounts` | `list`, `create`, `delete` |
42
- | `Vindi::Bill` | `bills` | `list`, `create`, `update`, `delete` |
43
- | `Vindi::BillItem` | `bill_items` | `list` |
44
- | `Vindi::Period` | `periods` | `list` |
45
- | `Vindi::Transaction` | `transactions` | `list`, `create` |
46
- | `Vindi::Usage` | `usages` | `list`, `create`, `delete` |
47
- | `Vindi::Invoice` | `invoices` | `list` |
48
- | `Vindi::Movement` | `movements` | `list` |
49
- | `Vindi::Message` | `messages` | `list` |
50
- | `Vindi::ExportBatch` | `export_batches` | `list`, `create` |
51
- | `Vindi::ImportBatch` | `import_batches` | `list`, `create` |
52
- | `Vindi::Issue` | `issues` | `list`, `update` |
53
- | `Vindi::Notification` | `notifications` | `list` |
54
- | `Vindi::Merchant` | `merchants` | `list` |
55
- | `Vindi::MerchantUser` | `merchant_users` | `list` |
56
- | `Vindi::Role` | `roles` | `list` |
57
- | `Vindi::User` | `users` | `list` |
58
- | `Vindi::Public` | `public` | Nenhuma (Configuração Estática) |
59
- | `Vindi::Affiliate` | `affiliates` | `list` |
60
- | `Vindi::Partner` | `partner` | `list` |
61
-
62
- ---
63
-
64
- ## 3. Exemplos de Uso
65
-
66
- ### Clientes (`Vindi::Customer`)
67
-
68
- ```ruby
69
- # Criar um cliente
70
- cliente = Vindi::Customer.create(
71
- name: "João Silva",
72
- email: "joao@exemplo.com"
73
- )
74
-
75
- # Acessar atributos do retorno
76
- puts cliente.id
77
- puts cliente.name
78
-
79
- # Atualizar cliente
80
- atualizado = Vindi::Customer.update(cliente.id, email: "joao.novo@exemplo.com")
81
-
82
- # Excluir cliente
83
- Vindi::Customer.delete(cliente.id)
84
- ```
85
-
86
- ### Perfis de Pagamento (`Vindi::PaymentProfile`)
87
-
88
- ```ruby
89
- # Criar perfil de pagamento com cartão
90
- perfil = Vindi::PaymentProfile.create(
91
- customer_id: 12345,
92
- payment_company_code: "visa",
93
- holder_name: "JOAO SILVA",
94
- card_number: "4111111111111111",
95
- card_expiration_date: "12/2030",
96
- card_cvv: "123"
97
- )
98
-
99
- # Excluir perfil de pagamento
100
- Vindi::PaymentProfile.delete(perfil.id)
101
- ```
102
-
103
- ### Assinaturas (`Vindi::Subscription`)
104
-
105
- ```ruby
106
- # Criar assinatura
107
- assinatura = Vindi::Subscription.create(
108
- customer_id: cliente.id,
109
- plan_id: plano.id,
110
- payment_method_code: "credit_card"
111
- )
112
-
113
- # Cancelar/Excluir assinatura
114
- Vindi::Subscription.delete(assinatura.id)
115
- ```
116
-
117
- ### Cobranças (`Vindi::Charge`)
118
-
119
- ```ruby
120
- # Listar cobranças pendentes
121
- cobrancas = Vindi::Charge.list(status: "pending")
122
-
123
- # Obter valor da primeira cobrança
124
- puts cobrancas.first.amount
125
- ```
126
-
127
- ### Planos (`Vindi::Plan`)
128
-
129
- ```ruby
130
- # Criar um plano
131
- plano = Vindi::Plan.create(
132
- name: "Plano Ouro Premium",
133
- code: "gold_premium",
134
- interval: "months",
135
- interval_count: 1
136
- )
137
-
138
- # Listar planos
139
- planos = Vindi::Plan.list
140
- ```
141
-
142
- ### Produtos & Itens de Produto (`Vindi::Product` & `Vindi::ProductItem`)
143
-
144
- ```ruby
145
- # Criar um produto
146
- produto = Vindi::Product.create(
147
- name: "Serviço de Hospedagem",
148
- code: "hosting"
149
- )
150
-
151
- # Associar um produto a um plano/assinatura
152
- item_produto = Vindi::ProductItem.create(
153
- product_id: produto.id,
154
- plan_id: plano.id
155
- )
156
- ```
157
-
158
- ### Descontos (`Vindi::Discount`)
159
-
160
- ```ruby
161
- # Criar/aplicar um desconto
162
- desconto = Vindi::Discount.create(
163
- amount: 15.00,
164
- discount_type: "percentage",
165
- percentage: 10
166
- )
167
- ```
168
-
169
- ### Faturas & Itens de Fatura (`Vindi::Bill` & `Vindi::BillItem`)
170
-
171
- ```ruby
172
- # Criar uma fatura manualmente
173
- fatura = Vindi::Bill.create(
174
- customer_id: cliente.id,
175
- payment_method_code: "credit_card",
176
- bill_items: [
177
- { product_id: produto.id, amount: 99.90 }
178
- ]
179
- )
180
-
181
- # Listar itens de uma fatura
182
- itens = Vindi::BillItem.list(bill_id: fatura.id)
183
- ```
184
-
185
- ### Períodos (`Vindi::Period`)
186
-
187
- ```ruby
188
- # Listar períodos de uma assinatura
189
- periodos = Vindi::Period.list(subscription_id: assinatura.id)
190
- ```
191
-
192
- ### Transações (`Vindi::Transaction`)
193
-
194
- ```ruby
195
- # Criar uma transação manual (captura de cobrança)
196
- transacao = Vindi::Transaction.create(
197
- charge_id: cobranca.id,
198
- amount: 99.90
199
- )
200
-
201
- # Listar transações
202
- transacoes = Vindi::Transaction.list
203
- ```
204
-
205
- ### Consumos/Usos (`Vindi::Usage`)
206
-
207
- ```ruby
208
- # Informar consumo de uso de uma assinatura
209
- uso = Vindi::Usage.create(
210
- subscription_id: assinatura.id,
211
- quantity: 50,
212
- description: "Chamadas de API consumidas"
213
- )
214
-
215
- # Listar consumos informados
216
- usos = Vindi::Usage.list(subscription_id: assinatura.id)
217
- ```
218
-
219
- ### Notas Fiscais (`Vindi::Invoice`)
220
-
221
- ```ruby
222
- # Listar notas fiscais emitidas
223
- notas_fiscais = Vindi::Invoice.list(status: "issued")
224
- ```
225
-
226
- ### Problemas/Pendências (`Vindi::Issue`)
227
-
228
- ```ruby
229
- # Atualizar status de uma pendência (ex: marcar como resolvida)
230
- pendencia = Vindi::Issue.update(issue_id, status: "resolved")
231
- ```
232
-
233
- ### Lotes de Importação/Exportação (`Vindi::ImportBatch` & `Vindi::ExportBatch`)
234
-
235
- ```ruby
236
- # Iniciar lote para importação de clientes/assinaturas
237
- lote_importacao = Vindi::ImportBatch.create(
238
- batch_type: "customer",
239
- file_url: "https://exemplo.com/importacao.csv"
240
- )
241
-
242
- # Solicitar lote de exportação de dados
243
- lote_exportacao = Vindi::ExportBatch.create(
244
- batch_type: "bill"
245
- )
246
- ```
1
+ # Wiki do SDK Vindi
2
+
3
+ [Read in English (WIKI.md)](./WIKI.md)
4
+
5
+ Bem-vindo à Wiki do SDK `vindi-rails`. Este documento detalha todos os recursos mapeados, operações suportadas e guias de uso.
6
+
7
+ ---
8
+
9
+ ## 1. Design & Arquitetura do SDK
10
+
11
+ O SDK utiliza o `RestClient` internamente para se comunicar com a API da Vindi.
12
+ Os recursos são representados como objetos Ruby que herdam de `Vindi::Resource`. Os atributos retornados pela API são acessíveis através de métodos getter dinâmicos nas instâncias.
13
+
14
+ ### Tratamento de Erros
15
+
16
+ O SDK lança exceções específicas de acordo com os códigos de status HTTP retornados. Todos os erros herdam de `Vindi::Error`:
17
+
18
+ - `Vindi::UnauthorizedError` (401)
19
+ - `Vindi::ForbiddenError` (403)
20
+ - `Vindi::NotFoundError` (404)
21
+ - `Vindi::UnprocessableEntityError` (422)
22
+ - `Vindi::RateLimitError` (429)
23
+ - `Vindi::InternalServerError` (500+)
24
+ - `Vindi::APIError` (Tratamento genérico para outros códigos HTTP)
25
+
26
+ ---
27
+
28
+ ## 2. Mapeamento de Recursos e Operações CRUD
29
+
30
+ A tabela abaixo lista todos os recursos mapeados e suas operações disponíveis:
31
+
32
+ | Classe do Recurso | Endpoint | Operações CRUD Habilitadas |
33
+ | :--- | :--- | :--- |
34
+ | `Vindi::Customer` | `customers` | `list`, `create`, `update`, `delete` |
35
+ | `Vindi::PaymentProfile` | `payment_profiles` | `list`, `create`, `delete` |
36
+ | `Vindi::Subscription` | `subscriptions` | `list`, `create`, `update`, `delete` |
37
+ | `Vindi::Charge` | `charges` | `list`, `create`, `update` |
38
+ | `Vindi::Plan` | `plans` | `list`, `create`, `update`, `delete` |
39
+ | `Vindi::Product` | `products` | `list`, `create`, `update`, `delete` |
40
+ | `Vindi::ProductItem` | `product_items` | `list`, `create`, `update`, `delete` |
41
+ | `Vindi::Discount` | `discounts` | `list`, `create`, `delete` |
42
+ | `Vindi::Bill` | `bills` | `list`, `create`, `update`, `delete` |
43
+ | `Vindi::BillItem` | `bill_items` | `list` |
44
+ | `Vindi::Period` | `periods` | `list` |
45
+ | `Vindi::Transaction` | `transactions` | `list`, `create` |
46
+ | `Vindi::Usage` | `usages` | `list`, `create`, `delete` |
47
+ | `Vindi::Invoice` | `invoices` | `list` |
48
+ | `Vindi::Movement` | `movements` | `list` |
49
+ | `Vindi::Message` | `messages` | `list` |
50
+ | `Vindi::ExportBatch` | `export_batches` | `list`, `create` |
51
+ | `Vindi::ImportBatch` | `import_batches` | `list`, `create` |
52
+ | `Vindi::Issue` | `issues` | `list`, `update` |
53
+ | `Vindi::Notification` | `notifications` | `list` |
54
+ | `Vindi::Merchant` | `merchants` | `list` |
55
+ | `Vindi::MerchantUser` | `merchant_users` | `list` |
56
+ | `Vindi::Role` | `roles` | `list` |
57
+ | `Vindi::User` | `users` | `list` |
58
+ | `Vindi::Public` | `public` | Nenhuma (Configuração Estática) |
59
+ | `Vindi::Affiliate` | `affiliates` | `list` |
60
+ | `Vindi::Partner` | `partner` | `list` |
61
+
62
+ ---
63
+
64
+ ## 3. Exemplos de Uso
65
+
66
+ ### Clientes (`Vindi::Customer`)
67
+
68
+ ```ruby
69
+ # Criar um cliente
70
+ cliente = Vindi::Customer.create(
71
+ name: "João Silva",
72
+ email: "joao@exemplo.com"
73
+ )
74
+
75
+ # Criar um cliente com uma chave de idempotência (evita duplicados)
76
+ cliente = Vindi::Customer.create(
77
+ { name: "João Silva", email: "joao@exemplo.com" },
78
+ idempotency_key: "chave-unica-aqui"
79
+ )
80
+
81
+ # Acessar atributos do retorno
82
+ puts cliente.id
83
+ puts cliente.name
84
+
85
+ # Atualizar cliente
86
+ atualizado = Vindi::Customer.update(cliente.id, email: "joao.novo@exemplo.com")
87
+
88
+ # Excluir cliente
89
+ Vindi::Customer.delete(cliente.id)
90
+ ```
91
+
92
+ ### Perfis de Pagamento (`Vindi::PaymentProfile`)
93
+
94
+ ```ruby
95
+ # Criar perfil de pagamento com cartão
96
+ perfil = Vindi::PaymentProfile.create(
97
+ customer_id: 12345,
98
+ payment_company_code: "visa",
99
+ holder_name: "JOAO SILVA",
100
+ card_number: "4111111111111111",
101
+ card_expiration_date: "12/2030",
102
+ card_cvv: "123"
103
+ )
104
+
105
+ # Excluir perfil de pagamento
106
+ Vindi::PaymentProfile.delete(perfil.id)
107
+ ```
108
+
109
+ ### Assinaturas (`Vindi::Subscription`)
110
+
111
+ ```ruby
112
+ # Criar assinatura
113
+ assinatura = Vindi::Subscription.create(
114
+ customer_id: cliente.id,
115
+ plan_id: plano.id,
116
+ payment_method_code: "credit_card"
117
+ )
118
+
119
+ # Cancelar/Excluir assinatura
120
+ Vindi::Subscription.delete(assinatura.id)
121
+ ```
122
+
123
+ ### Cobranças (`Vindi::Charge`)
124
+
125
+ ```ruby
126
+ # Listar cobranças pendentes
127
+ cobrancas = Vindi::Charge.list(status: "pending")
128
+
129
+ # Obter valor da primeira cobrança
130
+ puts cobrancas.first.amount
131
+ ```
132
+
133
+ ### Planos (`Vindi::Plan`)
134
+
135
+ ```ruby
136
+ # Criar um plano
137
+ plano = Vindi::Plan.create(
138
+ name: "Plano Ouro Premium",
139
+ code: "gold_premium",
140
+ interval: "months",
141
+ interval_count: 1
142
+ )
143
+
144
+ # Listar planos
145
+ planos = Vindi::Plan.list
146
+ ```
147
+
148
+ ### Produtos & Itens de Produto (`Vindi::Product` & `Vindi::ProductItem`)
149
+
150
+ ```ruby
151
+ # Criar um produto
152
+ produto = Vindi::Product.create(
153
+ name: "Serviço de Hospedagem",
154
+ code: "hosting"
155
+ )
156
+
157
+ # Associar um produto a um plano/assinatura
158
+ item_produto = Vindi::ProductItem.create(
159
+ product_id: produto.id,
160
+ plan_id: plano.id
161
+ )
162
+ ```
163
+
164
+ ### Descontos (`Vindi::Discount`)
165
+
166
+ ```ruby
167
+ # Criar/aplicar um desconto
168
+ desconto = Vindi::Discount.create(
169
+ amount: 15.00,
170
+ discount_type: "percentage",
171
+ percentage: 10
172
+ )
173
+ ```
174
+
175
+ ### Faturas & Itens de Fatura (`Vindi::Bill` & `Vindi::BillItem`)
176
+
177
+ ```ruby
178
+ # Criar uma fatura manualmente
179
+ fatura = Vindi::Bill.create(
180
+ customer_id: cliente.id,
181
+ payment_method_code: "credit_card",
182
+ bill_items: [
183
+ { product_id: produto.id, amount: 99.90 }
184
+ ]
185
+ )
186
+
187
+ # Listar itens de uma fatura
188
+ itens = Vindi::BillItem.list(bill_id: fatura.id)
189
+ ```
190
+
191
+ ### Períodos (`Vindi::Period`)
192
+
193
+ ```ruby
194
+ # Listar períodos de uma assinatura
195
+ periodos = Vindi::Period.list(subscription_id: assinatura.id)
196
+ ```
197
+
198
+ ### Transações (`Vindi::Transaction`)
199
+
200
+ ```ruby
201
+ # Criar uma transação manual (captura de cobrança)
202
+ transacao = Vindi::Transaction.create(
203
+ charge_id: cobranca.id,
204
+ amount: 99.90
205
+ )
206
+
207
+ # Listar transações
208
+ transacoes = Vindi::Transaction.list
209
+ ```
210
+
211
+ ### Consumos/Usos (`Vindi::Usage`)
212
+
213
+ ```ruby
214
+ # Informar consumo de uso de uma assinatura
215
+ uso = Vindi::Usage.create(
216
+ subscription_id: assinatura.id,
217
+ quantity: 50,
218
+ description: "Chamadas de API consumidas"
219
+ )
220
+
221
+ # Listar consumos informados
222
+ usos = Vindi::Usage.list(subscription_id: assinatura.id)
223
+ ```
224
+
225
+ ### Notas Fiscais (`Vindi::Invoice`)
226
+
227
+ ```ruby
228
+ # Listar notas fiscais emitidas
229
+ notas_fiscais = Vindi::Invoice.list(status: "issued")
230
+ ```
231
+
232
+ ### Problemas/Pendências (`Vindi::Issue`)
233
+
234
+ ```ruby
235
+ # Atualizar status de uma pendência (ex: marcar como resolvida)
236
+ pendencia = Vindi::Issue.update(issue_id, status: "resolved")
237
+ ```
238
+
239
+ ### Lotes de Importação/Exportação (`Vindi::ImportBatch` & `Vindi::ExportBatch`)
240
+
241
+ ```ruby
242
+ # Iniciar lote para importação de clientes/assinaturas
243
+ lote_importacao = Vindi::ImportBatch.create(
244
+ batch_type: "customer",
245
+ file_url: "https://exemplo.com/importacao.csv"
246
+ )
247
+
248
+ # Solicitar lote de exportação de dados
249
+ lote_exportacao = Vindi::ExportBatch.create(
250
+ batch_type: "bill"
251
+ )
252
+ ```
253
+
254
+ ---
255
+
256
+ ## 4. Gems de Extensão Adicionais
257
+
258
+ Para manter a biblioteca core leve e livre de dependências acopladas, as features específicas do Rails são distribuídas por meio de gems complementares.
259
+
260
+ ### 4.1 Integrações de Backend ([`vindi-rails-integrations`](https://github.com/wesleyskap/vindi-rails-integrations))
261
+
262
+ Fornece sincronização automática de modelos do ActiveRecord, endpoints de webhook, jobs de processamento assíncrono e tarefas administrativas via Rake.
263
+
264
+ #### Instalação
265
+ Adicione a gem ao seu Gemfile:
266
+ ```ruby
267
+ gem 'vindi-rails-integrations'
268
+ ```
269
+
270
+ #### Configuração de Webhooks
271
+ Gere o controller de webhook e o manipulador correspondente na sua aplicação Rails:
272
+ ```bash
273
+ bundle exec rails generate vindi:webhook
274
+ ```
275
+
276
+ ##### 1. Webhooks Controller (`app/controllers/vindi/webhooks_controller.rb`)
277
+ Valida as notificações via POST enviadas pela Vindi comparando um token de segurança recebido via parâmetros.
278
+ - **Endpoint**: `POST /vindi/webhooks?token=SEU_TOKEN_SEGURO`
279
+ - **Resposta do Controller**: Retorna `{ "status": "received" }` com status `200 OK` em caso de sucesso, ou `{ "error": "Unauthorized access token" }` (`401 Unauthorized`) / `{ "error": "Invalid payload" }` (`400 Bad Request`).
280
+
281
+ ##### 2. Processamento Assíncrono (`app/jobs/vindi/webhook_job.rb`)
282
+ Processa os eventos em background. Inclui regras de segurança recomendadas, como a validação de idempotência.
283
+
284
+ ##### 3. Handlers Modulares de Webhooks
285
+ Para arquiteturas mais limpas, separe o processamento de cada tipo de evento em arquivos de serviço dedicados:
286
+ ```bash
287
+ bundle exec rails generate vindi:webhook_handler subscription_canceled
288
+ ```
289
+ Isso gera `app/services/vindi/webhooks/base_handler.rb` (classe base) e `app/services/vindi/webhooks/subscription_canceled_handler.rb`. O `WebhookJob` gerado descobrirá e despachará automaticamente para essas classes modulares de forma dinâmica.
290
+
291
+ ###### Exemplo de Payload de Webhook Vindi (Evento)
292
+ ```json
293
+ {
294
+ "event": {
295
+ "id": 1928374,
296
+ "type": "bill_paid",
297
+ "created_at": "2026-06-10T15:00:00.000-03:00",
298
+ "data": {
299
+ "bill": {
300
+ "id": 887766,
301
+ "amount": "150.00",
302
+ "status": "paid",
303
+ "customer": {
304
+ "id": 112233,
305
+ "name": "Jane Doe",
306
+ "email": "jane.doe@example.com",
307
+ "code": "user_42"
308
+ }
309
+ }
310
+ }
311
+ }
312
+ }
313
+ ```
314
+
315
+ #### Sincronização de ActiveRecord
316
+ Associe qualquer modelo ActiveRecord (ex: `User`, `Account`) para ser sincronizado automaticamente com os Clientes da Vindi.
317
+
318
+ ##### 1. Configuração do Gerador
319
+ Execute o gerador de sincronização para o seu modelo:
320
+ ```bash
321
+ bundle exec rails generate vindi:sync User
322
+ ```
323
+ Isso criará uma migração para adicionar a coluna `vindi_customer_id` (String) à tabela correspondente e incluirá o módulo `Vindi::Synchronizable`.
324
+
325
+ ##### 2. Uso & Sobrescrita de Atributos
326
+ Inclua o Concern `Vindi::Synchronizable` e customize o mapeamento de atributos se necessário:
327
+ ```ruby
328
+ class User < ApplicationRecord
329
+ include Vindi::Synchronizable
330
+
331
+ # Opcional: Personalizar os atributos enviados à Vindi
332
+ def vindi_customer_attributes
333
+ {
334
+ name: "#{first_name} #{last_name}",
335
+ email: email,
336
+ registry_code: cpf_ou_cnpj, # Se aplicável
337
+ code: "user_#{id}"
338
+ }
339
+ end
340
+ end
341
+ ```
342
+
343
+ Quando um registro do modelo for salvo, os seguintes gatilhos serão acionados:
344
+ - **Ao Criar**: Chama `Vindi::Customer.create` e salva o `vindi_customer_id` retornado diretamente no seu banco local.
345
+ - **Ao Atualizar**: Verifica se `name` ou `email` mudaram e chama `Vindi::Customer.update` para sincronizar os dados na Vindi.
346
+
347
+ ##### 3. Fila Outbox Transacional Resiliente (Opcional)
348
+ Para evitar requisições HTTP síncronas de rede dentro das suas transações de banco de dados locais e garantir maior resiliência:
349
+
350
+ 1. Gere a migração do outbox:
351
+ ```bash
352
+ bundle exec rails generate vindi:outbox
353
+ bundle exec rails db:migrate
354
+ ```
355
+ 2. Habilite-o no initializer de configuração:
356
+ ```ruby
357
+ Vindi.configure do |config|
358
+ config.use_outbox = true
359
+ end
360
+ ```
361
+ 3. Ao cadastrar/atualizar um registro local, as pendências são salvas na tabela `vindi_pending_syncs` na mesma transação local, e o job `Vindi::ProcessPendingSyncsJob` é disparado assincronamente após o commit para fazer a sincronização final.
362
+
363
+ #### Tarefas Rake (Rake Tasks)
364
+ A gem disponibiliza ferramentas para auditoria e teste de integração local:
365
+
366
+ ##### 1. Auditoria de Sincronização (`vindi:audit`)
367
+ Compara a base local do seu modelo com o cadastro de clientes da API da Vindi:
368
+ ```bash
369
+ bundle exec rake vindi:audit model=User
370
+ ```
371
+ **Exemplo de log de saída da auditoria:**
372
+ ```text
373
+ Analyzing User database...
374
+ [Audit] Checking User ID: 42 (Vindi ID: 112233) - Match found.
375
+ [Audit] Checking User ID: 43 (Vindi ID: nil) - Missing in Vindi!
376
+ [Audit Warning] User ID 43 created in Vindi with customer ID 112234.
377
+ Reconciliation complete. 1 missing records synchronized.
378
+ ```
379
+
380
+ ##### 2. Simulador de Webhook (`vindi:test_webhook`)
381
+ Envia uma requisição POST de teste simulando um evento da Vindi diretamente para o seu endpoint local:
382
+ ```bash
383
+ bundle exec rake vindi:test_webhook event=bill_paid url=http://localhost:3000/vindi/webhooks token=SEU_TOKEN_SEGURO
384
+ ```
385
+ **Exemplo de requisição enviada:**
386
+ ```text
387
+ Sending POST to http://localhost:3000/vindi/webhooks?token=SEU_TOKEN_SEGURO...
388
+ Payload: {"event":{"id":9999,"type":"bill_paid","data":{...}}}
389
+ Response Code: 200 OK
390
+ Response Body: {"status":"received"}
391
+ ```
392
+
393
+ ##### 3. Diagnóstico e Conectividade (`vindi:status`)
394
+ Verifica as credenciais configuradas na API, ambiente ativo e executa testes rápidos de conectividade em tempo real com mascaramento seguro:
395
+ ```bash
396
+ bundle exec rake vindi:status
397
+ ```
398
+ **Exemplo de log de status:**
399
+ ```text
400
+ === Vindi Integration Status ===
401
+ Environment: Sandbox
402
+ API URL: https://sandbox-gp.vindi.com.br/api/v1
403
+ API Key: *****2345
404
+ Webhook: *****_999
405
+ --------------------------------
406
+ Connectivity: SUCCESS
407
+ ================================
408
+ ```
409
+
410
+ ---
411
+
412
+ ### 4.2 Componentes Front-End ([`vindi-rails-engines`](https://github.com/wesleyskap/vindi-rails-engines))
413
+
414
+ Assets e templates prontos para captura de dados de pagamento seguros no navegador em conformidade com as regras PCI.
415
+
416
+ #### Instalação
417
+ Adicione a gem ao seu Gemfile:
418
+ ```ruby
419
+ gem 'vindi-rails-engines'
420
+ ```
421
+
422
+ #### Configuração do Checkout
423
+ Inicialize os templates HTML e controladores Stimulus JS:
424
+ ```bash
425
+ bundle exec rails generate vindi:checkout
426
+ ```
427
+
428
+ ##### 1. Controlador Stimulus JS (`app/javascript/controllers/vindi_checkout_controller.js`)
429
+ Intercepta a submissão do formulário, serializa os dados do cartão, comunica-se com o tokenizador JS da Vindi e injeta o token gerado em um campo oculto antes de enviar os dados ao Rails:
430
+ ```javascript
431
+ // Connects to data-controller="vindi-checkout"
432
+ import { Controller } from "@hotwired/stimulus"
433
+
434
+ export default class extends Controller {
435
+ static targets = [ "publicKey", "holderName", "cardNumber", "expiry", "cvv", "tokenInput" ]
436
+
437
+ tokenizeCard(event) {
438
+ event.preventDefault()
439
+ const vindi = new Vindi(this.publicKeyTarget.value)
440
+
441
+ vindi.createToken({
442
+ holder_name: this.holderNameTarget.value,
443
+ card_number: this.cardNumberTarget.value.replace(/\s+/g, ''),
444
+ card_expiration: this.expiryTarget.value,
445
+ card_cvv: this.cvvTarget.value
446
+ }).then((response) => {
447
+ // response: { token: "tok_abc123XYZ", created_at: "2026-06-10..." }
448
+ this.tokenInputTarget.value = response.token
449
+ this.element.submit()
450
+ }).catch((error) => {
451
+ alert("Erro de Tokenização: " + error.message)
452
+ })
453
+ }
454
+ }
455
+ ```
456
+
457
+ ##### 2. Exemplo de Resposta de Chave Pública da Vindi
458
+ Ao chamar `vindi.createToken(...)` com os dados do cartão, o SDK Javascript da Vindi retorna o token de perfil de pagamento:
459
+ ```json
460
+ {
461
+ "token": "tok_3278918239abc",
462
+ "created_at": "2026-06-10T16:50:00.000-03:00"
463
+ }
464
+ ```
465
+
466
+ Utilize este token (`payment_profile_token`) no seu controller Rails no backend para criar assinaturas ou transações com segurança:
467
+ ```ruby
468
+ # Exemplo de Controller processando o token do checkout
469
+ def charge
470
+ Vindi::Charge.create(
471
+ payment_method_code: "credit_card",
472
+ payment_profile: {
473
+ token: params[:payment_profile_token]
474
+ },
475
+ amount: "150.00",
476
+ customer_id: current_user.vindi_customer_id
477
+ )
478
+ end
479
+ ```