react-native-mesmart 3.0.0 → 3.0.1

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.
Files changed (2) hide show
  1. package/README.md +364 -103
  2. package/package.json +1 -1
package/README.md CHANGED
@@ -1,178 +1,439 @@
1
1
  # react-native-mesmart
2
2
 
3
- Métodos nativos para integrar com POS Sunmi P2-B/P2-A11, Pax A910/A920, SDK de pagamento Plugpag da Pagbank, SDK de pagamento da Stone e SDK de pagamento da Paystore.
3
+ Módulos nativos (Android) para POS usadas pela Beerpass: leitura de cartão RFID (Mifare), impressão térmica e SDKs de pagamento.
4
4
 
5
- - [Plugpag](https://developer.pagbank.com.br/v1.0/reference/smart-pos-introducao)
6
- - [Stone](https://sdkandroid.stone.com.br/reference/overview-da-sdk)
7
- - [Paystore](http://177.69.97.18:6655/)
5
+ | Módulo | Para que serve | Onde roda |
6
+ |---|---|---|
7
+ | [`Plugpag`](#plugpag-pagbank) | Pagamento PagBank (PlugPag) | POS PagBank |
8
+ | [`Stone`](#stone) | Pagamento Stone (SDK de providers) | POS Stone |
9
+ | [`Paystore`](#paystore) | Pagamento Paystore | POS com Paystore |
10
+ | [`Sunmi`](#sunmi-p2-b--p2-a11) | RFID e impressão | Sunmi P2-B, P2-A11 |
11
+ | [`Tectoy`](#tectoy-t8) | RFID e impressão | Tectoy T8 |
12
+ | [`Gertec`](#gertec-gpos780--gpos780s) | RFID e impressão | Gertec GPOS780, GPOS780S |
13
+ | [`Pax`](#pax-a910) | RFID e impressão | Pax A910 |
14
+
15
+ Referências dos SDKs: [PlugPag](https://developer.pagbank.com.br/v1.0/reference/smart-pos-introducao) · [Stone](https://sdkandroid.stone.com.br/reference/bem-vindo-sdk-android) · [Paystore](http://177.69.97.18:6655/)
16
+
17
+ > Só Android. Importar no iOS lança `IOS_ERROR`.
18
+
19
+ ## Sumário
20
+
21
+ - [Compatibilidade](#compatibilidade)
22
+ - [Instalação](#instalação)
23
+ - [Configuração do app Android](#configuração-do-app-android)
24
+ - [Qual APK para qual POS](#qual-apk-para-qual-pos)
25
+ - [API](#api)
26
+ - [Eventos](#eventos)
27
+ - [Formato do RFID](#formato-do-rfid)
28
+ - [App de exemplo](#app-de-exemplo)
29
+ - [Migrando da 2.x para a 3.x](#migrando-da-2x-para-a-3x)
30
+ - [Publicando uma versão](#publicando-uma-versão)
31
+
32
+ ## Compatibilidade
33
+
34
+ | react-native-mesmart | SDK Stone | React Native | Toolchain Android |
35
+ |---|---|---|---|
36
+ | **3.x** | 4.20.16 | **≥ 0.80** (arquitetura antiga, `newArchEnabled=false`) | AGP ≥ 8.6, Gradle 8.14, compileSdk 35, JDK 17, Kotlin ≥ 2.1, minSdk 24 |
37
+ | 2.x | 4.12.0 | 0.72 | AGP 7.4, compileSdk 33, JDK 11 |
38
+
39
+ A 3.x exige RN ≥ 0.80 porque o SDK Stone 4.20 traz dependências compiladas em Kotlin 2.2, que só um compilador Kotlin 2.1 consegue ler. O RN 0.80 é o primeiro com Kotlin 2.1.
8
40
 
9
41
  ## Instalação
10
42
 
11
43
  ```sh
12
- npm install react-native-mesmart
44
+ yarn add react-native-mesmart
13
45
  ```
14
46
 
15
- OU
47
+ ou
16
48
 
17
49
  ```sh
18
- yarn add react-native-mesmart
50
+ npm install react-native-mesmart
19
51
  ```
20
52
 
21
- ## Configurações para Sunmi P2
22
-
23
- Adicione a seguinte permissão no AndroidManifest do seu app
53
+ ## Configuração do app Android
24
54
 
25
- ```
26
- <uses-permission android:name="com.sunmi.perm.CONTACTLESS_CARD" />
27
- ```
55
+ O [app de exemplo](example/android) está configurado assim e serve de referência completa.
28
56
 
29
- ## Configurações para Pax A910/A920
57
+ ### 1. Repositórios Maven
30
58
 
31
- Adicione as seguintes permissões no AndroidManifest do seu app
59
+ O SDK da Stone e o SDK da Sunmi vêm do repositório privado da Stone no packagecloud. O token é fornecido pela Stone. Coloque-o no `android/local.properties` do app, que não vai para o git:
32
60
 
33
- ```
34
- <uses-permission android:name="com.pax.permission.PICC" />
35
- <uses-permission android:name="com.pax.permission.PRINTER" />
61
+ ```properties
62
+ packageCloudReadToken=SEU_TOKEN
36
63
  ```
37
64
 
38
- Adicione essas configurações em android/app/build.gradle do seu app
65
+ Também é aceito pela variável de ambiente `PACKAGECLOUD_READ_TOKEN`, útil em CI.
39
66
 
40
- ```
41
- android {
42
- ...
43
- defaultConfig {
44
- ...
45
- ndk {
46
- abiFilters "armeabi-v7a"
47
- }
67
+ `android/build.gradle`:
68
+
69
+ ```gradle
70
+ buildscript {
71
+ ext {
72
+ // ...
73
+ compileSdkVersion = 35
74
+ stone_sdk_version = "4.20.16" // lido pela lib e pelos flavors do app
75
+
76
+ localProp = new Properties()
77
+ localProp.load(new FileInputStream(rootProject.file('local.properties')))
78
+ stoneToken = System.env.PACKAGECLOUD_READ_TOKEN ?: (localProp["packageCloudReadToken"] ?: "")
48
79
  }
49
- ...
50
- packagingOptions {
51
- jniLibs {
52
- useLegacyPackaging true
80
+ }
81
+
82
+ allprojects {
83
+ repositories {
84
+ mavenCentral()
85
+ // O GitHub responde 504 para artefatos que não existem e o Gradle aborta;
86
+ // por isso este repo fica restrito ao grupo do PlugPag.
87
+ maven {
88
+ url 'https://github.com/pagseguro/PlugPagServiceWrapper/raw/master'
89
+ content { includeGroupByRegex 'br\\.com\\.uol\\.pagseguro.*' }
53
90
  }
91
+ maven { url "https://packagecloud.io/priv/${stoneToken}/stone/pos-android/maven2" }
92
+ google()
54
93
  }
55
94
  }
56
95
  ```
57
96
 
58
- Crie um diretório android/app/src/main/jniLibs/armeabi-v7 e adicione o arquivo 'libDeviceConfig.so' que está presente no exemplo dessa biblioteca
97
+ ### 2. Um flavor por POS (HAL da Stone)
59
98
 
60
- ## Configurações para SDK Plugpag
99
+ Cada fabricante tem um HAL (driver) próprio no SDK da Stone. Na 4.20, os HALs da Sunmi e da Tectoy usam versões incompatíveis da mesma biblioteca e **não cabem no mesmo APK**. A lib não embute nenhum HAL: o app escolhe por product flavor, que é o modelo que a [documentação da Stone](https://sdkandroid.stone.com.br/reference/processo-de-build-de-aplicação.md) adota.
61
100
 
62
- Adicione a seguinte permissão no AndroidManifest do seu app
101
+ `android/app/build.gradle`:
63
102
 
64
- ```
65
- <uses-permission android:name="br.com.uol.pagseguro.permission.MANAGE_PAYMENTS" />
66
- ```
103
+ ```gradle
104
+ react {
105
+ // Com flavors, as variantes debug passam a ter o nome do flavor.
106
+ debuggableVariants = ["pagbankDebug", "sunmiDebug", "tectoyDebug"]
107
+ }
67
108
 
68
- Adicione essa configuração em android/build.gradle do seu app
109
+ android {
110
+ defaultConfig {
111
+ ndk { abiFilters "armeabi-v7a" } // todas as POS suportadas são 32 bits
112
+ }
69
113
 
70
- ```
71
- allprojects {
72
- repositories {
73
- ...
74
- maven {
75
- url 'https://github.com/pagseguro/PlugPagServiceWrapper/raw/master'
76
- }
114
+ flavorDimensions = ["pos"]
115
+ productFlavors {
116
+ pagbank {} // PagBank: sem HAL da Stone
117
+ sunmi {} // Stone em Sunmi P2-B / P2-A11
118
+ tectoy {} // Stone em Tectoy T8
119
+ }
120
+
121
+ compileOptions {
122
+ coreLibraryDesugaringEnabled true // exigido pelo SDK Stone 4.20
123
+ }
124
+
125
+ packagingOptions {
126
+ jniLibs { useLegacyPackaging true }
77
127
  }
78
128
  }
79
- ```
80
129
 
81
- ## Configurações para SDK Stone
130
+ dependencies {
131
+ coreLibraryDesugaring("com.android.tools:desugar_jdk_libs:2.1.5")
82
132
 
83
- Adicione as seguintes configurações no AndroidManifest do seu app
133
+ sunmiImplementation("br.com.stone:stone-sdk-posandroid-sunmi:${rootProject.ext.stone_sdk_version}")
134
+ tectoyImplementation("br.com.stone:stone-sdk-posandroid-tectoy:${rootProject.ext.stone_sdk_version}")
84
135
 
136
+ // AARs de fabricante que a lib usa mas não distribui (ver passo 4)
137
+ implementation fileTree(dir: 'libs', include: ['*.aar'])
138
+ }
85
139
  ```
86
- <manifest
87
- ...
88
- xmlns:tools="http://schemas.android.com/tools"
89
- >
90
- ...
140
+
141
+ Build de cada APK: `./gradlew :app:assembleTectoyRelease`, `:app:assembleSunmiRelease`, `:app:assemblePagbankRelease`.
142
+
143
+ ### 3. AndroidManifest
144
+
145
+ Uma dependência do SDK Stone declara `allowBackup`; sem o `tools:replace` o merge do manifest falha:
146
+
147
+ ```xml
148
+ <manifest xmlns:android="http://schemas.android.com/apk/res/android"
149
+ xmlns:tools="http://schemas.android.com/tools">
150
+
151
+ <!-- Sunmi: leitor RFID -->
152
+ <uses-permission android:name="com.sunmi.perm.CONTACTLESS_CARD" />
153
+ <!-- PlugPag -->
154
+ <uses-permission android:name="br.com.uol.pagseguro.permission.MANAGE_PAYMENTS" />
155
+ <!-- Pax -->
156
+ <uses-permission android:name="com.pax.permission.PICC" />
157
+ <uses-permission android:name="com.pax.permission.PRINTER" />
158
+ <!-- Paystore -->
159
+ <uses-permission android:name="br.com.phoebus.android.payments.provider.READ_PERMISSION" />
160
+
91
161
  <application
92
- ...
93
- android:allowBackup="true"
94
- tools:replace="android:allowBackup"
95
- >
162
+ android:allowBackup="false"
163
+ tools:replace="android:allowBackup">
96
164
  ...
97
165
  </application>
98
166
  </manifest>
99
167
  ```
100
168
 
101
- Adicione essas configurações em android/build.gradle do seu app
169
+ Inclua só as permissões dos módulos que o app usa. Stone, Tectoy e Gertec não pedem permissão no app; os HALs trazem as deles.
170
+
171
+ ### 4. Arquivos de fabricante no app
102
172
 
173
+ A lib compila contra esses arquivos, mas quem os empacota é o app. Copie do [`example/android/app`](example/android/app) para os mesmos caminhos no seu app:
174
+
175
+ | Módulo | Arquivo | Destino |
176
+ |---|---|---|
177
+ | Gertec | `android-easy-layer-gpos780-2.1.4-debug.aar`, `libgedi-1.16.21-gpos780-payment-release.aar` | `android/app/libs/` |
178
+ | Paystore | `paystore-api-v2.11.7.31.aar` | `android/app/libs/` |
179
+ | Pax | `libDeviceConfig.so` | `android/app/src/main/jniLibs/armeabi-v7a/` |
180
+
181
+ ## Qual APK para qual POS
182
+
183
+ | POS | Adquirente | Flavor | Pagamento | RFID e impressão |
184
+ |---|---|---|---|---|
185
+ | Sunmi P2-B / P2-A11 | Stone | `sunmi` | `Stone` | `Sunmi` |
186
+ | Tectoy T8 | Stone | `tectoy` | `Stone` | `Tectoy` |
187
+ | Gertec GPOS780 / GPOS780S | PagBank | `pagbank` | `Plugpag` | `Gertec` |
188
+ | Sunmi P2-B / P2-A11 | PagBank | `pagbank` | `Plugpag` | `Sunmi` |
189
+
190
+ O SDK de pagamento ativado no app tem que bater com o flavor instalado: o APK `pagbank` não tem HAL da Stone, então `Stone.pay` não funciona nele.
191
+
192
+ ## API
193
+
194
+ ```ts
195
+ import { Plugpag, Stone, Paystore, Sunmi, Tectoy, Gertec, Pax } from 'react-native-mesmart';
103
196
  ```
104
- buildscript {
105
- ext {
106
- ...
107
- localProp = new Properties()
108
- fileName = 'local.properties'
109
- localProp.load(new FileInputStream(rootProject.file(fileName)))
110
- stoneToken = System.env.PACKAGECLOUD_READ_TOKEN != null ? System.env.PACKAGECLOUD_READ_TOKEN : (localProp["packageCloudReadToken"] ?: "")
111
- }
112
- }
113
197
 
114
- allprojects {
115
- repositories {
116
- ...
117
- maven { url "https://packagecloud.io/priv/${stoneToken}/stone/pos-android/maven2" }
118
- }
198
+ Todos os métodos retornam `Promise`. Em erro, a promise é rejeitada com a mensagem do SDK. Valores monetários de **Stone e PlugPag são em centavos, como string** (`'500'` = R$ 5,00).
199
+
200
+ `PaymentMethod` = `'debitCard' | 'creditCard' | 'pix' | 'voucher' | 'money' | 'bonus'`. Cada SDK aceita só uma parte deles (ver em cada módulo).
201
+
202
+ ### Plugpag (PagBank)
203
+
204
+ Requer o PlugPagService instalado na POS (POS PagBank).
205
+
206
+ | Método | Retorno | Descrição |
207
+ |---|---|---|
208
+ | `init(activationCode)` | `null` | Ativa o terminal com o código de ativação da conta PagBank. |
209
+ | `isActivated()` | `boolean` | Se o `init` já rodou nesta sessão do app. |
210
+ | `pay(value, paymentMethod)` | `PlugpagTransactionResult` | Venda à vista. `value` em centavos. Métodos: `debitCard`, `creditCard`, `voucher`, `pix`. |
211
+ | `voidPayment({ transactionCode, transactionId, printReceipt?, voidType? })` | `PlugpagTransactionResult` | Estorno. `voidType`: `'payment'` (padrão) ou `'qrcode'`/`'pix'`. |
212
+ | `abortPayment()` | `null` | Cancela a transação em andamento. |
213
+ | `resolveEvent(eventData)` | `string` | Traduz um evento de `onPlugpagEventData` em mensagem para o cliente. |
214
+ | `destroy()` | `null` | Desativa o terminal. |
215
+
216
+ ```ts
217
+ import { Plugpag, PlugpagResult } from 'react-native-mesmart';
218
+
219
+ await Plugpag.init('123456');
220
+ const result = await Plugpag.pay('1500', 'creditCard'); // R$ 15,00
221
+ if (result.result === PlugpagResult.RET_OK) {
222
+ // aprovado: guarde result.transactionCode e result.transactionId para estorno
119
223
  }
120
224
  ```
121
225
 
122
- Lembre-se de adicionar no arquivo local.properties do diretório android do seu app o valor packageCloudReadToken com sua chave ofericida pela Stone
226
+ O progresso da transação chega pelo evento [`onPlugpagEventData`](#eventos).
227
+
228
+ ### Stone
123
229
 
124
- ## Configurações para SDK Paystore
230
+ Funciona nas POS Stone (flavors `sunmi` e `tectoy`).
125
231
 
126
- Adicione a seguinte permissão no AndroidManifest do seu app
232
+ | Método | Retorno | Descrição |
233
+ |---|---|---|
234
+ | `init({ providerId, authorization }, appName)` | `null` | Inicializa o SDK. As chaves são as de QR Code/PIX fornecidas pela Stone (`authorization` inclui o `Bearer`). `appName` é obrigatório. |
235
+ | `isActivated()` | `boolean` | Se o `init` já rodou. |
236
+ | `getStoneCode()` | `string` | Stone Code do usuário ativado na POS. |
237
+ | `pay(value, paymentMethod, isCapture = true)` | `null` | Inicia a venda. `value` em centavos. Métodos: `debitCard`, `creditCard`, `voucher`, `pix`. A resolução da promise **não** é o resultado: ele chega pelo evento [`onStoneEventData`](#eventos). |
238
+ | `abortPayment()` | `boolean` | Aborta a venda em andamento (`false` se não havia nenhuma). |
239
+ | `printVia(transaction, 'MERCHANT' \| 'CLIENT')` | `null` | Imprime a via padrão da Stone. |
240
+ | `captureTransaction(transaction)` | `StoneCaptureResponse` | Captura uma venda feita com `isCapture = false`. |
241
+ | `cancelTransaction(transaction)` | `StoneCancelResponse` | Cancela (estorna) uma venda. |
127
242
 
243
+ ```ts
244
+ await Stone.init({ providerId, authorization }, 'BeerPass');
245
+ await Stone.pay('1500', 'pix');
246
+ // acompanhe onStoneEventData: onStatusChanged (com qrCode no PIX), onSuccess ou onError
128
247
  ```
129
- <uses-permission android:name="br.com.phoebus.android.payments.provider.READ_PERMISSION" />
248
+
249
+ `transaction` é o `StoneTransaction` recebido no evento `onSuccess`.
250
+
251
+ ### Paystore
252
+
253
+ | Método | Retorno | Descrição |
254
+ |---|---|---|
255
+ | `init()` | `null` | Inicializa o client da Paystore. |
256
+ | `isActivated()` | `boolean` | Se o `init` já rodou. |
257
+ | `pay(value, transactionId, showReceipt, paymentMethods, installments)` | `void` | Inicia o pagamento. `value` em reais com ponto (`'15.00'`). `paymentMethods` aceita `creditCard`, `debitCard` e `voucher`. `installments = 0` é à vista. |
258
+
259
+ O pagamento é confirmado automaticamente e o resultado (`PaystorePaymentResult`) chega pelo evento [`onPayment`](#eventos). A promise de `pay` resolve assim que o fluxo começa.
260
+
261
+ ### Sunmi (P2-B / P2-A11)
262
+
263
+ Usa o SDK da própria Sunmi (paylib e serviço de impressora), não o da Stone. Funciona em qualquer flavor.
264
+
265
+ | Método | Retorno | Descrição |
266
+ |---|---|---|
267
+ | `scanRfid()` | `string` | Lê um cartão Mifare. Ver [formato do RFID](#formato-do-rfid). |
268
+ | `cancelScan()` | `null` | Cancela a leitura. |
269
+ | `setPrinterAlign('left' \| 'center' \| 'right')` | `null` | Alinhamento das próximas impressões. |
270
+ | `printText(text, fontSize = 24, isBold = false, isUnderline = false)` | `null` | Imprime texto. A quebra de linha vem do `\n` no texto. Com tamanho 24 cabem 32 colunas. |
271
+ | `printEmptyLine()` | `null` | Avança uma linha. |
272
+ | `printBitmap(base64, width = 200, height = 200)` | `null` | Imprime imagem PNG/JPEG em base64 (por exemplo, QR Code). |
273
+ | `printBpLogo()` | `null` | Imprime o logo da Beerpass. |
274
+ | `printClientReceipt(date, rechargeType, name, document, paymentMethod, rfid, rechargeValue)` | `void` | Comprovante de recarga pronto. |
275
+
276
+ Cada chamada imprime na hora.
277
+
278
+ ```ts
279
+ await Sunmi.setPrinterAlign('center');
280
+ await Sunmi.printBpLogo();
281
+ await Sunmi.printText('Cupom de Consumo\n', 28, true);
282
+ await Sunmi.setPrinterAlign('left');
283
+ await Sunmi.printText('================================\n', 24, true);
284
+ await Sunmi.printText('Valor: R$ 18,00\n');
285
+ await Sunmi.printEmptyLine();
130
286
  ```
131
287
 
132
- Adicione essa configuração em android/app/build.gradle do seu app
288
+ ### Tectoy (T8)
289
+
290
+ Usa o SDK da Stone com o HAL da Tectoy, então precisa do flavor `tectoy`. Inicializa o SDK Stone sozinho, sem depender do `Stone.init`.
133
291
 
292
+ | Método | Retorno | Descrição |
293
+ |---|---|---|
294
+ | `scanRfid()` | `string` | Lê um cartão Mifare (espera até 30 s). Ver [formato do RFID](#formato-do-rfid). |
295
+ | `cancelScan()` | `true` | Cancela a leitura; a promise do `scanRfid` é rejeitada. |
296
+ | `setPrinterAlign`, `printText`, `printEmptyLine`, `printBitmap`, `printBpLogo` | `null` | Mesmas assinaturas da [`Sunmi`](#sunmi-p2-b--p2-a11), mas **acumulam** o cupom em vez de imprimir na hora. |
297
+ | `commitPrint()` | `true` | **Imprime** tudo que foi acumulado, num único job. Obrigatório no fim de cada cupom. |
298
+
299
+ ```ts
300
+ await Tectoy.setPrinterAlign('center');
301
+ await Tectoy.printBpLogo();
302
+ await Tectoy.printText('Cupom de Consumo\n', 28, true);
303
+ await Tectoy.setPrinterAlign('left');
304
+ await Tectoy.printText('================================\n', 24, true);
305
+ await Tectoy.printText('Valor: R$ 18,00\n');
306
+ await Tectoy.commitPrint(); // sem isso nada sai
134
307
  ```
135
- dependencies {
136
- ...
137
- implementation fileTree(dir: 'libs', include: ['*.aar'])
138
- }
308
+
309
+ Por que é diferente da Sunmi:
310
+
311
+ - **Cupom num job só:** o HAL da Tectoy avança o papel de corte ao fim de cada impressão. Imprimir linha a linha deixaria um espaço de corte entre as linhas.
312
+ - **Sem HTML:** o firmware Stone da T8 bloqueia o processo da WebView, então impressão via HTML (como a da Gertec) não funciona. O texto é desenhado em bitmap com a mesma métrica da Sunmi (32 colunas no tamanho 24), e os templates da P2 servem sem ajuste, bastando chamar `commitPrint()` no final.
313
+
314
+ ### Gertec (GPOS780 / GPOS780S)
315
+
316
+ Usa o SDK da Gertec (easylayer e GEDI). Precisa das AARs da Gertec no app ([passo 4](#4-arquivos-de-fabricante-no-app)).
317
+
318
+ | Método | Retorno | Descrição |
319
+ |---|---|---|
320
+ | `scanRfid()` | `string` | Lê um cartão Mifare (espera até 30 s). |
321
+ | `cancelScan()` | `true` | Cancela a leitura. |
322
+ | `printHtml(html)` | `true` | Imprime um HTML (largura útil de 384 px). |
323
+ | `scrollPrinterPaper(lines)` | `true` | Avança o papel. |
324
+
325
+ ```ts
326
+ await Gertec.printHtml(`<html><body style="width:384px">...</body></html>`);
327
+ await Gertec.scrollPrinterPaper(60);
139
328
  ```
140
329
 
141
- Crie um diretório android/app/libs e adicione o arquivo 'paystore-api-v2.11.7.31.aar' que está presente no exemplo dessa biblioteca
330
+ ### Pax (A910)
331
+
332
+ Usa a NeptuneLite (já inclusa na lib). Precisa do `libDeviceConfig.so` no app ([passo 4](#4-arquivos-de-fabricante-no-app)). A lib só inicializa leitor e impressora quando o modelo é **A910**.
333
+
334
+ | Método | Retorno | Descrição |
335
+ |---|---|---|
336
+ | `scanRfid()` | `string` | Lê um cartão Mifare. |
337
+ | `cancelScan()` | `null` | Cancela a leitura. |
338
+ | `printerInit()` | `null` | Começa um cupom. |
339
+ | `addText(text, fontSize = 24)` | `null` | Adiciona texto ao cupom. |
340
+ | `addBpLogo()` | `null` | Adiciona o logo da Beerpass. |
341
+ | `printerStart()` | `null` | Imprime o cupom montado. |
342
+ | `printClientReceipt(date, rechargeType, name, document, paymentMethod, rfid, rechargeValue)` | `void` | Comprovante de recarga pronto. |
343
+
344
+ ## Eventos
142
345
 
143
- ## Listeners
346
+ Os eventos chegam pelo `DeviceEventEmitter`:
347
+
348
+ | Evento | Payload | Quando |
349
+ |---|---|---|
350
+ | `onPlugpagEventData` | `PlugpagEventData` (`eventCode`, `customMessage`) | Etapas da transação PlugPag (aguardando cartão, senha, aprovada…). |
351
+ | `onStoneEventData` | `StoneEventData` (`type`: `onStatusChanged`, `onSuccess` ou `onError`) | Progresso e resultado de `Stone.pay`. No PIX, `onStatusChanged` traz o `qrCode` em base64. |
352
+ | `onPayment` | `PaystorePaymentResult` | Resultado de `Paystore.pay`, já confirmado. |
144
353
 
145
354
  ```ts
146
355
  import { DeviceEventEmitter } from 'react-native';
147
356
  import {
357
+ Plugpag,
148
358
  type PlugpagEventData,
149
359
  type StoneEventData,
360
+ type PaystorePaymentResult,
150
361
  } from 'react-native-mesmart';
151
362
 
152
363
  useEffect(() => {
153
- const plugpagSubscribe = DeviceEventEmitter.addListener(
154
- 'onPlugpagEventData',
155
- (plugpagEvent: PlugPagEventData) => {
156
- console.log(plugpagEvent);
157
- }
158
- );
159
-
160
- const stoneSubscribe = DeviceEventEmitter.addListener(
161
- 'onStoneEventData',
162
- (event: StoneEventData) => {
163
- console.log(event);
164
- }
165
- );
166
-
167
- return () => {
168
- plugpagSubscribe.remove();
169
- stoneSubscribe.remove();
170
- };
364
+ const subs = [
365
+ DeviceEventEmitter.addListener('onPlugpagEventData', async (event: PlugpagEventData) => {
366
+ const message = await Plugpag.resolveEvent(event); // texto para mostrar ao cliente
367
+ }),
368
+ DeviceEventEmitter.addListener('onStoneEventData', (event: StoneEventData) => {
369
+ if (event.type === 'onSuccess') { /* event.transaction */ }
370
+ if (event.type === 'onError') { /* event.listOfErrors */ }
371
+ }),
372
+ DeviceEventEmitter.addListener('onPayment', (payment: PaystorePaymentResult) => {}),
373
+ ];
374
+ return () => subs.forEach((s) => s.remove());
171
375
  }, []);
172
376
  ```
173
377
 
378
+ Todos os tipos (`PlugpagTransactionResult`, `StoneTransaction`, `StoneEventData`, `PaystorePaymentResult`, `SunmiAPI`, `TectoyAPI`…) são exportados pelo pacote.
379
+
380
+ ## Formato do RFID
381
+
382
+ Todos os módulos devolvem o mesmo formato: os bytes do UID do cartão em ordem invertida, convertidos para decimal e completados com zeros à esquerda até 10 dígitos (ex.: `1839402837`). Assim, o mesmo cartão tem o mesmo número em qualquer POS.
383
+
384
+ ## App de exemplo
385
+
386
+ O [`example/`](example) tem uma tela por módulo (PLUGPAG, STONE, SUNMI, GERTEC e TECTOY) para testar na POS.
387
+
388
+ 1. `yarn` na raiz do repositório.
389
+ 2. Crie `example/android/local.properties` com `sdk.dir` e `packageCloudReadToken`.
390
+ 3. Build com **JDK 17** e o flavor da POS:
391
+
392
+ ```sh
393
+ cd example/android && ./gradlew :app:assembleTectoyDebug
394
+ ```
395
+
396
+ O APK sai em `example/android/app/build/outputs/apk/tectoy/debug/`.
397
+
398
+ 4. Metro e instalação:
399
+
400
+ ```sh
401
+ cd example && yarn start
402
+ adb install -r android/app/build/outputs/apk/tectoy/debug/app-tectoy-debug.apk
403
+ adb reverse tcp:8081 tcp:8081
404
+ ```
405
+
406
+ Se a POS reconectar no USB, o `adb reverse` se perde e precisa ser refeito.
407
+
408
+ ## Migrando da 2.x para a 3.x
409
+
410
+ 1. Atualize o app para **RN ≥ 0.80**, com AGP ≥ 8.6, Gradle 8.14, compileSdk 35 e JDK 17. Mantenha `newArchEnabled=false`.
411
+ 2. Crie os **flavors por POS** e mova o HAL da Stone para eles ([passo 2](#2-um-flavor-por-pos-hal-da-stone)). Defina `stone_sdk_version = "4.20.16"`.
412
+ 3. Ative o **core library desugaring** (`desugar_jdk_libs` 2.1.5).
413
+ 4. Adicione `tools:replace="android:allowBackup"` no manifest.
414
+ 5. Restrinja o repositório do PlugPag no GitHub com o `content { includeGroupByRegex ... }`.
415
+ 6. O SDK da Sunmi agora vem da própria lib: não dependa mais do HAL Sunmi da Stone para ter `Sunmi` em APKs PagBank.
416
+ 7. Nas Tectoy T8, imprima com os templates da P2 + `Tectoy.commitPrint()`.
417
+
418
+ ## Publicando uma versão
419
+
420
+ Para mantenedores. O bump de versão é feito pelo `release-it`, nunca à mão.
421
+
422
+ 1. Faça o merge na `main`.
423
+ 2. Commit, tag e release no GitHub (passe a versão explícita: sem ela, o `release-it` calcula pelos commits):
424
+
425
+ ```sh
426
+ GITHUB_TOKEN=$(gh auth token) yarn release-it X.Y.Z --no-npm.publish
427
+ ```
428
+
429
+ `--npm.publish=false` **não** desliga a publicação; use `--no-npm.publish`.
430
+
431
+ 3. Publique no npm. A conta exige 2FA por chave de segurança/Touch ID, e o CLI abre o navegador para confirmar:
432
+
433
+ ```sh
434
+ npm publish
435
+ ```
436
+
174
437
  ## License
175
438
 
176
439
  MIT
177
-
178
- ---
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "react-native-mesmart",
3
- "version": "3.0.0",
3
+ "version": "3.0.1",
4
4
  "description": "Native methods for integrating with Sunmi P2-B/P2-A11 POS, Pax A910/A920, Pagbank's Plugpag payment SDK, Stone's payment SDK, and Paystore's payment SDK.",
5
5
  "main": "lib/commonjs/index",
6
6
  "module": "lib/module/index",