@capacitor-community/stripe-terminal 6.2.1 → 6.4.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.
Files changed (40) hide show
  1. package/CapacitorCommunityStripeTerminal.podspec +3 -3
  2. package/Package.swift +30 -0
  3. package/README.md +50 -38
  4. package/android/build.gradle +3 -3
  5. package/android/src/main/java/com/getcapacitor/community/stripe/terminal/StripeTerminal.java +179 -96
  6. package/android/src/main/java/com/getcapacitor/community/stripe/terminal/StripeTerminalPlugin.java +1 -1
  7. package/android/src/main/java/com/getcapacitor/community/stripe/terminal/TerminalEvent.kt +1 -0
  8. package/android/src/main/java/com/getcapacitor/community/stripe/terminal/TokenProvider.java +7 -6
  9. package/android/src/main/java/com/getcapacitor/community/stripe/terminal/helper/TerminalMappers.java +3 -3
  10. package/dist/docs.json +23 -17
  11. package/dist/esm/definitions.d.ts +11 -11
  12. package/dist/esm/definitions.js.map +1 -1
  13. package/dist/esm/events.enum.d.ts +1 -0
  14. package/dist/esm/events.enum.js +1 -0
  15. package/dist/esm/events.enum.js.map +1 -1
  16. package/dist/esm/index.js +1 -1
  17. package/dist/esm/index.js.map +1 -1
  18. package/dist/esm/stripe.enum.d.ts +2 -2
  19. package/dist/esm/stripe.enum.js +2 -2
  20. package/dist/esm/stripe.enum.js.map +1 -1
  21. package/dist/esm/{terminalMappers.js → terminal-mappers.js} +2 -2
  22. package/dist/esm/terminal-mappers.js.map +1 -0
  23. package/dist/esm/web.js +14 -10
  24. package/dist/esm/web.js.map +1 -1
  25. package/dist/plugin.cjs.js +17 -14
  26. package/dist/plugin.cjs.js.map +1 -1
  27. package/dist/plugin.js +18 -15
  28. package/dist/plugin.js.map +1 -1
  29. package/ios/{Plugin → Sources/StripeTerminalPlugin}/StripeTerminal.swift +52 -45
  30. package/ios/{Plugin → Sources/StripeTerminalPlugin}/StripeTerminalPlugin.swift +22 -1
  31. package/ios/{Plugin → Sources/StripeTerminalPlugin}/TerminalEvents.swift +1 -0
  32. package/ios/{Plugin → Sources/StripeTerminalPlugin}/TerminalMappers.swift +2 -2
  33. package/ios/Tests/StripeTerminalPluginTests/StripeTerminalPluginTests.swift +15 -0
  34. package/package.json +16 -14
  35. package/dist/esm/terminalMappers.js.map +0 -1
  36. package/ios/Plugin/StripeTerminalPlugin.h +0 -10
  37. package/ios/Plugin/StripeTerminalPlugin.m +0 -24
  38. /package/dist/esm/{terminalMappers.d.ts → terminal-mappers.d.ts} +0 -0
  39. /package/ios/{Plugin → Sources/StripeTerminalPlugin}/Info.plist +0 -0
  40. /package/ios/{Plugin → Sources/StripeTerminalPlugin}/TerminalConnectTypes.swift +0 -0
@@ -6,6 +6,7 @@ import android.app.Application;
6
6
  import android.bluetooth.BluetoothAdapter;
7
7
  import android.content.Context;
8
8
  import android.content.pm.PackageManager;
9
+ import android.os.Build;
9
10
  import android.util.Log;
10
11
  import androidx.annotation.NonNull;
11
12
  import androidx.annotation.Nullable;
@@ -22,26 +23,25 @@ import com.stripe.stripeterminal.TerminalApplicationDelegate;
22
23
  import com.stripe.stripeterminal.external.callable.Callback;
23
24
  import com.stripe.stripeterminal.external.callable.Cancelable;
24
25
  import com.stripe.stripeterminal.external.callable.DiscoveryListener;
26
+ import com.stripe.stripeterminal.external.callable.InternetReaderListener;
27
+ import com.stripe.stripeterminal.external.callable.MobileReaderListener;
25
28
  import com.stripe.stripeterminal.external.callable.PaymentIntentCallback;
26
29
  import com.stripe.stripeterminal.external.callable.ReaderCallback;
