@capacitor-community/stripe-terminal 6.4.0 → 6.4.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.
@@ -1,872 +0,0 @@
1
- package com.getcapacitor.community.stripe.terminal;
2
-
3
- import android.Manifest;
4
- import android.app.Activity;
5
- import android.app.Application;
6
- import android.bluetooth.BluetoothAdapter;
7
- import android.content.Context;
8
- import android.content.pm.PackageManager;
9
- import android.os.Build;
10
- import android.util.Log;
11
- import androidx.annotation.NonNull;
12
- import androidx.annotation.Nullable;
13
- import androidx.core.app.ActivityCompat;
14
- import androidx.core.util.Supplier;
15
- import com.getcapacitor.JSArray;
16
- import com.getcapacitor.JSObject;
17
- import com.getcapacitor.PluginCall;
18
- import com.getcapacitor.community.stripe.terminal.helper.TerminalMappers;
19
- import com.getcapacitor.community.stripe.terminal.models.Executor;
20
- import com.google.android.gms.common.util.BiConsumer;
21
- import com.stripe.stripeterminal.Terminal;
22
- import com.stripe.stripeterminal.TerminalApplicationDelegate;
23
- import com.stripe.stripeterminal.external.callable.Callback;
24
- import com.stripe.stripeterminal.external.callable.Cancelable;
25
- import com.stripe.stripeterminal.external.callable.DiscoveryListener;
26
- import com.stripe.stripeterminal.external.callable.InternetReaderListener;
27
- import com.stripe.stripeterminal.external.callable.MobileReaderListener;
28
- import com.stripe.stripeterminal.external.callable.PaymentIntentCallback;
29
- import com.stripe.stripeterminal.external.callable.ReaderCallback;
30
- //import com.stripe.stripeterminal.external.callable.ReaderReconnectionListener;
31
- import com.stripe.stripeterminal.external.callable.TapToPayReaderListener;
32
- import com.stripe.stripeterminal.external.callable.TerminalListener;
33
- import com.stripe.stripeterminal.external.models.BatteryStatus;
34
- import com.stripe.stripeterminal.external.models.CardPresentDetails;
35
- import com.stripe.stripeterminal.external.models.Cart;
36
- import com.stripe.stripeterminal.external.models.CartLineItem;
37
- import com.stripe.stripeterminal.external.models.CollectConfiguration;
38
- import com.stripe.stripeterminal.external.models.ConnectionConfiguration;
39
- import com.stripe.stripeterminal.external.models.ConnectionConfiguration.BluetoothConnectionConfiguration;
40
- import com.stripe.stripeterminal.external.models.ConnectionConfiguration.InternetConnectionConfiguration;
41
- import com.stripe.stripeterminal.external.models.ConnectionConfiguration.UsbConnectionConfiguration;
42
- import com.stripe.stripeterminal.external.models.ConnectionStatus;
43
- import com.stripe.stripeterminal.external.models.DisconnectReason;
44
- import com.stripe.stripeterminal.external.models.DiscoveryConfiguration;
45
- import com.stripe.stripeterminal.external.models.PaymentIntent;
46
- import com.stripe.stripeterminal.external.models.PaymentMethod;
47
- import com.stripe.stripeterminal.external.models.PaymentStatus;
48
- import com.stripe.stripeterminal.external.models.Reader;
49
- import com.stripe.stripeterminal.external.models.ReaderDisplayMessage;
50
- import com.stripe.stripeterminal.external.models.ReaderEvent;
51
- import com.stripe.stripeterminal.external.models.ReaderInputOptions;
52
- import com.stripe.stripeterminal.external.models.ReaderSoftwareUpdate;
53
- import com.stripe.stripeterminal.external.models.SimulateReaderUpdate;
54
- import com.stripe.stripeterminal.external.models.SimulatedCard;
55
- import com.stripe.stripeterminal.external.models.SimulatedCardType;
56
- import com.stripe.stripeterminal.external.models.SimulatorConfiguration;
57
- import com.stripe.stripeterminal.external.models.TerminalException;
58
- import com.stripe.stripeterminal.log.LogLevel;
59
- import java.util.ArrayList;
60
- import java.util.List;
61
- import java.util.Objects;
62
- import org.jetbrains.annotations.NotNull;
63
- import org.json.JSONException;
64
- import org.json.JSONObject;
65
-
66
- public class StripeTerminal extends Executor {
67
-
68
- private TokenProvider tokenProvider;
69
- private Cancelable discoveryCancelable;
70
- private Cancelable collectCancelable;
71
- private Cancelable installUpdateCancelable;
72
- private Cancelable cancelReaderConnectionCancellable;
73
- private List<Reader> discoveredReadersList;
74
- private String locationId;
75
- private PluginCall collectCall;
76
- private PluginCall confirmPaymentIntentCall;
77
- private final JSObject emptyObject = new JSObject();
78
- private Boolean isTest;
79
- private TerminalConnectTypes terminalConnectType;
80
- private PaymentIntent paymentIntentInstance;
81
-
82
- private final TerminalMappers terminalMappers = new TerminalMappers();
83
-
84
- public StripeTerminal(
85
- Supplier<Context> contextSupplier,
86
- Supplier<Activity> activitySupplier,
87
- BiConsumer<String, JSObject> notifyListenersFunction,
88
- String pluginLogTag
89
- ) {
90
- super(contextSupplier, activitySupplier, notifyListenersFunction, pluginLogTag, "StripeTerminalExecutor");
91
- this.contextSupplier = contextSupplier;
92
- this.discoveredReadersList = new ArrayList<>();
93
- }
94
-
95
- public void initialize(final PluginCall call) throws TerminalException {
96
- this.isTest = call.getBoolean("isTest", true);
97
-
98
- BluetoothAdapter bluetooth = BluetoothAdapter.getDefaultAdapter();
99
- if (!bluetooth.isEnabled()) {
100
- if (
101
- ActivityCompat.checkSelfPermission(this.contextSupplier.get(), Manifest.permission.BLUETOOTH_CONNECT) ==
102
- PackageManager.PERMISSION_GRANTED
103
- ) {
104
- bluetooth.enable();
105
- }
106
- }
107
-
108
- this.activitySupplier.get()
109
- .runOnUiThread(() -> {
110
- TerminalApplicationDelegate.onCreate((Application) this.contextSupplier.get().getApplicationContext());
111
- notifyListeners(TerminalEnumEvent.Loaded.getWebEventName(), emptyObject);
112
- call.resolve();
113
- });
114
- TerminalListener listener = new TerminalListener() {
115
- @Override
116
- public void onConnectionStatusChange(@NonNull ConnectionStatus status) {
117
- notifyListeners(
118
- TerminalEnumEvent.ConnectionStatusChange.getWebEventName(),
119
- new JSObject().put("status", status.toString())
120
- );
121
- }
122
-
123
- @Override
124
- public void onPaymentStatusChange(@NonNull PaymentStatus status) {
125
- notifyListeners(TerminalEnumEvent.PaymentStatusChange.getWebEventName(), new JSObject().put("status", status.toString()));
126
- }
127
- };
128
- LogLevel logLevel = LogLevel.VERBOSE;
129
- this.tokenProvider = new TokenProvider(
130
- this.contextSupplier,
131
- call.getString("tokenProviderEndpoint", ""),
132
- this.notifyListenersFunction
133
- );
134
- if (!Terminal.isInitialized()) {
135
- Terminal.initTerminal(this.contextSupplier.get().getApplicationContext(), logLevel, this.tokenProvider, listener);
136
- }
137
- Terminal.getInstance();
138
- }
139
-
140
- public void setConnectionToken(PluginCall call) {
141
- this.tokenProvider.setConnectionToken(call);
142
- }
143
-
144
- public void setSimulatorConfiguration(PluginCall call) {
145
- try {
146
- Terminal.getInstance()
147
- .setSimulatorConfiguration(
148
- new SimulatorConfiguration(
149
- SimulateReaderUpdate.valueOf(call.getString("update", "UPDATE_AVAILABLE")),
150
- new SimulatedCard(SimulatedCardType.valueOf(call.getString("simulatedCard", "VISA"))),
151
- call.getLong("simulatedTipAmount", null),
152
- false
153
- )
154
- );
155
-
156
- call.resolve();
157
- } catch (Exception ex) {
158
- call.reject(ex.getMessage());
159
- }
160
- }
161
-
162
- public void onDiscoverReaders(final PluginCall call) {
163
- if (
164
- ActivityCompat.checkSelfPermission(this.contextSupplier.get(), Manifest.permission.ACCESS_FINE_LOCATION) !=
165
- PackageManager.PERMISSION_GRANTED
166
- ) {
167
- Log.d(this.logTag, "android.permission.ACCESS_FINE_LOCATION permission is not granted.");
168
- call.reject("android.permission.ACCESS_FINE_LOCATION permission is not granted.");
169
- return;
170
- }
171
-
172
- this.locationId = call.getString("locationId");
173
- final DiscoveryConfiguration config;
174
- if (Objects.equals(call.getString("type"), TerminalConnectTypes.TapToPay.getWebEventName())) {
175
- config = new DiscoveryConfiguration.TapToPayDiscoveryConfiguration(this.isTest);
176
- this.terminalConnectType = TerminalConnectTypes.TapToPay;
177
- } else if (Objects.equals(call.getString("type"), TerminalConnectTypes.Internet.getWebEventName())) {
178
- config = new DiscoveryConfiguration.InternetDiscoveryConfiguration(0, this.locationId, this.isTest);
179
- this.terminalConnectType = TerminalConnectTypes.Internet;
180
- } else if (Objects.equals(call.getString("type"), TerminalConnectTypes.Usb.getWebEventName())) {
181
- config = new DiscoveryConfiguration.UsbDiscoveryConfiguration(0, this.isTest);
182
- this.terminalConnectType = TerminalConnectTypes.Usb;
183
- } else if (
184
- Objects.equals(call.getString("type"), TerminalConnectTypes.Bluetooth.getWebEventName()) ||
185
- Objects.equals(call.getString("type"), TerminalConnectTypes.Simulated.getWebEventName())
186
- ) {
187
- config = new DiscoveryConfiguration.BluetoothDiscoveryConfiguration(0, this.isTest);
188
- this.terminalConnectType = TerminalConnectTypes.Bluetooth;
189
- } else {
190
- call.unimplemented(call.getString("type") + " is not support now");
191
- return;
192
- }
193
-
194
- final DiscoveryListener discoveryListener = readers -> {
195
- // 検索したReaderの一覧をListenerで渡す
196
- Log.d(logTag, String.valueOf(readers.get(0).getSerialNumber()));
197
- this.discoveredReadersList = readers;
198
- JSArray readersJSObject = new JSArray();
199
-
200
- int i = 0;
201
- for (Reader reader : this.discoveredReadersList) {
202
- readersJSObject.put(convertReaderInterface(reader).put("index", String.valueOf(i)));
203
- }
204
- this.notifyListeners(TerminalEnumEvent.DiscoveredReaders.getWebEventName(), new JSObject().put("readers", readersJSObject));
205
- call.resolve(new JSObject().put("readers", readersJSObject));
206
- };
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");
215
- }
216
-
217
- @Override
218
- public void onFailure(@NonNull TerminalException ex) {
219
- Log.d(logTag, ex.getLocalizedMessage());
220
- }
221
- }
222
- );
223
- }
224
-
225
- public void connectReader(final PluginCall call) {
226
- if (this.terminalConnectType == TerminalConnectTypes.TapToPay) {
227
- this.connectTapToPayReader(call);
228
- } else if (this.terminalConnectType == TerminalConnectTypes.Internet) {
229
- this.connectInternetReader(call);
230
- } else if (this.terminalConnectType == TerminalConnectTypes.Usb) {
231
- this.connectUsbReader(call);
232
- } else if (this.terminalConnectType == TerminalConnectTypes.Bluetooth) {
233
- this.connectBluetoothReader(call);
234
- } else {
235
- call.reject("type is not defined.");
236
- }
237
- }
238
-
239
- public void getConnectedReader(final PluginCall call) {
240
- Reader reader = Terminal.getInstance().getConnectedReader();
241
- if (reader == null) {
242
- call.resolve(new JSObject().put("reader", JSObject.NULL));
243
- } else {
244
- call.resolve(new JSObject().put("reader", convertReaderInterface(reader)));
245
- }
246
- }
247
-
248
- public void disconnectReader(final PluginCall call) {
249
- if (Terminal.getInstance().getConnectedReader() == null) {
250
- call.resolve();
251
- return;
252
- }
253
-
254
- Terminal.getInstance()
255
- .disconnectReader(
256
- new Callback() {
257
- @Override
258
- public void onSuccess() {
259
- notifyListeners(TerminalEnumEvent.DisconnectedReader.getWebEventName(), emptyObject);
260
- call.resolve();
261
- }
262
-
263
- @Override
264
- public void onFailure(@NonNull TerminalException ex) {
265
- call.reject(ex.getLocalizedMessage(), ex);
266
- }
267
- }
268
- );
269
- }
270
-
271
- private void connectTapToPayReader(final PluginCall call) {
272
- JSObject reader = call.getObject("reader");
273
- String serialNumber = reader.getString("serialNumber");
274
- this.locationId = call.getString("locationId", this.locationId);
275
-
276
- Reader foundReader = this.findReader(this.discoveredReadersList, serialNumber);
277
-
278
- if (serialNumber == null || foundReader == null) {
279
- call.reject("The reader value is not set correctly.");
280
- return;
281
- }
282
-
283
- Boolean autoReconnectOnUnexpectedDisconnect = Objects.requireNonNullElse(
284
- call.getBoolean("autoReconnectOnUnexpectedDisconnect", false),
285
- false
286
- );
287
-
288
- ConnectionConfiguration.TapToPayConnectionConfiguration config = new ConnectionConfiguration.TapToPayConnectionConfiguration(
289
- this.locationId,
290
- autoReconnectOnUnexpectedDisconnect,
291
- this.tapToPayReaderListener
292
- );
293
- Terminal.getInstance().connectReader(foundReader, config, this.readerCallback(call));
294
- }
295
-
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
-
305
- @Override
306
- public void onReaderReconnectStarted(
307
- @NonNull Reader reader,
308
- @NonNull Cancelable cancelReconnect,
309
- @NonNull DisconnectReason reason
310
- ) {
311
- cancelReaderConnectionCancellable = cancelReconnect;
312
- notifyListeners(
313
- TerminalEnumEvent.ReaderReconnectStarted.getWebEventName(),
314
- new JSObject().put("reason", reason.toString()).put("reader", convertReaderInterface(reader))
315
- );
316
- }
317
-
318
- @Override
319
- public void onReaderReconnectSucceeded(@NonNull Reader reader) {
320
- notifyListeners(
321
- TerminalEnumEvent.ReaderReconnectSucceeded.getWebEventName(),
322
- new JSObject().put("reader", convertReaderInterface(reader))
323
- );
324
- }
325
-
326
- @Override
327
- public void onDisconnect(@NonNull DisconnectReason reason) {
328
- notifyListeners(TerminalEnumEvent.DisconnectedReader.getWebEventName(), new JSObject().put("reason", reason.toString()));
329
- }
330
- };
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
-
366
- private void connectInternetReader(final PluginCall call) {
367
- JSObject reader = call.getObject("reader");
368
- String serialNumber = reader.getString("serialNumber");
369
- this.locationId = call.getString("locationId", this.locationId);
370
-
371
- Reader foundReader = this.findReader(this.discoveredReadersList, serialNumber);
372
-
373
- if (serialNumber == null || foundReader == null) {
374
- call.reject("The reader value is not set correctly.");
375
- return;
376
- }
377
-
378
- InternetConnectionConfiguration config = new InternetConnectionConfiguration(true, this.internetReaderListener);
379
- Terminal.getInstance().connectReader(foundReader, config, this.readerCallback(call));
380
- }
381
-
382
- private void connectUsbReader(final PluginCall call) {
383
- JSObject reader = call.getObject("reader");
384
- String serialNumber = reader.getString("serialNumber");
385
- this.locationId = call.getString("locationId", this.locationId);
386
-
387
- Reader foundReader = this.findReader(this.discoveredReadersList, serialNumber);
388
-
389
- if (serialNumber == null || foundReader == null) {
390
- call.reject("The reader value is not set correctly.");
391
- return;
392
- }
393
-
394
- UsbConnectionConfiguration config = new UsbConnectionConfiguration(this.locationId, true, this.readerListener());
395
- Terminal.getInstance().connectReader(foundReader, config, this.readerCallback(call));
396
- }
397
-
398
- private void connectBluetoothReader(final PluginCall call) {
399
- JSObject reader = call.getObject("reader");
400
- String serialNumber = reader.getString("serialNumber");
401
- this.locationId = call.getString("locationId", this.locationId);
402
-
403
- Reader foundReader = this.findReader(this.discoveredReadersList, serialNumber);
404
-
405
- if (serialNumber == null || foundReader == null) {
406
- call.reject("The reader value is not set correctly.");
407
- return;
408
- }
409
- Boolean autoReconnectOnUnexpectedDisconnect = Objects.requireNonNullElse(
410
- call.getBoolean("autoReconnectOnUnexpectedDisconnect", false),
411
- false
412
- );
413
-
414
- BluetoothConnectionConfiguration config = new BluetoothConnectionConfiguration(
415
- this.locationId,
416
- autoReconnectOnUnexpectedDisconnect,
417
- this.readerListener()
418
- );
419
- Terminal.getInstance().connectReader(foundReader, config, this.readerCallback(call));
420
- }
421
-
422
- public void cancelDiscoverReaders(final PluginCall call) {
423
- if (discoveryCancelable == null || discoveryCancelable.isCompleted()) {
424
- call.resolve();
425
- return;
426
- }
427
- discoveryCancelable.cancel(
428
- new Callback() {
429
- @Override
430
- public void onSuccess() {
431
- notifyListeners(TerminalEnumEvent.CancelDiscoveredReaders.getWebEventName(), emptyObject);
432
- call.resolve();
433
- }
434
-
435
- @Override
436
- public void onFailure(@NonNull TerminalException ex) {
437
- call.reject(ex.getLocalizedMessage(), ex);
438
- }
439
- }
440
- );
441
- }
442
-
443
- public void collectPaymentMethod(final PluginCall call) {
444
- String paymentIntent = call.getString("paymentIntent");
445
- if (paymentIntent == null) {
446
- call.reject("The value of paymentIntent is not set correctly.");
447
- return;
448
- }
449
- this.collectCall = call;
450
- Terminal.getInstance().retrievePaymentIntent(paymentIntent, createPaymentIntentCallback);
451
- }
452
-
453
- public void cancelCollectPaymentMethod(final PluginCall call) {
454
- if (this.collectCancelable == null || this.collectCancelable.isCompleted()) {
455
- call.resolve();
456
- return;
457
- }
458
-
459
- this.collectCancelable.cancel(
460
- new Callback() {
461
- @Override
462
- public void onSuccess() {
463
- notifyListeners(TerminalEnumEvent.Canceled.getWebEventName(), emptyObject);
464
- call.resolve();
465
- }
466
-
467
- @Override
468
- public void onFailure(@NonNull TerminalException e) {
469
- call.reject(e.getLocalizedMessage());
470
- }
471
- }
472
- );
473
- }
474
-
475
- private final PaymentIntentCallback createPaymentIntentCallback = new PaymentIntentCallback() {
476
- @Override
477
- public void onSuccess(@NonNull PaymentIntent paymentIntent) {
478
- CollectConfiguration collectConfig = new CollectConfiguration.Builder().updatePaymentIntent(true).build();
479
- collectCancelable = Terminal.getInstance().collectPaymentMethod(paymentIntent, collectPaymentMethodCallback, collectConfig);
480
- }
481
-
482
- @Override
483
- public void onFailure(@NonNull TerminalException exception) {
484
- notifyListeners(TerminalEnumEvent.Failed.getWebEventName(), emptyObject);
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);
492
- }
493
- };
494
-
495
- private final PaymentIntentCallback collectPaymentMethodCallback = new PaymentIntentCallback() {
496
- @Override
497
- public void onSuccess(PaymentIntent paymentIntent) {
498
- paymentIntentInstance = paymentIntent;
499
- notifyListeners(TerminalEnumEvent.CollectedPaymentIntent.getWebEventName(), emptyObject);
500
-
501
- PaymentMethod pm = paymentIntent.getPaymentMethod();
502
- CardPresentDetails card = null;
503
-
504
- if (pm != null) {
505
- card = pm.getCardPresentDetails() != null ? pm.getCardPresentDetails() : pm.getInteracPresentDetails();
506
- }
507
-
508
- if (card != null) {
509
- collectCall.resolve(
510
- new JSObject()
511
- .put("brand", card.getBrand())
512
- .put("cardholderName", card.getCardholderName())
513
- .put("country", card.getCountry())
514
- .put("emvAuthData", card.getEmvAuthData())
515
- .put("expMonth", card.getExpMonth())
516
- .put("expYear", card.getExpYear())
517
- .put("funding", card.getFunding())
518
- .put("generatedCard", card.getGeneratedCard())
519
- .put("incrementalAuthorizationStatus", card.getIncrementalAuthorizationStatus())
520
- .put("last4", card.getLast4())
521
- .put("networks", card.getNetworks())
522
- .put("readMethod", card.getReadMethod())
523
- );
524
- } else {
525
- collectCall.resolve();
526
- }
527
- }
528
-
529
- @Override
530
- public void onFailure(@NonNull TerminalException exception) {
531
- notifyListeners(TerminalEnumEvent.Failed.getWebEventName(), emptyObject);
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);
543
- }
544
- };
545
-
546
- public void confirmPaymentIntent(final PluginCall call) {
547
- if (this.paymentIntentInstance == null) {
548
- call.reject("PaymentIntent not found for confirmPaymentIntent. Use collect method first and try again.");
549
- return;
550
- }
551
-
552
- this.confirmPaymentIntentCall = call;
553
- Terminal.getInstance().confirmPaymentIntent(this.paymentIntentInstance, confirmPaymentMethodCallback);
554
- }
555
-
556
- public void installAvailableUpdate(final PluginCall call) {
557
- Terminal.getInstance().installAvailableUpdate();
558
- call.resolve(emptyObject);
559
- }
560
-
561
- public void cancelInstallUpdate(final PluginCall call) {
562
- if (this.installUpdateCancelable == null || this.installUpdateCancelable.isCompleted()) {
563
- call.resolve();
564
- return;
565
- }
566
-
567
- this.installUpdateCancelable.cancel(
568
- new Callback() {
569
- @Override
570
- public void onSuccess() {
571
- call.resolve();
572
- }
573
-
574
- @Override
575
- public void onFailure(@NonNull TerminalException e) {
576
- call.reject(e.getLocalizedMessage());
577
- }
578
- }
579
- );
580
- }
581
-
582
- public void setReaderDisplay(final PluginCall call) {
583
- String currency = call.getString("currency", null);
584
- if (currency == null) {
585
- call.reject("You must provide a currency value");
586
- return;
587
- }
588
-
589
- int tax = Objects.requireNonNullElse(call.getInt("tax", 0), 0);
590
- int total = Objects.requireNonNullElse(call.getInt("total", 0), 0);
591
- if (total == 0) {
592
- call.reject("You must provide a total value");
593
- return;
594
- }
595
-
596
- JSArray lineItems = call.getArray("lineItems");
597
- List<JSONObject> lineItemsList;
598
- try {
599
- lineItemsList = lineItems.toList();
600
- } catch (JSONException e) {
601
- call.reject(e.getLocalizedMessage());
602
- return;
603
- }
604
-
605
- List<CartLineItem> cartLineItems = new ArrayList<>();
606
- for (JSONObject item : lineItemsList) {
607
- try {
608
- JSObject itemObj = JSObject.fromJSONObject(item);
609
- cartLineItems.add(
610
- new CartLineItem(
611
- Objects.requireNonNull(itemObj.getString("displayName")),
612
- Objects.requireNonNull(itemObj.getInteger("quantity")),
613
- Objects.requireNonNull(itemObj.getInteger("amount"))
614
- )
615
- );
616
- } catch (JSONException e) {
617
- call.reject(e.getLocalizedMessage());
618
- return;
619
- }
620
- }
621
-
622
- Cart cart = new Cart.Builder(currency, tax, total, cartLineItems).build();
623
-
624
- Terminal.getInstance()
625
- .setReaderDisplay(
626
- cart,
627
- new Callback() {
628
- @Override
629
- public void onSuccess() {
630
- call.resolve();
631
- }
632
-
633
- @Override
634
- public void onFailure(@NonNull TerminalException e) {
635
- call.reject(e.getErrorMessage());
636
- }
637
- }
638
- );
639
- }
640
-
641
- public void clearReaderDisplay(final PluginCall call) {
642
- Terminal.getInstance()
643
- .clearReaderDisplay(
644
- new Callback() {
645
- @Override
646
- public void onSuccess() {
647
- call.resolve();
648
- }
649
-
650
- @Override
651
- public void onFailure(@NonNull TerminalException e) {
652
- call.reject(e.getErrorMessage());
653
- }
654
- }
655
- );
656
- }
657
-
658
- public void rebootReader(final PluginCall call) {
659
- Terminal.getInstance()
660
- .rebootReader(
661
- new Callback() {
662
- @Override
663
- public void onSuccess() {
664
- paymentIntentInstance = null;
665
- call.resolve(emptyObject);
666
- }
667
-
668
- @Override
669
- public void onFailure(@NonNull TerminalException e) {
670
- call.reject(e.getLocalizedMessage());
671
- }
672
- }
673
- );
674
- }
675
-
676
- public void cancelReaderReconnection(final PluginCall call) {
677
- if (cancelReaderConnectionCancellable == null || cancelReaderConnectionCancellable.isCompleted()) {
678
- call.resolve();
679
- return;
680
- }
681
- cancelReaderConnectionCancellable.cancel(
682
- new Callback() {
683
- @Override
684
- public void onSuccess() {
685
- call.resolve();
686
- }
687
-
688
- @Override
689
- public void onFailure(@NonNull TerminalException ex) {
690
- call.reject(ex.getLocalizedMessage(), ex);
691
- }
692
- }
693
- );
694
- }
695
-
696
- private final PaymentIntentCallback confirmPaymentMethodCallback = new PaymentIntentCallback() {
697
- @Override
698
- public void onSuccess(@NonNull PaymentIntent paymentIntent) {
699
- notifyListeners(TerminalEnumEvent.ConfirmedPaymentIntent.getWebEventName(), emptyObject);
700
- paymentIntentInstance = null;
701
- confirmPaymentIntentCall.resolve();
702
- }
703
-
704
- @Override
705
- public void onFailure(TerminalException exception) {
706
- notifyListeners(TerminalEnumEvent.Failed.getWebEventName(), emptyObject);
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);
714
- }
715
- };
716
-
717
- private ReaderCallback readerCallback(final PluginCall call) {
718
- return new ReaderCallback() {
719
- @Override
720
- public void onSuccess(@NonNull Reader r) {
721
- notifyListeners(TerminalEnumEvent.ConnectedReader.getWebEventName(), emptyObject);
722
- call.resolve();
723
- }
724
-
725
- @Override
726
- public void onFailure(@NonNull TerminalException ex) {
727
- ex.printStackTrace();
728
- call.reject(ex.getLocalizedMessage(), ex);
729
- }
730
- };
731
- }
732
-
733
- private MobileReaderListener readerListener() {
734
- return new MobileReaderListener() {
735
- @Override
736
- public void onStartInstallingUpdate(@NotNull ReaderSoftwareUpdate update, @NotNull Cancelable cancelable) {
737
- // Show UI communicating that a required update has started installing
738
- installUpdateCancelable = cancelable;
739
- notifyListeners(
740
- TerminalEnumEvent.StartInstallingUpdate.getWebEventName(),
741
- new JSObject().put("update", convertReaderSoftwareUpdate(update))
742
- );
743
- }
744
-
745
- @Override
746
- public void onReportReaderSoftwareUpdateProgress(float progress) {
747
- // Update the progress of the install
748
- notifyListeners(TerminalEnumEvent.ReaderSoftwareUpdateProgress.getWebEventName(), new JSObject().put("progress", progress));
749
- }
750
-
751
- @Override
752
- public void onFinishInstallingUpdate(@Nullable ReaderSoftwareUpdate update, @Nullable TerminalException error) {
753
- JSObject eventObject = new JSObject();
754
-
755
- if (error != null) {
756
- // note: Since errorCode cannot be obtained in iOS, use errorMessage for unification.
757
- eventObject.put("error", error.getLocalizedMessage());
758
- notifyListeners(TerminalEnumEvent.FinishInstallingUpdate.getWebEventName(), eventObject);
759
- return;
760
- }
761
-
762
- eventObject.put("update", update == null ? null : convertReaderSoftwareUpdate(update));
763
- notifyListeners(TerminalEnumEvent.FinishInstallingUpdate.getWebEventName(), eventObject);
764
- }
765
-
766
- @Override
767
- public void onBatteryLevelUpdate(float batteryLevel, @NonNull BatteryStatus batteryStatus, boolean isCharging) {
768
- notifyListeners(
769
- TerminalEnumEvent.BatteryLevel.getWebEventName(),
770
- new JSObject().put("level", batteryLevel).put("charging", isCharging).put("status", batteryStatus.toString())
771
- );
772
- }
773
-
774
- @Override
775
- public void onReportLowBatteryWarning() {}
776
-
777
- @Override
778
- public void onReportAvailableUpdate(@NotNull ReaderSoftwareUpdate update) {
779
- // An update is available for the connected reader. Show this update in your application.
780
- // This update can be installed using `Terminal.getInstance().installAvailableUpdate`.
781
- notifyListeners(
782
- TerminalEnumEvent.ReportAvailableUpdate.getWebEventName(),
783
- new JSObject().put("update", convertReaderSoftwareUpdate(update))
784
- );
785
- }
786
-
787
- @Override
788
- public void onReportReaderEvent(@NotNull ReaderEvent event) {
789
- notifyListeners(TerminalEnumEvent.ReaderEvent.getWebEventName(), new JSObject().put("event", event.toString()));
790
- }
791
-
792
- @Override
793
- public void onRequestReaderDisplayMessage(@NotNull ReaderDisplayMessage message) {
794
- notifyListeners(
795
- TerminalEnumEvent.RequestDisplayMessage.getWebEventName(),
796
- new JSObject().put("messageType", message.name()).put("message", message.toString())
797
- );
798
- }
799
-
800
- @Override
801
- public void onRequestReaderInput(@NotNull ReaderInputOptions options) {
802
- List<ReaderInputOptions.ReaderInputOption> optionsList = options.getOptions();
803
- JSArray jsOptions = new JSArray();
804
- for (ReaderInputOptions.ReaderInputOption optionType : optionsList) {
805
- jsOptions.put(optionType.name());
806
- }
807
-
808
- notifyListeners(
809
- TerminalEnumEvent.RequestReaderInput.getWebEventName(),
810
- new JSObject().put("options", jsOptions).put("message", options.toString())
811
- );
812
- }
813
-
814
- public void onDisconnect(@NotNull DisconnectReason reason) {
815
- notifyListeners(TerminalEnumEvent.DisconnectedReader.getWebEventName(), new JSObject().put("reason", reason.toString()));
816
- }
817
- };
818
- }
819
-
820
- private JSObject convertReaderInterface(Reader reader) {
821
- return new JSObject()
822
- .put("label", reader.getLabel())
823
- .put("serialNumber", reader.getSerialNumber())
824
- .put("id", reader.getId())
825
- .put("locationId", reader.getLocation() != null ? reader.getLocation().getId() : null)
826
- .put("deviceSoftwareVersion", reader.getDeviceSwVersion$public_release())
827
- .put("simulated", reader.isSimulated())
828
- .put("serialNumber", reader.getSerialNumber())
829
- .put("ipAddress", reader.getIpAddress())
830
- .put("baseUrl", reader.getBaseUrl())
831
- .put("bootloaderVersion", reader.getBootloaderVersion())
832
- .put("configVersion", reader.getConfigVersion())
833
- .put("emvKeyProfileId", reader.getEmvKeyProfileId())
834
- .put("firmwareVersion", reader.getFirmwareVersion())
835
- .put("hardwareVersion", reader.getHardwareVersion())
836
- .put("macKeyProfileId", reader.getMacKeyProfileId())
837
- .put("pinKeyProfileId", reader.getPinKeyProfileId())
838
- .put("trackKeyProfileId", reader.getTrackKeyProfileId())
839
- .put("settingsVersion", reader.getSettingsVersion())
840
- .put("pinKeysetId", reader.getPinKeysetId())
841
- .put("deviceType", terminalMappers.mapFromDeviceType(reader.getDeviceType()))
842
- .put("status", terminalMappers.mapFromNetworkStatus(reader.getNetworkStatus()))
843
- .put("locationStatus", terminalMappers.mapFromLocationStatus(reader.getLocationStatus()))
844
- .put("batteryLevel", reader.getBatteryLevel() != null ? reader.getBatteryLevel().doubleValue() : null)
845
- .put("availableUpdate", terminalMappers.mapFromReaderSoftwareUpdate(reader.getAvailableUpdate()))
846
- .put("location", terminalMappers.mapFromLocation(reader.getLocation()));
847
- }
848
-
849
- private JSObject convertReaderSoftwareUpdate(ReaderSoftwareUpdate update) {
850
- return terminalMappers.mapFromReaderSoftwareUpdate(update);
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
- }
872
- }