@capacitor-community/stripe-terminal 5.2.0 → 5.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.
@@ -13,6 +13,6 @@ Pod::Spec.new do |s|
13
13
  s.source_files = 'ios/Plugin/**/*.{swift,h,m,c,cc,mm,cpp}'
14
14
  s.ios.deployment_target = '13.0'
15
15
  s.dependency 'Capacitor'
16
- s.dependency 'StripeTerminal'
16
+ s.dependency 'StripeTerminal', '~> 2.17.1'
17
17
  s.swift_version = '5.1'
18
18
  end
package/README.md CHANGED
@@ -24,11 +24,11 @@ npx cap sync
24
24
  Add permissions to your `android/app/src/main/AndroidManifest.xml` file:
25
25
 
26
26
  ```diff
27
- + <uses-permission android:name="android.permission.BLUETOOTH" />
28
- + <uses-permission android:name="android.permission.BLUETOOTH_ADMIN" />
29
- + <uses-permission android:name="android.permission.BLUETOOTH_SCAN" />
30
- + <uses-permission android:name="android.permission.BLUETOOTH_ADVERTISE" />
27
+ + <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
28
+ + <uses-permission android:name="android.permission.BLUETOOTH" android:maxSdkVersion="30" />
29
+ + <uses-permission android:name="android.permission.BLUETOOTH_ADMIN" android:maxSdkVersion="30" />
31
30
  + <uses-permission android:name="android.permission.BLUETOOTH_CONNECT" />
31
+ + <uses-permission android:name="android.permission.BLUETOOTH_SCAN" />
32
32
  ```
33
33
 
34
34
  If used in conjunction with the `@capacitor-community/stripe` plugin, the following settings may be necessary
@@ -44,6 +44,35 @@ android {
44
44
  }