27
- import com.stripe.stripeterminal.external.callable.ReaderListener;
28
- import com.stripe.stripeterminal.external.callable.ReaderReconnectionListener;
30
+ //import com.stripe.stripeterminal.external.callable.ReaderReconnectionListener;
31
+ import com.stripe.stripeterminal.external.callable.TapToPayReaderListener;
29
32
  import com.stripe.stripeterminal.external.callable.TerminalListener;
30
33
  import com.stripe.stripeterminal.external.models.BatteryStatus;
31
34
  import com.stripe.stripeterminal.external.models.CardPresentDetails;
32
35
  import com.stripe.stripeterminal.external.models.Cart;
33
36
  import com.stripe.stripeterminal.external.models.CartLineItem;
34
37
  import com.stripe.stripeterminal.external.models.CollectConfiguration;
38
+ import com.stripe.stripeterminal.external.models.ConnectionConfiguration;
35
39
  import com.stripe.stripeterminal.external.models.ConnectionConfiguration.BluetoothConnectionConfiguration;
36
40
  import com.stripe.stripeterminal.external.models.ConnectionConfiguration.InternetConnectionConfiguration;
37
- import com.stripe.stripeterminal.external.models.ConnectionConfiguration.LocalMobileConnectionConfiguration;
38
41
  import com.stripe.stripeterminal.external.models.ConnectionConfiguration.UsbConnectionConfiguration;
39
42
  import com.stripe.stripeterminal.external.models.ConnectionStatus;
40
- import com.stripe.stripeterminal.external.models.DeviceType;
41
43
  import com.stripe.stripeterminal.external.models.DisconnectReason;
42
44
  import com.stripe.stripeterminal.external.models.DiscoveryConfiguration;
43
- import com.stripe.stripeterminal.external.models.Location;
44
- import com.stripe.stripeterminal.external.models.LocationStatus;
45
45
  import com.stripe.stripeterminal.external.models.PaymentIntent;
46
46
  import com.stripe.stripeterminal.external.models.PaymentMethod;
47
47
  import com.stripe.stripeterminal.external.models.PaymentStatus;
@@ -106,22 +106,12 @@ public class StripeTerminal extends Executor {
106
106
  }
107
107
 
108
108
  this.activitySupplier.get()
