@capacitor-community/stripe-terminal 0.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (35) hide show
  1. package/CapacitorCommunityStripeTerminal.podspec +18 -0
  2. package/README.md +263 -0
  3. package/android/build.gradle +70 -0
  4. package/android/src/main/AndroidManifest.xml +2 -0
  5. package/android/src/main/java/com/getcapacitor/community/stripe/terminal/StripeTerminal.java +227 -0
  6. package/android/src/main/java/com/getcapacitor/community/stripe/terminal/StripeTerminalPlugin.java +93 -0
  7. package/android/src/main/java/com/getcapacitor/community/stripe/terminal/TerminalEvent.kt +10 -0
  8. package/android/src/main/java/com/getcapacitor/community/stripe/terminal/TokenProvider.java +67 -0
  9. package/android/src/main/java/com/getcapacitor/community/stripe/terminal/helper/MetaData.java +28 -0
  10. package/android/src/main/java/com/getcapacitor/community/stripe/terminal/models/Executor.java +36 -0
  11. package/android/src/main/res/.gitkeep +0 -0
  12. package/dist/docs.json +337 -0
  13. package/dist/esm/definitions.d.ts +40 -0
  14. package/dist/esm/definitions.js +10 -0
  15. package/dist/esm/definitions.js.map +1 -0
  16. package/dist/esm/events.enum.d.ts +9 -0
  17. package/dist/esm/events.enum.js +10 -0
  18. package/dist/esm/events.enum.js.map +1 -0
  19. package/dist/esm/index.d.ts +4 -0
  20. package/dist/esm/index.js +7 -0
  21. package/dist/esm/index.js.map +1 -0
  22. package/dist/esm/web.d.ts +20 -0
  23. package/dist/esm/web.js +26 -0
  24. package/dist/esm/web.js.map +1 -0
  25. package/dist/plugin.cjs.js +60 -0
  26. package/dist/plugin.cjs.js.map +1 -0
  27. package/dist/plugin.js +63 -0
  28. package/dist/plugin.js.map +1 -0
  29. package/ios/Plugin/Info.plist +24 -0
  30. package/ios/Plugin/StripeTerminal.swift +155 -0
  31. package/ios/Plugin/StripeTerminalPlugin.h +10 -0
  32. package/ios/Plugin/StripeTerminalPlugin.m +11 -0
  33. package/ios/Plugin/StripeTerminalPlugin.swift +35 -0
  34. package/ios/Plugin/TerminalEvents.swift +8 -0
  35. package/package.json +78 -0