45
45
  ```
46
46
 
47
+ And update minSdkVersion to 26 And compileSdkVersion to 34 in your `android/app/build.gradle` file:
48
+
49
+ ```diff
50
+ ext {
51
+ - minSdkVersion = 22
52
+ - compileSdkVersion = 33
53
+ + minSdkVersion = 26
54
+ + compileSdkVersion = 34
55
+ ```
56
+
57
+ ## Usage
58
+
59
+ ```typescript
60
+ (async ()=> {
61
+ /**
62
+ * tokenProviderEndpoint: The URL of your backend to provide a token. Use Post request to get a token.
63
+ */
64
+ await StripeTerminal.initialize({ tokenProviderEndpoint: 'https://example.com/token', isTest: true })
65
+ const { readers } = await StripeTerminal.discoverReaders({
66
+ type: TerminalConnectTypes.TapToPay,
67
+ locationId: "**************",
68
+ });
69
+ await StripeTerminal.connectReader({
70
+ reader: readers[0],
71
+ });
72
+ await StripeTerminal.collect({ paymentIntent: "**************" });
73
+ });
74
+ ```
75
+
47
76
  ## API
48
77
 
49
78
  <docgen-index>
@@ -3,17 +3,22 @@ ext {
3
3
  androidxAppCompatVersion = project.hasProperty('androidxAppCompatVersion') ? rootProject.ext.androidxAppCompatVersion : '1.6.1'
4
4
  androidxJunitVersion = project.hasProperty('androidxJunitVersion') ? rootProject.ext.androidxJunitVersion : '1.1.5'
5
5
  androidxEspressoCoreVersion = project.hasProperty('androidxEspressoCoreVersion') ? rootProject.ext.androidxEspressoCoreVersion : '3.5.1'
6
+
7
+ playServicesWalletVersion = project.hasProperty('playServicesWalletVersion') ? rootProject.ext.playServicesWalletVersion : '19.2.+'
8
+ volleyVersion = project.hasProperty('volleyVersion') ? rootProject.ext.volleyVersion : '1.2.1'
9
+ stripeterminalLocalmobileVersion = project.hasProperty('stripeterminalLocalmobileVersion') ? rootProject.ext.stripeterminalLocalmobileVersion : '3.0.+'
10
+ stripeterminalCoreVersion = project.hasProperty('stripeterminalCoreVersion') ? rootProject.ext.stripeterminalCoreVersion : '3.1.+'
6
11
  }
7
12
 
8
13
  buildscript {
9
- ext.kotlin_version = project.hasProperty("kotlin_version") ? rootProject.ext.kotlin_version : '1.8.20'
14
+ ext.kotlinVersion = project.hasProperty("kotlinVersion") ? rootProject.ext.kotlinVersion : '1.8.20'
10
15
  repositories {
11
16
  google()
12
17
  mavenCentral()
13
18
  }
14
19
  dependencies {
15
20
  classpath 'com.android.tools.build:gradle:8.0.0'
16
- classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
21
+ classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlinVersion"
17
22
  }
18
23
  }
19
24
 
@@ -62,9 +67,10 @@ dependencies {
62
67
  androidTestImplementation "androidx.test.ext:junit:$androidxJunitVersion"
63
68
  androidTestImplementation "androidx.test.espresso:espresso-core:$androidxEspressoCoreVersion"
64
69
 
65
- implementation "com.stripe:stripeterminal-localmobile:2.23.0"
66
- implementation "com.stripe:stripeterminal-core:2.23.0"
67
- implementation 'com.android.volley:volley:1.2.1'
68
- implementation 'com.google.android.gms:play-services-wallet:19.1.0'
69
- implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version"
70
- }
70
+ implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlinVersion"
71
+
72
+ implementation "com.stripe:stripeterminal-core:$stripeterminalCoreVersion"
73
+ implementation "com.stripe:stripeterminal-localmobile:$stripeterminalLocalmobileVersion"
74
+ implementation "com.android.volley:volley:$volleyVersion"
75
+ implementation "com.google.android.gms:play-services-wallet:$playServicesWalletVersion"
76
+ }
@@ -1,4 +1,5 @@
1
1
  <manifest xmlns:android="http://schemas.android.com/apk/res/android">
2
2
 
3
+ <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
3
4
  <uses-permission android:name="android.permission.BLUETOOTH_CONNECT" />
4
5
  </manifest>
@@ -5,12 +5,14 @@ import android.app.Activity;
5
5
  import android.app.Application;
6
6
  import android.bluetooth.BluetoothAdapter;
7
7
  import android.content.Context;
8
- import android.content.pm.ApplicationInfo;
9
8
  import android.content.pm.PackageManager;
10
9
  import android.util.Log;
10
+
11
11
  import androidx.annotation.NonNull;
12
+ import androidx.annotation.Nullable;
12
13
  import androidx.core.app.ActivityCompat;
13
14
  import androidx.core.util.Supplier;
15
+
14
16
  import com.getcapacitor.JSArray;
15
17
  import com.getcapacitor.JSObject;
16
18
  import com.getcapacitor.PluginCall;
@@ -23,20 +25,29 @@ import com.stripe.stripeterminal.external.callable.Cancelable;
23
25
  import com.stripe.stripeterminal.external.callable.DiscoveryListener;
24
26
  import com.stripe.stripeterminal.external.callable.PaymentIntentCallback;
25
27
  import com.stripe.stripeterminal.external.callable.ReaderCallback;
28
+ import com.stripe.stripeterminal.external.callable.ReaderListener;
26
29
  import com.stripe.stripeterminal.external.callable.TerminalListener;
27
- import com.stripe.stripeterminal.external.models.ConnectionConfiguration;
30
+ import com.stripe.stripeterminal.external.models.CardPresentDetails;
31
+ import com.stripe.stripeterminal.external.models.CollectConfiguration;
32
+ import com.stripe.stripeterminal.external.models.ConnectionConfiguration.BluetoothConnectionConfiguration;
33
+ import com.stripe.stripeterminal.external.models.ConnectionConfiguration.InternetConnectionConfiguration;
34
+ import com.stripe.stripeterminal.external.models.ConnectionConfiguration.LocalMobileConnectionConfiguration;
35
+ import com.stripe.stripeterminal.external.models.ConnectionConfiguration.UsbConnectionConfiguration;
28
36
  import com.stripe.stripeterminal.external.models.ConnectionStatus;
29
37
  import com.stripe.stripeterminal.external.models.DiscoveryConfiguration;
30
- import com.stripe.stripeterminal.external.models.DiscoveryMethod;
31
38
  import com.stripe.stripeterminal.external.models.PaymentIntent;
39
+ import com.stripe.stripeterminal.external.models.PaymentMethod;
32
40
  import com.stripe.stripeterminal.external.models.PaymentStatus;
33
41
  import com.stripe.stripeterminal.external.models.Reader;
42
+ import com.stripe.stripeterminal.external.models.ReaderSoftwareUpdate;
34
43
  import com.stripe.stripeterminal.external.models.TerminalException;
35
44
  import com.stripe.stripeterminal.log.LogLevel;
45
+
46
+ import org.jetbrains.annotations.NotNull;
47
+
36
48
  import java.util.ArrayList;
37
49
  import java.util.List;
38
50
  import java.util.Objects;
39
- import org.json.JSONException;
40
51
 
41
52
  public class StripeTerminal extends Executor {
42
53
 
@@ -47,17 +58,17 @@ public class StripeTerminal extends Executor {
47
58
  private PluginCall collectCall;
48
59
  private final JSObject emptyObject = new JSObject();
49
60
  private Boolean isTest;
50
- private DiscoveryMethod type;
61
+ private TerminalConnectTypes terminalConnectType;
51
62
 
52
63
  public StripeTerminal(
53
- Supplier<Context> contextSupplier,
54
- Supplier<Activity> activitySupplier,
55
- BiConsumer<String, JSObject> notifyListenersFunction,
56
- String pluginLogTag
64
+ Supplier<Context> contextSupplier,
65
+ Supplier<Activity> activitySupplier,
66
+ BiConsumer<String, JSObject> notifyListenersFunction,
67
+ String pluginLogTag
57
68
  ) {
58
69
  super(contextSupplier, activitySupplier, notifyListenersFunction, pluginLogTag, "StripeTerminalExecutor");
59
70
  this.contextSupplier = contextSupplier;
60
- this.readers = new ArrayList<Reader>();
71
+ this.readers = new ArrayList<>();
61
72
  }
62
73
 
63
74
  public void initialize(final PluginCall call) throws TerminalException {
@@ -66,36 +77,36 @@ public class StripeTerminal extends Executor {
66
77
  BluetoothAdapter bluetooth = BluetoothAdapter.getDefaultAdapter();
67
78
  if (!bluetooth.isEnabled()) {
68
79
  if (
69
- ActivityCompat.checkSelfPermission(this.contextSupplier.get(), Manifest.permission.BLUETOOTH_CONNECT) ==
70
- PackageManager.PERMISSION_GRANTED
80
+ ActivityCompat.checkSelfPermission(this.contextSupplier.get(), Manifest.permission.BLUETOOTH_CONNECT) ==
81
+ PackageManager.PERMISSION_GRANTED
71
82
  ) {
72
83
  bluetooth.enable();
73
84
  }
74
85
  }
75
86
 
76
87
  this.activitySupplier.get()
77
- .runOnUiThread(
78
- () -> {
79
- TerminalApplicationDelegate.onCreate((Application) this.contextSupplier.get().getApplicationContext());
80
- notifyListeners(TerminalEnumEvent.Loaded.getWebEventName(), emptyObject);
81
- call.resolve();
82
- }
83
- );
88
+ .runOnUiThread(
89
+ () -> {
90
+ TerminalApplicationDelegate.onCreate((Application) this.contextSupplier.get().getApplicationContext());
91
+ notifyListeners(TerminalEnumEvent.Loaded.getWebEventName(), emptyObject);
92
+ call.resolve();
93
+ }
94
+ );
84
95
  TerminalListener listener = new TerminalListener() {
85
96
  @Override
86
97
  public void onUnexpectedReaderDisconnect(@NonNull Reader reader) {
87
98
  // TODO: Listenerを追加
88
99
  }
89
- //
90
- // @Override
91
- // public void onConnectionStatusChange(@NonNull ConnectionStatus status) {
92
- // // TODO: Listenerを追加
93
- // }
94
- //
95
- // @Override
96
- // public void onPaymentStatusChange(@NonNull PaymentStatus status) {
97
- // // TODO: Listenerを追加
98
- // }
100
+
101
+ @Override
102
+ public void onConnectionStatusChange(@NonNull ConnectionStatus status) {
103
+ // TODO: Listenerを追加
104
+ }
105
+
106
+ @Override
107
+ public void onPaymentStatusChange(@NonNull PaymentStatus status) {
108
+ // TODO: Listenerを追加
109
+ }
99
110
  };
100
111
  LogLevel logLevel = LogLevel.VERBOSE;
101
112
  TokenProvider tokenProvider = new TokenProvider(this.contextSupplier, call.getString("tokenProviderEndpoint"));
@@ -105,18 +116,32 @@ public class StripeTerminal extends Executor {
105
116
  Terminal.getInstance();
106
117
  }
107
118
 
108
- public void onDiscoverReaders(final PluginCall call) {
119
+ public void onDiscoverReaders(final PluginCall call) {
120
+ if (ActivityCompat.checkSelfPermission(this.contextSupplier.get(), Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
121
+ Log.d(this.logTag, "android.permission.ACCESS_FINE_LOCATION permission is not granted.");
122
+ call.reject("android.permission.ACCESS_FINE_LOCATION permission is not granted.");
123
+ return;
124
+ }
125
+
109
126
  this.locationId = call.getString("locationId");
127
+ final DiscoveryConfiguration config;
110
128
  if (Objects.equals(call.getString("type"), TerminalConnectTypes.TapToPay.getWebEventName())) {
111
- this.type = DiscoveryMethod.LOCAL_MOBILE;
129
+ config = new DiscoveryConfiguration.LocalMobileDiscoveryConfiguration(this.isTest);
130
+ this.terminalConnectType = TerminalConnectTypes.TapToPay;
112
131
  } else if (Objects.equals(call.getString("type"), TerminalConnectTypes.Internet.getWebEventName())) {
113
- this.type = DiscoveryMethod.INTERNET;
132
+ config = new DiscoveryConfiguration.InternetDiscoveryConfiguration(this.locationId, this.isTest);
133
+ this.terminalConnectType = TerminalConnectTypes.Internet;
134
+ } else if (Objects.equals(call.getString("type"), TerminalConnectTypes.Usb.getWebEventName())) {
135
+ config = new DiscoveryConfiguration.UsbDiscoveryConfiguration(0, this.isTest);
136
+ this.terminalConnectType = TerminalConnectTypes.Usb;
137
+ } else if (Objects.equals(call.getString("type"), TerminalConnectTypes.Bluetooth.getWebEventName()) || Objects.equals(call.getString("type"), TerminalConnectTypes.Simulated.getWebEventName())) {
138
+ config = new DiscoveryConfiguration.BluetoothDiscoveryConfiguration(0, this.isTest);
139
+ this.terminalConnectType = TerminalConnectTypes.Bluetooth;
114
140
  } else {
115
141
  call.unimplemented(call.getString("type") + " is not support now");
116
142
  return;
117
143
  }
118
144
 
119
- final DiscoveryConfiguration config = new DiscoveryConfiguration(0, this.type, this.isTest, call.getString("locationId"));
120
145
  final DiscoveryListener discoveryListener = readers -> {
121
146
  // 検索したReaderの一覧をListenerで渡す
122
147
  Log.d(logTag, String.valueOf(readers.get(0).getSerialNumber()));
@@ -131,37 +156,39 @@ public class StripeTerminal extends Executor {
131
156
  call.resolve(new JSObject().put("readers", readersJSObject));
132
157
  };
133
158
  discoveryCancelable =
134
- Terminal
135
- .getInstance()
136
- .discoverReaders(
137
- config,
138
- discoveryListener,
139
- // Callback run after connectReader
140
- new Callback() {
141
- @Override
142
- public void onSuccess() {
143
- Log.d(logTag, "Finished discovering readers");
144
- }
145
-
146
- @Override
147
- public void onFailure(@NonNull TerminalException ex) {
148
- Log.d(logTag, ex.getLocalizedMessage());
149
- }
150
- }
151
- );
159
+ Terminal.getInstance()
160
+ .discoverReaders(
161
+ config,
162
+ discoveryListener,
163
+ new Callback() {
164
+ @Override
165
+ public void onSuccess() {
166
+ Log.d(logTag, "Finished discovering readers");
167
+ }
168
+ @Override
169
+ public void onFailure(@NonNull TerminalException ex) {
170
+ Log.d(logTag, ex.getLocalizedMessage());
171
+ }
172
+ }
173
+ );
152
174
  }
153
175
 
154
176
  public void connectReader(final PluginCall call) {
155
- if (this.type == DiscoveryMethod.LOCAL_MOBILE) {
177
+ if (this.terminalConnectType == TerminalConnectTypes.TapToPay) {
156
178
  this.connectLocalMobileReader(call);
157
- } else if (this.type == DiscoveryMethod.INTERNET) {
179
+ } else if (this.terminalConnectType == TerminalConnectTypes.Internet) {
158
180
  this.connectInternetReader(call);
181
+ } else if (this.terminalConnectType == TerminalConnectTypes.Usb) {
182
+ this.connectUsbReader(call);
183
+ } else if (this.terminalConnectType == TerminalConnectTypes.Bluetooth) {
184
+ this.connectBluetoothReader(call);
185
+ } else {
186
+ call.reject("type is not defined.");
159
187
  }
160
188
  }
161
189
 
162
190
  public void getConnectedReader(final PluginCall call) {
163
191
  Reader reader = Terminal.getInstance().getConnectedReader();
164
-
165
192
  if (reader == null) {
166
193
  call.resolve(new JSObject().put("reader", JSObject.NULL));
167
194
  } else {
@@ -195,7 +222,13 @@ public class StripeTerminal extends Executor {
195
222
 
196
223
  private void connectLocalMobileReader(final PluginCall call) {
197
224
  JSObject reader = call.getObject("reader");
198
- ConnectionConfiguration.LocalMobileConnectionConfiguration config = new ConnectionConfiguration.LocalMobileConnectionConfiguration(
225
+
226
+ if (reader.getInteger("index") == null) {
227
+ call.reject("The reader value is not set correctly.");
228
+ return;
229
+ }
230
+
231
+ LocalMobileConnectionConfiguration config = new LocalMobileConnectionConfiguration(
199
232
  this.locationId
200
233
  );
201
234
  Terminal
@@ -203,46 +236,48 @@ public class StripeTerminal extends Executor {
203
236
  .connectLocalMobileReader(
204
237
  this.readers.get(reader.getInteger("index")),
205
238
  config,
206
- new ReaderCallback() {
207
- @Override
208
- public void onSuccess(Reader r) {
209
- notifyListeners(TerminalEnumEvent.ConnectedReader.getWebEventName(), emptyObject);
210
- call.resolve();
211
- }
212
-
213
- @Override
214
- public void onFailure(@NonNull TerminalException ex) {
215
- ex.printStackTrace();
216
- call.reject(ex.getLocalizedMessage(), ex);
217
- }
218
- }
239
+ this.readerCallback(call)
219
240
  );
220
241
  }
221
242
 
222
243
  private void connectInternetReader(final PluginCall call) {
223
244
  JSObject reader = call.getObject("reader");
224
- ConnectionConfiguration.InternetConnectionConfiguration config = new ConnectionConfiguration.InternetConnectionConfiguration();
245
+ InternetConnectionConfiguration config = new InternetConnectionConfiguration();
225
246
  Terminal
226
247
  .getInstance()
227
248
  .connectInternetReader(
228
249
  this.readers.get(reader.getInteger("index")),
229
250
  config,
230
- new ReaderCallback() {
231
- @Override
232
- public void onSuccess(@NonNull Reader r) {
233
- notifyListeners(TerminalEnumEvent.ConnectedReader.getWebEventName(), emptyObject);
234
- call.resolve();
235
- }
236
-
237
- @Override
238
- public void onFailure(@NonNull TerminalException ex) {
239
- ex.printStackTrace();
240
- call.reject(ex.getLocalizedMessage(), ex);
241
- }
242
- }
251
+ this.readerCallback(call)
243
252
  );
244
253
  }
245
254
 
255
+ private void connectUsbReader(final PluginCall call) {
256
+ JSObject reader = call.getObject("reader");
257
+ UsbConnectionConfiguration config = new UsbConnectionConfiguration(this.locationId);
258
+ Terminal
259
+ .getInstance()
260
+ .connectUsbReader(
261
+ this.readers.get(reader.getInteger("index")),
262
+ config,
263
+ this.readerListener(),
264
+ this.readerCallback(call)
265
+ );
266
+ }
267
+
268
+ private void connectBluetoothReader(final PluginCall call) {
269
+ JSObject reader = call.getObject("reader");
270
+ BluetoothConnectionConfiguration config = new BluetoothConnectionConfiguration(this.locationId);
271
+ Terminal
272
+ .getInstance()
273
+ .connectBluetoothReader(
274
+ this.readers.get(reader.getInteger("index")),
275
+ config,
276
+ this.readerListener(),
277
+ this.readerCallback(call)
278
+ );
279
+ }
280
+
246
281
  public void cancelDiscoverReaders(final PluginCall call) {
247
282
  if (discoveryCancelable != null) {
248
283
  discoveryCancelable.cancel(
@@ -254,7 +289,7 @@ public class StripeTerminal extends Executor {
254
289
  }
255
290
 
256
291
  @Override
257
- public void onFailure(TerminalException ex) {
292
+ public void onFailure(@NonNull TerminalException ex) {
258
293
  call.reject(ex.getLocalizedMessage(), ex);
259
294
  }
260
295
  }
@@ -265,9 +300,11 @@ public class StripeTerminal extends Executor {
265
300
  }
266
301
 
267
302
  public void collect(final PluginCall call) {
268
- // メソッドを分割するためcallを永続化
303
+ if (call.getString("paymentIntent") == null) {
304
+ call.reject("The value of paymentIntent is not set correctly.");
305
+ return;
306
+ }
269
307
  this.collectCall = call;
270
-
271
308
  Terminal.getInstance().retrievePaymentIntent(call.getString("paymentIntent"), createPaymentIntentCallback);
272
309
  }
273
310
 
@@ -297,7 +334,10 @@ public class StripeTerminal extends Executor {
297
334
  private final PaymentIntentCallback createPaymentIntentCallback = new PaymentIntentCallback() {
298
335
  @Override
299
336
  public void onSuccess(@NonNull PaymentIntent paymentIntent) {
300
- collectCancelable = Terminal.getInstance().collectPaymentMethod(paymentIntent, collectPaymentMethodCallback);
337
+ CollectConfiguration collectConfig = new CollectConfiguration.Builder()
338
+ .updatePaymentIntent(true)
339
+ .build();
340
+ collectCancelable = Terminal.getInstance().collectPaymentMethod(paymentIntent, collectPaymentMethodCallback, collectConfig);
301
341
  }
302
342
 
303
343
  @Override
@@ -310,9 +350,34 @@ public class StripeTerminal extends Executor {
310
350
  // Step 3 - we've collected the payment method, so it's time to process the payment
311
351
  private final PaymentIntentCallback collectPaymentMethodCallback = new PaymentIntentCallback() {
312
352
  @Override
313
- public void onSuccess(@NonNull PaymentIntent paymentIntent) {
353
+ public void onSuccess(PaymentIntent paymentIntent) {
314
354
  collectCancelable = null;
315
- Terminal.getInstance().processPayment(paymentIntent, processPaymentCallback);
355
+ notifyListeners(TerminalEnumEvent.Completed.getWebEventName(), emptyObject);
356
+
357
+ PaymentMethod pm = paymentIntent.getPaymentMethod();
358
+ CardPresentDetails card = pm.getCardPresentDetails() != null
359
+ ? pm.getCardPresentDetails()
360
+ : pm.getInteracPresentDetails();
361
+
362
+ if (card != null) {
363
+ collectCall.resolve(new JSObject()
364
+ .put("brand", card.getBrand())
365
+ .put("cardholderName", card.getCardholderName())
366
+ .put("country", card.getCountry())
367
+ .put("emvAuthData", card.getEmvAuthData())
368
+ .put("expMonth", card.getExpMonth())
369
+ .put("expYear", card.getExpYear())
370
+ .put("funding", card.getFunding())
371
+ .put("generatedCard", card.getGeneratedCard())
372
+ .put("incrementalAuthorizationStatus", card.getIncrementalAuthorizationStatus())
373
+ .put("last4", card.getLast4())
374
+ .put("networks", card.getNetworks())
375
+ .put("readMethod", card.getReadMethod())
376
+
377
+ );
378
+ } else {
379
+ collectCall.resolve();
380
+ }
316
381
  }
317
382
 
318
383
  @Override
@@ -323,18 +388,49 @@ public class StripeTerminal extends Executor {
323
388
  }
324
389
  };
325
390
 
326
- // Step 4 - we've processed the payment! Show a success screen
327
- private final PaymentIntentCallback processPaymentCallback = new PaymentIntentCallback() {
328
- @Override
329
- public void onSuccess(@NonNull PaymentIntent paymentIntent) {
330
- notifyListeners(TerminalEnumEvent.Completed.getWebEventName(), emptyObject);
331
- collectCall.resolve();
332
- }
391
+ private ReaderCallback readerCallback(final PluginCall call) {
392
+ return new ReaderCallback() {
393
+ @Override
394
+ public void onSuccess(@NonNull Reader r) {
395
+ notifyListeners(TerminalEnumEvent.ConnectedReader.getWebEventName(), emptyObject);
396
+ call.resolve();
397
+ }
333
398
 
334
- @Override
335
- public void onFailure(@NonNull TerminalException ex) {
336
- notifyListeners(TerminalEnumEvent.Failed.getWebEventName(), emptyObject);
337
- collectCall.reject(ex.getLocalizedMessage(), ex);
338
- }
339
- };
399
+ @Override
400
+ public void onFailure(@NonNull TerminalException ex) {
401
+ ex.printStackTrace();
402
+ call.reject(ex.getLocalizedMessage(), ex);
403
+ }
404
+ };
405
+ }
406
+
407
+ private ReaderListener readerListener() {
408
+ return new ReaderListener() {
409
+ @Override
410
+ public void onStartInstallingUpdate(@NotNull ReaderSoftwareUpdate update, @NotNull Cancelable cancelable) {
411
+ // Show UI communicating that a required update has started installing
412
+ }
413
+
414
+ @Override
415
+ public void onReportReaderSoftwareUpdateProgress(float progress) {
416
+ // Update the progress of the install
417
+ }
418
+
419
+ @Override
420
+ public void onFinishInstallingUpdate(@Nullable ReaderSoftwareUpdate update, @Nullable TerminalException e) {
421
+ // Report success or failure of the update
422
+ }
423
+
424
+ @Override
425
+ public void onReportLowBatteryWarning() {
426
+
427
+ }
428
+
429
+ @Override
430
+ public void onReportAvailableUpdate(@NotNull ReaderSoftwareUpdate update) {
431
+ // An update is available for the connected reader. Show this update in your application.
432
+ // This update can be installed using `Terminal.getInstance().installAvailableUpdate`.
433
+ }
434
+ };
435
+ }
340
436
  }
@@ -2,7 +2,9 @@ package com.getcapacitor.community.stripe.terminal;
2
2
 
3
3
  import android.Manifest;
4
4
  import android.os.Build;
5
+
5
6
  import androidx.annotation.RequiresApi;
7
+
6
8
  import com.getcapacitor.PermissionState;
7
9
  import com.getcapacitor.Plugin;
8
10
  import com.getcapacitor.PluginCall;
@@ -11,8 +13,6 @@ import com.getcapacitor.annotation.CapacitorPlugin;
11
13
  import com.getcapacitor.annotation.Permission;
12
14
  import com.getcapacitor.annotation.PermissionCallback;
13
15
  import com.stripe.stripeterminal.external.models.TerminalException;
14
- import java.util.Objects;
15
- import org.json.JSONException;
16
16
 
17
17
  @RequiresApi(api = Build.VERSION_CODES.S)
18
18
  @CapacitorPlugin(
@@ -2,7 +2,9 @@ package com.getcapacitor.community.stripe.terminal;
2
2
 
3
3
  import android.content.Context;
4
4
  import android.util.Log;
5
+
5
6
  import androidx.core.util.Supplier;
7
+
6
8
  import com.android.volley.Request;
7
9
  import com.android.volley.RequestQueue;
8
10
  import com.android.volley.Response;
@@ -12,6 +14,7 @@ import com.android.volley.toolbox.Volley;
12
14
  import com.stripe.stripeterminal.external.callable.ConnectionTokenCallback;
13
15
  import com.stripe.stripeterminal.external.callable.ConnectionTokenProvider;
14
16
  import com.stripe.stripeterminal.external.models.ConnectionTokenException;
17
+
15
18
  import org.json.JSONException;
16
19
  import org.json.JSONObject;
17
20
 
@@ -3,7 +3,9 @@ package com.getcapacitor.community.stripe.terminal.helper;
3
3
  import android.content.Context;
4
4
  import android.content.pm.ApplicationInfo;
5
5
  import android.content.pm.PackageManager;
6
+
6
7
  import androidx.core.util.Supplier;
8
+
7
9
  import com.getcapacitor.Logger;
8
10
 
9
11
  public class MetaData {
@@ -1,13 +1,12 @@
1
1
  package com.getcapacitor.community.stripe.terminal.models;
2
2
 
3
3
  import android.app.Activity;
4
- import android.app.Application;
5
4
  import android.content.Context;
5
+
6
6
  import androidx.core.util.Supplier;
7
+
7
8
  import com.getcapacitor.JSObject;
8
- import com.getcapacitor.Plugin;
9
9
  import com.google.android.gms.common.util.BiConsumer;
10
- import com.stripe.stripeterminal.TerminalApplicationDelegate;
11
10
 
12
11
  public abstract class Executor {
13
12
 
@@ -2,7 +2,7 @@ import Foundation
2
2
  import Capacitor
3
3
  import StripeTerminal
4
4
 
5
- public class StripeTerminal: NSObject, DiscoveryDelegate, LocalMobileReaderDelegate {
5
+ public class StripeTerminal: NSObject, DiscoveryDelegate, LocalMobileReaderDelegate, BluetoothReaderDelegate {
6
6
 
7
7
  weak var plugin: StripeTerminalPlugin?
8
8
  var discoverCancelable: Cancelable?
@@ -25,22 +25,26 @@ public class StripeTerminal: NSObject, DiscoveryDelegate, LocalMobileReaderDeleg
25
25
  call.resolve()
26
26
  }
27
27
 
28
- func discoverReaders(_ call: CAPPluginCall) {
28
+ func discoverReaders(_ call: CAPPluginCall) throws {
29
29
  let connectType = call.getString("type")
30
30
 
31
31
  if TerminalConnectTypes.TapToPay.rawValue == connectType {
32
32
  self.type = .localMobile
33
33
  } else if TerminalConnectTypes.Internet.rawValue == connectType {
34
34
  self.type = .internet
35
+ } else if TerminalConnectTypes.Bluetooth.rawValue == connectType {
36
+ self.type = DiscoveryMethod.bluetoothScan
35
37
  } else {
36
38
  call.unimplemented(connectType! + " is not support now")
37
39
  return
38
40
  }
39
41
 
42
+
40
43
  let config = DiscoveryConfiguration(
41
44
  discoveryMethod: self.type!,
42
45
  simulated: self.isTest!
43
46
  )
47
+
44
48
  self.discoverCall = call
45
49
  self.locationId = call.getString("locationId")
46
50
 
@@ -154,6 +158,21 @@ public class StripeTerminal: NSObject, DiscoveryDelegate, LocalMobileReaderDeleg
154
158
  }
155
159
  }
156
160
  }
161
+
162
+ private func connectBluetoothReader(_ call: CAPPluginCall) {
163
+ let config = BluetoothConnectionConfiguration(locationId: self.locationId!)
164
+ let reader: JSObject = call.getObject("reader")!
165
+ let index: Int = reader["index"] as! Int
166
+
167
+ Terminal.shared.connectBluetoothReader(self.readers![index], delegate: self, connectionConfig: config) { reader, error in
168
+ if let reader = reader {
169
+ self.plugin?.notifyListeners(TerminalEvents.ConnectedReader.rawValue, data: [:])
170
+ call.resolve()
171
+ } else if let error = error {
172
+ call.reject(error.localizedDescription)
173
+ }
174
+ }
175
+ }
157
176
 
158
177
  public func collect(_ call: CAPPluginCall) {
159
178
  Terminal.shared.retrievePaymentIntent(clientSecret: call.getString("paymentIntent")!) { retrieveResult, retrieveError in
@@ -188,7 +207,10 @@ public class StripeTerminal: NSObject, DiscoveryDelegate, LocalMobileReaderDeleg
188
207
  }
189
208
  call.resolve()
190
209
  }
210
+
191
211
 
212
+ // localMobile
213
+
192
214
  public func localMobileReader(_ reader: Reader, didStartInstallingUpdate update: ReaderSoftwareUpdate, cancelable: Cancelable?) {
193
215
  // TODO
194
216
  }
@@ -208,6 +230,33 @@ public class StripeTerminal: NSObject, DiscoveryDelegate, LocalMobileReaderDeleg
208
230
  public func localMobileReader(_ reader: Reader, didRequestReaderDisplayMessage displayMessage: ReaderDisplayMessage) {
209
231
  // TODO
210
232
  }
233
+
234
+
235
+ // bluetooth
236
+
237
+ public func reader(_: Reader, didReportAvailableUpdate update: ReaderSoftwareUpdate) {
238
+ // TODO
239
+ }
240
+
241
+ public func reader(_: Reader, didStartInstallingUpdate update: ReaderSoftwareUpdate, cancelable: Cancelable?) {
242
+ // TODO
243
+ }
244
+
245
+ public func reader(_: Reader, didReportReaderSoftwareUpdateProgress progress: Float) {
246
+ // TODO
247
+ }
248
+
249
+ public func reader(_: Reader, didFinishInstallingUpdate update: ReaderSoftwareUpdate?, error: Error?) {
250
+ // TODO
251
+ }
252
+
253
+ public func reader(_: Reader, didRequestReaderInput inputOptions: ReaderInputOptions = []) {
254
+ // TODO
255
+ }
256
+
257
+ public func reader(_: Reader, didRequestReaderDisplayMessage displayMessage: ReaderDisplayMessage) {
258
+ // TODO
259
+ }
211
260
  }
212
261
 
213
262
  class APIClient: ConnectionTokenProvider {
@@ -22,7 +22,11 @@ public class StripeTerminalPlugin: CAPPlugin {
22
22
  }
23
23
 
24
24
  @objc func discoverReaders(_ call: CAPPluginCall) {
25
- self.implementation.discoverReaders(call)
25
+ do {
26
+ try self.implementation.discoverReaders(call)
27
+ } catch {
28
+ call.reject("discoverReaders throw error.")
29
+ }
26
30
  }
27
31
 
28
32
  @objc func cancelDiscoverReaders(_ call: CAPPluginCall) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@capacitor-community/stripe-terminal",
3
- "version": "5.2.0",
3
+ "version": "5.3.0",
4
4
  "description": "Stripe SDK bindings for Capacitor Applications",
5
5
  "main": "dist/plugin.cjs.js",
6
6
  "module": "dist/esm/index.js",