109
- .runOnUiThread(
110
- () -> {
111
- TerminalApplicationDelegate.onCreate((Application) this.contextSupplier.get().getApplicationContext());
112
- notifyListeners(TerminalEnumEvent.Loaded.getWebEventName(), emptyObject);
113
- call.resolve();
114
- }
115
- );
109
+ .runOnUiThread(() -> {
110
+ TerminalApplicationDelegate.onCreate((Application) this.contextSupplier.get().getApplicationContext());
111
+ notifyListeners(TerminalEnumEvent.Loaded.getWebEventName(), emptyObject);
112
+ call.resolve();
113
+ });
116
114
  TerminalListener listener = new TerminalListener() {
117
- @Override
118
- public void onUnexpectedReaderDisconnect(@NonNull Reader reader) {
119
- notifyListeners(
120
- TerminalEnumEvent.UnexpectedReaderDisconnect.getWebEventName(),
121
- new JSObject().put("reader", convertReaderInterface(reader))
122
- );
123
- }
124
-
125
115
  @Override
126
116
  public void onConnectionStatusChange(@NonNull ConnectionStatus status) {
127
117
  notifyListeners(
@@ -136,8 +126,11 @@ public class StripeTerminal extends Executor {
136
126
  }
137
127
  };
138
128
  LogLevel logLevel = LogLevel.VERBOSE;
139
- this.tokenProvider =
140
- new TokenProvider(this.contextSupplier, call.getString("tokenProviderEndpoint", ""), this.notifyListenersFunction);
129
+ this.tokenProvider = new TokenProvider(
130
+ this.contextSupplier,
131
+ call.getString("tokenProviderEndpoint", ""),
132
+ this.notifyListenersFunction
133
+ );
141
134
  if (!Terminal.isInitialized()) {
142
135
  Terminal.initTerminal(this.contextSupplier.get().getApplicationContext(), logLevel, this.tokenProvider, listener);
143
136
  }
@@ -150,13 +143,13 @@ public class StripeTerminal extends Executor {
150
143
 
151
144
  public void setSimulatorConfiguration(PluginCall call) {
152
145
  try {
153
- Terminal
154
- .getInstance()
146
+ Terminal.getInstance()
155
147
  .setSimulatorConfiguration(
156
148
  new SimulatorConfiguration(
157
149
  SimulateReaderUpdate.valueOf(call.getString("update", "UPDATE_AVAILABLE")),
158
150
  new SimulatedCard(SimulatedCardType.valueOf(call.getString("simulatedCard", "VISA"))),
159
- call.getLong("simulatedTipAmount", null)
151
+ call.getLong("simulatedTipAmount", null),
152
+ false
160
153
  )
161
154
  );
162
155
 
@@ -179,10 +172,10 @@ public class StripeTerminal extends Executor {
179
172
  this.locationId = call.getString("locationId");
180
173
  final DiscoveryConfiguration config;
181
174
  if (Objects.equals(call.getString("type"), TerminalConnectTypes.TapToPay.getWebEventName())) {
182
- config = new DiscoveryConfiguration.LocalMobileDiscoveryConfiguration(this.isTest);
175
+ config = new DiscoveryConfiguration.TapToPayDiscoveryConfiguration(this.isTest);
183
176
  this.terminalConnectType = TerminalConnectTypes.TapToPay;
184
177
  } else if (Objects.equals(call.getString("type"), TerminalConnectTypes.Internet.getWebEventName())) {
185
- config = new DiscoveryConfiguration.InternetDiscoveryConfiguration(this.locationId, this.isTest);
178
+ config = new DiscoveryConfiguration.InternetDiscoveryConfiguration(0, this.locationId, this.isTest);
186
179
  this.terminalConnectType = TerminalConnectTypes.Internet;
187
180
  } else if (Objects.equals(call.getString("type"), TerminalConnectTypes.Usb.getWebEventName())) {
188
181
  config = new DiscoveryConfiguration.UsbDiscoveryConfiguration(0, this.isTest);
@@ -211,29 +204,27 @@ public class StripeTerminal extends Executor {
211
204
  this.notifyListeners(TerminalEnumEvent.DiscoveredReaders.getWebEventName(), new JSObject().put("readers", readersJSObject));
212
205
  call.resolve(new JSObject().put("readers", readersJSObject));
213
206
  };
214
- discoveryCancelable =
215
- Terminal
216
- .getInstance()
217
- .discoverReaders(
218
- config,
219
- discoveryListener,
220
- new Callback() {
221
- @Override
222
- public void onSuccess() {
223
- Log.d(logTag, "Finished discovering readers");
224
- }
225
-
226
- @Override
227
- public void onFailure(@NonNull TerminalException ex) {
228
- Log.d(logTag, ex.getLocalizedMessage());
229
- }
207
+ discoveryCancelable = Terminal.getInstance()
208
+ .discoverReaders(
209
+ config,
210
+ discoveryListener,
211
+ new Callback() {
212
+ @Override
213
+ public void onSuccess() {
214
+ Log.d(logTag, "Finished discovering readers");
230
215
  }
231
- );
216
+
217
+ @Override
218
+ public void onFailure(@NonNull TerminalException ex) {
219
+ Log.d(logTag, ex.getLocalizedMessage());
220
+ }
221
+ }
222
+ );
232
223
  }
233
224
 
234
225
  public void connectReader(final PluginCall call) {
235
226
  if (this.terminalConnectType == TerminalConnectTypes.TapToPay) {
236
- this.connectLocalMobileReader(call);
227
+ this.connectTapToPayReader(call);
237
228
  } else if (this.terminalConnectType == TerminalConnectTypes.Internet) {
238
229
  this.connectInternetReader(call);
239
230
  } else if (this.terminalConnectType == TerminalConnectTypes.Usb) {
@@ -260,8 +251,7 @@ public class StripeTerminal extends Executor {
260
251
  return;
261
252
  }
262
253
 
263
- Terminal
264
- .getInstance()
254
+ Terminal.getInstance()
265
255
  .disconnectReader(
266
256
  new Callback() {
267
257
  @Override
@@ -278,32 +268,47 @@ public class StripeTerminal extends Executor {
278
268
  );
279
269
  }
280
270
 
281
- private void connectLocalMobileReader(final PluginCall call) {
271
+ private void connectTapToPayReader(final PluginCall call) {
282
272
  JSObject reader = call.getObject("reader");
283
273
  String serialNumber = reader.getString("serialNumber");
274
+ this.locationId = call.getString("locationId", this.locationId);
284
275
 
285
- Reader foundReader =
286
- this.discoveredReadersList.stream().filter(device -> serialNumber.equals(device.getSerialNumber())).findFirst().orElse(null);
276
+ Reader foundReader = this.findReader(this.discoveredReadersList, serialNumber);
287
277
 
288
278
  if (serialNumber == null || foundReader == null) {
289
279
  call.reject("The reader value is not set correctly.");
290
280
  return;
291
281
  }
292
282
 
293
- Boolean autoReconnectOnUnexpectedDisconnect = call.getBoolean("autoReconnectOnUnexpectedDisconnect", false);
283
+ Boolean autoReconnectOnUnexpectedDisconnect = Objects.requireNonNullElse(
284
+ call.getBoolean("autoReconnectOnUnexpectedDisconnect", false),
285
+ false
286
+ );
294
287
 
295
- LocalMobileConnectionConfiguration config = new LocalMobileConnectionConfiguration(
288
+ ConnectionConfiguration.TapToPayConnectionConfiguration config = new ConnectionConfiguration.TapToPayConnectionConfiguration(
296
289
  this.locationId,
297
290
  autoReconnectOnUnexpectedDisconnect,
298
- this.readerReconnectionListener
291
+ this.tapToPayReaderListener
299
292
  );
300
- Terminal.getInstance().connectLocalMobileReader(foundReader, config, this.readerCallback(call));
293
+ Terminal.getInstance().connectReader(foundReader, config, this.readerCallback(call));
301
294
  }
302
295
 
303
- ReaderReconnectionListener readerReconnectionListener = new ReaderReconnectionListener() {
296
+ TapToPayReaderListener tapToPayReaderListener = new TapToPayReaderListener() {
297
+ @Override
298
+ public void onReaderReconnectFailed(@NonNull Reader reader) {
299
+ notifyListeners(
300
+ TerminalEnumEvent.ReaderReconnectFailed.getWebEventName(),
301
+ new JSObject().put("reader", convertReaderInterface(reader))
302
+ );
303
+ }
304
+
304
305
  @Override
305
- public void onReaderReconnectStarted(@NonNull Reader reader, @NonNull Cancelable cancelable, @NonNull DisconnectReason reason) {
306
- cancelReaderConnectionCancellable = cancelable;
306
+ public void onReaderReconnectStarted(
307
+ @NonNull Reader reader,
308
+ @NonNull Cancelable cancelReconnect,
309
+ @NonNull DisconnectReason reason
310
+ ) {
311
+ cancelReaderConnectionCancellable = cancelReconnect;
307
312
  notifyListeners(
308
313
  TerminalEnumEvent.ReaderReconnectStarted.getWebEventName(),
309
314
  new JSObject().put("reason", reason.toString()).put("reader", convertReaderInterface(reader))
@@ -319,65 +324,99 @@ public class StripeTerminal extends Executor {
319
324
  }
320
325
 
321
326
  @Override
322
- public void onReaderReconnectFailed(@NonNull Reader reader) {
323
- notifyListeners(
324
- TerminalEnumEvent.ReaderReconnectFailed.getWebEventName(),
325
- new JSObject().put("reader", convertReaderInterface(reader))
326
- );
327
+ public void onDisconnect(@NonNull DisconnectReason reason) {
328
+ notifyListeners(TerminalEnumEvent.DisconnectedReader.getWebEventName(), new JSObject().put("reason", reason.toString()));
327
329
  }
328
330
  };
329
331
 
332
+ InternetReaderListener internetReaderListener = new InternetReaderListener() {
333
+ @Override
334
+ public void onDisconnect(@NonNull DisconnectReason reason) {
335
+ notifyListeners(TerminalEnumEvent.DisconnectedReader.getWebEventName(), new JSObject().put("reason", reason.toString()));
336
+ }
337
+ };
338
+
339
+ // ReaderReconnectionListener readerReconnectionListener = new ReaderReconnectionListener() {
340
+ // @Override
341
+ // public void onReaderReconnectStarted(@NonNull Reader reader, @NonNull Cancelable cancelable, @NonNull DisconnectReason reason) {
342
+ // cancelReaderConnectionCancellable = cancelable;
343
+ // notifyListeners(
344
+ // TerminalEnumEvent.ReaderReconnectStarted.getWebEventName(),
345
+ // new JSObject().put("reason", reason.toString()).put("reader", convertReaderInterface(reader))
346
+ // );
347
+ // }
348
+ //
349
+ // @Override
350
+ // public void onReaderReconnectSucceeded(@NonNull Reader reader) {
351
+ // notifyListeners(
352
+ // TerminalEnumEvent.ReaderReconnectSucceeded.getWebEventName(),
353
+ // new JSObject().put("reader", convertReaderInterface(reader))
354
+ // );
355
+ // }
356
+ //
357
+ // @Override
358
+ // public void onReaderReconnectFailed(@NonNull Reader reader) {
359
+ // notifyListeners(
360
+ // TerminalEnumEvent.ReaderReconnectFailed.getWebEventName(),
361
+ // new JSObject().put("reader", convertReaderInterface(reader))
362
+ // );
363
+ // }
364
+ // };
365
+
330
366
  private void connectInternetReader(final PluginCall call) {
331
367
  JSObject reader = call.getObject("reader");
332
368
  String serialNumber = reader.getString("serialNumber");
369
+ this.locationId = call.getString("locationId", this.locationId);
333
370
 
334
- Reader foundReader =
335
- this.discoveredReadersList.stream().filter(device -> serialNumber.equals(device.getSerialNumber())).findFirst().orElse(null);
371
+ Reader foundReader = this.findReader(this.discoveredReadersList, serialNumber);
336
372
 
337
373
  if (serialNumber == null || foundReader == null) {
338
374
  call.reject("The reader value is not set correctly.");
339
375
  return;
340
376
  }
341
377
 
342
- InternetConnectionConfiguration config = new InternetConnectionConfiguration();
343
- Terminal.getInstance().connectInternetReader(foundReader, config, this.readerCallback(call));
378
+ InternetConnectionConfiguration config = new InternetConnectionConfiguration(true, this.internetReaderListener);
379
+ Terminal.getInstance().connectReader(foundReader, config, this.readerCallback(call));
344
380
  }
345
381
 
346
382
  private void connectUsbReader(final PluginCall call) {
347
383
  JSObject reader = call.getObject("reader");
348
384
  String serialNumber = reader.getString("serialNumber");
385
+ this.locationId = call.getString("locationId", this.locationId);
349
386
 
350
- Reader foundReader =
351
- this.discoveredReadersList.stream().filter(device -> serialNumber.equals(device.getSerialNumber())).findFirst().orElse(null);
387
+ Reader foundReader = this.findReader(this.discoveredReadersList, serialNumber);
352
388
 
353
389
  if (serialNumber == null || foundReader == null) {
354
390
  call.reject("The reader value is not set correctly.");
355
391
  return;
356
392
  }
357
393
 
358
- UsbConnectionConfiguration config = new UsbConnectionConfiguration(this.locationId);
359
- Terminal.getInstance().connectUsbReader(foundReader, config, this.readerListener(), this.readerCallback(call));
394
+ UsbConnectionConfiguration config = new UsbConnectionConfiguration(this.locationId, true, this.readerListener());
395
+ Terminal.getInstance().connectReader(foundReader, config, this.readerCallback(call));
360
396
  }
361
397
 
362
398
  private void connectBluetoothReader(final PluginCall call) {
363
399
  JSObject reader = call.getObject("reader");
364
400
  String serialNumber = reader.getString("serialNumber");
401
+ this.locationId = call.getString("locationId", this.locationId);
365
402
 
366
- Reader foundReader =
367
- this.discoveredReadersList.stream().filter(device -> serialNumber.equals(device.getSerialNumber())).findFirst().orElse(null);
403
+ Reader foundReader = this.findReader(this.discoveredReadersList, serialNumber);
368
404
 
369
405
  if (serialNumber == null || foundReader == null) {
370
406
  call.reject("The reader value is not set correctly.");
371
407
  return;
372
408
  }
373
- Boolean autoReconnectOnUnexpectedDisconnect = call.getBoolean("autoReconnectOnUnexpectedDisconnect", false);
409
+ Boolean autoReconnectOnUnexpectedDisconnect = Objects.requireNonNullElse(
410
+ call.getBoolean("autoReconnectOnUnexpectedDisconnect", false),
411
+ false
412
+ );
374
413
 
375
414
  BluetoothConnectionConfiguration config = new BluetoothConnectionConfiguration(
376
415
  this.locationId,
377
416
  autoReconnectOnUnexpectedDisconnect,
378
- this.readerReconnectionListener
417
+ this.readerListener()
379
418
  );
380
- Terminal.getInstance().connectBluetoothReader(foundReader, config, this.readerListener(), this.readerCallback(call));
419
+ Terminal.getInstance().connectReader(foundReader, config, this.readerCallback(call));
381
420
  }
382
421
 
383
422
  public void cancelDiscoverReaders(final PluginCall call) {
@@ -402,12 +441,13 @@ public class StripeTerminal extends Executor {
402
441
  }
403
442
 
404
443
  public void collectPaymentMethod(final PluginCall call) {
405
- if (call.getString("paymentIntent") == null) {
444
+ String paymentIntent = call.getString("paymentIntent");
445
+ if (paymentIntent == null) {
406
446
  call.reject("The value of paymentIntent is not set correctly.");
407
447
  return;
408
448
  }
409
449
  this.collectCall = call;
410
- Terminal.getInstance().retrievePaymentIntent(call.getString("paymentIntent"), createPaymentIntentCallback);
450
+ Terminal.getInstance().retrievePaymentIntent(paymentIntent, createPaymentIntentCallback);
411
451
  }
412
452
 
413
453
  public void cancelCollectPaymentMethod(final PluginCall call) {
@@ -440,9 +480,15 @@ public class StripeTerminal extends Executor {
440
480
  }
441
481
 
442
482
  @Override
443
- public void onFailure(@NonNull TerminalException ex) {
483
+ public void onFailure(@NonNull TerminalException exception) {
444
484
  notifyListeners(TerminalEnumEvent.Failed.getWebEventName(), emptyObject);
445
- collectCall.reject(ex.getLocalizedMessage(), ex);
485
+ var returnObject = new JSObject();
486
+ returnObject.put("message", exception.getLocalizedMessage());
487
+ if (exception.getApiError() != null) {
488
+ returnObject.put("code", exception.getApiError().getCode());
489
+ returnObject.put("declineCode", exception.getApiError().getDeclineCode());
490
+ }
491
+ collectCall.reject(exception.getLocalizedMessage(), (String) null, returnObject);
446
492
  }
447
493
  };
448
494
 
@@ -453,7 +499,11 @@ public class StripeTerminal extends Executor {
453
499
  notifyListeners(TerminalEnumEvent.CollectedPaymentIntent.getWebEventName(), emptyObject);
454
500
 
455
501
  PaymentMethod pm = paymentIntent.getPaymentMethod();
456
- CardPresentDetails card = pm.getCardPresentDetails() != null ? pm.getCardPresentDetails() : pm.getInteracPresentDetails();
502
+ CardPresentDetails card = null;
503
+
504
+ if (pm != null) {
505
+ card = pm.getCardPresentDetails() != null ? pm.getCardPresentDetails() : pm.getInteracPresentDetails();
506
+ }
457
507
 
458
508
  if (card != null) {
459
509
  collectCall.resolve(
@@ -477,9 +527,19 @@ public class StripeTerminal extends Executor {
477
527
  }
478
528
 
479
529
  @Override
480
- public void onFailure(@NonNull TerminalException ex) {
530
+ public void onFailure(@NonNull TerminalException exception) {
481
531
  notifyListeners(TerminalEnumEvent.Failed.getWebEventName(), emptyObject);
482
- collectCall.reject(ex.getLocalizedMessage(), ex);
532
+ String errorCode = "generic_error";
533
+ if (exception.getApiError() != null && exception.getApiError().getCode() != null) {
534
+ errorCode = exception.getApiError().getCode();
535
+ }
536
+ var returnObject = new JSObject();
537
+ returnObject.put("message", exception.getLocalizedMessage());
538
+ if (exception.getApiError() != null) {
539
+ returnObject.put("code", exception.getApiError().getCode());
540
+ returnObject.put("declineCode", exception.getApiError().getDeclineCode());
541
+ }
542
+ collectCall.reject(exception.getLocalizedMessage(), errorCode, returnObject);
483
543
  }
484
544
  };
485
545
 
@@ -526,8 +586,8 @@ public class StripeTerminal extends Executor {
526
586
  return;
527
587
  }
528
588
 
529
- int tax = call.getInt("tax", 0);
530
- int total = call.getInt("total", 0);
589
+ int tax = Objects.requireNonNullElse(call.getInt("tax", 0), 0);
590
+ int total = Objects.requireNonNullElse(call.getInt("total", 0), 0);
531
591
  if (total == 0) {
532
592
  call.reject("You must provide a total value");
533
593
  return;
@@ -561,8 +621,7 @@ public class StripeTerminal extends Executor {
561
621
 
562
622
  Cart cart = new Cart.Builder(currency, tax, total, cartLineItems).build();
563
623
 
564
- Terminal
565
- .getInstance()
624
+ Terminal.getInstance()
566
625
  .setReaderDisplay(
567
626
  cart,
568
627
  new Callback() {
@@ -580,8 +639,7 @@ public class StripeTerminal extends Executor {
580
639
  }
581
640
 
582
641
  public void clearReaderDisplay(final PluginCall call) {
583
- Terminal
584
- .getInstance()
642
+ Terminal.getInstance()
585
643
  .clearReaderDisplay(
586
644
  new Callback() {
587
645
  @Override
@@ -598,8 +656,7 @@ public class StripeTerminal extends Executor {
598
656
  }
599
657
 
600
658
  public void rebootReader(final PluginCall call) {
601
- Terminal
602
- .getInstance()
659
+ Terminal.getInstance()
603
660
  .rebootReader(
604
661
  new Callback() {
605
662
  @Override
@@ -638,7 +695,7 @@ public class StripeTerminal extends Executor {
638
695
 
639
696
  private final PaymentIntentCallback confirmPaymentMethodCallback = new PaymentIntentCallback() {
640
697
  @Override
641
- public void onSuccess(PaymentIntent paymentIntent) {
698
+ public void onSuccess(@NonNull PaymentIntent paymentIntent) {
642
699
  notifyListeners(TerminalEnumEvent.ConfirmedPaymentIntent.getWebEventName(), emptyObject);
643
700
  paymentIntentInstance = null;
644
701
  confirmPaymentIntentCall.resolve();
@@ -647,7 +704,13 @@ public class StripeTerminal extends Executor {
647
704
  @Override
648
705
  public void onFailure(TerminalException exception) {
649
706
  notifyListeners(TerminalEnumEvent.Failed.getWebEventName(), emptyObject);
650
- confirmPaymentIntentCall.reject(exception.getLocalizedMessage());
707
+ var returnObject = new JSObject();
708
+ returnObject.put("message", exception.getLocalizedMessage());
709
+ if (exception.getApiError() != null) {
710
+ returnObject.put("code", exception.getApiError().getCode());
711
+ returnObject.put("declineCode", exception.getApiError().getDeclineCode());
712
+ }
713
+ confirmPaymentIntentCall.reject(exception.getLocalizedMessage(), (String) null, returnObject);
651
714
  }
652
715
  };
653
716
 
@@ -667,8 +730,8 @@ public class StripeTerminal extends Executor {
667
730
  };
668
731
  }
669
732
 
670
- private ReaderListener readerListener() {
671
- return new ReaderListener() {
733
+ private MobileReaderListener readerListener() {
734
+ return new MobileReaderListener() {
672
735
  @Override
673
736
  public void onStartInstallingUpdate(@NotNull ReaderSoftwareUpdate update, @NotNull Cancelable cancelable) {
674
737
  // Show UI communicating that a required update has started installing
@@ -760,7 +823,7 @@ public class StripeTerminal extends Executor {
760
823
  .put("serialNumber", reader.getSerialNumber())
761
824
  .put("id", reader.getId())
762
825
  .put("locationId", reader.getLocation() != null ? reader.getLocation().getId() : null)
763
- .put("deviceSoftwareVersion", reader.getDeviceSwVersion$external_publish())
826
+ .put("deviceSoftwareVersion", reader.getDeviceSwVersion$public_release())
764
827
  .put("simulated", reader.isSimulated())
765
828
  .put("serialNumber", reader.getSerialNumber())
766
829
  .put("ipAddress", reader.getIpAddress())
@@ -786,4 +849,24 @@ public class StripeTerminal extends Executor {
786
849
  private JSObject convertReaderSoftwareUpdate(ReaderSoftwareUpdate update) {
787
850
  return terminalMappers.mapFromReaderSoftwareUpdate(update);
788
851
  }
852
+
853
+ private Reader findReader(List<Reader> discoveredReadersList, String serialNumber) {
854
+ Reader foundReader = null;
855
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
856
+ foundReader = discoveredReadersList
857
+ .stream()
858
+ .filter(device -> serialNumber != null && serialNumber.equals(device.getSerialNumber()))
859
+ .findFirst()
860
+ .orElse(null);
861
+ } else {
862
+ for (Reader device : discoveredReadersList) {
863
+ if (serialNumber != null && serialNumber.equals(device.getSerialNumber())) {
864
+ foundReader = device;
865
+ break;
866
+ }
867
+ }
868
+ }
869
+
870
+ return foundReader;
871
+ }
789
872
  }
@@ -94,7 +94,7 @@ public class StripeTerminalPlugin extends Plugin {
94
94
  }
95
95
  }
96
96
 
97
- @PluginMethod
97
+ @PluginMethod(returnType = PluginMethod.RETURN_CALLBACK)
98
98
  public void discoverReaders(PluginCall call) {
99
99
  if (
100
100
  Objects.equals(call.getString("type"), TerminalConnectTypes.Bluetooth.getWebEventName()) ||
@@ -2,6 +2,7 @@ package com.getcapacitor.community.stripe.terminal;
2
2
 
3
3
  enum class TerminalEnumEvent(val webEventName: String) {
4
4
  Loaded("terminalLoaded"),
5
+ DiscoveringReaders("terminalDiscoveringReaders"),
5
6
  DiscoveredReaders("terminalDiscoveredReaders"),
6
7
  CancelDiscoveredReaders("terminalCancelDiscoveredReaders"),
7
8
  ConnectedReader("terminalConnectedReader"),
@@ -15,6 +15,7 @@ import com.google.android.gms.common.util.BiConsumer;
15
15
  import com.stripe.stripeterminal.external.callable.ConnectionTokenCallback;
16
16
  import com.stripe.stripeterminal.external.callable.ConnectionTokenProvider;
17
17
  import com.stripe.stripeterminal.external.models.ConnectionTokenException;
18
+ import java.util.ArrayList;
18
19
  import java.util.Objects;
19
20
  import org.json.JSONException;
20
21
  import org.json.JSONObject;
@@ -24,7 +25,7 @@ public class TokenProvider implements ConnectionTokenProvider {
24
25
  protected Supplier<Context> contextSupplier;
25
26
  protected final String tokenProviderEndpoint;
26
27
  protected BiConsumer<String, JSObject> notifyListenersFunction;
27
- ConnectionTokenCallback pendingCallback = null;
28
+ ArrayList<ConnectionTokenCallback> pendingCallback = new ArrayList<>();
28
29
 
29
30
  public TokenProvider(
30
31
  Supplier<Context> contextSupplier,
@@ -38,15 +39,15 @@ public class TokenProvider implements ConnectionTokenProvider {
38
39
 
39
40
  public void setConnectionToken(PluginCall call) {
40
41
  String token = call.getString("token", "");
41
- if (pendingCallback != null) {
42
+ if (!pendingCallback.isEmpty()) {
43
+ ConnectionTokenCallback pending = pendingCallback.remove(0);
42
44
  if (Objects.equals(token, "")) {
43
- pendingCallback.onFailure(new ConnectionTokenException("Missing `token` is empty"));
45
+ pending.onFailure(new ConnectionTokenException("Missing `token` is empty"));
44
46
  call.reject("Missing `token` is empty");
45
47
  } else {
46
- pendingCallback.onSuccess(token);
48
+ pending.onSuccess(token);
47
49
  call.resolve();
48
50
  }
49
- pendingCallback = null;
50
51
  } else {
51
52
  call.reject("Stripe Terminal do not pending fetchConnectionToken");
52
53
  }
@@ -55,7 +56,7 @@ public class TokenProvider implements ConnectionTokenProvider {
55
56
  @Override
56
57
  public void fetchConnectionToken(ConnectionTokenCallback callback) {
57
58
  if (Objects.equals(this.tokenProviderEndpoint, "")) {
58
- pendingCallback = callback;
59
+ pendingCallback.add(callback);
59
60
  this.notifyListeners(TerminalEnumEvent.RequestedConnectionToken.getWebEventName(), new JSObject());
60
61
  } else {
61
62
  try {
@@ -40,8 +40,8 @@ public class TerminalMappers {
40
40
 
41
41
  return new JSObject()
42
42
  .put("deviceSoftwareVersion", update.getVersion())
43
- .put("estimatedUpdateTime", update.getTimeEstimate().toString())
44
- .put("requiredAt", update.getRequiredAt().getTime());
43
+ .put("estimatedUpdateTime", update.getDurationEstimate().toString())
44
+ .put("requiredAt", update.getRequiredAtMs());
45
45
  }
46
46
 
47
47
  public String mapFromLocationStatus(LocationStatus status) {
@@ -73,7 +73,7 @@ public class TerminalMappers {
73
73
  return switch (type) {
74
74
  case CHIPPER_1X -> "chipper1X";
75
75
  case CHIPPER_2X -> "chipper2X";
76
- case COTS_DEVICE -> "cotsDevice";
76
+ case TAP_TO_PAY_DEVICE -> "tapToPayDevice";
77
77
  case ETNA -> "etna";
78
78
  case STRIPE_M2 -> "stripeM2";
79
79
  case STRIPE_S700 -> "stripeS700";