@@ -0,0 +1,18 @@
1
+ require 'json'
2
+
3
+ package = JSON.parse(File.read(File.join(__dir__, 'package.json')))
4
+
5
+ Pod::Spec.new do |s|
6
+ s.name = 'CapacitorCommunityStripeTerminal'
7
+ s.version = package['version']
8
+ s.summary = package['description']
9
+ s.license = package['license']
10
+ s.homepage = package['repository']['url']
11
+ s.author = package['author']
12
+ s.source = { :git => package['repository']['url'], :tag => s.version.to_s }
13
+ s.source_files = 'ios/Plugin/**/*.{swift,h,m,c,cc,mm,cpp}'
14
+ s.ios.deployment_target = '13.0'
15
+ s.dependency 'Capacitor'
16
+ s.dependency 'StripeTerminal'
17
+ s.swift_version = '5.1'
18
+ end
package/README.md ADDED
@@ -0,0 +1,263 @@
1
+ # @capacitor-community/stripe-terminal
2
+
3
+ Stripe SDK bindings for Capacitor Applications. __This plugin is still in beta.__
4
+ We have confirmed that it works well in the demo project. Please refer to https://github.com/capacitor-community/stripe/tree/main/demo/angular for the implementation.
5
+
6
+ - [x] Tap To Pay
7
+ - [ ] Internet
8
+ - [ ] Bluetooth
9
+ - [ ] USB
10
+
11
+ ## Install
12
+
13
+ ```bash
14
+ npm install @capacitor-community/stripe-terminal
15
+ npx cap sync
16
+ ```
17
+
18
+ ### iOS
19
+
20
+ - [iOS Configure your app](https://stripe.com/docs/terminal/payments/setup-integration?terminal-sdk-platform=ios#configure)
21
+
22
+ ### Android
23
+
24
+ Add permissions to your `android/app/src/main/AndroidManifest.xml` file:
25
+
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" />
31
+ + <uses-permission android:name="android.permission.BLUETOOTH_CONNECT" />
32
+ ```
33
+
34
+ If used in conjunction with the `@capacitor-community/stripe` plugin, the following settings may be necessary
35
+
36
+ Add packagingOptions to your `android/app/build.gradle` file:
37
+
38
+ ```diff
39
+ android {
40
+ ...
41
+ + packagingOptions {
42
+ + resources.excludes.add("org/bouncycastle/x509/*")
43
+ + }
44
+ }
45
+ ```
46
+
47
+ ## API
48
+
49
+ <docgen-index>
50
+
51
+ * [`initialize(...)`](#initialize)
52
+ * [`discoverReaders(...)`](#discoverreaders)
53
+ * [`connectReader(...)`](#connectreader)
54
+ * [`collect(...)`](#collect)
55
+ * [`addListener(TerminalEventsEnum.Loaded, ...)`](#addlistenerterminaleventsenumloaded)
56
+ * [`addListener(TerminalEventsEnum.DiscoveredReaders, ...)`](#addlistenerterminaleventsenumdiscoveredreaders)
57
+ * [`addListener(TerminalEventsEnum.ConnectedReader, ...)`](#addlistenerterminaleventsenumconnectedreader)
58
+ * [`addListener(TerminalEventsEnum.Completed, ...)`](#addlistenerterminaleventsenumcompleted)
59
+ * [`addListener(TerminalEventsEnum.Canceled, ...)`](#addlistenerterminaleventsenumcanceled)
60
+ * [`addListener(TerminalEventsEnum.Failed, ...)`](#addlistenerterminaleventsenumfailed)
61
+ * [Interfaces](#interfaces)
62
+ * [Type Aliases](#type-aliases)
63
+ * [Enums](#enums)
64
+
65
+ </docgen-index>
66
+
67
+ <docgen-api>
68
+ <!--Update the source file JSDoc comments and rerun docgen to update the docs below-->
69
+
70
+ ### initialize(...)
71
+
72
+ ```typescript
73
+ initialize(options: { tokenProviderEndpoint: string; isTest: boolean; }) => Promise<void>
74
+ ```
75
+
76
+ | Param | Type |
77
+ | ------------- | ---------------------------------------------------------------- |
78
+ | **`options`** | <code>{ tokenProviderEndpoint: string; isTest: boolean; }</code> |
79
+
80
+ --------------------
81
+
82
+
83
+ ### discoverReaders(...)
84
+
85
+ ```typescript
86
+ discoverReaders(options: { type: TerminalConnectType; locationId?: string; }) => Promise<{ readers: ReaderInterface[]; }>
87
+ ```
88
+
89
+ | Param | Type |
90
+ | ------------- | --------------------------------------------------------------------------------------------------- |
91
+ | **`options`** | <code>{ type: <a href="#terminalconnecttype">TerminalConnectType</a>; locationId?: string; }</code> |
92
+
93
+ **Returns:** <code>Promise&lt;{ readers: ReaderInterface[]; }&gt;</code>
94
+
95
+ --------------------
96
+
97
+
98
+ ### connectReader(...)
99
+
100
+ ```typescript
101
+ connectReader(options: { reader: ReaderInterface; }) => Promise<void>
102
+ ```
103
+
104
+ | Param | Type |
105
+ | ------------- | ------------------------------------------------------------------------ |
106
+ | **`options`** | <code>{ reader: <a href="#readerinterface">ReaderInterface</a>; }</code> |
107
+
108
+ --------------------
109
+
110
+
111
+ ### collect(...)
112
+
113
+ ```typescript
114
+ collect(options: { paymentIntent: string; }) => Promise<void>
115
+ ```
116
+
117
+ | Param | Type |
118
+ | ------------- | --------------------------------------- |
119
+ | **`options`** | <code>{ paymentIntent: string; }</code> |
120
+
121
+ --------------------
122
+
123
+
124
+ ### addListener(TerminalEventsEnum.Loaded, ...)
125
+
126
+ ```typescript
127
+ addListener(eventName: TerminalEventsEnum.Loaded, listenerFunc: () => void) => PluginListenerHandle
128
+ ```
129
+
130
+ | Param | Type |
131
+ | ------------------ | ------------------------------------------------------------------------ |
132
+ | **`eventName`** | <code><a href="#terminaleventsenum">TerminalEventsEnum.Loaded</a></code> |
133
+ | **`listenerFunc`** | <code>() =&gt; void</code> |
134
+
135
+ **Returns:** <code><a href="#pluginlistenerhandle">PluginListenerHandle</a></code>
136
+
137
+ --------------------
138
+
139
+
140
+ ### addListener(TerminalEventsEnum.DiscoveredReaders, ...)
141
+
142
+ ```typescript
143
+ addListener(eventName: TerminalEventsEnum.DiscoveredReaders, listenerFunc: () => { reader: ReaderInterface; }) => PluginListenerHandle
144
+ ```
145
+
146
+ | Param | Type |
147
+ | ------------------ | ----------------------------------------------------------------------------------- |
148
+ | **`eventName`** | <code><a href="#terminaleventsenum">TerminalEventsEnum.DiscoveredReaders</a></code> |
149
+ | **`listenerFunc`** | <code>() =&gt; { reader: <a href="#readerinterface">ReaderInterface</a>; }</code> |
150
+
151
+ **Returns:** <code><a href="#pluginlistenerhandle">PluginListenerHandle</a></code>
152
+
153
+ --------------------
154
+
155
+
156
+ ### addListener(TerminalEventsEnum.ConnectedReader, ...)
157
+
158
+ ```typescript
159
+ addListener(eventName: TerminalEventsEnum.ConnectedReader, listenerFunc: () => void) => PluginListenerHandle
160
+ ```
161
+
162
+ | Param | Type |
163
+ | ------------------ | --------------------------------------------------------------------------------- |
164
+ | **`eventName`** | <code><a href="#terminaleventsenum">TerminalEventsEnum.ConnectedReader</a></code> |
165
+ | **`listenerFunc`** | <code>() =&gt; void</code> |
166
+
167
+ **Returns:** <code><a href="#pluginlistenerhandle">PluginListenerHandle</a></code>
168
+
169
+ --------------------
170
+
171
+
172
+ ### addListener(TerminalEventsEnum.Completed, ...)
173
+
174
+ ```typescript
175
+ addListener(eventName: TerminalEventsEnum.Completed, listenerFunc: () => void) => PluginListenerHandle
176
+ ```
177
+
178
+ | Param | Type |
179
+ | ------------------ | --------------------------------------------------------------------------- |
180
+ | **`eventName`** | <code><a href="#terminaleventsenum">TerminalEventsEnum.Completed</a></code> |
181
+ | **`listenerFunc`** | <code>() =&gt; void</code> |
182
+
183
+ **Returns:** <code><a href="#pluginlistenerhandle">PluginListenerHandle</a></code>
184
+
185
+ --------------------
186
+
187
+
188
+ ### addListener(TerminalEventsEnum.Canceled, ...)
189
+
190
+ ```typescript
191
+ addListener(eventName: TerminalEventsEnum.Canceled, listenerFunc: () => void) => PluginListenerHandle
192
+ ```
193
+
194
+ | Param | Type |
195
+ | ------------------ | -------------------------------------------------------------------------- |
196
+ | **`eventName`** | <code><a href="#terminaleventsenum">TerminalEventsEnum.Canceled</a></code> |
197
+ | **`listenerFunc`** | <code>() =&gt; void</code> |
198
+
199
+ **Returns:** <code><a href="#pluginlistenerhandle">PluginListenerHandle</a></code>
200
+
201
+ --------------------
202
+
203
+
204
+ ### addListener(TerminalEventsEnum.Failed, ...)
205
+
206
+ ```typescript
207
+ addListener(eventName: TerminalEventsEnum.Failed, listenerFunc: () => void) => PluginListenerHandle
208
+ ```
209
+
210
+ | Param | Type |
211
+ | ------------------ | ------------------------------------------------------------------------ |
212
+ | **`eventName`** | <code><a href="#terminaleventsenum">TerminalEventsEnum.Failed</a></code> |
213
+ | **`listenerFunc`** | <code>() =&gt; void</code> |
214
+
215
+ **Returns:** <code><a href="#pluginlistenerhandle">PluginListenerHandle</a></code>
216
+
217
+ --------------------
218
+
219
+
220
+ ### Interfaces
221
+
222
+
223
+ #### PluginListenerHandle
224
+
225
+ | Prop | Type |
226
+ | ------------ | ----------------------------------------- |
227
+ | **`remove`** | <code>() =&gt; Promise&lt;void&gt;</code> |
228
+
229
+
230
+ ### Type Aliases
231
+
232
+
233
+ #### ReaderInterface
234
+
235
+ <code>{ index: number; serialNumber: string; }</code>
236
+
237
+
238
+ ### Enums
239
+
240
+
241
+ #### TerminalConnectType
242
+
243
+ | Members | Value |
244
+ | --------------- | ------------------------- |
245
+ | **`Simulated`** | <code>'simulated'</code> |
246
+ | **`Internet`** | <code>'internet'</code> |
247
+ | **`Bluetooth`** | <code>'bluetooth'</code> |
248
+ | **`Usb`** | <code>'usb'</code> |
249
+ | **`TapToPay`** | <code>'tap-to-pay'</code> |
250
+
251
+
252
+ #### TerminalEventsEnum
253
+
254
+ | Members | Value |
255
+ | ----------------------- | ---------------------------------------- |
256
+ | **`Loaded`** | <code>'terminalLoaded'</code> |
257
+ | **`DiscoveredReaders`** | <code>'terminalDiscoveredReaders'</code> |
258
+ | **`ConnectedReader`** | <code>'terminalConnectedReader'</code> |
259
+ | **`Completed`** | <code>'terminalCompleted'</code> |
260
+ | **`Canceled`** | <code>'terminalCanceled'</code> |
261
+ | **`Failed`** | <code>'terminalFailed'</code> |
262
+
263
+ </docgen-api>
@@ -0,0 +1,70 @@
1
+ ext {
2
+ junitVersion = project.hasProperty('junitVersion') ? rootProject.ext.junitVersion : '4.13.2'
3
+ androidxAppCompatVersion = project.hasProperty('androidxAppCompatVersion') ? rootProject.ext.androidxAppCompatVersion : '1.6.1'
4
+ androidxJunitVersion = project.hasProperty('androidxJunitVersion') ? rootProject.ext.androidxJunitVersion : '1.1.5'
5
+ androidxEspressoCoreVersion = project.hasProperty('androidxEspressoCoreVersion') ? rootProject.ext.androidxEspressoCoreVersion : '3.5.1'
6
+ }
7
+
8
+ buildscript {
9
+ ext.kotlin_version = project.hasProperty("kotlin_version") ? rootProject.ext.kotlin_version : '1.8.20'
10
+ repositories {
11
+ google()
12
+ mavenCentral()
13
+ }
14
+ dependencies {
15
+ classpath 'com.android.tools.build:gradle:8.0.0'
16
+ classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
17
+ }
18
+ }
19
+
20
+ apply plugin: 'com.android.library'
21
+ apply plugin: 'kotlin-android'
22
+
23
+ android {
24
+ namespace "com.getcapacitor.community.stripe.terminal"
25
+ compileSdkVersion project.hasProperty('compileSdkVersion') ? rootProject.ext.compileSdkVersion : 33
26
+ defaultConfig {
27
+ minSdkVersion project.hasProperty('minSdkVersion') ? rootProject.ext.minSdkVersion : 22
28
+ targetSdkVersion project.hasProperty('targetSdkVersion') ? rootProject.ext.targetSdkVersion : 33
29
+ versionCode 1
30
+ versionName "1.0"
31
+ testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
32
+ }
33
+ buildTypes {
34
+ release {
35
+ minifyEnabled false
36
+ proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
37
+ }
38
+ }
39
+ lintOptions {
40
+ abortOnError false
41
+ }
42
+ compileOptions {
43
+ sourceCompatibility JavaVersion.VERSION_1_8
44
+ targetCompatibility JavaVersion.VERSION_1_8
45
+ }
46
+ kotlinOptions {
47
+ jvmTarget = "1.8"
48
+ }
49
+ }
50
+
51
+ repositories {
52
+ google()
53
+ mavenCentral()
54
+ }
55
+
56
+
57
+ dependencies {
58
+ implementation fileTree(dir: 'libs', include: ['*.jar'])
59
+ implementation project(':capacitor-android')
60
+ implementation "androidx.appcompat:appcompat:$androidxAppCompatVersion"
61
+ testImplementation "junit:junit:$junitVersion"
62
+ androidTestImplementation "androidx.test.ext:junit:$androidxJunitVersion"
63
+ androidTestImplementation "androidx.test.espresso:espresso-core:$androidxEspressoCoreVersion"
64
+
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
+ }
@@ -0,0 +1,2 @@
1
+ <manifest xmlns:android="http://schemas.android.com/apk/res/android">
2
+ </manifest>
@@ -0,0 +1,227 @@
1
+ package com.getcapacitor.community.stripe.terminal;
2
+
3
+ import android.app.Activity;
4
+ import android.app.Application;
5
+ import android.content.Context;
6
+ import android.content.pm.ApplicationInfo;
7
+ import android.util.Log;
8
+ import androidx.annotation.NonNull;
9
+ import androidx.core.util.Supplier;
10
+ import com.getcapacitor.JSArray;
11
+ import com.getcapacitor.JSObject;
12
+ import com.getcapacitor.PluginCall;
13
+ import com.getcapacitor.community.stripe.terminal.models.Executor;
14
+ import com.google.android.gms.common.util.BiConsumer;
15
+ import com.stripe.stripeterminal.Terminal;
16
+ import com.stripe.stripeterminal.TerminalApplicationDelegate;
17
+ import com.stripe.stripeterminal.external.callable.Callback;
18
+ import com.stripe.stripeterminal.external.callable.Cancelable;
19
+ import com.stripe.stripeterminal.external.callable.DiscoveryListener;
20
+ import com.stripe.stripeterminal.external.callable.PaymentIntentCallback;
21
+ import com.stripe.stripeterminal.external.callable.ReaderCallback;
22
+ import com.stripe.stripeterminal.external.callable.TerminalListener;
23
+ import com.stripe.stripeterminal.external.models.ConnectionConfiguration;
24
+ import com.stripe.stripeterminal.external.models.ConnectionStatus;
25
+ import com.stripe.stripeterminal.external.models.DiscoveryConfiguration;
26
+ import com.stripe.stripeterminal.external.models.DiscoveryMethod;
27
+ import com.stripe.stripeterminal.external.models.PaymentIntent;
28
+ import com.stripe.stripeterminal.external.models.PaymentStatus;
29
+ import com.stripe.stripeterminal.external.models.Reader;
30
+ import com.stripe.stripeterminal.external.models.TerminalException;
31
+ import com.stripe.stripeterminal.log.LogLevel;
32
+ import java.util.ArrayList;
33
+ import java.util.List;
34
+ import org.json.JSONException;
35
+
36
+ public class StripeTerminal extends Executor {
37
+
38
+ private Cancelable discoveryCancelable;
39
+ private List<Reader> readers;
40
+ private String locationId;
41
+ private PluginCall collectCall;
42
+ private final JSObject emptyObject = new JSObject();
43
+ private Boolean isTest;
44
+
45
+ public StripeTerminal(
46
+ Supplier<Context> contextSupplier,
47
+ Supplier<Activity> activitySupplier,
48
+ BiConsumer<String, JSObject> notifyListenersFunction,
49
+ String pluginLogTag
50
+ ) {
51
+ super(contextSupplier, activitySupplier, notifyListenersFunction, pluginLogTag, "StripeTerminalExecutor");
52
+ this.contextSupplier = contextSupplier;
53
+ this.readers = new ArrayList<Reader>();
54
+ }
55
+
56
+ public void initialize(final PluginCall call) throws TerminalException {
57
+ this.isTest = call.getBoolean("isTest", true);
58
+ this.activitySupplier.get()
59
+ .runOnUiThread(
60
+ () -> {
61
+ TerminalApplicationDelegate.onCreate((Application) this.contextSupplier.get().getApplicationContext());
62
+ notifyListeners(TerminalEnumEvent.Loaded.getWebEventName(), emptyObject);
63
+ call.resolve();
64
+ }
65
+ );
66
+ TerminalListener listener = new TerminalListener() {
67
+ @Override
68
+ public void onUnexpectedReaderDisconnect(@NonNull Reader reader) {
69
+ // TODO: Listenerを追加
70
+ }
71
+ //
72
+ // @Override
73
+ // public void onConnectionStatusChange(@NonNull ConnectionStatus status) {
74
+ // // TODO: Listenerを追加
75
+ // }
76
+ //
77
+ // @Override
78
+ // public void onPaymentStatusChange(@NonNull PaymentStatus status) {
79
+ // // TODO: Listenerを追加
80
+ // }
81
+ };
82
+ LogLevel logLevel = LogLevel.VERBOSE;
83
+ TokenProvider tokenProvider = new TokenProvider(this.contextSupplier, call.getString("tokenProviderEndpoint"));
84
+ if (!Terminal.isInitialized()) {
85
+ Terminal.initTerminal(this.contextSupplier.get().getApplicationContext(), logLevel, tokenProvider, listener);
86
+ }
87
+ Terminal.getInstance();
88
+ }
89
+
90
+ public void onDiscoverReaders(final PluginCall call) {
91
+ this.locationId = call.getString("locationId");
92
+ final DiscoveryConfiguration config = new DiscoveryConfiguration(
93
+ 0,
94
+ DiscoveryMethod.LOCAL_MOBILE,
95
+ this.isTest,
96
+ call.getString("locationId")
97
+ );
98
+ final DiscoveryListener discoveryListener = readers -> {
99
+ // 検索したReaderの一覧をListenerで渡す
100
+ Log.d(logTag, String.valueOf(readers.get(0).getSerialNumber()));
101
+ this.readers = readers;
102
+ JSArray readersJSObject = new JSArray();
103
+
104
+ int i = 0;
105
+ for (Reader reader : this.readers) {
106
+ readersJSObject.put(new JSObject().put("index", String.valueOf(i)).put("serialNumber", reader.getSerialNumber()));
107
+ }
108
+ this.notifyListeners(TerminalEnumEvent.DiscoveredReaders.getWebEventName(), new JSObject().put("readers", readersJSObject));
109
+ call.resolve(new JSObject().put("readers", readersJSObject));
110
+ };
111
+ discoveryCancelable =
112
+ Terminal
113
+ .getInstance()
114
+ .discoverReaders(
115
+ config,
116
+ discoveryListener,
117
+ // Callback run after connectReader
118
+ new Callback() {
119
+ @Override
120
+ public void onSuccess() {
121
+ Log.d(logTag, "Finished discovering readers");
122
+ }
123
+
124
+ @Override
125
+ public void onFailure(@NonNull TerminalException ex) {
126
+ Log.d(logTag, ex.getLocalizedMessage());
127
+ }
128
+ }
129
+ );
130
+ }
131
+
132
+ public void connectReader(final PluginCall call) {
133
+ JSObject reader = call.getObject("reader");
134
+ ConnectionConfiguration.LocalMobileConnectionConfiguration config = new ConnectionConfiguration.LocalMobileConnectionConfiguration(
135
+ this.locationId
136
+ );
137
+ Terminal
138
+ .getInstance()
139
+ .connectLocalMobileReader(
140
+ this.readers.get(reader.getInteger("index")),
141
+ config,
142
+ new ReaderCallback() {
143
+ @Override
144
+ public void onSuccess(Reader r) {
145
+ notifyListeners(TerminalEnumEvent.ConnectedReader.getWebEventName(), emptyObject);
146
+ call.resolve();
147
+ }
148
+
149
+ @Override
150
+ public void onFailure(@NonNull TerminalException ex) {
151
+ ex.printStackTrace();
152
+ call.reject(ex.getLocalizedMessage(), ex);
153
+ }
154
+ }
155
+ );
156
+ }
157
+
158
+ public void cancelDiscovering(final PluginCall call) {
159
+ if (discoveryCancelable != null) {
160
+ discoveryCancelable.cancel(
161
+ new Callback() {
162
+ @Override
163
+ public void onSuccess() {
164
+ call.resolve();
165
+ }
166
+
167
+ @Override
168
+ public void onFailure(TerminalException ex) {
169
+ Log.d(logTag, ex.getLocalizedMessage());
170
+ call.reject(ex.getLocalizedMessage(), ex);
171
+ }
172
+ }
173
+ );
174
+ } else {
175
+ call.resolve();
176
+ }
177
+ }
178
+
179
+ public void collect(final PluginCall call) {
180
+ // メソッドを分割するためcallを永続化
181
+ this.collectCall = call;
182
+
183
+ Terminal.getInstance().retrievePaymentIntent(call.getString("paymentIntent"), createPaymentIntentCallback);
184
+ }
185
+
186
+ private final PaymentIntentCallback createPaymentIntentCallback = new PaymentIntentCallback() {
187
+ @Override
188
+ public void onSuccess(@NonNull PaymentIntent paymentIntent) {
189
+ Terminal.getInstance().collectPaymentMethod(paymentIntent, collectPaymentMethodCallback);
190
+ }
191
+
192
+ @Override
193
+ public void onFailure(@NonNull TerminalException ex) {
194
+ notifyListeners(TerminalEnumEvent.Failed.getWebEventName(), emptyObject);
195
+ collectCall.reject(ex.getLocalizedMessage(), ex);
196
+ }
197
+ };
198
+
199
+ // Step 3 - we've collected the payment method, so it's time to process the payment
200
+ private final PaymentIntentCallback collectPaymentMethodCallback = new PaymentIntentCallback() {
201
+ @Override
202
+ public void onSuccess(@NonNull PaymentIntent paymentIntent) {
203
+ Terminal.getInstance().processPayment(paymentIntent, processPaymentCallback);
204
+ }
205
+
206
+ @Override
207
+ public void onFailure(@NonNull TerminalException ex) {
208
+ notifyListeners(TerminalEnumEvent.Failed.getWebEventName(), emptyObject);
209
+ collectCall.reject(ex.getLocalizedMessage(), ex);
210
+ }
211
+ };
212
+
213
+ // Step 4 - we've processed the payment! Show a success screen
214
+ private final PaymentIntentCallback processPaymentCallback = new PaymentIntentCallback() {
215
+ @Override
216
+ public void onSuccess(@NonNull PaymentIntent paymentIntent) {
217
+ notifyListeners(TerminalEnumEvent.Completed.getWebEventName(), emptyObject);
218
+ collectCall.resolve();
219
+ }
220
+
221
+ @Override
222
+ public void onFailure(@NonNull TerminalException ex) {
223
+ notifyListeners(TerminalEnumEvent.Failed.getWebEventName(), emptyObject);
224
+ collectCall.reject(ex.getLocalizedMessage(), ex);
225
+ }
226
+ };
227
+ }
@@ -0,0 +1,93 @@
1
+ package com.getcapacitor.community.stripe.terminal;
2
+
3
+ import android.Manifest;
4
+ import android.os.Build;
5
+ import androidx.annotation.RequiresApi;
6
+ import com.getcapacitor.PermissionState;
7
+ import com.getcapacitor.Plugin;
8
+ import com.getcapacitor.PluginCall;
9
+ import com.getcapacitor.PluginMethod;
10
+ import com.getcapacitor.annotation.CapacitorPlugin;
11
+ import com.getcapacitor.annotation.Permission;
12
+ import com.getcapacitor.annotation.PermissionCallback;
13
+ import com.stripe.stripeterminal.external.models.TerminalException;
14
+ import java.util.Objects;
15
+ import org.json.JSONException;
16
+
17
+ @RequiresApi(api = Build.VERSION_CODES.S)
18
+ @CapacitorPlugin(
19
+ name = "StripeTerminal",
20
+ permissions = {
21
+ @Permission(alias = "location", strings = { Manifest.permission.ACCESS_FINE_LOCATION }),
22
+ @Permission(
23
+ alias = "bluetooth",
24
+ strings = {
25
+ Manifest.permission.BLUETOOTH,
26
+ Manifest.permission.BLUETOOTH_ADMIN,
27
+ Manifest.permission.BLUETOOTH_SCAN,
28
+ Manifest.permission.BLUETOOTH_ADVERTISE,
29
+ Manifest.permission.BLUETOOTH_CONNECT
30
+ }
31
+ )
32
+ }
33
+ )
34
+ public class StripeTerminalPlugin extends Plugin {
35
+
36
+ private final StripeTerminal implementation = new StripeTerminal(
37
+ this::getContext,
38
+ this::getActivity,
39
+ this::notifyListeners,
40
+ getLogTag()
41
+ );
42
+
43
+ @PluginMethod
44
+ public void initialize(PluginCall call) throws TerminalException {
45
+ this._initialize(call);
46
+ }
47
+
48
+ @PermissionCallback
49
+ private void locationPermsCallback(PluginCall call) throws TerminalException {
50
+ if (getPermissionState("location") == PermissionState.GRANTED) {
51
+ this._initialize(call);
52
+ } else {
53
+ call.reject("Permission is required to get location");
54
+ }
55
+ }
56
+
57
+ @PermissionCallback
58
+ private void bluetoothPermsCallback(PluginCall call) throws TerminalException {
59
+ if (getPermissionState("bluetooth") == PermissionState.GRANTED) {
60
+ this._initialize(call);
61
+ } else {
62
+ call.reject("Permission is required to get bluetooth");
63
+ }
64
+ }
65
+
66
+ private void _initialize(PluginCall call) throws TerminalException {
67
+ if (getPermissionState("location") != PermissionState.GRANTED) {
68
+ requestPermissionForAlias("location", call, "locationPermsCallback");
69
+ } else if (getPermissionState("bluetooth") != PermissionState.GRANTED) {
70
+ requestPermissionForAlias("bluetooth", call, "bluetoothPermsCallback");
71
+ } else {
72
+ this.implementation.initialize(call);
73
+ }
74
+ }
75
+
76
+ @PluginMethod
77
+ public void discoverReaders(PluginCall call) {
78
+ if (!Objects.equals(call.getString("type"), "tap-to-pay")) {
79
+ call.unimplemented();
80
+ }
81
+ this.implementation.onDiscoverReaders(call);
82
+ }
83
+
84
+ @PluginMethod
85
+ public void connectReader(PluginCall call) {
86
+ this.implementation.connectReader(call);
87
+ }
88
+
89
+ @PluginMethod
90
+ public void collect(PluginCall call) {
91
+ this.implementation.collect(call);
92
+ }
93
+ }
@@ -0,0 +1,10 @@
1
+ package com.getcapacitor.community.stripe.terminal;
2
+
3
+ enum class TerminalEnumEvent(val webEventName: String) {
4
+ Loaded("terminalLoaded"),
5
+ DiscoveredReaders("terminalDiscoveredReaders"),
6
+ ConnectedReader("terminalConnectedReader"),
7
+ Completed("terminalCompleted"),
8
+ Canceled("terminalCanceled"),
9
+ Failed("terminalFailed"),
10
+ }